Skip to content

Commit

Permalink
[PATCH] ppc64: Fix huge pages MMU mapping bug
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Herrenschmidt authored and Linus Torvalds committed Sep 23, 2005
1 parent 2601c2e commit 67b1081
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 5 deletions.
5 changes: 2 additions & 3 deletions arch/ppc64/mm/hash_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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
Expand Down
7 changes: 5 additions & 2 deletions arch/ppc64/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,10 +710,13 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
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;
Expand Down

0 comments on commit 67b1081

Please sign in to comment.