Skip to contentSkip to conversation

s390: add support for DYNAMIC_FTRACE_WITH_REGS

PATCH In review Vojtech Pavlik 2 participants 8 messages Jul 3, 2014 – Aug 15, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 s390: add support for DYNAMIC_FTRACE_WITH_REGS

Add support for DYNAMIC_FTRACE_WITH_REGS to 64-bit and 31-bit s390 architectures. This is required for kGraft and kpatch to work on s390.

It's done by adding a _regs variant of ftrace_caller that preserves registers and puts them on stack in a struct pt_regs layout and allows modification of return address by changing the PSW (instruction pointer) member od struct pt_regs.

---

 arch/s390/Kconfig               |    1 
 arch/s390/include/asm/ftrace.h  |    4 ++
 arch/s390/include/asm/lowcore.h |   12 ++++---
 arch/s390/kernel/asm-offsets.c  |    1 
 arch/s390/kernel/early.c        |    3 +
 arch/s390/kernel/ftrace.c       |   68 +++++++++++++++++++++++++++++++++++-----
 arch/s390/kernel/mcount.S       |   43 +++++++++++++++++++++++++
 arch/s390/kernel/mcount64.S     |   38 ++++++++++++++++++++++
 arch/s390/kernel/setup.c        |    1 
 arch/s390/kernel/smp.c          |    1 
 include/linux/ftrace.h          |    1 
 11 files changed, 160 insertions(+), 13 deletions(-)
arch/s390/Kconfig +1 -0
index bb63499..1de14d3 100644
@@ -113,6 +113,7 @@ config S390
 	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_DYNAMIC_FTRACE_WITH_REGS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
arch/s390/include/asm/ftrace.h +4 -0
index bf246da..df87fd2 100644
@@ -17,6 +17,10 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 
 #endif /* __ASSEMBLY__ */
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#endif
+
 #ifdef CONFIG_64BIT
 #define MCOUNT_INSN_SIZE  12
 #else
arch/s390/include/asm/lowcore.h +7 -5
index 4349197..31b064a 100644
@@ -142,9 +142,10 @@ struct _lowcore {
 	__u32	percpu_offset;			/* 0x02f0 */
 	__u32	machine_flags;			/* 0x02f4 */
 	__u32	ftrace_func;			/* 0x02f8 */
-	__u32	spinlock_lockval;		/* 0x02fc */
+	__u32	ftrace_regs_func;		/* 0x02fc */
+	__u32	spinlock_lockval;		/* 0x0300 */
 
-	__u8	pad_0x0300[0x0e00-0x0300];	/* 0x0300 */
+	__u8	pad_0x0304[0x0e00-0x0304];	/* 0x0304 */
 
 	/*
 	 * 0xe00 contains the address of the IPL Parameter Information
@@ -287,9 +288,10 @@ struct _lowcore {
 	__u64	vdso_per_cpu_data;		/* 0x0380 */
 	__u64	machine_flags;			/* 0x0388 */
 	__u64	ftrace_func;			/* 0x0390 */
-	__u64	gmap;				/* 0x0398 */
-	__u32	spinlock_lockval;		/* 0x03a0 */
-	__u8	pad_0x03a0[0x0400-0x03a4];	/* 0x03a4 */
+	__u64	ftrace_regs_func;		/* 0x0398 */
+	__u64	gmap;				/* 0x03a0 */
+	__u32	spinlock_lockval;		/* 0x03a8 */
+	__u8	pad_0x03ac[0x0400-0x03ac];	/* 0x03ac */
 
 	/* Per cpu primary space access list */
 	__u32	paste[16];			/* 0x0400 */
arch/s390/kernel/asm-offsets.c +1 -0
index afe1715..12ef6ce 100644
@@ -150,6 +150,7 @@ int main(void)
 	DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
 	DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags));
 	DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func));
+	DEFINE(__LC_FTRACE_REGS_FUNC, offsetof(struct _lowcore, ftrace_regs_func));
 	DEFINE(__LC_DUMP_REIPL, offsetof(struct _lowcore, ipib));
 	BLANK();
 	DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area));
