summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/process.c
diff options
context:
space:
mode:
authorCyril Bur <cyrilbur@gmail.com>2016-02-29 17:53:48 +1100
committerMichael Ellerman <mpe@ellerman.id.au>2016-03-02 23:34:48 +1100
commitde2a20aa7237b45d3c14a2505804a8daa95a8f53 (patch)
tree13593cbcaa3c487fa1a8a9ce76c1bdc5e50b602f /arch/powerpc/kernel/process.c
parent70fe3d980f5f14d8125869125ba9a0ea95e09c6b (diff)
downloadlwn-de2a20aa7237b45d3c14a2505804a8daa95a8f53.tar.gz
lwn-de2a20aa7237b45d3c14a2505804a8daa95a8f53.zip
powerpc: Prepare for splitting giveup_{fpu, altivec, vsx} in two
This prepares for the decoupling of saving {fpu,altivec,vsx} registers and marking {fpu,altivec,vsx} as being unused by a thread. Currently giveup_{fpu,altivec,vsx}() does both however optimisations to task switching can be made if these two operations are decoupled. save_all() will permit the saving of registers to thread structs and leave threads MSR with bits enabled. This patch introduces no functional change. Signed-off-by: Cyril Bur <cyrilbur@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r--arch/powerpc/kernel/process.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 55c1eb0465af..29da07fb3b4a 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -444,12 +444,41 @@ void restore_math(struct pt_regs *regs)
regs->msr = msr;
}
+void save_all(struct task_struct *tsk)
+{
+ unsigned long usermsr;
+
+ if (!tsk->thread.regs)
+ return;
+
+ usermsr = tsk->thread.regs->msr;
+
+ if ((usermsr & msr_all_available) == 0)
+ return;
+
+ msr_check_and_set(msr_all_available);
+
+ if (usermsr & MSR_FP)
+ __giveup_fpu(tsk);
+
+ if (usermsr & MSR_VEC)
+ __giveup_altivec(tsk);
+
+ if (usermsr & MSR_VSX)
+ __giveup_vsx(tsk);
+
+ if (usermsr & MSR_SPE)
+ __giveup_spe(tsk);
+
+ msr_check_and_clear(msr_all_available);
+}
+
void flush_all_to_thread(struct task_struct *tsk)
{
if (tsk->thread.regs) {
preempt_disable();
BUG_ON(tsk != current);
- giveup_all(tsk);
+ save_all(tsk);
#ifdef CONFIG_SPE
if (tsk->thread.regs->msr & MSR_SPE)