summaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
authorSven Schnelle <svens@linux.ibm.com>2024-07-16 13:50:54 +0200
committerVasily Gorbik <gor@linux.ibm.com>2024-07-23 16:02:31 +0200
commit7f9d85998f6c5b989796470fd1ac066232c60723 (patch)
tree5de2f33c2c98b2e9b6353c2d927c1fcf98964512 /arch/s390
parentb3e0c5f734f934dab1cfdef669e3baa165a0cbfe (diff)
s390/alternatives: Allow early alternative patching in decompressor
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>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/boot/Makefile2
-rw-r--r--arch/s390/boot/alternative.c3
-rw-r--r--arch/s390/boot/boot.h2
-rw-r--r--arch/s390/boot/startup.c5
-rw-r--r--arch/s390/include/asm/alternative.h12
-rw-r--r--arch/s390/kernel/alternative.c5
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
7 files changed, 27 insertions, 4 deletions
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
index e7658997452b..5d8cb7e3b096 100644
--- a/arch/s390/boot/Makefile
+++ b/arch/s390/boot/Makefile
@@ -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
index 000000000000..abc08d2c873d
--- /dev/null
+++ b/arch/s390/boot/alternative.c
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "../kernel/alternative.c"
diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h
index 18027fdc92b0..ed2f0ec24f0d 100644
--- a/arch/s390/boot/boot.h
+++ b/arch/s390/boot/boot.h
@@ -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;
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index cc8753c0c121..cca2f1bad33c 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -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.
diff --git a/arch/s390/include/asm/alternative.h b/arch/s390/include/asm/alternative.h
index 5b931070be16..32c208332e57 100644
--- a/arch/s390/include/asm/alternative.h
+++ b/arch/s390/include/asm/alternative.h
@@ -27,15 +27,21 @@
* 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)
diff --git a/arch/s390/kernel/alternative.c b/arch/s390/kernel/alternative.c
index ecabdff89bce..de89c9e8b1a3 100644
--- a/arch/s390/kernel/alternative.c
+++ b/arch/s390/kernel/alternative.c
@@ -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;
}
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 5128ccee9c67..975c654cf5a5 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -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)