arch/s390/kernel/early.c +3 -0
index 0dff972..2ab52d2 100644
@@ -493,5 +493,8 @@ void __init startup_init(void)
 #ifdef CONFIG_DYNAMIC_FTRACE
 	S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
 #endif
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+	S390_lowcore.ftrace_regs_func = (unsigned long)ftrace_regs_caller;
+#endif
 	lockdep_on();
 }
arch/s390/kernel/ftrace.c +60 -8

111 lines not on this page · raw message

arch/s390/kernel/mcount.S +43 -0

49 lines not on this page · raw message

arch/s390/kernel/mcount64.S +38 -0
index 1c52eae..bcad958 100644
@@ -49,6 +49,44 @@ ENTRY(ftrace_graph_caller)
 	lg	%r14,112(%r15)
 	br	%r14
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+ENTRY(ftrace_regs_caller)
+	larl	%r1,function_trace_stop
+	icm	%r1,0xf,0(%r1)
+	bnzr	%r14
+	lgr	%r1,%r15
+	aghi	%r15,-336
+	stg	%r1,__SF_BACKCHAIN(%r15)
+	stg	%r1,304(%r15)
+	stmg	%r0,%r13,184(%r15)
+	stg	%r14,176(%r15)
+	lgr	%r2,%r14
+	aghi	%r2,-MCOUNT_INSN_SIZE
+	lg	%r3,344(%r15)
+	stg	%r3,296(%r15)
+	larl	%r4,function_trace_op
+	lg	%r4,0(%r4)
+	lgr	%r5, %r15
+	aghi	%r5, 160
+	larl	%r14,ftrace_trace_function
+	lg	%r14,0(%r14)
+	basr	%r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	lg	%r2,344(%r15)
+	lg	%r3,448(%r15)
+ENTRY(ftrace_regs_graph_caller)
+# The bras instruction gets runtime patched to call prepare_ftrace_return.
+# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
+#	bras	%r14,prepare_ftrace_return
+	bras	%r14,0f
+0:	stg	%r2,344(%r15)
+#endif
+	lmg	%r0,%r13,184(%r15)
+	lg	%r14,176(%r15)
+	aghi	%r15,336
+	br	%r14
+#endif
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
 ENTRY(return_to_handler)
arch/s390/kernel/setup.c +1 -0
index 1e2264b..6cdf2a1 100644
@@ -352,6 +352,7 @@ static void __init setup_lowcore(void)
 	lc->last_update_timer = S390_lowcore.last_update_timer;
 	lc->last_update_clock = S390_lowcore.last_update_clock;
 	lc->ftrace_func = S390_lowcore.ftrace_func;
+	lc->ftrace_regs_func = S390_lowcore.ftrace_regs_func;
 
 	restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0);
 	restart_stack += ASYNC_SIZE;
arch/s390/kernel/smp.c +1 -0
index 243c7e5..152967a 100644
@@ -232,6 +232,7 @@ static void pcpu_prepare_secondary(struct pcpu *pcpu, int cpu)
 	lc->kernel_asce = S390_lowcore.kernel_asce;
 	lc->machine_flags = S390_lowcore.machine_flags;
 	lc->ftrace_func = S390_lowcore.ftrace_func;
+	lc->ftrace_regs_func = S390_lowcore.ftrace_regs_func;
 	lc->user_timer = lc->system_timer = lc->steal_timer = 0;
 	__ctl_store(lc->cregs_save_area, 0, 15);
 	save_access_regs((unsigned int *) lc->access_regs_save_area);
include/linux/ftrace.h +1 -0
index 404a686..70ccc82 100644
@@ -441,6 +441,7 @@ void ftrace_modify_all_code(int command);
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 extern void ftrace_graph_caller(void);
+extern void ftrace_regs_graph_caller(void);
 extern int ftrace_enable_ftrace_graph_caller(void);
 extern int ftrace_disable_ftrace_graph_caller(void);
 #else
#1 lore raw
Quoted 11 lines · Vojtech Pavlik

Add support for DYNAMIC_FTRACE_WITH_REGS to 64-bit and 31-bit s390 architectures. This is required for kGraft and kpatch to work on s390.

It's done by adding a _regs variant of ftrace_caller that preserves registers and puts them on stack in a struct pt_regs layout and allows modification of return address by changing the PSW (instruction pointer) member od struct pt_regs.

