mbox series

[RFC,0/3] QEMU changes to do PVH boot

Message ID 1544049446-6359-1-git-send-email-liam.merwick@oracle.com (mailing list archive)
Headers show
Series QEMU changes to do PVH boot | expand

Message

Liam Merwick Dec. 5, 2018, 10:37 p.m. UTC
For certain applications it is desirable to rapidly boot a KVM virtual
machine. In cases where legacy hardware and software support within the
guest is not needed, QEMU should be able to boot directly into the
uncompressed Linux kernel binary with minimal firmware involvement.

There already exists an ABI to allow this for Xen PVH guests and the ABI
is supported by Linux and FreeBSD:

   https://xenbits.xen.org/docs/unstable/misc/pvh.html

Details on the Linux changes: https://lkml.org/lkml/2018/4/16/1002
qboot patches: http://patchwork.ozlabs.org/project/qemu-devel/list/?series=80020

This patch series provides QEMU support to read the ELF header of an
uncompressed kernel binary and get the 32-bit PVH kernel entry point
from an ELF Note.  This is called when initialising the machine state
in pc_memory_init().  Later on in load_linux() if the kernel entry
address is present, the uncompressed kernel binary (ELF) is loaded
and qboot does futher initialisation of the guest (e820, etc.) and
jumps to the kernel entry address and boots the guest.


Usіng the method/scripts documented by the NEMU team at

   https://github.com/intel/nemu/wiki/Measuring-Boot-Latency
   https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg00200.html

below are some timings measured (vmlinux and bzImage from the same build)
Time to get to kernel start is almost halved (95ṁs -> 48ms)

QEMU + qboot + vmlinux (PVH + 4.20-rc4)
 qemu_init_end: 41.550521
 fw_start: 41.667139 (+0.116618)
 fw_do_boot: 47.448495 (+5.781356)
 linux_startup_64: 47.720785 (+0.27229)
 linux_start_kernel: 48.399541 (+0.678756)
 linux_start_user: 296.952056 (+248.552515)

QEMU + qboot + bzImage:
 qemu_init_end: 29.209276
 fw_start: 29.317342 (+0.108066)
 linux_start_boot: 36.679362 (+7.36202)
 linux_startup_64: 94.531349 (+57.851987)
 linux_start_kernel: 94.900913 (+0.369564)
 linux_start_user: 401.060971 (+306.160058)

QEMU + bzImage:
 qemu_init_end: 30.424430
 linux_startup_64: 893.770334 (+863.345904)
 linux_start_kernel: 894.17049 (+0.400156)
 linux_start_user: 1208.679768 (+314.509278)


Liam Merwick (3):
  pvh: Add x86/HVM direct boot ABI header file
  pc: Read PVH entry point from ELF note in kernel binary
  pvh: Boot uncompressed kernel using direct boot ABI

 hw/i386/pc.c                | 344 +++++++++++++++++++++++++++++++++++++++++++-
 include/elf.h               |  10 ++
 include/hw/xen/start_info.h | 146 +++++++++++++++++++
 3 files changed, 499 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/xen/start_info.h

Comments

no-reply@patchew.org Dec. 6, 2018, 12:01 a.m. UTC | #1
Patchew URL: https://patchew.org/QEMU/1544049446-6359-1-git-send-email-liam.merwick@oracle.com/



Hi,

This series failed the docker-mingw@fedora build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
time make docker-test-mingw@fedora SHOW_ENV=1 J=8
=== TEST SCRIPT END ===

  CC      x86_64-softmmu/target/i386/hax-windows.o
  CC      x86_64-softmmu/target/i386/sev-stub.o
