Message ID | 20240830011101.3189522-4-zhangchunyan@iscas.ac.cn (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | riscv: mm: Add soft-dirty and uffd-wp support | expand |
On 2024/8/30 9:11, Chunyan Zhang wrote: > Reuse PTE bit(9) to do uffd-wp tracking and make it mutually exclusive > with soft-dirty and DEVMAP which all use this PTE bit. > > Additionally for tracking the uffd-wp state as a PTE swap bit, > we use swap entry pte bit(4) which is also used by swap > soft-dirty tracking. > > Signed-off-by: Chunyan Zhang <zhangchunyan@iscas.ac.cn> Hi, I have submitted a similar patch below before rebased on commit 216e04bf1e4d ("riscv: mm: Add support for ZONE_DEVICE") has been removed: https://lore.kernel.org/all/20240730095325.3540198-1-ruanjinjie@huawei.com/ > --- > arch/riscv/Kconfig | 7 +++ > arch/riscv/include/asm/pgtable-bits.h | 13 ++++++ > arch/riscv/include/asm/pgtable.h | 66 ++++++++++++++++++++++++++- > 3 files changed, 85 insertions(+), 1 deletion(-) > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index f1460fc01cd4..aa595a5ed4b8 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -971,6 +971,13 @@ config RISCV_HAS_SOFT_DIRTY > help > The PTE bit(9) is used for soft-dirty tracking. > > +config RISCV_HAS_USERFAULTFD_WP > + bool "userfaultfd write protection" > + select HAVE_ARCH_USERFAULTFD_WP > + depends on USERFAULTFD > + help > + The PTE bit(9) is used for userfaultfd write-protected > + tracking. > endchoice > > endmenu # "Kernel features" > diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h > index c6d51fe9fc6f..7de16141c049 100644 > --- a/arch/riscv/include/asm/pgtable-bits.h > +++ b/arch/riscv/include/asm/pgtable-bits.h > @@ -38,6 +38,19 @@ > #define _PAGE_SWP_SOFT_DIRTY 0 > #endif /* CONFIG_MEM_SOFT_DIRTY */ > > +#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP > +/* > + * CONFIG_HAVE_ARCH_USERFAULTFD_WP is mutually exclusive with > + * HAVE_ARCH_SOFT_DIRTY so we can use the same bit for uffd-wp > + * and soft-dirty tracking. > + */ > +#define _PAGE_UFFD_WP (1 << 9) /* RSW: 0x2 for uffd-wp tracking */ > +#define _PAGE_SWP_UFFD_WP _PAGE_USER > +#else > +#define _PAGE_UFFD_WP 0 > +#define _PAGE_SWP_UFFD_WP 0 > +#endif > + > #define _PAGE_TABLE _PAGE_PRESENT > > /* > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h > index d41507919ef2..6ce4c9ba862a 100644 > --- a/arch/riscv/include/asm/pgtable.h > +++ b/arch/riscv/include/asm/pgtable.h > @@ -417,6 +417,38 @@ static inline pte_t pte_wrprotect(pte_t pte) > return __pte(pte_val(pte) & ~(_PAGE_WRITE)); > } > > +#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP > +static inline int pte_uffd_wp(pte_t pte) > +{ > + return pte_val(pte) & _PAGE_UFFD_WP; > +} > + > +static inline pte_t pte_mkuffd_wp(pte_t pte) > +{ > + return pte_wrprotect(__pte(pte_val(pte) | _PAGE_UFFD_WP)); > +} > + > +static inline pte_t pte_clear_uffd_wp(pte_t pte) > +{ > + return __pte(pte_val(pte) & ~(_PAGE_UFFD_WP)); > +} > + > +static inline int pte_swp_uffd_wp(pte_t pte) > +{ > + return pte_val(pte) & _PAGE_SWP_UFFD_WP; > +} > + > +static inline pte_t pte_swp_mkuffd_wp(pte_t pte) > +{ > + return pte_wrprotect(__pte(pte_val(pte) | _PAGE_SWP_UFFD_WP)); > +} > + > +static inline pte_t pte_swp_clear_uffd_wp(pte_t pte) > +{ > + return __pte(pte_val(pte) & ~(_PAGE_SWP_UFFD_WP)); > +} > +#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_WP */ > + > /* static inline pte_t pte_mkread(pte_t pte) */ > > static inline pte_t pte_mkwrite_novma(pte_t pte) > @@ -783,6 +815,38 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd) > return pte_pmd(pte_mkdevmap(pmd_pte(pmd))); > } > > +#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP > +static inline int pmd_uffd_wp(pmd_t pmd) > +{ > + return pte_uffd_wp(pmd_pte(pmd)); > +} > + > +static inline pmd_t pmd_mkuffd_wp(pmd_t pmd) > +{ > + return pte_pmd(pte_mkuffd_wp(pmd_pte(pmd))); > +} > + > +static inline pmd_t pmd_clear_uffd_wp(pmd_t pmd) > +{ > + return pte_pmd(pte_clear_uffd_wp(pmd_pte(pmd))); > +} > + > +static inline int pmd_swp_uffd_wp(pmd_t pmd) > +{ > + return pte_swp_uffd_wp(pmd_pte(pmd)); > +} > + > +static inline pmd_t pmd_swp_mkuffd_wp(pmd_t pmd) > +{ > + return pte_pmd(pte_swp_mkuffd_wp(pmd_pte(pmd))); > +} > + > +static inline pmd_t pmd_swp_clear_uffd_wp(pmd_t pmd) > +{ > + return pte_pmd(pte_swp_clear_uffd_wp(pmd_pte(pmd))); > +} > +#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_WP */ > + > #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY > static inline int pmd_soft_dirty(pmd_t pmd) > { > @@ -907,7 +971,7 @@ extern pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, > * Format of swap PTE: > * bit 0: _PAGE_PRESENT (zero) > * bit 1 to 3: _PAGE_LEAF (zero) > - * bit 4: _PAGE_SWP_SOFT_DIRTY > + * bit 4: _PAGE_SWP_SOFT_DIRTY or _PAGE_SWP_UFFD_WP > * bit 5: _PAGE_PROT_NONE (zero) > * bit 6: exclusive marker > * bits 7 to 11: swap type
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index f1460fc01cd4..aa595a5ed4b8 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -971,6 +971,13 @@ config RISCV_HAS_SOFT_DIRTY help The PTE bit(9) is used for soft-dirty tracking. +config RISCV_HAS_USERFAULTFD_WP + bool "userfaultfd write protection" + select HAVE_ARCH_USERFAULTFD_WP + depends on USERFAULTFD + help + The PTE bit(9) is used for userfaultfd write-protected + tracking. endchoice endmenu # "Kernel features" diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h index c6d51fe9fc6f..7de16141c049 100644 --- a/arch/riscv/include/asm/pgtable-bits.h +++ b/arch/riscv/include/asm/pgtable-bits.h @@ -38,6 +38,19 @@ #define _PAGE_SWP_SOFT_DIRTY 0 #endif /* CONFIG_MEM_SOFT_DIRTY */ +#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP +/* + * CONFIG_HAVE_ARCH_USERFAULTFD_WP is mutually exclusive with + * HAVE_ARCH_SOFT_DIRTY so we can use the same bit for uffd-wp + * and soft-dirty tracking. + */ +#define _PAGE_UFFD_WP (1 << 9) /* RSW: 0x2 for uffd-wp tracking */ +#define _PAGE_SWP_UFFD_WP _PAGE_USER +#else +#define _PAGE_UFFD_WP 0 +#define _PAGE_SWP_UFFD_WP 0 +#endif + #define _PAGE_TABLE _PAGE_PRESENT /* diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index d41507919ef2..6ce4c9ba862a 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -417,6 +417,38 @@ static inline pte_t pte_wrprotect(pte_t pte) return __pte(pte_val(pte) & ~(_PAGE_WRITE)); } +#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP +static inline int pte_uffd_wp(pte_t pte) +{ + return pte_val(pte) & _PAGE_UFFD_WP; +} + +static inline pte_t pte_mkuffd_wp(pte_t pte) +{ + return pte_wrprotect(__pte(pte_val(pte) | _PAGE_UFFD_WP)); +} + +static inline pte_t pte_clear_uffd_wp(pte_t pte) +{ + return __pte(pte_val(pte) & ~(_PAGE_UFFD_WP)); +} + +static inline int pte_swp_uffd_wp(pte_t pte) +{ + return pte_val(pte) & _PAGE_SWP_UFFD_WP; +} + +static inline pte_t pte_swp_mkuffd_wp(pte_t pte) +{ + return pte_wrprotect(__pte(pte_val(pte) | _PAGE_SWP_UFFD_WP)); +} + +static inline pte_t pte_swp_clear_uffd_wp(pte_t pte) +{ + return __pte(pte_val(pte) & ~(_PAGE_SWP_UFFD_WP)); +} +#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_WP */ + /* static inline pte_t pte_mkread(pte_t pte) */ static inline pte_t pte_mkwrite_novma(pte_t pte) @@ -783,6 +815,38 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd) return pte_pmd(pte_mkdevmap(pmd_pte(pmd))); } +#ifdef CONFIG_HAVE_ARCH_USERFAULTFD_WP +static inline int pmd_uffd_wp(pmd_t pmd) +{ + return pte_uffd_wp(pmd_pte(pmd)); +} + +static inline pmd_t pmd_mkuffd_wp(pmd_t pmd) +{ + return pte_pmd(pte_mkuffd_wp(pmd_pte(pmd))); +} + +static inline pmd_t pmd_clear_uffd_wp(pmd_t pmd) +{ + return pte_pmd(pte_clear_uffd_wp(pmd_pte(pmd))); +} + +static inline int pmd_swp_uffd_wp(pmd_t pmd) +{ + return pte_swp_uffd_wp(pmd_pte(pmd)); +} + +static inline pmd_t pmd_swp_mkuffd_wp(pmd_t pmd) +{ + return pte_pmd(pte_swp_mkuffd_wp(pmd_pte(pmd))); +} + +static inline pmd_t pmd_swp_clear_uffd_wp(pmd_t pmd) +{ + return pte_pmd(pte_swp_clear_uffd_wp(pmd_pte(pmd))); +} +#endif /* CONFIG_HAVE_ARCH_USERFAULTFD_WP */ + #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY static inline int pmd_soft_dirty(pmd_t pmd) { @@ -907,7 +971,7 @@ extern pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, * Format of swap PTE: * bit 0: _PAGE_PRESENT (zero) * bit 1 to 3: _PAGE_LEAF (zero) - * bit 4: _PAGE_SWP_SOFT_DIRTY + * bit 4: _PAGE_SWP_SOFT_DIRTY or _PAGE_SWP_UFFD_WP * bit 5: _PAGE_PROT_NONE (zero) * bit 6: exclusive marker * bits 7 to 11: swap type
Reuse PTE bit(9) to do uffd-wp tracking and make it mutually exclusive with soft-dirty and DEVMAP which all use this PTE bit. Additionally for tracking the uffd-wp state as a PTE swap bit, we use swap entry pte bit(4) which is also used by swap soft-dirty tracking. Signed-off-by: Chunyan Zhang <zhangchunyan@iscas.ac.cn> --- arch/riscv/Kconfig | 7 +++ arch/riscv/include/asm/pgtable-bits.h | 13 ++++++ arch/riscv/include/asm/pgtable.h | 66 ++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 1 deletion(-)