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

Commit e1088430 authored by Chris Zankel's avatar Chris Zankel
Browse files

[XTENSA] Fix register corruption for certain processor configurations



For processor configurations that have optional registers
(compiler-used but non-coprocessor), user space registers
might get corrupted when there are only 4 registers in
the current window-frame, ie. register a4 belongs to the
oldest frame in the register file.

Signed-off-by: default avatarChris Zankel <chris@zankel.net>
parent 9f8fcf38
Loading
Loading
Loading
Loading
+15 −29
Original line number Original line Diff line number Diff line
@@ -395,55 +395,49 @@ common_exception_return:
	/* Jump if we are returning from kernel exceptions. */
	/* Jump if we are returning from kernel exceptions. */


1:	l32i	a3, a1, PT_PS
1:	l32i	a3, a1, PT_PS
	_bbsi.l	a3, PS_UM_BIT, 2f
	_bbci.l	a3, PS_UM_BIT, 4f
	j	kernel_exception_exit


	/* Specific to a user exception exit:
	/* Specific to a user exception exit:
	 * We need to check some flags for signal handling and rescheduling,
	 * We need to check some flags for signal handling and rescheduling,
	 * and have to restore WB and WS, extra states, and all registers
	 * and have to restore WB and WS, extra states, and all registers
	 * in the register file that were in use in the user task.
	 * in the register file that were in use in the user task.
	 */
	 * Note that we don't disable interrupts here. 

2:	wsr	a3, PS		/* disable interrupts */

	/* Check for signals (keep interrupts disabled while we read TI_FLAGS)
	 * Note: PS.INTLEVEL = 0, PS.EXCM = 1
	 */
	 */


	GET_THREAD_INFO(a2,a1)
	GET_THREAD_INFO(a2,a1)
	l32i	a4, a2, TI_FLAGS
	l32i	a4, a2, TI_FLAGS


	/* Enable interrupts again.
	 * Note: When we get here, we certainly have handled any interrupts.
	 *       (Hint: There is only one user exception frame on stack)
	 */

	movi	a3, 1 << PS_WOE_BIT

	_bbsi.l	a4, TIF_NEED_RESCHED, 3f
	_bbsi.l	a4, TIF_NEED_RESCHED, 3f
	_bbci.l	a4, TIF_SIGPENDING, 4f
	_bbci.l	a4, TIF_SIGPENDING, 4f


	l32i	a4, a1, PT_DEPC
	l32i	a4, a1, PT_DEPC
	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
	/* Reenable interrupts and call do_signal() */


	wsr	a3, PS
	/* Call do_signal() */

	movi	a4, do_signal	# int do_signal(struct pt_regs*, sigset_t*)
	movi	a4, do_signal	# int do_signal(struct pt_regs*, sigset_t*)
	mov	a6, a1
	mov	a6, a1
	movi	a7, 0
	movi	a7, 0
	callx4	a4
	callx4	a4
	j	1b
	j	1b


3:	/* Reenable interrupts and reschedule */
3:	/* Reschedule */


	wsr	a3, PS
	movi	a4, schedule	# void schedule (void)
	movi	a4, schedule	# void schedule (void)
	callx4	a4
	callx4	a4
	j	1b
	j	1b


	/* Restore the state of the task and return from the exception. */
4:	/* Restore optional registers. */

	load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT


4:	/* a2 holds GET_CURRENT(a2,a1)  */
	wsr	a3, PS		/* disable interrupts */

	_bbci.l	a3, PS_UM_BIT, kernel_exception_exit

user_exception_exit:

	/* Restore the state of the task and return from the exception. */


	/* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
	/* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */


@@ -509,10 +503,6 @@ common_exception_return:


kernel_exception_exit:
kernel_exception_exit:


	/* Disable interrupts (a3 holds PT_PS) */

	wsr	a3, PS

#ifdef PREEMPTIBLE_KERNEL
#ifdef PREEMPTIBLE_KERNEL


#ifdef CONFIG_PREEMPT
#ifdef CONFIG_PREEMPT
@@ -591,10 +581,6 @@ kernel_exception_exit:


common_exception_exit:
common_exception_exit:


	/* Restore optional registers. */

	load_xtregs_opt a1 a3 a4 a5 a6 a7 PT_XTREGS_OPT

	/* Restore address registers. */
	/* Restore address registers. */


	_bbsi.l	a2, 1, 1f
	_bbsi.l	a2, 1, 1f