Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux...
[sfrench/cifs-2.6.git] / arch / ia64 / kernel / kprobes.c
index 5dc98b5abcfbcc3de963e60faaa139d86d362170..8d9a446a0d178e47a8ffad9a47711ee564680da3 100644 (file)
@@ -40,6 +40,8 @@ extern void jprobe_inst_return(void);
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
+struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
+
 enum instruction_type {A, I, M, F, B, L, X, u};
 static enum instruction_type bundle_encoding[32][3] = {
   { M, I, I },                         /* 00 */
@@ -180,8 +182,8 @@ static int __kprobes unsupported_inst(uint template, uint  slot,
        qp = kprobe_inst & 0x3f;
        if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) {
                if (slot == 1 && qp)  {
-                       printk(KERN_WARNING "Kprobes on cmp unc"
-                                       "instruction on slot 1 at <0x%lx>"
+                       printk(KERN_WARNING "Kprobes on cmp unc "
+                                       "instruction on slot 1 at <0x%lx> "
                                        "is not supported\n", addr);
                        return -EINVAL;
 
@@ -219,8 +221,8 @@ static int __kprobes unsupported_inst(uint template, uint  slot,
                         * bit 12 to be equal to 1
                         */
                        if (slot == 1 && qp) {
-                               printk(KERN_WARNING "Kprobes on test bit"
-                                               "instruction on slot at <0x%lx>"
+                               printk(KERN_WARNING "Kprobes on test bit "
+                                               "instruction on slot at <0x%lx> "
                                                "is not supported\n", addr);
                                return -EINVAL;
                        }
@@ -240,7 +242,7 @@ static int __kprobes unsupported_inst(uint template, uint  slot,
                         */
                        int x6=(kprobe_inst >> 27) & 0x3F;
                        if ((x6 == 0x10) || (x6 == 0x11)) {
-                               printk(KERN_WARNING "Kprobes on"
+                               printk(KERN_WARNING "Kprobes on "
                                        "Indirect Predict is not supported\n");
                                return -EINVAL;
                        }
@@ -379,9 +381,10 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        unsigned int i;
-       i = atomic_sub_return(1, &kcb->prev_kprobe_index);
-       __get_cpu_var(current_kprobe) = kcb->prev_kprobe[i].kp;
-       kcb->kprobe_status = kcb->prev_kprobe[i].status;
+       i = atomic_read(&kcb->prev_kprobe_index);
+       __get_cpu_var(current_kprobe) = kcb->prev_kprobe[i-1].kp;
+       kcb->kprobe_status = kcb->prev_kprobe[i-1].status;
+       atomic_sub(1, &kcb->prev_kprobe_index);
 }
 
 static void __kprobes set_current_kprobe(struct kprobe *p,
@@ -428,6 +431,23 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
         *       real return address, and all the rest will point to
         *       kretprobe_trampoline
         */
+       hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+               if (ri->task != current)
+                       /* another task is sharing our hash bucket */
+                       continue;
+
+               orig_ret_address = (unsigned long)ri->ret_addr;
+               if (orig_ret_address != trampoline_address)
+                       /*
+                        * This is the real return address. Any other
+                        * instances associated with this task are for
+                        * other calls deeper on the call stack
+                        */
+                       break;
+       }
+
+       regs->cr_iip = orig_ret_address;
+
        hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
                if (ri->task != current)
                        /* another task is sharing our hash bucket */
@@ -450,8 +470,6 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 
        kretprobe_assert(ri, orig_ret_address, trampoline_address);
 
-       regs->cr_iip = orig_ret_address;
-
        reset_current_kprobe();
        spin_unlock_irqrestore(&kretprobe_lock, flags);
        preempt_enable_no_resched();
@@ -820,7 +838,7 @@ out:
        return 1;
 }
 
-int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -983,6 +1001,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        return 1;
 }
 
+/* ia64 does not need this */
+void __kprobes jprobe_return(void)
+{
+}
+
 int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 {
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();