When restoring spsr values when handling traps use spsr_fsxc instead
authorjsg <jsg@openbsd.org>
Sun, 18 Jan 2015 16:26:39 +0000 (16:26 +0000)
committerjsg <jsg@openbsd.org>
Sun, 18 Jan 2015 16:26:39 +0000 (16:26 +0000)
of spsr_all so all the bits are restored.  Using the msr instruction
with spsr_all is treated the same as spsr_fc and does not include the
status and extension fields (bits 23:8).

This fixes the problem of some i.MX6 machines powering up with the
big endian bit set in the extension field causing them to crash
on returning from the first interrupt.

From NetBSD.

sys/arch/arm/include/frame.h

index e55378f..9f2adff 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: frame.h,v 1.5 2015/01/18 12:03:11 jsg Exp $   */
+/*     $OpenBSD: frame.h,v 1.6 2015/01/18 16:26:39 jsg Exp $   */
 /*     $NetBSD: frame.h,v 1.9 2003/12/01 08:48:33 scw Exp $    */
 
 /*
@@ -217,7 +217,7 @@ struct frame {
 
 #define PULLFRAME                                                         \
         ldr     r0, [sp], #0x0004;      /* Get the SPSR from stack */     \
-        msr     spsr_all, r0;                                             \
+        msr     spsr_fsxc, r0;                                            \
         ldmia   sp, {r0-r14}^;         /* Restore registers (usr mode) */ \
         mov     r0, r0;                 /* NOP for previous instruction */ \
        add     sp, sp, #(4*17);        /* Adjust the stack pointer */     \
@@ -244,7 +244,7 @@ struct frame {
        str     r0, [sp, #-4]!;         /* Push return address */          \
        str     lr, [sp, #-4]!;         /* Push SVC lr */                  \
        str     r2, [sp, #-4]!;         /* Push SVC sp */                  \
-       msr     spsr_all, r3;           /* Restore correct spsr */         \
+       msr     spsr_fsxc, r3;          /* Restore correct spsr */         \
        ldmdb   r1, {r0-r3};            /* Restore 4 regs from xxx mode */ \
        sub     sp, sp, #(4*15);        /* Adjust the stack pointer */     \
        stmia   sp, {r0-r14}^;          /* Push the user mode registers */ \
@@ -261,7 +261,7 @@ struct frame {
 
 #define PULLFRAMEFROMSVCANDEXIT                                                   \
         ldr     r0, [sp], #0x0004;     /* Get the SPSR from stack */      \
-        msr     spsr_all, r0;          /* restore SPSR */                 \
+        msr     spsr_fsxc, r0;         /* restore SPSR */                 \
         ldmia   sp, {r0-r14}^;         /* Restore registers (usr mode) */ \
         mov     r0, r0;                        /* NOP for previous instruction */ \
        add     sp, sp, #(4*15);        /* Adjust the stack pointer */     \