From 3ded2c8e6ce800581c61c8e04ef76cff12ced58a Mon Sep 17 00:00:00 2001 From: Prasanna S Panchamukhi Date: Sun, 26 Mar 2006 01:38:24 -0800 Subject: [PATCH] --- yaml --- r: 24112 b: refs/heads/master c: 50e21f2b2861711b6df0b72ffef4a70d1532b023 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/powerpc/kernel/kprobes.c | 63 +++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/[refs] b/[refs] index 14aa1a2a8b31..adf75a3b5b6f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c28f896634f2c931a298490deab3861ab117716a +refs/heads/master: 50e21f2b2861711b6df0b72ffef4a70d1532b023 diff --git a/trunk/arch/powerpc/kernel/kprobes.c b/trunk/arch/powerpc/kernel/kprobes.c index aea25dd18dae..ad7a90212204 100644 --- a/trunk/arch/powerpc/kernel/kprobes.c +++ b/trunk/arch/powerpc/kernel/kprobes.c @@ -30,9 +30,11 @@ #include #include #include +#include #include #include #include +#include DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); @@ -372,17 +374,62 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) - return 1; - - if (kcb->kprobe_status & KPROBE_HIT_SS) { - resume_execution(cur, regs); + const struct exception_table_entry *entry; + + switch(kcb->kprobe_status) { + case KPROBE_HIT_SS: + case KPROBE_REENTER: + /* + * We are here because the instruction being single + * stepped caused a page fault. We reset the current + * kprobe and the nip points back to the probe address + * and allow the page fault handler to continue as a + * normal page fault. + */ + regs->nip = (unsigned long)cur->addr; regs->msr &= ~MSR_SE; regs->msr |= kcb->kprobe_saved_msr; - - reset_current_kprobe(); + if (kcb->kprobe_status == KPROBE_REENTER) + restore_previous_kprobe(kcb); + else + reset_current_kprobe(); preempt_enable_no_resched(); + break; + case KPROBE_HIT_ACTIVE: + case KPROBE_HIT_SSDONE: + /* + * We increment the nmissed count for accounting, + * we can also use npre/npostfault count for accouting + * these specific fault cases. + */ + kprobes_inc_nmissed_count(cur); + + /* + * We come here because instructions in the pre/post + * handler caused the page_fault, this could happen + * if handler tries to access user space by + * copy_from_user(), get_user() etc. Let the + * user-specified handler try to fix it first. + */ + if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) + return 1; + + /* + * In case the user-specified fault handler returned + * zero, try to fix up. + */ + if ((entry = search_exception_tables(regs->nip)) != NULL) { + regs->nip = entry->fixup; + return 1; + } + + /* + * fixup_exception() could not handle it, + * Let do_page_fault() fix it. + */ + break; + default: + break; } return 0; }