Date: Mon, 5 Aug 2013 19:06:28 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r253968 - in head/sys/arm: arm include Message-ID: <201308051906.r75J6Snq094540@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: andrew Date: Mon Aug 5 19:06:28 2013 New Revision: 253968 URL: http://svnweb.freebsd.org/changeset/base/253968 Log: When entering exception handlers we may not have an aligned stack. This is because an exception may happen at any time. The stack alignment rules on ARM EABI state the only place the stack must be 8-byte aligned is on a function boundary. If an exception happens while a function is setting up or tearing down it's stack frame it may not be correctly aligned. There is also no requirement for it to be when the function is a leaf node. The fix is to align the stack after we have stored a backup of the old stack pointer, but before we have stored anything in the trapframe. Along with this we need to adjust the size of the trapframe by 4 bytes to ensure the stack below it is also correctly aligned. Modified: head/sys/arm/arm/vm_machdep.c head/sys/arm/include/asmacros.h head/sys/arm/include/frame.h Modified: head/sys/arm/arm/vm_machdep.c ============================================================================== --- head/sys/arm/arm/vm_machdep.c Mon Aug 5 18:53:59 2013 (r253967) +++ head/sys/arm/arm/vm_machdep.c Mon Aug 5 19:06:28 2013 (r253968) @@ -74,10 +74,11 @@ __FBSDID("$FreeBSD$"); #include <machine/md_var.h> /* - * struct switchframe must be a multiple of 8 for correct stack alignment + * struct switchframe and trapframe must both be a multiple of 8 + * for correct stack alignment. */ CTASSERT(sizeof(struct switchframe) == 24); -CTASSERT(sizeof(struct trapframe) == 76); +CTASSERT(sizeof(struct trapframe) == 80); #ifndef NSFBUFS #define NSFBUFS (512 + maxusers * 16) Modified: head/sys/arm/include/asmacros.h ============================================================================== --- head/sys/arm/include/asmacros.h Mon Aug 5 18:53:59 2013 (r253967) +++ head/sys/arm/include/asmacros.h Mon Aug 5 19:06:28 2013 (r253968) @@ -63,6 +63,7 @@ */ #ifdef ARM_TP_ADDRESS #define PUSHFRAME \ + sub sp, sp, #4; /* Align the stack */ \ str lr, [sp, #-4]!; /* Push the return address */ \ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ @@ -78,6 +79,7 @@ str r1, [r0, #4]; #else #define PUSHFRAME \ + sub sp, sp, #4; /* Align the stack */ \ str lr, [sp, #-4]!; /* Push the return address */ \ sub sp, sp, #(4*17); /* Adjust the stack pointer */ \ stmia sp, {r0-r12}; /* Push the user mode registers */ \ @@ -100,7 +102,8 @@ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*17); /* Adjust the stack pointer */ \ - ldr lr, [sp], #0x0004; /* Pull the return address */ + ldr lr, [sp], #0x0004; /* Pull the return address */ \ + add sp, sp, #4 /* Align the stack */ #else #define PULLFRAME \ ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ @@ -109,7 +112,8 @@ ldmia sp, {r0-r14}^; /* Restore registers (usr mode) */ \ mov r0, r0; /* NOP for previous instruction */ \ add sp, sp, #(4*17); /* Adjust the stack pointer */ \ - ldr lr, [sp], #0x0004; /* Pull the return address */ + ldr lr, [sp], #0x0004; /* Pull the return address */ \ + add sp, sp, #4 /* Align the stack */ #endif /* @@ -133,6 +137,8 @@ orr r2, r2, #(PSR_SVC32_MODE); \ msr cpsr_c, r2; /* Punch into SVC mode */ \ mov r2, sp; /* Save SVC sp */ \ + bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ + sub sp, sp, #4; /* Pad trapframe to keep alignment */ \ str r0, [sp, #-4]!; /* Push return address */ \ str lr, [sp, #-4]!; /* Push SVC lr */ \ str r2, [sp, #-4]!; /* Push SVC sp */ \ @@ -168,6 +174,8 @@ orr r2, r2, #(PSR_SVC32_MODE); \ msr cpsr_c, r2; /* Punch into SVC mode */ \ mov r2, sp; /* Save SVC sp */ \ + bic sp, sp, #7; /* Align sp to an 8-byte addrress */ \ + sub sp, sp, #4; /* Pad trapframe to keep alignment */ \ str r0, [sp, #-4]!; /* Push return address */ \ str lr, [sp, #-4]!; /* Push SVC lr */ \ str r2, [sp, #-4]!; /* Push SVC sp */ \ @@ -209,6 +217,7 @@ #endif #if defined(__ARM_EABI__) #define UNWINDSVCFRAME \ + .pad #(4); /* Skip stack alignment */ \ .save {r13-r15}; /* Restore sp, lr, pc */ \ .pad #(2*4); /* Skip user sp and lr */ \ .save {r0-r12}; /* Restore r0-r12 */ \ Modified: head/sys/arm/include/frame.h ============================================================================== --- head/sys/arm/include/frame.h Mon Aug 5 18:53:59 2013 (r253967) +++ head/sys/arm/include/frame.h Mon Aug 5 19:06:28 2013 (r253968) @@ -62,7 +62,7 @@ typedef struct trapframe { register_t tf_spsr; /* Zero on arm26 */ register_t tf_r0; - register_t tf_r1; + register_t tf_r1; register_t tf_r2; register_t tf_r3; register_t tf_r4; @@ -78,7 +78,8 @@ typedef struct trapframe { register_t tf_usr_lr; register_t tf_svc_sp; /* Not used on arm26 */ register_t tf_svc_lr; /* Not used on arm26 */ - register_t tf_pc; + register_t tf_pc; + register_t tf_pad; } trapframe_t; /* Register numbers */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308051906.r75J6Snq094540>