[RFC PATCH 4/4] s390/mm: implement __ptent-aware pte_t type
From: Alexander Gordeev
Date: Fri Jul 17 2026 - 09:36:49 EST
Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxxxxx>
---
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)
#ifdef STRICT_MM_TYPECHECKS
+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; \
}
+static inline unsigned long pte_val(pte_t pte)
+{
+ return ((__force pteraw_t *)&pte)->pte;
+}
+
#else /* STRICT_MM_TYPECHECKS */
typedef unsigned long pgprot_t;
@@ -98,6 +105,11 @@ typedef unsigned long pud_t;
typedef unsigned long p4d_t;
typedef unsigned long pgd_t;
+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(name ## _t name) \
#endif /* STRICT_MM_TYPECHECKS */
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;
#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/pgtable.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);
}
+#ifdef STRICT_MM_TYPECHECKS
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+ pteraw_t *pteraw_ptep = (__force pteraw_t *)ptep;
+ pteraw_t pteraw = __pteraw(pte_val(pte));
+
+ if (pte_present(pte))
+ pte = 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 = (__force pteraw_t *)ptep;
+ pteraw_t pteraw = 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 = (__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
#define pmdp_get pmdp_get
static inline pmd_t pmdp_get(pmd_t *pmdp)
--
2.53.0