Fix stack alignment in the kernel to be on an 8 byte boundary as required

by AAPCS.
This commit is contained in:
Andrew Turner 2013-03-06 06:19:56 +00:00
parent 833d853cbf
commit 078996e049
3 changed files with 24 additions and 3 deletions

View File

@ -211,10 +211,12 @@ ENTRY(cpu_throw)
GET_PCPU(r6) GET_PCPU(r6)
str r7, [r6, #PC_CURPCB] str r7, [r6, #PC_CURPCB]
add sp, sp, #4;
ldmfd sp!, {r4-r7, pc} ldmfd sp!, {r4-r7, pc}
ENTRY(cpu_switch) ENTRY(cpu_switch)
stmfd sp!, {r4-r7, lr} stmfd sp!, {r4-r7, lr}
sub sp, sp, #4;
mov r6, r2 /* Save the mutex */ mov r6, r2 /* Save the mutex */
.Lswitch_resume: .Lswitch_resume:
@ -488,6 +490,7 @@ ENTRY(cpu_switch)
* Pull the registers that got pushed when either savectx() or * Pull the registers that got pushed when either savectx() or
* cpu_switch() was called and return. * cpu_switch() was called and return.
*/ */
add sp, sp, #4;
ldmfd sp!, {r4-r7, pc} ldmfd sp!, {r4-r7, pc}
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
.Lswitch_bogons: .Lswitch_bogons:
@ -501,6 +504,7 @@ ENTRY(cpu_switch)
#endif #endif
ENTRY(savectx) ENTRY(savectx)
stmfd sp!, {r4-r7, lr} stmfd sp!, {r4-r7, lr}
sub sp, sp, #4
/* /*
* r0 = pcb * r0 = pcb
*/ */
@ -528,6 +532,7 @@ ENTRY(savectx)
bl _C_LABEL(vfp_store) bl _C_LABEL(vfp_store)
1: 1:
#endif /* ARM_VFP_SUPPORT */ #endif /* ARM_VFP_SUPPORT */
add sp, sp, #4;
ldmfd sp!, {r4-r7, pc} ldmfd sp!, {r4-r7, pc}
ENTRY(fork_trampoline) ENTRY(fork_trampoline)

View File

@ -73,6 +73,12 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h> #include <machine/md_var.h>
/*
* struct switchframe must be a multiple of 8 for correct stack alignment
*/
CTASSERT(sizeof(struct switchframe) == 24);
CTASSERT(sizeof(struct trapframe) == 76);
#ifndef NSFBUFS #ifndef NSFBUFS
#define NSFBUFS (512 + maxusers * 16) #define NSFBUFS (512 + maxusers * 16)
#endif #endif
@ -131,8 +137,8 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
pcb2->un_32.pcb32_sp = td2->td_kstack + pcb2->un_32.pcb32_sp = td2->td_kstack +
USPACE_SVC_STACK_TOP - sizeof(*pcb2); USPACE_SVC_STACK_TOP - sizeof(*pcb2);
pmap_activate(td2); pmap_activate(td2);
td2->td_frame = tf = td2->td_frame = tf = (struct trapframe *)STACKALIGN(
(struct trapframe *)pcb2->un_32.pcb32_sp - 1; pcb2->un_32.pcb32_sp - sizeof(struct trapframe));
*tf = *td1->td_frame; *tf = *td1->td_frame;
sf = (struct switchframe *)tf - 1; sf = (struct switchframe *)tf - 1;
sf->sf_r4 = (u_int)fork_return; sf->sf_r4 = (u_int)fork_return;
@ -142,6 +148,8 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
tf->tf_r0 = 0; tf->tf_r0 = 0;
tf->tf_r1 = 0; tf->tf_r1 = 0;
pcb2->un_32.pcb32_sp = (u_int)sf; pcb2->un_32.pcb32_sp = (u_int)sf;
KASSERT((pcb2->un_32.pcb32_sp & 7) == 0,
("cpu_fork: Incorrect stack alignment"));
/* Setup to release spin count in fork_exit(). */ /* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1; td2->td_md.md_spinlock_count = 1;
@ -345,6 +353,8 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
tf->tf_r0 = 0; tf->tf_r0 = 0;
td->td_pcb->un_32.pcb32_sp = (u_int)sf; td->td_pcb->un_32.pcb32_sp = (u_int)sf;
td->td_pcb->un_32.pcb32_und_sp = td->td_kstack + USPACE_UNDEF_STACK_TOP; td->td_pcb->un_32.pcb32_und_sp = td->td_kstack + USPACE_UNDEF_STACK_TOP;
KASSERT((td->td_pcb->un_32.pcb32_sp & 7) == 0,
("cpu_set_upcall: Incorrect stack alignment"));
/* Setup to release spin count in fork_exit(). */ /* Setup to release spin count in fork_exit(). */
td->td_md.md_spinlock_count = 1; td->td_md.md_spinlock_count = 1;
@ -438,6 +448,8 @@ cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
sf->sf_r4 = (u_int)func; sf->sf_r4 = (u_int)func;
sf->sf_r5 = (u_int)arg; sf->sf_r5 = (u_int)arg;
td->td_pcb->un_32.pcb32_sp = (u_int)sf; td->td_pcb->un_32.pcb32_sp = (u_int)sf;
KASSERT((td->td_pcb->un_32.pcb32_sp & 7) == 0,
("cpu_set_fork_handler: Incorrect stack alignment"));
} }
/* /*

View File

@ -138,10 +138,14 @@ typedef struct irqframe {
} irqframe_t; } irqframe_t;
/* /*
* Switch frame * Switch frame.
*
* It is important this is a multiple of 8 bytes so the stack is correctly
* aligned when we create new threads.
*/ */
struct switchframe { struct switchframe {
u_int pad; /* Used to pad the struct to a multiple of 8-bytes */
u_int sf_r4; u_int sf_r4;
u_int sf_r5; u_int sf_r5;
u_int sf_r6; u_int sf_r6;