[RFC PATCH 4/4] s390/mm: implement __ptent-aware pte_t type
Alexander Gordeev <[email protected]> Fri, 17 Jul 2026 15:32:22 +0200
| Newsgroups | org.kernel.vger.linux-sparse,org.kernel.vger.linux-kernel,org.kernel.vger.linux-s390,org.kvack.linux-mm |
|---|---|
| Message-ID | <2580c0c643125fb89247f255ff42803bea44e4c3.1784292223.git.agordeev@linux.ibm.com> |
Signed-off-by: Alexander Gordeev <[email protected]> --- arch/s390/include/asm/page.h | 16 ++++++++++-- arch/s390/include/asm/pgtable.h | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index 56da819a79e6..ce68994a0292 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -76,8 +76,10 @@ static inline void copy_page(void *to, void *from) =20 #ifdef STRICT_MM_TYPECHECKS =20 +typedef struct { unsigned long pte; } pteraw_t; +typedef pteraw_t __ptent pte_t; + typedef struct { unsigned long pgprot; } pgprot_t; -typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pmd; } pmd_t; typedef struct { unsigned long pud; } pud_t; typedef struct { unsigned long p4d; } p4d_t; @@ -89,6 +91,11 @@ static __always_inline unsigned long name ## _val(name= ## _t name) \ return name.name; \ } =20 +static inline unsigned long pte_val(pte_t pte) +{ + return ((__force pteraw_t *)&pte)->pte; +} + #else /* STRICT_MM_TYPECHECKS */ =20 typedef unsigned long pgprot_t; @@ -98,6 +105,11 @@ typedef unsigned long pud_t; typedef unsigned long p4d_t; typedef unsigned long pgd_t; =20 +static inline unsigned long pte_val(pte_t pte) +{ + return pte; +} + #define DEFINE_PGVAL_FUNC(name) \ static __always_inline unsigned long name ## _val(name ## _t name) \ { \ @@ -107,7 +119,6 @@ static __always_inline unsigned long name ## _val(nam= e ## _t name) \ #endif /* STRICT_MM_TYPECHECKS */ =20 DEFINE_PGVAL_FUNC(pgprot) -DEFINE_PGVAL_FUNC(pte) DEFINE_PGVAL_FUNC(pmd) DEFINE_PGVAL_FUNC(pud) DEFINE_PGVAL_FUNC(p4d) @@ -116,6 +127,7 @@ DEFINE_PGVAL_FUNC(pgd) typedef pte_t *pgtable_t; =20 #define __pgprot(x) ((pgprot_t) { (x) } ) +#define __pteraw(x) ((pteraw_t) { (x) } ) #define __pte(x) ((pte_t) { (x) } ) #define __pmd(x) ((pmd_t) { (x) } ) #define __pud(x) ((pud_t) { (x) } ) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgta= ble.h index 859ce7c7d454..6398f58c09ce 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -978,6 +978,49 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) WRITE_ONCE(*pmdp, pmd); } =20 +#ifdef STRICT_MM_TYPECHECKS +static inline void set_pte(pte_t *ptep, pte_t pte) +{ + pteraw_t *pteraw_ptep =3D (__force pteraw_t *)ptep; + pteraw_t pteraw =3D __pteraw(pte_val(pte)); + + if (pte_present(pte)) + pte =3D clear_pte_bit(pte, __pgprot(_PAGE_UNUSED)); + WRITE_ONCE(*pteraw_ptep, pteraw); +} + +#define ptep_get ptep_get +static inline pte_t ptep_get(pte_t *ptep) +{ + pteraw_t *pteraw_ptep =3D (__force pteraw_t *)ptep; + pteraw_t pteraw =3D READ_ONCE(*pteraw_ptep); + + return __pte(pteraw.pte); +} + +#define ptep_get_nopgtable ptep_get_nopgtable +static inline pte_t ptep_get_nopgtable(pte_t *ptep) +{ + /* + * Ensure this is a pointer to a copy not a pointer into a page table. + * If this is a stack value, it won't be a valid virtual address, but + * that's fine because it also cannot be pointing into the page table. + */ + VM_WARN_ON(virt_addr_valid(ptep) && PageTable(virt_to_page(ptep))); + + return (__force pte_t)(*(pteraw_t *)ptep); +} + +#define set_pte_nopgtable set_pte_nopgtable +static inline void set_pte_nopgtable(pte_t *ptep, pte_t pte) +{ + /* + * See comment in ptep_get_nopgtable(). + */ + VM_WARN_ON(virt_addr_valid(ptep) && PageTable(virt_to_page(ptep))); + *(pteraw_t *)ptep =3D (__force pteraw_t)pte; +} +#else static inline void set_pte(pte_t *ptep, pte_t pte) { if (pte_present(pte)) @@ -990,6 +1033,7 @@ static inline pte_t ptep_get(pte_t *ptep) { return READ_ONCE(*ptep); } +#endif =20 #define pmdp_get pmdp_get static inline pmd_t pmdp_get(pmd_t *pmdp) --=20 2.53.0