144 lines
5.4 KiB
Plaintext
144 lines
5.4 KiB
Plaintext
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 =
|