[ARM] 3102/1: ARM EABI: stack pointer must be 64-bit aligned after a CPU exception
authorNicolas Pitre <nico@cam.org>
Sat, 14 Jan 2006 16:18:08 +0000 (16:18 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 14 Jan 2006 16:18:08 +0000 (16:18 +0000)
Patch from Nicolas Pitre

The ARM EABI says that the stack pointer has to be 64-bit aligned for
reasons already mentioned in patch #3101 when calling C functions.

We therefore must verify and adjust sp accordingly when taking an
exception from kernel mode since sp might not necessarily be 64-bit
aligned if the exception occurs in the middle of a kernel function.

If the exception occurs while in user mode then no sp fixup is needed as
long as sizeof(struct pt_regs) as well as any additional syscall data
stack space remain multiples of 8.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-header.S
include/asm-arm/ptrace.h

index fb8e7f4c4b37f9364c0789704f6a3357dbebaea6..874e6bb7940578fd86878e69ae9ddc7b91eee03f 100644 (file)
@@ -105,14 +105,24 @@ common_invalid:
 /*
  * SVC mode handlers
  */
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
+#define SPFIX(code...) code
+#else
+#define SPFIX(code...)
+#endif
+
        .macro  svc_entry
        sub     sp, sp, #S_FRAME_SIZE
+ SPFIX(        tst     sp, #4          )
+ SPFIX(        bicne   sp, sp, #4      )
        stmib   sp, {r1 - r12}
 
        ldmia   r0, {r1 - r3}
        add     r5, sp, #S_SP           @ here for interlock avoidance
        mov     r4, #-1                 @  ""  ""      ""       ""
        add     r0, sp, #S_FRAME_SIZE   @  ""  ""      ""       ""
+ SPFIX(        addne   r0, r0, #4      )
        str     r1, [sp]                @ save the "real" r0 copied
                                        @ from the exception stack
 
@@ -303,7 +313,14 @@ __pabt_svc:
 
 /*
  * User mode handlers
+ *
+ * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
  */
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
+#error "sizeof(struct pt_regs) must be a multiple of 8"
+#endif
+
        .macro  usr_entry
        sub     sp, sp, #S_FRAME_SIZE
        stmib   sp, {r1 - r12}
index 648cfff93138bdc1df9e025efef31dbc1211a821..55c99cdab7d64f430f1e3063343111cfdf9dfce9 100644 (file)
@@ -19,6 +19,7 @@
 @
 @ Most of the stack format comes from struct pt_regs, but with
 @ the addition of 8 bytes for storing syscall args 5 and 6.
+@ This _must_ remain a multiple of 8 for EABI.
 @
 #define S_OFF          8
 
index 4377e22b7e1a9a7359d1e6255e4098b1227e7aa2..f40948d54448b7e4aa4f38bf1c1de697875369bf 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call.  Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
 struct pt_regs {
        long uregs[18];
 };