So I assume you use the instruction_pointer() macro to access the return address then?

All of this seems a bit of a hack to me.. the natural place of the return address of a function would be register 14, and not the psw member of the pt_regs structure.

It's then also inconsistent to only save register r0-r13 to the gprs member.. well, you can't save r14, since what should happen if both r14 in the gprs member of pt_regs and in the psw part would have been changed?

Besides that a couple more comments below.

arch/s390/kernel/mcount64.S ENTRY(ftrace_graph_caller) · line 56

Quoted 13 lines
arch/s390/kernel/mcount64.S +5 -0
index 1c52eae..bcad958 100644
@@ -49,6 +49,44 @@ ENTRY(ftrace_graph_caller)
 	lg	%r14,112(%r15)
 	br	%r14
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+ENTRY(ftrace_regs_caller)
+	larl	%r1,function_trace_stop
+	icm	%r1,0xf,0(%r1)
+	bnzr	%r14

The three lines above should go away, but that's not your problem, since Steven is about to remove the function_trace_stop functionality.

Quoted 22 lines
arch/s390/kernel/mcount64.S +22 -0
+	lgr	%r1,%r15
+	aghi	%r15,-336
+	stg	%r1,__SF_BACKCHAIN(%r15)
+	stg	%r1,304(%r15)
+	stmg	%r0,%r13,184(%r15)
+	stg	%r14,176(%r15)
+	lgr	%r2,%r14
+	aghi	%r2,-MCOUNT_INSN_SIZE
+	lg	%r3,344(%r15)
+	stg	%r3,296(%r15)
+	larl	%r4,function_trace_op
+	lg	%r4,0(%r4)
+	lgr	%r5, %r15
+	aghi	%r5, 160
+	larl	%r14,ftrace_trace_function
+	lg	%r14,0(%r14)
+	basr	%r14,%r14
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	lg	%r2,344(%r15)
+	lg	%r3,448(%r15)
+ENTRY(ftrace_regs_graph_caller)
+# The bras instruction gets runtime patched to call prepare_ftrace_return.

arch/s390/kernel/mcount64.S ENTRY(ftrace_graph_caller) · line 88

Quoted 10 lines
arch/s390/kernel/mcount64.S +10 -0
+# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
+#	bras	%r14,prepare_ftrace_return
+	bras	%r14,0f
+0:	stg	%r2,344(%r15)
+#endif
+	lmg	%r0,%r13,184(%r15)
+	lg	%r14,176(%r15)
+	aghi	%r15,336
+	br	%r14
+#endif

Some objections: this code assumes that sizeof(struct pt_regs) does not change, which is not correct. So as soon as we touch struct pt_regs this code would be broken. Also the order of the members within struct pt_regs is not necessarily static (pt_regs is not ABI).

So using the supplied asm-offsets.c offsets within the pt_regs structure would be the way to go.

In addition I don't like the code duplication. This is nearly an identical copy of ftrace_caller, except that it (partially) creates a pt_regs structure on the stack. I'd rather change the existing ftrace_caller code to do that unconditionally.

However, what I _really_ do not like is the odd usage of r14 to create a malformed psw member within the pt_regs structure, and thus omitting r14 from the gprs array.

#2 lore raw
Quoted 26 lines · Heiko Carstens
Quoted 11 lines · Vojtech Pavlik

Add support for DYNAMIC_FTRACE_WITH_REGS to 64-bit and 31-bit s390 architectures. This is required for kGraft and kpatch to work on s390.

It's done by adding a _regs variant of ftrace_caller that preserves registers and puts them on stack in a struct pt_regs layout and allows modification of return address by changing the PSW (instruction pointer) member od struct pt_regs.

So I assume you use the instruction_pointer() macro to access the return address then?

All of this seems a bit of a hack to me.. the natural place of the return address of a function would be register 14, and not the psw member of the pt_regs structure.

It's then also inconsistent to only save register r0-r13 to the gprs member.. well, you can't save r14, since what should happen if both r14 in the gprs member of pt_regs and in the psw part would have been changed?

Besides that a couple more comments below.

[...]

Quoted 4 lines

