Some HW invert some PTE bits. In some case, __pte(0) is not 0 so the PTEs shall
be properly set prior to being used.

Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr>

---
 arch/powerpc/mm/pgtable_32.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index a349089..71a2821 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -96,6 +96,14 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 #endif
 }
 
+static inline void pte_alloc_clear(pte_t *pte)
+{
+       int i;
+
+       for (i = 0; i < PTRS_PER_PTE; i++)
+               pte[i] = __pte(0);
+}
+
 __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long 
address)
 {
        pte_t *pte;
@@ -109,18 +117,24 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct 
*mm, unsigned long add
                if (pte)
                        clear_page(pte);
        }
+       if (pte && !pte_none(*pte))
+               pte_alloc_clear(pte);
        return pte;
 }
 
 pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        struct page *ptepage;
+       pte_t *pte;
 
        gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
 
        ptepage = alloc_pages(flags, 0);
        if (!ptepage)
                return NULL;
+       pte = (pte_t *)pfn_to_kaddr(page_to_pfn(ptepage));
+       if (!pte_none(*pte))
+               pte_alloc_clear(pte);
        if (!pgtable_page_ctor(ptepage)) {
                __free_page(ptepage);
                return NULL;
-- 
2.1.0

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to