aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2011-01-05 06:47:23 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2011-01-05 06:47:24 -0500
commit0e917cc3297f3274993d25b5972c2b1c6f763819 (patch)
tree6638db354d17cee5a5fc0954b8b2b7a30aaa93d8 /arch/s390
parent92b8cbf17ae98a118d3e4a123246a05130114d06 (diff)
[S390] kprobes: restructure handler function
Restructure the kprobe breakpoint handler function. Add comments to make it more comprehensible and add a sanity check for re-entering kprobes. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/kprobes.c114
1 files changed, 71 insertions, 43 deletions
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 4efd5dbfd72d..2a19f4154f2d 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -238,25 +238,44 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
238 regs->gprs[14] = (unsigned long)&kretprobe_trampoline; 238 regs->gprs[14] = (unsigned long)&kretprobe_trampoline;
239} 239}
240 240
241static void __kprobes kprobe_reenter_check(struct kprobe_ctlblk *kcb,
242 struct kprobe *p)
243{
244 switch (kcb->kprobe_status) {
245 case KPROBE_HIT_SSDONE:
246 case KPROBE_HIT_ACTIVE:
247 kprobes_inc_nmissed_count(p);
248 break;
249 case KPROBE_HIT_SS:
250 case KPROBE_REENTER:
251 default:
252 /*
253 * A kprobe on the code path to single step an instruction
254 * is a BUG. The code path resides in the .kprobes.text
255 * section and is executed with interrupts disabled.
256 */
257 printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
258 dump_kprobe(p);
259 BUG();
260 }
261}
262
241static int __kprobes kprobe_handler(struct pt_regs *regs) 263static int __kprobes kprobe_handler(struct pt_regs *regs)
242{ 264{
243 struct kprobe *p;
244 int ret = 0;
245 unsigned long *addr = (unsigned long *)
246 ((regs->psw.addr & PSW_ADDR_INSN) - 2);
247 struct kprobe_ctlblk *kcb; 265 struct kprobe_ctlblk *kcb;
266 struct kprobe *p;
248 267
249 /* 268 /*
250 * We don't want to be preempted for the entire 269 * We want to disable preemption for the entire duration of kprobe
251 * duration of kprobe processing 270 * processing. That includes the calls to the pre/post handlers
271 * and single stepping the kprobe instruction.
252 */ 272 */
253 preempt_disable(); 273 preempt_disable();
254 kcb = get_kprobe_ctlblk(); 274 kcb = get_kprobe_ctlblk();
275 p = get_kprobe((void *)((regs->psw.addr & PSW_ADDR_INSN) - 2));
255 276
256 /* Check we're not actually recursing */ 277 if (p) {
257 if (kprobe_running()) { 278 if (kprobe_running()) {
258 p = get_kprobe(addr);
259 if (p) {
260 /* 279 /*
261 * We have hit a kprobe while another is still 280 * We have hit a kprobe while another is still
262 * active. This can happen in the pre and post 281 * active. This can happen in the pre and post
@@ -266,45 +285,54 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
266 * push_kprobe and pop_kprobe saves and restores 285 * push_kprobe and pop_kprobe saves and restores
267 * the currently active kprobe. 286 * the currently active kprobe.
268 */ 287 */
288 kprobe_reenter_check(kcb, p);
269 push_kprobe(kcb, p); 289 push_kprobe(kcb, p);
270 kprobes_inc_nmissed_count(p);
271 enable_singlestep(kcb, regs,
272 (unsigned long) p->ainsn.insn);
273 kcb->kprobe_status = KPROBE_REENTER; 290 kcb->kprobe_status = KPROBE_REENTER;
274 return 1;
275 } else { 291 } else {
276 p = __get_cpu_var(current_kprobe); 292 /*
277 if (p->break_handler && p->break_handler(p, regs)) { 293 * If we have no pre-handler or it returned 0, we
278 goto ss_probe; 294 * continue with single stepping. If we have a
279 } 295 * pre-handler and it returned non-zero, it prepped
296 * for calling the break_handler below on re-entry
297 * for jprobe processing, so get out doing nothing
298 * more here.
299 */
300 push_kprobe(kcb, p);
301 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
302 if (p->pre_handler && p->pre_handler(p, regs))
303 return 1;
304 kcb->kprobe_status = KPROBE_HIT_SS;
280 } 305 }
281 goto no_kprobe; 306 enable_singlestep(kcb, regs, (unsigned long) p->ainsn.insn);
282 }
283
284 p = get_kprobe(addr);
285 if (!p)
286 /*
287 * No kprobe at this address. The fault has not been
288 * caused by a kprobe breakpoint. The race of breakpoint
289 * vs. kprobe remove does not exist because on s390 we
290 * use stop_machine to arm/disarm the breakpoints.
291 */
292 goto no_kprobe;
293
294 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
295 push_kprobe(kcb, p);
296 if (p->pre_handler && p->pre_handler(p, regs))
297 /* handler has already set things up, so skip ss setup */
298 return 1; 307 return 1;
299 308 } else if (kprobe_running()) {
300ss_probe: 309 p = __get_cpu_var(current_kprobe);
301 enable_singlestep(kcb, regs, (unsigned long) p->ainsn.insn); 310 if (p->break_handler && p->break_handler(p, regs)) {
302 kcb->kprobe_status = KPROBE_HIT_SS; 311 /*
303 return 1; 312 * Continuation after the jprobe completed and
304 313 * caused the jprobe_return trap. The jprobe
305no_kprobe: 314 * break_handler "returns" to the original
315 * function that still has the kprobe breakpoint
316 * installed. We continue with single stepping.
317 */
318 kcb->kprobe_status = KPROBE_HIT_SS;
319 enable_singlestep(kcb, regs,
320 (unsigned long) p->ainsn.insn);
321 return 1;
322 } /* else:
323 * No kprobe at this address and the current kprobe
324 * has no break handler (no jprobe!). The kernel just
325 * exploded, let the standard trap handler pick up the
326 * pieces.
327 */
328 } /* else:
329 * No kprobe at this address and no active kprobe. The trap has
330 * not been caused by a kprobe breakpoint. The race of breakpoint
331 * vs. kprobe remove does not exist because on s390 as we use
332 * stop_machine to arm/disarm the breakpoints.
333 */
306 preempt_enable_no_resched(); 334 preempt_enable_no_resched();
307 return ret; 335 return 0;
308} 336}
309 337
310/* 338/*