Merge tag 'drm/tegra/for-4.8-rc4' of git://anongit.freedesktop.org/tegra/linux into...
[cascardo/linux.git] / arch / powerpc / kernel / process.c
index 0b93893..9ee2623 100644 (file)
@@ -58,6 +58,7 @@
 #include <asm/code-patching.h>
 #include <asm/exec.h>
 #include <asm/livepatch.h>
+#include <asm/cpu_has_feature.h>
 
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
@@ -139,12 +140,16 @@ EXPORT_SYMBOL(__msr_check_and_clear);
 #ifdef CONFIG_PPC_FPU
 void __giveup_fpu(struct task_struct *tsk)
 {
+       unsigned long msr;
+
        save_fpu(tsk);
-       tsk->thread.regs->msr &= ~MSR_FP;
+       msr = tsk->thread.regs->msr;
+       msr &= ~MSR_FP;
 #ifdef CONFIG_VSX
        if (cpu_has_feature(CPU_FTR_VSX))
-               tsk->thread.regs->msr &= ~MSR_VSX;
+               msr &= ~MSR_VSX;
 #endif
+       tsk->thread.regs->msr = msr;
 }
 
 void giveup_fpu(struct task_struct *tsk)
@@ -219,12 +224,16 @@ static int restore_fp(struct task_struct *tsk) { return 0; }
 
 static void __giveup_altivec(struct task_struct *tsk)
 {
+       unsigned long msr;
+
        save_altivec(tsk);
-       tsk->thread.regs->msr &= ~MSR_VEC;
+       msr = tsk->thread.regs->msr;
+       msr &= ~MSR_VEC;
 #ifdef CONFIG_VSX
        if (cpu_has_feature(CPU_FTR_VSX))
-               tsk->thread.regs->msr &= ~MSR_VSX;
+               msr &= ~MSR_VSX;
 #endif
+       tsk->thread.regs->msr = msr;
 }
 
 void giveup_altivec(struct task_struct *tsk)
@@ -794,7 +803,7 @@ static void tm_reclaim_thread(struct thread_struct *thr,
         * this state.
         * We do this using the current MSR, rather tracking it in
         * some specific thread_struct bit, as it has the additional
-        * benifit of checking for a potential TM bad thing exception.
+        * benefit of checking for a potential TM bad thing exception.
         */
        if (!MSR_TM_SUSPENDED(mfmsr()))
                return;
@@ -1009,6 +1018,14 @@ static inline void save_sprs(struct thread_struct *t)
                 */
                t->tar = mfspr(SPRN_TAR);
        }
+
+       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+               /* Conditionally save Load Monitor registers, if enabled */
+               if (t->fscr & FSCR_LM) {
+                       t->lmrr = mfspr(SPRN_LMRR);
+                       t->lmser = mfspr(SPRN_LMSER);
+               }
+       }
 #endif
 }
 
@@ -1023,18 +1040,11 @@ static inline void restore_sprs(struct thread_struct *old_thread,
 #ifdef CONFIG_PPC_BOOK3S_64
        if (cpu_has_feature(CPU_FTR_DSCR)) {
                u64 dscr = get_paca()->dscr_default;
-               u64 fscr = old_thread->fscr & ~FSCR_DSCR;
-
-               if (new_thread->dscr_inherit) {
+               if (new_thread->dscr_inherit)
                        dscr = new_thread->dscr;
-                       fscr |= FSCR_DSCR;
-               }
 
                if (old_thread->dscr != dscr)
                        mtspr(SPRN_DSCR, dscr);
-
-               if (old_thread->fscr != fscr)
-                       mtspr(SPRN_FSCR, fscr);
        }
 
        if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
@@ -1045,9 +1055,22 @@ static inline void restore_sprs(struct thread_struct *old_thread,
                if (old_thread->ebbrr != new_thread->ebbrr)
                        mtspr(SPRN_EBBRR, new_thread->ebbrr);
 
+               if (old_thread->fscr != new_thread->fscr)
+                       mtspr(SPRN_FSCR, new_thread->fscr);
+
                if (old_thread->tar != new_thread->tar)
                        mtspr(SPRN_TAR, new_thread->tar);
        }
+
+       if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+               /* Conditionally restore Load Monitor registers, if enabled */
+               if (new_thread->fscr & FSCR_LM) {
+                       if (old_thread->lmrr != new_thread->lmrr)
+                               mtspr(SPRN_LMRR, new_thread->lmrr);
+                       if (old_thread->lmser != new_thread->lmser)
+                               mtspr(SPRN_LMSER, new_thread->lmser);
+               }
+       }
 #endif
 }