Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70aa488c authored by Keith Owens's avatar Keith Owens Committed by Tony Luck
Browse files

[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: default avatarKeith Owens <kaos@sgi.com>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
parent 86ebacd3
Loading
Loading
Loading
Loading
+18 −0
Original line number Original line Diff line number Diff line
@@ -111,6 +111,24 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
	siginfo_t siginfo;
	siginfo_t siginfo;
	int sig, code;
	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: */
	/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
	siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
	siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
	siginfo.si_imm = break_num;
	siginfo.si_imm = break_num;