All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] xtensa: add division by zero exception handler
@ 2022-05-14  3:34 Max Filippov
  2022-05-14  3:34 ` [PATCH v2 1/3] xtensa: add trap handler for division by zero Max Filippov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Max Filippov @ 2022-05-14  3:34 UTC (permalink / raw)
  To: linux-xtensa; +Cc: Chris Zankel, linux-kernel, Max Filippov

Hello,

this series adds handlers for hardware and artificial division by zero
exceptions and improves call0 ABI probing in the presence of unrelated
illegal instructions.

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

Max Filippov (3):
  xtensa: add trap handler for division by zero
  xtensa: support artificial division by 0 exception
  xtensa: improve call0 ABI probing

 arch/xtensa/include/asm/thread_info.h |  4 +++
 arch/xtensa/kernel/asm-offsets.c      |  3 ++
 arch/xtensa/kernel/entry.S            |  5 +++
 arch/xtensa/kernel/traps.c            | 50 ++++++++++++++++++++++++++-
 4 files changed, 61 insertions(+), 1 deletion(-)

-- 
2.30.2


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/3] xtensa: add trap handler for division by zero
  2022-05-14  3:34 [PATCH v2 0/3] xtensa: add division by zero exception handler Max Filippov
@ 2022-05-14  3:34 ` Max Filippov
  2022-05-14  3:34 ` [PATCH v2 2/3] xtensa: support artificial division by 0 exception Max Filippov
  2022-05-14  3:34 ` [PATCH v2 3/3] xtensa: improve call0 ABI probing Max Filippov
  2 siblings, 0 replies; 4+ messages in thread
From: Max Filippov @ 2022-05-14  3:34 UTC (permalink / raw)
  To: linux-xtensa; +Cc: Chris Zankel, linux-kernel, Max Filippov

Add c-level handler for the division by zero exception and kill the task
if it was thrown from the kernel space or send SIGFPE otherwise.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 arch/xtensa/kernel/traps.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 138a86fbe9d7..24d11b44fa57 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -49,6 +49,7 @@
  */
 
 static void do_illegal_instruction(struct pt_regs *regs);
+static void do_div0(struct pt_regs *regs);
 static void do_interrupt(struct pt_regs *regs);
 #if XTENSA_FAKE_NMI
 static void do_nmi(struct pt_regs *regs);
@@ -95,7 +96,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
 #ifdef SUPPORT_WINDOWED
 { EXCCAUSE_ALLOCA,		USER|KRNL, fast_alloca },
 #endif
-/* EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
+{ EXCCAUSE_INTEGER_DIVIDE_BY_ZERO, 0,	   do_div0 },
 /* EXCCAUSE_PRIVILEGED unhandled */
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
 #ifdef CONFIG_XTENSA_UNALIGNED_USER
@@ -307,6 +308,11 @@ static void do_illegal_instruction(struct pt_regs *regs)
 	force_sig(SIGILL);
 }
 
