Skip to content

Commit

Permalink
[IA64] Extract correct break number for break.b
Browse files Browse the repository at this point in the history
break.b does not store the break number in cr.iim, instead it stores 0,
which makes all break.b instructions look like BUG().  Extract the
break number from the instruction itself.

Signed-off-by: Keith Owens <kaos@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
  • Loading branch information
Keith Owens authored and Tony Luck committed Jun 8, 2005
1 parent 86ebacd commit 70aa488
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions arch/ia64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,24 @@ 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;
Expand Down

0 comments on commit 70aa488

Please sign in to comment.