diff options
Diffstat (limited to 'arch/ppc64/kernel/kprobes.c')
-rw-r--r-- | arch/ppc64/kernel/kprobes.c | 25 |
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 | ||
226 | no_kprobe: | 228 | no_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 | ||