s390/cmma: move parsing of cmma kernel parameter to early boot code
authorHeiko Carstens <hca@linux.ibm.com>
Fri, 27 Oct 2023 12:12:36 +0000 (14:12 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Sun, 5 Nov 2023 21:34:57 +0000 (22:34 +0100)
The "cmma=" kernel command line parameter needs to be parsed early for
upcoming changes. Therefore move the parsing code.

Note that EX_TABLE handling of cmma_test_essa() needs to be open-coded,
since the early boot code doesn't have infrastructure for handling expected
exceptions.

Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/boot/ipl_parm.c
arch/s390/boot/startup.c
arch/s390/include/asm/page-states.h
arch/s390/include/asm/setup.h
arch/s390/kernel/early.c
arch/s390/mm/init.c
arch/s390/mm/page-states.c

index 7b7521762633f9a75a1a4a09070436c7e2782ffc..2ab4872fbee1c9ab6938c2bf973d9590ccea2d06 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/init.h>
 #include <linux/ctype.h>
 #include <linux/pgtable.h>
+#include <asm/page-states.h>
 #include <asm/ebcdic.h>
 #include <asm/sclp.h>
 #include <asm/sections.h>
@@ -24,6 +25,7 @@ unsigned int __bootdata_preserved(zlib_dfltcc_support) = ZLIB_DFLTCC_FULL;
 struct ipl_parameter_block __bootdata_preserved(ipl_block);
 int __bootdata_preserved(ipl_block_valid);
 int __bootdata_preserved(__kaslr_enabled);
+int __bootdata_preserved(cmma_flag) = 1;
 
 unsigned long vmalloc_size = VMALLOC_DEFAULT_SIZE;
 unsigned long memory_limit;
@@ -295,6 +297,12 @@ void parse_boot_command_line(void)
                if (!strcmp(param, "nokaslr"))
                        __kaslr_enabled = 0;
 
+               if (!strcmp(param, "cmma")) {
+                       rc = kstrtobool(val, &enabled);
+                       if (!rc && !enabled)
+                               cmma_flag = 0;
+               }
+
 #if IS_ENABLED(CONFIG_KVM)
                if (!strcmp(param, "prot_virt")) {
                        rc = kstrtobool(val, &enabled);
index 8826c4f1864595c96a6073940f0371d4487b4945..8104e0e3d188d8e58b3c2824672d84ea780f0d7f 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/string.h>
 #include <linux/elf.h>
+#include <asm/page-states.h>
 #include <asm/boot_data.h>
 #include <asm/sections.h>
 #include <asm/maccess.h>
@@ -57,6 +58,48 @@ static void detect_facilities(void)
                machine.has_nx = 1;
 }
 
+static int cmma_test_essa(void)
+{
+       unsigned long reg1, reg2, tmp = 0;
+       int rc = 1;
+       psw_t old;
+
+       /* Test ESSA_GET_STATE */
+       asm volatile(
+               "       mvc     0(16,%[psw_old]),0(%[psw_pgm])\n"
+               "       epsw    %[reg1],%[reg2]\n"
+               "       st      %[reg1],0(%[psw_pgm])\n"
+               "       st      %[reg2],4(%[psw_pgm])\n"
+               "       larl    %[reg1],1f\n"
+               "       stg     %[reg1],8(%[psw_pgm])\n"
+               "       .insn   rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n"
+               "       la      %[rc],0\n"
+               "1:     mvc     0(16,%[psw_pgm]),0(%[psw_old])\n"
+               : [reg1] "=&d" (reg1),
+                 [reg2] "=&a" (reg2),
+                 [rc] "+&d" (rc),
+                 [tmp] "=&d" (tmp),
+                 "+Q" (S390_lowcore.program_new_psw),
+                 "=Q" (old)
+               : [psw_old] "a" (&old),
+                 [psw_pgm] "a" (&S390_lowcore.program_new_psw),
+                 [cmd] "i" (ESSA_GET_STATE)
+               : "cc", "memory");
+       return rc;
+}
+
+static void cmma_init(void)
+{
+       if (!cmma_flag)
+               return;
+       if (cmma_test_essa()) {
+               cmma_flag = 0;
+               return;
+       }
+       if (test_facility(147))
+               cmma_flag = 2;
+}
+
 static void setup_lpp(void)
 {
        S390_lowcore.current_pid = 0;
@@ -306,6 +349,7 @@ void startup_kernel(void)
        setup_boot_command_line();
        parse_boot_command_line();
        detect_facilities();
+       cmma_init();
        sanitize_prot_virt_host();
        max_physmem_end = detect_max_physmem_end();
        setup_ident_map_size(max_physmem_end);
index c33c4deb545ffda9078bd6d1f5bb22804488060f..659e3c963ce6597e14fb70ce1f5060cb36234d65 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef PAGE_STATES_H
 #define PAGE_STATES_H
 
+#include <asm/sections.h>
+
 #define ESSA_GET_STATE                 0
 #define ESSA_SET_STABLE                        1
 #define ESSA_SET_UNUSED                        2
@@ -18,4 +20,6 @@
 
 #define ESSA_MAX       ESSA_SET_STABLE_NODAT
 
+extern int __bootdata_preserved(cmma_flag);
+
 #endif
index 25cadc2b9cff277e46ec688bd20b288fb095f77e..ad66412456587b83242d01382dfb734180cc94e0 100644 (file)
@@ -125,7 +125,6 @@ static inline void vmcp_cma_reserve(void) { }
 
 void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault);
 
-void cmma_init(void);
 void cmma_init_nodat(void);
 
 extern void (*_machine_restart)(char *command);
index ff1f02b54771cbe26a8c3c45b75def84a0e157f7..eb43e5922a25d75489d7fe1cfe715449ac55c0c8 100644 (file)
@@ -46,6 +46,7 @@ decompressor_handled_param(vmalloc);
 decompressor_handled_param(dfltcc);
 decompressor_handled_param(facilities);
 decompressor_handled_param(nokaslr);
+decompressor_handled_param(cmma);
 #if IS_ENABLED(CONFIG_KVM)
 decompressor_handled_param(prot_virt);
 #endif
index 7eca10c32caa5bab87bc822a21b71b91fce32ef0..c322d09624bc737c1d57baf421af8c5797a9b58e 100644 (file)
@@ -164,8 +164,6 @@ void __init mem_init(void)
 
        pv_init();
        kfence_split_mapping();
-       /* Setup guest page hinting */
-       cmma_init();
 
        /* this will put all low memory onto the freelists */
        memblock_free_all();
index 202dacdf17db01a811f0b9bb1d3ccfe8144bf322..b68fef3d1230c1cab0075b96500dea43bdc4e540 100644 (file)
 #include <asm/facility.h>
 #include <asm/page-states.h>
 
-static int cmma_flag = 1;
-
-static int __init cmma(char *str)
-{
-       bool enabled;
-
-       if (!kstrtobool(str, &enabled))
-               cmma_flag = enabled;
-       return 1;
-}
-__setup("cmma=", cmma);
-
-static inline int cmma_test_essa(void)
-{
-       unsigned long tmp = 0;
-       int rc = -EOPNOTSUPP;
-
-       /* test ESSA_GET_STATE */
-       asm volatile(
-               "       .insn   rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n"
-               "0:     la      %[rc],0\n"
-               "1:\n"
-               EX_TABLE(0b, 1b)
-               : [rc] "+&d" (rc), [tmp] "+&d" (tmp)
-               : [cmd] "i" (ESSA_GET_STATE));
-       return rc;
-}
-
-void __init cmma_init(void)
-{
-       if (!cmma_flag)
-               return;
-       if (cmma_test_essa()) {
-               cmma_flag = 0;
-               return;
-       }
-       if (test_facility(147))
-               cmma_flag = 2;
-}
+int __bootdata_preserved(cmma_flag);
 
 static __always_inline void essa(unsigned long paddr, unsigned char cmd)
 {