aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-09-23 16:24:07 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-23 16:35:36 -0400
commit67b108131df1230bad20a7279a8897de123d690b (patch)
treed9551fb8d2d610840e5538760ac5ba61c8c32c7e /arch/ppc64
parent2601c2e278863cd48c01bce1377b4c9747893025 (diff)
[PATCH] ppc64: Fix huge pages MMU mapping bug
Current kernel has a couple of sneaky bugs in the ppc64 hugetlb code that cause huge pages to be potentially left stale in the hash table and TLBs (improperly invalidated), with all the nasty consequences that can have. One is that we forgot to set the "secondary" bit in the hash PTEs when hashing a huge page in the secondary bucket (fortunately very rare). The other one is on non-LPAR machines (like Apple G5s), flush_hash_range() which is used to flush a batch of PTEs simply did not work for huge pages. Historically, our huge page code didn't batch, but this was changed without fixing this routine. This patch fixes both. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ppc64')
-rw-r--r--arch/ppc64/mm/hash_native.c5
-rw-r--r--arch/ppc64/mm/hugetlbpage.c7
2 files changed, 7 insertions, 5 deletions
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index 7626bb59954d..eb1bbb5b6c16 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -343,9 +343,7 @@ static void native_flush_hash_range(unsigned long context,
343 hpte_t *hptep; 343 hpte_t *hptep;
344 unsigned long hpte_v; 344 unsigned long hpte_v;
345 struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); 345 struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
346 346 unsigned long large;
347 /* XXX fix for large ptes */
348 unsigned long large = 0;
349 347
350 local_irq_save(flags); 348 local_irq_save(flags);
351 349
@@ -358,6 +356,7 @@ static void native_flush_hash_range(unsigned long context,
358 356
359 va = (vsid << 28) | (batch->addr[i] & 0x0fffffff); 357 va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
360 batch->vaddr[j] = va; 358 batch->vaddr[j] = va;
359 large = pte_huge(batch->pte[i]);
361 if (large) 360 if (large)
362 vpn = va >> HPAGE_SHIFT; 361 vpn = va >> HPAGE_SHIFT;
363 else 362 else
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index 338771ec70d7..0ea0994ed974 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -710,10 +710,13 @@ repeat:
710 hpte_group = ((~hash & htab_hash_mask) * 710 hpte_group = ((~hash & htab_hash_mask) *
711 HPTES_PER_GROUP) & ~0x7UL; 711 HPTES_PER_GROUP) & ~0x7UL;
712 slot = ppc_md.hpte_insert(hpte_group, va, prpn, 712 slot = ppc_md.hpte_insert(hpte_group, va, prpn,
713 HPTE_V_LARGE, rflags); 713 HPTE_V_LARGE |
714 HPTE_V_SECONDARY,
715 rflags);
714 if (slot == -1) { 716 if (slot == -1) {
715 if (mftb() & 0x1) 717 if (mftb() & 0x1)
716 hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; 718 hpte_group = ((hash & htab_hash_mask) *
719 HPTES_PER_GROUP)&~0x7UL;
717 720
718 ppc_md.hpte_remove(hpte_group); 721 ppc_md.hpte_remove(hpte_group);
719 goto repeat; 722 goto repeat;