diff options
author | Keir Fraser <keir@xensource.com> | 2007-09-26 14:14:16 +0100 |
---|---|---|
committer | Keir Fraser <keir@xensource.com> | 2007-09-26 14:14:16 +0100 |
commit | 1906b3ab6683ce6669d298279211bca575eea2ed (patch) | |
tree | 7deeef1ead7680dfae582228ff4e116e86ae295c /xen/arch/x86/e820.c | |
parent | b85210e23c64c43efefa86fa1f701d5172d4556b (diff) | |
download | xen-1906b3ab6683ce6669d298279211bca575eea2ed.tar.gz xen-1906b3ab6683ce6669d298279211bca575eea2ed.tar.bz2 xen-1906b3ab6683ce6669d298279211bca575eea2ed.zip |
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@novell.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/arch/x86/e820.c')
-rw-r--r-- | xen/arch/x86/e820.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c index 835a0f76f3..e678a4be52 100644 --- a/xen/arch/x86/e820.c +++ b/xen/arch/x86/e820.c @@ -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_t limit, char *warnmsg) } } +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_memory_setup( "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( |