linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / sparc64 / kernel / kprobes.c
index 8e75ed7..b9a9ce7 100644 (file)
@@ -3,13 +3,12 @@
  * Copyright (C) 2004 David S. Miller <davem@davemloft.net>
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
-#include <linux/module.h>
 #include <asm/kdebug.h>
 #include <asm/signal.h>
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
 
 /* We do not have hardware single-stepping on sparc64.
  * So we implement software single-stepping with breakpoint
@@ -62,7 +61,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
        flushi(p->addr);
 }
 
-static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        kcb->prev_kprobe.kp = kprobe_running();
        kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -70,7 +69,7 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
 }
 
-static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
        kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -78,7 +77,7 @@ static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
 }
 
-static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
                                struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = p;
@@ -86,7 +85,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
        kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
 }
 
-static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
                        struct kprobe_ctlblk *kcb)
 {
        regs->tstate |= TSTATE_PIL;
@@ -272,7 +271,7 @@ static void __kprobes resume_execution(struct kprobe *p,
                        kcb->kprobe_orig_tstate_pil);
 }
 
-static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+static inline int post_kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -299,72 +298,20 @@ out:
        return 1;
 }
 
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-       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 tpc points back to the probe address
-                * and allow the page fault handler to continue as a
-                * normal page fault.
-                */
-               regs->tpc = (unsigned long)cur->addr;
-               regs->tnpc = kcb->kprobe_orig_tnpc;
-               regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
-                               kcb->kprobe_orig_tstate_pil);
-               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 (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+               return 1;
 
-               entry = search_exception_tables(regs->tpc);
-               if (entry) {
-                       regs->tpc = entry->fixup;
-                       regs->tnpc = regs->tpc + 4;
-                       return 1;
-               }
+       if (kcb->kprobe_status & KPROBE_HIT_SS) {
+               resume_execution(cur, regs, kcb);
 
-               /*
-                * fixup_exception() could not handle it,
-                * Let do_page_fault() fix it.
-                */
-               break;
-       default:
-               break;
+               reset_current_kprobe();
+               preempt_enable_no_resched();
        }
-
        return 0;
 }
 
@@ -377,9 +324,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
        struct die_args *args = (struct die_args *)data;
        int ret = NOTIFY_DONE;
 
-       if (args->regs && user_mode(args->regs))
-               return ret;
-
        switch (val) {
        case DIE_DEBUG:
                if (kprobe_handler(args->regs))