Messages in this thread Patch in this message | | | From | Max Filippov <> | Subject | [PATCH v2 2/3] xtensa: support artificial division by 0 exception | Date | Fri, 13 May 2022 20:34:36 -0700 |
| |
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 <jcmvbkbc@gmail.com> --- Changes v1->v2:
- split ABI probing improvement from the artificial division by 0 - don't limit artificial division by 0 pattern detection to configurations without HW division opcodes, do it always
arch/xtensa/kernel/traps.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 24d11b44fa57..47445b2d4217 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -293,12 +293,42 @@ static void do_interrupt(struct pt_regs *regs) set_irq_regs(old_regs); } +static int check_div0(struct pt_regs *regs) +{ + u8 buf[7]; + void *p; + static const u8 pattern1[] = {0, 0, 0, 'D', 'I', 'V', '0'}; +#if defined(__XTENSA_EB__) + static const u8 pattern2[] = {0xd6, 0x0f, 'D', 'I', 'V', '0'}; +#elif defined(__XTENSA_EL__) + static const u8 pattern2[] = {0x6d, 0xf0, 'D', 'I', 'V', '0'}; +#else +#error Unsupported Xtensa endianness +#endif + + if (user_mode(regs)) { + if (copy_from_user(buf, (void __user *)regs->pc, 7)) + return 0; + p = buf; + } else { + p = (void *)regs->pc; + } + + return memcmp(p, pattern1, sizeof(pattern1)) == 0 || + memcmp(p, pattern2, sizeof(pattern2)) == 0; +} + /* * Illegal instruction. Fatal if in kernel space. */ static void do_illegal_instruction(struct pt_regs *regs) { + if (check_div0(regs)) { + do_div0(regs); + return; + } + __die_if_kernel("Illegal instruction in kernel", regs, SIGKILL); /* If in user mode, send SIGILL signal to current process. */ -- 2.30.2
| |