Commit 22ef9729 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Khalid Elmously

s390/ftrace: use expoline for indirect branches

BugLink: https://bugs.launchpad.net/bugs/1775771

commit 23a4d7fd upstream.

The return from the ftrace_stub, _mcount, ftrace_caller and
return_to_handler functions is done with "br %r14" and "br %r1".
These are indirect branches as well and need to use execute
trampolines for CONFIG_EXPOLINE=y.

The ftrace_caller function is a special case as it returns to the
start of a function and may only use %r0 and %r1. For a pre z10
machine the standard execute trampoline uses a LARL + EX to do
this, but this requires *two* registers in the range %r1..%r15.
To get around this the 'br %r1' located in the lowcore is used,
then the EX instruction does not need an address register.
But the lowcore trick may only be used for pre z14 machines,
with noexec=on the mapping for the first page may not contain
instructions. The solution for that is an ALTERNATIVE in the
expoline THUNK generated by 'GEN_BR_THUNK %r1' to switch to
EXRL, this relies on the fact that a machine that supports
noexec=on has EXRL as well.

Cc: stable@vger.kernel.org # 4.16
Fixes: f19fbd5e ("s390: introduce execute-trampolines for branches")
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent fb82f2aa
...@@ -2,10 +2,15 @@ ...@@ -2,10 +2,15 @@
#ifndef _ASM_S390_NOSPEC_ASM_H #ifndef _ASM_S390_NOSPEC_ASM_H
#define _ASM_S390_NOSPEC_ASM_H #define _ASM_S390_NOSPEC_ASM_H
#include <asm/alternative-asm.h>
#include <asm/asm-offsets.h>
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
#ifdef CONFIG_EXPOLINE #ifdef CONFIG_EXPOLINE
_LC_BR_R1 = __LC_BR_R1
/* /*
* The expoline macros are used to create thunks in the same format * The expoline macros are used to create thunks in the same format
* as gcc generates them. The 'comdat' section flag makes sure that * as gcc generates them. The 'comdat' section flag makes sure that
...@@ -101,13 +106,21 @@ ...@@ -101,13 +106,21 @@
.endm .endm
.macro __THUNK_EX_BR reg,ruse .macro __THUNK_EX_BR reg,ruse
# Be very careful when adding instructions to this macro!
# The ALTERNATIVE replacement code has a .+10 which targets
# the "br \reg" after the code has been patched.
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
exrl 0,555f exrl 0,555f
j . j .
#else #else
.ifc \reg,%r1
ALTERNATIVE "ex %r0,_LC_BR_R1", ".insn ril,0xc60000000000,0,.+10", 35
j .
.else
larl \ruse,555f larl \ruse,555f
ex 0,0(\ruse) ex 0,0(\ruse)
j . j .
.endif
#endif #endif
555: br \reg 555: br \reg
.endm .endm
......
...@@ -171,6 +171,7 @@ int main(void) ...@@ -171,6 +171,7 @@ int main(void)
OFFSET(__LC_MACHINE_FLAGS, _lowcore, machine_flags); OFFSET(__LC_MACHINE_FLAGS, _lowcore, machine_flags);
OFFSET(__LC_GMAP, _lowcore, gmap); OFFSET(__LC_GMAP, _lowcore, gmap);
OFFSET(__LC_PASTE, _lowcore, paste); OFFSET(__LC_PASTE, _lowcore, paste);
OFFSET(__LC_BR_R1, _lowcore, br_r1_trampoline);
/* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */ /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
OFFSET(__LC_DUMP_REIPL, _lowcore, ipib); OFFSET(__LC_DUMP_REIPL, _lowcore, ipib);
/* hardware defined lowcore locations 0x1000 - 0x18ff */ /* hardware defined lowcore locations 0x1000 - 0x18ff */
......
...@@ -8,12 +8,16 @@ ...@@ -8,12 +8,16 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/ftrace.h> #include <asm/ftrace.h>
#include <asm/nospec-insn.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
GEN_BR_THUNK %r1
GEN_BR_THUNK %r14
.section .kprobes.text, "ax" .section .kprobes.text, "ax"
ENTRY(ftrace_stub) ENTRY(ftrace_stub)
br %r14 BR_EX %r14
#define STACK_FRAME_SIZE (STACK_FRAME_OVERHEAD + __PT_SIZE) #define STACK_FRAME_SIZE (STACK_FRAME_OVERHEAD + __PT_SIZE)
#define STACK_PTREGS (STACK_FRAME_OVERHEAD) #define STACK_PTREGS (STACK_FRAME_OVERHEAD)
...@@ -21,7 +25,7 @@ ENTRY(ftrace_stub) ...@@ -21,7 +25,7 @@ ENTRY(ftrace_stub)
#define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW) #define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW)
ENTRY(_mcount) ENTRY(_mcount)
br %r14 BR_EX %r14
ENTRY(ftrace_caller) ENTRY(ftrace_caller)
.globl ftrace_regs_caller .globl ftrace_regs_caller
...@@ -49,7 +53,7 @@ ENTRY(ftrace_caller) ...@@ -49,7 +53,7 @@ ENTRY(ftrace_caller)
#endif #endif
lgr %r3,%r14 lgr %r3,%r14
la %r5,STACK_PTREGS(%r15) la %r5,STACK_PTREGS(%r15)
basr %r14,%r1 BASR_EX %r14,%r1
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_FUNCTION_GRAPH_TRACER
# The j instruction gets runtime patched to a nop instruction. # The j instruction gets runtime patched to a nop instruction.
# See ftrace_enable_ftrace_graph_caller. # See ftrace_enable_ftrace_graph_caller.
...@@ -64,7 +68,7 @@ ftrace_graph_caller_end: ...@@ -64,7 +68,7 @@ ftrace_graph_caller_end:
#endif #endif
lg %r1,(STACK_PTREGS_PSW+8)(%r15) lg %r1,(STACK_PTREGS_PSW+8)(%r15)
lmg %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15) lmg %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15)
br %r1 BR_EX %r1
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_FUNCTION_GRAPH_TRACER
...@@ -77,6 +81,6 @@ ENTRY(return_to_handler) ...@@ -77,6 +81,6 @@ ENTRY(return_to_handler)
aghi %r15,STACK_FRAME_OVERHEAD aghi %r15,STACK_FRAME_OVERHEAD
lgr %r14,%r2 lgr %r14,%r2
lmg %r2,%r5,32(%r15) lmg %r2,%r5,32(%r15)
br %r14 BR_EX %r14
#endif #endif
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