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

Re: [PATCH 04/10] x86 setup: porting dom0 construction logic to boot module structures



On Sat, 1 Jul 2023, Christopher Clark wrote:
> Adjust the PV and PVH dom0 construction entry points to take boot module
> structures as parameters, and add further fields to the boot module
> structures to plumb the data needed to support this use. Populate these
> from the multiboot module data.
> 
> This change removes multiboot from the PV and PVH dom0 construction logic.
> 
> Introduce and use new inline accessor functions for navigating the boot
> module structures.
> 
> The per-boot-module arrays are expanded from singletons to accommodate
> all modules, up to a static maximum of 64 modules including Xen that can
> be accepted from a bootloader to match the previous value from the
> module map check.
> 
> The field that identifies the type of a boot module (kernel, ramdisk,
> etc) is introduced to the common boot module structure and declared as a
> non-enum integer type to allow the field to be of a known-size and so
> structure can be packed in a subsequent patch in the series, and it will
> then be reconciled with the equivalent Arm boot field type.
> 
> The command line provided by multiboot for each boot module is added
> directly to the boot_module structure, which is appropriate for this
> logic just replacing multiboot.
> 
> The maximum number of boot modules that a bootloader can provide in
> addition to the Xen hypervisor is preserved from prior logic with the
> module_map at 63.
> 
> Signed-off-by: Christopher Clark <christopher.w.clark@xxxxxxxxx>
> Signed-off-by: Daniel P. Smith <dpsmith@xxxxxxxxxxxxxxxxxxxx>
> 
> ---
> Changes since v1: patch is a subset of v1 series patches 2 and 3.
> - The module_map is kept for now since still in use.
> - Move the static inline functions into a separate dedicated header.
> - <mm-frame.h> and <compiler.h> replace prior inclusion of <mm.h>
>   for simpler dependencies.
> 
>  xen/arch/x86/dom0_build.c             |  10 +-
>  xen/arch/x86/hvm/dom0_build.c         |  43 +++---
>  xen/arch/x86/include/asm/boot.h       |  36 +++++
>  xen/arch/x86/include/asm/bootinfo.h   |  24 +++
>  xen/arch/x86/include/asm/dom0_build.h |  13 +-
>  xen/arch/x86/include/asm/setup.h      |   4 +-
>  xen/arch/x86/pv/dom0_build.c          |  32 ++--
>  xen/arch/x86/setup.c                  | 206 +++++++++++++++-----------
>  xen/include/xen/bootinfo.h            |  27 ++++
>  9 files changed, 254 insertions(+), 141 deletions(-)
> 
> diff --git a/xen/arch/x86/dom0_build.c b/xen/arch/x86/dom0_build.c
> index 9f5300a3ef..42310202a2 100644
> --- a/xen/arch/x86/dom0_build.c
> +++ b/xen/arch/x86/dom0_build.c
> @@ -4,6 +4,7 @@
>   * Copyright (c) 2002-2005, K A Fraser
>   */
>  
> +#include <xen/bootinfo.h>
>  #include <xen/init.h>
>  #include <xen/iocap.h>
>  #include <xen/libelf.h>
> @@ -562,9 +563,8 @@ int __init dom0_setup_permissions(struct domain *d)
>      return rc;
>  }
>  
> -int __init construct_dom0(struct domain *d, const module_t *image,
> -                          unsigned long image_headroom, module_t *initrd,
> -                          char *cmdline)
> +int __init construct_dom0(struct domain *d, const struct boot_module *image,
> +    struct boot_module *initrd, char *cmdline)
>  {
>      int rc;
>  
> @@ -576,9 +576,9 @@ int __init construct_dom0(struct domain *d, const 
> module_t *image,
>      process_pending_softirqs();
>  
>      if ( is_hvm_domain(d) )
> -        rc = dom0_construct_pvh(d, image, image_headroom, initrd, cmdline);
> +        rc = dom0_construct_pvh(d, image, initrd, cmdline);
>      else if ( is_pv_domain(d) )
> -        rc = dom0_construct_pv(d, image, image_headroom, initrd, cmdline);
> +        rc = dom0_construct_pv(d, image, initrd, cmdline);
>      else
>          panic("Cannot construct Dom0. No guest interface available\n");
>  
> diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c
> index 56fe89632b..c094863bb8 100644
> --- a/xen/arch/x86/hvm/dom0_build.c
> +++ b/xen/arch/x86/hvm/dom0_build.c
> @@ -8,9 +8,9 @@
>   */
>  
>  #include <xen/acpi.h>
> +#include <xen/bootinfo.h>
>  #include <xen/init.h>
>  #include <xen/libelf.h>
> -#include <xen/multiboot.h>
>  #include <xen/pci.h>
>  #include <xen/softirq.h>
>  
> @@ -530,14 +530,13 @@ static paddr_t __init find_memory(
>      return INVALID_PADDR;
>  }
>  
> -static int __init pvh_load_kernel(struct domain *d, const module_t *image,
> -                                  unsigned long image_headroom,
> -                                  module_t *initrd, void *image_base,
> -                                  char *cmdline, paddr_t *entry,
> -                                  paddr_t *start_info_addr)
> +static int __init pvh_load_kernel(
> +    struct domain *d, const struct boot_module *image,
> +    struct boot_module *initrd, void *image_base, char *cmdline, paddr_t 
> *entry,
> +    paddr_t *start_info_addr)
>  {
> -    void *image_start = image_base + image_headroom;
> -    unsigned long image_len = image->mod_end;
> +    void *image_start = image_base + image->arch->headroom;
> +    unsigned long image_len = image->size;
>      struct elf_binary elf;
>      struct elf_dom_parms parms;
>      paddr_t last_addr;
> @@ -546,7 +545,7 @@ static int __init pvh_load_kernel(struct domain *d, const 
> module_t *image,
>      struct vcpu *v = d->vcpu[0];
>      int rc;
>  
> -    if ( (rc = bzimage_parse(image_base, &image_start, image_headroom,
> +    if ( (rc = bzimage_parse(image_base, &image_start, image->arch->headroom,
>                               &image_len)) != 0 )
>      {
>          printk("Error trying to detect bz compressed kernel\n");
> @@ -594,7 +593,7 @@ static int __init pvh_load_kernel(struct domain *d, const 
> module_t *image,
>       * simplify it.
>       */
>      last_addr = find_memory(d, &elf, sizeof(start_info) +
> -                            (initrd ? ROUNDUP(initrd->mod_end, PAGE_SIZE) +
> +                            (initrd ? ROUNDUP(initrd->size, PAGE_SIZE) +
>                                        sizeof(mod)
>                                      : 0) +
>                              (cmdline ? ROUNDUP(strlen(cmdline) + 1,
> @@ -608,8 +607,8 @@ static int __init pvh_load_kernel(struct domain *d, const 
> module_t *image,
>  
>      if ( initrd != NULL )
>      {
> -        rc = hvm_copy_to_guest_phys(last_addr, 
> mfn_to_virt(initrd->mod_start),
> -                                    initrd->mod_end, v);
> +        rc = hvm_copy_to_guest_phys(last_addr, maddr_to_virt(initrd->start),
> +                                    initrd->size, v);
>          if ( rc )
>          {
>              printk("Unable to copy initrd to guest\n");
> @@ -617,11 +616,11 @@ static int __init pvh_load_kernel(struct domain *d, 
> const module_t *image,
>          }
>  
>          mod.paddr = last_addr;
> -        mod.size = initrd->mod_end;
> -        last_addr += ROUNDUP(initrd->mod_end, elf_64bit(&elf) ? 8 : 4);
> -        if ( initrd->string )
> +        mod.size = initrd->size;
> +        last_addr += ROUNDUP(initrd->size, elf_64bit(&elf) ? 8 : 4);
> +        if ( initrd->string.len )
>          {
> -            char *str = __va(initrd->string);
> +            char *str = initrd->string.bytes;
>              size_t len = strlen(str) + 1;
>  
>              rc = hvm_copy_to_guest_phys(last_addr, str, len, v);
> @@ -1176,10 +1175,9 @@ static void __hwdom_init pvh_setup_mmcfg(struct domain 
> *d)
>      }
>  }
>  
> -int __init dom0_construct_pvh(struct domain *d, const module_t *image,
> -                              unsigned long image_headroom,
> -                              module_t *initrd,
> -                              char *cmdline)
> +int __init dom0_construct_pvh(
> +    struct domain *d, const struct boot_module *image,
> +    struct boot_module *initrd, char *cmdline)
>  {
>      paddr_t entry, start_info;
>      int rc;
> @@ -1209,9 +1207,8 @@ int __init dom0_construct_pvh(struct domain *d, const 
> module_t *image,
>          return rc;
>      }
>  
> -    rc = pvh_load_kernel(d, image, image_headroom, initrd,
> -                         bootstrap_map_multiboot(image),
> -                         cmdline, &entry, &start_info);
> +    rc = pvh_load_kernel(d, image, initrd, bootstrap_map(image), cmdline,
> +                         &entry, &start_info);
>      if ( rc )
>      {
>          printk("Failed to load Dom0 kernel\n");
> diff --git a/xen/arch/x86/include/asm/boot.h b/xen/arch/x86/include/asm/boot.h
> index 10b17f12b2..bcf4f2e2e3 100644
> --- a/xen/arch/x86/include/asm/boot.h
> +++ b/xen/arch/x86/include/asm/boot.h
> @@ -19,6 +19,42 @@ static inline void *bootstrap_map_multiboot(const module_t 
> *mod)
>      return bootstrap_map(&bm);
>  }
>  
> +static inline unsigned long bootmodule_index(
> +    const struct boot_info *info, bootmod_type_t bootmod_type,
> +    unsigned long start)
> +{
> +    for ( ; start < info->nr_mods; start++ )
> +        if ( info->mods[start].bootmod_type == bootmod_type )
> +            return start;
> +
> +    return info->nr_mods + 1;
> +}
> +
> +static inline struct boot_module *bootmodule_next(
> +    const struct boot_info *info, bootmod_type_t bootmod_type)
> +{
> +    unsigned long i;
> +
> +    for ( i = 0; i < info->nr_mods; i++ )
> +        if ( info->mods[i].bootmod_type == bootmod_type )
> +            return &info->mods[i];
> +
> +    return NULL;
> +}
> +
> +static inline void bootmodule_update_start(struct boot_module *bm,
> +    paddr_t new_start)
> +{
> +    bm->start = new_start;
> +    bm->mfn = maddr_to_mfn(new_start);
> +}
> +
> +static inline void bootmodule_update_mfn(struct boot_module *bm, mfn_t 
> new_mfn)
> +{
> +    bm->mfn = new_mfn;
> +    bm->start = mfn_to_maddr(new_mfn);
> +}
> +
>  #endif
>  
>  /*
> diff --git a/xen/arch/x86/include/asm/bootinfo.h 
> b/xen/arch/x86/include/asm/bootinfo.h
> index a25054f372..30c27980e0 100644
> --- a/xen/arch/x86/include/asm/bootinfo.h
> +++ b/xen/arch/x86/include/asm/bootinfo.h
> @@ -2,9 +2,33 @@
>  #define __ARCH_X86_BOOTINFO_H__
>  
>  struct arch_bootmodule {
> +#define BOOTMOD_FLAG_X86_RELOCATED     1U << 0
> +    uint32_t flags;
>      unsigned headroom;
>  };
>  
> +struct arch_boot_info {
> +    uint32_t flags;
> +#define BOOTINFO_FLAG_X86_CMDLINE      1U << 2

Is this to indicate the presence of the Xen cmdline?


> +#define BOOTINFO_FLAG_X86_MODULES      1U << 3
> +#define BOOTINFO_FLAG_X86_MEMMAP       1U << 6
> +#define BOOTINFO_FLAG_X86_LOADERNAME   1U << 9
> +
> +    char *boot_loader_name;
> +
> +    uint32_t mmap_length;
> +    paddr_t mmap_addr;
> +};
> +
> +struct __packed mb_memmap {
> +    uint32_t size;
> +    uint32_t base_addr_low;
> +    uint32_t base_addr_high;
> +    uint32_t length_low;
> +    uint32_t length_high;
> +    uint32_t type;
> +};
> +
>  #endif
>  
>  /*
> diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
> index 3b623a4149..f9b04daebd 100644
> --- a/xen/arch/x86/setup.c
> +++ b/xen/arch/x86/setup.c
> @@ -37,6 +37,7 @@
>  #include <asm/processor.h>
>  #include <asm/mpspec.h>
>  #include <asm/apic.h>
> +#include <asm/boot.h>
>  #include <asm/msi.h>
>  #include <asm/desc.h>
>  #include <asm/paging.h>
> @@ -59,6 +60,9 @@
>  #include <asm/prot-key.h>
>  #include <asm/pv/domain.h>
>  
> +/* Max number of boot modules a bootloader can provide in addition to Xen */
> +#define MAX_NR_BOOTMODS 63

Call it MAX_MODULES ?
Like I wrote in the past, you already did the hard work of aligning the
interfaces, we might as well also use the same names.

[...]

> @@ -1357,12 +1382,14 @@ void __init noreturn __start_xen(unsigned long mbi_p)
>           * respective reserve_e820_ram() invocation below. No need to
>           * query efi_boot_mem_unused() here, though.
>           */
> -        mod[boot_info->nr_mods].mod_start = virt_to_mfn(_stext);
> -        mod[boot_info->nr_mods].mod_end = __2M_rwdata_end - _stext;
> +        bootmodule_update_start(&boot_info->mods[boot_info->nr_mods],
> +                                virt_to_maddr(_stext));
> +        boot_info->mods[boot_info->nr_mods].size = __2M_rwdata_end - _stext;
>      }

The original code had the end address as "__2M_rwdata_end - _stext"
while now we have the size as "__2M_rwdata_end - _stext" which is not
the same?



>      boot_info->mods[0].arch->headroom =
> -        bzimage_headroom(bootstrap_map_multiboot(mod), mod->mod_end);
> +        bzimage_headroom(bootstrap_map(&boot_info->mods[0]),
> +                         boot_info->mods[0].size);
>  
>      bootstrap_map(NULL);
>  

[...]


> diff --git a/xen/include/xen/bootinfo.h b/xen/include/xen/bootinfo.h
> index eb93cc3439..2f4284a91f 100644
> --- a/xen/include/xen/bootinfo.h
> +++ b/xen/include/xen/bootinfo.h
> @@ -2,23 +2,50 @@
>  #define __XEN_BOOTINFO_H__
>  
>  #include <xen/types.h>
> +#include <xen/compiler.h>
> +#include <xen/mm-frame.h>
>  
>  #ifdef CONFIG_X86
>  #include <asm/bootinfo.h>
>  #else
>      struct arch_bootmodule { };
> +    struct arch_boot_info { };
>  #endif
>  
> +/* Boot module binary type / purpose */
> +#define BOOTMOD_UNKNOWN     0
> +#define BOOTMOD_XEN         1
> +#define BOOTMOD_FDT         2
> +#define BOOTMOD_KERNEL      3
> +#define BOOTMOD_RAMDISK     4
> +#define BOOTMOD_XSM         5
> +#define BOOTMOD_UCODE       6
> +#define BOOTMOD_GUEST_DTB   7
> +typedef unsigned int bootmod_type_t;
> +
> +#define BOOTMOD_STRING_MAX_LEN 1024

BOOTMOD_MAX_CMDLINE ?


> +struct boot_string {

struct bootcmdline ?


> +    char bytes[BOOTMOD_STRING_MAX_LEN];

cmdline?

If the string is \0 terminated we don't need len?


> +    size_t len;
> +};
> +
>  struct boot_module {
> +    bootmod_type_t bootmod_type;

Why not use a good old enum?


>      paddr_t start;
> +    mfn_t mfn;

I think mfn should be in arch_bootmodule


>      size_t size;
>  
>      struct arch_bootmodule *arch;
> +    struct boot_string string;
>  };
>  
>  struct boot_info {
> +    char *cmdline;

Is this for Xen cmdline? While all the other cmdline are in the various
struct boot_string? Is there any benefit in using the BOOTMOD_XEN for it?
BOOTMOD_XEN is not used so far, so if you don't end up using it,
probably not, otherwise it could be considered.




>      unsigned int nr_mods;
>      struct boot_module *mods;
> +
> +    struct arch_boot_info *arch;
>  };
>  
>  #endif
> -- 
> 2.25.1
> 
> 



 


Rackspace

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