]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: jbeulich@novell.com |
2 | Subject: fix issues with the assignment of huge amounts of memory | |
3 | Patch-mainline: obsolete | |
82094b55 | 4 | References: bnc#482614, bnc#537435 |
2cb7cef9 | 5 | |
82094b55 AF |
6 | --- sle11-2009-09-18.orig/arch/x86/kernel/e820-xen.c 2009-02-17 14:01:20.000000000 +0100 |
7 | +++ sle11-2009-09-18/arch/x86/kernel/e820-xen.c 2009-09-18 10:08:03.000000000 +0200 | |
8 | @@ -1317,6 +1317,26 @@ static int __init parse_memopt(char *p) | |
2cb7cef9 BS |
9 | |
10 | i = e820.nr_map - 1; | |
11 | current_end = e820.map[i].addr + e820.map[i].size; | |
12 | + | |
13 | + /* | |
14 | + * A little less than 2% of available memory are needed for page | |
15 | + * tables, p2m map, and mem_map. Hence the maximum amount of memory | |
16 | + * we can potentially balloon up to can in no case exceed about 50 | |
17 | + * times of what we've been given initially. Since even with that we | |
18 | + * won't be able to boot (due to various calculations done based on | |
19 | + * the total number of pages) we further restrict this to factor 32. | |
20 | + */ | |
21 | + if ((mem_size >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) { | |
22 | + u64 size = (u64)xen_start_info->nr_pages << 5; | |
23 | + | |
24 | + printk(KERN_WARNING "mem=%Luk is invalid for an initial" | |
25 | + " allocation of %luk, using %Luk\n", | |
26 | + (unsigned long long)mem_size >> 10, | |
27 | + xen_start_info->nr_pages << (PAGE_SHIFT - 10), | |
28 | + (unsigned long long)size << (PAGE_SHIFT - 10)); | |
29 | + mem_size = size << PAGE_SHIFT; | |
30 | + } | |
31 | + | |
32 | if (current_end < mem_size) { | |
33 | /* | |
34 | * The e820 map ends before our requested size so | |
82094b55 | 35 | @@ -1416,7 +1436,7 @@ void __init e820_reserve_resources(void) |
2cb7cef9 BS |
36 | struct resource *res; |
37 | u64 end; | |
38 | ||
39 | - res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map); | |
40 | + res = alloc_bootmem(sizeof(struct resource) * e820.nr_map); | |
41 | for (i = 0; i < e820.nr_map; i++) { | |
42 | end = e820.map[i].addr + e820.map[i].size - 1; | |
43 | #ifndef CONFIG_RESOURCES_64BIT | |
82094b55 AF |
44 | @@ -1498,6 +1518,7 @@ char *__init __attribute__((weak)) machi |
45 | char * __init memory_setup(void) | |
46 | { | |
47 | int rc, nr_map; | |
48 | + unsigned long long maxmem; | |
49 | struct xen_memory_map memmap; | |
50 | /* | |
51 | * This is rather large for a stack variable but this early in | |
52 | @@ -1527,6 +1548,22 @@ char * __init memory_setup(void) | |
53 | BUG(); | |
54 | ||
55 | #ifdef CONFIG_XEN | |
56 | + /* See the comment in parse_memopt(). */ | |
57 | + for (maxmem = rc = 0; rc < e820.nr_map; ++rc) | |
58 | + if (e820.map[rc].type == E820_RAM) | |
59 | + maxmem += e820.map[rc].size; | |
60 | + if ((maxmem >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) { | |
61 | + unsigned long long size = (u64)xen_start_info->nr_pages << 5; | |
62 | + | |
63 | + printk(KERN_WARNING "maxmem of %LuM is invalid for an initial" | |
64 | + " allocation of %luM, using %LuM\n", | |
65 | + maxmem >> 20, | |
66 | + xen_start_info->nr_pages >> (20 - PAGE_SHIFT), | |
67 | + size >> (20 - PAGE_SHIFT)); | |
68 | + size <<= PAGE_SHIFT; | |
69 | + e820_remove_range(size, ULLONG_MAX - size, E820_RAM, 1); | |
70 | + } | |
71 | + | |
72 | if (is_initial_xendomain()) { | |
73 | memmap.nr_entries = E820MAX; | |
74 | set_xen_guest_handle(memmap.buffer, machine_e820.map); | |
75 | --- sle11-2009-09-18.orig/arch/x86/kernel/setup-xen.c 2009-07-31 15:14:20.000000000 +0200 | |
76 | +++ sle11-2009-09-18/arch/x86/kernel/setup-xen.c 2009-07-31 15:14:31.000000000 +0200 | |
2cb7cef9 BS |
77 | @@ -128,12 +128,7 @@ static struct notifier_block xen_panic_b |
78 | unsigned long *phys_to_machine_mapping; | |
79 | EXPORT_SYMBOL(phys_to_machine_mapping); | |
80 | ||
81 | -unsigned long *pfn_to_mfn_frame_list_list, | |
82 | -#ifdef CONFIG_X86_64 | |
83 | - *pfn_to_mfn_frame_list[512]; | |
84 | -#else | |
85 | - *pfn_to_mfn_frame_list[128]; | |
86 | -#endif | |
87 | +unsigned long *pfn_to_mfn_frame_list_list, **pfn_to_mfn_frame_list; | |
88 | ||
89 | /* Raw start-of-day parameters from the hypervisor. */ | |
90 | start_info_t *xen_start_info; | |
91 | @@ -1036,17 +1031,17 @@ void __init setup_arch(char **cmdline_p) | |
92 | p2m_pages = xen_start_info->nr_pages; | |
93 | ||
94 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | |
95 | - unsigned long i, j; | |
96 | + unsigned long i, j, size; | |
97 | unsigned int k, fpp; | |
98 | ||
99 | /* Make sure we have a large enough P->M table. */ | |
100 | phys_to_machine_mapping = alloc_bootmem_pages( | |
101 | max_pfn * sizeof(unsigned long)); | |
102 | - memset(phys_to_machine_mapping, ~0, | |
103 | - max_pfn * sizeof(unsigned long)); | |
104 | memcpy(phys_to_machine_mapping, | |
105 | (unsigned long *)xen_start_info->mfn_list, | |
106 | p2m_pages * sizeof(unsigned long)); | |
107 | + memset(phys_to_machine_mapping + p2m_pages, ~0, | |
108 | + (max_pfn - p2m_pages) * sizeof(unsigned long)); | |
109 | free_bootmem( | |
110 | __pa(xen_start_info->mfn_list), | |
111 | PFN_PHYS(PFN_UP(xen_start_info->nr_pages * | |
112 | @@ -1056,15 +1051,26 @@ void __init setup_arch(char **cmdline_p) | |
113 | * Initialise the list of the frames that specify the list of | |
114 | * frames that make up the p2m table. Used by save/restore. | |
115 | */ | |
116 | - pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE); | |
117 | - | |
118 | fpp = PAGE_SIZE/sizeof(unsigned long); | |
119 | + size = (max_pfn + fpp - 1) / fpp; | |
120 | + size = (size + fpp - 1) / fpp; | |
121 | + ++size; /* include a zero terminator for crash tools */ | |
122 | + size *= sizeof(unsigned long); | |
123 | + pfn_to_mfn_frame_list_list = alloc_bootmem_pages(size); | |
124 | + if (size > PAGE_SIZE | |
125 | + && xen_create_contiguous_region((unsigned long) | |
126 | + pfn_to_mfn_frame_list_list, | |
127 | + get_order(size), 0)) | |
128 | + BUG(); | |
129 | + size -= sizeof(unsigned long); | |
130 | + pfn_to_mfn_frame_list = alloc_bootmem(size); | |
131 | + | |
132 | for (i = j = 0, k = -1; i < max_pfn; i += fpp, j++) { | |
133 | if (j == fpp) | |
134 | j = 0; | |
135 | if (j == 0) { | |
136 | k++; | |
137 | - BUG_ON(k>=ARRAY_SIZE(pfn_to_mfn_frame_list)); | |
138 | + BUG_ON(k * sizeof(unsigned long) >= size); | |
139 | pfn_to_mfn_frame_list[k] = | |
140 | alloc_bootmem_pages(PAGE_SIZE); | |
141 | pfn_to_mfn_frame_list_list[k] = | |
82094b55 AF |
142 | --- sle11-2009-09-18.orig/arch/x86/kernel/setup_percpu-xen.c 2009-08-26 12:17:43.000000000 +0200 |
143 | +++ sle11-2009-09-18/arch/x86/kernel/setup_percpu-xen.c 2009-08-26 12:19:19.000000000 +0200 | |
144 | @@ -206,7 +206,7 @@ static void __init setup_node_to_cpumask | |
2cb7cef9 BS |
145 | } |
146 | ||
147 | /* allocate the map */ | |
148 | - map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t)); | |
149 | + map = alloc_bootmem(nr_node_ids * sizeof(cpumask_t)); | |
150 | ||
151 | pr_debug(KERN_DEBUG "Node to cpumask map at %p for %d nodes\n", | |
152 | map, nr_node_ids); | |
82094b55 AF |
153 | --- sle11-2009-09-18.orig/drivers/xen/core/machine_kexec.c 2009-06-04 10:21:39.000000000 +0200 |
154 | +++ sle11-2009-09-18/drivers/xen/core/machine_kexec.c 2009-03-13 16:13:15.000000000 +0100 | |
2cb7cef9 BS |
155 | @@ -57,7 +57,7 @@ void __init xen_machine_kexec_setup_reso |
156 | ||
157 | /* allocate xen_phys_cpus */ | |
158 | ||
159 | - xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource)); | |
160 | + xen_phys_cpus = alloc_bootmem(k * sizeof(struct resource)); | |
161 | BUG_ON(xen_phys_cpus == NULL); | |
162 | ||
163 | /* fill in xen_phys_cpus with per-cpu crash note information */ | |
82094b55 AF |
164 | --- sle11-2009-09-18.orig/drivers/xen/core/machine_reboot.c 2009-02-17 12:23:48.000000000 +0100 |
165 | +++ sle11-2009-09-18/drivers/xen/core/machine_reboot.c 2009-02-17 12:25:29.000000000 +0100 | |
2cb7cef9 BS |
166 | @@ -76,7 +76,7 @@ static void post_suspend(int suspend_can |
167 | unsigned long shinfo_mfn; | |
168 | extern unsigned long max_pfn; | |
169 | extern unsigned long *pfn_to_mfn_frame_list_list; | |
170 | - extern unsigned long *pfn_to_mfn_frame_list[]; | |
171 | + extern unsigned long **pfn_to_mfn_frame_list; | |
172 | ||
173 | if (suspend_cancelled) { | |
174 | xen_start_info->store_mfn = |