aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-30 11:10:12 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-04-30 11:10:12 -0400
commit24a77daf3d80bddcece044e6dc3675e427eef3f3 (patch)
tree2c5e0b0bea394d6fe62c5d5857c252e83e48ac48 /arch/powerpc/mm
parente389f9aec689209724105ae80a6c91fd2e747bc9 (diff)
parentf900e9777fc9b65140cb9570438597bc8fae56ab (diff)
Merge branch 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'for-2.6.22' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (255 commits) [POWERPC] Remove dev_dbg redefinition in drivers/ps3/vuart.c [POWERPC] remove kernel module option for booke wdt [POWERPC] Avoid putting cpu node twice [POWERPC] Spinlock initializer cleanup [POWERPC] ppc4xx_sgdma needs dma-mapping.h [POWERPC] arch/powerpc/sysdev/timer.c build fix [POWERPC] get_property cleanups [POWERPC] Remove the unused HTDMSOUND driver [POWERPC] cell: cbe_cpufreq cleanup and crash fix [POWERPC] Declare enable_kernel_spe in a header [POWERPC] Add dt_xlate_addr() to bootwrapper [POWERPC] bootwrapper: CONFIG_ -> CONFIG_DEVICE_TREE [POWERPC] Don't define a custom bd_t for Xilixn Virtex based boards. [POWERPC] Add sane defaults for Xilinx EDK generated xparameters files [POWERPC] Add uartlite boot console driver for the zImage wrapper [POWERPC] Stop using ppc_sys for Xilinx Virtex boards [POWERPC] New registration for common Xilinx Virtex ppc405 platform devices [POWERPC] Merge common virtex header files [POWERPC] Rework Kconfig dependancies for Xilinx Virtex ppc405 platform [POWERPC] Clean up cpufreq Kconfig dependencies ...
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/hash_low_32.S22
-rw-r--r--arch/powerpc/mm/hash_low_64.S5
-rw-r--r--arch/powerpc/mm/hash_native_64.c2
-rw-r--r--arch/powerpc/mm/hash_utils_64.c127
-rw-r--r--arch/powerpc/mm/hugetlbpage.c16
-rw-r--r--arch/powerpc/mm/init_32.c4
-rw-r--r--arch/powerpc/mm/lmb.c4
-rw-r--r--arch/powerpc/mm/mem.c3
-rw-r--r--arch/powerpc/mm/mmu_decl.h5
-rw-r--r--arch/powerpc/mm/numa.c24
-rw-r--r--arch/powerpc/mm/pgtable_32.c76
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c4
-rw-r--r--arch/powerpc/mm/tlb_64.c68
13 files changed, 279 insertions, 81 deletions
diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S
index bd68df5fa78a..ddceefc06ecc 100644
--- a/arch/powerpc/mm/hash_low_32.S
+++ b/arch/powerpc/mm/hash_low_32.S
@@ -283,6 +283,7 @@ Hash_msk = (((1 << Hash_bits) - 1) * 64)
283#define PTEG_SIZE 64 283#define PTEG_SIZE 64
284#define LG_PTEG_SIZE 6 284#define LG_PTEG_SIZE 6
285#define LDPTEu lwzu 285#define LDPTEu lwzu
286#define LDPTE lwz
286#define STPTE stw 287#define STPTE stw
287#define CMPPTE cmpw 288#define CMPPTE cmpw
288#define PTE_H 0x40 289#define PTE_H 0x40
@@ -389,13 +390,30 @@ _GLOBAL(hash_page_patch_C)
389 * and we know there is a definite (although small) speed 390 * and we know there is a definite (although small) speed
390 * advantage to putting the PTE in the primary PTEG, we always 391 * advantage to putting the PTE in the primary PTEG, we always
391 * put the PTE in the primary PTEG. 392 * put the PTE in the primary PTEG.
393 *
394 * In addition, we skip any slot that is mapping kernel text in
395 * order to avoid a deadlock when not using BAT mappings if
396 * trying to hash in the kernel hash code itself after it has
397 * already taken the hash table lock. This works in conjunction
398 * with pre-faulting of the kernel text.
399 *
400 * If the hash table bucket is full of kernel text entries, we'll
401 * lockup here but that shouldn't happen
392 */ 402 */
393 addis r4,r7,next_slot@ha 403
4041: addis r4,r7,next_slot@ha /* get next evict slot */
394 lwz r6,next_slot@l(r4) 405 lwz r6,next_slot@l(r4)
395 addi r6,r6,PTE_SIZE 406 addi r6,r6,PTE_SIZE /* search for candidate */
396 andi. r6,r6,7*PTE_SIZE 407 andi. r6,r6,7*PTE_SIZE
397 stw r6,next_slot@l(r4) 408 stw r6,next_slot@l(r4)
398 add r4,r3,r6 409 add r4,r3,r6
410 LDPTE r0,PTE_SIZE/2(r4) /* get PTE second word */
411 clrrwi r0,r0,12
412 lis r6,etext@h
413 ori r6,r6,etext@l /* get etext */
414 tophys(r6,r6)
415 cmpl cr0,r0,r6 /* compare and try again */
416 blt 1b
399 417
400#ifndef CONFIG_SMP 418#ifndef CONFIG_SMP
401 /* Store PTE in PTEG */ 419 /* Store PTE in PTEG */
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index 9bc0a9c2b9bc..e64ce3eec36e 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -445,9 +445,12 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
445 445
446htab_insert_pte: 446htab_insert_pte:
447 /* real page number in r5, PTE RPN value + index */ 447 /* real page number in r5, PTE RPN value + index */
448 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT 448 andis. r0,r31,_PAGE_4K_PFN@h
449 srdi r5,r31,PTE_RPN_SHIFT
450 bne- htab_special_pfn
449 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT 451 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
450 add r5,r5,r25 452 add r5,r5,r25
453htab_special_pfn:
451 sldi r5,r5,HW_PAGE_SHIFT 454 sldi r5,r5,HW_PAGE_SHIFT
452 455
453 /* Calculate primary group hash */ 456 /* Calculate primary group hash */
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 6f1016acdbf6..79aedaf36f2b 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -505,7 +505,7 @@ static inline int tlb_batching_enabled(void)
505 int enabled = 1; 505 int enabled = 1;
506 506
507 if (root) { 507 if (root) {
508 const char *model = get_property(root, "model", NULL); 508 const char *model = of_get_property(root, "model", NULL);
509 if (model && !strcmp(model, "IBM,9076-N81")) 509 if (model && !strcmp(model, "IBM,9076-N81"))
510 enabled = 0; 510 enabled = 0;
511 of_node_put(root); 511 of_node_put(root);
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 3c7fe2c65b5a..49618461defb 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -100,6 +100,11 @@ unsigned int HPAGE_SHIFT;
100#ifdef CONFIG_PPC_64K_PAGES 100#ifdef CONFIG_PPC_64K_PAGES
101int mmu_ci_restrictions; 101int mmu_ci_restrictions;
102#endif 102#endif
103#ifdef CONFIG_DEBUG_PAGEALLOC
104static u8 *linear_map_hash_slots;
105static unsigned long linear_map_hash_count;
106static spinlock_t linear_map_hash_lock;
107#endif /* CONFIG_DEBUG_PAGEALLOC */
103 108
104/* There are definitions of page sizes arrays to be used when none 109/* There are definitions of page sizes arrays to be used when none
105 * is provided by the firmware. 110 * is provided by the firmware.
@@ -152,11 +157,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
152 157
153 for (vaddr = vstart, paddr = pstart; vaddr < vend; 158 for (vaddr = vstart, paddr = pstart; vaddr < vend;
154 vaddr += step, paddr += step) { 159 vaddr += step, paddr += step) {
155 unsigned long vpn, hash, hpteg; 160 unsigned long hash, hpteg;
156 unsigned long vsid = get_kernel_vsid(vaddr); 161 unsigned long vsid = get_kernel_vsid(vaddr);
157 unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff); 162 unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff);
158 163
159 vpn = va >> shift;
160 tmp_mode = mode; 164 tmp_mode = mode;
161 165
162 /* Make non-kernel text non-executable */ 166 /* Make non-kernel text non-executable */
@@ -174,6 +178,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
174 178
175 if (ret < 0) 179 if (ret < 0)
176 break; 180 break;
181#ifdef CONFIG_DEBUG_PAGEALLOC
182 if ((paddr >> PAGE_SHIFT) < linear_map_hash_count)
183 linear_map_hash_slots[paddr >> PAGE_SHIFT] = ret | 0x80;
184#endif /* CONFIG_DEBUG_PAGEALLOC */
177 } 185 }
178 return ret < 0 ? ret : 0; 186 return ret < 0 ? ret : 0;
179} 187}
@@ -281,6 +289,7 @@ static void __init htab_init_page_sizes(void)
281 memcpy(mmu_psize_defs, mmu_psize_defaults_gp, 289 memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
282 sizeof(mmu_psize_defaults_gp)); 290 sizeof(mmu_psize_defaults_gp));
283 found: 291 found:
292#ifndef CONFIG_DEBUG_PAGEALLOC
284 /* 293 /*
285 * Pick a size for the linear mapping. Currently, we only support 294 * Pick a size for the linear mapping. Currently, we only support
286 * 16M, 1M and 4K which is the default 295 * 16M, 1M and 4K which is the default
@@ -289,6 +298,7 @@ static void __init htab_init_page_sizes(void)
289 mmu_linear_psize = MMU_PAGE_16M; 298 mmu_linear_psize = MMU_PAGE_16M;
290 else if (mmu_psize_defs[MMU_PAGE_1M].shift) 299 else if (mmu_psize_defs[MMU_PAGE_1M].shift)
291 mmu_linear_psize = MMU_PAGE_1M; 300 mmu_linear_psize = MMU_PAGE_1M;
301#endif /* CONFIG_DEBUG_PAGEALLOC */
292 302
293#ifdef CONFIG_PPC_64K_PAGES 303#ifdef CONFIG_PPC_64K_PAGES
294 /* 304 /*
@@ -303,12 +313,14 @@ static void __init htab_init_page_sizes(void)
303 if (mmu_psize_defs[MMU_PAGE_64K].shift) { 313 if (mmu_psize_defs[MMU_PAGE_64K].shift) {
304 mmu_virtual_psize = MMU_PAGE_64K; 314 mmu_virtual_psize = MMU_PAGE_64K;
305 mmu_vmalloc_psize = MMU_PAGE_64K; 315 mmu_vmalloc_psize = MMU_PAGE_64K;
316 if (mmu_linear_psize == MMU_PAGE_4K)
317 mmu_linear_psize = MMU_PAGE_64K;
306 if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE)) 318 if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
307 mmu_io_psize = MMU_PAGE_64K; 319 mmu_io_psize = MMU_PAGE_64K;
308 else 320 else
309 mmu_ci_restrictions = 1; 321 mmu_ci_restrictions = 1;
310 } 322 }
311#endif 323#endif /* CONFIG_PPC_64K_PAGES */
312 324
313 printk(KERN_DEBUG "Page orders: linear mapping = %d, " 325 printk(KERN_DEBUG "Page orders: linear mapping = %d, "
314 "virtual = %d, io = %d\n", 326 "virtual = %d, io = %d\n",
@@ -476,6 +488,13 @@ void __init htab_initialize(void)
476 488
477 mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; 489 mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
478 490
491#ifdef CONFIG_DEBUG_PAGEALLOC
492 linear_map_hash_count = lmb_end_of_DRAM() >> PAGE_SHIFT;
493 linear_map_hash_slots = __va(lmb_alloc_base(linear_map_hash_count,
494 1, lmb.rmo_size));
495 memset(linear_map_hash_slots, 0, linear_map_hash_count);
496#endif /* CONFIG_DEBUG_PAGEALLOC */
497
479 /* On U3 based machines, we need to reserve the DART area and 498 /* On U3 based machines, we need to reserve the DART area and
480 * _NOT_ map it to avoid cache paradoxes as it's remapped non 499 * _NOT_ map it to avoid cache paradoxes as it's remapped non
481 * cacheable later on 500 * cacheable later on
@@ -573,6 +592,27 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
573 return pp; 592 return pp;
574} 593}
575 594
595/*
596 * Demote a segment to using 4k pages.
597 * For now this makes the whole process use 4k pages.
598 */
599void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
600{
601#ifdef CONFIG_PPC_64K_PAGES
602 if (mm->context.user_psize == MMU_PAGE_4K)
603 return;
604 mm->context.user_psize = MMU_PAGE_4K;
605 mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp;
606 get_paca()->context = mm->context;
607 slb_flush_and_rebolt();
608#ifdef CONFIG_SPE_BASE
609 spu_flush_all_slbs(mm);
610#endif
611#endif
612}
613
614EXPORT_SYMBOL_GPL(demote_segment_4k);
615
576/* Result code is: 616/* Result code is:
577 * 0 - handled 617 * 0 - handled
578 * 1 - normal page fault 618 * 1 - normal page fault
@@ -665,15 +705,19 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
665#ifndef CONFIG_PPC_64K_PAGES 705#ifndef CONFIG_PPC_64K_PAGES
666 rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); 706 rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
667#else 707#else
708 /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */
709 if (pte_val(*ptep) & _PAGE_4K_PFN) {
710 demote_segment_4k(mm, ea);
711 psize = MMU_PAGE_4K;
712 }
713
668 if (mmu_ci_restrictions) { 714 if (mmu_ci_restrictions) {
669 /* If this PTE is non-cacheable, switch to 4k */ 715 /* If this PTE is non-cacheable, switch to 4k */
670 if (psize == MMU_PAGE_64K && 716 if (psize == MMU_PAGE_64K &&
671 (pte_val(*ptep) & _PAGE_NO_CACHE)) { 717 (pte_val(*ptep) & _PAGE_NO_CACHE)) {
672 if (user_region) { 718 if (user_region) {
719 demote_segment_4k(mm, ea);
673 psize = MMU_PAGE_4K; 720 psize = MMU_PAGE_4K;
674 mm->context.user_psize = MMU_PAGE_4K;
675 mm->context.sllp = SLB_VSID_USER |
676 mmu_psize_defs[MMU_PAGE_4K].sllp;
677 } else if (ea < VMALLOC_END) { 721 } else if (ea < VMALLOC_END) {
678 /* 722 /*
679 * some driver did a non-cacheable mapping 723 * some driver did a non-cacheable mapping
@@ -756,16 +800,8 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
756 if (mmu_ci_restrictions) { 800 if (mmu_ci_restrictions) {
757 /* If this PTE is non-cacheable, switch to 4k */ 801 /* If this PTE is non-cacheable, switch to 4k */
758 if (mm->context.user_psize == MMU_PAGE_64K && 802 if (mm->context.user_psize == MMU_PAGE_64K &&
759 (pte_val(*ptep) & _PAGE_NO_CACHE)) { 803 (pte_val(*ptep) & _PAGE_NO_CACHE))
760 mm->context.user_psize = MMU_PAGE_4K; 804 demote_segment_4k(mm, ea);
761 mm->context.sllp = SLB_VSID_USER |
762 mmu_psize_defs[MMU_PAGE_4K].sllp;
763 get_paca()->context = mm->context;
764 slb_flush_and_rebolt();
765#ifdef CONFIG_SPE_BASE
766 spu_flush_all_slbs(mm);
767#endif
768 }
769 } 805 }
770 if (mm->context.user_psize == MMU_PAGE_64K) 806 if (mm->context.user_psize == MMU_PAGE_64K)
771 __hash_page_64K(ea, access, vsid, ptep, trap, local); 807 __hash_page_64K(ea, access, vsid, ptep, trap, local);
@@ -825,3 +861,62 @@ void low_hash_fault(struct pt_regs *regs, unsigned long address)
825 } 861 }
826 bad_page_fault(regs, address, SIGBUS); 862 bad_page_fault(regs, address, SIGBUS);
827} 863}
864
865#ifdef CONFIG_DEBUG_PAGEALLOC
866static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
867{
868 unsigned long hash, hpteg, vsid = get_kernel_vsid(vaddr);
869 unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff);
870 unsigned long mode = _PAGE_ACCESSED | _PAGE_DIRTY |
871 _PAGE_COHERENT | PP_RWXX | HPTE_R_N;
872 int ret;
873
874 hash = hpt_hash(va, PAGE_SHIFT);
875 hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
876
877 ret = ppc_md.hpte_insert(hpteg, va, __pa(vaddr),
878 mode, HPTE_V_BOLTED, mmu_linear_psize);
879 BUG_ON (ret < 0);
880 spin_lock(&linear_map_hash_lock);
881 BUG_ON(linear_map_hash_slots[lmi] & 0x80);
882 linear_map_hash_slots[lmi] = ret | 0x80;
883 spin_unlock(&linear_map_hash_lock);
884}
885
886static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
887{
888 unsigned long hash, hidx, slot, vsid = get_kernel_vsid(vaddr);
889 unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff);
890
891 hash = hpt_hash(va, PAGE_SHIFT);
892 spin_lock(&linear_map_hash_lock);
893 BUG_ON(!(linear_map_hash_slots[lmi] & 0x80));
894 hidx = linear_map_hash_slots[lmi] & 0x7f;
895 linear_map_hash_slots[lmi] = 0;
896 spin_unlock(&linear_map_hash_lock);
897 if (hidx & _PTEIDX_SECONDARY)
898 hash = ~hash;
899 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
900 slot += hidx & _PTEIDX_GROUP_IX;
901 ppc_md.hpte_invalidate(slot, va, mmu_linear_psize, 0);
902}
903
904void kernel_map_pages(struct page *page, int numpages, int enable)
905{
906 unsigned long flags, vaddr, lmi;
907 int i;
908
909 local_irq_save(flags);
910 for (i = 0; i < numpages; i++, page++) {
911 vaddr = (unsigned long)page_address(page);
912 lmi = __pa(vaddr) >> PAGE_SHIFT;
913 if (lmi >= linear_map_hash_count)
914 continue;
915 if (enable)
916 kernel_map_linear_page(vaddr, lmi);
917 else
918 kernel_unmap_linear_page(vaddr, lmi);
919 }
920 local_irq_restore(flags);
921}
922#endif /* CONFIG_DEBUG_PAGEALLOC */
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index f6ffaaa7a5bf..8508f973d9cc 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -316,12 +316,11 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
316{ 316{
317 if (pte_present(*ptep)) { 317 if (pte_present(*ptep)) {
318 /* We open-code pte_clear because we need to pass the right 318 /* We open-code pte_clear because we need to pass the right
319 * argument to hpte_update (huge / !huge) 319 * argument to hpte_need_flush (huge / !huge). Might not be
320 * necessary anymore if we make hpte_need_flush() get the
321 * page size from the slices
320 */ 322 */
321 unsigned long old = pte_update(ptep, ~0UL); 323 pte_update(mm, addr & HPAGE_MASK, ptep, ~0UL, 1);
322 if (old & _PAGE_HASHPTE)
323 hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
324 flush_tlb_pending();
325 } 324 }
326 *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); 325 *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
327} 326}
@@ -329,12 +328,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
329pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, 328pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
330 pte_t *ptep) 329 pte_t *ptep)
331{ 330{
332 unsigned long old = pte_update(ptep, ~0UL); 331 unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1);
333
334 if (old & _PAGE_HASHPTE)
335 hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1);
336 *ptep = __pte(0);
337
338 return __pte(old); 332 return __pte(old);
339} 333}
340 334
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 0e53ca8f02fb..5fce6ccecb8d 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -115,6 +115,10 @@ void MMU_setup(void)
115 if (strstr(cmd_line, "noltlbs")) { 115 if (strstr(cmd_line, "noltlbs")) {
116 __map_without_ltlbs = 1; 116 __map_without_ltlbs = 1;
117 } 117 }
118#ifdef CONFIG_DEBUG_PAGEALLOC
119 __map_without_bats = 1;
120 __map_without_ltlbs = 1;
121#endif
118} 122}
119 123
120/* 124/*
diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
index 716a2906a24d..e3a1e8dc536a 100644
--- a/arch/powerpc/mm/lmb.c
+++ b/arch/powerpc/mm/lmb.c
@@ -146,6 +146,10 @@ static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
146 unsigned long rgnbase = rgn->region[i].base; 146 unsigned long rgnbase = rgn->region[i].base;
147 unsigned long rgnsize = rgn->region[i].size; 147 unsigned long rgnsize = rgn->region[i].size;
148 148
149 if ((rgnbase == base) && (rgnsize == size))
150 /* Already have this region, so we're done */
151 return 0;
152
149 adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); 153 adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
150 if ( adjacent > 0 ) { 154 if ( adjacent > 0 ) {
151 rgn->region[i].base -= size; 155 rgn->region[i].base -= size;
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 52f397c108a7..c4bcd7546424 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -58,9 +58,6 @@ int init_bootmem_done;
58int mem_init_done; 58int mem_init_done;
59unsigned long memory_limit; 59unsigned long memory_limit;
60 60
61extern void hash_preload(struct mm_struct *mm, unsigned long ea,
62 unsigned long access, unsigned long trap);
63
64int page_is_ram(unsigned long pfn) 61int page_is_ram(unsigned long pfn)
65{ 62{
66 unsigned long paddr = (pfn << PAGE_SHIFT); 63 unsigned long paddr = (pfn << PAGE_SHIFT);
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index bea2d21ac6f7..9c4538bb04b0 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -19,9 +19,14 @@
19 * 2 of the License, or (at your option) any later version. 19 * 2 of the License, or (at your option) any later version.
20 * 20 *
21 */ 21 */
22#include <linux/mm.h>
22#include <asm/tlbflush.h> 23#include <asm/tlbflush.h>
23#include <asm/mmu.h> 24#include <asm/mmu.h>
24 25
26extern void hash_preload(struct mm_struct *mm, unsigned long ea,
27 unsigned long access, unsigned long trap);
28
29
25#ifdef CONFIG_PPC32 30#ifdef CONFIG_PPC32
26extern void mapin_ram(void); 31extern void mapin_ram(void);
27extern int map_page(unsigned long va, phys_addr_t pa, int flags); 32extern int map_page(unsigned long va, phys_addr_t pa, int flags);
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e86c37c82cfd..b3a592b25ab3 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -74,7 +74,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
74 74
75 while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) { 75 while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) {
76 /* Try interrupt server first */ 76 /* Try interrupt server first */
77 interrupt_server = get_property(cpu_node, 77 interrupt_server = of_get_property(cpu_node,
78 "ibm,ppc-interrupt-server#s", &len); 78 "ibm,ppc-interrupt-server#s", &len);
79 79
80 len = len / sizeof(u32); 80 len = len / sizeof(u32);
@@ -85,7 +85,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
85 return cpu_node; 85 return cpu_node;
86 } 86 }
87 } else { 87 } else {
88 reg = get_property(cpu_node, "reg", &len); 88 reg = of_get_property(cpu_node, "reg", &len);
89 if (reg && (len > 0) && (reg[0] == hw_cpuid)) 89 if (reg && (len > 0) && (reg[0] == hw_cpuid))
90 return cpu_node; 90 return cpu_node;
91 } 91 }
@@ -97,7 +97,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
97/* must hold reference to node during call */ 97/* must hold reference to node during call */
98static const int *of_get_associativity(struct device_node *dev) 98static const int *of_get_associativity(struct device_node *dev)
99{ 99{
100 return get_property(dev, "ibm,associativity", NULL); 100 return of_get_property(dev, "ibm,associativity", NULL);
101} 101}
102 102
103/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa 103/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
@@ -179,7 +179,7 @@ static int __init find_min_common_depth(void)
179 * configuration (should be all 0's) and the second is for a normal 179 * configuration (should be all 0's) and the second is for a normal
180 * NUMA configuration. 180 * NUMA configuration.
181 */ 181 */
182 ref_points = get_property(rtas_root, 182 ref_points = of_get_property(rtas_root,
183 "ibm,associativity-reference-points", &len); 183 "ibm,associativity-reference-points", &len);
184 184
185 if ((len >= 1) && ref_points) { 185 if ((len >= 1) && ref_points) {
@@ -201,8 +201,8 @@ static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells)
201 if (!memory) 201 if (!memory)
202 panic("numa.c: No memory nodes found!"); 202 panic("numa.c: No memory nodes found!");
203 203
204 *n_addr_cells = prom_n_addr_cells(memory); 204 *n_addr_cells = of_n_addr_cells(memory);
205 *n_size_cells = prom_n_size_cells(memory); 205 *n_size_cells = of_n_size_cells(memory);
206 of_node_put(memory); 206 of_node_put(memory);
207} 207}
208 208
@@ -308,9 +308,9 @@ static void __init parse_drconf_memory(struct device_node *memory)
308 int nid, default_nid = 0; 308 int nid, default_nid = 0;
309 unsigned int start, ai, flags; 309 unsigned int start, ai, flags;
310 310
311 lm = get_property(memory, "ibm,lmb-size", &ls); 311 lm = of_get_property(memory, "ibm,lmb-size", &ls);
312 dm = get_property(memory, "ibm,dynamic-memory", &ld); 312 dm = of_get_property(memory, "ibm,dynamic-memory", &ld);
313 aa = get_property(memory, "ibm,associativity-lookup-arrays", &la); 313 aa = of_get_property(memory, "ibm,associativity-lookup-arrays", &la);
314 if (!lm || !dm || !aa || 314 if (!lm || !dm || !aa ||
315 ls < sizeof(unsigned int) || ld < sizeof(unsigned int) || 315 ls < sizeof(unsigned int) || ld < sizeof(unsigned int) ||
316 la < 2 * sizeof(unsigned int)) 316 la < 2 * sizeof(unsigned int))
@@ -404,10 +404,10 @@ static int __init parse_numa_properties(void)
404 const unsigned int *memcell_buf; 404 const unsigned int *memcell_buf;
405 unsigned int len; 405 unsigned int len;
406 406
407 memcell_buf = get_property(memory, 407 memcell_buf = of_get_property(memory,
408 "linux,usable-memory", &len); 408 "linux,usable-memory", &len);
409 if (!memcell_buf || len <= 0) 409 if (!memcell_buf || len <= 0)
410 memcell_buf = get_property(memory, "reg", &len); 410 memcell_buf = of_get_property(memory, "reg", &len);
411 if (!memcell_buf || len <= 0) 411 if (!memcell_buf || len <= 0)
412 continue; 412 continue;
413 413
@@ -725,7 +725,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
725 const unsigned int *memcell_buf; 725 const unsigned int *memcell_buf;
726 unsigned int len; 726 unsigned int len;
727 727
728 memcell_buf = get_property(memory, "reg", &len); 728 memcell_buf = of_get_property(memory, "reg", &len);
729 if (!memcell_buf || len <= 0) 729 if (!memcell_buf || len <= 0)
730 continue; 730 continue;
731 731
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index c284bdac9947..bca560374927 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -183,8 +183,8 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
183 * mem_init() sets high_memory so only do the check after that. 183 * mem_init() sets high_memory so only do the check after that.
184 */ 184 */
185 if (mem_init_done && (p < virt_to_phys(high_memory))) { 185 if (mem_init_done && (p < virt_to_phys(high_memory))) {
186 printk("__ioremap(): phys addr "PHYS_FMT" is RAM lr %p\n", p, 186 printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
187 __builtin_return_address(0)); 187 (unsigned long long)p, __builtin_return_address(0));
188 return NULL; 188 return NULL;
189 } 189 }
190 190
@@ -266,9 +266,12 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
266 pg = pte_alloc_kernel(pd, va); 266 pg = pte_alloc_kernel(pd, va);
267 if (pg != 0) { 267 if (pg != 0) {
268 err = 0; 268 err = 0;
269 set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); 269 /* The PTE should never be already set nor present in the
270 if (mem_init_done) 270 * hash table
271 flush_HPTE(0, va, pmd_val(*pd)); 271 */
272 BUG_ON(pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE));
273 set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT,
274 __pgprot(flags)));
272 } 275 }
273 return err; 276 return err;
274} 277}
@@ -279,16 +282,19 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
279void __init mapin_ram(void) 282void __init mapin_ram(void)
280{ 283{
281 unsigned long v, p, s, f; 284 unsigned long v, p, s, f;
285 int ktext;
282 286
283 s = mmu_mapin_ram(); 287 s = mmu_mapin_ram();
284 v = KERNELBASE + s; 288 v = KERNELBASE + s;
285 p = PPC_MEMSTART + s; 289 p = PPC_MEMSTART + s;
286 for (; s < total_lowmem; s += PAGE_SIZE) { 290 for (; s < total_lowmem; s += PAGE_SIZE) {
287 if ((char *) v >= _stext && (char *) v < etext) 291 ktext = ((char *) v >= _stext && (char *) v < etext);
288 f = _PAGE_RAM_TEXT; 292 f = ktext ?_PAGE_RAM_TEXT : _PAGE_RAM;
289 else
290 f = _PAGE_RAM;
291 map_page(v, p, f); 293 map_page(v, p, f);
294#ifdef CONFIG_PPC_STD_MMU_32
295 if (ktext)
296 hash_preload(&init_mm, v, 0, 0x300);
297#endif
292 v += PAGE_SIZE; 298 v += PAGE_SIZE;
293 p += PAGE_SIZE; 299 p += PAGE_SIZE;
294 } 300 }
@@ -445,3 +451,55 @@ exit:
445 return ret; 451 return ret;
446} 452}
447 453
454#ifdef CONFIG_DEBUG_PAGEALLOC
455
456static int __change_page_attr(struct page *page, pgprot_t prot)
457{
458 pte_t *kpte;
459 pmd_t *kpmd;
460 unsigned long address;
461
462 BUG_ON(PageHighMem(page));
463 address = (unsigned long)page_address(page);
464
465 if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address))
466 return 0;
467 if (!get_pteptr(&init_mm, address, &kpte, &kpmd))
468 return -EINVAL;
469 set_pte_at(&init_mm, address, kpte, mk_pte(page, prot));
470 wmb();
471 flush_HPTE(0, address, pmd_val(*kpmd));
472 pte_unmap(kpte);
473
474 return 0;
475}
476
477/*
478 * Change the page attributes of an page in the linear mapping.
479 *
480 * THIS CONFLICTS WITH BAT MAPPINGS, DEBUG USE ONLY
481 */
482static int change_page_attr(struct page *page, int numpages, pgprot_t prot)
483{
484 int i, err = 0;
485 unsigned long flags;
486
487 local_irq_save(flags);
488 for (i = 0; i < numpages; i++, page++) {
489 err = __change_page_attr(page, prot);
490 if (err)
491 break;
492 }
493 local_irq_restore(flags);
494 return err;
495}
496
497
498void kernel_map_pages(struct page *page, int numpages, int enable)
499{
500 if (PageHighMem(page))
501 return;
502
503 change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
504}
505#endif /* CONFIG_DEBUG_PAGEALLOC */
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 7cceb2c44cb9..05066674a7a0 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -85,8 +85,10 @@ unsigned long __init mmu_mapin_ram(void)
85 unsigned long max_size = (256<<20); 85 unsigned long max_size = (256<<20);
86 unsigned long align; 86 unsigned long align;
87 87
88 if (__map_without_bats) 88 if (__map_without_bats) {
89 printk(KERN_DEBUG "RAM mapped without BATs\n");
89 return 0; 90 return 0;
91 }
90 92
91 /* Set up BAT2 and if necessary BAT3 to cover RAM. */ 93 /* Set up BAT2 and if necessary BAT3 to cover RAM. */
92 94
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index b58baa65c4a7..fd8d08c325eb 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -120,17 +120,20 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
120} 120}
121 121
122/* 122/*
123 * Update the MMU hash table to correspond with a change to 123 * A linux PTE was changed and the corresponding hash table entry
124 * a Linux PTE. If wrprot is true, it is permissible to 124 * neesd to be flushed. This function will either perform the flush
125 * change the existing HPTE to read-only rather than removing it 125 * immediately or will batch it up if the current CPU has an active
126 * (if we remove it we should clear the _PTE_HPTEFLAGS bits). 126 * batch on it.
127 *
128 * Must be called from within some kind of spinlock/non-preempt region...
127 */ 129 */
128void hpte_update(struct mm_struct *mm, unsigned long addr, 130void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
129 pte_t *ptep, unsigned long pte, int huge) 131 pte_t *ptep, unsigned long pte, int huge)
130{ 132{
131 struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); 133 struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
132 unsigned long vsid; 134 unsigned long vsid, vaddr;
133 unsigned int psize; 135 unsigned int psize;
136 real_pte_t rpte;
134 int i; 137 int i;
135 138
136 i = batch->index; 139 i = batch->index;
@@ -151,6 +154,26 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
151 } else 154 } else
152 psize = pte_pagesize_index(pte); 155 psize = pte_pagesize_index(pte);
153 156
157 /* Build full vaddr */
158 if (!is_kernel_addr(addr)) {
159 vsid = get_vsid(mm->context.id, addr);
160 WARN_ON(vsid == 0);
161 } else
162 vsid = get_kernel_vsid(addr);
163 vaddr = (vsid << 28 ) | (addr & 0x0fffffff);
164 rpte = __real_pte(__pte(pte), ptep);
165
166 /*
167 * Check if we have an active batch on this CPU. If not, just
168 * flush now and return. For now, we don global invalidates
169 * in that case, might be worth testing the mm cpu mask though
170 * and decide to use local invalidates instead...
171 */
172 if (!batch->active) {
173 flush_hash_page(vaddr, rpte, psize, 0);
174 return;
175 }
176
154 /* 177 /*
155 * This can happen when we are in the middle of a TLB batch and 178 * This can happen when we are in the middle of a TLB batch and
156 * we encounter memory pressure (eg copy_page_range when it tries 179 * we encounter memory pressure (eg copy_page_range when it tries
@@ -162,47 +185,42 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
162 * batch 185 * batch
163 */ 186 */
164 if (i != 0 && (mm != batch->mm || batch->psize != psize)) { 187 if (i != 0 && (mm != batch->mm || batch->psize != psize)) {
165 flush_tlb_pending(); 188 __flush_tlb_pending(batch);
166 i = 0; 189 i = 0;
167 } 190 }
168 if (i == 0) { 191 if (i == 0) {
169 batch->mm = mm; 192 batch->mm = mm;
170 batch->psize = psize; 193 batch->psize = psize;
171 } 194 }
172 if (!is_kernel_addr(addr)) { 195 batch->pte[i] = rpte;
173 vsid = get_vsid(mm->context.id, addr); 196 batch->vaddr[i] = vaddr;
174 WARN_ON(vsid == 0);
175 } else
176 vsid = get_kernel_vsid(addr);
177 batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff);
178 batch->pte[i] = __real_pte(__pte(pte), ptep);
179 batch->index = ++i; 197 batch->index = ++i;
180 if (i >= PPC64_TLB_BATCH_NR) 198 if (i >= PPC64_TLB_BATCH_NR)
181 flush_tlb_pending(); 199 __flush_tlb_pending(batch);
182} 200}
183 201
202/*
203 * This function is called when terminating an mmu batch or when a batch
204 * is full. It will perform the flush of all the entries currently stored
205 * in a batch.
206 *
207 * Must be called from within some kind of spinlock/non-preempt region...
208 */
184void __flush_tlb_pending(struct ppc64_tlb_batch *batch) 209void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
185{ 210{
186 int i;
187 int cpu;
188 cpumask_t tmp; 211 cpumask_t tmp;
189 int local = 0; 212 int i, local = 0;
190 213
191 BUG_ON(in_interrupt());
192
193 cpu = get_cpu();
194 i = batch->index; 214 i = batch->index;
195 tmp = cpumask_of_cpu(cpu); 215 tmp = cpumask_of_cpu(smp_processor_id());
196 if (cpus_equal(batch->mm->cpu_vm_mask, tmp)) 216 if (cpus_equal(batch->mm->cpu_vm_mask, tmp))
197 local = 1; 217 local = 1;
198
199 if (i == 1) 218 if (i == 1)
200 flush_hash_page(batch->vaddr[0], batch->pte[0], 219 flush_hash_page(batch->vaddr[0], batch->pte[0],
201 batch->psize, local); 220 batch->psize, local);
202 else 221 else
203 flush_hash_range(i, local); 222 flush_hash_range(i, local);
204 batch->index = 0; 223 batch->index = 0;
205 put_cpu();
206} 224}
207 225
208void pte_free_finish(void) 226void pte_free_finish(void)