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

[Xen-changelog] [xen-unstable] x86: force DMI table to not be in E820 RAM region



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1190812456 -3600
# Node ID 80277ff19c9ccfae3bade36ca2664aae339cb91c
# Parent  0b873d909ad30e554a3ffebf14176e7257a3e023
x86: force DMI table to not be in E820 RAM region

In order for Dom0 to be able to map the DMI table, it must not be in
E820 RAM; since some BIOS versions apparently fail to set the type
correctly for the page(s) containing this table, adjust it before
starting to consume memory.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/dmi_scan.c    |   31 +++++++++++++--------
 xen/arch/x86/e820.c        |   65 +++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/setup.c       |   64 ++++----------------------------------------
 xen/include/asm-x86/e820.h |    1 
 xen/include/xen/dmi.h      |    2 +
 5 files changed, 94 insertions(+), 69 deletions(-)

diff -r 0b873d909ad3 -r 80277ff19c9c xen/arch/x86/dmi_scan.c
--- a/xen/arch/x86/dmi_scan.c   Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/arch/x86/dmi_scan.c   Wed Sep 26 14:14:16 2007 +0100
@@ -100,23 +100,32 @@ inline static int __init dmi_checksum(u8
        return (sum==0);
 }
 
-static int __init dmi_iterate(void (*decode)(struct dmi_header *))
+int __init dmi_get_table(u32 *base, u32 *len)
 {
        u8 buf[15];
        char __iomem *p, *q;
 
-       /*
-        * no iounmap() for that ioremap(); it would be a no-op, but it's
-        * so early in setup that sucker gets confused into doing what
-        * it shouldn't if we actually call it.
-        */
-       p = ioremap(0xF0000, 0x10000);
-       if (p == NULL)
-               return -1;
+       p = maddr_to_virt(0xF0000);
        for (q = p; q < p + 0x10000; q += 16) {
                memcpy_fromio(buf, q, 15);
-               if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
-               {
+               if (memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) {
+                       *base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+                       *len=buf[7]<<8|buf[6];
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+static int __init dmi_iterate(void (*decode)(struct dmi_header *))
+{
+       u8 buf[15];
+       char __iomem *p, *q;
+
+       p = maddr_to_virt(0xF0000);
+       for (q = p; q < p + 0x10000; q += 16) {
+               memcpy_fromio(buf, q, 15);
+               if (memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) {
                        u16 num=buf[13]<<8|buf[12];
                        u16 len=buf[7]<<8|buf[6];
                        u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
diff -r 0b873d909ad3 -r 80277ff19c9c xen/arch/x86/e820.c
--- a/xen/arch/x86/e820.c       Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/arch/x86/e820.c       Wed Sep 26 14:14:16 2007 +0100
@@ -2,6 +2,7 @@
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/compat.h>
+#include <xen/dmi.h>
 #include <asm/e820.h>
 #include <asm/page.h>
 
@@ -343,6 +344,15 @@ static void __init clip_to_limit(uint64_
     }
 }
 
+static void __init reserve_dmi_region(void)
+{
+    u32 base, len;
+    if ( (dmi_get_table(&base, &len) == 0) && ((base + len) > base) &&
+         reserve_e820_ram(&e820, base, base + len) )
+        printk("WARNING: DMI table located in E820 RAM %08x-%08x. Fixed.\n",
+               base, base+len);
+}
+
 static void __init machine_specific_memory_setup(
     struct e820entry *raw, int *raw_nr)
 {
@@ -366,6 +376,61 @@ static void __init machine_specific_memo
                   "Only the first %u GB of the physical memory map "
                   "can be accessed by 32-on-64 guests.");
 #endif
+
+    reserve_dmi_region();
+}
+
+/* Reserve RAM area (@s,@e) in the specified e820 map. */
+int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e)
+{
+    uint64_t rs = 0, re = 0;
+    int i;
+
+    for ( i = 0; i < e820->nr_map; i++ )
+    {
+        /* Have we found the e820 region that includes the specified range? */
+        rs = e820->map[i].addr;
+        re = rs + e820->map[i].size;
+        if ( (s >= rs) && (e <= re) )
+            break;
+    }
+
+    if ( (i == e820->nr_map) || (e820->map[i].type != E820_RAM) )
+        return 0;
+
+    if ( (s == rs) && (e == re) )
+    {
+        /* Complete excision. */
+        memmove(&e820->map[i], &e820->map[i+1],
+                (e820->nr_map-i-1) * sizeof(e820->map[0]));
+        e820->nr_map--;
+    }
+    else if ( s == rs )
+    {
+        /* Truncate start. */
+        e820->map[i].addr += e - s;
+        e820->map[i].size -= e - s;
+    }
+    else if ( e == re )
+    {
+        /* Truncate end. */
+        e820->map[i].size -= e - s;
+    }
+    else
+    {
+        /* Split in two. */
+        if ( e820->nr_map >= ARRAY_SIZE(e820->map) )
+            return 0;
+        memmove(&e820->map[i+1], &e820->map[i],
+                (e820->nr_map-i) * sizeof(e820->map[0]));
+        e820->nr_map++;
+        e820->map[i].size = s - rs;
+        i++;
+        e820->map[i].addr = e;
+        e820->map[i].size = re - e;
+    }
+
+    return 1;
 }
 
 unsigned long __init init_e820(
diff -r 0b873d909ad3 -r 80277ff19c9c xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/arch/x86/setup.c      Wed Sep 26 14:14:16 2007 +0100
@@ -19,6 +19,7 @@
 #include <xen/numa.h>
 #include <xen/rcupdate.h>
 #include <xen/vga.h>
+#include <xen/dmi.h>
 #include <public/version.h>
 #ifdef CONFIG_COMPAT
 #include <compat/platform.h>
@@ -45,7 +46,6 @@
 #define maddr_to_bootstrap_virt(m) ((void *)(long)(m))
 #endif
 
-extern void dmi_scan_machine(void);
 extern void generic_apic_probe(void);
 extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn);
 
@@ -280,41 +280,6 @@ static void __init move_memory(
 
 /* A temporary copy of the e820 map that we can mess with during bootstrap. */
 static struct e820map __initdata boot_e820;
-
-/* Reserve area (@s,@e) in the temporary bootstrap e820 map. */
-static int __init reserve_in_boot_e820(unsigned long s, unsigned long e)
-{
-    uint64_t rs, re;
-    int i;
-
-    for ( i = 0; i < boot_e820.nr_map; i++ )
-    {
-        /* Have we found the e820 region that includes the specified range? */
-        rs = boot_e820.map[i].addr;
-        re = rs + boot_e820.map[i].size;
-        if ( (s >= rs) && (e <= re) )
-            goto found;
-    }
-
-    return 0;
-
- found:
-    /* Start fragment. */
-    boot_e820.map[i].size = s - rs;
-
-    /* End fragment. */
-    if ( e < re )
-    {
-        memmove(&boot_e820.map[i+1], &boot_e820.map[i],
-                (boot_e820.nr_map-i) * sizeof(boot_e820.map[0]));
-        boot_e820.nr_map++;
-        i++;
-        boot_e820.map[i].addr = e;
-        boot_e820.map[i].size = re - e;
-    }
-
-    return 1;
-}
 
 struct boot_video_info {
     u8  orig_x;             /* 0x00 */
@@ -547,7 +512,7 @@ void __init __start_xen(unsigned long mb
     else if ( mbi->flags & MBI_MEMMAP )
     {
         memmap_type = "Multiboot-e820";
-        while ( bytes < mbi->mmap_length )
+        while ( (bytes < mbi->mmap_length) && (e820_raw_nr < E820MAX) )
         {
             memory_map_t *map = __va(mbi->mmap_addr + bytes);
 
@@ -597,23 +562,6 @@ void __init __start_xen(unsigned long mb
         EARLY_FAIL("Bootloader provided no memory information.\n");
     }
 
-    /* Ensure that all E820 RAM regions are page-aligned and -sized. */
-    for ( i = 0; i < e820_raw_nr; i++ )
-    {
-        uint64_t s, e;
-
-        if ( e820_raw[i].type != E820_RAM )
-            continue;
-        s = PFN_UP(e820_raw[i].addr);
-        e = PFN_DOWN(e820_raw[i].addr + e820_raw[i].size);
-        e820_raw[i].size = 0; /* discarded later */
-        if ( s < e )
-        {
-            e820_raw[i].addr = s << PAGE_SHIFT;
-            e820_raw[i].size = (e - s) << PAGE_SHIFT;
-        }
-    }
-
     /* Sanitise the raw E820 map to produce a final clean version. */
     max_page = init_e820(memmap_type, e820_raw, &e820_raw_nr);
 
@@ -760,7 +708,7 @@ void __init __start_xen(unsigned long mb
 
     if ( !initial_images_start )
         EARLY_FAIL("Not enough memory to relocate the dom0 kernel image.\n");
-    reserve_in_boot_e820(initial_images_start, initial_images_end);
+    reserve_e820_ram(&boot_e820, initial_images_start, initial_images_end);
 
     /*
      * With modules (and Xen itself, on x86/64) relocated out of the way, we
@@ -772,8 +720,8 @@ void __init __start_xen(unsigned long mb
     if ( !xen_phys_start )
         EARLY_FAIL("Not enough memory to relocate Xen.\n");
     xenheap_phys_end += xen_phys_start;
-    reserve_in_boot_e820(xen_phys_start,
-                         xen_phys_start + (opt_xenheap_megabytes<<20));
+    reserve_e820_ram(&boot_e820, xen_phys_start,
+                     xen_phys_start + (opt_xenheap_megabytes<<20));
     init_boot_pages(1<<20, 16<<20); /* Initial seed: 15MB */
 #else
     init_boot_pages(xenheap_phys_end, 16<<20); /* Initial seed: 4MB */
@@ -786,7 +734,7 @@ void __init __start_xen(unsigned long mb
 
         kdump_size = (kdump_size + PAGE_SIZE - 1) & PAGE_MASK;
 
-        if ( !reserve_in_boot_e820(kdump_start, kdump_size) )
+        if ( !reserve_e820_ram(&boot_e820, kdump_start, kdump_size) )
         {
             printk("Kdump: DISABLED (failed to reserve %luMB (%lukB) at 0x%lx)"
                    "\n", kdump_size >> 20, kdump_size >> 10, kdump_start);
diff -r 0b873d909ad3 -r 80277ff19c9c xen/include/asm-x86/e820.h
--- a/xen/include/asm-x86/e820.h        Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/include/asm-x86/e820.h        Wed Sep 26 14:14:16 2007 +0100
@@ -23,6 +23,7 @@ struct e820map {
     struct e820entry map[E820MAX];
 };
 
+extern int reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e);
 extern unsigned long init_e820(const char *, struct e820entry *, int *);
 extern struct e820map e820;
 
diff -r 0b873d909ad3 -r 80277ff19c9c xen/include/xen/dmi.h
--- a/xen/include/xen/dmi.h     Wed Sep 26 09:19:12 2007 +0100
+++ b/xen/include/xen/dmi.h     Wed Sep 26 14:14:16 2007 +0100
@@ -34,5 +34,7 @@ struct dmi_system_id {
 
 extern int dmi_check_system(struct dmi_system_id *list);
 extern char * dmi_get_system_info(int field);
+extern void dmi_scan_machine(void);
+extern int dmi_get_table(u32 *base, u32 *len);
 
 #endif /* __DMI_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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