From: Nicolas Pitre Date: Sat, 14 Jan 2006 16:18:08 +0000 (+0000) Subject: [ARM] 3102/1: ARM EABI: stack pointer must be 64-bit aligned after a CPU exception X-Git-Tag: v2.6.16-rc1~107^2~11 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2dede2d8e925f4c2cb4e136b14df127685e15dd3;p=linux-2.6 [ARM] 3102/1: ARM EABI: stack pointer must be 64-bit aligned after a CPU exception 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 Signed-off-by: Russell King --- diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index fb8e7f4c4b..874e6bb794 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -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} diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 648cfff931..55c99cdab7 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -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 diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index 4377e22b7e..f40948d544 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -60,9 +60,11 @@ #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]; };