Skip to content

Commit 56eecdb

Browse files
kvaneeshozbenh
authored andcommitted
mm: Use ptep/pmdp_set_numa() for updating _PAGE_NUMA bit
Archs like ppc64 doesn't do tlb flush in set_pte/pmd functions when using a hash table MMU for various reasons (the flush is handled as part of the PTE modification when necessary). ppc64 thus doesn't implement flush_tlb_range for hash based MMUs. Additionally ppc64 require the tlb flushing to be batched within ptl locks. The reason to do that is to ensure that the hash page table is in sync with linux page table. We track the hpte index in linux pte and if we clear them without flushing hash and drop the ptl lock, we can have another cpu update the pte and can end up with duplicate entry in the hash table, which is fatal. We also want to keep set_pte_at simpler by not requiring them to do hash flush for performance reason. We do that by assuming that set_pte_at() is never *ever* called on a PTE that is already valid. This was the case until the NUMA code went in which broke that assumption. Fix that by introducing a new pair of helpers to set _PAGE_NUMA in a way similar to ptep/pmdp_set_wrprotect(), with a generic implementation using set_pte_at() and a powerpc specific one using the appropriate mechanism needed to keep the hash table in sync. Acked-by: Mel Gorman <[email protected]> Reviewed-by: Rik van Riel <[email protected]> Signed-off-by: Aneesh Kumar K.V <[email protected]> Signed-off-by: Benjamin Herrenschmidt <[email protected]>
1 parent 9d85d58 commit 56eecdb

File tree

4 files changed

+64
-10
lines changed

4 files changed

+64
-10
lines changed

arch/powerpc/include/asm/pgtable.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,34 @@ static inline pte_t pte_mknuma(pte_t pte)
7575
return pte;
7676
}
7777

78+
#define ptep_set_numa ptep_set_numa
79+
static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
80+
pte_t *ptep)
81+
{
82+
if ((pte_val(*ptep) & _PAGE_PRESENT) == 0)
83+
VM_BUG_ON(1);
84+
85+
pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0);
86+
return;
87+
}
88+
7889
#define pmd_numa pmd_numa
7990
static inline int pmd_numa(pmd_t pmd)
8091
{
8192
return pte_numa(pmd_pte(pmd));
8293
}
8394

95+
#define pmdp_set_numa pmdp_set_numa
96+
static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
97+
pmd_t *pmdp)
98+
{
99+
if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0)
100+
VM_BUG_ON(1);
101+
102+
pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA);
103+
return;
104+
}
105+
84106
#define pmd_mknonnuma pmd_mknonnuma
85107
static inline pmd_t pmd_mknonnuma(pmd_t pmd)
86108
{

include/asm-generic/pgtable.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,20 +701,46 @@ static inline pte_t pte_mknuma(pte_t pte)
701701
}
702702
#endif
703703

704+
#ifndef ptep_set_numa
705+
static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
706+
pte_t *ptep)
707+
{
708+
pte_t ptent = *ptep;
709+
710+
ptent = pte_mknuma(ptent);
711+
set_pte_at(mm, addr, ptep, ptent);
712+
return;
713+
}
714+
#endif
715+
704716
#ifndef pmd_mknuma
705717
static inline pmd_t pmd_mknuma(pmd_t pmd)
706718
{
707719
pmd = pmd_set_flags(pmd, _PAGE_NUMA);
708720
return pmd_clear_flags(pmd, _PAGE_PRESENT);
709721
}
710722
#endif
723+
724+
#ifndef pmdp_set_numa
725+
static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
726+
pmd_t *pmdp)
727+
{
728+
pmd_t pmd = *pmdp;
729+
730+
pmd = pmd_mknuma(pmd);
731+
set_pmd_at(mm, addr, pmdp, pmd);
732+
return;
733+
}
734+
#endif
711735
#else
712736
extern int pte_numa(pte_t pte);
713737
extern int pmd_numa(pmd_t pmd);
714738
extern pte_t pte_mknonnuma(pte_t pte);
715739
extern pmd_t pmd_mknonnuma(pmd_t pmd);
716740
extern pte_t pte_mknuma(pte_t pte);
717741
extern pmd_t pmd_mknuma(pmd_t pmd);
742+
extern void ptep_set_numa(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
743+
extern void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp);
718744
#endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */
719745
#else
720746
static inline int pmd_numa(pmd_t pmd)
@@ -742,10 +768,23 @@ static inline pte_t pte_mknuma(pte_t pte)
742768
return pte;
743769
}
744770

771+
static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
772+
pte_t *ptep)
773+
{
774+
return;
775+
}
776+
777+
745778
static inline pmd_t pmd_mknuma(pmd_t pmd)
746779
{
747780
return pmd;
748781
}
782+
783+
static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
784+
pmd_t *pmdp)
785+
{
786+
return ;
787+
}
749788
#endif /* CONFIG_NUMA_BALANCING */
750789

751790
#endif /* CONFIG_MMU */

mm/huge_memory.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,7 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
15451545
entry = pmd_mknonnuma(entry);
15461546
entry = pmd_modify(entry, newprot);
15471547
ret = HPAGE_PMD_NR;
1548+
set_pmd_at(mm, addr, pmd, entry);
15481549
BUG_ON(pmd_write(entry));
15491550
} else {
15501551
struct page *page = pmd_page(*pmd);
@@ -1557,16 +1558,10 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
15571558
*/
15581559
if (!is_huge_zero_page(page) &&
15591560
!pmd_numa(*pmd)) {
1560-
entry = *pmd;
1561-
entry = pmd_mknuma(entry);
1561+
pmdp_set_numa(mm, addr, pmd);
15621562
ret = HPAGE_PMD_NR;
15631563
}
15641564
}
1565-
1566-
/* Set PMD if cleared earlier */
1567-
if (ret == HPAGE_PMD_NR)
1568-
set_pmd_at(mm, addr, pmd, entry);
1569-
15701565
spin_unlock(ptl);
15711566
}
15721567

mm/mprotect.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,10 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
6969
} else {
7070
struct page *page;
7171

72-
ptent = *pte;
7372
page = vm_normal_page(vma, addr, oldpte);
7473
if (page && !PageKsm(page)) {
7574
if (!pte_numa(oldpte)) {
76-
ptent = pte_mknuma(ptent);
77-
set_pte_at(mm, addr, pte, ptent);
75+
ptep_set_numa(mm, addr, pte);
7876
updated = true;
7977
}
8078
}

0 commit comments

Comments
 (0)