aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/e820.c
diff options
context:
space:
mode:
authorKeir Fraser <keir@xensource.com>2007-09-26 14:14:16 +0100
committerKeir Fraser <keir@xensource.com>2007-09-26 14:14:16 +0100
commit1906b3ab6683ce6669d298279211bca575eea2ed (patch)
tree7deeef1ead7680dfae582228ff4e116e86ae295c /xen/arch/x86/e820.c
parentb85210e23c64c43efefa86fa1f701d5172d4556b (diff)
downloadxen-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.c65
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(