]> git.ipfire.org Git - people/arne_f/kernel.git/blobdiff - arch/powerpc/kernel/signal_32.c
powerpc/tm: Set MSR[TS] just prior to recheckpoint
[people/arne_f/kernel.git] / arch / powerpc / kernel / signal_32.c
index 9d39e0eb03ff1aadb56762fdb3bde0f698aff95a..7484f43493d30e62c1cc2541f71bd944e5478406 100644 (file)
@@ -848,7 +848,23 @@ static long restore_tm_user_regs(struct pt_regs *regs,
        /* If TM bits are set to the reserved value, it's an invalid context */
        if (MSR_TM_RESV(msr_hi))
                return 1;
-       /* Pull in the MSR TM bits from the user context */
+
+       /*
+        * Disabling preemption, since it is unsafe to be preempted
+        * with MSR[TS] set without recheckpointing.
+        */
+       preempt_disable();
+
+       /*
+        * CAUTION:
+        * After regs->MSR[TS] being updated, make sure that get_user(),
+        * put_user() or similar functions are *not* called. These
+        * functions can generate page faults which will cause the process
+        * to be de-scheduled with MSR[TS] set but without calling
+        * tm_recheckpoint(). This can cause a bug.
+        *
+        * Pull in the MSR TM bits from the user context
+        */
        regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK);
        /* Now, recheckpoint.  This loads up all of the checkpointed (older)
         * registers, including FP and V[S]Rs.  After recheckpointing, the
@@ -873,6 +889,8 @@ static long restore_tm_user_regs(struct pt_regs *regs,
        }
 #endif
 
+       preempt_enable();
+
        return 0;
 }
 #endif