ftrace.c (c39f2d9db0fd81ea20bb5cce9b3f082ca63753e2) | ftrace.c (657480d9c01574d1e11bbb29e725db9907daf782) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Dynamic function tracer architecture backend. 4 * 5 * Copyright IBM Corp. 2009,2014 6 * 7 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, 8 * Martin Schwidefsky <schwidefsky@de.ibm.com> --- 58 unchanged lines hidden (view full) --- 67 insn->disp = 0; 68#else 69 /* stg r14,8(r15) */ 70 insn->opc = 0xe3e0; 71 insn->disp = 0xf0080024; 72#endif 73} 74 | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Dynamic function tracer architecture backend. 4 * 5 * Copyright IBM Corp. 2009,2014 6 * 7 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>, 8 * Martin Schwidefsky <schwidefsky@de.ibm.com> --- 58 unchanged lines hidden (view full) --- 67 insn->disp = 0; 68#else 69 /* stg r14,8(r15) */ 70 insn->opc = 0xe3e0; 71 insn->disp = 0xf0080024; 72#endif 73} 74 |
75static inline int is_kprobe_on_ftrace(struct ftrace_insn *insn) 76{ 77#ifdef CONFIG_KPROBES 78 if (insn->opc == BREAKPOINT_INSTRUCTION) 79 return 1; 80#endif 81 return 0; 82} 83 | |
84static inline void ftrace_generate_kprobe_nop_insn(struct ftrace_insn *insn) 85{ 86#ifdef CONFIG_KPROBES 87 insn->opc = BREAKPOINT_INSTRUCTION; 88 insn->disp = KPROBE_ON_FTRACE_NOP; 89#endif 90} 91 --- 17 unchanged lines hidden (view full) --- 109 struct ftrace_insn orig, new, old; 110 111 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) 112 return -EFAULT; 113 if (addr == MCOUNT_ADDR) { 114 /* Initial code replacement */ 115 ftrace_generate_orig_insn(&orig); 116 ftrace_generate_nop_insn(&new); | 75static inline void ftrace_generate_kprobe_nop_insn(struct ftrace_insn *insn) 76{ 77#ifdef CONFIG_KPROBES 78 insn->opc = BREAKPOINT_INSTRUCTION; 79 insn->disp = KPROBE_ON_FTRACE_NOP; 80#endif 81} 82 --- 17 unchanged lines hidden (view full) --- 100 struct ftrace_insn orig, new, old; 101 102 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) 103 return -EFAULT; 104 if (addr == MCOUNT_ADDR) { 105 /* Initial code replacement */ 106 ftrace_generate_orig_insn(&orig); 107 ftrace_generate_nop_insn(&new); |
117 } else if (is_kprobe_on_ftrace(&old)) { 118 /* 119 * If we find a breakpoint instruction, a kprobe has been 120 * placed at the beginning of the function. We write the 121 * constant KPROBE_ON_FTRACE_NOP into the remaining four 122 * bytes of the original instruction so that the kprobes 123 * handler can execute a nop, if it reaches this breakpoint. 124 */ 125 ftrace_generate_kprobe_call_insn(&orig); 126 ftrace_generate_kprobe_nop_insn(&new); | |
127 } else { 128 /* Replace ftrace call with a nop. */ 129 ftrace_generate_call_insn(&orig, rec->ip); 130 ftrace_generate_nop_insn(&new); 131 } 132 /* Verify that the to be replaced code matches what we expect. */ 133 if (memcmp(&orig, &old, sizeof(old))) 134 return -EINVAL; 135 s390_kernel_write((void *) rec->ip, &new, sizeof(new)); 136 return 0; 137} 138 139int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) 140{ 141 struct ftrace_insn orig, new, old; 142 143 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) 144 return -EFAULT; | 108 } else { 109 /* Replace ftrace call with a nop. */ 110 ftrace_generate_call_insn(&orig, rec->ip); 111 ftrace_generate_nop_insn(&new); 112 } 113 /* Verify that the to be replaced code matches what we expect. */ 114 if (memcmp(&orig, &old, sizeof(old))) 115 return -EINVAL; 116 s390_kernel_write((void *) rec->ip, &new, sizeof(new)); 117 return 0; 118} 119 120int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) 121{ 122 struct ftrace_insn orig, new, old; 123 124 if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) 125 return -EFAULT; |
145 if (is_kprobe_on_ftrace(&old)) { 146 /* 147 * If we find a breakpoint instruction, a kprobe has been 148 * placed at the beginning of the function. We write the 149 * constant KPROBE_ON_FTRACE_CALL into the remaining four 150 * bytes of the original instruction so that the kprobes 151 * handler can execute a brasl if it reaches this breakpoint. 152 */ 153 ftrace_generate_kprobe_nop_insn(&orig); 154 ftrace_generate_kprobe_call_insn(&new); 155 } else { 156 /* Replace nop with an ftrace call. */ 157 ftrace_generate_nop_insn(&orig); 158 ftrace_generate_call_insn(&new, rec->ip); 159 } | 126 /* Replace nop with an ftrace call. */ 127 ftrace_generate_nop_insn(&orig); 128 ftrace_generate_call_insn(&new, rec->ip); 129 |
160 /* Verify that the to be replaced code matches what we expect. */ 161 if (memcmp(&orig, &old, sizeof(old))) 162 return -EINVAL; 163 s390_kernel_write((void *) rec->ip, &new, sizeof(new)); 164 return 0; 165} 166 167int ftrace_update_ftrace_func(ftrace_func_t func) --- 68 unchanged lines hidden (view full) --- 236{ 237 u8 op = 0xf4; /* set mask field to all ones */ 238 239 s390_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op)); 240 return 0; 241} 242 243#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 130 /* Verify that the to be replaced code matches what we expect. */ 131 if (memcmp(&orig, &old, sizeof(old))) 132 return -EINVAL; 133 s390_kernel_write((void *) rec->ip, &new, sizeof(new)); 134 return 0; 135} 136 137int ftrace_update_ftrace_func(ftrace_func_t func) --- 68 unchanged lines hidden (view full) --- 206{ 207 u8 op = 0xf4; /* set mask field to all ones */ 208 209 s390_kernel_write(__va(ftrace_graph_caller)+1, &op, sizeof(op)); 210 return 0; 211} 212 213#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
214 215#ifdef CONFIG_KPROBES_ON_FTRACE 216void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, 217 struct ftrace_ops *ops, struct pt_regs *regs) 218{ 219 struct kprobe_ctlblk *kcb; 220 struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip); 221 222 if (unlikely(!p) || kprobe_disabled(p)) 223 return; 224 225 if (kprobe_running()) { 226 kprobes_inc_nmissed_count(p); 227 return; 228 } 229 230 __this_cpu_write(current_kprobe, p); 231 232 kcb = get_kprobe_ctlblk(); 233 kcb->kprobe_status = KPROBE_HIT_ACTIVE; 234 235 instruction_pointer_set(regs, ip); 236 237 if (!p->pre_handler || !p->pre_handler(p, regs)) { 238 239 instruction_pointer_set(regs, ip + MCOUNT_INSN_SIZE); 240 241 if (unlikely(p->post_handler)) { 242 kcb->kprobe_status = KPROBE_HIT_SSDONE; 243 p->post_handler(p, regs, 0); 244 } 245 } 246 __this_cpu_write(current_kprobe, NULL); 247} 248NOKPROBE_SYMBOL(kprobe_ftrace_handler); 249 250int arch_prepare_kprobe_ftrace(struct kprobe *p) 251{ 252 p->ainsn.insn = NULL; 253 return 0; 254} 255#endif |
|