+static void do_div0(struct pt_regs *regs)
+{
+	__die_if_kernel("Unhandled division by 0 in kernel", regs, SIGKILL);
+	force_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)regs->pc);
+}
 
 /*
  * Handle unaligned memory accesses from user space. Kill task.
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/3] xtensa: support artificial division by 0 exception
  2022-05-14  3:34 [PATCH v2 0/3] xtensa: add division by zero exception handler Max Filippov
  2022-05-14  3:34 ` [PATCH v2 1/3] xtensa: add trap handler for division by zero Max Filippov
@ 2022-05-14  3:34 ` Max Filippov
  2022-05-14  3:34 ` [PATCH v2 3/3] xtensa: improve call0 ABI probing Max Filippov
  2 siblings, 0 replies; 4+ messages in thread
From: Max Filippov @ 2022-05-14  3:34 UTC (permalink / raw)
  To: linux-xtensa; +Cc: Chris Zankel, linux-kernel, Max Filippov

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


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 3/3] xtensa: improve call0 ABI probing
  2022-05-14  3:34 [PATCH v2 0/3] xtensa: add division by zero exception handler Max Filippov
  2022-05-14  3:34 ` [PATCH v2 1/3] xtensa: add trap handler for division by zero Max Filippov
  2022-05-14  3:34 ` [PATCH v2 2/3] xtensa: support artificial division by 0 exception Max Filippov
@ 2022-05-14  3:34 ` Max Filippov
  2 siblings, 0 replies; 4+ messages in thread
From: Max Filippov @ 2022-05-14  3:34 UTC (permalink / raw)
  To: linux-xtensa; +Cc: Chris Zankel, linux-kernel, Max Filippov

When call0 userspace ABI support by probing is enabled instructions that
cause illegal instruction exception when PS.WOE is clear are retried
with PS.WOE set before calling c-level exception handler. Record user pc
at which PS.WOE was set in the fast exception handler and clear PS.WOE
in the c-level exception handler if we get there from the same address.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
Changes v1->v2:

- split ABI probing improvement from the artificial division by 0

 arch/xtensa/include/asm/thread_info.h |  4 ++++
 arch/xtensa/kernel/asm-offsets.c      |  3 +++
 arch/xtensa/kernel/entry.S            |  5 +++++
 arch/xtensa/kernel/traps.c            | 12 ++++++++++++
 4 files changed, 24 insertions(+)

diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h
index 52974317a6b6..326db1c1d5d8 100644
--- a/arch/xtensa/include/asm/thread_info.h
+++ b/arch/xtensa/include/asm/thread_info.h
@@ -56,6 +56,10 @@ struct thread_info {
 	/* result of the most recent exclusive store */
 	unsigned long		atomctl8;
 #endif
+#ifdef CONFIG_USER_ABI_CALL0_PROBE
+	/* Address where PS.WOE was enabled by the ABI probing code */
+	unsigned long		ps_woe_fix_addr;
+#endif
 
 	/*
 	 * If i-th bit is set then coprocessor state is loaded into the
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 9a1db6ffcbf4..da38de20ae59 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -88,6 +88,9 @@ int main(void)
 	OFFSET(TI_STSTUS, thread_info, status);
 	OFFSET(TI_CPU, thread_info, cpu);
 	OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
+#ifdef CONFIG_USER_ABI_CALL0_PROBE
+	OFFSET(TI_PS_WOE_FIX_ADDR, thread_info, ps_woe_fix_addr);
+#endif
 
 	/* struct thread_info (offset from start_struct) */
 	DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 3224b4ceca34..e3eae648ba2e 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1056,6 +1056,11 @@ ENTRY(fast_illegal_instruction_user)
 	movi	a3, PS_WOE_MASK
 	or	a0, a0, a3
 	wsr	a0, ps
+#ifdef CONFIG_USER_ABI_CALL0_PROBE
+	GET_THREAD_INFO(a3, a2)
+	rsr	a0, epc1
+	s32i	a0, a3, TI_PS_WOE_FIX_ADDR
+#endif
 	l32i	a3, a2, PT_AREG3
 	l32i	a0, a2, PT_AREG0
 	rsr	a2, depc
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 47445b2d4217..21c2c30baf69 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -324,6 +324,18 @@ static int check_div0(struct pt_regs *regs)
 
 static void do_illegal_instruction(struct pt_regs *regs)
 {
+#ifdef CONFIG_USER_ABI_CALL0_PROBE
+	/*
+	 * When call0 application encounters an illegal instruction fast
+	 * exception handler will attempt to set PS.WOE and retry failing
+	 * instruction.
+	 * If we get here we know that that instruction is also illegal
+	 * with PS.WOE set, so it's not related to the windowed option
+	 * hence PS.WOE may be cleared.
+	 */
+	if (regs->pc == current_thread_info()->ps_woe_fix_addr)
+		regs->ps &= ~PS_WOE_MASK;
+#endif
 	if (check_div0(regs)) {
 		do_div0(regs);
 		return;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-05-14  3:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-14  3:34 [PATCH v2 0/3] xtensa: add division by zero exception handler Max Filippov
2022-05-14  3:34 ` [PATCH v2 1/3] xtensa: add trap handler for division by zero Max Filippov
2022-05-14  3:34 ` [PATCH v2 2/3] xtensa: support artificial division by 0 exception Max Filippov
2022-05-14  3:34 ` [PATCH v2 3/3] xtensa: improve call0 ABI probing Max Filippov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.