x86: move e820_mark_nosave_regions to e820.c
[deliverable/linux.git] / arch / x86 / kernel / e820_32.c
1 #include <linux/kernel.h>
2 #include <linux/types.h>
3 #include <linux/init.h>
4 #include <linux/bootmem.h>
5 #include <linux/ioport.h>
6 #include <linux/string.h>
7 #include <linux/kexec.h>
8 #include <linux/module.h>
9 #include <linux/mm.h>
10 #include <linux/pfn.h>
11 #include <linux/uaccess.h>
12
13 #include <asm/pgtable.h>
14 #include <asm/page.h>
15 #include <asm/e820.h>
16 #include <asm/setup.h>
17
18 static struct resource system_rom_resource = {
19 .name = "System ROM",
20 .start = 0xf0000,
21 .end = 0xfffff,
22 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
23 };
24
25 static struct resource extension_rom_resource = {
26 .name = "Extension ROM",
27 .start = 0xe0000,
28 .end = 0xeffff,
29 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
30 };
31
32 static struct resource adapter_rom_resources[] = { {
33 .name = "Adapter ROM",
34 .start = 0xc8000,
35 .end = 0,
36 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
37 }, {
38 .name = "Adapter ROM",
39 .start = 0,
40 .end = 0,
41 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
42 }, {
43 .name = "Adapter ROM",
44 .start = 0,
45 .end = 0,
46 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
47 }, {
48 .name = "Adapter ROM",
49 .start = 0,
50 .end = 0,
51 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
52 }, {
53 .name = "Adapter ROM",
54 .start = 0,
55 .end = 0,
56 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
57 }, {
58 .name = "Adapter ROM",
59 .start = 0,
60 .end = 0,
61 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
62 } };
63
64 static struct resource video_rom_resource = {
65 .name = "Video ROM",
66 .start = 0xc0000,
67 .end = 0xc7fff,
68 .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM
69 };
70
71 #define ROMSIGNATURE 0xaa55
72
73 static int __init romsignature(const unsigned char *rom)
74 {
75 const unsigned short * const ptr = (const unsigned short *)rom;
76 unsigned short sig;
77
78 return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;
79 }
80
81 static int __init romchecksum(const unsigned char *rom, unsigned long length)
82 {
83 unsigned char sum, c;
84
85 for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)
86 sum += c;
87 return !length && !sum;
88 }
89
90 static void __init probe_roms(void)
91 {
92 const unsigned char *rom;
93 unsigned long start, length, upper;
94 unsigned char c;
95 int i;
96
97 /* video rom */
98 upper = adapter_rom_resources[0].start;
99 for (start = video_rom_resource.start; start < upper; start += 2048) {
100 rom = isa_bus_to_virt(start);
101 if (!romsignature(rom))
102 continue;
103
104 video_rom_resource.start = start;
105
106 if (probe_kernel_address(rom + 2, c) != 0)
107 continue;
108
109 /* 0 < length <= 0x7f * 512, historically */
110 length = c * 512;
111
112 /* if checksum okay, trust length byte */
113 if (length && romchecksum(rom, length))
114 video_rom_resource.end = start + length - 1;
115
116 request_resource(&iomem_resource, &video_rom_resource);
117 break;
118 }
119
120 start = (video_rom_resource.end + 1 + 2047) & ~2047UL;
121 if (start < upper)
122 start = upper;
123
124 /* system rom */
125 request_resource(&iomem_resource, &system_rom_resource);
126 upper = system_rom_resource.start;
127
128 /* check for extension rom (ignore length byte!) */
129 rom = isa_bus_to_virt(extension_rom_resource.start);
130 if (romsignature(rom)) {
131 length = extension_rom_resource.end - extension_rom_resource.start + 1;
132 if (romchecksum(rom, length)) {
133 request_resource(&iomem_resource, &extension_rom_resource);
134 upper = extension_rom_resource.start;
135 }
136 }
137
138 /* check for adapter roms on 2k boundaries */
139 for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {
140 rom = isa_bus_to_virt(start);
141 if (!romsignature(rom))
142 continue;
143
144 if (probe_kernel_address(rom + 2, c) != 0)
145 continue;
146
147 /* 0 < length <= 0x7f * 512, historically */
148 length = c * 512;
149
150 /* but accept any length that fits if checksum okay */
151 if (!length || start + length > upper || !romchecksum(rom, length))
152 continue;
153
154 adapter_rom_resources[i].start = start;
155 adapter_rom_resources[i].end = start + length - 1;
156 request_resource(&iomem_resource, &adapter_rom_resources[i]);
157
158 start = adapter_rom_resources[i++].end & ~2047UL;
159 }
160 }
161
162 /*
163 * Request address space for all standard RAM and ROM resources
164 * and also for regions reported as reserved by the e820.
165 */
166 void __init init_iomem_resources(struct resource *code_resource,
167 struct resource *data_resource,
168 struct resource *bss_resource)
169 {
170 int i;
171
172 probe_roms();
173 for (i = 0; i < e820.nr_map; i++) {
174 struct resource *res;
175 #ifndef CONFIG_RESOURCES_64BIT
176 if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
177 continue;
178 #endif
179 res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
180 switch (e820.map[i].type) {
181 case E820_RAM: res->name = "System RAM"; break;
182 case E820_ACPI: res->name = "ACPI Tables"; break;
183 case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
184 default: res->name = "reserved";
185 }
186 res->start = e820.map[i].addr;
187 res->end = res->start + e820.map[i].size - 1;
188 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
189 if (request_resource(&iomem_resource, res)) {
190 kfree(res);
191 continue;
192 }
193 if (e820.map[i].type == E820_RAM) {
194 /*
195 * We don't know which RAM region contains kernel data,
196 * so we try it repeatedly and let the resource manager
197 * test it.
198 */
199 request_resource(res, code_resource);
200 request_resource(res, data_resource);
201 request_resource(res, bss_resource);
202 #ifdef CONFIG_KEXEC
203 if (crashk_res.start != crashk_res.end)
204 request_resource(res, &crashk_res);
205 #endif
206 }
207 }
208 }
209
210 /*
211 * Find the highest page frame number we have available
212 */
213 void __init propagate_e820_map(void)
214 {
215 int i;
216
217 max_pfn = 0;
218
219 for (i = 0; i < e820.nr_map; i++) {
220 unsigned long start, end;
221 /* RAM? */
222 if (e820.map[i].type != E820_RAM)
223 continue;
224 start = PFN_UP(e820.map[i].addr);
225 end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
226 if (start >= end)
227 continue;
228 if (end > max_pfn)
229 max_pfn = end;
230 memory_present(0, start, end);
231 }
232 }
233
234 /*
235 * Register fully available low RAM pages with the bootmem allocator.
236 */
237 void __init register_bootmem_low_pages(unsigned long max_low_pfn)
238 {
239 int i;
240
241 for (i = 0; i < e820.nr_map; i++) {
242 unsigned long curr_pfn, last_pfn, size;
243 /*
244 * Reserve usable low memory
245 */
246 if (e820.map[i].type != E820_RAM)
247 continue;
248 /*
249 * We are rounding up the start address of usable memory:
250 */
251 curr_pfn = PFN_UP(e820.map[i].addr);
252 if (curr_pfn >= max_low_pfn)
253 continue;
254 /*
255 * ... and at the end of the usable range downwards:
256 */
257 last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
258
259 if (last_pfn > max_low_pfn)
260 last_pfn = max_low_pfn;
261
262 /*
263 * .. finally, did all the rounding and playing
264 * around just make the area go away?
265 */
266 if (last_pfn <= curr_pfn)
267 continue;
268
269 size = last_pfn - curr_pfn;
270 free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
271 }
272 }
273
274 void __init limit_regions(unsigned long long size)
275 {
276 unsigned long long current_addr;
277 int i;
278
279 e820_print_map("limit_regions start");
280 for (i = 0; i < e820.nr_map; i++) {
281 current_addr = e820.map[i].addr + e820.map[i].size;
282 if (current_addr < size)
283 continue;
284
285 if (e820.map[i].type != E820_RAM)
286 continue;
287
288 if (e820.map[i].addr >= size) {
289 /*
290 * This region starts past the end of the
291 * requested size, skip it completely.
292 */
293 e820.nr_map = i;
294 } else {
295 e820.nr_map = i + 1;
296 e820.map[i].size -= current_addr - size;
297 }
298 e820_print_map("limit_regions endfor");
299 return;
300 }
301 e820_print_map("limit_regions endfunc");
302 }
303
304 /* Overridden in paravirt.c if CONFIG_PARAVIRT */
305 char * __init __attribute__((weak)) memory_setup(void)
306 {
307 return machine_specific_memory_setup();
308 }
309
310 void __init setup_memory_map(void)
311 {
312 printk(KERN_INFO "BIOS-provided physical RAM map:\n");
313 e820_print_map(memory_setup());
314 }
315
316 static int __initdata user_defined_memmap;
317
318 /*
319 * "mem=nopentium" disables the 4MB page tables.
320 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
321 * to <mem>, overriding the bios size.
322 * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
323 * <start> to <start>+<mem>, overriding the bios size.
324 *
325 * HPA tells me bootloaders need to parse mem=, so no new
326 * option should be mem= [also see Documentation/i386/boot.txt]
327 */
328 static int __init parse_mem(char *arg)
329 {
330 if (!arg)
331 return -EINVAL;
332
333 if (strcmp(arg, "nopentium") == 0) {
334 setup_clear_cpu_cap(X86_FEATURE_PSE);
335 } else {
336 /* If the user specifies memory size, we
337 * limit the BIOS-provided memory map to
338 * that size. exactmap can be used to specify
339 * the exact map. mem=number can be used to
340 * trim the existing memory map.
341 */
342 unsigned long long mem_size;
343
344 mem_size = memparse(arg, &arg);
345 limit_regions(mem_size);
346 user_defined_memmap = 1;
347 }
348 return 0;
349 }
350 early_param("mem", parse_mem);
351
352 static int __init parse_memmap(char *arg)
353 {
354 if (!arg)
355 return -EINVAL;
356
357 if (strcmp(arg, "exactmap") == 0) {
358 #ifdef CONFIG_CRASH_DUMP
359 /* If we are doing a crash dump, we
360 * still need to know the real mem
361 * size before original memory map is
362 * reset.
363 */
364 propagate_e820_map();
365 saved_max_pfn = max_pfn;
366 #endif
367 e820.nr_map = 0;
368 user_defined_memmap = 1;
369 } else {
370 /* If the user specifies memory size, we
371 * limit the BIOS-provided memory map to
372 * that size. exactmap can be used to specify
373 * the exact map. mem=number can be used to
374 * trim the existing memory map.
375 */
376 unsigned long long start_at, mem_size;
377
378 mem_size = memparse(arg, &arg);
379 if (*arg == '@') {
380 start_at = memparse(arg+1, &arg);
381 add_memory_region(start_at, mem_size, E820_RAM);
382 } else if (*arg == '#') {
383 start_at = memparse(arg+1, &arg);
384 add_memory_region(start_at, mem_size, E820_ACPI);
385 } else if (*arg == '$') {
386 start_at = memparse(arg+1, &arg);
387 add_memory_region(start_at, mem_size, E820_RESERVED);
388 } else {
389 limit_regions(mem_size);
390 user_defined_memmap = 1;
391 }
392 }
393 return 0;
394 }
395 early_param("memmap", parse_memmap);
396
397 void __init finish_e820_parsing(void)
398 {
399 if (user_defined_memmap) {
400 printk(KERN_INFO "user-defined physical RAM map:\n");
401 e820_print_map("user");
402 }
403 }
404
This page took 0.038366 seconds and 5 git commands to generate.