diff options
-rw-r--r-- | arch/s390/Kconfig | 1 | ||||
-rw-r--r-- | arch/s390/Makefile | 10 | ||||
-rw-r--r-- | arch/s390/include/asm/ftrace.h | 15 | ||||
-rw-r--r-- | arch/s390/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/s390/kernel/ftrace.c | 15 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/mcount.S | 2 | ||||
-rwxr-xr-x | scripts/recordmcount.pl | 9 |
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) | |||
87 | cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack | 87 | cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack |
88 | endif | 88 | endif |
89 | 89 | ||
90 | ifdef CONFIG_FUNCTION_TRACER | ||
91 | # make use of hotpatch feature if the compiler supports it | ||
92 | cc_hotpatch := -mhotpatch=0,3 | ||
93 | ifeq ($(call cc-option-yn,$(cc_hotpatch)),y) | ||
94 | CC_FLAGS_FTRACE := $(cc_hotpatch) | ||
95 | KBUILD_AFLAGS += -DCC_USING_HOTPATCH | ||
96 | KBUILD_CFLAGS += -DCC_USING_HOTPATCH | ||
97 | endif | ||
98 | endif | ||
99 | |||
90 | KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y) | 100 | KBUILD_CFLAGS += -mbackchain -msoft-float $(cflags-y) |
91 | KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare | 101 | KBUILD_CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare |
92 | KBUILD_AFLAGS += $(aflags-y) | 102 | KBUILD_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 { | |||
37 | static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn) | 41 | static 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 | ||
46 | static inline int is_ftrace_nop(struct ftrace_insn *insn) | 56 | static 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 | ||
5 | ifdef CONFIG_FUNCTION_TRACER | 5 | ifdef CONFIG_FUNCTION_TRACER |
6 | # Don't trace early setup code and tracing code | 6 | # Don't trace early setup code and tracing code |
7 | CFLAGS_REMOVE_early.o = -pg | 7 | CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE) |
8 | CFLAGS_REMOVE_ftrace.o = -pg | 8 | CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) |
9 | endif | 9 | endif |
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 | ||
51 | unsigned long ftrace_plt; | 58 | unsigned 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"; |