diff options
Diffstat (limited to 'arch/sparc64/kernel/kprobes.c')
-rw-r--r-- | arch/sparc64/kernel/kprobes.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 58a815e90373..96bd09b098f4 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c | |||
@@ -113,7 +113,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
113 | struct kprobe *p; | 113 | struct kprobe *p; |
114 | void *addr = (void *) regs->tpc; | 114 | void *addr = (void *) regs->tpc; |
115 | int ret = 0; | 115 | int ret = 0; |
116 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 116 | struct kprobe_ctlblk *kcb; |
117 | |||
118 | /* | ||
119 | * We don't want to be preempted for the entire | ||
120 | * duration of kprobe processing | ||
121 | */ | ||
122 | preempt_disable(); | ||
123 | kcb = get_kprobe_ctlblk(); | ||
117 | 124 | ||
118 | if (kprobe_running()) { | 125 | if (kprobe_running()) { |
119 | p = get_kprobe(addr); | 126 | p = get_kprobe(addr); |
@@ -159,11 +166,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
159 | goto no_kprobe; | 166 | goto no_kprobe; |
160 | } | 167 | } |
161 | 168 | ||
162 | /* | ||
163 | * This preempt_disable() matches the preempt_enable_no_resched() | ||
164 | * in post_kprobes_handler() | ||
165 | */ | ||
166 | preempt_disable(); | ||
167 | set_current_kprobe(p, regs, kcb); | 169 | set_current_kprobe(p, regs, kcb); |
168 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | 170 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; |
169 | if (p->pre_handler && p->pre_handler(p, regs)) | 171 | if (p->pre_handler && p->pre_handler(p, regs)) |
@@ -175,6 +177,7 @@ ss_probe: | |||
175 | return 1; | 177 | return 1; |
176 | 178 | ||
177 | no_kprobe: | 179 | no_kprobe: |
180 | preempt_enable_no_resched(); | ||
178 | return ret; | 181 | return ret; |
179 | } | 182 | } |
180 | 183 | ||
@@ -321,7 +324,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
321 | struct die_args *args = (struct die_args *)data; | 324 | struct die_args *args = (struct die_args *)data; |
322 | int ret = NOTIFY_DONE; | 325 | int ret = NOTIFY_DONE; |
323 | 326 | ||
324 | rcu_read_lock(); | ||
325 | switch (val) { | 327 | switch (val) { |
326 | case DIE_DEBUG: | 328 | case DIE_DEBUG: |
327 | if (kprobe_handler(args->regs)) | 329 | if (kprobe_handler(args->regs)) |
@@ -333,14 +335,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
333 | break; | 335 | break; |
334 | case DIE_GPF: | 336 | case DIE_GPF: |
335 | case DIE_PAGE_FAULT: | 337 | case DIE_PAGE_FAULT: |
338 | /* kprobe_running() needs smp_processor_id() */ | ||
339 | preempt_disable(); | ||
336 | if (kprobe_running() && | 340 | if (kprobe_running() && |
337 | kprobe_fault_handler(args->regs, args->trapnr)) | 341 | kprobe_fault_handler(args->regs, args->trapnr)) |
338 | ret = NOTIFY_STOP; | 342 | ret = NOTIFY_STOP; |
343 | preempt_enable(); | ||
339 | break; | 344 | break; |
340 | default: | 345 | default: |
341 | break; | 346 | break; |
342 | } | 347 | } |
343 | rcu_read_unlock(); | ||
344 | return ret; | 348 | return ret; |
345 | } | 349 | } |
346 | 350 | ||
@@ -426,6 +430,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
426 | &(kcb->jprobe_saved_stack), | 430 | &(kcb->jprobe_saved_stack), |
427 | sizeof(kcb->jprobe_saved_stack)); | 431 | sizeof(kcb->jprobe_saved_stack)); |
428 | 432 | ||
433 | preempt_enable_no_resched(); | ||
429 | return 1; | 434 | return 1; |
430 | } | 435 | } |
431 | return 0; | 436 | return 0; |