summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-09-23 13:24:07 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-23 13:35:36 -0700
commit67b108131df1230bad20a7279a8897de123d690b (patch)
treed9551fb8d2d610840e5538760ac5ba61c8c32c7e
parent2601c2e278863cd48c01bce1377b4c9747893025 (diff)
downloadlinux-67b108131df1230bad20a7279a8897de123d690b.tar.gz
linux-67b108131df1230bad20a7279a8897de123d690b.tar.bz2
linux-67b108131df1230bad20a7279a8897de123d690b.zip
[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>
-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,
hpte_t *hptep;
unsigned long hpte_v;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
-
- /* XXX fix for large ptes */
- unsigned long large = 0;
+ unsigned long large;
local_irq_save(flags);
@@ -358,6 +356,7 @@ static void native_flush_hash_range(unsigned long context,
va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
batch->vaddr[j] = va;
+ large = pte_huge(batch->pte[i]);
if (large)
vpn = va >> HPAGE_SHIFT;
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:
hpte_group = ((~hash & htab_hash_mask) *
HPTES_PER_GROUP) & ~0x7UL;
slot = ppc_md.hpte_insert(hpte_group, va, prpn,
- HPTE_V_LARGE, rflags);
+ HPTE_V_LARGE |
+ HPTE_V_SECONDARY,
+ rflags);
if (slot == -1) {
if (mftb() & 0x1)
- hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
+ hpte_group = ((hash & htab_hash_mask) *
+ HPTES_PER_GROUP)&~0x7UL;
ppc_md.hpte_remove(hpte_group);
goto repeat;