Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sven Schnelle and committed by
Helge Deller
52a22e6c d562aca3

+157 -4
+1 -1
Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
··· 21 21 | nds32: | TODO | 22 22 | nios2: | TODO | 23 23 | openrisc: | TODO | 24 - | parisc: | TODO | 24 + | parisc: | ok | 25 25 | powerpc: | ok | 26 26 | riscv: | TODO | 27 27 | s390: | TODO |
+2
arch/parisc/Kconfig
··· 61 61 select HAVE_KRETPROBES 62 62 select HAVE_DYNAMIC_FTRACE if $(cc-option,-fpatchable-function-entry=1,1) 63 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 67 help 66 68 The PA-RISC microprocessor is designed by Hewlett-Packard and used
+99
arch/parisc/kernel/entry.S
··· 1996 1996 * calling mcount(), and 2 instructions for ftrace_stub(). That way we 1997 1997 * have all on one L1 cacheline. 1998 1998 */ 1999 + ldi 0, %arg3 1999 2000 b ftrace_function_trampoline 2000 2001 copy %r3, %arg2 /* caller original %sp */ 2001 2002 ftrace_stub: ··· 2049 2048 LDREG 0(%r3), %r25 2050 2049 copy %rp, %r26 2051 2050 ldo -8(%r25), %r25 2051 + ldi 0, %r23 /* no pt_regs */ 2052 2052 b,l ftrace_function_trampoline, %rp 2053 2053 copy %r3, %r24 2054 2054 ··· 2077 2075 2078 2076 ENDPROC_CFI(ftrace_caller) 2079 2077 2078 + #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS 2079 + ENTRY_CFI(ftrace_regs_caller,caller,frame=FTRACE_FRAME_SIZE+PT_SZ_ALGN, 2080 + CALLS,SAVE_RP,SAVE_SP) 2081 + ftrace_regs_caller: 2082 + .global ftrace_regs_caller 2083 + 2084 + ldo -FTRACE_FRAME_SIZE(%sp), %r1 2085 + STREG %rp, -RP_OFFSET(%r1) 2086 + 2087 + copy %sp, %r1 2088 + ldo PT_SZ_ALGN(%sp), %sp 2089 + 2090 + STREG %rp, PT_GR2(%r1) 2091 + STREG %r3, PT_GR3(%r1) 2092 + STREG %r4, PT_GR4(%r1) 2093 + STREG %r5, PT_GR5(%r1) 2094 + STREG %r6, PT_GR6(%r1) 2095 + STREG %r7, PT_GR7(%r1) 2096 + STREG %r8, PT_GR8(%r1) 2097 + STREG %r9, PT_GR9(%r1) 2098 + STREG %r10, PT_GR10(%r1) 2099 + STREG %r11, PT_GR11(%r1) 2100 + STREG %r12, PT_GR12(%r1) 2101 + STREG %r13, PT_GR13(%r1) 2102 + STREG %r14, PT_GR14(%r1) 2103 + STREG %r15, PT_GR15(%r1) 2104 + STREG %r16, PT_GR16(%r1) 2105 + STREG %r17, PT_GR17(%r1) 2106 + STREG %r18, PT_GR18(%r1) 2107 + STREG %r19, PT_GR19(%r1) 2108 + STREG %r20, PT_GR20(%r1) 2109 + STREG %r21, PT_GR21(%r1) 2110 + STREG %r22, PT_GR22(%r1) 2111 + STREG %r23, PT_GR23(%r1) 2112 + STREG %r24, PT_GR24(%r1) 2113 + STREG %r25, PT_GR25(%r1) 2114 + STREG %r26, PT_GR26(%r1) 2115 + STREG %r27, PT_GR27(%r1) 2116 + STREG %r28, PT_GR28(%r1) 2117 + STREG %r29, PT_GR29(%r1) 2118 + STREG %r30, PT_GR30(%r1) 2119 + STREG %r31, PT_GR31(%r1) 2120 + mfctl %cr11, %r26 2121 + STREG %r26, PT_SAR(%r1) 2122 + 2123 + copy %rp, %r26 2124 + LDREG -FTRACE_FRAME_SIZE-PT_SZ_ALGN(%sp), %r25 2125 + ldo -8(%r25), %r25 2126 + copy %r3, %arg2 2127 + b,l ftrace_function_trampoline, %rp 2128 + copy %r1, %arg3 /* struct pt_regs */ 2129 + 2130 + ldo -PT_SZ_ALGN(%sp), %r1 2131 + 2132 + LDREG PT_SAR(%r1), %rp 2133 + mtctl %rp, %cr11 2134 + 2135 + LDREG PT_GR2(%r1), %rp 2136 + LDREG PT_GR3(%r1), %r3 2137 + LDREG PT_GR4(%r1), %r4 2138 + LDREG PT_GR5(%r1), %r5 2139 + LDREG PT_GR6(%r1), %r6 2140 + LDREG PT_GR7(%r1), %r7 2141 + LDREG PT_GR8(%r1), %r8 2142 + LDREG PT_GR9(%r1), %r9 2143 + LDREG PT_GR10(%r1),%r10 2144 + LDREG PT_GR11(%r1),%r11 2145 + LDREG PT_GR12(%r1),%r12 2146 + LDREG PT_GR13(%r1),%r13 2147 + LDREG PT_GR14(%r1),%r14 2148 + LDREG PT_GR15(%r1),%r15 2149 + LDREG PT_GR16(%r1),%r16 2150 + LDREG PT_GR17(%r1),%r17 2151 + LDREG PT_GR18(%r1),%r18 2152 + LDREG PT_GR19(%r1),%r19 2153 + LDREG PT_GR20(%r1),%r20 2154 + LDREG PT_GR21(%r1),%r21 2155 + LDREG PT_GR22(%r1),%r22 2156 + LDREG PT_GR23(%r1),%r23 2157 + LDREG PT_GR24(%r1),%r24 2158 + LDREG PT_GR25(%r1),%r25 2159 + LDREG PT_GR26(%r1),%r26 2160 + LDREG PT_GR27(%r1),%r27 2161 + LDREG PT_GR28(%r1),%r28 2162 + LDREG PT_GR29(%r1),%r29 2163 + LDREG PT_GR30(%r1),%r30 2164 + LDREG PT_GR31(%r1),%r31 2165 + 2166 + ldo -PT_SZ_ALGN(%sp), %sp 2167 + LDREGM -FTRACE_FRAME_SIZE(%sp), %r1 2168 + /* Adjust return point to jump back to beginning of traced function */ 2169 + ldo -4(%r1), %r1 2170 + bv,n (%r1) 2171 + 2172 + ENDPROC_CFI(ftrace_regs_caller) 2173 + 2174 + #endif 2080 2175 #endif 2081 2176 2082 2177 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+55 -3
arch/parisc/kernel/ftrace.c
··· 13 13 #include <linux/init.h> 14 14 #include <linux/ftrace.h> 15 15 #include <linux/uaccess.h> 16 + #include <linux/kprobes.h> 17 + #include <linux/ptrace.h> 16 18 17 19 #include <asm/assembly.h> 18 20 #include <asm/sections.h> ··· 50 48 51 49 void notrace __hot ftrace_function_trampoline(unsigned long parent, 52 50 unsigned long self_addr, 53 - unsigned long org_sp_gr3) 51 + unsigned long org_sp_gr3, 52 + struct pt_regs *regs) 54 53 { 55 54 #ifndef CONFIG_DYNAMIC_FTRACE 56 55 extern ftrace_func_t ftrace_trace_function; ··· 61 58 if (function_trace_op->flags & FTRACE_OPS_FL_ENABLED && 62 59 ftrace_trace_function != ftrace_stub) 63 60 ftrace_trace_function(self_addr, parent, 64 - function_trace_op, NULL); 61 + function_trace_op, regs); 65 62 66 63 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 67 64 if (ftrace_graph_return != (trace_func_graph_ret_t) ftrace_stub || 68 - ftrace_graph_entry != ftrace_graph_entry_stub) { 65 + ftrace_graph_entry != ftrace_graph_entry_stub) { 69 66 unsigned long *parent_rp; 70 67 71 68 /* calculate pointer to %rp in stack */ ··· 99 96 return 0; 100 97 } 101 98 int ftrace_update_ftrace_func(ftrace_func_t func) 99 + { 100 + return 0; 101 + } 102 + 103 + int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, 104 + unsigned long addr) 102 105 { 103 106 return 0; 104 107 } ··· 197 188 __patch_text((void *)rec->ip, INSN_NOP); 198 189 __patch_text_multiple((void *)rec->ip + 4 - sizeof(insn), 199 190 insn, sizeof(insn)-4); 191 + return 0; 192 + } 193 + #endif 194 + 195 + #ifdef CONFIG_KPROBES_ON_FTRACE 196 + void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, 197 + struct ftrace_ops *ops, struct pt_regs *regs) 198 + { 199 + struct kprobe_ctlblk *kcb; 200 + struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip); 201 + 202 + if (unlikely(!p) || kprobe_disabled(p)) 203 + return; 204 + 205 + if (kprobe_running()) { 206 + kprobes_inc_nmissed_count(p); 207 + return; 208 + } 209 + 210 + __this_cpu_write(current_kprobe, p); 211 + 212 + kcb = get_kprobe_ctlblk(); 213 + kcb->kprobe_status = KPROBE_HIT_ACTIVE; 214 + 215 + regs->iaoq[0] = ip; 216 + regs->iaoq[1] = ip + 4; 217 + 218 + if (!p->pre_handler || !p->pre_handler(p, regs)) { 219 + regs->iaoq[0] = ip + 4; 220 + regs->iaoq[1] = ip + 8; 221 + 222 + if (unlikely(p->post_handler)) { 223 + kcb->kprobe_status = KPROBE_HIT_SSDONE; 224 + p->post_handler(p, regs, 0); 225 + } 226 + } 227 + __this_cpu_write(current_kprobe, NULL); 228 + } 229 + NOKPROBE_SYMBOL(kprobe_ftrace_handler); 230 + 231 + int arch_prepare_kprobe_ftrace(struct kprobe *p) 232 + { 233 + p->ainsn.insn = NULL; 200 234 return 0; 201 235 } 202 236 #endif