Commit 5cc5f19f authored by Max Filippov's avatar Max Filippov
Browse files

xtensa: improve call0 ABI probing



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: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent d7486200
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -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));
+5 −0
Original line number Diff line number Diff line
@@ -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
+12 −0
Original line number Diff line number Diff line
@@ -317,6 +317,18 @@ static bool 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;