Some objections: this code assumes that sizeof(struct pt_regs) does not change, which is not correct. So as soon as we touch struct pt_regs this code would be broken. Also the order of the members within struct pt_regs is not necessarily static (pt_regs is not ABI).

FWIW, this already happened with d3a73acbc26a4a81a01a35fd162973e53d0386f5 "s390: split TIF bits into CIF, PIF and TIF bits".

Anyway, since I didn't got any response from you during the last couple of weeks, I changed the ftrace code so it should fit your needs.
I will send five patches in reply to this mail - patch 4 of 5 is the one that implements the DYNAMIC_FTRACE_WITH_REGS functionality, how differently to your patch, especially possible return address changing.

#3 lore raw

PATCH 1/5 s390: pass march flag to assembly files as well

Currently the march flag gets only passed to C files, but not to assembler files.
This means that we can't add new instructions like e.g. aghik to asm files, since the assembler doesn't know of the new instructions if the appropriate march flag isn't specified.

So also pass the march flag when compiling assembler files as well.

---
 arch/s390/Makefile | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
arch/s390/Makefile +10 -7
index 874e6d6e9c5f..878e67973151 100644
@@ -35,13 +35,16 @@ endif
 
 export LD_BFD
 
-cflags-$(CONFIG_MARCH_G5)     += -march=g5
-cflags-$(CONFIG_MARCH_Z900)   += -march=z900
-cflags-$(CONFIG_MARCH_Z990)   += -march=z990
-cflags-$(CONFIG_MARCH_Z9_109) += -march=z9-109
-cflags-$(CONFIG_MARCH_Z10)    += -march=z10
-cflags-$(CONFIG_MARCH_Z196)   += -march=z196
-cflags-$(CONFIG_MARCH_ZEC12)  += -march=zEC12
+mflags-$(CONFIG_MARCH_G5)     := -march=g5
+mflags-$(CONFIG_MARCH_Z900)   := -march=z900
+mflags-$(CONFIG_MARCH_Z990)   := -march=z990
+mflags-$(CONFIG_MARCH_Z9_109) := -march=z9-109
+mflags-$(CONFIG_MARCH_Z10)    := -march=z10
+mflags-$(CONFIG_MARCH_Z196)   := -march=z196
+mflags-$(CONFIG_MARCH_ZEC12)  := -march=zEC12
+
+aflags-y += $(mflags-y)
+cflags-y += $(mflags-y)
 
 cflags-$(CONFIG_MARCH_G5_TUNE)		+= -mtune=g5
 cflags-$(CONFIG_MARCH_Z900_TUNE)	+= -mtune=z900
Signature · 1 line
1.8.5.5
#4 lore raw

PATCH 2/5 s390/ftrace: optimize patched mcount calling code

In reply to Heiko Carstens

We can skip executing the first "stg" instruction of the patched and disabled mcount code in function tracer enabled kernels. This saves one instruction per function.

---
 arch/s390/include/asm/ftrace.h |  2 +-
 arch/s390/kernel/ftrace.c      | 16 ++++++++--------
 scripts/recordmcount.c         |  2 +-
 scripts/recordmcount.pl        |  2 +-
 4 files changed, 11 insertions(+), 11 deletions(-)
arch/s390/include/asm/ftrace.h +1 -1
index bf246dae1367..4b264caa0704 100644
@@ -18,7 +18,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_64BIT
-#define MCOUNT_INSN_SIZE  12
+#define MCOUNT_INSN_SIZE  18
 #else
 #define MCOUNT_INSN_SIZE  22
 #endif
