aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2010-11-10 04:05:57 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-11-10 04:05:54 -0500
commitadb45839817392102e659c19e5c19aa39530021f (patch)
tree00a28ba170a4f82e083942863997a55e5389b30a /arch/s390
parentbecf91f18750cf1c60828aa2ee63a36b05c2e4d0 (diff)
[S390] kprobes: disable interrupts throughout
Execute the kprobe exception and fault handler with interrupts disabled. To disable the interrupts only while a single step is in progress is not good enough, a kprobe from interrupt context while another kprobe is handled can confuse the internal house keeping. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/kprobes.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index d60fc4398516..70cf73bdba25 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -30,6 +30,7 @@
30#include <asm/sections.h> 30#include <asm/sections.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/hardirq.h>
33 34
34DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; 35DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
35DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 36DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -212,7 +213,7 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
212 /* Set the PER control regs, turns on single step for this address */ 213 /* Set the PER control regs, turns on single step for this address */
213 __ctl_load(kprobe_per_regs, 9, 11); 214 __ctl_load(kprobe_per_regs, 9, 11);
214 regs->psw.mask |= PSW_MASK_PER; 215 regs->psw.mask |= PSW_MASK_PER;
215 regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); 216 regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT);
216} 217}
217 218
218static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) 219static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
@@ -239,7 +240,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
239 __get_cpu_var(current_kprobe) = p; 240 __get_cpu_var(current_kprobe) = p;
240 /* Save the interrupt and per flags */ 241 /* Save the interrupt and per flags */
241 kcb->kprobe_saved_imask = regs->psw.mask & 242 kcb->kprobe_saved_imask = regs->psw.mask &
242 (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); 243 (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT);
243 /* Save the control regs that govern PER */ 244 /* Save the control regs that govern PER */
244 __ctl_store(kcb->kprobe_saved_ctl, 9, 11); 245 __ctl_store(kcb->kprobe_saved_ctl, 9, 11);
245} 246}
@@ -316,8 +317,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
316 return 1; 317 return 1;
317 318
318ss_probe: 319ss_probe:
319 if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO))
320 local_irq_disable();
321 prepare_singlestep(p, regs); 320 prepare_singlestep(p, regs);
322 kcb->kprobe_status = KPROBE_HIT_SS; 321 kcb->kprobe_status = KPROBE_HIT_SS;
323 return 1; 322 return 1;
@@ -465,8 +464,6 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
465 goto out; 464 goto out;
466 } 465 }
467 reset_current_kprobe(); 466 reset_current_kprobe();
468 if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO))
469 local_irq_enable();
470out: 467out:
471 preempt_enable_no_resched(); 468 preempt_enable_no_resched();
472 469
@@ -482,7 +479,7 @@ out:
482 return 1; 479 return 1;
483} 480}
484 481
485int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) 482static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr)
486{ 483{
487 struct kprobe *cur = kprobe_running(); 484 struct kprobe *cur = kprobe_running();
488 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 485 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -508,8 +505,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
508 restore_previous_kprobe(kcb); 505 restore_previous_kprobe(kcb);
509 else { 506 else {
510 reset_current_kprobe(); 507 reset_current_kprobe();
511 if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO))
512 local_irq_enable();
513 } 508 }
514 preempt_enable_no_resched(); 509 preempt_enable_no_resched();
515 break; 510 break;
@@ -553,6 +548,18 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
553 return 0; 548 return 0;
554} 549}
555 550
551int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
552{
553 int ret;
554
555 if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT))
556 local_irq_disable();
557 ret = kprobe_trap_handler(regs, trapnr);
558 if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT))
559 local_irq_restore(regs->psw.mask & ~PSW_MASK_PER);
560 return ret;
561}
562
556/* 563/*
557 * Wrapper routine to for handling exceptions. 564 * Wrapper routine to for handling exceptions.
558 */ 565 */
@@ -560,8 +567,12 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
560 unsigned long val, void *data) 567 unsigned long val, void *data)
561{ 568{
562 struct die_args *args = (struct die_args *)data; 569 struct die_args *args = (struct die_args *)data;
570 struct pt_regs *regs = args->regs;
563 int ret = NOTIFY_DONE; 571 int ret = NOTIFY_DONE;
564 572
573 if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT))
574 local_irq_disable();
575
565 switch (val) { 576 switch (val) {
566 case DIE_BPT: 577 case DIE_BPT:
567 if (kprobe_handler(args->regs)) 578 if (kprobe_handler(args->regs))
@@ -572,16 +583,17 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
572 ret = NOTIFY_STOP; 583 ret = NOTIFY_STOP;
573 break; 584 break;
574 case DIE_TRAP: 585 case DIE_TRAP:
575 /* kprobe_running() needs smp_processor_id() */ 586 if (!preemptible() && kprobe_running() &&
576 preempt_disable(); 587 kprobe_trap_handler(args->regs, args->trapnr))
577 if (kprobe_running() &&
578 kprobe_fault_handler(args->regs, args->trapnr))
579 ret = NOTIFY_STOP; 588 ret = NOTIFY_STOP;
580 preempt_enable();
581 break; 589 break;
582 default: 590 default:
583 break; 591 break;
584 } 592 }
593
594 if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT))
595 local_irq_restore(regs->psw.mask & ~PSW_MASK_PER);
596
585 return ret; 597 return ret;
586} 598}
587 599
@@ -595,6 +607,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
595 607
596 /* setup return addr to the jprobe handler routine */ 608 /* setup return addr to the jprobe handler routine */
597 regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE; 609 regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE;
610 regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT);
598 611
599 /* r14 is the function return address */ 612 /* r14 is the function return address */
600 kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14]; 613 kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14];