/tmp/qemu-test/src/hw/i386/pc.c: In function 'get_elf_note_type':
/tmp/qemu-test/src/hw/i386/pc.c:884:42: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'size_t {aka long long unsigned int}' [-Werror=format=]
             error_report("Note type (0x%lx) not found in ELF Note section",
                                        ~~^
                                        %llx
/tmp/qemu-test/src/hw/i386/pc.c: In function 'read_pvh_start_addr_elf_note':
/tmp/qemu-test/src/hw/i386/pc.c:982:12: error: implicit declaration of function 'mmap'; did you mean 'max'? [-Werror=implicit-function-declaration]
     ehdr = mmap(0, statbuf.st_size,
            ^~~~
            max
/tmp/qemu-test/src/hw/i386/pc.c:982:12: error: nested extern declaration of 'mmap' [-Werror=nested-externs]
/tmp/qemu-test/src/hw/i386/pc.c:983:9: error: 'PROT_READ' undeclared (first use in this function); did you mean 'OF_READ'?
         PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(file), 0);
         ^~~~~~~~~
         OF_READ
/tmp/qemu-test/src/hw/i386/pc.c:983:9: note: each undeclared identifier is reported only once for each function it appears in
/tmp/qemu-test/src/hw/i386/pc.c:983:21: error: 'PROT_WRITE' undeclared (first use in this function); did you mean 'OF_WRITE'?
         PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(file), 0);
                     ^~~~~~~~~~
                     OF_WRITE
/tmp/qemu-test/src/hw/i386/pc.c:983:33: error: 'MAP_PRIVATE' undeclared (first use in this function); did you mean 'MEM_PRIVATE'?
         PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(file), 0);
                                 ^~~~~~~~~~~
                                 MEM_PRIVATE
