Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23a4d7fd authored by Martin Schwidefsky's avatar Martin Schwidefsky
Browse files

s390/ftrace: use expoline for indirect branches



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>
parent 97489e06
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -2,12 +2,16 @@
#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>
#include <asm/dwarf.h>
#include <asm/dwarf.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
@@ -78,13 +82,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
+1 −0
Original line number Original line Diff line number Diff line
@@ -181,6 +181,7 @@ int main(void)
	OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags);
	OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags);
	OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count);
	OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count);
	OFFSET(__LC_GMAP, lowcore, gmap);
	OFFSET(__LC_GMAP, lowcore, gmap);
	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 */
+9 −5
Original line number Original line Diff line number Diff line
@@ -9,13 +9,17 @@
#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>
#include <asm/export.h>
#include <asm/export.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)
@@ -23,7 +27,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


EXPORT_SYMBOL(_mcount)
EXPORT_SYMBOL(_mcount)


@@ -53,7 +57,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.
@@ -68,7 +72,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


@@ -81,6 +85,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