]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
xtensa: don't allow overflow/underflow on unaligned stack
authorMax Filippov <jcmvbkbc@gmail.com>
Wed, 6 Aug 2014 21:03:01 +0000 (01:03 +0400)
committerMax Filippov <jcmvbkbc@gmail.com>
Thu, 14 Aug 2014 07:59:32 +0000 (11:59 +0400)
Double exceptions that happen during register window overflow/underflow
are handled in the topmost stack frame, as if it was the only exception
that occured. However unaligned access exception handler is special
because it needs to analyze instruction that caused the exception, but
the userspace instruction that triggered window exception is completely
irrelevant. Unaligned data access is rather normal in the generic
userspace code, but stack pointer manipulation must always be done by
architecture-aware code and thus unaligned stack means a serious problem
anyway.
Use the default unaligned access handler that raises SIGBUS in case
of unaligned access in window overflow/underflow handler.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
arch/xtensa/kernel/traps.c
arch/xtensa/kernel/vectors.S
arch/xtensa/kernel/vmlinux.lds.S

index eebbfd8c26fc25121bced6cb18c074a55c6cb5f5..9d2f45f010ef7e9448e3837e873b617f0a493b23 100644 (file)
@@ -101,9 +101,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
 #ifdef CONFIG_XTENSA_UNALIGNED_USER
 { EXCCAUSE_UNALIGNED,          USER,      fast_unaligned },
-#else
-{ EXCCAUSE_UNALIGNED,          0,         do_unaligned_user },
 #endif
+{ EXCCAUSE_UNALIGNED,          0,         do_unaligned_user },
 { EXCCAUSE_UNALIGNED,          KRNL,      fast_unaligned },
 #endif
 #ifdef CONFIG_MMU
@@ -264,7 +263,6 @@ do_illegal_instruction(struct pt_regs *regs)
  */
 
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-#ifndef CONFIG_XTENSA_UNALIGNED_USER
 void
 do_unaligned_user (struct pt_regs *regs)
 {
@@ -286,7 +284,6 @@ do_unaligned_user (struct pt_regs *regs)
 
 }
 #endif
-#endif
 
 void
 do_debug(struct pt_regs *regs)
index 8453e6e398951b0d1864b6e570c8d7d63e45d356..1b397a902292f8224f27856f6ff14471fad1e6ff 100644 (file)
@@ -454,8 +454,14 @@ _DoubleExceptionVector_WindowOverflow:
        s32i    a0, a2, PT_DEPC
 
 _DoubleExceptionVector_handle_exception:
+       addi    a0, a0, -EXCCAUSE_UNALIGNED
+       beqz    a0, 2f
        addx4   a0, a0, a3
-       l32i    a0, a0, EXC_TABLE_FAST_USER
+       l32i    a0, a0, EXC_TABLE_FAST_USER + 4 * EXCCAUSE_UNALIGNED
+       xsr     a3, excsave1
+       jx      a0
+2:
+       movi    a0, user_exception
        xsr     a3, excsave1
        jx      a0
 
index d16db6df86f8e3d823ac2f189816d9889249323e..fc1bc2ba8d5deb34348e783d82f6e0a0b919828a 100644 (file)
@@ -269,13 +269,13 @@ SECTIONS
                  .UserExceptionVector.literal)
   SECTION_VECTOR (_DoubleExceptionVector_literal,
                  .DoubleExceptionVector.literal,
-                 DOUBLEEXC_VECTOR_VADDR - 40,
+                 DOUBLEEXC_VECTOR_VADDR - 48,
                  SIZEOF(.UserExceptionVector.text),
                  .UserExceptionVector.text)
   SECTION_VECTOR (_DoubleExceptionVector_text,
                  .DoubleExceptionVector.text,
                  DOUBLEEXC_VECTOR_VADDR,
-                 40,
+                 48,
                  .DoubleExceptionVector.literal)
 
   . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;