/tmp/qemu-test/src/hw/i386/pc.c:984:17: error: 'MAP_FAILED' undeclared (first use in this function); did you mean 'WAIT_FAILED'?
     if (ehdr == MAP_FAILED) {
                 ^~~~~~~~~~
                 WAIT_FAILED
/tmp/qemu-test/src/hw/i386/pc.c:1058:44: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'long long int' [-Werror=format=]
         error_report("ELF Nhdr offset (0x%lx) exceeds file (%s) bounds (%ld)",
                                          ~~^
                                          %llx
             (nhdr - ehdr), filename, statbuf.st_size);
             ~~~~~~~~~~~~~                   
/tmp/qemu-test/src/hw/i386/pc.c:1058:75: error: format '%ld' expects argument of type 'long int', but argument 4 has type 'long long int' [-Werror=format=]
         error_report("ELF Nhdr offset (0x%lx) exceeds file (%s) bounds (%ld)",
                                                                         ~~^
                                                                         %lld
             (nhdr - ehdr), filename, statbuf.st_size);
                                      ~~~~~~~~~~~~~~~                       
/tmp/qemu-test/src/hw/i386/pc.c:1075:46: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'long long unsigned int' [-Werror=format=]
         error_report("ELF Nhdr contents (0x%lx) exceeds file bounds (%ld)",
                                            ~~^
                                            %llx
/tmp/qemu-test/src/hw/i386/pc.c:1075:72: error: format '%ld' expects argument of type 'long int', but argument 3 has type 'long long int' [-Werror=format=]
         error_report("ELF Nhdr contents (0x%lx) exceeds file bounds (%ld)",
                                                                      ~~^
                                                                      %lld
/tmp/qemu-test/src/hw/i386/pc.c:1077:53:
             QEMU_ALIGN_UP(nhdr_descsz, phdr_align), statbuf.st_size);
                                                     ~~~~~~~~~~~~~~~     
/tmp/qemu-test/src/hw/i386/pc.c:1091:46: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'long long unsigned int' [-Werror=format=]
         error_report("PVH ELF note addr (0x%lx) exceeds file (%s) bounds (%ld)",
                                            ~~^
                                            %llx
             (elf_note_data_addr - (size_t)ehdr), filename, statbuf.st_size);
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/qemu-test/src/hw/i386/pc.c:1091:77: error: format '%ld' expects argument of type 'long int', but argument 4 has type 'long long int' [-Werror=format=]
         error_report("PVH ELF note addr (0x%lx) exceeds file (%s) bounds (%ld)",
                                                                           ~~^
                                                                           %lld
             (elf_note_data_addr - (size_t)ehdr), filename, statbuf.st_size);
                                                            ~~~~~~~~~~~~~~~   
/tmp/qemu-test/src/hw/i386/pc.c:1098:12: error: implicit declaration of function 'munmap'; did you mean 'gunzip'? [-Werror=implicit-function-declaration]
     (void) munmap(ehdr, statbuf.st_size);
            ^~~~~~
            gunzip
/tmp/qemu-test/src/hw/i386/pc.c:1098:12: error: nested extern declaration of 'munmap' [-Werror=nested-externs]
cc1: all warnings being treated as errors
  CC      aarch64-softmmu/hw/display/xlnx_dp.o
  GEN     trace/generated-helpers.c


The full log is available at
http://patchew.org/logs/1544049446-6359-1-git-send-email-liam.merwick@oracle.com/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
Maran Wilson Dec. 6, 2018, 6:18 a.m. UTC | #2
On 12/5/2018 2:37 PM, Liam Merwick wrote:
> For certain applications it is desirable to rapidly boot a KVM virtual
> machine. In cases where legacy hardware and software support within the
> guest is not needed, QEMU should be able to boot directly into the
> uncompressed Linux kernel binary with minimal firmware involvement.
>
> There already exists an ABI to allow this for Xen PVH guests and the ABI
> is supported by Linux and FreeBSD:
>
>     https://xenbits.xen.org/docs/unstable/misc/pvh.html
>
> Details on the Linux changes: https://lkml.org/lkml/2018/4/16/1002

In case anyone wants to grab the patches and give it a try, I've just 
posted an updated version of the Linux patches rebased to the latest 
mainline code:

https://lkml.org/lkml/2018/12/6/26

No functional changes from before, just some minor conflict resolution 
as part of the rebase.

Thanks,
-Maran

> qboot patches: http://patchwork.ozlabs.org/project/qemu-devel/list/?series=80020
>
> This patch series provides QEMU support to read the ELF header of an
> uncompressed kernel binary and get the 32-bit PVH kernel entry point
> from an ELF Note.  This is called when initialising the machine state
> in pc_memory_init().  Later on in load_linux() if the kernel entry
> address is present, the uncompressed kernel binary (ELF) is loaded
> and qboot does futher initialisation of the guest (e820, etc.) and
> jumps to the kernel entry address and boots the guest.
>
>
> Usіng the method/scripts documented by the NEMU team at
>
>     https://github.com/intel/nemu/wiki/Measuring-Boot-Latency
>     https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg00200.html
>
> below are some timings measured (vmlinux and bzImage from the same build)
> Time to get to kernel start is almost halved (95ṁs -> 48ms)
>
> QEMU + qboot + vmlinux (PVH + 4.20-rc4)
>   qemu_init_end: 41.550521
>   fw_start: 41.667139 (+0.116618)
>   fw_do_boot: 47.448495 (+5.781356)
>   linux_startup_64: 47.720785 (+0.27229)
>   linux_start_kernel: 48.399541 (+0.678756)
>   linux_start_user: 296.952056 (+248.552515)
>
> QEMU + qboot + bzImage:
>   qemu_init_end: 29.209276
>   fw_start: 29.317342 (+0.108066)
>   linux_start_boot: 36.679362 (+7.36202)
>   linux_startup_64: 94.531349 (+57.851987)
>   linux_start_kernel: 94.900913 (+0.369564)
>   linux_start_user: 401.060971 (+306.160058)
>
> QEMU + bzImage:
>   qemu_init_end: 30.424430
>   linux_startup_64: 893.770334 (+863.345904)
>   linux_start_kernel: 894.17049 (+0.400156)
>   linux_start_user: 1208.679768 (+314.509278)
>
>
> Liam Merwick (3):
>    pvh: Add x86/HVM direct boot ABI header file
>    pc: Read PVH entry point from ELF note in kernel binary
>    pvh: Boot uncompressed kernel using direct boot ABI
>
>   hw/i386/pc.c                | 344 +++++++++++++++++++++++++++++++++++++++++++-
>   include/elf.h               |  10 ++
>   include/hw/xen/start_info.h | 146 +++++++++++++++++++
>   3 files changed, 499 insertions(+), 1 deletion(-)
>   create mode 100644 include/hw/xen/start_info.h
>