On Fri, Aug 20, 2021 at 11:11:41AM -0700, Yu-cheng Yu wrote: > @@ -1322,6 +1340,24 @@ static inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm, > static inline void pmdp_set_wrprotect(struct mm_struct *mm, > unsigned long addr, pmd_t *pmdp) > { > + /* > + * If Shadow Stack is enabled, pmd_wrprotect() moves _PAGE_DIRTY > + * to _PAGE_COW (see comments at pmd_wrprotect()). > + * When a thread reads a RW=1, Dirty=0 PMD and before changing it > + * to RW=0, Dirty=0, another thread could have written to the page > + * and the PMD is RW=1, Dirty=1 now. Use try_cmpxchg() to detect > + * PMD changes and update old_pmd, then try again. > + */ > + if (cpu_feature_enabled(X86_FEATURE_SHSTK)) { > + pmd_t old_pmd, new_pmd; > + > + old_pmd = READ_ONCE(*pmdp); > + do { > + new_pmd = pmd_wrprotect(old_pmd); > + } while (!try_cmpxchg((pmdval_t *)pmdp, (pmdval_t *)&old_pmd, pmd_val(new_pmd))); >From the previous thread: > If !(CONFIG_PGTABLE_LEVELS > 2), we don't have pmd_t.pmd. So I guess you can do this, in line with how the pmd folding is done in the rest of the mm headers. There's no need to make this more complex than it is just so that 32-bit !PAE builds but where CET is not even enabled. --- diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index df4ce715560a..7c0542997790 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1340,6 +1340,7 @@ static inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm, static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp) { +#if CONFIG_PGTABLE_LEVELS > 2 /* * If Shadow Stack is enabled, pmd_wrprotect() moves _PAGE_DIRTY * to _PAGE_COW (see comments at pmd_wrprotect()). @@ -1354,10 +1355,11 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, old_pmd = READ_ONCE(*pmdp); do { new_pmd = pmd_wrprotect(old_pmd); - } while (!try_cmpxchg((pmdval_t *)pmdp, (pmdval_t *)&old_pmd, pmd_val(new_pmd))); + } while (!try_cmpxchg(&pmdp->pmd, &old_pmd.pmd, new_pmd.pmd)); return; } +#endif clear_bit(_PAGE_BIT_RW, (unsigned long *)pmdp); } -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette