[IA64] Remove getting break_num by decoding instruction
authorKeshavamurthy Anil S <anil.s.keshavamurthy@intel.com>
Tue, 22 Nov 2005 22:15:49 +0000 (14:15 -0800)
committerTony Luck <tony.luck@intel.com>
Tue, 29 Nov 2005 17:24:39 +0000 (09:24 -0800)
break.b always sets cr.iim to 0 and the current code tries to
get the break_num by decoding instruction. However, their
seems to be a race condition while reading the regs->cr_iip,
as on other cpu the break.b at regs->cr_iip might have been
replaced with the original instruction as a result of
unregister_kprobe() and hence decoding instruction to
obtain break_num will result in wrong value in this case.

Also includes changes to kprobes.c which now has to handle
break number zero.

Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
arch/ia64/kernel/kprobes.c
arch/ia64/kernel/traps.c

index 801eeaeaf3de6c760905361ec61b9ad7eb8ebaf5..2895d6e6062f72df56f7f064fe8057077496c9d1 100644 (file)
@@ -740,7 +740,7 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
        switch(val) {
        case DIE_BREAK:
                /* err is break number from ia64_bad_break() */
-               if (args->err == 0x80200 || args->err == 0x80300)
+               if (args->err == 0x80200 || args->err == 0x80300 || args->err == 0)
                        if (pre_kprobes_handler(args))
                                ret = NOTIFY_STOP;
                break;
index fba5fdd1f9689351dda3adf028e864ff8c05c0bf..d3e0ecb56d627c0a0514f9bfdefefd1467df0a59 100644 (file)
@@ -132,24 +132,6 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
        siginfo_t siginfo;
        int sig, code;
 
-       /* break.b always sets cr.iim to 0, which causes problems for
-        * debuggers.  Get the real break number from the original instruction,
-        * but only for kernel code.  User space break.b is left alone, to
-        * preserve the existing behaviour.  All break codings have the same
-        * format, so there is no need to check the slot type.
-        */
-       if (break_num == 0 && !user_mode(regs)) {
-               struct ia64_psr *ipsr = ia64_psr(regs);
-               unsigned long *bundle = (unsigned long *)regs->cr_iip;
-               unsigned long slot;
-               switch (ipsr->ri) {
-                     case 0:  slot = (bundle[0] >>  5); break;
-                     case 1:  slot = (bundle[0] >> 46) | (bundle[1] << 18); break;
-                     default: slot = (bundle[1] >> 23); break;
-               }
-               break_num = ((slot >> 36 & 1) << 20) | (slot >> 6 & 0xfffff);
-       }
-
        /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
        siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
        siginfo.si_imm = break_num;