summaryrefslogtreecommitdiffstats
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.c24
1 files changed, 6 insertions, 18 deletions
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 3f89f3e5584a..e0a25b35437f 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -30,7 +30,6 @@
#include <linux/config.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
-#include <linux/spinlock.h>
#include <linux/preempt.h>
#include <asm/cacheflush.h>
#include <asm/kdebug.h>
@@ -125,6 +124,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_saved_msr = regs->msr;
}
+/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
struct pt_regs *regs)
{
@@ -152,8 +152,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
/* Check we're not actually recursing */
if (kprobe_running()) {
- /* We *are* holding lock here, so this is safe.
- Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
kprobe_opcode_t insn = *p->ainsn.insn;
@@ -161,7 +159,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
is_trap(insn)) {
regs->msr &= ~MSR_SE;
regs->msr |= kcb->kprobe_saved_msr;
- unlock_kprobes();
goto no_kprobe;
}
/* We have reentered the kprobe_handler(), since
@@ -183,14 +180,11 @@ static inline int kprobe_handler(struct pt_regs *regs)
goto ss_probe;
}
}
- /* If it's not ours, can't be delete race, (we hold lock). */
goto no_kprobe;
}
- lock_kprobes();
p = get_kprobe(addr);
if (!p) {
- unlock_kprobes();
if (*addr != BREAKPOINT_INSTRUCTION) {
/*
* PowerPC has multiple variants of the "trap"
@@ -254,9 +248,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
+ unsigned long flags, orig_ret_address = 0;
unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+ spin_lock_irqsave(&kretprobe_lock, flags);
head = kretprobe_inst_table_head(current);
/*
@@ -296,7 +291,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
regs->nip = orig_ret_address;
reset_current_kprobe();
- unlock_kprobes();
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
preempt_enable_no_resched();
/*
@@ -348,7 +343,6 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
goto out;
}
reset_current_kprobe();
- unlock_kprobes();
out:
preempt_enable_no_resched();
@@ -363,7 +357,6 @@ out:
return 1;
}
-/* Interrupts disabled, kprobe_lock held. */
static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
@@ -378,7 +371,6 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
regs->msr |= kcb->kprobe_saved_msr;
reset_current_kprobe();
- unlock_kprobes();
preempt_enable_no_resched();
}
return 0;
@@ -393,11 +385,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
- /*
- * Interrupts are not disabled here. We need to disable
- * preemption, because kprobe_running() uses smp_processor_id().
- */
- preempt_disable();
+ rcu_read_lock();
switch (val) {
case DIE_BPT:
if (kprobe_handler(args->regs))
@@ -415,7 +403,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
default:
break;
}
- preempt_enable_no_resched();
+ rcu_read_unlock();
return ret;
}