]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/kernel/tm.S
powerpc: Correct DSCR during TM context switch
[karo-tx-linux.git] / arch / powerpc / kernel / tm.S
index 03567c05950a3cf5ee465ef0d3a8e540ad5594a8..2a324f4cb1b9bd2d7354b783641d40ed54c5a2c2 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/ppc-opcode.h>
 #include <asm/ptrace.h>
 #include <asm/reg.h>
+#include <asm/bug.h>
 
 #ifdef CONFIG_VSX
 /* See fpu.S, this is borrowed from there */
@@ -41,7 +42,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX);           \
 /* Stack frame offsets for local variables. */
 #define TM_FRAME_L0    TM_FRAME_SIZE-16
 #define TM_FRAME_L1    TM_FRAME_SIZE-8
-#define STACK_PARAM(x) (48+((x)*8))
 
 
 /* In order to access the TM SPRs, TM must be enabled.  So, do so: */
@@ -78,12 +78,6 @@ _GLOBAL(tm_abort)
        TABORT(R3)
        blr
 
-       .section        ".toc","aw"
-DSCR_DEFAULT:
-       .tc dscr_default[TC],dscr_default
-
-       .section        ".text"
-
 /* void tm_reclaim(struct thread_struct *thread,
  *                 unsigned long orig_msr,
  *                uint8_t cause)
@@ -108,12 +102,12 @@ _GLOBAL(tm_reclaim)
        mflr    r0
        stw     r6, 8(r1)
        std     r0, 16(r1)
-       std     r2, 40(r1)
+       std     r2, STK_GOT(r1)
        stdu    r1, -TM_FRAME_SIZE(r1)
 
        /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */
 
-       std     r3, STACK_PARAM(0)(r1)
+       std     r3, STK_PARAM(R3)(r1)
        SAVE_NVGPRS(r1)
 
        /* We need to setup MSR for VSX register save instructions.  Here we
@@ -175,6 +169,13 @@ dont_backup_vec:
        stfd    fr0,FPSTATE_FPSCR(r7)
 
 dont_backup_fp:
+       /* Do sanity check on MSR to make sure we are suspended */
+       li      r7, (MSR_TS_S)@higher
+       srdi    r6, r14, 32
+       and     r6, r6, r7
+1:     tdeqi   r6, 0
+       EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
+
        /* The moment we treclaim, ALL of our GPRs will switch
         * to user register state.  (FPRs, CCR etc. also!)
         * Use an sprg and a tm_scratch in the PACA to shuffle.
@@ -202,7 +203,7 @@ dont_backup_fp:
        /* Now get some more GPRS free */
        std     r7, GPR7(r1)                    /* Temporary stash */
        std     r12, GPR12(r1)                  /* ''   ''    ''   */
-       ld      r12, STACK_PARAM(0)(r1)         /* Param 0, thread_struct * */
+       ld      r12, STK_PARAM(R3)(r1)          /* Param 0, thread_struct * */
 
        std     r11, THREAD_TM_PPR(r12)         /* Store PPR and free r11 */
 
@@ -289,11 +290,10 @@ dont_backup_fp:
        ld      r0, 16(r1)
        mtcr    r4
        mtlr    r0
-       ld      r2, 40(r1)
+       ld      r2, STK_GOT(r1)
 
-       /* Load system default DSCR */
-       ld      r4, DSCR_DEFAULT@toc(r2)
-       ld      r0, 0(r4)
+       /* Load CPU's default DSCR */
+       ld      r0, PACA_DSCR(r13)
        mtspr   SPRN_DSCR, r0
 
        blr
@@ -312,7 +312,7 @@ _GLOBAL(__tm_recheckpoint)
        mflr    r0
        stw     r5, 8(r1)
        std     r0, 16(r1)
-       std     r2, 40(r1)
+       std     r2, STK_GOT(r1)
        stdu    r1, -TM_FRAME_SIZE(r1)
 
        /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD].
@@ -320,8 +320,6 @@ _GLOBAL(__tm_recheckpoint)
         */
        SAVE_NVGPRS(r1)
 
-       std     r1, PACAR1(r13)
-
        /* Load complete register state from ts_ckpt* registers */
 
        addi    r7, r3, PT_CKPT_REGS            /* Thread's ckpt_regs */
@@ -385,12 +383,10 @@ restore_gprs:
        /* ******************** CR,LR,CCR,MSR ********** */
        ld      r4, _CTR(r7)
        ld      r5, _LINK(r7)
-       ld      r6, _CCR(r7)
        ld      r8, _XER(r7)
 
        mtctr   r4
        mtlr    r5
-       mtcr    r6
        mtxer   r8
 
        /* ******************** TAR ******************** */
@@ -406,7 +402,8 @@ restore_gprs:
        li      r4, 0
        mtmsrd  r4, 1
 
-       REST_4GPRS(0, r7)                       /* GPR0-3 */
+       REST_GPR(0, r7)                         /* GPR0 */
+       REST_2GPRS(2, r7)                       /* GPR2-3 */
        REST_GPR(4, r7)                         /* GPR4 */
        REST_4GPRS(8, r7)                       /* GPR8-11 */
        REST_2GPRS(12, r7)                      /* GPR12-13 */
@@ -418,6 +415,31 @@ restore_gprs:
        mtspr   SPRN_DSCR, r5
        mtspr   SPRN_PPR, r6
 
+       /* Do final sanity check on TEXASR to make sure FS is set.  Do this
+        * here before we load up the userspace r1 so any bugs we hit will get
+        * a call chain */
+       mfspr   r5, SPRN_TEXASR
+       srdi    r5, r5, 16
+       li      r6, (TEXASR_FS)@h
+       and     r6, r6, r5
+1:     tdeqi   r6, 0
+       EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
+
+       /* Do final sanity check on MSR to make sure we are not transactional
+        * or suspended
+        */
+       mfmsr   r6
+       li      r5, (MSR_TS_MASK)@higher
+       srdi    r6, r6, 32
+       and     r6, r6, r5
+1:     tdnei   r6, 0
+       EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
+
+       /* Restore CR */
+       ld      r6, _CCR(r7)
+       mtcr    r6
+
+       REST_GPR(1, r7)                         /* GPR1 */
        REST_GPR(5, r7)                         /* GPR5-7 */
        REST_GPR(6, r7)
        ld      r7, GPR7(r7)
@@ -448,11 +470,10 @@ restore_gprs:
        ld      r0, 16(r1)
        mtcr    r4
        mtlr    r0
-       ld      r2, 40(r1)
+       ld      r2, STK_GOT(r1)
 
-       /* Load system default DSCR */
-       ld      r4, DSCR_DEFAULT@toc(r2)
-       ld      r0, 0(r4)
+       /* Load CPU's default DSCR */
+       ld      r0, PACA_DSCR(r13)
        mtspr   SPRN_DSCR, r0
 
        blr