arch/s390/kernel/ftrace.c +8 -8
index 54d6493c4a56..ae4141fbcb07 100644
@@ -25,22 +25,22 @@ void ftrace_enable_insn(void);
 #ifdef CONFIG_64BIT
 /*
  * The 64-bit mcount code looks like this:
- *	stg	%r14,8(%r15)		# offset 0
+ * >	stg	%r14,8(%r15)		# offset 0
  * >	larl	%r1,<&counter>		# offset 6
  * >	brasl	%r14,_mcount		# offset 12
  *	lg	%r14,8(%r15)		# offset 18
- * Total length is 24 bytes. The middle two instructions of the mcount
+ * Total length is 24 bytes. The first three instructions of the mcount
  * block get overwritten by ftrace_make_nop / ftrace_make_call.
  * The 64-bit enabled ftrace code block looks like this:
- *	stg	%r14,8(%r15)		# offset 0
+ * >	stg	%r14,8(%r15)		# offset 0
  * >	lg	%r1,__LC_FTRACE_FUNC	# offset 6
  * >	lgr	%r0,%r0			# offset 12
  * >	basr	%r14,%r1		# offset 16
  *	lg	%r14,8(%15)		# offset 18
  * The return points of the mcount/ftrace function have the same offset 18.
  * The 64-bit disable ftrace code block looks like this:
- *	stg	%r14,8(%r15)		# offset 0
- * >	jg	.+18			# offset 6
+ * >	jg	.+24			# offset 6
+ * >	lg	%r1,__LC_FTRACE_FUNC	# offset 6
  * >	lgr	%r0,%r0			# offset 12
  * >	basr	%r14,%r1		# offset 16
  *	lg	%r14,8(%15)		# offset 18
@@ -50,13 +50,13 @@ void ftrace_enable_insn(void);
 asm(
 	"	.align	4\n"
 	"ftrace_disable_code:\n"
-	"	jg	0f\n"
+	"	jg	.+24\n"
+	"	lg	%r1,"__stringify(__LC_FTRACE_FUNC)"\n"
 	"	lgr	%r0,%r0\n"
 	"	basr	%r14,%r1\n"
-	"0:\n"
 	"	.align	4\n"
 	"ftrace_enable_insn:\n"
-	"	lg	%r1,"__stringify(__LC_FTRACE_FUNC)"\n");
+	"	stg	%r14,8(%r15)\n");
 
 #define FTRACE_INSN_SIZE	6
 
scripts/recordmcount.c +1 -1
index 650ecc83d7d7..efca581d8553 100644
@@ -408,7 +408,7 @@ do_file(char const *const fname)
 		}
 		if (w2(ghdr->e_machine) == EM_S390) {
 			reltype = R_390_64;
-			mcount_adjust_64 = -8;
+			mcount_adjust_64 = -14;
 		}
 		if (w2(ghdr->e_machine) == EM_MIPS) {
 			reltype = R_MIPS_64;
scripts/recordmcount.pl +1 -1
index 397b6b84e8c5..2e260fc27a60 100755
@@ -250,7 +250,7 @@ if ($arch eq "x86_64") {
 
 } elsif ($arch eq "s390" && $bits == 64) {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
-    $mcount_adjust = -8;
+    $mcount_adjust = -14;
     $alignment = 8;
     $type = ".quad";
     $ld .= " -m elf64_s390";
Signature · 1 line
1.8.5.5
#5 lore raw

PATCH 3/5 s390/ftrace: optimize function graph caller code

In reply to Heiko Carstens

When the function graph tracer is disabled we can skip three additional instructions. So let's just do just this.

So if function tracing is enabled but function graph tracing is runtime disabled, we get away with a single unconditional branch.

---
 arch/s390/include/asm/ftrace.h |  1 +
 arch/s390/kernel/ftrace.c      | 24 ++++++++++++++++++++++++
 arch/s390/kernel/mcount64.S    | 15 +++++++++------
 3 files changed, 34 insertions(+), 6 deletions(-)
arch/s390/include/asm/ftrace.h +1 -0
index 4b264caa0704..874f903c2eb4 100644
@@ -4,6 +4,7 @@
 #ifndef __ASSEMBLY__
 
 extern void _mcount(void);
+extern char ftrace_graph_caller_end;
 
 struct dyn_arch_ftrace { };
 
arch/s390/kernel/ftrace.c +24 -0
index ae4141fbcb07..7dc7df3857c4 100644
@@ -170,6 +170,29 @@ out:
  * directly after the instructions. To enable the call we calculate
  * the original offset to prepare_ftrace_return and put it back.
  */
