aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-04-15 17:51:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-04-15 17:51:45 -0400
commit60ea7bb0077b38f80a3a27b9e32ad45879944a57 (patch)
treec983c6b14f8b9ba513d9ff7f9f596cd6c8c4671a
parent806fdcce017dc98c4dbf8ed001750a0d7d2bb0af (diff)
parent366dd4ea9d5f0eb78fdf4982d76506f99480ec0a (diff)
Merge branch 'parisc-4.6-4' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc ftrace fixes from Helge Deller: "This is (most likely) the last pull request for v4.6 for the parisc architecture. It fixes the FTRACE feature for parisc, which is horribly broken since quite some time and doesn't even compile. This patch just fixes the bare minimum (it actually removes more lines than it adds), so that the function tracer works again on 32- and 64bit kernels. I've queued up additional patches on top of this patch which e.g. add the syscall tracer, but those have to wait for the merge window for v4.7." * 'parisc-4.6-4' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: parisc: Fix ftrace function tracer
-rw-r--r--arch/parisc/Kconfig4
-rw-r--r--arch/parisc/Kconfig.debug4
-rw-r--r--arch/parisc/Makefile4
-rw-r--r--arch/parisc/include/asm/ftrace.h18
-rw-r--r--arch/parisc/kernel/Makefile4
-rw-r--r--arch/parisc/kernel/entry.S93
-rw-r--r--arch/parisc/kernel/ftrace.c146
-rw-r--r--arch/parisc/kernel/head.S9
8 files changed, 114 insertions, 168 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index bd3c873951a1..88cfaa8af78e 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -4,8 +4,8 @@ config PARISC
4 select ARCH_MIGHT_HAVE_PC_PARPORT 4 select ARCH_MIGHT_HAVE_PC_PARPORT
5 select HAVE_IDE 5 select HAVE_IDE
6 select HAVE_OPROFILE 6 select HAVE_OPROFILE
7 select HAVE_FUNCTION_TRACER if 64BIT 7 select HAVE_FUNCTION_TRACER
8 select HAVE_FUNCTION_GRAPH_TRACER if 64BIT 8 select HAVE_FUNCTION_GRAPH_TRACER
9 select ARCH_WANT_FRAME_POINTERS 9 select ARCH_WANT_FRAME_POINTERS
10 select RTC_CLASS 10 select RTC_CLASS
11 select RTC_DRV_GENERIC 11 select RTC_DRV_GENERIC
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index bc989e522a04..68b7cbd0810a 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -2,9 +2,13 @@ menu "Kernel hacking"
2 2
3source "lib/Kconfig.debug" 3source "lib/Kconfig.debug"
4 4
5config TRACE_IRQFLAGS_SUPPORT
6 def_bool y
7
5config DEBUG_RODATA 8config DEBUG_RODATA
6 bool "Write protect kernel read-only data structures" 9 bool "Write protect kernel read-only data structures"
7 depends on DEBUG_KERNEL 10 depends on DEBUG_KERNEL
11 default y
8 help 12 help
9 Mark the kernel read-only data as write-protected in the pagetables, 13 Mark the kernel read-only data as write-protected in the pagetables,
10 in order to catch accidental (and incorrect) writes to such const 14 in order to catch accidental (and incorrect) writes to such const
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 965a0999fc4c..75cb451b1f03 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -62,9 +62,7 @@ cflags-y += -mdisable-fpregs
62 62
63# Without this, "ld -r" results in .text sections that are too big 63# Without this, "ld -r" results in .text sections that are too big
64# (> 0x40000) for branches to reach stubs. 64# (> 0x40000) for branches to reach stubs.
65ifndef CONFIG_FUNCTION_TRACER 65cflags-y += -ffunction-sections
66 cflags-y += -ffunction-sections
67endif
68 66
69# Use long jumps instead of long branches (needed if your linker fails to 67# Use long jumps instead of long branches (needed if your linker fails to
70# link a too big vmlinux executable). Not enabled for building modules. 68# link a too big vmlinux executable). Not enabled for building modules.
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 544ed8ef87eb..24cd81d58d70 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -4,23 +4,7 @@
4#ifndef __ASSEMBLY__ 4#ifndef __ASSEMBLY__
5extern void mcount(void); 5extern void mcount(void);
6 6
7/* 7#define MCOUNT_INSN_SIZE 4
8 * Stack of return addresses for functions of a thread.
9 * Used in struct thread_info
10 */
11struct ftrace_ret_stack {
12 unsigned long ret;
13 unsigned long func;
14 unsigned long long calltime;
15};
16
17/*
18 * Primary handler of a function return.
19 * It relays on ftrace_return_to_handler.
20 * Defined in entry.S
21 */
22extern void return_to_handler(void);
23
24 8
25extern unsigned long return_address(unsigned int); 9extern unsigned long return_address(unsigned int);
26 10
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index ff87b4603e3d..69a11183d48d 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -15,11 +15,7 @@ ifdef CONFIG_FUNCTION_TRACER
15# Do not profile debug and lowlevel utilities 15# Do not profile debug and lowlevel utilities
16CFLAGS_REMOVE_ftrace.o = -pg 16CFLAGS_REMOVE_ftrace.o = -pg
17CFLAGS_REMOVE_cache.o = -pg 17CFLAGS_REMOVE_cache.o = -pg
18CFLAGS_REMOVE_irq.o = -pg
19CFLAGS_REMOVE_pacache.o = -pg
20CFLAGS_REMOVE_perf.o = -pg 18CFLAGS_REMOVE_perf.o = -pg
21CFLAGS_REMOVE_traps.o = -pg
22CFLAGS_REMOVE_unaligned.o = -pg
23CFLAGS_REMOVE_unwind.o = -pg 19CFLAGS_REMOVE_unwind.o = -pg
24endif 20endif
25 21
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 623496c11756..39127d3e70e5 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1970,43 +1970,98 @@ pt_regs_ok:
1970 b intr_restore 1970 b intr_restore
1971 copy %r25,%r16 1971 copy %r25,%r16
1972 1972
1973 .import schedule,code
1974syscall_do_resched: 1973syscall_do_resched:
1975 BL schedule,%r2 1974 load32 syscall_check_resched,%r2 /* if resched, we start over again */
1975 load32 schedule,%r19
1976 bv %r0(%r19) /* jumps to schedule() */
1976#ifdef CONFIG_64BIT 1977#ifdef CONFIG_64BIT
1977 ldo -16(%r30),%r29 /* Reference param save area */ 1978 ldo -16(%r30),%r29 /* Reference param save area */
1978#else 1979#else
1979 nop 1980 nop
1980#endif 1981#endif
1981 b syscall_check_resched /* if resched, we start over again */
1982 nop
1983ENDPROC(syscall_exit) 1982ENDPROC(syscall_exit)
1984 1983
1985 1984
1986#ifdef CONFIG_FUNCTION_TRACER 1985#ifdef CONFIG_FUNCTION_TRACER
1986
1987 .import ftrace_function_trampoline,code 1987 .import ftrace_function_trampoline,code
1988ENTRY(_mcount) 1988 .align L1_CACHE_BYTES
1989 copy %r3, %arg2 1989 .globl mcount
1990 .type mcount, @function
1991ENTRY(mcount)
1992_mcount:
1993 .export _mcount,data
1994 .proc
1995 .callinfo caller,frame=0
1996 .entry
1997 /*
1998 * The 64bit mcount() function pointer needs 4 dwords, of which the
1999 * first two are free. We optimize it here and put 2 instructions for
2000 * calling mcount(), and 2 instructions for ftrace_stub(). That way we
2001 * have all on one L1 cacheline.
2002 */
1990 b ftrace_function_trampoline 2003 b ftrace_function_trampoline
2004 copy %r3, %arg2 /* caller original %sp */
2005ftrace_stub:
2006 .globl ftrace_stub
2007 .type ftrace_stub, @function
2008#ifdef CONFIG_64BIT
2009 bve (%rp)
2010#else
2011 bv %r0(%rp)
2012#endif
1991 nop 2013 nop
1992ENDPROC(_mcount) 2014#ifdef CONFIG_64BIT
2015 .dword mcount
2016 .dword 0 /* code in head.S puts value of global gp here */
2017#endif
2018 .exit
2019 .procend
2020ENDPROC(mcount)
1993 2021
2022 .align 8
2023 .globl return_to_handler
2024 .type return_to_handler, @function
1994ENTRY(return_to_handler) 2025ENTRY(return_to_handler)
1995 load32 return_trampoline, %rp 2026 .proc
1996 copy %ret0, %arg0 2027 .callinfo caller,frame=FRAME_SIZE
1997 copy %ret1, %arg1 2028 .entry
1998 b ftrace_return_to_handler 2029 .export parisc_return_to_handler,data
1999 nop 2030parisc_return_to_handler:
2000return_trampoline: 2031 copy %r3,%r1
2001 copy %ret0, %rp 2032 STREG %r0,-RP_OFFSET(%sp) /* store 0 as %rp */
2002 copy %r23, %ret0 2033 copy %sp,%r3
2003 copy %r24, %ret1 2034 STREGM %r1,FRAME_SIZE(%sp)
2035 STREG %ret0,8(%r3)
2036 STREG %ret1,16(%r3)
2004 2037
2005.globl ftrace_stub 2038#ifdef CONFIG_64BIT
2006ftrace_stub: 2039 loadgp
2040#endif
2041
2042 /* call ftrace_return_to_handler(0) */
2043#ifdef CONFIG_64BIT
2044 ldo -16(%sp),%ret1 /* Reference param save area */
2045#endif
2046 BL ftrace_return_to_handler,%r2
2047 ldi 0,%r26
2048 copy %ret0,%rp
2049
2050 /* restore original return values */
2051 LDREG 8(%r3),%ret0
2052 LDREG 16(%r3),%ret1
2053
2054 /* return from function */
2055#ifdef CONFIG_64BIT
2056 bve (%rp)
2057#else
2007 bv %r0(%rp) 2058 bv %r0(%rp)
2008 nop 2059#endif
2060 LDREGM -FRAME_SIZE(%sp),%r3
2061 .exit
2062 .procend
2009ENDPROC(return_to_handler) 2063ENDPROC(return_to_handler)
2064
2010#endif /* CONFIG_FUNCTION_TRACER */ 2065#endif /* CONFIG_FUNCTION_TRACER */
2011 2066
2012#ifdef CONFIG_IRQSTACKS 2067#ifdef CONFIG_IRQSTACKS
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
index 559d400f9385..b13f9ec6f294 100644
--- a/arch/parisc/kernel/ftrace.c
+++ b/arch/parisc/kernel/ftrace.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Code for tracing calls in Linux kernel. 2 * Code for tracing calls in Linux kernel.
3 * Copyright (C) 2009 Helge Deller <deller@gmx.de> 3 * Copyright (C) 2009-2016 Helge Deller <deller@gmx.de>
4 * 4 *
5 * based on code for x86 which is: 5 * based on code for x86 which is:
6 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> 6 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
@@ -13,104 +13,21 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/ftrace.h> 14#include <linux/ftrace.h>
15 15
16#include <asm/assembly.h>
16#include <asm/sections.h> 17#include <asm/sections.h>
17#include <asm/ftrace.h> 18#include <asm/ftrace.h>
18 19
19 20
20
21#ifdef CONFIG_FUNCTION_GRAPH_TRACER 21#ifdef CONFIG_FUNCTION_GRAPH_TRACER
22
23/* Add a function return address to the trace stack on thread info.*/
24static int push_return_trace(unsigned long ret, unsigned long long time,
25 unsigned long func, int *depth)
26{
27 int index;
28
29 if (!current->ret_stack)
30 return -EBUSY;
31
32 /* The return trace stack is full */
33 if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) {
34 atomic_inc(&current->trace_overrun);
35 return -EBUSY;
36 }
37
38 index = ++current->curr_ret_stack;
39 barrier();
40 current->ret_stack[index].ret = ret;
41 current->ret_stack[index].func = func;
42 current->ret_stack[index].calltime = time;
43 *depth = index;
44
45 return 0;
46}
47
48/* Retrieve a function return address to the trace stack on thread info.*/
49static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
50{
51 int index;
52
53 index = current->curr_ret_stack;
54
55 if (unlikely(index < 0)) {
56 ftrace_graph_stop();
57 WARN_ON(1);
58 /* Might as well panic, otherwise we have no where to go */
59 *ret = (unsigned long)
60 dereference_function_descriptor(&panic);
61 return;
62 }
63
64 *ret = current->ret_stack[index].ret;
65 trace->func = current->ret_stack[index].func;
66 trace->calltime = current->ret_stack[index].calltime;
67 trace->overrun = atomic_read(&current->trace_overrun);
68 trace->depth = index;
69 barrier();
70 current->curr_ret_stack--;
71
72}
73
74/*
75 * Send the trace to the ring-buffer.
76 * @return the original return address.
77 */
78unsigned long ftrace_return_to_handler(unsigned long retval0,
79 unsigned long retval1)
80{
81 struct ftrace_graph_ret trace;
82 unsigned long ret;
83
84 pop_return_trace(&trace, &ret);
85 trace.rettime = local_clock();
86 ftrace_graph_return(&trace);
87
88 if (unlikely(!ret)) {
89 ftrace_graph_stop();
90 WARN_ON(1);
91 /* Might as well panic. What else to do? */
92 ret = (unsigned long)
93 dereference_function_descriptor(&panic);
94 }
95
96 /* HACK: we hand over the old functions' return values
97 in %r23 and %r24. Assembly in entry.S will take care
98 and move those to their final registers %ret0 and %ret1 */
99 asm( "copy %0, %%r23 \n\t"
100 "copy %1, %%r24 \n" : : "r" (retval0), "r" (retval1) );
101
102 return ret;
103}
104
105/* 22/*
106 * Hook the return address and push it in the stack of return addrs 23 * Hook the return address and push it in the stack of return addrs
107 * in current thread info. 24 * in current thread info.
108 */ 25 */
109void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) 26static void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
110{ 27{
111 unsigned long old; 28 unsigned long old;
112 unsigned long long calltime;
113 struct ftrace_graph_ent trace; 29 struct ftrace_graph_ent trace;
30 extern int parisc_return_to_handler;
114 31
115 if (unlikely(ftrace_graph_is_dead())) 32 if (unlikely(ftrace_graph_is_dead()))
116 return; 33 return;
@@ -119,64 +36,47 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
119 return; 36 return;
120 37
121 old = *parent; 38 old = *parent;
122 *parent = (unsigned long)
123 dereference_function_descriptor(&return_to_handler);
124 39
125 if (unlikely(!__kernel_text_address(old))) { 40 trace.func = self_addr;
126 ftrace_graph_stop(); 41 trace.depth = current->curr_ret_stack + 1;
127 *parent = old;
128 WARN_ON(1);
129 return;
130 }
131
132 calltime = local_clock();
133 42
134 if (push_return_trace(old, calltime, 43 /* Only trace if the calling function expects to */
135 self_addr, &trace.depth) == -EBUSY) { 44 if (!ftrace_graph_entry(&trace))
136 *parent = old;
137 return; 45 return;
138 }
139 46
140 trace.func = self_addr; 47 if (ftrace_push_return_trace(old, self_addr, &trace.depth,
48 0 ) == -EBUSY)
49 return;
141 50
142 /* Only trace if the calling function expects to */ 51 /* activate parisc_return_to_handler() as return point */
143 if (!ftrace_graph_entry(&trace)) { 52 *parent = (unsigned long) &parisc_return_to_handler;
144 current->curr_ret_stack--;
145 *parent = old;
146 }
147} 53}
148
149#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 54#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
150 55
151 56void notrace ftrace_function_trampoline(unsigned long parent,
152void ftrace_function_trampoline(unsigned long parent,
153 unsigned long self_addr, 57 unsigned long self_addr,
154 unsigned long org_sp_gr3) 58 unsigned long org_sp_gr3)
155{ 59{
156 extern ftrace_func_t ftrace_trace_function; 60 extern ftrace_func_t ftrace_trace_function; /* depends on CONFIG_DYNAMIC_FTRACE */
61 extern int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace);
157 62
158 if (ftrace_trace_function != ftrace_stub) { 63 if (ftrace_trace_function != ftrace_stub) {
159 ftrace_trace_function(parent, self_addr); 64 /* struct ftrace_ops *op, struct pt_regs *regs); */
65 ftrace_trace_function(parent, self_addr, NULL, NULL);
160 return; 66 return;
161 } 67 }
68
162#ifdef CONFIG_FUNCTION_GRAPH_TRACER 69#ifdef CONFIG_FUNCTION_GRAPH_TRACER
163 if (ftrace_graph_entry && ftrace_graph_return) { 70 if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
164 unsigned long sp; 71 ftrace_graph_entry != ftrace_graph_entry_stub) {
165 unsigned long *parent_rp; 72 unsigned long *parent_rp;
166 73
167 asm volatile ("copy %%r30, %0" : "=r"(sp));
168 /* sanity check: is stack pointer which we got from
169 assembler function in entry.S in a reasonable
170 range compared to current stack pointer? */
171 if ((sp - org_sp_gr3) > 0x400)
172 return;
173
174 /* calculate pointer to %rp in stack */ 74 /* calculate pointer to %rp in stack */
175 parent_rp = (unsigned long *) org_sp_gr3 - 0x10; 75 parent_rp = (unsigned long *) (org_sp_gr3 - RP_OFFSET);
176 /* sanity check: parent_rp should hold parent */ 76 /* sanity check: parent_rp should hold parent */
177 if (*parent_rp != parent) 77 if (*parent_rp != parent)
178 return; 78 return;
179 79
180 prepare_ftrace_return(parent_rp, self_addr); 80 prepare_ftrace_return(parent_rp, self_addr);
181 return; 81 return;
182 } 82 }
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 75aa0db9f69e..bbbe360b458f 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -129,6 +129,15 @@ $pgt_fill_loop:
129 /* And the stack pointer too */ 129 /* And the stack pointer too */
130 ldo THREAD_SZ_ALGN(%r6),%sp 130 ldo THREAD_SZ_ALGN(%r6),%sp
131 131
132#if defined(CONFIG_64BIT) && defined(CONFIG_FUNCTION_TRACER)
133 .import _mcount,data
134 /* initialize mcount FPTR */
135 /* Get the global data pointer */
136 loadgp
137 load32 PA(_mcount), %r10
138 std %dp,0x18(%r10)
139#endif
140
132#ifdef CONFIG_SMP 141#ifdef CONFIG_SMP
133 /* Set the smp rendezvous address into page zero. 142 /* Set the smp rendezvous address into page zero.
134 ** It would be safer to do this in init_smp_config() but 143 ** It would be safer to do this in init_smp_config() but