aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorKeith Owens <kaos@sgi.com>2005-05-28 02:09:00 -0400
committerTony Luck <tony.luck@intel.com>2005-06-08 15:25:24 -0400
commit70aa488cff83c965c9e1850f48d82b000d0d6c1c (patch)
tree9236fa880fe3fab2ee3cf2bcb0ec4a4e19ded3c5 /arch
parent86ebacd360767f6a5cf9c8810977593dccf3f3da (diff)
[IA64] Extract correct break number for break.b
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>
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/kernel/traps.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index e82ad78081b3..9bad6652d531 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -111,6 +111,24 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
111 siginfo_t siginfo; 111 siginfo_t siginfo;
112 int sig, code; 112 int sig, code;
113 113
114 /* break.b always sets cr.iim to 0, which causes problems for
115 * debuggers. Get the real break number from the original instruction,
116 * but only for kernel code. User space break.b is left alone, to
117 * preserve the existing behaviour. All break codings have the same
118 * format, so there is no need to check the slot type.
119 */
120 if (break_num == 0 && !user_mode(regs)) {
121 struct ia64_psr *ipsr = ia64_psr(regs);
122 unsigned long *bundle = (unsigned long *)regs->cr_iip;
123 unsigned long slot;
124 switch (ipsr->ri) {
125 case 0: slot = (bundle[0] >> 5); break;
126 case 1: slot = (bundle[0] >> 46) | (bundle[1] << 18); break;
127 default: slot = (bundle[1] >> 23); break;
128 }
129 break_num = ((slot >> 36 & 1) << 20) | (slot >> 6 & 0xfffff);
130 }
131
114 /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ 132 /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
115 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); 133 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
116 siginfo.si_imm = break_num; 134 siginfo.si_imm = break_num;