You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qubes-linux-kernel/patches.xen/xen-x86-bigmem

144 lines
5.4 KiB

From: jbeulich@novell.com
Subject: fix issues with the assignment of huge amounts of memory
Patch-mainline: obsolete
References: bnc#482614, bnc#537435
--- head-2011-01-30.orig/arch/x86/kernel/e820-xen.c 2011-02-01 15:41:35.000000000 +0100
+++ head-2011-01-30/arch/x86/kernel/e820-xen.c 2011-02-03 14:42:11.000000000 +0100
@@ -951,6 +951,26 @@ static int __init parse_memopt(char *p)
userdef = 1;
mem_size = memparse(p, &p);
+#ifdef CONFIG_XEN
+ /*
+ * A little less than 2% of available memory are needed for page
+ * tables, p2m map, and mem_map. Hence the maximum amount of memory
+ * we can potentially balloon up to can in no case exceed about 50
+ * times of what we've been given initially. Since even with that we
+ * won't be able to boot (due to various calculations done based on
+ * the total number of pages) we further restrict this to factor 32.
+ */
+ if ((mem_size >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) {
+ u64 size = (u64)xen_start_info->nr_pages << 5;
+
+ pr_warning("mem=%Luk is invalid for an initial"
+ " allocation of %luk, using %Luk\n",
+ (unsigned long long)mem_size >> 10,
+ xen_start_info->nr_pages << (PAGE_SHIFT - 10),
+ (unsigned long long)size << (PAGE_SHIFT - 10));
+ mem_size = size << PAGE_SHIFT;
+ }
+#endif
e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
i = e820.nr_map - 1;
@@ -1149,6 +1169,7 @@ void __init e820_reserve_resources_late(
char *__init default_machine_specific_memory_setup(void)
{
int rc, nr_map;
+ unsigned long long maxmem;
struct xen_memory_map memmap;
static struct e820entry __initdata map[E820MAX];
@@ -1174,6 +1195,22 @@ char *__init default_machine_specific_me
BUG();
#ifdef CONFIG_XEN
+ /* See the comment in parse_memopt(). */
+ for (maxmem = rc = 0; rc < e820.nr_map; ++rc)
+ if (e820.map[rc].type == E820_RAM)
+ maxmem += e820.map[rc].size;
+ if ((maxmem >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) {
+ unsigned long long size = (u64)xen_start_info->nr_pages << 5;
+
+ pr_warning("maxmem of %LuM is invalid for an initial"
+ " allocation of %luM, using %LuM\n",
+ maxmem >> 20,
+ xen_start_info->nr_pages >> (20 - PAGE_SHIFT),
+ size >> (20 - PAGE_SHIFT));
+ size <<= PAGE_SHIFT;
+ e820_remove_range(size, ULLONG_MAX - size, E820_RAM, 1);
+ }
+
if (is_initial_xendomain()) {
memmap.nr_entries = E820MAX;
set_xen_guest_handle(memmap.buffer, machine_e820.map);
--- head-2011-01-30.orig/arch/x86/kernel/setup-xen.c 2011-01-03 14:07:52.000000000 +0100
+++ head-2011-01-30/arch/x86/kernel/setup-xen.c 2011-02-03 14:42:11.000000000 +0100
@@ -132,12 +132,7 @@ static struct notifier_block xen_panic_b
unsigned long *phys_to_machine_mapping;
EXPORT_SYMBOL(phys_to_machine_mapping);
-unsigned long *pfn_to_mfn_frame_list_list,
-#ifdef CONFIG_X86_64
- *pfn_to_mfn_frame_list[512];
-#else
- *pfn_to_mfn_frame_list[128];
-#endif
+unsigned long *pfn_to_mfn_frame_list_list, **pfn_to_mfn_frame_list;
/* Raw start-of-day parameters from the hypervisor. */
start_info_t *xen_start_info;
@@ -1188,17 +1183,17 @@ void __init setup_arch(char **cmdline_p)
p2m_pages = xen_start_info->nr_pages;
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
- unsigned long i, j;
+ unsigned long i, j, size;
unsigned int k, fpp;
/* Make sure we have a large enough P->M table. */
phys_to_machine_mapping = alloc_bootmem_pages(
max_pfn * sizeof(unsigned long));
- memset(phys_to_machine_mapping, ~0,
- max_pfn * sizeof(unsigned long));
memcpy(phys_to_machine_mapping,
(unsigned long *)xen_start_info->mfn_list,
p2m_pages * sizeof(unsigned long));
+ memset(phys_to_machine_mapping + p2m_pages, ~0,
+ (max_pfn - p2m_pages) * sizeof(unsigned long));
free_bootmem(
__pa(xen_start_info->mfn_list),
PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
@@ -1208,15 +1203,26 @@ void __init setup_arch(char **cmdline_p)
* Initialise the list of the frames that specify the list of
* frames that make up the p2m table. Used by save/restore.
*/
- pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE);
-
fpp = PAGE_SIZE/sizeof(unsigned long);
+ size = (max_pfn + fpp - 1) / fpp;
+ size = (size + fpp - 1) / fpp;
+ ++size; /* include a zero terminator for crash tools */
+ size *= sizeof(unsigned long);
+ pfn_to_mfn_frame_list_list = alloc_bootmem_pages(size);
+ if (size > PAGE_SIZE
+ && xen_create_contiguous_region((unsigned long)
+ pfn_to_mfn_frame_list_list,
+ get_order(size), 0))
+ BUG();
+ size -= sizeof(unsigned long);
+ pfn_to_mfn_frame_list = alloc_bootmem(size);
+
for (i = j = 0, k = -1; i < max_pfn; i += fpp, j++) {
if (j == fpp)
j = 0;
if (j == 0) {
k++;
- BUG_ON(k>=ARRAY_SIZE(pfn_to_mfn_frame_list));
+ BUG_ON(k * sizeof(unsigned long) >= size);
pfn_to_mfn_frame_list[k] =
alloc_bootmem_pages(PAGE_SIZE);
pfn_to_mfn_frame_list_list[k] =
--- head-2011-01-30.orig/drivers/xen/core/machine_reboot.c 2011-02-02 15:10:16.000000000 +0100
+++ head-2011-01-30/drivers/xen/core/machine_reboot.c 2011-02-03 14:42:11.000000000 +0100
@@ -75,7 +75,7 @@ static void post_suspend(int suspend_can
unsigned long shinfo_mfn;
extern unsigned long max_pfn;
extern unsigned long *pfn_to_mfn_frame_list_list;
- extern unsigned long *pfn_to_mfn_frame_list[];
+ extern unsigned long **pfn_to_mfn_frame_list;
if (suspend_cancelled) {
xen_start_info->store_mfn =