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

Commit e6d60b36 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

s390/ftrace: hotpatch support for function tracing



Make use of gcc's hotpatch support to generate better code for ftrace
function tracing.
The generated code now contains only a six byte nop in each function
prologue instead of a 24 byte code block which will be runtime patched to
support function tracing.
With the new code generation the runtime overhead for supporting function
tracing is close to zero, while the original code did show a significant
performance impact.

Acked-by: default avatarSteven Rostedt <rostedt@goodmis.org>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 61f55214
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -117,7 +117,6 @@ config S390
	select HAVE_BPF_JIT if 64BIT && PACK_STACK
	select HAVE_CMPXCHG_DOUBLE
	select HAVE_CMPXCHG_LOCAL
	select HAVE_C_RECORDMCOUNT
	select HAVE_DEBUG_KMEMLEAK
	select HAVE_DYNAMIC_FTRACE if 64BIT
	select HAVE_DYNAMIC_FTRACE_WITH_REGS if 64BIT
+10 −0
Original line number Diff line number Diff line
@@ -87,6 +87,16 @@ ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
endif

ifdef CONFIG_FUNCTION_TRACER
# make use of hotpatch feature if the compiler supports it
cc_hotpatch	:= -mhotpatch=0,3
ifeq ($(call cc-option-yn,$(cc_hotpatch)),y)
CC_FLAGS_FTRACE := $(cc_hotpatch)
KBUILD_AFLAGS	+= -DCC_USING_HOTPATCH
KBUILD_CFLAGS	+= -DCC_USING_HOTPATCH
endif
endif

KBUILD_CFLAGS	+= -mbackchain -msoft-float $(cflags-y)
KBUILD_CFLAGS	+= -pipe -fno-strength-reduce -Wno-sign-compare
KBUILD_AFLAGS	+= $(aflags-y)
+15 −0
Original line number Diff line number Diff line
@@ -3,8 +3,12 @@

#define ARCH_SUPPORTS_FTRACE_OPS 1

#ifdef CC_USING_HOTPATCH
#define MCOUNT_INSN_SIZE	6
#else
#define MCOUNT_INSN_SIZE	24
#define MCOUNT_RETURN_FIXUP	18
#endif

#ifndef __ASSEMBLY__

@@ -37,17 +41,28 @@ struct ftrace_insn {
static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn)
{
#ifdef CONFIG_FUNCTION_TRACER
#ifdef CC_USING_HOTPATCH
	/* brcl 0,0 */
	insn->opc = 0xc004;
	insn->disp = 0;
#else
	/* jg .+24 */
	insn->opc = 0xc0f4;
	insn->disp = MCOUNT_INSN_SIZE / 2;
#endif
#endif
}

static inline int is_ftrace_nop(struct ftrace_insn *insn)
{
#ifdef CONFIG_FUNCTION_TRACER
#ifdef CC_USING_HOTPATCH
	if (insn->disp == 0)
		return 1;
#else
	if (insn->disp == MCOUNT_INSN_SIZE / 2)
		return 1;
#endif
#endif
	return 0;
}
+2 −2
Original line number Diff line number Diff line
@@ -4,8 +4,8 @@

ifdef CONFIG_FUNCTION_TRACER
# Don't trace early setup code and tracing code
CFLAGS_REMOVE_early.o = -pg
CFLAGS_REMOVE_ftrace.o = -pg
CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
endif

#
+14 −1
Original line number Diff line number Diff line
@@ -46,6 +46,13 @@
 *	lg	%r14,8(%r15)		# offset 18
 * The jg instruction branches to offset 24 to skip as many instructions
 * as possible.
 * In case we use gcc's hotpatch feature the original and also the disabled
 * function prologue contains only a single six byte instruction and looks
 * like this:
 * >	brcl	0,0			# offset 0
 * To enable ftrace the code gets patched like above and afterwards looks
 * like this:
 * >	brasl	%r0,ftrace_caller	# offset 0
 */

unsigned long ftrace_plt;
@@ -64,9 +71,15 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
	if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
		return -EFAULT;
	if (addr == MCOUNT_ADDR) {
		/* Initial code replacement; we expect to see stg r14,8(r15) */
		/* Initial code replacement */
#ifdef CC_USING_HOTPATCH
		/* We expect to see brcl 0,0 */
		ftrace_generate_nop_insn(&orig);
#else
		/* We expect to see stg r14,8(r15) */
		orig.opc = 0xe3e0;
		orig.disp = 0xf0080024;
#endif
		ftrace_generate_nop_insn(&new);
	} else if (old.opc == BREAKPOINT_INSTRUCTION) {
		/*
Loading