diff options
author | Anton Blanchard <anton@samba.org> | 2015-10-29 01:43:59 +0100 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-12-01 03:52:25 +0100 |
commit | 611b0e5c19963374175b39f42117b03ee7573228 (patch) | |
tree | 31a1ae1a8d869e574386650d5ef33e9a200d59be | |
parent | powerpc: Simplify TM restore checks (diff) | |
download | linux-611b0e5c19963374175b39f42117b03ee7573228.tar.xz linux-611b0e5c19963374175b39f42117b03ee7573228.zip |
powerpc: Create mtmsrd_isync()
mtmsrd_isync() will do an mtmsrd followed by an isync on older
processors. On newer processors we avoid the isync via a feature fixup.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/process.c | 30 |
2 files changed, 30 insertions, 8 deletions
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index a908ada8e0a5..987dac090244 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1193,12 +1193,20 @@ #define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \ : : "r" (v) : "memory") #define mtmsr(v) __mtmsrd((v), 0) +#define __MTMSR "mtmsrd" #else #define mtmsr(v) asm volatile("mtmsr %0" : \ : "r" ((unsigned long)(v)) \ : "memory") +#define __MTMSR "mtmsr" #endif +static inline void mtmsr_isync(unsigned long val) +{ + asm volatile(__MTMSR " %0; " ASM_FTR_IFCLR("isync", "nop", %1) : : + "r" (val), "i" (CPU_FTR_ARCH_206) : "memory"); +} + #define mfspr(rn) ({unsigned long rval; \ asm volatile("mfspr %0," __stringify(rn) \ : "=r" (rval)); rval;}) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ef64219548d5..5bf8ec2597d4 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -130,7 +130,10 @@ void enable_kernel_fp(void) check_if_tm_restore_required(current); giveup_fpu(current); } else { - giveup_fpu(NULL); /* just enables FP for kernel */ + u64 oldmsr = mfmsr(); + + if (!(oldmsr & MSR_FP)) + mtmsr_isync(oldmsr | MSR_FP); } } EXPORT_SYMBOL(enable_kernel_fp); @@ -144,7 +147,10 @@ void enable_kernel_altivec(void) check_if_tm_restore_required(current); giveup_altivec(current); } else { - giveup_altivec_notask(); + u64 oldmsr = mfmsr(); + + if (!(oldmsr & MSR_VEC)) + mtmsr_isync(oldmsr | MSR_VEC); } } EXPORT_SYMBOL(enable_kernel_altivec); @@ -173,10 +179,14 @@ void enable_kernel_vsx(void) { WARN_ON(preemptible()); - if (current->thread.regs && (current->thread.regs->msr & MSR_VSX)) + if (current->thread.regs && (current->thread.regs->msr & MSR_VSX)) { giveup_vsx(current); - else - giveup_vsx(NULL); /* just enable vsx for kernel - force */ + } else { + u64 oldmsr = mfmsr(); + + if (!(oldmsr & MSR_VSX)) + mtmsr_isync(oldmsr | MSR_VSX); + } } EXPORT_SYMBOL(enable_kernel_vsx); @@ -209,10 +219,14 @@ void enable_kernel_spe(void) { WARN_ON(preemptible()); - if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) + if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) { giveup_spe(current); - else - giveup_spe(NULL); /* just enable SPE for kernel - force */ + } else { + u64 oldmsr = mfmsr(); + + if (!(oldmsr & MSR_SPE)) + mtmsr_isync(oldmsr | MSR_SPE); + } } EXPORT_SYMBOL(enable_kernel_spe); |