Skip to content

Commit d748620

Browse files
committed
xtensa: support artificial division by 0 exception
On xtensa cores wihout hardware division option division support functions from libgcc react to division by 0 attempt by executing illegal instruction followed by the characters 'DIV0'. Recognize this pattern in illegal instruction exception handler and convert it to division by 0. Signed-off-by: Max Filippov <[email protected]>
1 parent 408b1d3 commit d748620

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

arch/xtensa/kernel/traps.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,35 @@ static void do_interrupt(struct pt_regs *regs)
293293
set_irq_regs(old_regs);
294294
}
295295

296+
static bool check_div0(struct pt_regs *regs)
297+
{
298+
static const u8 pattern[] = {'D', 'I', 'V', '0'};
299+
const u8 *p;
300+
u8 buf[5];
301+
302+
if (user_mode(regs)) {
303+
if (copy_from_user(buf, (void __user *)regs->pc + 2, 5))
304+
return 0;
305+
p = buf;
306+
} else {
307+
p = (const u8 *)regs->pc + 2;
308+
}
309+
310+
return memcmp(p, pattern, sizeof(pattern)) == 0 ||
311+
memcmp(p + 1, pattern, sizeof(pattern)) == 0;
312+
}
313+
296314
/*
297315
* Illegal instruction. Fatal if in kernel space.
298316
*/
299317

300318
static void do_illegal_instruction(struct pt_regs *regs)
301319
{
320+
if (check_div0(regs)) {
321+
do_div0(regs);
322+
return;
323+
}
324+
302325
__die_if_kernel("Illegal instruction in kernel", regs, SIGKILL);
303326

304327
/* If in user mode, send SIGILL signal to current process. */

0 commit comments

Comments
 (0)