aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/mm/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/mm/init.c')
-rw-r--r--arch/x86_64/mm/init.c129
1 files changed, 79 insertions, 50 deletions
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index e60a1a848de8..286f6a624c3a 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -22,6 +22,7 @@
22#include <linux/pagemap.h> 22#include <linux/pagemap.h>
23#include <linux/bootmem.h> 23#include <linux/bootmem.h>
24#include <linux/proc_fs.h> 24#include <linux/proc_fs.h>
25#include <linux/pci.h>
25 26
26#include <asm/processor.h> 27#include <asm/processor.h>
27#include <asm/system.h> 28#include <asm/system.h>
@@ -36,16 +37,13 @@
36#include <asm/mmu_context.h> 37#include <asm/mmu_context.h>
37#include <asm/proto.h> 38#include <asm/proto.h>
38#include <asm/smp.h> 39#include <asm/smp.h>
40#include <asm/sections.h>
39 41
40#ifndef Dprintk 42#ifndef Dprintk
41#define Dprintk(x...) 43#define Dprintk(x...)
42#endif 44#endif
43 45
44#ifdef CONFIG_GART_IOMMU 46static unsigned long dma_reserve __initdata;
45extern int swiotlb;
46#endif
47
48extern char _stext[];
49 47
50DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 48DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
51 49
@@ -86,9 +84,6 @@ void show_mem(void)
86 84
87/* References to section boundaries */ 85/* References to section boundaries */
88 86
89extern char _text, _etext, _edata, __bss_start, _end[];
90extern char __init_begin, __init_end;
91
92int after_bootmem; 87int after_bootmem;
93 88
94static void *spp_getpage(void) 89static void *spp_getpage(void)
@@ -308,42 +303,81 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
308 table_end<<PAGE_SHIFT); 303 table_end<<PAGE_SHIFT);
309} 304}
310 305
311extern struct x8664_pda cpu_pda[NR_CPUS]; 306void __cpuinit zap_low_mappings(int cpu)
307{
308 if (cpu == 0) {
309 pgd_t *pgd = pgd_offset_k(0UL);
310 pgd_clear(pgd);
311 } else {
312 /*
313 * For AP's, zap the low identity mappings by changing the cr3
314 * to init_level4_pgt and doing local flush tlb all
315 */
316 asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt)));
317 }
318 __flush_tlb_all();
319}
312 320
313/* Assumes all CPUs still execute in init_mm */ 321/* Compute zone sizes for the DMA and DMA32 zones in a node. */
314void zap_low_mappings(void) 322__init void
323size_zones(unsigned long *z, unsigned long *h,
324 unsigned long start_pfn, unsigned long end_pfn)
315{ 325{
316 pgd_t *pgd = pgd_offset_k(0UL); 326 int i;
317 pgd_clear(pgd); 327 unsigned long w;
318 flush_tlb_all(); 328
329 for (i = 0; i < MAX_NR_ZONES; i++)
330 z[i] = 0;
331
332 if (start_pfn < MAX_DMA_PFN)
333 z[ZONE_DMA] = MAX_DMA_PFN - start_pfn;
334 if (start_pfn < MAX_DMA32_PFN) {
335 unsigned long dma32_pfn = MAX_DMA32_PFN;
336 if (dma32_pfn > end_pfn)
337 dma32_pfn = end_pfn;
338 z[ZONE_DMA32] = dma32_pfn - start_pfn;
339 }
340 z[ZONE_NORMAL] = end_pfn - start_pfn;
341
342 /* Remove lower zones from higher ones. */
343 w = 0;
344 for (i = 0; i < MAX_NR_ZONES; i++) {
345 if (z[i])
346 z[i] -= w;
347 w += z[i];
348 }
349
350 /* Compute holes */
351 w = 0;
352 for (i = 0; i < MAX_NR_ZONES; i++) {
353 unsigned long s = w;
354 w += z[i];
355 h[i] = e820_hole_size(s, w);
356 }
357
358 /* Add the space pace needed for mem_map to the holes too. */
359 for (i = 0; i < MAX_NR_ZONES; i++)
360 h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE;
361
362 /* The 16MB DMA zone has the kernel and other misc mappings.
363 Account them too */
364 if (h[ZONE_DMA]) {
365 h[ZONE_DMA] += dma_reserve;
366 if (h[ZONE_DMA] >= z[ZONE_DMA]) {
367 printk(KERN_WARNING
368 "Kernel too large and filling up ZONE_DMA?\n");
369 h[ZONE_DMA] = z[ZONE_DMA];
370 }
371 }
319} 372}
320 373
321#ifndef CONFIG_NUMA 374#ifndef CONFIG_NUMA
322void __init paging_init(void) 375void __init paging_init(void)
323{ 376{
324 { 377 unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
325 unsigned long zones_size[MAX_NR_ZONES]; 378 size_zones(zones, holes, 0, end_pfn);
326 unsigned long holes[MAX_NR_ZONES]; 379 free_area_init_node(0, NODE_DATA(0), zones,
327 unsigned int max_dma; 380 __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
328
329 memset(zones_size, 0, sizeof(zones_size));
330 memset(holes, 0, sizeof(holes));
331
332 max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
333
334 if (end_pfn < max_dma) {
335 zones_size[ZONE_DMA] = end_pfn;
336 holes[ZONE_DMA] = e820_hole_size(0, end_pfn);
337 } else {
338 zones_size[ZONE_DMA] = max_dma;
339 holes[ZONE_DMA] = e820_hole_size(0, max_dma);
340 zones_size[ZONE_NORMAL] = end_pfn - max_dma;
341 holes[ZONE_NORMAL] = e820_hole_size(max_dma, end_pfn);
342 }
343 free_area_init_node(0, NODE_DATA(0), zones_size,
344 __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
345 }
346 return;
347} 381}
348#endif 382#endif
349 383
@@ -438,19 +472,16 @@ void __init mem_init(void)
438 datasize >> 10, 472 datasize >> 10,
439 initsize >> 10); 473 initsize >> 10);
440 474
475#ifdef CONFIG_SMP
441 /* 476 /*
442 * Subtle. SMP is doing its boot stuff late (because it has to 477 * Sync boot_level4_pgt mappings with the init_level4_pgt
443 * fork idle threads) - but it also needs low mappings for the 478 * except for the low identity mappings which are already zapped
444 * protected-mode entry to work. We zap these entries only after 479 * in init_level4_pgt. This sync-up is essential for AP's bringup
445 * the WP-bit has been tested.
446 */ 480 */
447#ifndef CONFIG_SMP 481 memcpy(boot_level4_pgt+1, init_level4_pgt+1, (PTRS_PER_PGD-1)*sizeof(pgd_t));
448 zap_low_mappings();
449#endif 482#endif
450} 483}
451 484
452extern char __initdata_begin[], __initdata_end[];
453
454void free_initmem(void) 485void free_initmem(void)
455{ 486{
456 unsigned long addr; 487 unsigned long addr;
@@ -464,7 +495,7 @@ void free_initmem(void)
464 totalram_pages++; 495 totalram_pages++;
465 } 496 }
466 memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin); 497 memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin);
467 printk ("Freeing unused kernel memory: %luk freed\n", (&__init_end - &__init_begin) >> 10); 498 printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10);
468} 499}
469 500
470#ifdef CONFIG_BLK_DEV_INITRD 501#ifdef CONFIG_BLK_DEV_INITRD
@@ -491,6 +522,8 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
491#else 522#else
492 reserve_bootmem(phys, len); 523 reserve_bootmem(phys, len);
493#endif 524#endif
525 if (phys+len <= MAX_DMA_PFN*PAGE_SIZE)
526 dma_reserve += len / PAGE_SIZE;
494} 527}
495 528
496int kern_addr_valid(unsigned long addr) 529int kern_addr_valid(unsigned long addr)
@@ -532,10 +565,6 @@ extern int exception_trace, page_fault_trace;
532static ctl_table debug_table2[] = { 565static ctl_table debug_table2[] = {
533 { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL, 566 { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL,
534 proc_dointvec }, 567 proc_dointvec },
535#ifdef CONFIG_CHECKING
536 { 100, "page-fault-trace", &page_fault_trace, sizeof(int), 0644, NULL,
537 proc_dointvec },
538#endif
539 { 0, } 568 { 0, }
540}; 569};
541 570