# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID d61211a6c273de817af91944c666ffb6406c6798
# Parent 810ad61870e8c61a4e9ed096c4f73ab62048183b
Convert x86/32 Linux to use the new memory map hypercall.
This change removes several of the differences between the bare-metal
and Xen versions.
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 224
++++------
linux-2.6-xen-sparse/arch/i386/mm/init-xen.c | 13
linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h | 28 +
3 files changed, 134 insertions(+), 131 deletions(-)
diff -r 810ad61870e8 -r d61211a6c273
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Mon May 22 09:22:18
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Mon May 22 09:23:03
2006 +0100
@@ -70,9 +70,6 @@
/* Forward Declaration. */
void __init find_max_pfn(void);
-
-/* Allows setting of maximum possible memory size */
-static unsigned long xen_override_max_pfn;
static int xen_panic_event(struct notifier_block *, unsigned long, void *);
static struct notifier_block xen_panic_block = {
@@ -462,6 +459,19 @@ static void __init limit_regions(unsigne
}
return;
}
+#ifdef CONFIG_XEN
+ if (i==e820.nr_map && current_addr < size) {
+ /*
+ * The e820 map finished before our requested size so
+ * extend the final entry to the requested address.
+ */
+ --i;
+ if (e820.map[i].type == E820_RAM)
+ e820.map[i].size -= current_addr - size;
+ else
+ add_memory_region(current_addr, size - current_addr,
E820_RAM);
+ }
+#endif
}
#define E820_DEBUG 1
@@ -492,7 +502,6 @@ static void __init print_memory_map(char
}
}
-#if 0
/*
* Sanitize the BIOS e820 map.
*
@@ -680,9 +689,13 @@ static int __init sanitize_e820_map(stru
*/
static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
{
+#ifndef CONFIG_XEN
/* Only one memory region (or negative)? Ignore it */
if (nr_map < 2)
return -1;
+#else
+ BUG_ON(nr_map < 1);
+#endif
do {
unsigned long long start = biosmap->addr;
@@ -694,6 +707,7 @@ static int __init copy_e820_map(struct e
if (start > end)
return -1;
+#ifndef CONFIG_XEN
/*
* Some BIOSes claim RAM in the 640k - 1M region.
* Not right. Fix it up.
@@ -708,11 +722,11 @@ static int __init copy_e820_map(struct e
size = end - start;
}
}
+#endif
add_memory_region(start, size, type);
} while (biosmap++,--nr_map);
return 0;
}
-#endif
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd;
@@ -785,13 +799,8 @@ static void __init parse_cmdline_early (
unsigned long long mem_size;
mem_size = memparse(from+4, &from);
-#if 0
limit_regions(mem_size);
userdef=1;
-#else
- xen_override_max_pfn =
- (unsigned long)(mem_size>>PAGE_SHIFT);
-#endif
}
}
@@ -984,7 +993,6 @@ static void __init parse_cmdline_early (
}
}
-#if 0 /* !XEN */
/*
* Callback for efi_memory_walk.
*/
@@ -1036,21 +1044,6 @@ void __init find_max_pfn(void)
memory_present(0, start, end);
}
}
-#else
-/* We don't use the fake e820 because we need to respond to user override. */
-void __init find_max_pfn(void)
-{
- if (xen_override_max_pfn == 0) {
- max_pfn = xen_start_info->nr_pages;
- /* Default 8MB slack (to balance backend allocations). */
- max_pfn += 8 << (20 - PAGE_SHIFT);
- } else if (xen_override_max_pfn > xen_start_info->nr_pages) {
- max_pfn = xen_override_max_pfn;
- } else {
- max_pfn = xen_start_info->nr_pages;
- }
-}
-#endif /* XEN */
/*
* Determine low and high memory ranges:
@@ -1158,6 +1151,15 @@ static void __init register_bootmem_low_
*/
last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+#ifdef CONFIG_XEN
+ /*
+ * Truncate to the number of actual pages currently
+ * present.
+ */
+ if (last_pfn > xen_start_info->nr_pages)
+ last_pfn = xen_start_info->nr_pages;
+#endif
+
if (last_pfn > max_low_pfn)
last_pfn = max_low_pfn;
@@ -1351,83 +1353,33 @@ void __init remapped_pgdat_init(void)
* and also for regions reported as reserved by the e820.
*/
static void __init
-legacy_init_iomem_resources(struct resource *code_resource, struct resource
*data_resource)
+legacy_init_iomem_resources(struct e820entry *e820, int nr_map,
+ struct resource *code_resource,
+ struct resource *data_resource)
{
int i;
-#ifdef CONFIG_XEN
- dom0_op_t op;
- struct dom0_memory_map_entry *map;
- unsigned long gapstart, gapsize;
- unsigned long long last;
-#endif
-
-#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+
+#if defined(CONFIG_XEN_PRIVILEGED_GUEST) || !defined(CONFIG_XEN)
probe_roms();
#endif
-#ifdef CONFIG_XEN
- map = alloc_bootmem_low_pages(PAGE_SIZE);
- op.cmd = DOM0_PHYSICAL_MEMORY_MAP;
- set_xen_guest_handle(op.u.physical_memory_map.memory_map, map);
- op.u.physical_memory_map.max_map_entries =
- PAGE_SIZE / sizeof(struct dom0_memory_map_entry);
- BUG_ON(HYPERVISOR_dom0_op(&op));
-
- last = 0x100000000ULL;
- gapstart = 0x10000000;
- gapsize = 0x400000;
-
- for (i = op.u.physical_memory_map.nr_map_entries - 1; i >= 0; i--) {
+ for (i = 0; i < nr_map; i++) {
struct resource *res;
-
- if ((last > map[i].end) && ((last - map[i].end) > gapsize)) {
- gapsize = last - map[i].end;
- gapstart = map[i].end;
- }
- if (map[i].start < last)
- last = map[i].start;
-
- if (map[i].end > 0x100000000ULL)
+ if (e820[i].addr + e820[i].size > 0x100000000ULL)
continue;
res = alloc_bootmem_low(sizeof(struct resource));
- res->name = map[i].is_ram ? "System RAM" : "reserved";
- res->start = map[i].start;
- res->end = map[i].end - 1;
- res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- request_resource(&iomem_resource, res);
- }
-
- free_bootmem(__pa(map), PAGE_SIZE);
-
- /*
- * Start allocating dynamic PCI memory a bit into the gap,
- * aligned up to the nearest megabyte.
- *
- * Question: should we try to pad it up a bit (do something
- * like " + (gapsize >> 3)" in there too?). We now have the
- * technology.
- */
- pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
-
- printk("Allocating PCI resources starting at %08lx (gap:
%08lx:%08lx)\n",
- pci_mem_start, gapstart, gapsize);
-#else
- for (i = 0; i < e820.nr_map; i++) {
- struct resource *res;
- if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
- continue;
- res = alloc_bootmem_low(sizeof(struct resource));
- switch (e820.map[i].type) {
+ switch (e820[i].type) {
case E820_RAM: res->name = "System RAM"; break;
case E820_ACPI: res->name = "ACPI Tables"; break;
case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
default: res->name = "reserved";
}
- res->start = e820.map[i].addr;
- res->end = res->start + e820.map[i].size - 1;
+ res->start = e820[i].addr;
+ res->end = res->start + e820[i].size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
- if (e820.map[i].type == E820_RAM) {
+#ifndef CONFIG_XEN
+ if (e820[i].type == E820_RAM) {
/*
* We don't know which RAM region contains kernel data,
* so we try it repeatedly and let the resource manager
@@ -1439,38 +1391,21 @@ legacy_init_iomem_resources(struct resou
request_resource(res, &crashk_res);
#endif
}
- }
-#endif
-}
-
-/*
- * Request address space for all standard resources
- */
-static void __init register_memory(void)
-{
-#ifndef CONFIG_XEN
+#endif
+ }
+}
+
+/*
+ * Locate a unused range of the physical address space below 4G which
+ * can be used for PCI mappings.
+ */
+static void __init
+e820_setup_gap(struct e820entry *e820, int nr_map)
+{
unsigned long gapstart, gapsize, round;
unsigned long long last;
-#endif
- int i;
-
- /* Nothing to do if not running in dom0. */
- if (!(xen_start_info->flags & SIF_INITDOMAIN))
- return;
-
- if (efi_enabled)
- efi_initialize_iomem_resources(&code_resource, &data_resource);
- else
- legacy_init_iomem_resources(&code_resource, &data_resource);
-
- /* EFI systems may still have VGA */
- request_resource(&iomem_resource, &video_ram_resource);
-
- /* request I/O space for devices used on all i[345]86 PCs */
- for (i = 0; i < STANDARD_IO_RESOURCES; i++)
- request_resource(&ioport_resource, &standard_io_resources[i]);
-
-#ifndef CONFIG_XEN
+ int i;
+
/*
* Search for the bigest gap in the low 32 bits of the e820
* memory space.
@@ -1478,10 +1413,10 @@ static void __init register_memory(void)
last = 0x100000000ull;
gapstart = 0x10000000;
gapsize = 0x400000;
- i = e820.nr_map;
+ i = nr_map;
while (--i >= 0) {
- unsigned long long start = e820.map[i].addr;
- unsigned long long end = start + e820.map[i].size;
+ unsigned long long start = e820[i].addr;
+ unsigned long long end = start + e820[i].size;
/*
* Since "last" is at most 4GB, we know we'll
@@ -1511,6 +1446,53 @@ static void __init register_memory(void)
printk("Allocating PCI resources starting at %08lx (gap:
%08lx:%08lx)\n",
pci_mem_start, gapstart, gapsize);
+}
+
+/*
+ * Request address space for all standard resources
+ */
+static void __init register_memory(void)
+{
+#ifdef CONFIG_XEN
+ struct e820entry *machine_e820;
+ struct xen_memory_map memmap;
+#endif
+ int i;
+
+ /* Nothing to do if not running in dom0. */
+ if (!(xen_start_info->flags & SIF_INITDOMAIN))
+ return;
+
+#ifdef CONFIG_XEN
+ machine_e820 = alloc_bootmem_low_pages(PAGE_SIZE);
+
+ memmap.nr_entries = E820MAX;
+ set_xen_guest_handle(memmap.buffer, machine_e820);
+
+ BUG_ON(HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap));
+
+ legacy_init_iomem_resources(machine_e820, memmap.nr_entries,
+ &code_resource, &data_resource);
+#else
+ if (efi_enabled)
+ efi_initialize_iomem_resources(&code_resource, &data_resource);
+ else
+ legacy_init_iomem_resources(e820.map, e820.nr_map,
+ &code_resource, &data_resource);
+#endif
+
+ /* EFI systems may still have VGA */
+ request_resource(&iomem_resource, &video_ram_resource);
+
+ /* request I/O space for devices used on all i[345]86 PCs */
+ for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+ request_resource(&ioport_resource, &standard_io_resources[i]);
+
+#ifdef CONFIG_XEN
+ e820_setup_gap(machine_e820, memmap.nr_entries);
+ free_bootmem(__pa(machine_e820), PAGE_SIZE);
+#else
+ e820_setup_gap(e820.map, e820.nr_map);
#endif
}
diff -r 810ad61870e8 -r d61211a6c273
linux-2.6-xen-sparse/arch/i386/mm/init-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c Mon May 22 09:22:18
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/mm/init-xen.c Mon May 22 09:23:03
2006 +0100
@@ -228,6 +228,12 @@ static inline int page_kills_ppro(unsign
return 0;
}
+#else
+
+#define page_kills_ppro(p) 0
+
+#endif
+
extern int is_available_memory(efi_memory_desc_t *);
int page_is_ram(unsigned long pagenr)
@@ -268,13 +274,6 @@ int page_is_ram(unsigned long pagenr)
}
return 0;
}
-
-#else /* CONFIG_XEN */
-
-#define page_kills_ppro(p) 0
-#define page_is_ram(p) 1
-
-#endif
#ifdef CONFIG_HIGHMEM
pte_t *kmap_pte;
diff -r 810ad61870e8 -r d61211a6c273
linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Mon May
22 09:22:18 2006 +0100
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Mon May
22 09:23:03 2006 +0100
@@ -10,10 +10,32 @@
static char * __init machine_specific_memory_setup(void)
{
- unsigned long max_pfn = xen_start_info->nr_pages;
+ int rc;
+ struct xen_memory_map memmap;
+ /*
+ * This is rather large for a stack variable but this early in
+ * the boot process we know we have plenty slack space.
+ */
+ struct e820entry map[E820MAX];
- e820.nr_map = 0;
- add_memory_region(0, PFN_PHYS(max_pfn), E820_RAM);
+ memmap.nr_entries = E820MAX;
+ set_xen_guest_handle(memmap.buffer, map);
+
+ rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
+ if ( rc == -ENOSYS ) {
+ memmap.nr_entries = 1;
+ map[0].addr = 0ULL;
+ map[0].size = xen_start_info->nr_pages << PAGE_SHIFT;
+ /* 8MB slack (to balance backend allocations). */
+ map[0].size += 8 << 20;
+ map[0].type = E820_RAM;
+ rc = 0;
+ }
+ BUG_ON(rc);
+
+ sanitize_e820_map(map, (char *)&memmap.nr_entries);
+
+ BUG_ON(copy_e820_map(map, (char)memmap.nr_entries) < 0);
return "Xen";
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|