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

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



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
 };
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;
+
+    /*
+     * 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®.