]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/alternatives: Allow early alternative patching in decompressor
authorSven Schnelle <svens@linux.ibm.com>
Tue, 16 Jul 2024 11:50:54 +0000 (13:50 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 23 Jul 2024 14:02:31 +0000 (16:02 +0200)
Add the required code to patch alternatives early in the decompressor.
This is required for the upcoming lowcore relocation changes, where
alternatives for facility 193 need to get patched before lowcore
alternatives.

Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
Co-developed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/boot/Makefile
arch/s390/boot/alternative.c [new file with mode: 0644]
arch/s390/boot/boot.h
arch/s390/boot/startup.c
arch/s390/include/asm/alternative.h
arch/s390/kernel/alternative.c
arch/s390/kernel/vmlinux.lds.S

index e7658997452b1ac82f98e2016e609822ffe9a0a2..5d8cb7e3b096323871cd02cfbe45ab13564d6486 100644 (file)
@@ -39,7 +39,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
 
 obj-y  := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o
 obj-y  += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
-obj-y  += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o
+obj-y  += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o alternative.o
 obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE))  += uv.o
 obj-$(CONFIG_RANDOMIZE_BASE)   += kaslr.o
 obj-y  += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o
diff --git a/arch/s390/boot/alternative.c b/arch/s390/boot/alternative.c
new file mode 100644 (file)
index 0000000..abc08d2
--- /dev/null
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "../kernel/alternative.c"
index 18027fdc92b0c9b4b12170f28ac5ee4bd64ff03a..ed2f0ec24f0da45b3ac1f539e5148ec6f3d898e3 100644 (file)
@@ -30,6 +30,8 @@ struct vmlinux_info {
        unsigned long init_mm_off;
        unsigned long swapper_pg_dir_off;
        unsigned long invalid_pg_dir_off;
+       unsigned long alt_instructions;
+       unsigned long alt_instructions_end;
 #ifdef CONFIG_KASAN
        unsigned long kasan_early_shadow_page_off;
        unsigned long kasan_early_shadow_pte_off;
index cc8753c0c1216214a96d7099698d2b71f41cfc91..cca2f1bad33c9d932115e1bef00cb2e28856336f 100644 (file)
@@ -376,6 +376,8 @@ static void kaslr_adjust_vmlinux_info(long offset)
        vmlinux.init_mm_off += offset;
        vmlinux.swapper_pg_dir_off += offset;
        vmlinux.invalid_pg_dir_off += offset;
+       vmlinux.alt_instructions += offset;
+       vmlinux.alt_instructions_end += offset;
 #ifdef CONFIG_KASAN
        vmlinux.kasan_early_shadow_page_off += offset;
        vmlinux.kasan_early_shadow_pte_off += offset;
@@ -507,6 +509,9 @@ void startup_kernel(void)
        kaslr_adjust_got(__kaslr_offset);
        setup_vmem(__kaslr_offset, __kaslr_offset + kernel_size, asce_limit);
        copy_bootdata();
+       __apply_alternatives((struct alt_instr *)_vmlinux_info.alt_instructions,
+                            (struct alt_instr *)_vmlinux_info.alt_instructions_end,
+                            ALT_CTX_EARLY);
 
        /*
         * Save KASLR offset for early dumps, before vmcore_info is set.
index 5b931070be16524f3bed763bb3de74334b858f84..32c208332e579c25f03d3cd0e4a9ecbef365e8d0 100644 (file)
  * alternative should be applied.
  */
 
-#define ALT_CTX_LATE           1
-#define ALT_CTX_ALL            ALT_CTX_LATE
+#define ALT_CTX_EARLY          1
+#define ALT_CTX_LATE           2
+#define ALT_CTX_ALL            (ALT_CTX_EARLY | ALT_CTX_LATE)
 
-#define ALT_TYPE_FACILITY      0
+#define ALT_TYPE_FACILITY_EARLY        0
+#define ALT_TYPE_FACILITY      1
 
 #define ALT_DATA_SHIFT         0
 #define ALT_TYPE_SHIFT         20
 #define ALT_CTX_SHIFT          28
 
+#define ALT_FACILITY_EARLY(facility)   (ALT_CTX_EARLY << ALT_CTX_SHIFT            | \
+                                        ALT_TYPE_FACILITY_EARLY << ALT_TYPE_SHIFT | \
+                                        (facility) << ALT_DATA_SHIFT)
+
 #define ALT_FACILITY(facility)         (ALT_CTX_LATE << ALT_CTX_SHIFT          | \
                                         ALT_TYPE_FACILITY << ALT_TYPE_SHIFT    | \
                                         (facility) << ALT_DATA_SHIFT)
index ecabdff89bce0bea59e1ea279ae776bb00003fdc..de89c9e8b1a3087e42f8c43603f4dbb058e6a54c 100644 (file)
@@ -18,9 +18,14 @@ void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsign
                if (!(a->ctx & ctx))
                        continue;
                switch (a->type) {
+               case ALT_TYPE_FACILITY_EARLY:
+                       replace = test_facility(a->data);
+                       break;
+#ifndef __DECOMPRESSOR
                case ALT_TYPE_FACILITY:
                        replace = __test_facility(a->data, alt_stfle_fac_list);
                        break;
+#endif
                default:
                        replace = false;
                }
index 5128ccee9c6746289ea055485c8bf2038f2716a1..975c654cf5a51f42f89862895240e58c013a008d 100644 (file)
@@ -222,6 +222,8 @@ SECTIONS
                QUAD(init_mm)
                QUAD(swapper_pg_dir)
                QUAD(invalid_pg_dir)
+               QUAD(__alt_instructions)
+               QUAD(__alt_instructions_end)
 #ifdef CONFIG_KASAN
                QUAD(kasan_early_shadow_page)
                QUAD(kasan_early_shadow_pte)