+
+#ifdef CONFIG_64BIT
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	static unsigned short offset = 0x0002;
+
+	return probe_kernel_write((void *) ftrace_graph_caller + 2,
+				  &offset, sizeof(offset));
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	unsigned short offset;
+
+	offset = ((void *) &ftrace_graph_caller_end -
+		  (void *) ftrace_graph_caller) / 2;
+	return probe_kernel_write((void *) ftrace_graph_caller + 2,
+				  &offset, sizeof(offset));
+}
+
+#else /* CONFIG_64BIT */
+
 int ftrace_enable_ftrace_graph_caller(void)
 {
 	unsigned short offset;
@@ -188,5 +211,6 @@ int ftrace_disable_ftrace_graph_caller(void)
 				  &offset, sizeof(offset));
 }
 
+#endif /* CONFIG_64BIT */
 #endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
arch/s390/kernel/mcount64.S +9 -6
index c67a8bf0fd9a..b03896d29274 100644
@@ -32,14 +32,17 @@ ENTRY(ftrace_caller)
 	lg	%r14,0(%r14)
 	basr	%r14,%r14
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+# The j instruction gets runtime patched to a nop instruction.
+# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
+#	j	.+2
+ENTRY(ftrace_graph_caller)
+	j	ftrace_graph_caller_end
 	lg	%r2,168(%r15)
 	lg	%r3,272(%r15)
-ENTRY(ftrace_graph_caller)
-# The bras instruction gets runtime patched to call prepare_ftrace_return.
-# See ftrace_enable_ftrace_graph_caller. The patched instruction is:
-#	bras	%r14,prepare_ftrace_return
-	bras	%r14,0f
-0:	stg	%r2,168(%r15)
+	brasl	%r14,prepare_ftrace_return
+	stg	%r2,168(%r15)
+ftrace_graph_caller_end:
+	.globl	ftrace_graph_caller_end
 #endif
 	aghi	%r15,160
 	lmg	%r2,%r5,32(%r15)
Signature · 1 line
1.8.5.5
#6 lore raw

PATCH 4/5 s390/ftrace: add HAVE_DYNAMIC_FTRACE_WITH_REGS support

In reply to Heiko Carstens

This code is based on a patch from Vojtech Pavlik.
http://marc.info/?l=linux-s390&m=140438885114413&w=2

The actual implementation now differs significantly:
Instead of adding a second function "ftrace_regs_caller" which would be nearly identical to the existing ftrace_caller function, the current ftrace_caller function is now an alias to ftrace_regs_caller and always passes the needed pt_regs structure and function_trace_op parameters unconditionally.

Besides that also use asm offsets to correctly allocate and access the new struct pt_regs on the stack.

While at it we can make use of new instruction to get rid of some indirect loads if compiled for new machines.

The passed struct pt_regs can be changed by the called function and it's new contents will replace the current contents. E.g. r14 can be modified to change the return address of a traced function.

We explicitly do not use the psw_t member of struct pt_regs to pass (and modify) r14, since that would result in a fake psw where the mask member is invalid. In addition r14 and the psw_t member have different semantics anyway.

Cc Vojtech Pavlik <[email protected]>
Cc Jiri Kosina <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Steven Rostedt <[email protected]>
---
 arch/s390/Kconfig              |  1 +
 arch/s390/include/asm/ftrace.h |  4 ++++
 arch/s390/kernel/ftrace.c      |  5 +++++
 arch/s390/kernel/mcount64.S    | 45 ++++++++++++++++++++++++++++--------------
 4 files changed, 40 insertions(+), 15 deletions(-)
arch/s390/Kconfig +1 -0
index ab39ceb89ecf..2d935cb77393 100644
@@ -116,6 +116,7 @@ config S390
 	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_DYNAMIC_FTRACE_WITH_REGS if 64BIT
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
arch/s390/include/asm/ftrace.h +4 -0
index 874f903c2eb4..d419362dc231 100644
@@ -24,4 +24,8 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #define MCOUNT_INSN_SIZE  22
 #endif
 
+#ifdef CONFIG_64BIT
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#endif
+
 #endif /* _ASM_S390_FTRACE_H */
arch/s390/kernel/ftrace.c +5 -0
index 7dc7df3857c4..69eb49ccf8a4 100644
@@ -107,6 +107,11 @@ asm(
 
 #endif /* CONFIG_64BIT */
 
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+		       unsigned long addr)
+{
+	return 0;
+}
 
 int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
 		    unsigned long addr)
arch/s390/kernel/mcount64.S +30 -15

