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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to