Rework the pte handling for hardware AF/DBM
Catalin Marinas
maintainerv2 cover Rework the pte handling for hardware AF/DBM
Hi,
That's the second version of the pte accessors reworking series (first version at [1]).
Changes since v1:
- READ_ONCE moved out of the cmpxchg loops since cmpxchg already returns the old value (probably more efficient with LSE atomics)
- The first patch from the first series has been merged upstream (cc stable)
- Kconfig entry kept just to disable the hardware feature but the code paths all assume hardware AF/DBM
- PAGE_COPY(_EXEC) removed as they just duplicate PAGE_READONLY(_EXEC)
I kept the review-by tags in place as the logic is unchanged but feel free to look at the patches again.
Thanks.
[1] http://lkml.kernel.org/r/20170725135308.18173-1-catalin.marinas at arm.com
Catalin Marinas (5):
arm64: Convert pte handling from inline asm to using (cmp)xchg
kvm: arm64: Convert kvm_set_s2pte_readonly() from inline asm to
cmpxchg()
arm64: Move PTE_RDONLY bit handling out of set_pte_at()
arm64: Ignore hardware dirty bit updates in ptep_set_wrprotect()
arm64: Remove the !CONFIG_ARM64_HW_AFDBM alternative code paths
arch/arm64/include/asm/kvm_mmu.h | 21 +++---- arch/arm64/include/asm/pgtable-prot.h | 18 +++--- arch/arm64/include/asm/pgtable.h | 103 ++++++++++++++-------------------- arch/arm64/kernel/hibernate.c | 4 +- arch/arm64/kvm/hyp/s2-setup.c | 2 +- arch/arm64/mm/fault.c | 30 ++++------ 6 files changed, 72 insertions(+), 106 deletions(-)
Catalin Marinas
maintainerPATCH v2 1/5 arm64: Convert pte handling from inline asm to using (cmp)xchg
With the support for hardware updates of the access and dirty states, the following pte handling functions had to be implemented using
exclusives: __ptep_test_and_clear_young(), ptep_get_and_clear(), ptep_set_wrprotect() and ptep_set_access_flags(). To take advantage of the LSE atomic instructions and also make the code cleaner, convert these pte functions to use the more generic cmpxchg()/xchg().
--- arch/arm64/include/asm/pgtable.h | 71 +++++++++++++++++++--------------------- arch/arm64/mm/fault.c | 24 +++++++------- 2 files changed, 44 insertions(+), 51 deletions(-)
arch/arm64/include/asm/pgtable.h +33 -38
@@ -39,6 +39,7 @@#ifndef __ASSEMBLY__ +#include <asm/cmpxchg.h> #include <asm/fixmap.h> #include <linux/mmdebug.h>
@@ -173,6 +174,11 @@ static inline pte_t pte_clear_rdonly(pte_t pte)return clear_pte_bit (pte,__pgprot (PTE_RDONLY )); } +static inline pte_t pte_set_rdonly (pte_t pte) +{ +return set_pte_bit (pte,__pgprot (PTE_RDONLY )); +} +static inline pte_t pte_mkpresent (pte_t pte) {return set_pte_bit (pte,__pgprot (PTE_VALID ));
@@ -593,20 +599,17 @@ static inline int pmdp_set_access_flags(struct vm_area_struct *vma,#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNGstatic inline int __ptep_test_and_clear_young (pte_t *ptep) { -pteval_t pteval; -unsigned int tmp, res; +pte_t old_pte, pte; - asmvolatile ("// __ptep_test_and_clear_young\n" -" prfm pstl1strm, %2\n" -"1: ldxr %0, %2\n" -" ubfx %w3, %w0, %5, #1 // extract PTE_AF (young)\n" -" and %0, %0, %4 // clear PTE_AF\n" -" stxr %w1, %0, %2\n" -" cbnz %w1, 1b\n" - :"=&r" (pteval),"=&r" (tmp),"+Q" (pte_val (*ptep)),"=&r" (res) - :"L" (~PTE_AF ),"I" (ilog2 (PTE_AF ))); + pte =READ_ONCE (*ptep); +do { + old_pte = pte; + pte =pte_mkold (pte); +pte_val (pte) =cmpxchg_relaxed (&pte_val (*ptep), +pte_val (old_pte),pte_val (pte)); + }while (pte_val (pte) !=pte_val (old_pte)); -return res; +return pte_young (pte); } static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
@@ -630,17 +633,7 @@ 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) { -pteval_t old_pteval; -unsigned int tmp; - - asmvolatile ("// ptep_get_and_clear\n" -" prfm pstl1strm, %2\n" -"1: ldxr %0, %2\n" -" stxr %w1, xzr, %2\n" -" cbnz %w1, 1b\n" - :"=&r" (old_pteval),"=&r" (tmp),"+Q" (pte_val (*ptep))); - -return __pte (old_pteval); +return __pte (xchg_relaxed (&pte_val (*ptep),0 )); }#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -659,21 +652,23 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,#define __HAVE_ARCH_PTEP_SET_WRPROTECTstatic inline void ptep_set_wrprotect (struct mm_struct *mm,unsigned long address,pte_t *ptep) { -pteval_t pteval; -unsigned long tmp; - - asmvolatile ("// ptep_set_wrprotect\n" -" prfm pstl1strm, %2\n" -"1: ldxr %0, %2\n" -" tst %0, %4 // check for hw dirty (!PTE_RDONLY)\n" -" csel %1, %3, xzr, eq // set PTE_DIRTY|PTE_RDONLY if dirty\n" -" orr %0, %0, %1 // if !dirty, PTE_RDONLY is already set\n" -" and %0, %0, %5 // clear PTE_WRITE/PTE_DBM\n" -" stxr %w1, %0, %2\n" -" cbnz %w1, 1b\n" - :"=&r" (pteval),"=&r" (tmp),"+Q" (pte_val (*ptep)) - :"r" (PTE_DIRTY |PTE_RDONLY ),"L" (PTE_RDONLY ),"L" (~PTE_WRITE ) - :"cc" ); +pte_t old_pte, pte; + + pte =READ_ONCE (*ptep); +do { + old_pte = pte; +/* +* If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY +* clear), set the PTE_DIRTY and PTE_RDONLY bits. +*/ +if (pte_hw_dirty (pte)) { + pte =pte_mkdirty (pte); + pte =pte_set_rdonly (pte); + } + pte =pte_wrprotect (pte); +pte_val (pte) =cmpxchg_relaxed (&pte_val (*ptep), +pte_val (old_pte),pte_val (pte)); + }while (pte_val (pte) !=pte_val (old_pte)); }#ifdef CONFIG_TRANSPARENT_HUGEPAGE
arch/arm64/mm/fault.c +11 -13
@@ -34,6 +34,7 @@#include <linux/hugetlb.h> #include <asm/bug.h> +#include <asm/cmpxchg.h> #include <asm/cpufeature.h> #include <asm/exception.h> #include <asm/debug-monitors.h>
@@ -154,8 +155,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, pte_t *ptep, pte_t entry, int dirty) { - pteval_t old_pteval; -unsigned int tmp; + pteval_t old_pteval, pteval;if (pte_same (*ptep, entry))return 0 ;
@@ -165,7 +165,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,/* set PTE_RDONLY if actual read-only or clean PTE */ if (!pte_write (entry) || !pte_sw_dirty (entry)) -pte_val (entry) |=PTE_RDONLY ; + entry =pte_set_rdonly (entry);/* * Setting the flags must be done atomically to avoid racing with the
@@ -174,16 +174,14 @@ int ptep_set_access_flags(struct vm_area_struct *vma,* (calculated as: a & b == ~(~a | ~b)). */ pte_val (entry) ^=PTE_RDONLY ; - asmvolatile ("// ptep_set_access_flags\n" -" prfm pstl1strm, %2\n" -"1: ldxr %0, %2\n" -" eor %0, %0, %3 // negate PTE_RDONLY in *ptep\n" -" orr %0, %0, %4 // set flags\n" -" eor %0, %0, %3 // negate final PTE_RDONLY\n" -" stxr %w1, %0, %2\n" -" cbnz %w1, 1b\n" - :"=&r" (old_pteval),"=&r" (tmp),"+Q" (pte_val (*ptep)) - :"L" (PTE_RDONLY ),"r" (pte_val (entry))); + pteval =READ_ONCE (pte_val (*ptep)); +do { + old_pteval = pteval; + pteval ^=PTE_RDONLY ; + pteval |=pte_val (entry); + pteval ^=PTE_RDONLY ; + pteval =cmpxchg_relaxed (&pte_val (*ptep), old_pteval, pteval); + }while (pteval != old_pteval);flush_tlb_fix_spurious_fault (vma, address);return 1 ;
Catalin Marinas
maintainerPATCH v2 2/5 kvm: arm64: Convert kvm_set_s2pte_readonly() from inline asm to cmpxchg()
In reply to Catalin MarinasTo take advantage of the LSE atomic instructions and also make the code cleaner, convert the kvm_set_s2pte_readonly() function to use the more generic cmpxchg().
--- arch/arm64/include/asm/kvm_mmu.h | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-)
arch/arm64/include/asm/kvm_mmu.h +9 -12
@@ -175,18 +175,15 @@ static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)static inline void kvm_set_s2pte_readonly (pte_t *pte) { -pteval_t pteval; -unsigned long tmp; - - asmvolatile ("// kvm_set_s2pte_readonly\n" -" prfm pstl1strm, %2\n" -"1: ldxr %0, %2\n" -" and %0, %0, %3 // clear PTE_S2_RDWR\n" -" orr %0, %0, %4 // set PTE_S2_RDONLY\n" -" stxr %w1, %0, %2\n" -" cbnz %w1, 1b\n" - :"=&r" (pteval),"=&r" (tmp),"+Q" (pte_val (*pte)) - :"L" (~PTE_S2_RDWR ),"L" (PTE_S2_RDONLY )); +pteval_t old_pteval, pteval; + + pteval =READ_ONCE (pte_val (*pte)); +do { + old_pteval = pteval; + pteval &= ~PTE_S2_RDWR ; + pteval |=PTE_S2_RDONLY ; + pteval =cmpxchg_relaxed (&pte_val (*pte), old_pteval, pteval); + }while (pteval != old_pteval); }static inline bool kvm_s2pte_readonly (pte_t *pte)
Catalin Marinas
maintainerPATCH v2 3/5 arm64: Move PTE_RDONLY bit handling out of set_pte_at()
In reply to Catalin MarinasCurrently PTE_RDONLY is treated as a hardware only bit and not handled by the pte_mkwrite(), pte_wrprotect() or the user PAGE_* definitions. The set_pte_at() function is responsible for setting this bit based on the write permission or dirty state. This patch moves the PTE_RDONLY handling out of set_pte_at into the pte_mkwrite()/pte_wrprotect() functions. The PAGE_* definitions to need to be updated to explicitly include PTE_RDONLY when !PTE_WRITE.
The patch also removes the redundant PAGE_COPY(_EXEC) definitions as they are identical to the corresponding PAGE_READONLY(_EXEC).
--- arch/arm64/include/asm/pgtable-prot.h | 18 ++++++++---------- arch/arm64/include/asm/pgtable.h | 34 ++++++++++------------------------ arch/arm64/kernel/hibernate.c | 4 ++-- arch/arm64/mm/fault.c | 6 +----- 4 files changed, 21 insertions(+), 41 deletions(-)
arch/arm64/include/asm/pgtable-prot.h +8 -10
@@ -63,23 +63,21 @@#define PAGE_S2 __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY)#define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN) -#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_PXN | PTE_UXN) +#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN)#define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)#define PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE) -#define PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) -#define PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) -#define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) -#define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) -#define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN) +#define PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) +#define PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN) +#define PAGE_EXECONLY __pgprot(_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN)#define __P000 PAGE_NONE#define __P001 PAGE_READONLY -#define __P010 PAGE_COPY -#define __P011 PAGE_COPY +#define __P010 PAGE_READONLY +#define __P011 PAGE_READONLY#define __P100 PAGE_EXECONLY#define __P101 PAGE_READONLY_EXEC -#define __P110 PAGE_COPY_EXEC -#define __P111 PAGE_COPY_EXEC +#define __P110 PAGE_READONLY_EXEC +#define __P111 PAGE_READONLY_EXEC#define __S000 PAGE_NONE#define __S001 PAGE_READONLY
arch/arm64/include/asm/pgtable.h +10 -24
@@ -125,12 +125,16 @@ static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot)static inline pte_t pte_wrprotect (pte_t pte) { -return clear_pte_bit (pte,__pgprot (PTE_WRITE )); + pte =clear_pte_bit (pte,__pgprot (PTE_WRITE )); + pte =set_pte_bit (pte,__pgprot (PTE_RDONLY )); +return pte; }static inline pte_t pte_mkwrite (pte_t pte) { -return set_pte_bit (pte,__pgprot (PTE_WRITE )); + pte =set_pte_bit (pte,__pgprot (PTE_WRITE )); + pte =clear_pte_bit (pte,__pgprot (PTE_RDONLY )); +return pte; }static inline pte_t pte_mkclean (pte_t pte)
@@ -169,16 +173,6 @@ static inline pte_t pte_mknoncont(pte_t pte)return clear_pte_bit (pte,__pgprot (PTE_CONT )); } -static inline pte_t pte_clear_rdonly (pte_t pte) -{ -return clear_pte_bit (pte,__pgprot (PTE_RDONLY )); -} - -static inline pte_t pte_set_rdonly (pte_t pte) -{ -return set_pte_bit (pte,__pgprot (PTE_RDONLY )); -} -static inline pte_t pte_mkpresent (pte_t pte) {return set_pte_bit (pte,__pgprot (PTE_VALID ));
@@ -226,14 +220,8 @@ extern void __sync_icache_dcache(pte_t pteval, 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)) { -if (pte_sw_dirty (pte) &&pte_write (pte)) -pte_val (pte) &= ~PTE_RDONLY ; -else -pte_val (pte) |=PTE_RDONLY ; -if (pte_user_exec (pte) && !pte_special (pte)) -__sync_icache_dcache (pte, addr); - } +if (pte_present (pte) &&pte_user_exec (pte) && !pte_special (pte)) +__sync_icache_dcache (pte, addr);/* * If the existing pte is valid, check for potential race with
@@ -659,12 +647,10 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres old_pte = pte;/* * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY -* clear), set the PTE_DIRTY and PTE_RDONLY bits. +* clear), set the PTE_DIRTY bit. */ -if (pte_hw_dirty (pte)) { +if (pte_hw_dirty (pte)) pte =pte_mkdirty (pte); - pte =pte_set_rdonly (pte); - } pte =pte_wrprotect (pte);pte_val (pte) =cmpxchg_relaxed (&pte_val (*ptep),pte_val (old_pte),pte_val (pte));
arch/arm64/kernel/hibernate.c +2 -2
@@ -330,7 +330,7 @@ static void _copy_pte(pte_t *dst_pte, pte_t *src_pte, unsigned long addr)* read only (code, rodata). Clear the RDONLY bit from * the temporary mappings we use during restore. */ -set_pte (dst_pte,pte_clear_rdonly (pte)); +set_pte (dst_pte,pte_mkwrite (pte)); }else if (debug_pagealloc_enabled () && !pte_none (pte)) {/* * debug_pagealloc will removed the PTE_VALID bit if
@@ -343,7 +343,7 @@ static void _copy_pte(pte_t *dst_pte, pte_t *src_pte, unsigned long addr)*/ BUG_ON (!pfn_valid (pte_pfn (pte))); -set_pte (dst_pte,pte_mkpresent (pte_clear_rdonly (pte))); +set_pte (dst_pte,pte_mkpresent (pte_mkwrite (pte))); } }
arch/arm64/mm/fault.c +1 -5
@@ -161,11 +161,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,return 0 ;/* only preserve the access flags and write permission */ -pte_val (entry) &=PTE_AF |PTE_WRITE |PTE_DIRTY ; - -/* set PTE_RDONLY if actual read-only or clean PTE */ -if (!pte_write (entry) || !pte_sw_dirty (entry)) - entry =pte_set_rdonly (entry); +pte_val (entry) &=PTE_RDONLY |PTE_AF |PTE_WRITE |PTE_DIRTY ;/* * Setting the flags must be done atomically to avoid racing with the
Catalin Marinas
maintainerPATCH v2 4/5 arm64: Ignore hardware dirty bit updates in ptep_set_wrprotect()
In reply to Catalin Marinasptep_set_wrprotect() is only called on CoW mappings which are private (!VM_SHARED) with the pte either read-only (!PTE_WRITE && PTE_RDONLY) or writable and software-dirty (PTE_WRITE && !PTE_RDONLY && PTE_DIRTY). There is no race with the hardware update of the dirty state: clearing of PTE_RDONLY when PTE_WRITE (a.k.a. PTE_DBM) is set. This patch removes the code setting the software PTE_DIRTY bit in ptep_set_wrprotect() as superfluous. A VM_WARN_ONCE is introduced in case the above logic is wrong or the core mm code changes its use of ptep_set_wrprotect().
--- arch/arm64/include/asm/pgtable.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
arch/arm64/include/asm/pgtable.h +13 -8
@@ -634,23 +634,28 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ /* -* ptep_set_wrprotect - mark read-only while trasferring potential hardware -* dirty status (PTE_DBM && !PTE_RDONLY) to the software PTE_DIRTY bit. +* ptep_set_wrprotect - mark read-only while preserving the hardware update of +* the Access Flag. */ #define __HAVE_ARCH_PTEP_SET_WRPROTECTstatic inline void ptep_set_wrprotect (struct mm_struct *mm,unsigned long address,pte_t *ptep) {pte_t old_pte, pte; +/* +* ptep_set_wrprotect() is only called on CoW mappings which are +* private (!VM_SHARED) with the pte either read-only (!PTE_WRITE && +* PTE_RDONLY) or writable and software-dirty (PTE_WRITE && +* !PTE_RDONLY && PTE_DIRTY); see is_cow_mapping() and +* protection_map[]. There is no race with the hardware update of the +* dirty state: clearing of PTE_RDONLY when PTE_WRITE (a.k.a. PTE_DBM) +* is set. +*/ +VM_WARN_ONCE (pte_write (*ptep) && !pte_dirty (*ptep), +"%s: potential race with hardware DBM" , __func__); pte =READ_ONCE (*ptep); do { old_pte = pte; - /* - * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY - * clear), set the PTE_DIRTY bit. - */ - if (pte_hw_dirty(pte)) - pte = pte_mkdirty(pte); pte = pte_wrprotect(pte); pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep), pte_val(old_pte), pte_val(pte));
Catalin Marinas
maintainerPATCH v2 5/5 arm64: Remove the !CONFIG_ARM64_HW_AFDBM alternative code paths
In reply to Catalin MarinasSince the pte handling for hardware AF/DBM works even when the hardware feature is not present, make the pte accessors implementation permanent and remove the corresponding #ifdefs. The Kconfig option is kept as it can still be used to disable the feature at the hardware level.
--- arch/arm64/include/asm/pgtable.h | 9 +-------- arch/arm64/kvm/hyp/s2-setup.c | 2 +- arch/arm64/mm/fault.c | 2 -- 3 files changed, 2 insertions(+), 11 deletions(-)
arch/arm64/include/asm/pgtable.h +1 -8
@@ -85,11 +85,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; (__boundary -1 < (end) -1 ) ? __boundary : (end); \ }) -#ifdef CONFIG_ARM64_HW_AFDBM #define pte_hw_dirty (pte) (pte_write(pte) && !(pte_val(pte) & PTE_RDONLY)) -#else -#define pte_hw_dirty (pte) (0) -#endif #define pte_sw_dirty (pte) (!!(pte_val(pte) & PTE_DIRTY))#define pte_dirty (pte) (pte_sw_dirty(pte) || pte_hw_dirty(pte))
@@ -228,8 +224,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,* hardware updates of the pte (ptep_set_access_flags safely changes * valid ptes without going through an invalid entry). */ -if (IS_ENABLED (CONFIG_ARM64_HW_AFDBM ) && -pte_valid (*ptep) &&pte_valid (pte)) { +if (pte_valid (*ptep) &&pte_valid (pte)) {VM_WARN_ONCE (!pte_young (pte),"%s: racy access flag clearing: 0x%016llx -> 0x%016llx" , __func__,pte_val (*ptep),pte_val (pte));
@@ -565,7 +560,6 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)return pte_pmd (pte_modify (pmd_pte (pmd), newprot)); } -#ifdef CONFIG_ARM64_HW_AFDBM #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, pte_t *ptep,
@@ -670,7 +664,6 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, ptep_set_wrprotect(mm, address, (pte_t *)pmdp); }#endif -#endif /* CONFIG_ARM64_HW_AFDBM */ extern pgd_t swapper_pg_dir[PTRS_PER_PGD ];extern pgd_t idmap_pg_dir[PTRS_PER_PGD ];
arch/arm64/kvm/hyp/s2-setup.c +1 -1
@@ -70,7 +70,7 @@ u32 __hyp_text __init_stage2_translation(void)* Management in ID_AA64MMFR1_EL1 and enable the feature in VTCR_EL2. */ tmp = (read_sysreg (id_aa64mmfr1_el1) >>ID_AA64MMFR1_HADBS_SHIFT ) &0xf ; -if (IS_ENABLED (CONFIG_ARM64_HW_AFDBM ) && tmp) +if (tmp) val |=VTCR_EL2_HA ;/*
arch/arm64/mm/fault.c +0 -2
@@ -140,7 +140,6 @@ void show_pte(unsigned long addr)pr_cont ("\n" ); } -#ifdef CONFIG_ARM64_HW_AFDBM /* * This function sets the access flags (dirty, accessed), as well as write * permission, and only to a more permissive setting.
@@ -182,7 +181,6 @@ int ptep_set_access_flags(struct vm_area_struct *vma,flush_tlb_fix_spurious_fault (vma, address);return 1 ; } -#endif static bool is_el1_instruction_abort (unsigned int esr) {
v2 cover Rework the pte handling for hardware AF/DBM
In reply to Catalin MarinasQuoted 11 lines · Catalin Marinas
That's the second version of the pte accessors reworking series (first version at [1]).
Changes since v1:
-
READ_ONCEmoved out of the cmpxchg loops since cmpxchg already returns the old value (probably more efficient with LSE atomics)- The first patch from the first series has been merged upstream (cc stable)
Quoted 7 lines
-
Kconfigentry kept just to disable the hardware feature but the code paths all assume hardware AF/DBM-
PAGE_COPY(_EXEC)removed as they just duplicatePAGE_READONLY(_EXEC)I kept the review-by tags in place as the logic is unchanged but feel free to look at the patches again.
Thanks, this looks good to me now:
Will
Catalin Marinas
maintainerv2 cover Rework the pte handling for hardware AF/DBM
Quoted 15 lines · Will Deacon
Quoted 14 lines · Catalin Marinas
That's the second version of the pte accessors reworking series (first version at [1]).
Changes since v1:
-
READ_ONCEmoved out of the cmpxchg loops since cmpxchg already returns the old value (probably more efficient with LSE atomics)- The first patch from the first series has been merged upstream (cc stable)
-
Kconfigentry kept just to disable the hardware feature but the code paths all assume hardware AF/DBM
Quoted 8 lines
Quoted 4 lines
-
PAGE_COPY(_EXEC)removed as they just duplicatePAGE_READONLY(_EXEC)I kept the review-by tags in place as the logic is unchanged but feel free to look at the patches again.
Thanks, this looks good to me now:
Reviewed-by Will Deacon <[email protected]>
Thanks. I merged them into for-next/core.
Signature · 1 line
Catalin