]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/mm: Add configurable STRICT_MM_TYPECHECKS
authorHeiko Carstens <hca@linux.ibm.com>
Tue, 4 Mar 2025 08:14:33 +0000 (09:14 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 11 Mar 2025 14:27:34 +0000 (15:27 +0100)
Add support for configurable STRICT_MM_TYPECHECKS. The s390 ABI defines
that return values with complex types like structures and unions are
returned in a return value buffer allocated by the caller. This is also
true for small structures and unions which would fit into a register.  On
the other hand when such types are passed as arguments to functions they
are passed in registers, if they are small enough.
This leads to inefficient code when such a return value of a function call
is then passed as argument to a subsequent function call.

This is especially true for all mm types, like pte_t and others, which are
only for type checking reasons defined as a structure. This however can be
bypassed with the STRICT_MM_TYPECHECKS feature, which is used by a few
other architectures, which seem to have the same problem.

Add CONFIG_STRICT_MM_TYPECHECKS which can be used to change the type of
pte_t and other structures. If the config option is not enabled the types
are defined to unsigned long, allowing for better code generation, however
there is no type checking anymore. If it is enabled the types are
structures like before so that type checking is performed, but less
efficient code is generated.

The option is always enabled in debug_defconfig, and for convenience an
mmtypes.config topic target is added, which allows to easily enable it, in
case memory management code is changed.

CONFIG_STRICT_MM_TYPECHECKS and STRICT_MM_TYPECHECKS are kept separate,
since STRICT_MM_TYPECHECKS is common across architectures and common
code. Therefore use the same define also for s390 code.

Add CONFIG_STRICT_MM_TYPECHECKS to make it build time configurable.

Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/Kconfig.debug
arch/s390/configs/debug_defconfig
arch/s390/configs/mmtypes.config [new file with mode: 0644]
arch/s390/include/asm/page.h

index c4300ea4abf818015cdf2159461381d64b8e1707..7955d7eee7d8e99deaa9e1244e76bec50b36c92f 100644 (file)
@@ -13,6 +13,16 @@ config DEBUG_ENTRY
 
          If unsure, say N.
 
+config STRICT_MM_TYPECHECKS
+       bool "Strict Memory Management Type Checks"
+       depends on DEBUG_KERNEL
+       help
+         Enable strict type checking for memory management types like pte_t
+         and pmd_t. This generates slightly worse code and should be used
+         for debug builds.
+
+         If unsure, say N.
+
 config CIO_INJECT
        bool "CIO Inject interfaces"
        depends on DEBUG_KERNEL && DEBUG_FS
index d6beec5292a00ab3ec295a874bc15b0c43eff1fb..e0d39aa03fc51cd17a927668dc0c6e29e2b1bb86 100644 (file)
@@ -893,6 +893,7 @@ CONFIG_SAMPLE_FTRACE_DIRECT=m
 CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m
 CONFIG_SAMPLE_FTRACE_OPS=m
 CONFIG_DEBUG_ENTRY=y
+CONFIG_STRICT_MM_TYPECHECKS=y
 CONFIG_CIO_INJECT=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_DEBUGFS=y
diff --git a/arch/s390/configs/mmtypes.config b/arch/s390/configs/mmtypes.config
new file mode 100644 (file)
index 0000000..fe32b44
--- /dev/null
@@ -0,0 +1,2 @@
+# Help: Enable strict memory management typechecks
+CONFIG_STRICT_MM_TYPECHECKS=y
index 8bd0901bdf9ce2e767266db622abe65b2fe3e619..4e5dbabdf202560dacd364772e1c6d6628252312 100644 (file)
@@ -71,9 +71,11 @@ static inline void copy_page(void *to, void *from)
 #define vma_alloc_zeroed_movable_folio(vma, vaddr) \
        vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr)
 
-/*
- * These are used to make use of C type-checking..
- */
+#ifdef CONFIG_STRICT_MM_TYPECHECKS
+#define STRICT_MM_TYPECHECKS
+#endif
+
+#ifdef STRICT_MM_TYPECHECKS
 
 typedef struct { unsigned long pgprot; } pgprot_t;
 typedef struct { unsigned long pgste; } pgste_t;
@@ -82,42 +84,40 @@ typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pud; } pud_t;
 typedef struct { unsigned long p4d; } p4d_t;
 typedef struct { unsigned long pgd; } pgd_t;
-typedef pte_t *pgtable_t;
 
-static inline unsigned long pgprot_val(pgprot_t pgprot)
-{
-       return pgprot.pgprot;
+#define DEFINE_PGVAL_FUNC(name)                                                \
+static __always_inline unsigned long name ## _val(name ## _t name)     \
+{                                                                      \
+       return name.name;                                               \
 }
 
-static inline unsigned long pgste_val(pgste_t pgste)
-{
-       return pgste.pgste;
-}
+#else /* STRICT_MM_TYPECHECKS */
 
-static inline unsigned long pte_val(pte_t pte)
-{
-       return pte.pte;
-}
+typedef unsigned long pgprot_t;
+typedef unsigned long pgste_t;
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pud_t;
+typedef unsigned long p4d_t;
+typedef unsigned long pgd_t;
 
-static inline unsigned long pmd_val(pmd_t pmd)
-{
-       return pmd.pmd;
+#define DEFINE_PGVAL_FUNC(name)                                                \
+static __always_inline unsigned long name ## _val(name ## _t name)     \
+{                                                                      \
+       return name;                                                    \
 }
 
-static inline unsigned long pud_val(pud_t pud)
-{
-       return pud.pud;
-}
+#endif /* STRICT_MM_TYPECHECKS */
 
-static inline unsigned long p4d_val(p4d_t p4d)
-{
-       return p4d.p4d;
-}
+DEFINE_PGVAL_FUNC(pgprot)
+DEFINE_PGVAL_FUNC(pgste)
+DEFINE_PGVAL_FUNC(pte)
+DEFINE_PGVAL_FUNC(pmd)
+DEFINE_PGVAL_FUNC(pud)
+DEFINE_PGVAL_FUNC(p4d)
+DEFINE_PGVAL_FUNC(pgd)
 
-static inline unsigned long pgd_val(pgd_t pgd)
-{
-       return pgd.pgd;
-}
+typedef pte_t *pgtable_t;
 
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 #define __pgste(x)     ((pgste_t) { (x) } )