s390/nospec: add an option to use thunk-extern
Currently with -mindirect-branch=thunk and -mfunction-return=thunk compiler options expoline thunks are put into individual COMDAT group sections. s390 is the only architecture which has group sections and it has implications for kpatch and objtool tools support. Using -mindirect-branch=thunk-extern and -mfunction-return=thunk-extern is an alternative, which comes with a need to generate all required expoline thunks manually. Unfortunately modules area is too far away from the kernel image, and expolines from the kernel image cannon be used. But since all new distributions (except Debian) build kernels for machine generations newer than z10, where "exrl" instruction is available, that leaves only 16 expolines thunks possible. Provide an option to build the kernel with -mindirect-branch=thunk-extern and -mfunction-return=thunk-extern for z10 or newer. This also requires to postlink expoline thunks into all modules explicitly. Currently modules already contain most expolines anyhow. Unfortunately -mindirect-branch=thunk-extern and -mfunction-return=thunk-extern options support is broken in gcc <= 11.2. Additional compile test is required to verify proper gcc support. Acked-by: Ilya Leoshkevich <iii@linux.ibm.com> Co-developed-by: Sumanth Korikkar <sumanthk@linux.ibm.com> Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
eed38cd2f4
commit
1d2ad08480
@ -585,6 +585,7 @@ config KERNEL_NOBP
|
||||
|
||||
config EXPOLINE
|
||||
def_bool n
|
||||
depends on $(cc-option,-mindirect-branch=thunk)
|
||||
prompt "Avoid speculative indirect branches in the kernel"
|
||||
help
|
||||
Compile the kernel with the expoline compiler options to guard
|
||||
@ -595,6 +596,20 @@ config EXPOLINE
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config EXPOLINE_EXTERN
|
||||
def_bool n
|
||||
depends on EXPOLINE
|
||||
depends on HAVE_MARCH_Z10_FEATURES
|
||||
depends on CC_IS_GCC && GCC_VERSION >= 110200
|
||||
depends on $(success,$(srctree)/arch/s390/tools/gcc-thunk-extern.sh $(CC))
|
||||
prompt "Generate expolines as extern functions."
|
||||
help
|
||||
This option is required for some tooling like kpatch. The kernel is
|
||||
compiled with -mindirect-branch=thunk-extern and requires a newer
|
||||
compiler.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
choice
|
||||
prompt "Expoline default"
|
||||
depends on EXPOLINE
|
||||
|
@ -81,14 +81,18 @@ ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),)
|
||||
endif
|
||||
|
||||
ifdef CONFIG_EXPOLINE
|
||||
ifneq ($(call cc-option,$(CC_FLAGS_MARCH) -mindirect-branch=thunk),)
|
||||
ifdef CONFIG_EXPOLINE_EXTERN
|
||||
KBUILD_LDFLAGS_MODULE += arch/s390/lib/expoline.o
|
||||
CC_FLAGS_EXPOLINE := -mindirect-branch=thunk-extern
|
||||
CC_FLAGS_EXPOLINE += -mfunction-return=thunk-extern
|
||||
else
|
||||
CC_FLAGS_EXPOLINE := -mindirect-branch=thunk
|
||||
CC_FLAGS_EXPOLINE += -mfunction-return=thunk
|
||||
CC_FLAGS_EXPOLINE += -mindirect-branch-table
|
||||
export CC_FLAGS_EXPOLINE
|
||||
cflags-y += $(CC_FLAGS_EXPOLINE) -DCC_USING_EXPOLINE
|
||||
aflags-y += -DCC_USING_EXPOLINE
|
||||
endif
|
||||
CC_FLAGS_EXPOLINE += -mindirect-branch-table
|
||||
export CC_FLAGS_EXPOLINE
|
||||
cflags-y += $(CC_FLAGS_EXPOLINE) -DCC_USING_EXPOLINE
|
||||
aflags-y += -DCC_USING_EXPOLINE
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
|
@ -18,7 +18,11 @@ _LC_BR_R1 = __LC_BR_R1
|
||||
* the various thunks are merged into a single copy.
|
||||
*/
|
||||
.macro __THUNK_PROLOG_NAME name
|
||||
#ifdef CONFIG_EXPOLINE_EXTERN
|
||||
.pushsection .text,"ax",@progbits
|
||||
#else
|
||||
.pushsection .text.\name,"axG",@progbits,\name,comdat
|
||||
#endif
|
||||
.globl \name
|
||||
.hidden \name
|
||||
.type \name,@function
|
||||
@ -115,7 +119,13 @@ _LC_BR_R1 = __LC_BR_R1
|
||||
555: br \reg
|
||||
.endm
|
||||
|
||||
#ifdef CONFIG_EXPOLINE_EXTERN
|
||||
.macro GEN_BR_THUNK reg,ruse=%r1
|
||||
.endm
|
||||
.macro GEN_BR_THUNK_EXTERN reg,ruse=%r1
|
||||
#else
|
||||
.macro GEN_BR_THUNK reg,ruse=%r1
|
||||
#endif
|
||||
__DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
|
||||
__THUNK_EX_BR \reg,\ruse
|
||||
__THUNK_EPILOG
|
||||
|
@ -7,6 +7,7 @@ lib-y += delay.o string.o uaccess.o find.o spinlock.o
|
||||
obj-y += mem.o xor.o
|
||||
lib-$(CONFIG_KPROBES) += probes.o
|
||||
lib-$(CONFIG_UPROBES) += probes.o
|
||||
obj-$(CONFIG_EXPOLINE_EXTERN) += expoline.o
|
||||
obj-$(CONFIG_S390_KPROBES_SANITY_TEST) += test_kprobes_s390.o
|
||||
test_kprobes_s390-objs += test_kprobes_asm.o test_kprobes.o
|
||||
|
||||
|
12
arch/s390/lib/expoline.S
Normal file
12
arch/s390/lib/expoline.S
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <asm/nospec-insn.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.macro GEN_ALL_BR_THUNK_EXTERN
|
||||
.irp r1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
|
||||
GEN_BR_THUNK_EXTERN %r\r1
|
||||
.endr
|
||||
.endm
|
||||
|
||||
GEN_ALL_BR_THUNK_EXTERN
|
24
arch/s390/tools/gcc-thunk-extern.sh
Executable file
24
arch/s390/tools/gcc-thunk-extern.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Borrowed from gcc: gcc/testsuite/gcc.target/s390/nobp-section-type-conflict.c
|
||||
# Checks that we don't get error: section type conflict with ‘put_page’.
|
||||
|
||||
cat << "END" | $@ -x c - -fno-PIE -march=z10 -mindirect-branch=thunk-extern -mfunction-return=thunk-extern -mindirect-branch-table -O2 -c -o /dev/null
|
||||
int a;
|
||||
int b (void);
|
||||
void c (int);
|
||||
|
||||
static void
|
||||
put_page (void)
|
||||
{
|
||||
if (b ())
|
||||
c (a);
|
||||
}
|
||||
|
||||
__attribute__ ((__section__ (".init.text"), __cold__)) void
|
||||
d (void)
|
||||
{
|
||||
put_page ();
|
||||
put_page ();
|
||||
}
|
||||
END
|
@ -658,6 +658,11 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
|
||||
strstarts(symname, "_savevr_") ||
|
||||
strcmp(symname, ".TOC.") == 0)
|
||||
return 1;
|
||||
|
||||
if (info->hdr->e_machine == EM_S390)
|
||||
/* Expoline thunks are linked on all kernel modules during final link of .ko */
|
||||
if (strstarts(symname, "__s390_indirect_jump_r"))
|
||||
return 1;
|
||||
/* Do not ignore this symbol */
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user