WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-3.1-testing] x86: force DMI table to not be in E820

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-3.1-testing] x86: force DMI table to not be in E820 RAM region
From: "Xen patchbot-3.1-testing" <patchbot-3.1-testing@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 10 Dec 2007 03:11:00 -0800
Delivery-date: Mon, 10 Dec 2007 03:51:56 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1197134286 0
# Node ID 49fa281c89721b623203bfa0548d451b846c0728
# Parent  0069a86da1040fd6ebba5734f28f8dee56cc5eaf
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-unstable changeset:   15964:80277ff19c9c
xen-unstable date:        Wed Sep 26 14:14:16 2007 +0100
---
 xen/arch/x86/dmi_scan.c    |   31 +++++++++++-------
 xen/arch/x86/e820.c        |   77 +++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/setup.c       |   64 +++----------------------------------
 xen/include/asm-x86/e820.h |    1 
 xen/include/xen/dmi.h      |    2 +
 5 files changed, 106 insertions(+), 69 deletions(-)

diff -r 0069a86da104 -r 49fa281c8972 xen/arch/x86/dmi_scan.c
--- a/xen/arch/x86/dmi_scan.c   Sat Dec 08 17:07:56 2007 +0000
+++ b/xen/arch/x86/dmi_scan.c   Sat Dec 08 17:18:06 2007 +0000
@@ -102,23 +102,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 0069a86da104 -r 49fa281c8972 xen/arch/x86/e820.c
--- a/xen/arch/x86/e820.c       Sat Dec 08 17:07:56 2007 +0000
+++ b/xen/arch/x86/e820.c       Sat Dec 08 17:18:06 2007 +0000
@@ -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>
 
@@ -367,6 +368,15 @@ static void __init clip_mem(void)
     }
 }
 
+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)
 {
@@ -376,6 +386,73 @@ static void __init machine_specific_memo
     (void)copy_e820_map(raw, nr);
     clip_4gb();
     clip_mem();
+    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 if ( e820->nr_map < ARRAY_SIZE(e820->map) )
+    {
+        /* Split in two. */
+        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;
+    }
+    else
+    {
+        /* e820map is at maximum size. We have to leak some space. */
+        if ( (s - rs) > (re - e) )
+        {
+            printk("e820 overflow: leaking RAM %"PRIx64"-%"PRIx64"\n", e, re);
+            e820->map[i].size = s - rs;
+        }
+        else
+        {
+            printk("e820 overflow: leaking RAM %"PRIx64"-%"PRIx64"\n", rs, s);
+            e820->map[i].addr = e;
+            e820->map[i].size = re - e;
+        }
+    }
+
+    return 1;
 }
 
 unsigned long __init init_e820(
diff -r 0069a86da104 -r 49fa281c8972 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Sat Dec 08 17:07:56 2007 +0000
+++ b/xen/arch/x86/setup.c      Sat Dec 08 17:18:06 2007 +0000
@@ -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>
@@ -44,7 +45,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);
 
@@ -313,41 +313,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 */
@@ -582,7 +547,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);
 
@@ -633,23 +598,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);
 
@@ -796,7 +744,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
@@ -808,8 +756,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 */
@@ -822,7 +770,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 0069a86da104 -r 49fa281c8972 xen/include/asm-x86/e820.h
--- a/xen/include/asm-x86/e820.h        Sat Dec 08 17:07:56 2007 +0000
+++ b/xen/include/asm-x86/e820.h        Sat Dec 08 17:18:06 2007 +0000
@@ -22,6 +22,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 0069a86da104 -r 49fa281c8972 xen/include/xen/dmi.h
--- a/xen/include/xen/dmi.h     Sat Dec 08 17:07:56 2007 +0000
+++ b/xen/include/xen/dmi.h     Sat Dec 08 17:18:06 2007 +0000
@@ -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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-3.1-testing] x86: force DMI table to not be in E820 RAM region, Xen patchbot-3.1-testing <=