powerpc/mm/hugetlb: Update hugetlb related locks
With split pmd page table lock enabled, we don't use mm->page_table_lock when
updating pmd entries. This patch update hugetlb path to use the right lock
when inserting huge page directory entries into page table.
ex: if we are using hugepd and inserting hugepd entry at the pmd level, we
use pmd_lockptr, which based on config can be split pmd lock.
For update huge page directory entries itself we use mm->page_table_lock. We
do have a helper huge_pte_lockptr() for that.
Fixes: 675d99529
("powerpc/book3s64: Enable split pmd ptlock")
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
91d0697188
commit
ed515b6898
|
@ -52,7 +52,8 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, unsigned long s
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
|
static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
|
||||||
unsigned long address, unsigned pdshift, unsigned pshift)
|
unsigned long address, unsigned int pdshift,
|
||||||
|
unsigned int pshift, spinlock_t *ptl)
|
||||||
{
|
{
|
||||||
struct kmem_cache *cachep;
|
struct kmem_cache *cachep;
|
||||||
pte_t *new;
|
pte_t *new;
|
||||||
|
@ -82,8 +83,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
|
||||||
*/
|
*/
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(ptl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have multiple higher-level entries that point to the same
|
* We have multiple higher-level entries that point to the same
|
||||||
* actual pte location. Fill in each as we go and backtrack on error.
|
* actual pte location. Fill in each as we go and backtrack on error.
|
||||||
|
@ -113,7 +113,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
|
||||||
*hpdp = __hugepd(0);
|
*hpdp = __hugepd(0);
|
||||||
kmem_cache_free(cachep, new);
|
kmem_cache_free(cachep, new);
|
||||||
}
|
}
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(ptl);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +138,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz
|
||||||
hugepd_t *hpdp = NULL;
|
hugepd_t *hpdp = NULL;
|
||||||
unsigned pshift = __ffs(sz);
|
unsigned pshift = __ffs(sz);
|
||||||
unsigned pdshift = PGDIR_SHIFT;
|
unsigned pdshift = PGDIR_SHIFT;
|
||||||
|
spinlock_t *ptl;
|
||||||
|
|
||||||
addr &= ~(sz-1);
|
addr &= ~(sz-1);
|
||||||
pg = pgd_offset(mm, addr);
|
pg = pgd_offset(mm, addr);
|
||||||
|
@ -146,39 +147,46 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz
|
||||||
if (pshift == PGDIR_SHIFT)
|
if (pshift == PGDIR_SHIFT)
|
||||||
/* 16GB huge page */
|
/* 16GB huge page */
|
||||||
return (pte_t *) pg;
|
return (pte_t *) pg;
|
||||||
else if (pshift > PUD_SHIFT)
|
else if (pshift > PUD_SHIFT) {
|
||||||
/*
|
/*
|
||||||
* We need to use hugepd table
|
* We need to use hugepd table
|
||||||
*/
|
*/
|
||||||
|
ptl = &mm->page_table_lock;
|
||||||
hpdp = (hugepd_t *)pg;
|
hpdp = (hugepd_t *)pg;
|
||||||
else {
|
} else {
|
||||||
pdshift = PUD_SHIFT;
|
pdshift = PUD_SHIFT;
|
||||||
pu = pud_alloc(mm, pg, addr);
|
pu = pud_alloc(mm, pg, addr);
|
||||||
if (pshift == PUD_SHIFT)
|
if (pshift == PUD_SHIFT)
|
||||||
return (pte_t *)pu;
|
return (pte_t *)pu;
|
||||||
else if (pshift > PMD_SHIFT)
|
else if (pshift > PMD_SHIFT) {
|
||||||
|
ptl = pud_lockptr(mm, pu);
|
||||||
hpdp = (hugepd_t *)pu;
|
hpdp = (hugepd_t *)pu;
|
||||||
else {
|
} else {
|
||||||
pdshift = PMD_SHIFT;
|
pdshift = PMD_SHIFT;
|
||||||
pm = pmd_alloc(mm, pu, addr);
|
pm = pmd_alloc(mm, pu, addr);
|
||||||
if (pshift == PMD_SHIFT)
|
if (pshift == PMD_SHIFT)
|
||||||
/* 16MB hugepage */
|
/* 16MB hugepage */
|
||||||
return (pte_t *)pm;
|
return (pte_t *)pm;
|
||||||
else
|
else {
|
||||||
|
ptl = pmd_lockptr(mm, pm);
|
||||||
hpdp = (hugepd_t *)pm;
|
hpdp = (hugepd_t *)pm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (pshift >= HUGEPD_PGD_SHIFT) {
|
if (pshift >= HUGEPD_PGD_SHIFT) {
|
||||||
|
ptl = &mm->page_table_lock;
|
||||||
hpdp = (hugepd_t *)pg;
|
hpdp = (hugepd_t *)pg;
|
||||||
} else {
|
} else {
|
||||||
pdshift = PUD_SHIFT;
|
pdshift = PUD_SHIFT;
|
||||||
pu = pud_alloc(mm, pg, addr);
|
pu = pud_alloc(mm, pg, addr);
|
||||||
if (pshift >= HUGEPD_PUD_SHIFT) {
|
if (pshift >= HUGEPD_PUD_SHIFT) {
|
||||||
|
ptl = pud_lockptr(mm, pu);
|
||||||
hpdp = (hugepd_t *)pu;
|
hpdp = (hugepd_t *)pu;
|
||||||
} else {
|
} else {
|
||||||
pdshift = PMD_SHIFT;
|
pdshift = PMD_SHIFT;
|
||||||
pm = pmd_alloc(mm, pu, addr);
|
pm = pmd_alloc(mm, pu, addr);
|
||||||
|
ptl = pmd_lockptr(mm, pm);
|
||||||
hpdp = (hugepd_t *)pm;
|
hpdp = (hugepd_t *)pm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +196,8 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz
|
||||||
|
|
||||||
BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp));
|
BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp));
|
||||||
|
|
||||||
if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift))
|
if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr,
|
||||||
|
pdshift, pshift, ptl))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return hugepte_offset(*hpdp, addr, pdshift);
|
return hugepte_offset(*hpdp, addr, pdshift);
|
||||||
|
@ -499,6 +508,10 @@ struct page *follow_huge_pd(struct vm_area_struct *vma,
|
||||||
struct mm_struct *mm = vma->vm_mm;
|
struct mm_struct *mm = vma->vm_mm;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
|
/*
|
||||||
|
* hugepage directory entries are protected by mm->page_table_lock
|
||||||
|
* Use this instead of huge_pte_lockptr
|
||||||
|
*/
|
||||||
ptl = &mm->page_table_lock;
|
ptl = &mm->page_table_lock;
|
||||||
spin_lock(ptl);
|
spin_lock(ptl);
|
||||||
|
|
||||||
|
|
|
@ -249,17 +249,19 @@ extern int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_BOOK3S_64
|
#ifdef CONFIG_PPC_BOOK3S_64
|
||||||
struct hstate *hstate = hstate_file(vma->vm_file);
|
struct hstate *h = hstate_vma(vma);
|
||||||
psize = hstate_get_psize(hstate);
|
|
||||||
|
psize = hstate_get_psize(h);
|
||||||
|
#ifdef CONFIG_DEBUG_VM
|
||||||
|
assert_spin_locked(huge_pte_lockptr(h, vma->vm_mm, ptep));
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
* Not used on non book3s64 platforms. But 8xx
|
* Not used on non book3s64 platforms. But 8xx
|
||||||
* can possibly use tsize derived from hstate.
|
* can possibly use tsize derived from hstate.
|
||||||
*/
|
*/
|
||||||
psize = 0;
|
psize = 0;
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_DEBUG_VM
|
|
||||||
assert_spin_locked(&vma->vm_mm->page_table_lock);
|
|
||||||
#endif
|
#endif
|
||||||
__ptep_set_access_flags(vma, ptep, pte, addr, psize);
|
__ptep_set_access_flags(vma, ptep, pte, addr, psize);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue