From dfd9f7abc0fb67b5781f340d982384cea53b2884 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Jun 2009 10:26:44 +0200 Subject: [S390] ftrace: add dynamic ftrace support Dynamic ftrace support for s390. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/mcount.S | 119 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 27 deletions(-) (limited to 'arch/s390/kernel/mcount.S') diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index 80641224a09..de274996f64 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S @@ -1,5 +1,5 @@ /* - * Copyright IBM Corp. 2008 + * Copyright IBM Corp. 2008,2009 * * Author(s): Heiko Carstens , * @@ -7,36 +7,46 @@ #include -#ifndef CONFIG_64BIT -.globl _mcount + .globl ftrace_stub +ftrace_stub: + br %r14 + +#ifdef CONFIG_64BIT + +#ifdef CONFIG_DYNAMIC_FTRACE + + .globl _mcount _mcount: - stm %r0,%r5,8(%r15) - st %r14,56(%r15) - lr %r1,%r15 - ahi %r15,-96 - l %r3,100(%r15) - la %r2,0(%r14) - st %r1,__SF_BACKCHAIN(%r15) - la %r3,0(%r3) - bras %r14,0f - .long ftrace_trace_function -0: l %r14,0(%r14) - l %r14,0(%r14) - basr %r14,%r14 - ahi %r15,96 - lm %r0,%r5,8(%r15) - l %r14,56(%r15) br %r14 -.globl ftrace_stub -ftrace_stub: + .globl ftrace_caller +ftrace_caller: + stmg %r2,%r5,32(%r15) + stg %r14,112(%r15) + lgr %r1,%r15 + aghi %r15,-160 + stg %r1,__SF_BACKCHAIN(%r15) + lgr %r2,%r14 + lg %r3,168(%r15) + larl %r14,ftrace_dyn_func + lg %r14,0(%r14) + basr %r14,%r14 + aghi %r15,160 + lmg %r2,%r5,32(%r15) + lg %r14,112(%r15) br %r14 -#else /* CONFIG_64BIT */ + .data + .globl ftrace_dyn_func +ftrace_dyn_func: + .quad ftrace_stub + .previous + +#else /* CONFIG_DYNAMIC_FTRACE */ -.globl _mcount + .globl _mcount _mcount: - stmg %r0,%r5,16(%r15) + stmg %r2,%r5,32(%r15) stg %r14,112(%r15) lgr %r1,%r15 aghi %r15,-160 @@ -47,12 +57,67 @@ _mcount: lg %r14,0(%r14) basr %r14,%r14 aghi %r15,160 - lmg %r0,%r5,16(%r15) + lmg %r2,%r5,32(%r15) lg %r14,112(%r15) br %r14 -.globl ftrace_stub -ftrace_stub: +#endif /* CONFIG_DYNAMIC_FTRACE */ + +#else /* CONFIG_64BIT */ + +#ifdef CONFIG_DYNAMIC_FTRACE + + .globl _mcount +_mcount: + br %r14 + + .globl ftrace_caller +ftrace_caller: + stm %r2,%r5,16(%r15) + st %r14,56(%r15) + lr %r1,%r15 + ahi %r15,-96 + l %r3,100(%r15) + la %r2,0(%r14) + st %r1,__SF_BACKCHAIN(%r15) + la %r3,0(%r3) + bras %r14,0f + .long ftrace_dyn_func +0: l %r14,0(%r14) + l %r14,0(%r14) + basr %r14,%r14 + ahi %r15,96 + lm %r2,%r5,16(%r15) + l %r14,56(%r15) + br %r14 + + .data + .globl ftrace_dyn_func +ftrace_dyn_func: + .long ftrace_stub + .previous + +#else /* CONFIG_DYNAMIC_FTRACE */ + + .globl _mcount +_mcount: + stm %r2,%r5,16(%r15) + st %r14,56(%r15) + lr %r1,%r15 + ahi %r15,-96 + l %r3,100(%r15) + la %r2,0(%r14) + st %r1,__SF_BACKCHAIN(%r15) + la %r3,0(%r3) + bras %r14,0f + .long ftrace_trace_function +0: l %r14,0(%r14) + l %r14,0(%r14) + basr %r14,%r14 + ahi %r15,96 + lm %r2,%r5,16(%r15) + l %r14,56(%r15) br %r14 +#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_64BIT */ -- cgit v1.2.3-70-g09d2 From 8b4488f85d619253c9e631ec723368f400106771 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Jun 2009 10:26:45 +0200 Subject: [S390] ftrace: add function trace mcount test support Add support for early test if the function tracer is enabled or disabled. Saves some extra function calls. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + arch/s390/kernel/mcount.S | 38 ++++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) (limited to 'arch/s390/kernel/mcount.S') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index b674e79044a..480590f2157 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -82,6 +82,7 @@ config S390 select USE_GENERIC_SMP_HELPERS if SMP select HAVE_SYSCALL_WRAPPERS select HAVE_FUNCTION_TRACER + select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE select HAVE_DEFAULT_NO_SPIN_MUTEXES diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index de274996f64..0aa85ec94d0 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S @@ -21,6 +21,9 @@ _mcount: .globl ftrace_caller ftrace_caller: + larl %r1,function_trace_stop + icm %r1,0xf,0(%r1) + bnzr %r14 stmg %r2,%r5,32(%r15) stg %r14,112(%r15) lgr %r1,%r15 @@ -46,6 +49,9 @@ ftrace_dyn_func: .globl _mcount _mcount: + larl %r1,function_trace_stop + icm %r1,0xf,0(%r1) + bnzr %r14 stmg %r2,%r5,32(%r15) stg %r14,112(%r15) lgr %r1,%r15 @@ -74,21 +80,25 @@ _mcount: .globl ftrace_caller ftrace_caller: stm %r2,%r5,16(%r15) + bras %r1,2f +0: .long ftrace_trace_function +1: .long function_trace_stop +2: l %r2,1b-0b(%r1) + icm %r2,0xf,0(%r2) + jnz 3f st %r14,56(%r15) - lr %r1,%r15 + lr %r0,%r15 ahi %r15,-96 l %r3,100(%r15) la %r2,0(%r14) - st %r1,__SF_BACKCHAIN(%r15) + st %r0,__SF_BACKCHAIN(%r15) la %r3,0(%r3) - bras %r14,0f - .long ftrace_dyn_func -0: l %r14,0(%r14) + l %r14,0b-0b(%r1) l %r14,0(%r14) basr %r14,%r14 ahi %r15,96 - lm %r2,%r5,16(%r15) l %r14,56(%r15) +3: lm %r2,%r5,16(%r15) br %r14 .data @@ -102,21 +112,25 @@ ftrace_dyn_func: .globl _mcount _mcount: stm %r2,%r5,16(%r15) + bras %r1,2f +0: .long ftrace_trace_function +1: .long function_trace_stop +2: l %r2,1b-0b(%r1) + icm %r2,0xf,0(%r2) + jnz 3f st %r14,56(%r15) - lr %r1,%r15 + lr %r0,%r15 ahi %r15,-96 l %r3,100(%r15) la %r2,0(%r14) - st %r1,__SF_BACKCHAIN(%r15) + st %r0,__SF_BACKCHAIN(%r15) la %r3,0(%r3) - bras %r14,0f - .long ftrace_trace_function -0: l %r14,0(%r14) + l %r14,0b-0b(%r1) l %r14,0(%r14) basr %r14,%r14 ahi %r15,96 - lm %r2,%r5,16(%r15) l %r14,56(%r15) +3: lm %r2,%r5,16(%r15) br %r14 #endif /* CONFIG_DYNAMIC_FTRACE */ -- cgit v1.2.3-70-g09d2 From 88dbd2037229bd2ed7543ffd0d8f2d9dec9d31d2 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Jun 2009 10:26:46 +0200 Subject: [S390] ftrace: add function graph tracer support Function graph tracer support for s390. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + arch/s390/include/asm/ftrace.h | 10 +++--- arch/s390/kernel/Makefile | 6 ++-- arch/s390/kernel/ftrace.c | 72 ++++++++++++++++++++++++++++++++++++++ arch/s390/kernel/mcount.S | 79 ++++++++++++++++++++++++++++++++++++++++++ arch/s390/kernel/s390_ext.c | 3 +- arch/s390/kernel/time.c | 2 +- arch/s390/kernel/vmlinux.lds.S | 1 + drivers/s390/cio/cio.c | 4 +-- 9 files changed, 166 insertions(+), 12 deletions(-) (limited to 'arch/s390/kernel/mcount.S') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 480590f2157..9023cc900bd 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -85,6 +85,7 @@ config S390 select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE + select HAVE_FUNCTION_GRAPH_TRACER select HAVE_DEFAULT_NO_SPIN_MUTEXES select HAVE_OPROFILE select HAVE_KPROBES diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index ba23d8f97d0..96c14a9102b 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h @@ -11,11 +11,13 @@ struct dyn_arch_ftrace { }; #define MCOUNT_ADDR ((long)_mcount) #ifdef CONFIG_64BIT -#define MCOUNT_INSN_SIZE 24 -#define MCOUNT_OFFSET 14 +#define MCOUNT_OFFSET_RET 18 +#define MCOUNT_INSN_SIZE 24 +#define MCOUNT_OFFSET 14 #else -#define MCOUNT_INSN_SIZE 30 -#define MCOUNT_OFFSET 8 +#define MCOUNT_OFFSET_RET 26 +#define MCOUNT_INSN_SIZE 30 +#define MCOUNT_OFFSET 8 #endif static inline unsigned long ftrace_call_adjust(unsigned long addr) diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index ce172bfaab8..c75ed43b1a1 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -3,11 +3,8 @@ # ifdef CONFIG_FUNCTION_TRACER -# Do not trace early boot code +# Don't trace early setup code and tracing code CFLAGS_REMOVE_early.o = -pg -endif - -ifdef CONFIG_DYNAMIC_FTRACE CFLAGS_REMOVE_ftrace.o = -pg endif @@ -46,6 +43,7 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_FUNCTION_TRACER) += mcount.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o # Kexec part S390_KEXEC_OBJS := machine_kexec.o crash.o diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 0b81a784e03..c92a1095327 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -7,13 +7,17 @@ * */ +#include #include #include #include #include #include +#ifdef CONFIG_DYNAMIC_FTRACE + void ftrace_disable_code(void); +void ftrace_disable_return(void); void ftrace_call_code(void); void ftrace_nop_code(void); @@ -28,6 +32,7 @@ asm( " .word 0x0024\n" " lg %r1,"__stringify(__LC_FTRACE_FUNC)"\n" " basr %r14,%r1\n" + "ftrace_disable_return:\n" " lg %r14,8(15)\n" " lgr %r0,%r0\n" "0:\n"); @@ -50,6 +55,7 @@ asm( " j 0f\n" " l %r1,"__stringify(__LC_FTRACE_FUNC)"\n" " basr %r14,%r1\n" + "ftrace_disable_return:\n" " l %r14,4(%r15)\n" " j 0f\n" " bcr 0,%r7\n" @@ -130,3 +136,69 @@ int __init ftrace_dyn_arch_init(void *data) *(unsigned long *)data = 0; return 0; } + +#endif /* CONFIG_DYNAMIC_FTRACE */ + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +#ifdef CONFIG_DYNAMIC_FTRACE +/* + * Patch the kernel code at ftrace_graph_caller location: + * The instruction there is branch relative on condition. The condition mask + * is either all ones (always branch aka disable ftrace_graph_caller) or all + * zeroes (nop aka enable ftrace_graph_caller). + * Instruction format for brc is a7m4xxxx where m is the condition mask. + */ +int ftrace_enable_ftrace_graph_caller(void) +{ + unsigned short opcode = 0xa704; + + return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode)); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + unsigned short opcode = 0xa7f4; + + return probe_kernel_write(ftrace_graph_caller, &opcode, sizeof(opcode)); +} + +static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr) +{ + return addr - (ftrace_disable_return - ftrace_disable_code); +} + +#else /* CONFIG_DYNAMIC_FTRACE */ + +static inline unsigned long ftrace_mcount_call_adjust(unsigned long addr) +{ + return addr - MCOUNT_OFFSET_RET; +} + +#endif /* CONFIG_DYNAMIC_FTRACE */ + +/* + * Hook the return address and push it in the stack of return addresses + * in current thread info. + */ +unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent) +{ + struct ftrace_graph_ent trace; + + /* Nmi's are currently unsupported. */ + if (unlikely(in_nmi())) + goto out; + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + goto out; + if (ftrace_push_return_trace(parent, ip, &trace.depth) == -EBUSY) + goto out; + trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN; + /* Only trace if the calling function expects to. */ + if (!ftrace_graph_entry(&trace)) { + current->curr_ret_stack--; + goto out; + } + parent = (unsigned long)return_to_handler; +out: + return parent; +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index 0aa85ec94d0..2a0a5e97ba8 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S @@ -34,6 +34,18 @@ ftrace_caller: larl %r14,ftrace_dyn_func lg %r14,0(%r14) basr %r14,%r14 +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + .globl ftrace_graph_caller +ftrace_graph_caller: + # This unconditional branch gets runtime patched. Change only if + # you know what you are doing. See ftrace_enable_graph_caller(). + j 0f + lg %r2,272(%r15) + lg %r3,168(%r15) + brasl %r14,prepare_ftrace_return + stg %r2,168(%r15) +0: +#endif aghi %r15,160 lmg %r2,%r5,32(%r15) lg %r14,112(%r15) @@ -62,6 +74,12 @@ _mcount: larl %r14,ftrace_trace_function lg %r14,0(%r14) basr %r14,%r14 +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + lg %r2,272(%r15) + lg %r3,168(%r15) + brasl %r14,prepare_ftrace_return + stg %r2,168(%r15) +#endif aghi %r15,160 lmg %r2,%r5,32(%r15) lg %r14,112(%r15) @@ -69,6 +87,22 @@ _mcount: #endif /* CONFIG_DYNAMIC_FTRACE */ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + + .globl return_to_handler +return_to_handler: + stmg %r2,%r5,32(%r15) + lgr %r1,%r15 + aghi %r15,-160 + stg %r1,__SF_BACKCHAIN(%r15) + brasl %r14,ftrace_return_to_handler + aghi %r15,160 + lgr %r14,%r2 + lmg %r2,%r5,32(%r15) + br %r14 + +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + #else /* CONFIG_64BIT */ #ifdef CONFIG_DYNAMIC_FTRACE @@ -96,6 +130,21 @@ ftrace_caller: l %r14,0b-0b(%r1) l %r14,0(%r14) basr %r14,%r14 +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + .globl ftrace_graph_caller +ftrace_graph_caller: + # This unconditional branch gets runtime patched. Change only if + # you know what you are doing. See ftrace_enable_graph_caller(). + j 1f + bras %r1,0f + .long prepare_ftrace_return +0: l %r2,152(%r15) + l %r4,0(%r1) + l %r3,100(%r15) + basr %r14,%r4 + st %r2,100(%r15) +1: +#endif ahi %r15,96 l %r14,56(%r15) 3: lm %r2,%r5,16(%r15) @@ -128,10 +177,40 @@ _mcount: l %r14,0b-0b(%r1) l %r14,0(%r14) basr %r14,%r14 +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + bras %r1,0f + .long prepare_ftrace_return +0: l %r2,152(%r15) + l %r4,0(%r1) + l %r3,100(%r15) + basr %r14,%r4 + st %r2,100(%r15) +#endif ahi %r15,96 l %r14,56(%r15) 3: lm %r2,%r5,16(%r15) br %r14 #endif /* CONFIG_DYNAMIC_FTRACE */ + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + + .globl return_to_handler +return_to_handler: + stm %r2,%r5,16(%r15) + st %r14,56(%r15) + lr %r0,%r15 + ahi %r15,-96 + st %r0,__SF_BACKCHAIN(%r15) + bras %r1,0f + .long ftrace_return_to_handler +0: l %r2,0b-0b(%r1) + basr %r14,%r2 + lr %r14,%r2 + ahi %r15,96 + lm %r2,%r5,16(%r15) + br %r14 + +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + #endif /* CONFIG_64BIT */ diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c index 6b0686d78fc..0de305b598c 100644 --- a/arch/s390/kernel/s390_ext.c +++ b/arch/s390/kernel/s390_ext.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -112,7 +113,7 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler, return 0; } -void do_extint(struct pt_regs *regs, unsigned short code) +void __irq_entry do_extint(struct pt_regs *regs, unsigned short code) { ext_int_info_t *p; int index; diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index ad9a999aaa9..215330a2c12 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -70,7 +70,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators); /* * Scheduler clock - returns current time in nanosec units. */ -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { return ((get_clock_xt() - sched_clock_base_cc) * 125) >> 9; } diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 89399b8756c..a53db23ee09 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -34,6 +34,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT KPROBES_TEXT + IRQENTRY_TEXT *(.fixup) *(.gnu.warning) } :text = 0x0700 diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 9889f188c7c..5ec7789bd9d 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -12,6 +12,7 @@ #define KMSG_COMPONENT "cio" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include #include #include #include @@ -626,8 +627,7 @@ out: * handlers). * */ -void -do_IRQ (struct pt_regs *regs) +void __irq_entry do_IRQ(struct pt_regs *regs) { struct tpi_info *tpi_info; struct subchannel *sch; -- cgit v1.2.3-70-g09d2