Commit a160e941 authored by Max Filippov's avatar Max Filippov
Browse files

xtensa: fix unaligned and load/store configuration interaction



Unaligned exception handler is needed in configurations with hardware
support for unaligned access when the load/store exception handler is
enabled because such configurations would still raise an exception on
unaligned access through the instruction bus.

Fixes: f29cf776 ("xtensa: add load/store exception handler")
Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent bc8d5916
Loading
Loading
Loading
Loading
+14 −20
Original line number Original line Diff line number Diff line
/*
/*
 * arch/xtensa/kernel/align.S
 * arch/xtensa/kernel/align.S
 *
 *
 * Handle unalignment exceptions in kernel space.
 * Handle unalignment and load/store exceptions.
 *
 *
 * This file is subject to the terms and conditions of the GNU General
 * This file is subject to the terms and conditions of the GNU General
 * Public License.  See the file "COPYING" in the main directory of
 * Public License.  See the file "COPYING" in the main directory of
@@ -26,20 +26,18 @@
#define LOAD_EXCEPTION_HANDLER
#define LOAD_EXCEPTION_HANDLER
#endif
#endif


#if XCHAL_UNALIGNED_STORE_EXCEPTION || defined LOAD_EXCEPTION_HANDLER
#if XCHAL_UNALIGNED_STORE_EXCEPTION || defined CONFIG_XTENSA_LOAD_STORE
#define STORE_EXCEPTION_HANDLER
#endif

#if defined LOAD_EXCEPTION_HANDLER || defined STORE_EXCEPTION_HANDLER
#define ANY_EXCEPTION_HANDLER
#define ANY_EXCEPTION_HANDLER
#endif
#endif


#if XCHAL_HAVE_WINDOWED
#if XCHAL_HAVE_WINDOWED && defined CONFIG_MMU
#define UNALIGNED_USER_EXCEPTION
#define UNALIGNED_USER_EXCEPTION
#endif
#endif


/*  First-level exception handler for unaligned exceptions.
 *
 *  Note: This handler works only for kernel exceptions.  Unaligned user
 *        access should get a seg fault.
 */

/* Big and little endian 16-bit values are located in
/* Big and little endian 16-bit values are located in
 * different halves of a register.  HWORD_START helps to
 * different halves of a register.  HWORD_START helps to
 * abstract the notion of extracting a 16-bit value from a
 * abstract the notion of extracting a 16-bit value from a
@@ -228,8 +226,6 @@ ENDPROC(fast_load_store)
#ifdef ANY_EXCEPTION_HANDLER
#ifdef ANY_EXCEPTION_HANDLER
ENTRY(fast_unaligned)
ENTRY(fast_unaligned)


#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION

	call0	.Lsave_and_load_instruction
	call0	.Lsave_and_load_instruction


	/* Analyze the instruction (load or store?). */
	/* Analyze the instruction (load or store?). */
@@ -244,8 +240,7 @@ ENTRY(fast_unaligned)
	/* 'store indicator bit' not set, jump */
	/* 'store indicator bit' not set, jump */
	_bbci.l	a4, OP1_SI_BIT + INSN_OP1, .Lload
	_bbci.l	a4, OP1_SI_BIT + INSN_OP1, .Lload


#endif
#ifdef STORE_EXCEPTION_HANDLER
#if XCHAL_UNALIGNED_STORE_EXCEPTION


	/* Store: Jump to table entry to get the value in the source register.*/
	/* Store: Jump to table entry to get the value in the source register.*/


@@ -254,7 +249,7 @@ ENTRY(fast_unaligned)
	addx8	a5, a6, a5
	addx8	a5, a6, a5
	jx	a5			# jump into table
	jx	a5			# jump into table
#endif
#endif
#if XCHAL_UNALIGNED_LOAD_EXCEPTION
#ifdef LOAD_EXCEPTION_HANDLER


	/* Load: Load memory address. */
	/* Load: Load memory address. */


@@ -328,7 +323,7 @@ ENTRY(fast_unaligned)
	mov	a14, a3		;	_j .Lexit;	.align 8
	mov	a14, a3		;	_j .Lexit;	.align 8
	mov	a15, a3		;	_j .Lexit;	.align 8
	mov	a15, a3		;	_j .Lexit;	.align 8
#endif
#endif
#if XCHAL_UNALIGNED_STORE_EXCEPTION
#ifdef STORE_EXCEPTION_HANDLER
.Lstore_table:
.Lstore_table:
	l32i	a3, a2, PT_AREG0;	_j .Lstore_w;	.align 8
	l32i	a3, a2, PT_AREG0;	_j .Lstore_w;	.align 8
	mov	a3, a1;			_j .Lstore_w;	.align 8	# fishy??
	mov	a3, a1;			_j .Lstore_w;	.align 8	# fishy??
@@ -348,7 +343,6 @@ ENTRY(fast_unaligned)
	mov	a3, a15		;	_j .Lstore_w;	.align 8
	mov	a3, a15		;	_j .Lstore_w;	.align 8
#endif
#endif


#ifdef ANY_EXCEPTION_HANDLER
	/* We cannot handle this exception. */
	/* We cannot handle this exception. */


	.extern _kernel_exception
	.extern _kernel_exception
@@ -377,8 +371,8 @@ ENTRY(fast_unaligned)


2:	movi	a0, _user_exception
2:	movi	a0, _user_exception
	jx	a0
	jx	a0
#endif

#if XCHAL_UNALIGNED_STORE_EXCEPTION
#ifdef STORE_EXCEPTION_HANDLER


	# a7: instruction pointer, a4: instruction, a3: value
	# a7: instruction pointer, a4: instruction, a3: value
.Lstore_w:
.Lstore_w:
@@ -444,7 +438,7 @@ ENTRY(fast_unaligned)
	s32i	a6, a4, 4
	s32i	a6, a4, 4
#endif
#endif
#endif
#endif
#ifdef ANY_EXCEPTION_HANDLER

.Lexit:
.Lexit:
#if XCHAL_HAVE_LOOPS
#if XCHAL_HAVE_LOOPS
	rsr	a4, lend		# check if we reached LEND
	rsr	a4, lend		# check if we reached LEND
@@ -539,7 +533,7 @@ ENTRY(fast_unaligned)
	__src_b	a4, a4, a5	# a4 has the instruction
	__src_b	a4, a4, a5	# a4 has the instruction


	ret
	ret
#endif

ENDPROC(fast_unaligned)
ENDPROC(fast_unaligned)


ENTRY(fast_unaligned_fixup)
ENTRY(fast_unaligned_fixup)
+2 −1
Original line number Original line Diff line number Diff line
@@ -102,7 +102,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
#endif
#endif
{ EXCCAUSE_INTEGER_DIVIDE_BY_ZERO, 0,	   do_div0 },
{ EXCCAUSE_INTEGER_DIVIDE_BY_ZERO, 0,	   do_div0 },
/* EXCCAUSE_PRIVILEGED unhandled */
/* EXCCAUSE_PRIVILEGED unhandled */
#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION || \
		IS_ENABLED(CONFIG_XTENSA_LOAD_STORE)
#ifdef CONFIG_XTENSA_UNALIGNED_USER
#ifdef CONFIG_XTENSA_UNALIGNED_USER
{ EXCCAUSE_UNALIGNED,		USER,	   fast_unaligned },
{ EXCCAUSE_UNALIGNED,		USER,	   fast_unaligned },
#endif
#endif