Skip to content

Commit 42b2547

Browse files
Kefeng Wangakpm00
Kefeng Wang
authored andcommitted
arm64/mm: enable ARCH_SUPPORTS_PAGE_TABLE_CHECK
As commit d283d42 ("x86: mm: add x86_64 support for page table check") , enable ARCH_SUPPORTS_PAGE_TABLE_CHECK on arm64. Add additional page table check stubs for page table helpers, these stubs can be used to check the existing page table entries. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Kefeng Wang <[email protected]> Signed-off-by: Tong Tiangen <[email protected]> Reviewed-by: Pasha Tatashin <[email protected]> Acked-by: Catalin Marinas <[email protected]> Cc: Anshuman Khandual <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Dave Hansen <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 2e7dc2b commit 42b2547

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

arch/arm64/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ config ARM64
9292
select ARCH_SUPPORTS_ATOMIC_RMW
9393
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
9494
select ARCH_SUPPORTS_NUMA_BALANCING
95+
select ARCH_SUPPORTS_PAGE_TABLE_CHECK
9596
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
9697
select ARCH_WANT_DEFAULT_BPF_JIT
9798
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT

arch/arm64/include/asm/pgtable.h

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <linux/mmdebug.h>
3434
#include <linux/mm_types.h>
3535
#include <linux/sched.h>
36+
#include <linux/page_table_check.h>
3637

3738
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
3839
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
@@ -96,6 +97,7 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
9697
#define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
9798
#define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
9899
#define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))
100+
#define pte_user(pte) (!!(pte_val(pte) & PTE_USER))
99101
#define pte_user_exec(pte) (!(pte_val(pte) & PTE_UXN))
100102
#define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT))
101103
#define pte_devmap(pte) (!!(pte_val(pte) & PTE_DEVMAP))
@@ -312,8 +314,8 @@ static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep,
312314
__func__, pte_val(old_pte), pte_val(pte));
313315
}
314316

315-
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
316-
pte_t *ptep, pte_t pte)
317+
static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
318+
pte_t *ptep, pte_t pte)
317319
{
318320
if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
319321
__sync_icache_dcache(pte);
@@ -343,6 +345,13 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
343345
set_pte(ptep, pte);
344346
}
345347

348+
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
349+
pte_t *ptep, pte_t pte)
350+
{
351+
page_table_check_pte_set(mm, addr, ptep, pte);
352+
return __set_pte_at(mm, addr, ptep, pte);
353+
}
354+
346355
/*
347356
* Huge pte definitions.
348357
*/
@@ -454,6 +463,8 @@ static inline int pmd_trans_huge(pmd_t pmd)
454463
#define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
455464
#define pmd_young(pmd) pte_young(pmd_pte(pmd))
456465
#define pmd_valid(pmd) pte_valid(pmd_pte(pmd))
466+
#define pmd_user(pmd) pte_user(pmd_pte(pmd))
467+
#define pmd_user_exec(pmd) pte_user_exec(pmd_pte(pmd))
457468
#define pmd_cont(pmd) pte_cont(pmd_pte(pmd))
458469
#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
459470
#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
@@ -501,8 +512,19 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
501512
#define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT)
502513
#define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
503514

504-
#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
505-
#define set_pud_at(mm, addr, pudp, pud) set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud))
515+
static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
516+
pmd_t *pmdp, pmd_t pmd)
517+
{
518+
page_table_check_pmd_set(mm, addr, pmdp, pmd);
519+
return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
520+
}
521+
522+
static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
523+
pud_t *pudp, pud_t pud)
524+
{
525+
page_table_check_pud_set(mm, addr, pudp, pud);
526+
return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
527+
}
506528

507529
#define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
508530
#define __phys_to_p4d_val(phys) __phys_to_pte_val(phys)
@@ -643,6 +665,24 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
643665
#define pud_present(pud) pte_present(pud_pte(pud))
644666
#define pud_leaf(pud) (pud_present(pud) && !pud_table(pud))
645667
#define pud_valid(pud) pte_valid(pud_pte(pud))
668+
#define pud_user(pud) pte_user(pud_pte(pud))
669+
670+
#ifdef CONFIG_PAGE_TABLE_CHECK
671+
static inline bool pte_user_accessible_page(pte_t pte)
672+
{
673+
return pte_present(pte) && (pte_user(pte) || pte_user_exec(pte));
674+
}
675+
676+
static inline bool pmd_user_accessible_page(pmd_t pmd)
677+
{
678+
return pmd_present(pmd) && (pmd_user(pmd) || pmd_user_exec(pmd));
679+
}
680+
681+
static inline bool pud_user_accessible_page(pud_t pud)
682+
{
683+
return pud_present(pud) && pud_user(pud);
684+
}
685+
#endif
646686

647687
static inline void set_pud(pud_t *pudp, pud_t pud)
648688
{
@@ -876,15 +916,23 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
876916
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
877917
unsigned long address, pte_t *ptep)
878918
{
879-
return __pte(xchg_relaxed(&pte_val(*ptep), 0));
919+
pte_t pte = __pte(xchg_relaxed(&pte_val(*ptep), 0));
920+
921+
page_table_check_pte_clear(mm, address, pte);
922+
923+
return pte;
880924
}
881925

882926
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
883927
#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
884928
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
885929
unsigned long address, pmd_t *pmdp)
886930
{
887-
return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
931+
pmd_t pmd = __pmd(xchg_relaxed(&pmd_val(*pmdp), 0));
932+
933+
page_table_check_pmd_clear(mm, address, pmd);
934+
935+
return pmd;
888936
}
889937
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
890938

@@ -918,6 +966,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
918966
static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
919967
unsigned long address, pmd_t *pmdp, pmd_t pmd)
920968
{
969+
page_table_check_pmd_set(vma->vm_mm, address, pmdp, pmd);
921970
return __pmd(xchg_relaxed(&pmd_val(*pmdp), pmd_val(pmd)));
922971
}
923972
#endif

0 commit comments

Comments
 (0)