* [PATCH -next v6 1/6] mm: page_table_check: using PxD_SIZE instead of PxD_PAGE_SIZE
2022-04-26 8:10 [PATCH -next v6 0/6]mm: page_table_check: add support on arm64 and riscv Tong Tiangen
@ 2022-04-26 8:10 ` Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 2/6] mm: page_table_check: move pxx_user_accessible_page into x86 Tong Tiangen
` (4 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Tong Tiangen @ 2022-04-26 8:10 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pasha Tatashin, Anshuman Khandual, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Tong Tiangen, Kefeng Wang, Guohanjun
Compared with PxD_PAGE_SIZE, which is defined and used only on X86,
PxD_SIZE is more common in each architecture. Therefore, it is more
reasonable to use PxD_SIZE instead of PxD_PAGE_SIZE in page_table_check.c.
At the same time, it is easier to support page table check in other
architectures. The substitution has no functional impact on the x86.
Suggested-by: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
Acked-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
---
mm/page_table_check.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/mm/page_table_check.c b/mm/page_table_check.c
index 2458281bff89..eb0d0b71cdf6 100644
--- a/mm/page_table_check.c
+++ b/mm/page_table_check.c
@@ -177,7 +177,7 @@ void __page_table_check_pmd_clear(struct mm_struct *mm, unsigned long addr,
if (pmd_user_accessible_page(pmd)) {
page_table_check_clear(mm, addr, pmd_pfn(pmd),
- PMD_PAGE_SIZE >> PAGE_SHIFT);
+ PMD_SIZE >> PAGE_SHIFT);
}
}
EXPORT_SYMBOL(__page_table_check_pmd_clear);
@@ -190,7 +190,7 @@ void __page_table_check_pud_clear(struct mm_struct *mm, unsigned long addr,
if (pud_user_accessible_page(pud)) {
page_table_check_clear(mm, addr, pud_pfn(pud),
- PUD_PAGE_SIZE >> PAGE_SHIFT);
+ PUD_SIZE >> PAGE_SHIFT);
}
}
EXPORT_SYMBOL(__page_table_check_pud_clear);
@@ -219,7 +219,7 @@ void __page_table_check_pmd_set(struct mm_struct *mm, unsigned long addr,
__page_table_check_pmd_clear(mm, addr, *pmdp);
if (pmd_user_accessible_page(pmd)) {
page_table_check_set(mm, addr, pmd_pfn(pmd),
- PMD_PAGE_SIZE >> PAGE_SHIFT,
+ PMD_SIZE >> PAGE_SHIFT,
pmd_write(pmd));
}
}
@@ -234,7 +234,7 @@ void __page_table_check_pud_set(struct mm_struct *mm, unsigned long addr,
__page_table_check_pud_clear(mm, addr, *pudp);
if (pud_user_accessible_page(pud)) {
page_table_check_set(mm, addr, pud_pfn(pud),
- PUD_PAGE_SIZE >> PAGE_SHIFT,
+ PUD_SIZE >> PAGE_SHIFT,
pud_write(pud));
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH -next v6 2/6] mm: page_table_check: move pxx_user_accessible_page into x86
2022-04-26 8:10 [PATCH -next v6 0/6]mm: page_table_check: add support on arm64 and riscv Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 1/6] mm: page_table_check: using PxD_SIZE instead of PxD_PAGE_SIZE Tong Tiangen
@ 2022-04-26 8:10 ` Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 3/6] mm: page_table_check: add hooks to public helpers Tong Tiangen
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Tong Tiangen @ 2022-04-26 8:10 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pasha Tatashin, Anshuman Khandual, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Tong Tiangen, Kefeng Wang, Guohanjun
From: Kefeng Wang <wangkefeng.wang@huawei.com>
The pxx_user_accessible_page() checks the PTE bit, it's
architecture-specific code, move them into x86's pgtable.h.
These helpers are being moved out to make the page table check framework
platform independent.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
Acked-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
---
arch/x86/include/asm/pgtable.h | 17 +++++++++++++++++
mm/page_table_check.c | 17 -----------------
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 0821f87d495f..46fa65d818bd 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1447,6 +1447,23 @@ static inline bool arch_faults_on_old_pte(void)
return false;
}
+#ifdef CONFIG_PAGE_TABLE_CHECK
+static inline bool pte_user_accessible_page(pte_t pte)
+{
+ return (pte_val(pte) & _PAGE_PRESENT) && (pte_val(pte) & _PAGE_USER);
+}
+
+static inline bool pmd_user_accessible_page(pmd_t pmd)
+{
+ return pmd_leaf(pmd) && (pmd_val(pmd) & _PAGE_PRESENT) && (pmd_val(pmd) & _PAGE_USER);
+}
+
+static inline bool pud_user_accessible_page(pud_t pud)
+{
+ return pud_leaf(pud) && (pud_val(pud) & _PAGE_PRESENT) && (pud_val(pud) & _PAGE_USER);
+}
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_PGTABLE_H */
diff --git a/mm/page_table_check.c b/mm/page_table_check.c
index eb0d0b71cdf6..3692bea2ea2c 100644
--- a/mm/page_table_check.c
+++ b/mm/page_table_check.c
@@ -52,23 +52,6 @@ static struct page_table_check *get_page_table_check(struct page_ext *page_ext)
return (void *)(page_ext) + page_table_check_ops.offset;
}
-static inline bool pte_user_accessible_page(pte_t pte)
-{
- return (pte_val(pte) & _PAGE_PRESENT) && (pte_val(pte) & _PAGE_USER);
-}
-
-static inline bool pmd_user_accessible_page(pmd_t pmd)
-{
- return pmd_leaf(pmd) && (pmd_val(pmd) & _PAGE_PRESENT) &&
- (pmd_val(pmd) & _PAGE_USER);
-}
-
-static inline bool pud_user_accessible_page(pud_t pud)
-{
- return pud_leaf(pud) && (pud_val(pud) & _PAGE_PRESENT) &&
- (pud_val(pud) & _PAGE_USER);
-}
-
/*
* An enty is removed from the page table, decrement the counters for that page
* verify that it is of correct type and counters do not become negative.
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH -next v6 3/6] mm: page_table_check: add hooks to public helpers
2022-04-26 8:10 [PATCH -next v6 0/6]mm: page_table_check: add support on arm64 and riscv Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 1/6] mm: page_table_check: using PxD_SIZE instead of PxD_PAGE_SIZE Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 2/6] mm: page_table_check: move pxx_user_accessible_page into x86 Tong Tiangen
@ 2022-04-26 8:10 ` Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 4/6] mm: remove __HAVE_ARCH_PTEP_CLEAR in pgtable.h Tong Tiangen
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Tong Tiangen @ 2022-04-26 8:10 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pasha Tatashin, Anshuman Khandual, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Tong Tiangen, Kefeng Wang, Guohanjun
Move ptep_clear() to the include/linux/pgtable.h and add page table check
relate hooks to some helpers, it's prepare for support page table check
feature on new architecture.
Optimize the implementation of ptep_clear(), page table hooks added page
table check stubs, the interface control should be at stubs, there is no
rationale for doing a IS_ENABLED() check here.
For architectures that do not enable CONFIG_PAGE_TABLE_CHECK, they will
call a fallback page table check stubs[1] when getting their page table
helpers[2] in include/linux/pgtable.h.
[1] page table check stubs defined in include/linux/page_table_check.h
[2] ptep_clear() ptep_get_and_clear() pmdp_huge_get_and_clear()
pudp_huge_get_and_clear()
Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
Acked-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
arch/x86/include/asm/pgtable.h | 10 ----------
include/linux/pgtable.h | 23 +++++++++++++++--------
2 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 46fa65d818bd..44e2d6f1dbaa 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1072,16 +1072,6 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
return pte;
}
-#define __HAVE_ARCH_PTEP_CLEAR
-static inline void ptep_clear(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep)
-{
- if (IS_ENABLED(CONFIG_PAGE_TABLE_CHECK))
- ptep_get_and_clear(mm, addr, ptep);
- else
- pte_clear(mm, addr, ptep);
-}
-
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
static inline void ptep_set_wrprotect(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index 530b1817b58c..3c825162c8da 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -12,6 +12,7 @@
#include <linux/bug.h>
#include <linux/errno.h>
#include <asm-generic/pgtable_uffd.h>
+#include <linux/page_table_check.h>
#if 5 - defined(__PAGETABLE_P4D_FOLDED) - defined(__PAGETABLE_PUD_FOLDED) - \
defined(__PAGETABLE_PMD_FOLDED) != CONFIG_PGTABLE_LEVELS
@@ -259,14 +260,6 @@ static inline int pmdp_clear_flush_young(struct vm_area_struct *vma,
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
#endif
-#ifndef __HAVE_ARCH_PTEP_CLEAR
-static inline void ptep_clear(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep)
-{
- pte_clear(mm, addr, ptep);
-}
-#endif
-
#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address,
@@ -274,10 +267,19 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
{
pte_t pte = *ptep;
pte_clear(mm, address, ptep);
+ page_table_check_pte_clear(mm, address, pte);
return pte;
}
#endif
+#ifndef __HAVE_ARCH_PTEP_CLEAR
+static inline void ptep_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ ptep_get_and_clear(mm, addr, ptep);
+}
+#endif
+
#ifndef __HAVE_ARCH_PTEP_GET
static inline pte_t ptep_get(pte_t *ptep)
{
@@ -347,7 +349,10 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
pmd_t *pmdp)
{
pmd_t pmd = *pmdp;
+
pmd_clear(pmdp);
+ page_table_check_pmd_clear(mm, address, pmd);
+
return pmd;
}
#endif /* __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR */
@@ -359,6 +364,8 @@ static inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm,
pud_t pud = *pudp;
pud_clear(pudp);
+ page_table_check_pud_clear(mm, address, pud);
+
return pud;
}
#endif /* __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR */
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH -next v6 4/6] mm: remove __HAVE_ARCH_PTEP_CLEAR in pgtable.h
2022-04-26 8:10 [PATCH -next v6 0/6]mm: page_table_check: add support on arm64 and riscv Tong Tiangen
` (2 preceding siblings ...)
2022-04-26 8:10 ` [PATCH -next v6 3/6] mm: page_table_check: add hooks to public helpers Tong Tiangen
@ 2022-04-26 8:10 ` Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK Tong Tiangen
2022-04-26 8:10 ` [PATCH -next v6 6/6] riscv/mm: " Tong Tiangen
5 siblings, 0 replies; 11+ messages in thread
From: Tong Tiangen @ 2022-04-26 8:10 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pasha Tatashin, Anshuman Khandual, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Tong Tiangen, Kefeng Wang, Guohanjun
Currently, there is no architecture definition __HAVE_ARCH_PTEP_CLEAR,
Generic ptep_clear() is the only definition for all architecture, So
drop the "#ifndef __HAVE_ARCH_PTEP_CLEAR".
Suggested-by: Anshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
---
include/linux/pgtable.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index 3c825162c8da..b7a785e787b5 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -272,13 +272,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
}
#endif
-#ifndef __HAVE_ARCH_PTEP_CLEAR
static inline void ptep_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
ptep_get_and_clear(mm, addr, ptep);
}
-#endif
#ifndef __HAVE_ARCH_PTEP_GET
static inline pte_t ptep_get(pte_t *ptep)
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK
2022-04-26 8:10 [PATCH -next v6 0/6]mm: page_table_check: add support on arm64 and riscv Tong Tiangen
` (3 preceding siblings ...)
2022-04-26 8:10 ` [PATCH -next v6 4/6] mm: remove __HAVE_ARCH_PTEP_CLEAR in pgtable.h Tong Tiangen
@ 2022-04-26 8:10 ` Tong Tiangen
2022-04-29 6:18 ` Anshuman Khandual
2022-04-26 8:10 ` [PATCH -next v6 6/6] riscv/mm: " Tong Tiangen
5 siblings, 1 reply; 11+ messages in thread
From: Tong Tiangen @ 2022-04-26 8:10 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pasha Tatashin, Anshuman Khandual, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Tong Tiangen, Kefeng Wang, Guohanjun
From: Kefeng Wang <wangkefeng.wang@huawei.com>
As commit d283d422c6c4 ("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.
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/pgtable.h | 59 +++++++++++++++++++++++++++++---
2 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 18a18a0e855d..c1509525ab8e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -92,6 +92,7 @@ config ARM64
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
select ARCH_SUPPORTS_NUMA_BALANCING
+ select ARCH_SUPPORTS_PAGE_TABLE_CHECK
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
select ARCH_WANT_DEFAULT_BPF_JIT
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index ad9b221963d4..fe17788a6885 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -33,6 +33,7 @@
#include <linux/mmdebug.h>
#include <linux/mm_types.h>
#include <linux/sched.h>
+#include <linux/page_table_check.h>
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
@@ -96,6 +97,7 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
#define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
#define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
#define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))
+#define pte_user(pte) (!!(pte_val(pte) & PTE_USER))
#define pte_user_exec(pte) (!(pte_val(pte) & PTE_UXN))
#define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT))
#define pte_devmap(pte) (!!(pte_val(pte) & PTE_DEVMAP))
@@ -312,7 +314,7 @@ static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep,
__func__, pte_val(old_pte), pte_val(pte));
}
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
@@ -343,6 +345,13 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
set_pte(ptep, pte);
}
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ page_table_check_pte_set(mm, addr, ptep, pte);
+ return __set_pte_at(mm, addr, ptep, pte);
+}
+
/*
* Huge pte definitions.
*/
@@ -454,6 +463,8 @@ static inline int pmd_trans_huge(pmd_t pmd)
#define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
#define pmd_young(pmd) pte_young(pmd_pte(pmd))
#define pmd_valid(pmd) pte_valid(pmd_pte(pmd))
+#define pmd_user(pmd) pte_user(pmd_pte(pmd))
+#define pmd_user_exec(pmd) pte_user_exec(pmd_pte(pmd))
#define pmd_cont(pmd) pte_cont(pmd_pte(pmd))
#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
@@ -501,8 +512,19 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
#define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT)
#define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
-#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
-#define set_pud_at(mm, addr, pudp, pud) set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud))
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd)
+{
+ page_table_check_pmd_set(mm, addr, pmdp, pmd);
+ return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
+}
+
+static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
+ pud_t *pudp, pud_t pud)
+{
+ page_table_check_pud_set(mm, addr, pudp, pud);
+ return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
+}
#define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
#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)
#define pud_present(pud) pte_present(pud_pte(pud))
#define pud_leaf(pud) pud_sect(pud)
#define pud_valid(pud) pte_valid(pud_pte(pud))
+#define pud_user(pud) pte_user(pud_pte(pud))
+
+#ifdef CONFIG_PAGE_TABLE_CHECK
+static inline bool pte_user_accessible_page(pte_t pte)
+{
+ return pte_present(pte) && (pte_user(pte) || pte_user_exec(pte));
+}
+
+static inline bool pmd_user_accessible_page(pmd_t pmd)
+{
+ return pmd_present(pmd) && (pmd_user(pmd) || pmd_user_exec(pmd));
+}
+
+static inline bool pud_user_accessible_page(pud_t pud)
+{
+ return pud_present(pud) && pud_user(pud);
+}
+#endif
static inline void set_pud(pud_t *pudp, pud_t pud)
{
@@ -876,7 +916,11 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, pte_t *ptep)
{
- return __pte(xchg_relaxed(&pte_val(*ptep), 0));
+ pte_t pte = __pte(xchg_relaxed(&pte_val(*ptep), 0));
+
+ page_table_check_pte_clear(mm, address, pte);
+
+ return pte;
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -884,7 +928,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
unsigned long address, pmd_t *pmdp)
{
- return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
+ pmd_t pmd = pte_pmd(__pte(xchg_relaxed(&pte_val(*(pte_t *)pmdp), 0)));
+
+ page_table_check_pmd_clear(mm, address, pmd);
+
+ return pmd;
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
@@ -918,6 +966,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
unsigned long address, pmd_t *pmdp, pmd_t pmd)
{
+ page_table_check_pmd_set(vma->vm_mm, address, pmdp, pmd);
return __pmd(xchg_relaxed(&pmd_val(*pmdp), pmd_val(pmd)));
}
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK
2022-04-26 8:10 ` [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK Tong Tiangen
@ 2022-04-29 6:18 ` Anshuman Khandual
2022-05-03 1:13 ` Tong Tiangen
0 siblings, 1 reply; 11+ messages in thread
From: Anshuman Khandual @ 2022-04-29 6:18 UTC (permalink / raw)
To: Tong Tiangen, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Pasha Tatashin, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Kefeng Wang, Guohanjun
On 4/26/22 13:40, Tong Tiangen wrote:
> From: Kefeng Wang <wangkefeng.wang@huawei.com>
>
> As commit d283d422c6c4 ("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.
>
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
> Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> ---
> arch/arm64/Kconfig | 1 +
> arch/arm64/include/asm/pgtable.h | 59 +++++++++++++++++++++++++++++---
> 2 files changed, 55 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 18a18a0e855d..c1509525ab8e 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -92,6 +92,7 @@ config ARM64
> select ARCH_SUPPORTS_ATOMIC_RMW
> select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
> select ARCH_SUPPORTS_NUMA_BALANCING
> + select ARCH_SUPPORTS_PAGE_TABLE_CHECK
> select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
> select ARCH_WANT_DEFAULT_BPF_JIT
> select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
> index ad9b221963d4..fe17788a6885 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
> @@ -33,6 +33,7 @@
> #include <linux/mmdebug.h>
> #include <linux/mm_types.h>
> #include <linux/sched.h>
> +#include <linux/page_table_check.h>
>
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
> @@ -96,6 +97,7 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
> #define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
> #define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
> #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))
> +#define pte_user(pte) (!!(pte_val(pte) & PTE_USER))
> #define pte_user_exec(pte) (!(pte_val(pte) & PTE_UXN))
> #define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT))
> #define pte_devmap(pte) (!!(pte_val(pte) & PTE_DEVMAP))
> @@ -312,7 +314,7 @@ static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep,
> __func__, pte_val(old_pte), pte_val(pte));
> }
>
> -static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
> +static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
> pte_t *ptep, pte_t pte)
A small nit. Subsequent line containing the arguments "pte_t *ptep ..."
needs to be aligned properly, after '__' got added into set_pte_at().
> {
> if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
> @@ -343,6 +345,13 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
> set_pte(ptep, pte);
> }
>
> +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
> + pte_t *ptep, pte_t pte)
> +{
> + page_table_check_pte_set(mm, addr, ptep, pte);
> + return __set_pte_at(mm, addr, ptep, pte);
> +}
> +
> /*
> * Huge pte definitions.
> */
> @@ -454,6 +463,8 @@ static inline int pmd_trans_huge(pmd_t pmd)
> #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
> #define pmd_young(pmd) pte_young(pmd_pte(pmd))
> #define pmd_valid(pmd) pte_valid(pmd_pte(pmd))
> +#define pmd_user(pmd) pte_user(pmd_pte(pmd))
> +#define pmd_user_exec(pmd) pte_user_exec(pmd_pte(pmd))
> #define pmd_cont(pmd) pte_cont(pmd_pte(pmd))
> #define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
> #define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
> @@ -501,8 +512,19 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
> #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT)
> #define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
>
> -#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
> -#define set_pud_at(mm, addr, pudp, pud) set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud))
> +static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
> + pmd_t *pmdp, pmd_t pmd)
> +{
> + page_table_check_pmd_set(mm, addr, pmdp, pmd);
> + return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
> +}
> +
> +static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
> + pud_t *pudp, pud_t pud)
> +{
> + page_table_check_pud_set(mm, addr, pudp, pud);
> + return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
> +}
>
> #define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
> #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)
> #define pud_present(pud) pte_present(pud_pte(pud))
> #define pud_leaf(pud) pud_sect(pud)
> #define pud_valid(pud) pte_valid(pud_pte(pud))
> +#define pud_user(pud) pte_user(pud_pte(pud))
> +
> +#ifdef CONFIG_PAGE_TABLE_CHECK
> +static inline bool pte_user_accessible_page(pte_t pte)
> +{
> + return pte_present(pte) && (pte_user(pte) || pte_user_exec(pte));
> +}
> +
> +static inline bool pmd_user_accessible_page(pmd_t pmd)
> +{
> + return pmd_present(pmd) && (pmd_user(pmd) || pmd_user_exec(pmd));
> +}
> +
> +static inline bool pud_user_accessible_page(pud_t pud)
> +{
> + return pud_present(pud) && pud_user(pud);
> +}
> +#endif
>
> static inline void set_pud(pud_t *pudp, pud_t pud)
> {
> @@ -876,7 +916,11 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
> static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
> unsigned long address, pte_t *ptep)
> {
> - return __pte(xchg_relaxed(&pte_val(*ptep), 0));
> + pte_t pte = __pte(xchg_relaxed(&pte_val(*ptep), 0));
> +
> + page_table_check_pte_clear(mm, address, pte);
> +
> + return pte;
> }
>
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> @@ -884,7 +928,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
> static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
> unsigned long address, pmd_t *pmdp)
> {
> - return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
> + pmd_t pmd = pte_pmd(__pte(xchg_relaxed(&pte_val(*(pte_t *)pmdp), 0)));
Why there is any change here ? Why not just the following instead, like what you did
in ptep_get_and_clear() above. The page table entry return value here just needs to
be preserved for subsequent page table check helpers.
pmd_t pmd = pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
> +
> + page_table_check_pmd_clear(mm, address, pmd);
> +
> + return pmd;
> }
> #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>
> @@ -918,6 +966,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
> static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
> unsigned long address, pmd_t *pmdp, pmd_t pmd)
> {
> + page_table_check_pmd_set(vma->vm_mm, address, pmdp, pmd);
> return __pmd(xchg_relaxed(&pmd_val(*pmdp), pmd_val(pmd)));
> }
> #endif
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK
2022-04-29 6:18 ` Anshuman Khandual
@ 2022-05-03 1:13 ` Tong Tiangen
2022-05-04 17:26 ` Catalin Marinas
0 siblings, 1 reply; 11+ messages in thread
From: Tong Tiangen @ 2022-05-03 1:13 UTC (permalink / raw)
To: Anshuman Khandual, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Pasha Tatashin, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Kefeng Wang, Guohanjun
在 2022/4/29 14:18, Anshuman Khandual 写道:
>
>
> On 4/26/22 13:40, Tong Tiangen wrote:
>> From: Kefeng Wang <wangkefeng.wang@huawei.com>
>>
>> As commit d283d422c6c4 ("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.
>>
>> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
>> Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
>> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
>> ---
>> arch/arm64/Kconfig | 1 +
>> arch/arm64/include/asm/pgtable.h | 59 +++++++++++++++++++++++++++++---
>> 2 files changed, 55 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 18a18a0e855d..c1509525ab8e 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -92,6 +92,7 @@ config ARM64
>> select ARCH_SUPPORTS_ATOMIC_RMW
>> select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
>> select ARCH_SUPPORTS_NUMA_BALANCING
>> + select ARCH_SUPPORTS_PAGE_TABLE_CHECK
>> select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
>> select ARCH_WANT_DEFAULT_BPF_JIT
>> select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
>> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
>> index ad9b221963d4..fe17788a6885 100644
>> --- a/arch/arm64/include/asm/pgtable.h
>> +++ b/arch/arm64/include/asm/pgtable.h
>> @@ -33,6 +33,7 @@
>> #include <linux/mmdebug.h>
>> #include <linux/mm_types.h>
>> #include <linux/sched.h>
>> +#include <linux/page_table_check.h>
>>
>> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
>> @@ -96,6 +97,7 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
>> #define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
>> #define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
>> #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))
>> +#define pte_user(pte) (!!(pte_val(pte) & PTE_USER))
>> #define pte_user_exec(pte) (!(pte_val(pte) & PTE_UXN))
>> #define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT))
>> #define pte_devmap(pte) (!!(pte_val(pte) & PTE_DEVMAP))
>> @@ -312,7 +314,7 @@ static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep,
>> __func__, pte_val(old_pte), pte_val(pte));
>> }
>>
>> -static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
>> +static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
>> pte_t *ptep, pte_t pte)
>
> A small nit. Subsequent line containing the arguments "pte_t *ptep ..."
> needs to be aligned properly, after '__' got added into set_pte_at().
OK, missing that, .will fix it next version.
>
>> {
>> if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
>> @@ -343,6 +345,13 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
>> set_pte(ptep, pte);
>> }
>>
>> +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
>> + pte_t *ptep, pte_t pte)
>> +{
>> + page_table_check_pte_set(mm, addr, ptep, pte);
>> + return __set_pte_at(mm, addr, ptep, pte);
>> +}
>> +
>> /*
>> * Huge pte definitions.
>> */
>> @@ -454,6 +463,8 @@ static inline int pmd_trans_huge(pmd_t pmd)
>> #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
>> #define pmd_young(pmd) pte_young(pmd_pte(pmd))
>> #define pmd_valid(pmd) pte_valid(pmd_pte(pmd))
>> +#define pmd_user(pmd) pte_user(pmd_pte(pmd))
>> +#define pmd_user_exec(pmd) pte_user_exec(pmd_pte(pmd))
>> #define pmd_cont(pmd) pte_cont(pmd_pte(pmd))
>> #define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
>> #define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
>> @@ -501,8 +512,19 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
>> #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT)
>> #define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
>>
>> -#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
>> -#define set_pud_at(mm, addr, pudp, pud) set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud))
>> +static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
>> + pmd_t *pmdp, pmd_t pmd)
>> +{
>> + page_table_check_pmd_set(mm, addr, pmdp, pmd);
>> + return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
>> +}
>> +
>> +static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
>> + pud_t *pudp, pud_t pud)
>> +{
>> + page_table_check_pud_set(mm, addr, pudp, pud);
>> + return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
>> +}
>>
>> #define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
>> #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)
>> #define pud_present(pud) pte_present(pud_pte(pud))
>> #define pud_leaf(pud) pud_sect(pud)
>> #define pud_valid(pud) pte_valid(pud_pte(pud))
>> +#define pud_user(pud) pte_user(pud_pte(pud))
>> +
>> +#ifdef CONFIG_PAGE_TABLE_CHECK
>> +static inline bool pte_user_accessible_page(pte_t pte)
>> +{
>> + return pte_present(pte) && (pte_user(pte) || pte_user_exec(pte));
>> +}
>> +
>> +static inline bool pmd_user_accessible_page(pmd_t pmd)
>> +{
>> + return pmd_present(pmd) && (pmd_user(pmd) || pmd_user_exec(pmd));
>> +}
>> +
>> +static inline bool pud_user_accessible_page(pud_t pud)
>> +{
>> + return pud_present(pud) && pud_user(pud);
>> +}
>> +#endif
>>
>> static inline void set_pud(pud_t *pudp, pud_t pud)
>> {
>> @@ -876,7 +916,11 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
>> static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
>> unsigned long address, pte_t *ptep)
>> {
>> - return __pte(xchg_relaxed(&pte_val(*ptep), 0));
>> + pte_t pte = __pte(xchg_relaxed(&pte_val(*ptep), 0));
>> +
>> + page_table_check_pte_clear(mm, address, pte);
>> +
>> + return pte;
>> }
>>
>> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> @@ -884,7 +928,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
>> static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
>> unsigned long address, pmd_t *pmdp)
>> {
>> - return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
>> + pmd_t pmd = pte_pmd(__pte(xchg_relaxed(&pte_val(*(pte_t *)pmdp), 0)));
>
> Why there is any change here ? Why not just the following instead, like what you did
> in ptep_get_and_clear() above. The page table entry return value here just needs to
> be preserved for subsequent page table check helpers.
>
> pmd_t pmd = pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
>
Hi Anshuman:
The purpose of what I do here is to avoid doing
page_table_check_pte_clear() in ptep_get_and_clear(). there is no
functional change here.
Thanks,
Tong.
>> +
>> + page_table_check_pmd_clear(mm, address, pmd);
>> +
>> + return pmd;
>> }
>> #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>>
>> @@ -918,6 +966,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
>> static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
>> unsigned long address, pmd_t *pmdp, pmd_t pmd)
>> {
>> + page_table_check_pmd_set(vma->vm_mm, address, pmdp, pmd);
>> return __pmd(xchg_relaxed(&pmd_val(*pmdp), pmd_val(pmd)));
>> }
>> #endif
> .
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK
2022-05-03 1:13 ` Tong Tiangen
@ 2022-05-04 17:26 ` Catalin Marinas
2022-05-05 6:46 ` Tong Tiangen
0 siblings, 1 reply; 11+ messages in thread
From: Catalin Marinas @ 2022-05-04 17:26 UTC (permalink / raw)
To: Tong Tiangen
Cc: Anshuman Khandual, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Pasha Tatashin, Andrew Morton,
Will Deacon, Paul Walmsley, Palmer Dabbelt, Albert Ou,
linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Kefeng Wang, Guohanjun
On Tue, May 03, 2022 at 09:13:20AM +0800, Tong Tiangen wrote:
> 在 2022/4/29 14:18, Anshuman Khandual 写道:
> > On 4/26/22 13:40, Tong Tiangen wrote:
> > > @@ -884,7 +928,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
> > > static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
> > > unsigned long address, pmd_t *pmdp)
> > > {
> > > - return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
> > > + pmd_t pmd = pte_pmd(__pte(xchg_relaxed(&pte_val(*(pte_t *)pmdp), 0)));
> >
> > Why there is any change here ? Why not just the following instead, like what you did
> > in ptep_get_and_clear() above. The page table entry return value here just needs to
> > be preserved for subsequent page table check helpers.
> >
> > pmd_t pmd = pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
>
> The purpose of what I do here is to avoid doing page_table_check_pte_clear()
> in ptep_get_and_clear(). there is no functional change here.
I'm fine with using xchg here but I'd go for pmd_val directly, no need
for conversion to pte_t:
pmd_t pmd = __pmd(xchg_relaxed(&pmd_val(*pmdp), 0));
--
Catalin
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK
2022-05-04 17:26 ` Catalin Marinas
@ 2022-05-05 6:46 ` Tong Tiangen
0 siblings, 0 replies; 11+ messages in thread
From: Tong Tiangen @ 2022-05-05 6:46 UTC (permalink / raw)
To: Catalin Marinas
Cc: Anshuman Khandual, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, x86, H. Peter Anvin, Pasha Tatashin, Andrew Morton,
Will Deacon, Paul Walmsley, Palmer Dabbelt, Albert Ou,
linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Kefeng Wang, Guohanjun
在 2022/5/5 1:26, Catalin Marinas 写道:
> On Tue, May 03, 2022 at 09:13:20AM +0800, Tong Tiangen wrote:
>> 在 2022/4/29 14:18, Anshuman Khandual 写道:
>>> On 4/26/22 13:40, Tong Tiangen wrote:
>>>> @@ -884,7 +928,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
>>>> static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
>>>> unsigned long address, pmd_t *pmdp)
>>>> {
>>>> - return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
>>>> + pmd_t pmd = pte_pmd(__pte(xchg_relaxed(&pte_val(*(pte_t *)pmdp), 0)));
>>>
>>> Why there is any change here ? Why not just the following instead, like what you did
>>> in ptep_get_and_clear() above. The page table entry return value here just needs to
>>> be preserved for subsequent page table check helpers.
>>>
>>> pmd_t pmd = pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
>>
>> The purpose of what I do here is to avoid doing page_table_check_pte_clear()
>> in ptep_get_and_clear(). there is no functional change here.
>
> I'm fine with using xchg here but I'd go for pmd_val directly, no need
> for conversion to pte_t:
>
> pmd_t pmd = __pmd(xchg_relaxed(&pmd_val(*pmdp), 0));
>
OK, This implementation is good and avoids redundant conversion, will
fix it next version.
Thanks,
Tong.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH -next v6 6/6] riscv/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK
2022-04-26 8:10 [PATCH -next v6 0/6]mm: page_table_check: add support on arm64 and riscv Tong Tiangen
` (4 preceding siblings ...)
2022-04-26 8:10 ` [PATCH -next v6 5/6] arm64/mm: Enable ARCH_SUPPORTS_PAGE_TABLE_CHECK Tong Tiangen
@ 2022-04-26 8:10 ` Tong Tiangen
5 siblings, 0 replies; 11+ messages in thread
From: Tong Tiangen @ 2022-04-26 8:10 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Pasha Tatashin, Anshuman Khandual, Andrew Morton,
Catalin Marinas, Will Deacon, Paul Walmsley, Palmer Dabbelt,
Albert Ou
Cc: linux-kernel, linux-mm, linux-arm-kernel, linux-riscv,
Tong Tiangen, Kefeng Wang, Guohanjun
As commit d283d422c6c4 ("x86: mm: add x86_64 support for page table check")
, enable ARCH_SUPPORTS_PAGE_TABLE_CHECK on riscv.
Add additional page table check stubs for page table helpers, these stubs
can be used to check the existing page table entries.
Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/pgtable.h | 71 +++++++++++++++++++++++++++++---
2 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 63f7258984f3..66d241cee52c 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -38,6 +38,7 @@ config RISCV
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
select ARCH_SUPPORTS_HUGETLBFS if MMU
+ select ARCH_SUPPORTS_PAGE_TABLE_CHECK
select ARCH_USE_MEMTEST
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
select ARCH_WANT_FRAME_POINTERS
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 046b44225623..5af8aebbdd92 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -114,6 +114,8 @@
#include <asm/pgtable-32.h>
#endif /* CONFIG_64BIT */
+#include <linux/page_table_check.h>
+
#ifdef CONFIG_XIP_KERNEL
#define XIP_FIXUP(addr) ({ \
uintptr_t __a = (uintptr_t)(addr); \
@@ -315,6 +317,11 @@ static inline int pte_exec(pte_t pte)
return pte_val(pte) & _PAGE_EXEC;
}
+static inline int pte_user(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_USER;
+}
+
static inline int pte_huge(pte_t pte)
{
return pte_present(pte) && (pte_val(pte) & _PAGE_LEAF);
@@ -446,7 +453,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
void flush_icache_pte(pte_t pte);
-static inline void set_pte_at(struct mm_struct *mm,
+static inline void __set_pte_at(struct mm_struct *mm,
unsigned long addr, pte_t *ptep, pte_t pteval)
{
if (pte_present(pteval) && pte_exec(pteval))
@@ -455,10 +462,17 @@ static inline void set_pte_at(struct mm_struct *mm,
set_pte(ptep, pteval);
}
+static inline void set_pte_at(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep, pte_t pteval)
+{
+ page_table_check_pte_set(mm, addr, ptep, pteval);
+ __set_pte_at(mm, addr, ptep, pteval);
+}
+
static inline void pte_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
{
- set_pte_at(mm, addr, ptep, __pte(0));
+ __set_pte_at(mm, addr, ptep, __pte(0));
}
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
@@ -479,7 +493,11 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma,
static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
unsigned long address, pte_t *ptep)
{
- return __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
+ pte_t pte = __pte(atomic_long_xchg((atomic_long_t *)ptep, 0));
+
+ page_table_check_pte_clear(mm, address, pte);
+
+ return pte;
}
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
@@ -546,6 +564,13 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
return ((__pmd_to_phys(pmd) & PMD_MASK) >> PAGE_SHIFT);
}
+#define __pud_to_phys(pud) (pud_val(pud) >> _PAGE_PFN_SHIFT << PAGE_SHIFT)
+
+static inline unsigned long pud_pfn(pud_t pud)
+{
+ return ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT);
+}
+
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
{
return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
@@ -567,6 +592,11 @@ static inline int pmd_young(pmd_t pmd)
return pte_young(pmd_pte(pmd));
}
+static inline int pmd_user(pmd_t pmd)
+{
+ return pte_user(pmd_pte(pmd));
+}
+
static inline pmd_t pmd_mkold(pmd_t pmd)
{
return pte_pmd(pte_mkold(pmd_pte(pmd)));
@@ -600,15 +630,39 @@ static inline pmd_t pmd_mkdirty(pmd_t pmd)
static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
pmd_t *pmdp, pmd_t pmd)
{
- return set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
+ page_table_check_pmd_set(mm, addr, pmdp, pmd);
+ return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd));
+}
+
+static inline int pud_user(pud_t pud)
+{
+ return pte_user(pud_pte(pud));
}
static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
pud_t *pudp, pud_t pud)
{
- return set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
+ page_table_check_pud_set(mm, addr, pudp, pud);
+ return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud));
+}
+
+#ifdef CONFIG_PAGE_TABLE_CHECK
+static inline bool pte_user_accessible_page(pte_t pte)
+{
+ return pte_present(pte) && pte_user(pte);
+}
+
+static inline bool pmd_user_accessible_page(pmd_t pmd)
+{
+ return pmd_leaf(pmd) && pmd_user(pmd);
}
+static inline bool pud_user_accessible_page(pud_t pud)
+{
+ return pud_leaf(pud) && pud_user(pud);
+}
+#endif
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline int pmd_trans_huge(pmd_t pmd)
{
@@ -634,7 +688,11 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
unsigned long address, pmd_t *pmdp)
{
- return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
+ pmd_t pmd = pte_pmd(__pte(atomic_long_xchg((atomic_long_t *)(pte_t *)pmdp, 0)));
+
+ page_table_check_pmd_clear(mm, address, pmd);
+
+ return pmd;
}
#define __HAVE_ARCH_PMDP_SET_WRPROTECT
@@ -648,6 +706,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
unsigned long address, pmd_t *pmdp, pmd_t pmd)
{
+ page_table_check_pmd_set(vma->vm_mm, address, pmdp, pmd);
return __pmd(atomic_long_xchg((atomic_long_t *)pmdp, pmd_val(pmd)));
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
--
2.25.1
^ permalink raw reply related [flat|nested] 11+ messages in thread