qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Liam Merwick <liam.merwick@oracle.com>
To: Sergio Lopez <slp@redhat.com>,
	mst@redhat.com, marcel.apfelbaum@gmail.com,  pbonzini@redhat.com,
	rth@twiddle.net, ehabkost@redhat.com, maran.wilson@oracle.com,
	sgarzare@redhat.com, kraxel@redhat.com
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v3 3/4] hw/i386: Factorize PVH related functions
Date: Tue, 23 Jul 2019 09:39:13 +0100	[thread overview]
Message-ID: <92aae459-a27f-9d3d-313e-ae99f1bbed92@oracle.com> (raw)
In-Reply-To: <20190702121106.28374-4-slp@redhat.com>

On 02/07/2019 13:11, Sergio Lopez wrote:
> Extract PVH related functions from pc.c, and put them in pvh.c, so
> they can be shared with other components.
> 
> Signed-off-by: Sergio Lopez <slp@redhat.com>


Refactoring LGTM

Reviewed-by: Liam Merwick <liam.merwick@oracle.com>


> ---
>   hw/i386/Makefile.objs |   1 +
>   hw/i386/pc.c          | 120 +++++-------------------------------------
>   hw/i386/pvh.c         | 113 +++++++++++++++++++++++++++++++++++++++
>   hw/i386/pvh.h         |  10 ++++
>   4 files changed, 136 insertions(+), 108 deletions(-)
>   create mode 100644 hw/i386/pvh.c
>   create mode 100644 hw/i386/pvh.h
> 
> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
> index 5d9c9efd5f..c5f20bbd72 100644
> --- a/hw/i386/Makefile.objs
> +++ b/hw/i386/Makefile.objs
> @@ -1,5 +1,6 @@
>   obj-$(CONFIG_KVM) += kvm/
>   obj-y += multiboot.o
> +obj-y += pvh.o
>   obj-y += pc.o
>   obj-$(CONFIG_I440FX) += pc_piix.o
>   obj-$(CONFIG_Q35) += pc_q35.o
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 3983621f1c..325ec2c1c8 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -42,6 +42,7 @@
>   #include "hw/loader.h"
>   #include "elf.h"
>   #include "multiboot.h"
> +#include "pvh.h"
>   #include "hw/timer/mc146818rtc.h"
>   #include "hw/dma/i8257.h"
>   #include "hw/timer/i8254.h"
> @@ -108,9 +109,6 @@ static struct e820_entry *e820_table;
>   static unsigned e820_entries;
>   struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
>   
> -/* Physical Address of PVH entry point read from kernel ELF NOTE */
> -static size_t pvh_start_addr;
> -
>   GlobalProperty pc_compat_4_0[] = {};
>   const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
>   
> @@ -1061,109 +1059,6 @@ struct setup_data {
>       uint8_t data[0];
>   } __attribute__((packed));
>   
> -
> -/*
> - * The entry point into the kernel for PVH boot is different from
> - * the native entry point.  The PVH entry is defined by the x86/HVM
> - * direct boot ABI and is available in an ELFNOTE in the kernel binary.
> - *
> - * This function is passed to load_elf() when it is called from
> - * load_elfboot() which then additionally checks for an ELF Note of
> - * type XEN_ELFNOTE_PHYS32_ENTRY and passes it to this function to
> - * parse the PVH entry address from the ELF Note.
> - *
> - * Due to trickery in elf_opts.h, load_elf() is actually available as
> - * load_elf32() or load_elf64() and this routine needs to be able
> - * to deal with being called as 32 or 64 bit.
> - *
> - * The address of the PVH entry point is saved to the 'pvh_start_addr'
> - * global variable.  (although the entry point is 32-bit, the kernel
> - * binary can be either 32-bit or 64-bit).
> - */
> -static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
> -{
> -    size_t *elf_note_data_addr;
> -
> -    /* Check if ELF Note header passed in is valid */
> -    if (arg1 == NULL) {
> -        return 0;
> -    }
> -
> -    if (is64) {
> -        struct elf64_note *nhdr64 = (struct elf64_note *)arg1;
> -        uint64_t nhdr_size64 = sizeof(struct elf64_note);
> -        uint64_t phdr_align = *(uint64_t *)arg2;
> -        uint64_t nhdr_namesz = nhdr64->n_namesz;
> -
> -        elf_note_data_addr =
> -            ((void *)nhdr64) + nhdr_size64 +
> -            QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
> -    } else {
> -        struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
> -        uint32_t nhdr_size32 = sizeof(struct elf32_note);
> -        uint32_t phdr_align = *(uint32_t *)arg2;
> -        uint32_t nhdr_namesz = nhdr32->n_namesz;
> -
> -        elf_note_data_addr =
> -            ((void *)nhdr32) + nhdr_size32 +
> -            QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
> -    }
> -
> -    pvh_start_addr = *elf_note_data_addr;
> -
> -    return pvh_start_addr;
> -}
> -
> -static bool load_elfboot(const char *kernel_filename,
> -                   int kernel_file_size,
> -                   uint8_t *header,
> -                   size_t pvh_xen_start_addr,
> -                   FWCfgState *fw_cfg)
> -{
> -    uint32_t flags = 0;
> -    uint32_t mh_load_addr = 0;
> -    uint32_t elf_kernel_size = 0;
> -    uint64_t elf_entry;
> -    uint64_t elf_low, elf_high;
> -    int kernel_size;
> -
> -    if (ldl_p(header) != 0x464c457f) {
> -        return false; /* no elfboot */
> -    }
> -
> -    bool elf_is64 = header[EI_CLASS] == ELFCLASS64;
> -    flags = elf_is64 ?
> -        ((Elf64_Ehdr *)header)->e_flags : ((Elf32_Ehdr *)header)->e_flags;
> -
> -    if (flags & 0x00010004) { /* LOAD_ELF_HEADER_HAS_ADDR */
> -        error_report("elfboot unsupported flags = %x", flags);
> -        exit(1);
> -    }
> -
> -    uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
> -    kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
> -                           NULL, &elf_note_type, &elf_entry,
> -                           &elf_low, &elf_high, 0, I386_ELF_MACHINE,
> -                           0, 0);
> -
> -    if (kernel_size < 0) {
> -        error_report("Error while loading elf kernel");
> -        exit(1);
> -    }
> -    mh_load_addr = elf_low;
> -    elf_kernel_size = elf_high - elf_low;
> -
> -    if (pvh_start_addr == 0) {
> -        error_report("Error loading uncompressed kernel without PVH ELF Note");
> -        exit(1);
> -    }
> -    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, pvh_start_addr);
> -    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
> -    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, elf_kernel_size);
> -
> -    return true;
> -}
> -
>   static void load_linux(PCMachineState *pcms,
>                          FWCfgState *fw_cfg)
>   {
> @@ -1203,6 +1098,9 @@ static void load_linux(PCMachineState *pcms,
>       if (ldl_p(header+0x202) == 0x53726448) {
>           protocol = lduw_p(header+0x206);
>       } else {
> +        size_t pvh_start_addr;
> +        uint32_t mh_load_addr = 0;
> +        uint32_t elf_kernel_size = 0;
>           /*
>            * This could be a multiboot kernel. If it is, let's stop treating it
>            * like a Linux kernel.
> @@ -1220,10 +1118,16 @@ static void load_linux(PCMachineState *pcms,
>            * If load_elfboot() is successful, populate the fw_cfg info.
>            */
>           if (pcmc->pvh_enabled &&
> -            load_elfboot(kernel_filename, kernel_size,
> -                         header, pvh_start_addr, fw_cfg)) {
> +            pvh_load_elfboot(kernel_filename,
> +                             &mh_load_addr, &elf_kernel_size)) {
>               fclose(f);
>   
> +            pvh_start_addr = pvh_get_start_addr();
> +
> +            fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, pvh_start_addr);
> +            fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, mh_load_addr);
> +            fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, elf_kernel_size);
> +
>               fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
>                   strlen(kernel_cmdline) + 1);
>               fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
> diff --git a/hw/i386/pvh.c b/hw/i386/pvh.c
> new file mode 100644
> index 0000000000..61623b4533
> --- /dev/null
> +++ b/hw/i386/pvh.c
> @@ -0,0 +1,113 @@
> +/*
> + * PVH Boot Helper
> + *
> + * Copyright (C) 2019 Oracle
> + * Copyright (C) 2019 Red Hat, Inc
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/units.h"
> +#include "qemu/error-report.h"
> +#include "hw/loader.h"
> +#include "cpu.h"
> +#include "elf.h"
> +#include "pvh.h"
> +
> +static size_t pvh_start_addr = 0;
> +
> +size_t pvh_get_start_addr(void)
> +{
> +    return pvh_start_addr;
> +}
> +
> +/*
> + * The entry point into the kernel for PVH boot is different from
> + * the native entry point.  The PVH entry is defined by the x86/HVM
> + * direct boot ABI and is available in an ELFNOTE in the kernel binary.
> + *
> + * This function is passed to load_elf() when it is called from
> + * load_elfboot() which then additionally checks for an ELF Note of
> + * type XEN_ELFNOTE_PHYS32_ENTRY and passes it to this function to
> + * parse the PVH entry address from the ELF Note.
> + *
> + * Due to trickery in elf_opts.h, load_elf() is actually available as
> + * load_elf32() or load_elf64() and this routine needs to be able
> + * to deal with being called as 32 or 64 bit.
> + *
> + * The address of the PVH entry point is saved to the 'pvh_start_addr'
> + * global variable.  (although the entry point is 32-bit, the kernel
> + * binary can be either 32-bit or 64-bit).
> + */
> +
> +static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
> +{
> +    size_t *elf_note_data_addr;
> +
> +    /* Check if ELF Note header passed in is valid */
> +    if (arg1 == NULL) {
> +        return 0;
> +    }
> +
> +    if (is64) {
> +        struct elf64_note *nhdr64 = (struct elf64_note *)arg1;
> +        uint64_t nhdr_size64 = sizeof(struct elf64_note);
> +        uint64_t phdr_align = *(uint64_t *)arg2;
> +        uint64_t nhdr_namesz = nhdr64->n_namesz;
> +
> +        elf_note_data_addr =
> +            ((void *)nhdr64) + nhdr_size64 +
> +            QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
> +    } else {
> +        struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
> +        uint32_t nhdr_size32 = sizeof(struct elf32_note);
> +        uint32_t phdr_align = *(uint32_t *)arg2;
> +        uint32_t nhdr_namesz = nhdr32->n_namesz;
> +
> +        elf_note_data_addr =
> +            ((void *)nhdr32) + nhdr_size32 +
> +            QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
> +    }
> +
> +    pvh_start_addr = *elf_note_data_addr;
> +
> +    return pvh_start_addr;
> +}
> +
> +bool pvh_load_elfboot(const char *kernel_filename,
> +                      uint32_t *mh_load_addr,
> +                      uint32_t *elf_kernel_size)
> +{
> +    uint64_t elf_entry;
> +    uint64_t elf_low, elf_high;
> +    int kernel_size;
> +    uint64_t elf_note_type = XEN_ELFNOTE_PHYS32_ENTRY;
> +
> +    kernel_size = load_elf(kernel_filename, read_pvh_start_addr,
> +                           NULL, &elf_note_type, &elf_entry,
> +                           &elf_low, &elf_high, 0, I386_ELF_MACHINE,
> +                           0, 0);
> +
> +    if (kernel_size < 0) {
> +        error_report("Error while loading elf kernel");
> +        return false;
> +    }
> +
> +    if (pvh_start_addr == 0) {
> +        error_report("Error loading uncompressed kernel without PVH ELF Note");
> +        return false;
> +    }
> +
> +    if (mh_load_addr) {
> +        *mh_load_addr = elf_low;
> +    }
> +
> +    if (elf_kernel_size) {
> +        *elf_kernel_size = elf_high - elf_low;
> +    }
> +
> +    return true;
> +}
> diff --git a/hw/i386/pvh.h b/hw/i386/pvh.h
> new file mode 100644
> index 0000000000..ada67ff6e8
> --- /dev/null
> +++ b/hw/i386/pvh.h
> @@ -0,0 +1,10 @@
> +#ifndef HW_I386_PVH_H
> +#define HW_I386_PVH_H
> +
> +size_t pvh_get_start_addr(void);
> +
> +bool pvh_load_elfboot(const char *kernel_filename,
> +                      uint32_t *mh_load_addr,
> +                      uint32_t *elf_kernel_size);
> +
> +#endif
> 



  reply	other threads:[~2019-07-23  8:39 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-02 12:11 [Qemu-devel] [PATCH v3 0/4] Introduce the microvm machine type Sergio Lopez
2019-07-02 12:11 ` [Qemu-devel] [PATCH v3 1/4] hw/virtio: Factorize virtio-mmio headers Sergio Lopez
2019-07-25  9:46   ` Liam Merwick
2019-07-25  9:58     ` Michael S. Tsirkin
2019-07-25 10:03       ` Peter Maydell
2019-07-25 10:36       ` Paolo Bonzini
2019-07-02 12:11 ` [Qemu-devel] [PATCH v3 2/4] hw/i386: Add an Intel MPTable generator Sergio Lopez
2019-07-02 12:11 ` [Qemu-devel] [PATCH v3 3/4] hw/i386: Factorize PVH related functions Sergio Lopez
2019-07-23  8:39   ` Liam Merwick [this message]
2019-07-02 12:11 ` [Qemu-devel] [PATCH v3 4/4] hw/i386: Introduce the microvm machine type Sergio Lopez
2019-07-02 13:58   ` Gerd Hoffmann
2019-07-25 10:47   ` Paolo Bonzini
2019-07-02 15:01 ` [Qemu-devel] [PATCH v3 0/4] " no-reply
2019-07-02 15:23 ` Peter Maydell
2019-07-02 17:34   ` Sergio Lopez
2019-07-02 18:04     ` Peter Maydell
2019-07-02 22:04       ` Sergio Lopez
2019-07-25  9:59         ` Michael S. Tsirkin
2019-07-25 10:05           ` Peter Maydell
2019-07-25 10:10             ` Michael S. Tsirkin
2019-07-25 14:52               ` Sergio Lopez
2019-07-25 10:42             ` Sergio Lopez
2019-07-25 11:23               ` Paolo Bonzini
2019-07-25 12:01                 ` Stefan Hajnoczi
2019-07-25 12:10                   ` Michael S. Tsirkin
2019-07-25 13:26                     ` Stefan Hajnoczi
2019-07-25 13:43                       ` Paolo Bonzini
2019-07-25 13:54                         ` Michael S. Tsirkin
2019-07-25 14:13                           ` Paolo Bonzini
2019-07-25 14:42                             ` Michael S. Tsirkin
2019-07-25 14:04                         ` Peter Maydell
2019-07-25 14:26                           ` Paolo Bonzini
2019-07-25 14:35                             ` Michael S. Tsirkin
2019-07-25 14:42                         ` Sergio Lopez
2019-07-25 14:58                           ` Michael S. Tsirkin
2019-07-25 15:01                             ` Michael S. Tsirkin
2019-07-25 15:39                               ` Paolo Bonzini
2019-07-25 17:38                                 ` Michael S. Tsirkin
2019-07-26 12:46                                   ` Igor Mammedov
2019-07-25 15:49                               ` Sergio Lopez
2019-07-25 13:48                       ` Michael S. Tsirkin
2019-07-02 15:30 ` no-reply
2019-07-03  9:58 ` Stefan Hajnoczi
2019-07-18 15:21   ` Sergio Lopez
2019-07-19 10:29     ` Stefan Hajnoczi
2019-07-19 13:48       ` Sergio Lopez
2019-07-19 15:09         ` Stefan Hajnoczi
2019-07-19 15:42           ` Montes, Julio
2019-07-23  8:43             ` Sergio Lopez
2019-07-23  9:47               ` Stefan Hajnoczi
2019-07-23 10:01                 ` Paolo Bonzini
2019-07-24 11:14                   ` Paolo Bonzini
2019-07-25  9:35                     ` Sergio Lopez
2019-07-25 10:03                     ` Michael S. Tsirkin
2019-07-25 10:55                       ` Paolo Bonzini
2019-07-25 14:46                     ` Michael S. Tsirkin
2019-07-25 15:35                       ` Paolo Bonzini
2019-07-25 17:33                         ` Michael S. Tsirkin
2019-07-25 20:30                         ` Michael S. Tsirkin
2019-07-26  7:57                           ` Paolo Bonzini
2019-07-26 11:10                             ` Michael S. Tsirkin
2019-07-23 11:30                 ` Stefano Garzarella
2019-07-24 15:23                   ` Stefano Garzarella
2019-08-29  9:02 ` Jing Liu
2019-08-29 15:46   ` Sergio Lopez
2019-08-30  4:53     ` Jing Liu
2019-08-30 14:27       ` Sergio Lopez
2019-09-02  5:43         ` Jing Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=92aae459-a27f-9d3d-313e-ae99f1bbed92@oracle.com \
    --to=liam.merwick@oracle.com \
    --cc=ehabkost@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=maran.wilson@oracle.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=sgarzare@redhat.com \
    --cc=slp@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).