Commit a160e941 authored by Max Filippov's avatar Max Filippov

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
/* /*
* 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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
......
...@@ -102,7 +102,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment