powerpc/mm/hash64: Store the slot information at the right offset for hugetlb
The hugetlb pte entries are at the PMD and PUD level, so we can't use
PTRS_PER_PTE to find the second half of the page table. Use the right
offset for PUD/PMD to get to the second half of the table.
Fixes: bf9a95f9a6
("powerpc: Free up four 64K PTE bits in 64K backed HPTE pages")
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:

committed by
Michael Ellerman

parent
4a7aa4fecb
commit
ff31e10546
@@ -55,7 +55,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
* need to add in 0x1 if it's a read-only user page
|
||||
*/
|
||||
rflags = htab_convert_pte_flags(new_pte);
|
||||
rpte = __real_pte(__pte(old_pte), ptep);
|
||||
rpte = __real_pte(__pte(old_pte), ptep, PTRS_PER_PTE);
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_NOEXECUTE) &&
|
||||
!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
|
||||
@@ -117,7 +117,7 @@ repeat:
|
||||
return -1;
|
||||
}
|
||||
new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | H_PAGE_HASHPTE;
|
||||
new_pte |= pte_set_hidx(ptep, rpte, 0, slot);
|
||||
new_pte |= pte_set_hidx(ptep, rpte, 0, slot, PTRS_PER_PTE);
|
||||
}
|
||||
*ptep = __pte(new_pte & ~H_PAGE_BUSY);
|
||||
return 0;
|
||||
|
@@ -86,7 +86,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
|
||||
subpg_index = (ea & (PAGE_SIZE - 1)) >> shift;
|
||||
vpn = hpt_vpn(ea, vsid, ssize);
|
||||
rpte = __real_pte(__pte(old_pte), ptep);
|
||||
rpte = __real_pte(__pte(old_pte), ptep, PTRS_PER_PTE);
|
||||
/*
|
||||
*None of the sub 4k page is hashed
|
||||
*/
|
||||
@@ -214,7 +214,7 @@ repeat:
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_pte |= pte_set_hidx(ptep, rpte, subpg_index, slot);
|
||||
new_pte |= pte_set_hidx(ptep, rpte, subpg_index, slot, PTRS_PER_PTE);
|
||||
new_pte |= H_PAGE_HASHPTE;
|
||||
|
||||
*ptep = __pte(new_pte & ~H_PAGE_BUSY);
|
||||
@@ -262,7 +262,7 @@ int __hash_page_64K(unsigned long ea, unsigned long access,
|
||||
} while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
|
||||
|
||||
rflags = htab_convert_pte_flags(new_pte);
|
||||
rpte = __real_pte(__pte(old_pte), ptep);
|
||||
rpte = __real_pte(__pte(old_pte), ptep, PTRS_PER_PTE);
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_NOEXECUTE) &&
|
||||
!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
|
||||
@@ -327,7 +327,7 @@ repeat:
|
||||
}
|
||||
|
||||
new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | H_PAGE_HASHPTE;
|
||||
new_pte |= pte_set_hidx(ptep, rpte, 0, slot);
|
||||
new_pte |= pte_set_hidx(ptep, rpte, 0, slot, PTRS_PER_PTE);
|
||||
}
|
||||
*ptep = __pte(new_pte & ~H_PAGE_BUSY);
|
||||
return 0;
|
||||
|
@@ -27,7 +27,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
unsigned long vpn;
|
||||
unsigned long old_pte, new_pte;
|
||||
unsigned long rflags, pa, sz;
|
||||
long slot;
|
||||
long slot, offset;
|
||||
|
||||
BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
|
||||
|
||||
@@ -63,7 +63,11 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
} while(!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
|
||||
|
||||
rflags = htab_convert_pte_flags(new_pte);
|
||||
rpte = __real_pte(__pte(old_pte), ptep);
|
||||
if (unlikely(mmu_psize == MMU_PAGE_16G))
|
||||
offset = PTRS_PER_PUD;
|
||||
else
|
||||
offset = PTRS_PER_PMD;
|
||||
rpte = __real_pte(__pte(old_pte), ptep, offset);
|
||||
|
||||
sz = ((1UL) << shift);
|
||||
if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
|
||||
@@ -104,7 +108,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_pte |= pte_set_hidx(ptep, rpte, 0, slot);
|
||||
new_pte |= pte_set_hidx(ptep, rpte, 0, slot, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -51,7 +51,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
|
||||
unsigned int psize;
|
||||
int ssize;
|
||||
real_pte_t rpte;
|
||||
int i;
|
||||
int i, offset;
|
||||
|
||||
i = batch->index;
|
||||
|
||||
@@ -67,6 +67,10 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
|
||||
psize = get_slice_psize(mm, addr);
|
||||
/* Mask the address for the correct page size */
|
||||
addr &= ~((1UL << mmu_psize_defs[psize].shift) - 1);
|
||||
if (unlikely(psize == MMU_PAGE_16G))
|
||||
offset = PTRS_PER_PUD;
|
||||
else
|
||||
offset = PTRS_PER_PMD;
|
||||
#else
|
||||
BUG();
|
||||
psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
|
||||
@@ -78,6 +82,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
|
||||
* support 64k pages, this might be different from the
|
||||
* hardware page size encoded in the slice table. */
|
||||
addr &= PAGE_MASK;
|
||||
offset = PTRS_PER_PTE;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +96,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
|
||||
}
|
||||
WARN_ON(vsid == 0);
|
||||
vpn = hpt_vpn(addr, vsid, ssize);
|
||||
rpte = __real_pte(__pte(pte), ptep);
|
||||
rpte = __real_pte(__pte(pte), ptep, offset);
|
||||
|
||||
/*
|
||||
* Check if we have an active batch on this CPU. If not, just
|
||||
|
Reference in New Issue
Block a user