[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [RFC 3/3] pvh: Boot uncompressed kernel using direct boot ABI



On Tue, Dec 11, 2018 at 7:35 PM Maran Wilson <maran.wilson@xxxxxxxxxx> wrote:
>
> On 12/11/2018 9:11 AM, Stefano Garzarella wrote:
> > Hi Liam,
> > in order to support PVH also with SeaBIOS, I'm going to work on a new
> > option rom (like linuxboot/multiboot) that can be used in this case.
>
> That is awesome. Yes, please keep us posted when you have something working.

Yes, I'll keep you updated!

>
> Just FYI, before switching over to using Qemu+qboot, we had been using a
> Qemu only solution (but not using an option rom) internally that worked
> very well using no FW at all. We had Qemu simply parse the ELF file and
> jump to the PVH entry point if one is found. The only gotcha was that we
> had to include a pair of patches that were originally written by folks
> at Intel as part of the clear containers work. Specifically, in order to
> be able to skip firmware entirely, we had to do 2 additional things: (1)
> ACPI tables generated by Qemu are usually patched up by FW. Since we
> were running no FW, we needed to do that patching up of the ACPI tables
> in Qemu when it was detected that we were going to enter the OS via the
> PVH entry point. (2) We also needed to add a patch to Qemu to enable a
> few PM registers -- something typically done by FW.

I had a look of qemu-lite, are you referring to this?

>
> But if SeaBIOS is involved in the solution you are working on, I guess
> you won't really need those extra patches. Just figured I'd mention it
> so you have the full picture.

Thank you very much to share with me these details!

Cheers,
Stefano

>
> Thanks,
> -Maran
>
> > I'll keep you updated on it!
> >
> > Cheers,
> > Stefano
> > On Wed, Dec 5, 2018 at 11:38 PM Liam Merwick <liam.merwick@xxxxxxxxxx> 
> > wrote:
> >> These changes (along with corresponding qboot and Linux kernel changes)
> >> enable a guest to be booted using the x86/HVM direct boot ABI.
> >>
> >> This commit adds a load_elfboot() routine to pass the size and
> >> location of the kernel entry point to qboot (which will fill in
> >> the start_info struct information needed to to boot the guest).
> >> Having loaded the ELF binary, load_linux() will run qboot
> >> which continues the boot.
> >>
> >> The address for the kernel entry point has already been read
> >> from an ELF Note in the uncompressed kernel binary earlier
> >> in pc_memory_init().
> >>
> >> Signed-off-by: George Kennedy <George.Kennedy@xxxxxxxxxx>
> >> Signed-off-by: Liam Merwick <Liam.Merwick@xxxxxxxxxx>
> >> ---
> >>   hw/i386/pc.c | 72 
> >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>   1 file changed, 72 insertions(+)
> >>
> >> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> >> index 056aa46d99b9..d3012cbd8597 100644
> >> --- a/hw/i386/pc.c
> >> +++ b/hw/i386/pc.c
> >> @@ -54,6 +54,7 @@
> >>   #include "sysemu/qtest.h"
> >>   #include "kvm_i386.h"
> >>   #include "hw/xen/xen.h"
> >> +#include "hw/xen/start_info.h"
> >>   #include "ui/qemu-spice.h"
> >>   #include "exec/memory.h"
> >>   #include "exec/address-spaces.h"
> >> @@ -1098,6 +1099,50 @@ done:
> >>       return pvh_start_addr != 0;
> >>   }
> >>
> >> +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);
> >> +    }
> >> +
> >> +    kernel_size = load_elf(kernel_filename, NULL, NULL, &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;
> >> +
> >> +    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ENTRY, pvh_xen_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)
> >>   {
> >> @@ -1138,6 +1183,33 @@ static void load_linux(PCMachineState *pcms,
> >>       if (ldl_p(header+0x202) == 0x53726448) {
> >>           protocol = lduw_p(header+0x206);
> >>       } else {
> >> +        /* If the kernel address for using the x86/HVM direct boot ABI has
> >> +         * been saved then proceed with booting the uncompressed kernel */
> >> +        if (pvh_start_addr) {
> >> +            if (load_elfboot(kernel_filename, kernel_size,
> >> +                             header, pvh_start_addr, fw_cfg)) {
> >> +                struct hvm_modlist_entry ramdisk_mod = { 0 };
> >> +
> >> +                fclose(f);
> >> +
> >> +                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);
> >> +
> >> +                assert(machine->device_memory != NULL);
> >> +                ramdisk_mod.paddr = machine->device_memory->base;
> >> +                ramdisk_mod.size =
> >> +                    memory_region_size(&machine->device_memory->mr);
> >> +
> >> +                fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, &ramdisk_mod,
> >> +                                 sizeof(ramdisk_mod));
> >> +                fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, sizeof(header));
> >> +                fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA,
> >> +                                 header, sizeof(header));
> >> +
> >> +                return;
> >> +            }
> >> +        }
> >>           /* This looks like a multiboot kernel. If it is, let's stop
> >>              treating it like a Linux kernel. */
> >>           if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
> >> --
> >> 1.8.3.1
> >>
> >
>


-- 
Stefano Garzarella
Red Hat

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.