aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/Makefile10
-rw-r--r--arch/s390/include/asm/ftrace.h15
-rw-r--r--arch/s390/kernel/Makefile4
-rw-r--r--arch/s390/kernel/ftrace.c15
-rw-r--r--arch/s390/kernel/kprobes.c3
-rw-r--r--arch/s390/kernel/mcount.S2
-rwxr-xr-xscripts/recordmcount.pl9
8 files changed, 52 insertions, 7 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 7eba5b5723e9..8d11babf9aa5 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -117,7 +117,6 @@ config S390
117 select HAVE_BPF_JIT if 64BIT && PACK_STACK 117 select HAVE_BPF_JIT if 64BIT && PACK_STACK
118 select HAVE_CMPXCHG_DOUBLE 118 select HAVE_CMPXCHG_DOUBLE
119 select HAVE_CMPXCHG_LOCAL 119 select HAVE_CMPXCHG_LOCAL
120 select HAVE_C_RECORDMCOUNT
121 select HAVE_DEBUG_KMEMLEAK 120 select HAVE_DEBUG_KMEMLEAK
122 select HAVE_DYNAMIC_FTRACE if 64BIT 121 select HAVE_DYNAMIC_FTRACE if 64BIT
123 select HAVE_DYNAMIC_FTRACE_WITH_REGS if 64BIT 122 select HAVE_DYNAMIC_FTRACE_WITH_REGS if 64BIT
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index e742ec5de9a7..acb6859c6a95 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -87,6 +87,16 @@ ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
87cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack 87cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
88endif 88endif
89 89
90ifdef CONFIG_FUNCTION_TRACER
91# make use of hotpatch feature if the compiler supports it
92cc_hotpatch := -mhotpatch=0,3
93ifeq ($(call cc-option-yn,$(cc_hotpatch)),y)
94CC_FLAGS_FTRACE := $(cc_hotpatch)
95KBUILD_AFLAGS += -DCC_USING_HOTPATCH
96KBUILD_CFLAGS += -DCC_USING_HOTPATCH
97endif
98endif
99
90KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y) 100KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y)
91KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare 101KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare
92KBUILD_AFLAGS += $(aflags-y) 102KBUILD_AFLAGS += $(aflags-y)
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h
index abb618f1ead2..836c56290499 100644
--- a/arch/s390/include/asm/ftrace.h
+++ b/arch/s390/include/asm/ftrace.h
@@ -3,8 +3,12 @@
3 3
4#define ARCH_SUPPORTS_FTRACE_OPS 1 4#define ARCH_SUPPORTS_FTRACE_OPS 1
5 5
6#ifdef CC_USING_HOTPATCH
7#define MCOUNT_INSN_SIZE 6
8#else
6#define MCOUNT_INSN_SIZE 24 9#define MCOUNT_INSN_SIZE 24
7#define MCOUNT_RETURN_FIXUP 18 10#define MCOUNT_RETURN_FIXUP 18
11#endif
8 12
9#ifndef __ASSEMBLY__ 13#ifndef __ASSEMBLY__
10 14
@@ -37,18 +41,29 @@ struct ftrace_insn {
37static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn) 41static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn)
38{ 42{
39#ifdef CONFIG_FUNCTION_TRACER 43#ifdef CONFIG_FUNCTION_TRACER
44#ifdef CC_USING_HOTPATCH
45 /* brcl 0,0 */
46 insn->opc = 0xc004;
47 insn->disp = 0;
48#else
40 /* jg .+24 */ 49 /* jg .+24 */
41 insn->opc = 0xc0f4; 50 insn->opc = 0xc0f4;
42 insn->disp = MCOUNT_INSN_SIZE / 2; 51 insn->disp = MCOUNT_INSN_SIZE / 2;
43#endif 52#endif
53#endif
44} 54}
45 55
46static inline int is_ftrace_nop(struct ftrace_insn *insn) 56static inline int is_ftrace_nop(struct ftrace_insn *insn)
47{ 57{
48#ifdef CONFIG_FUNCTION_TRACER 58#ifdef CONFIG_FUNCTION_TRACER
59#ifdef CC_USING_HOTPATCH
60 if (insn->disp == 0)
61 return 1;
62#else
49 if (insn->disp == MCOUNT_INSN_SIZE / 2) 63 if (insn->disp == MCOUNT_INSN_SIZE / 2)
50 return 1; 64 return 1;
51#endif 65#endif
66#endif
52 return 0; 67 return 0;
53} 68}
54 69
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 204c43a4c245..31fab2676fe9 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -4,8 +4,8 @@
4 4
5ifdef CONFIG_FUNCTION_TRACER 5ifdef CONFIG_FUNCTION_TRACER
6# Don't trace early setup code and tracing code 6# Don't trace early setup code and tracing code
7CFLAGS_REMOVE_early.o = -pg 7CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE)
8CFLAGS_REMOVE_ftrace.o = -pg 8CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
9endif 9endif
10 10
11# 11#
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 3dabcae40e04..82c19899574f 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -46,6 +46,13 @@
46 * lg %r14,8(%r15) # offset 18 46 * lg %r14,8(%r15) # offset 18
47 * The jg instruction branches to offset 24 to skip as many instructions 47 * The jg instruction branches to offset 24 to skip as many instructions
48 * as possible. 48 * as possible.
49 * In case we use gcc's hotpatch feature the original and also the disabled
50 * function prologue contains only a single six byte instruction and looks
51 * like this:
52 * > brcl 0,0 # offset 0
53 * To enable ftrace the code gets patched like above and afterwards looks
54 * like this:
55 * > brasl %r0,ftrace_caller # offset 0
49 */ 56 */
50 57
51unsigned long ftrace_plt; 58unsigned long ftrace_plt;
@@ -64,9 +71,15 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
64 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) 71 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
65 return -EFAULT; 72 return -EFAULT;
66 if (addr == MCOUNT_ADDR) { 73 if (addr == MCOUNT_ADDR) {
67 /* Initial code replacement; we expect to see stg r14,8(r15) */ 74 /* Initial code replacement */
75#ifdef CC_USING_HOTPATCH
76 /* We expect to see brcl 0,0 */
77 ftrace_generate_nop_insn(&orig);
78#else
79 /* We expect to see stg r14,8(r15) */
68 orig.opc = 0xe3e0; 80 orig.opc = 0xe3e0;
69 orig.disp = 0xf0080024; 81 orig.disp = 0xf0080024;
82#endif
70 ftrace_generate_nop_insn(&new); 83 ftrace_generate_nop_insn(&new);
71 } else if (old.opc == BREAKPOINT_INSTRUCTION) { 84 } else if (old.opc == BREAKPOINT_INSTRUCTION) {
72 /* 85 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 1e4c710dfb92..f516edc1fbe3 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -69,7 +69,8 @@ static void copy_instruction(struct kprobe *p)
69 /* 69 /*
70 * If kprobes patches the instruction that is morphed by 70 * If kprobes patches the instruction that is morphed by
71 * ftrace make sure that kprobes always sees the branch 71 * ftrace make sure that kprobes always sees the branch
72 * "jg .+24" that skips the mcount block 72 * "jg .+24" that skips the mcount block or the "brcl 0,0"
73 * in case of hotpatch.
73 */ 74 */
74 ftrace_generate_nop_insn((struct ftrace_insn *)p->ainsn.insn); 75 ftrace_generate_nop_insn((struct ftrace_insn *)p->ainsn.insn);
75 p->ainsn.is_ftrace_insn = 1; 76 p->ainsn.is_ftrace_insn = 1;
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index b6dfc5bfcb89..e499370fbccb 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -27,7 +27,9 @@ ENTRY(ftrace_caller)
27 .globl ftrace_regs_caller 27 .globl ftrace_regs_caller
28 .set ftrace_regs_caller,ftrace_caller 28 .set ftrace_regs_caller,ftrace_caller
29 lgr %r1,%r15 29 lgr %r1,%r15
30#ifndef CC_USING_HOTPATCH
30 aghi %r0,MCOUNT_RETURN_FIXUP 31 aghi %r0,MCOUNT_RETURN_FIXUP
32#endif
31 aghi %r15,-STACK_FRAME_SIZE 33 aghi %r15,-STACK_FRAME_SIZE
32 stg %r1,__SF_BACKCHAIN(%r15) 34 stg %r1,__SF_BACKCHAIN(%r15)
33 stg %r1,(STACK_PTREGS_GPRS+15*8)(%r15) 35 stg %r1,(STACK_PTREGS_GPRS+15*8)(%r15)
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 56ea99a12ab7..be39be0abefc 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -242,8 +242,13 @@ if ($arch eq "x86_64") {
242 $cc .= " -m32"; 242 $cc .= " -m32";
243 243
244} elsif ($arch eq "s390" && $bits == 64) { 244} elsif ($arch eq "s390" && $bits == 64) {
245 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$"; 245 if ($cc =~ /-DCC_USING_HOTPATCH/) {
246 $mcount_adjust = -14; 246 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$";
247 $mcount_adjust = 0;
248 } else {
249 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
250 $mcount_adjust = -14;
251 }
247 $alignment = 8; 252 $alignment = 8;
248 $type = ".quad"; 253 $type = ".quad";
249 $ld .= " -m elf64_s390"; 254 $ld .= " -m elf64_s390";