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

Re: [Xen-devel] [PATCH for-xen-4.5 v3 09/16] x86: Move legacy BIOS memory map stuff to boot_info



On Wed, 8 Oct 2014, Daniel Kiper wrote:
> Signed-off-by: Daniel Kiper <daniel.kiper@xxxxxxxxxx>
> ---
>  xen/arch/x86/boot_info.c        |  105 
> ++++++++++++++++++++++++++++++++++++---
>  xen/arch/x86/efi/efi-boot.h     |   18 +++----
>  xen/arch/x86/setup.c            |   73 ++-------------------------
>  xen/common/efi/runtime.c        |    7 +++
>  xen/include/asm-x86/boot_info.h |   22 ++++++++
>  xen/include/asm-x86/e820.h      |    8 ---
>  6 files changed, 138 insertions(+), 95 deletions(-)
> 
> diff --git a/xen/arch/x86/boot_info.c b/xen/arch/x86/boot_info.c
> index 7101f6c..53e890b 100644
> --- a/xen/arch/x86/boot_info.c
> +++ b/xen/arch/x86/boot_info.c
> @@ -15,40 +15,127 @@
>   * with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +/*
> + * Some ideas are taken (out) from xen/arch/x86/boot/reloc.c,
> + * xen/arch/x86/efi/boot.c and xen/arch/x86/setup.c.
> + */
> +
>  #include <xen/types.h>
>  #include <xen/cache.h>
>  #include <xen/init.h>
>  #include <xen/multiboot.h>
>  
>  #include <asm/boot_info.h>
> +#include <asm/e820.h>
>  #include <asm/mbd.h>
>  #include <asm/page.h>
>  
> +/* These symbols live in the boot trampoline. Access via bootsym(). */
> +extern struct e820entry e820map[];
> +extern unsigned int e820nr;
> +extern unsigned int lowmem_kb, highmem_kb;
> +
>  static multiboot_info_t __read_mostly mbi;
>  
>  static boot_info_t __read_mostly boot_info_mb = {
>      .boot_loader_name = "UNKNOWN",
>      .cmdline = NULL,
> +    .mmap_type = NULL,
> +    .mem_upper = 0,
> +    .e820map_nr = 0,
> +    .e820map = NULL,
>      .warn_msg = NULL,
>      .err_msg = NULL
>  };
>  
> +#define e820_raw bootsym(e820map)
> +#define e820_raw_nr bootsym(e820nr)
> +
>  extern void enable_exception_support(void);
>  
> +static void __init init_mmap(boot_info_t *boot_info, mbd_t *mbd)
> +{
> +    int bytes = 0;
> +    memory_map_t *map;
> +
> +    if ( e820_raw_nr )
> +        boot_info->mmap_type = "Xen-e820";
> +    else if ( mbd->mmap_size )
> +    {
> +        boot_info->mmap_type = "Multiboot-e820";
> +
> +        while ( (bytes < mbd->mmap_size) && (e820_raw_nr < E820MAX) )
> +        {
> +            /*
> +             * This is a gross workaround for a BIOS bug. Some bootloaders do
> +             * not write e820 map entries into pre-zeroed memory. This is
> +             * okay if the BIOS fills in all fields of the map entry, but
> +             * some broken BIOSes do not bother to write the high word of
> +             * the length field if the length is smaller than 4GB. We
> +             * detect and fix this by flagging sections below 4GB that
> +             * appear to be larger than 4GB in size.
> +             */
> +            map = __va(mbd->mmap + bytes);
> +
> +            if ( !map->base_addr_high && map->length_high )
> +            {
> +                map->length_high = 0;
> +                boot_info->warn_msg = "WARNING: Buggy e820 map detected and 
> fixed "
> +                                "(truncated length fields).\n";
> +            }
> +
> +            e820_raw[e820_raw_nr].addr =
> +                ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
> +            e820_raw[e820_raw_nr].size =
> +                ((u64)map->length_high << 32) | (u64)map->length_low;
> +            e820_raw[e820_raw_nr].type = map->type;
> +            e820_raw_nr++;
> +
> +            bytes += map->size + 4;
> +        }
> +    }
> +    else if ( bootsym(lowmem_kb) )
> +    {
> +        boot_info->mmap_type = "Xen-e801";
> +
> +        e820_raw[0].addr = 0;
> +        e820_raw[0].size = bootsym(lowmem_kb) << 10;
> +        e820_raw[0].type = E820_RAM;
> +        e820_raw[1].addr = 0x100000;
> +        e820_raw[1].size = bootsym(highmem_kb) << 10;
> +        e820_raw[1].type = E820_RAM;
> +        e820_raw_nr = 2;
> +    }
> +    else if ( mbd->mem_lower || mbd->mem_upper )
> +    {
> +        boot_info->mmap_type = "Multiboot-e801";
> +
> +        e820_raw[0].addr = 0;
> +        e820_raw[0].size = mbd->mem_lower << 10;
> +        e820_raw[0].type = E820_RAM;
> +        e820_raw[1].addr = 0x100000;
> +        e820_raw[1].size = mbd->mem_upper << 10;
> +        e820_raw[1].type = E820_RAM;
> +        e820_raw_nr = 2;
> +    }
> +    else
> +    {
> +        boot_info->err_msg = "Bootloader provided no memory information.\n";
> +        return;
> +    }
> +
> +    boot_info->mem_upper = mbd->mem_upper;
> +
> +    boot_info->e820map_nr = e820_raw_nr;
> +    boot_info->e820map = e820_raw;
> +}
> +
>  unsigned long __init __init_mbi(u32 mbd_pa)
>  {
>      mbd_t *mbd = __va(mbd_pa);
>  
>      enable_exception_support();
>  
> -    mbi.flags |= MBI_MEMLIMITS;
> -    mbi.mem_lower = mbd->mem_lower;
> -    mbi.mem_upper = mbd->mem_upper;
> -
> -    mbi.flags |= MBI_MEMMAP;
> -    mbi.mmap_length = mbd->mmap_size;
> -    mbi.mmap_addr = mbd->mmap;
> -
>      mbi.flags |= MBI_MODULES;
>      mbi.mods_count = mbd->mods_nr;
>      mbi.mods_addr = mbd->mods;
> @@ -66,5 +153,7 @@ paddr_t __init __init_boot_info(u32 mbd_pa)
>      if ( mbd->cmdline )
>          boot_info_mb.cmdline = __va(mbd->cmdline);
>  
> +    init_mmap(&boot_info_mb, mbd);
> +
>      return __pa(&boot_info_mb);
>  }
> diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
> index 3b5628a..8e57ac2 100644
> --- a/xen/arch/x86/efi/efi-boot.h
> +++ b/xen/arch/x86/efi/efi-boot.h
> @@ -148,7 +148,7 @@ static void __init 
> efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
>      unsigned int i;
>  
>      /* Populate E820 table and check trampoline area availability. */
> -    e = e820map - 1;
> +    e = boot_info_efi.e820map - 1;
>      for ( i = 0; i < map_size; i += desc_size )
>      {
>          EFI_MEMORY_DESCRIPTOR *desc = map + i;
> @@ -182,10 +182,10 @@ static void __init 
> efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
>              type = E820_NVS;
>              break;
>          }
> -        if ( e820nr && type == e->type &&
> +        if ( boot_info_efi.e820map_nr && type == e->type &&
>               desc->PhysicalStart == e->addr + e->size )
>              e->size += len;
> -        else if ( !len || e820nr >= E820MAX )
> +        else if ( !len || boot_info_efi.e820map_nr >= E820MAX )
>              continue;
>          else
>          {
> @@ -193,7 +193,7 @@ static void __init 
> efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
>              e->addr = desc->PhysicalStart;
>              e->size = len;
>              e->type = type;
> -            ++e820nr;
> +            ++boot_info_efi.e820map_nr;
>          }
>      }
>  
> @@ -201,12 +201,12 @@ static void __init 
> efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
>  
>  static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
>  {
> -    place_string_u32(&mbi.mem_upper, NULL);
> -    mbi.mem_upper -= map_size;
> -    mbi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
> -    if ( mbi.mem_upper < xen_phys_start )
> +    place_string_u32(&boot_info_efi.mem_upper, NULL);
> +    boot_info_efi.mem_upper -= map_size;
> +    boot_info_efi.mem_upper &= -__alignof__(EFI_MEMORY_DESCRIPTOR);
> +    if ( boot_info_efi.mem_upper < xen_phys_start )
>          return NULL;
> -    return (void *)(long)mbi.mem_upper;
> +    return (void *)(long)boot_info_efi.mem_upper;
>  }
>  
>  static void __init efi_arch_pre_exit_boot(void)
> diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
> index d7416d3..de29d9e 100644
> --- a/xen/arch/x86/setup.c
> +++ b/xen/arch/x86/setup.c
> @@ -553,13 +553,12 @@ void __init enable_exception_support(void)
>  
>  void __init noreturn __start_xen(unsigned long mbi_p, paddr_t boot_info_pa)
>  {
> -    char *memmap_type = NULL;
>      char *cmdline, *kextra;
>      unsigned int initrdidx, domcr_flags = DOMCRF_s3_integrity;
>      multiboot_info_t *mbi = __va(mbi_p);
>      module_t *mod = (module_t *)__va(mbi->mods_addr);
>      unsigned long nr_pages, raw_max_page, modules_headroom, *module_map;
> -    int i, j, e820_warn = 0, bytes = 0;
> +    int i, j;
>      bool_t acpi_boot_table_init_done = 0;
>      struct domain *dom0;
>      struct ns16550_defaults ns16550 = {
> @@ -692,77 +691,11 @@ void __init noreturn __start_xen(unsigned long mbi_p, 
> paddr_t boot_info_pa)
>          /* Make boot page tables match non-EFI boot. */
>          l3_bootmap[l3_table_offset(BOOTSTRAP_MAP_BASE)] =
>              l3e_from_paddr(__pa(l2_bootmap), __PAGE_HYPERVISOR);
> -
> -        memmap_type = boot_info->boot_loader_name;
> -    }
> -    else if ( e820_raw_nr != 0 )
> -    {
> -        memmap_type = "Xen-e820";
>      }
> -    else if ( mbi->flags & MBI_MEMMAP )
> -    {
> -        memmap_type = "Multiboot-e820";
> -        while ( (bytes < mbi->mmap_length) && (e820_raw_nr < E820MAX) )
> -        {
> -            memory_map_t *map = __va(mbi->mmap_addr + bytes);
> -
> -            /*
> -             * This is a gross workaround for a BIOS bug. Some bootloaders do
> -             * not write e820 map entries into pre-zeroed memory. This is
> -             * okay if the BIOS fills in all fields of the map entry, but
> -             * some broken BIOSes do not bother to write the high word of
> -             * the length field if the length is smaller than 4GB. We
> -             * detect and fix this by flagging sections below 4GB that
> -             * appear to be larger than 4GB in size.
> -             */
> -            if ( (map->base_addr_high == 0) && (map->length_high != 0) )
> -            {
> -                if ( !e820_warn )
> -                {
> -                    printk("WARNING: Buggy e820 map detected and fixed "
> -                           "(truncated length fields).\n");
> -                    e820_warn = 1;
> -                }
> -                map->length_high = 0;
> -            }
> -
> -            e820_raw[e820_raw_nr].addr = 
> -                ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
> -            e820_raw[e820_raw_nr].size = 
> -                ((u64)map->length_high << 32) | (u64)map->length_low;
> -            e820_raw[e820_raw_nr].type = map->type;
> -            e820_raw_nr++;
> -
> -            bytes += map->size + 4;
> -        }
> -    }
> -    else if ( bootsym(lowmem_kb) )
> -    {
> -        memmap_type = "Xen-e801";
> -        e820_raw[0].addr = 0;
> -        e820_raw[0].size = bootsym(lowmem_kb) << 10;
> -        e820_raw[0].type = E820_RAM;
> -        e820_raw[1].addr = 0x100000;
> -        e820_raw[1].size = bootsym(highmem_kb) << 10;
> -        e820_raw[1].type = E820_RAM;
> -        e820_raw_nr = 2;
> -    }
> -    else if ( mbi->flags & MBI_MEMLIMITS )
> -    {
> -        memmap_type = "Multiboot-e801";
> -        e820_raw[0].addr = 0;
> -        e820_raw[0].size = mbi->mem_lower << 10;
> -        e820_raw[0].type = E820_RAM;
> -        e820_raw[1].addr = 0x100000;
> -        e820_raw[1].size = mbi->mem_upper << 10;
> -        e820_raw[1].type = E820_RAM;
> -        e820_raw_nr = 2;
> -    }
> -    else
> -        panic("Bootloader provided no memory information.");
>  
>      /* Sanitise the raw E820 map to produce a final clean version. */
> -    max_page = raw_max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);
> +    max_page = raw_max_page = init_e820(boot_info->mmap_type, 
> boot_info->e820map,
> +                                        &boot_info->e820map_nr);
>  
>      /* Create a temporary copy of the E820 map. */
>      memcpy(&boot_e820, &e820, sizeof(e820));
> diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
> index ee2ee2d..865d0bc 100644
> --- a/xen/common/efi/runtime.c
> +++ b/xen/common/efi/runtime.c
> @@ -7,6 +7,7 @@
>  #include <xen/time.h>
>  #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
>  #include <asm/boot_info.h>
> +#include <asm/e820.h>
>  #endif
>  
>  DEFINE_XEN_GUEST_HANDLE(CHAR16);
> @@ -53,9 +54,15 @@ struct efi __read_mostly efi = {
>  const struct efi_pci_rom *__read_mostly efi_pci_roms;
>  
>  #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
> +extern struct e820entry e820map[];
> +
>  boot_info_t __read_mostly boot_info_efi = {
>      .boot_loader_name = "EFI",
>      .cmdline = NULL,
> +    .mmap_type = "EFI",
> +    .mem_upper = 0,
> +    .e820map_nr = 0,
> +    .e820map = e820map,
>      .warn_msg = NULL,
>      .err_msg = NULL
>  };

This is not going in the right direction of getting rid of arch-specific
concepts from xen/common/efi/runtime.c.


> diff --git a/xen/include/asm-x86/boot_info.h b/xen/include/asm-x86/boot_info.h
> index d74ed67..640a420 100644
> --- a/xen/include/asm-x86/boot_info.h
> +++ b/xen/include/asm-x86/boot_info.h
> @@ -18,6 +18,10 @@
>  #ifndef __BOOT_INFO_H__
>  #define __BOOT_INFO_H__
>  
> +#include <xen/types.h>
> +
> +#include <asm/e820.h>
> +
>  /*
>   * Define boot_info type. It will be used to define variable which in turn
>   * will store data collected by bootloader and preloader. This way it will
> @@ -35,6 +39,24 @@ typedef struct {
>      /* Xen command line. */
>      char *cmdline;
>  
> +    /* Memory map type (source of memory map). */
> +    char *mmap_type;

I realize that you inherited mmap_type from existing code, but shouldn't
this be an enum?


> +    /*
> +     * Amount of upper memory (in KiB) accordingly to The Multiboot
> +     * Specification version 0.6.96.
> +     */
> +    u32 mem_upper;
> +
> +    /* Number of memory map entries provided by Xen preloader. */
> +    unsigned int e820map_nr;
> +
> +    /*
> +     * Memory map provided by Xen preloader. It should always point
> +     * to an area able to accommodate at least E820MAX entries.
> +     */
> +    struct e820entry *e820map;
> +
>      /*
>       * Info about warning occurred during boot_info initialization.
>       * NULL if everything went OK.
> diff --git a/xen/include/asm-x86/e820.h b/xen/include/asm-x86/e820.h
> index d9ff4eb..8727afb 100644
> --- a/xen/include/asm-x86/e820.h
> +++ b/xen/include/asm-x86/e820.h
> @@ -33,12 +33,4 @@ extern int e820_add_range(
>  extern unsigned long init_e820(const char *, struct e820entry *, unsigned 
> int *);
>  extern struct e820map e820;
>  
> -/* These symbols live in the boot trampoline. */
> -extern struct e820entry e820map[];
> -extern unsigned int e820nr;
> -extern unsigned int lowmem_kb, highmem_kb;
> -
> -#define e820_raw bootsym(e820map)
> -#define e820_raw_nr bootsym(e820nr)
> -
>  #endif /*__E820_HEADER*/
> -- 
> 1.7.10.4
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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