Commit 1d2ad084 authored by Vasily Gorbik's avatar Vasily Gorbik

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: default avatarIlya Leoshkevich <iii@linux.ibm.com>
Co-developed-by: default avatarSumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: default avatarSumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent eed38cd2
...@@ -585,6 +585,7 @@ config KERNEL_NOBP ...@@ -585,6 +585,7 @@ config KERNEL_NOBP
config EXPOLINE config EXPOLINE
def_bool n def_bool n
depends on $(cc-option,-mindirect-branch=thunk)
prompt "Avoid speculative indirect branches in the kernel" prompt "Avoid speculative indirect branches in the kernel"
help help
Compile the kernel with the expoline compiler options to guard Compile the kernel with the expoline compiler options to guard
...@@ -595,6 +596,20 @@ config EXPOLINE ...@@ -595,6 +596,20 @@ config EXPOLINE
If unsure, say N. 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 choice
prompt "Expoline default" prompt "Expoline default"
depends on EXPOLINE depends on EXPOLINE
......
...@@ -81,14 +81,18 @@ ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),) ...@@ -81,14 +81,18 @@ ifneq ($(call cc-option,-mstack-size=8192 -mstack-guard=128),)
endif endif
ifdef CONFIG_EXPOLINE 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 := -mindirect-branch=thunk
CC_FLAGS_EXPOLINE += -mfunction-return=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 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 endif
ifdef CONFIG_FUNCTION_TRACER ifdef CONFIG_FUNCTION_TRACER
......
...@@ -18,7 +18,11 @@ _LC_BR_R1 = __LC_BR_R1 ...@@ -18,7 +18,11 @@ _LC_BR_R1 = __LC_BR_R1
* the various thunks are merged into a single copy. * the various thunks are merged into a single copy.
*/ */
.macro __THUNK_PROLOG_NAME name .macro __THUNK_PROLOG_NAME name
#ifdef CONFIG_EXPOLINE_EXTERN
.pushsection .text,"ax",@progbits
#else
.pushsection .text.\name,"axG",@progbits,\name,comdat .pushsection .text.\name,"axG",@progbits,\name,comdat
#endif
.globl \name .globl \name
.hidden \name .hidden \name
.type \name,@function .type \name,@function
...@@ -115,7 +119,13 @@ _LC_BR_R1 = __LC_BR_R1 ...@@ -115,7 +119,13 @@ _LC_BR_R1 = __LC_BR_R1
555: br \reg 555: br \reg
.endm .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 .macro GEN_BR_THUNK reg,ruse=%r1
#endif
__DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
__THUNK_EX_BR \reg,\ruse __THUNK_EX_BR \reg,\ruse
__THUNK_EPILOG __THUNK_EPILOG
......
...@@ -7,6 +7,7 @@ lib-y += delay.o string.o uaccess.o find.o spinlock.o ...@@ -7,6 +7,7 @@ lib-y += delay.o string.o uaccess.o find.o spinlock.o
obj-y += mem.o xor.o obj-y += mem.o xor.o
lib-$(CONFIG_KPROBES) += probes.o lib-$(CONFIG_KPROBES) += probes.o
lib-$(CONFIG_UPROBES) += probes.o lib-$(CONFIG_UPROBES) += probes.o
obj-$(CONFIG_EXPOLINE_EXTERN) += expoline.o
obj-$(CONFIG_S390_KPROBES_SANITY_TEST) += test_kprobes_s390.o obj-$(CONFIG_S390_KPROBES_SANITY_TEST) += test_kprobes_s390.o
test_kprobes_s390-objs += test_kprobes_asm.o test_kprobes.o test_kprobes_s390-objs += test_kprobes_asm.o test_kprobes.o
......
/* 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
#!/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) ...@@ -658,6 +658,11 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
strstarts(symname, "_savevr_") || strstarts(symname, "_savevr_") ||
strcmp(symname, ".TOC.") == 0) strcmp(symname, ".TOC.") == 0)
return 1; 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 */ /* Do not ignore this symbol */
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment