Skip site navigation (1)Skip section navigation (2)
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>