x86_64: fixes initial stack alignment
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 11 Jul 2013 23:11:54 +0000 (16:11 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 11 Jul 2013 23:11:54 +0000 (16:11 -0700)
Stacks at function entry points need to be 8 bytes off from 16 byte alignment.
This 16-byte aligns stack-based input args, and also the compiler can get a 16
byte aligned stack by subtracting (or adding) 8 to %rsp, for use in xmm
instructions (like movaps).

kern/arch/x86/process64.c
user/parlib/include/x86/vcore64.h

index fd2179d..9bff07e 100644 (file)
@@ -81,7 +81,12 @@ void proc_init_ctx(struct user_context *ctx, uint32_t vcoreid, uintptr_t entryp,
         * The low 2 bits of each segment register contains the
         * Requestor Privilege Level (RPL); 3 means user mode. */
        tf->tf_ss = GD_UD | 3;
-       tf->tf_rsp = stack_top-64;
+       /* Stack pointers in a fresh stackframe need to be such that adding or
+        * subtracting 8 will result in 16 byte alignment (AMD64 ABI).  The reason
+        * is so that input arguments (on the stack) are 16 byte aligned.  The
+        * extra 8 bytes is the retaddr, pushed on the stack.  Compilers know they
+        * can subtract 8 to get 16 byte alignment for instructions like movaps. */
+       tf->tf_rsp = ROUNDDOWN(stack_top, 16) - 8;
        tf->tf_cs = GD_UT | 3;
        /* set the env's EFLAGSs to have interrupts enabled */
        tf->tf_rflags |= 0x00000200; // bit 9 is the interrupts-enabled
index fcf3b6e..ee6f327 100644 (file)
@@ -342,11 +342,16 @@ static inline void init_user_ctx(struct user_context *ctx, uintptr_t entry_pt,
 {
        struct sw_trapframe *sw_tf = &ctx->tf.sw_tf;
        ctx->type = ROS_SW_CTX;
-       /* No need to bother with setting the other GP registers; the called
-        * function won't care about their contents. */
-       sw_tf->tf_rsp = stack_top;
+       /* Stack pointers in a fresh stackframe need to be such that adding or
+        * subtracting 8 will result in 16 byte alignment (AMD64 ABI).  The reason
+        * is so that input arguments (on the stack) are 16 byte aligned.  The
+        * extra 8 bytes is the retaddr, pushed on the stack.  Compilers know they
+        * can subtract 8 to get 16 byte alignment for instructions like movaps. */
+       sw_tf->tf_rsp = ROUNDDOWN(stack_top, 16) - 8;
        sw_tf->tf_rip = entry_pt;
        sw_tf->tf_rbp = 0;      /* for potential backtraces */
+       /* No need to bother with setting the other GP registers; the called
+        * function won't care about their contents. */
        sw_tf->tf_mxcsr = 0x00001f80;   /* x86 default mxcsr */
        sw_tf->tf_fpucw = 0x037f;               /* x86 default FP CW */
 }