1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-23 11:18:54 +00:00

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.
This commit is contained in:
Andrew Turner 2013-08-05 19:06:28 +00:00
parent 8239a7a878
commit d8e3f572e2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253968
3 changed files with 17 additions and 6 deletions

View File

@ -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)

View File

@ -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 */ \

View File

@ -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 */