aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel/kprobes.c')
-rw-r--r--arch/ppc64/kernel/kprobes.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index e0a25b35437f..511af54e6230 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -148,7 +148,14 @@ static inline int kprobe_handler(struct pt_regs *regs)
148 struct kprobe *p; 148 struct kprobe *p;
149 int ret = 0; 149 int ret = 0;
150 unsigned int *addr = (unsigned int *)regs->nip; 150 unsigned int *addr = (unsigned int *)regs->nip;
151 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 151 struct kprobe_ctlblk *kcb;
152
153 /*
154 * We don't want to be preempted for the entire
155 * duration of kprobe processing
156 */
157 preempt_disable();
158 kcb = get_kprobe_ctlblk();
152 159
153 /* Check we're not actually recursing */ 160 /* Check we're not actually recursing */
154 if (kprobe_running()) { 161 if (kprobe_running()) {
@@ -207,11 +214,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
207 goto no_kprobe; 214 goto no_kprobe;
208 } 215 }
209 216
210 /*
211 * This preempt_disable() matches the preempt_enable_no_resched()
212 * in post_kprobe_handler().
213 */
214 preempt_disable();
215 kcb->kprobe_status = KPROBE_HIT_ACTIVE; 217 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
216 set_current_kprobe(p, regs, kcb); 218 set_current_kprobe(p, regs, kcb);
217 if (p->pre_handler && p->pre_handler(p, regs)) 219 if (p->pre_handler && p->pre_handler(p, regs))
@@ -224,6 +226,7 @@ ss_probe:
224 return 1; 226 return 1;
225 227
226no_kprobe: 228no_kprobe:
229 preempt_enable_no_resched();
227 return ret; 230 return ret;
228} 231}
229 232
@@ -296,8 +299,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
296 299
297 /* 300 /*
298 * By returning a non-zero value, we are telling 301 * By returning a non-zero value, we are telling
299 * kprobe_handler() that we have handled unlocking 302 * kprobe_handler() that we don't want the post_handler
300 * and re-enabling preemption. 303 * to run (and have re-enabled preemption)
301 */ 304 */
302 return 1; 305 return 1;
303} 306}
@@ -385,7 +388,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
385 struct die_args *args = (struct die_args *)data; 388 struct die_args *args = (struct die_args *)data;
386 int ret = NOTIFY_DONE; 389 int ret = NOTIFY_DONE;
387 390
388 rcu_read_lock();
389 switch (val) { 391 switch (val) {
390 case DIE_BPT: 392 case DIE_BPT:
391 if (kprobe_handler(args->regs)) 393 if (kprobe_handler(args->regs))
@@ -396,14 +398,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
396 ret = NOTIFY_STOP; 398 ret = NOTIFY_STOP;
397 break; 399 break;
398 case DIE_PAGE_FAULT: 400 case DIE_PAGE_FAULT:
401 /* kprobe_running() needs smp_processor_id() */
402 preempt_disable();
399 if (kprobe_running() && 403 if (kprobe_running() &&
400 kprobe_fault_handler(args->regs, args->trapnr)) 404 kprobe_fault_handler(args->regs, args->trapnr))
401 ret = NOTIFY_STOP; 405 ret = NOTIFY_STOP;
406 preempt_enable();
402 break; 407 break;
403 default: 408 default:
404 break; 409 break;
405 } 410 }
406 rcu_read_unlock();
407 return ret; 411 return ret;
408} 412}
409 413
@@ -440,6 +444,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
440 * saved regs... 444 * saved regs...
441 */ 445 */
442 memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); 446 memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
447 preempt_enable_no_resched();
443 return 1; 448 return 1;
444} 449}
445 450