85 lines not on this page · raw message

Signature · 1 line
1.8.5.5
#7 lore raw

PATCH 5/5 s390/ftrace: enforce DYNAMIC_FTRACE if FUNCTION_TRACER is selected

In reply to Heiko Carstens

We have too many combinations for function tracing. Lets simply stick to the most advanced option, so we don't have to care of other combinations.

This means we always select DYNAMIC_FTRACE if FUNCTION_TRACER is selected.

In the s390 Makefile also remove CONFIG_FTRACE_SYSCALLS since that functionality got moved to architecture independent code in the meantime.

---
 arch/s390/Kconfig           | 1 +
 arch/s390/kernel/Makefile   | 4 +---
 arch/s390/kernel/ftrace.c   | 6 ------
 arch/s390/kernel/mcount.S   | 2 --
 arch/s390/kernel/mcount64.S | 2 --
 5 files changed, 2 insertions(+), 13 deletions(-)
arch/s390/Kconfig +1 -0
index 2d935cb77393..a8cbc72837d0 100644
@@ -99,6 +99,7 @@ config S390
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select BUILDTIME_EXTABLE_SORT
 	select CLONE_BACKWARDS2
+	select DYNAMIC_FTRACE if FUNCTION_TRACER
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CPU_DEVICES if !SMP
 	select GENERIC_FIND_FIRST_BIT
arch/s390/kernel/Makefile +1 -3
index a95c4ca99617..d44245d4df37 100644
@@ -53,9 +53,7 @@ obj-$(CONFIG_COMPAT)		+= compat_wrapper.o $(compat-obj-y)
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_FUNCTION_TRACER)	+= $(if $(CONFIG_64BIT),mcount64.o,mcount.o)
-obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
-obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
-obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
+obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 
 ifdef CONFIG_64BIT
arch/s390/kernel/ftrace.c +0 -6
index 69eb49ccf8a4..40d4da7c9f8a 100644
@@ -17,8 +17,6 @@
 #include <asm/asm-offsets.h>
 #include "entry.h"
 
-#ifdef CONFIG_DYNAMIC_FTRACE
-
 void ftrace_disable_code(void);
 void ftrace_enable_insn(void);
 
@@ -140,8 +138,6 @@ int __init ftrace_dyn_arch_init(void)
 	return 0;
 }
 
-#endif /* CONFIG_DYNAMIC_FTRACE */
-
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Hook the return address and push it in the stack of return addresses
@@ -167,7 +163,6 @@ out:
 	return parent;
 }
 
-#ifdef CONFIG_DYNAMIC_FTRACE
 /*
  * Patch the kernel code at ftrace_graph_caller location. The instruction
  * there is branch relative and save to prepare_ftrace_return. To disable
@@ -217,5 +212,4 @@ int ftrace_disable_ftrace_graph_caller(void)
 }
 
 #endif /* CONFIG_64BIT */
-#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
arch/s390/kernel/mcount.S +0 -2
index 433c6dbfa442..be6dbd9a81a7 100644
@@ -15,11 +15,9 @@ ENTRY(ftrace_stub)
 	br	%r14
 
 ENTRY(_mcount)
-#ifdef CONFIG_DYNAMIC_FTRACE
 	br	%r14
 
 ENTRY(ftrace_caller)
-#endif
 	stm	%r2,%r5,16(%r15)
 	bras	%r1,1f
 0:	.long	ftrace_trace_function
arch/s390/kernel/mcount64.S +0 -2
index 92f8994f37b8..5c7b506ef44d 100644
@@ -21,13 +21,11 @@ ENTRY(ftrace_stub)
 #define STACK_PTREGS_GPRS (STACK_PTREGS + __PT_GPRS)
 
 ENTRY(_mcount)
-#ifdef CONFIG_DYNAMIC_FTRACE
 	br	%r14
 
 ENTRY(ftrace_caller)
 	.globl	ftrace_regs_caller
 	.set	ftrace_regs_caller,ftrace_caller
-#endif
 	lgr	%r1,%r15
 	aghi	%r15,-STACK_FRAME_SIZE
 	stg	%r1,__SF_BACKCHAIN(%r15)
Signature · 1 line
1.8.5.5