# 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
|