aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorSven Schnelle <svens@stackframe.org>2019-07-23 16:37:52 -0400
committerHelge Deller <deller@gmx.de>2019-08-03 02:56:57 -0400
commit52a22e6c27be9089fdd9c4e1857939f0dec8f57c (patch)
tree760e141459f496f85115018ed325878598f41c0e /arch/parisc
parentd562aca37a543cc3de85be6a6946771a27d50c6a (diff)
parisc/ftrace: Add KPROBES_ON_FTRACE
Allow KPROBES to use the ftrace infrastructure on PA-RISC. Signed-off-by: Sven Schnelle <svens@stackframe.org> Signed-off-by: Helge Deller <deller@gmx.de>
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/Kconfig2
-rw-r--r--arch/parisc/kernel/entry.S99
-rw-r--r--arch/parisc/kernel/ftrace.c58
3 files changed, 156 insertions, 3 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 6d732e451071..ee59171edffe 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -61,6 +61,8 @@ config PARISC
61 select HAVE_KRETPROBES 61 select HAVE_KRETPROBES
62 select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1) 62 select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1)
63 select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE 63 select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
64 select HAVE_KPROBES_ON_FTRACE
65 select HAVE_DYNAMIC_FTRACE_WITH_REGS
64 66
65 help 67 help
66 The PA-RISC microprocessor is designed by Hewlett-Packard and used 68 The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index d9d3387f7c47..1d1d748c227f 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1996,6 +1996,7 @@ _mcount:
1996 * calling mcount(), and 2 instructions for ftrace_stub(). That way we 1996 * calling mcount(), and 2 instructions for ftrace_stub(). That way we
1997 * have all on one L1 cacheline. 1997 * have all on one L1 cacheline.
1998 */ 1998 */
1999 ldi 0, %arg3
1999 b ftrace_function_trampoline 2000 b ftrace_function_trampoline
2000 copy %r3, %arg2 /* caller original %sp */ 2001 copy %r3, %arg2 /* caller original %sp */
2001ftrace_stub: 2002ftrace_stub:
@@ -2048,6 +2049,7 @@ ftrace_caller:
2048 LDREG 0(%r3), %r25 2049 LDREG 0(%r3), %r25
2049 copy %rp, %r26 2050 copy %rp, %r26
2050 ldo -8(%r25), %r25 2051 ldo -8(%r25), %r25
2052 ldi 0, %r23 /* no pt_regs */
2051 b,l ftrace_function_trampoline, %rp 2053 b,l ftrace_function_trampoline, %rp
2052 copy %r3, %r24 2054 copy %r3, %r24
2053 2055
@@ -2075,6 +2077,103 @@ ftrace_caller:
2075 2077
2076ENDPROC_CFI(ftrace_caller) 2078ENDPROC_CFI(ftrace_caller)
2077 2079
2080#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS
2081ENTRY_CFI(ftrace_regs_caller,caller,frame=FTRACE_FRAME_SIZE+PT_SZ_ALGN,
2082 CALLS,SAVE_RP,SAVE_SP)
2083ftrace_regs_caller:
2084 .global ftrace_regs_caller
2085
2086 ldo -FTRACE_FRAME_SIZE(%sp), %r1
2087 STREG %rp, -RP_OFFSET(%r1)
2088
2089 copy %sp, %r1
2090 ldo PT_SZ_ALGN(%sp), %sp
2091
2092 STREG %rp, PT_GR2(%r1)
2093 STREG %r3, PT_GR3(%r1)
2094 STREG %r4, PT_GR4(%r1)
2095 STREG %r5, PT_GR5(%r1)
2096 STREG %r6, PT_GR6(%r1)
2097 STREG %r7, PT_GR7(%r1)
2098 STREG %r8, PT_GR8(%r1)
2099 STREG %r9, PT_GR9(%r1)
2100 STREG %r10, PT_GR10(%r1)
2101 STREG %r11, PT_GR11(%r1)
2102 STREG %r12, PT_GR12(%r1)
2103 STREG %r13, PT_GR13(%r1)
2104 STREG %r14, PT_GR14(%r1)
2105 STREG %r15, PT_GR15(%r1)
2106 STREG %r16, PT_GR16(%r1)
2107 STREG %r17, PT_GR17(%r1)
2108 STREG %r18, PT_GR18(%r1)
2109 STREG %r19, PT_GR19(%r1)
2110 STREG %r20, PT_GR20(%r1)
2111 STREG %r21, PT_GR21(%r1)
2112 STREG %r22, PT_GR22(%r1)
2113 STREG %r23, PT_GR23(%r1)
2114 STREG %r24, PT_GR24(%r1)
2115 STREG %r25, PT_GR25(%r1)
2116 STREG %r26, PT_GR26(%r1)
2117 STREG %r27, PT_GR27(%r1)
2118 STREG %r28, PT_GR28(%r1)
2119 STREG %r29, PT_GR29(%r1)
2120 STREG %r30, PT_GR30(%r1)
2121 STREG %r31, PT_GR31(%r1)
2122 mfctl %cr11, %r26
2123 STREG %r26, PT_SAR(%r1)
2124
2125 copy %rp, %r26
2126 LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25
2127 ldo -8(%r25), %r25
2128 copy %r3, %arg2
2129 b,l ftrace_function_trampoline, %rp
2130 copy %r1, %arg3 /* struct pt_regs */
2131
2132 ldo -PT_SZ_ALGN(%sp), %r1
2133
2134 LDREG PT_SAR(%r1), %rp
2135 mtctl %rp, %cr11
2136
2137 LDREG PT_GR2(%r1), %rp
2138 LDREG PT_GR3(%r1), %r3
2139 LDREG PT_GR4(%r1), %r4
2140 LDREG PT_GR5(%r1), %r5
2141 LDREG PT_GR6(%r1), %r6
2142 LDREG PT_GR7(%r1), %r7
2143 LDREG PT_GR8(%r1), %r8
2144 LDREG PT_GR9(%r1), %r9
2145 LDREG PT_GR10(%r1),%r10
2146 LDREG PT_GR11(%r1),%r11
2147 LDREG PT_GR12(%r1),%r12
2148 LDREG PT_GR13(%r1),%r13
2149 LDREG PT_GR14(%r1),%r14
2150 LDREG PT_GR15(%r1),%r15
2151 LDREG PT_GR16(%r1),%r16
2152 LDREG PT_GR17(%r1),%r17
2153 LDREG PT_GR18(%r1),%r18
2154 LDREG PT_GR19(%r1),%r19
2155 LDREG PT_GR20(%r1),%r20
2156 LDREG PT_GR21(%r1),%r21
2157 LDREG PT_GR22(%r1),%r22
2158 LDREG PT_GR23(%r1),%r23
2159 LDREG PT_GR24(%r1),%r24
2160 LDREG PT_GR25(%r1),%r25
2161 LDREG PT_GR26(%r1),%r26
2162 LDREG PT_GR27(%r1),%r27
2163 LDREG PT_GR28(%r1),%r28
2164 LDREG PT_GR29(%r1),%r29
2165 LDREG PT_GR30(%r1),%r30
2166 LDREG PT_GR31(%r1),%r31
2167
2168 ldo -PT_SZ_ALGN(%sp), %sp
2169 LDREGM -FTRACE_FRAME_SIZE(%sp), %r1
2170 /* Adjust return point to jump back to beginning of traced function */
2171 ldo -4(%r1), %r1
2172 bv,n (%r1)
2173
2174ENDPROC_CFI(ftrace_regs_caller)
2175
2176#endif
2078#endif 2177#endif
2079 2178
2080#ifdef CONFIG_FUNCTION_GRAPH_TRACER 2179#ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
index 23ce416787ac..b836fc61a24f 100644
--- a/arch/parisc/kernel/ftrace.c
+++ b/arch/parisc/kernel/ftrace.c
@@ -13,6 +13,8 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/ftrace.h> 14#include <linux/ftrace.h>
15#include <linux/uaccess.h> 15#include <linux/uaccess.h>
16#include <linux/kprobes.h>
17#include <linux/ptrace.h>
16 18
17#include <asm/assembly.h> 19#include <asm/assembly.h>
18#include <asm/sections.h> 20#include <asm/sections.h>
@@ -48,7 +50,8 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
48 50
49void notrace __hot ftrace_function_trampoline(unsigned long parent, 51void notrace __hot ftrace_function_trampoline(unsigned long parent,
50 unsigned long self_addr, 52 unsigned long self_addr,
51 unsigned long org_sp_gr3) 53 unsigned long org_sp_gr3,
54 struct pt_regs *regs)
52{ 55{
53#ifndef CONFIG_DYNAMIC_FTRACE 56#ifndef CONFIG_DYNAMIC_FTRACE
54 extern ftrace_func_t ftrace_trace_function; 57 extern ftrace_func_t ftrace_trace_function;
@@ -58,11 +61,11 @@ void notrace __hot ftrace_function_trampoline(unsigned long parent,
58 if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED && 61 if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED &&
59 ftrace_trace_function != ftrace_stub) 62 ftrace_trace_function != ftrace_stub)
60 ftrace_trace_function(self_addr, parent, 63 ftrace_trace_function(self_addr, parent,
61 function_trace_op, NULL); 64 function_trace_op, regs);
62 65
63#ifdef CONFIG_FUNCTION_GRAPH_TRACER 66#ifdef CONFIG_FUNCTION_GRAPH_TRACER
64 if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub || 67 if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub ||
65 ftrace_graph_entry != ftrace_graph_entry_stub) { 68 ftrace_graph_entry != ftrace_graph_entry_stub) {
66 unsigned long *parent_rp; 69 unsigned long *parent_rp;
67 70
68 /* calculate pointer to %rp in stack */ 71 /* calculate pointer to %rp in stack */
@@ -100,6 +103,12 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
100 return 0; 103 return 0;
101} 104}
102 105
106int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
107 unsigned long addr)
108{
109 return 0;
110}
111
103unsigned long ftrace_call_adjust(unsigned long addr) 112unsigned long ftrace_call_adjust(unsigned long addr)
104{ 113{
105 return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4; 114 return addr+(FTRACE_PATCHABLE_FUNCTION_SIZE-1)*4;
@@ -191,3 +200,46 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
191 return 0; 200 return 0;
192} 201}
193#endif 202#endif
203
204#ifdef CONFIG_KPROBES_ON_FTRACE
205void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
206 struct ftrace_ops *ops, struct pt_regs *regs)
207{
208 struct kprobe_ctlblk *kcb;
209 struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip);
210
211 if (unlikely(!p) || kprobe_disabled(p))
212 return;
213
214 if (kprobe_running()) {
215 kprobes_inc_nmissed_count(p);
216 return;
217 }
218
219 __this_cpu_write(current_kprobe, p);
220
221 kcb = get_kprobe_ctlblk();
222 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
223
224 regs->iaoq[0] = ip;
225 regs->iaoq[1] = ip + 4;
226
227 if (!p->pre_handler || !p->pre_handler(p, regs)) {
228 regs->iaoq[0] = ip + 4;
229 regs->iaoq[1] = ip + 8;
230
231 if (unlikely(p->post_handler)) {
232 kcb->kprobe_status = KPROBE_HIT_SSDONE;
233 p->post_handler(p, regs, 0);
234 }
235 }
236 __this_cpu_write(current_kprobe, NULL);
237}
238NOKPROBE_SYMBOL(kprobe_ftrace_handler);
239
240int arch_prepare_kprobe_ftrace(struct kprobe *p)
241{
242 p->ainsn.insn = NULL;
243 return 0;
244}
245#endif