]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] ppc64: hugepage hash flushing bugfix
authorDavid Gibson <david@gibson.dropbear.id.au>
Fri, 25 Feb 2005 00:48:33 +0000 (16:48 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 25 Feb 2005 00:48:33 +0000 (16:48 -0800)
This fixes a potentially bad (although very rarely triggered) bug in the
ppc64 hugepage code.

hpte_update() did not correctly calculate the address for hugepages, so
pte_clear() (which we use for hugepage ptes as well as normal ones)
would not correctly flush the hash page table entry.  Under the right
circumstances this could potentially lead to duplicate hash entries,
which is very bad.

davem's upcoming patch to pass the virtual address directly to set_pte()
and its ilk will obsolete this, but this is bad enough it should
probably be fixed in the meantime.

Signed-off-by: David Gibson <dwg@au1.ibm.com>
Acked-by: William Irwin <wli@holomorphy.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/ppc64/mm/tlb.c

index aa2d76ca46f25a46de64d95d934a41133d6c8b83..8495c7b5f860c1b5e762443857698dc2d3560909 100644 (file)
@@ -85,8 +85,12 @@ void hpte_update(pte_t *ptep, unsigned long pte, int wrprot)
 
        ptepage = virt_to_page(ptep);
        mm = (struct mm_struct *) ptepage->mapping;
-       addr = ptepage->index +
-               (((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE);
+       addr = ptepage->index;
+       if (pte_huge(pte))
+               addr +=  ((unsigned long)ptep & ~PAGE_MASK)
+                       / sizeof(*ptep) * HPAGE_SIZE;
+       else
+               addr += ((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE;
 
        if (REGION_ID(addr) == USER_REGION_ID)
                context = mm->context.id;