aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/process.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2013-09-10 06:21:10 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-10-11 02:26:50 -0400
commit18461960cbf50bf345ef0667d45d5f64de8fb893 (patch)
tree58947fe30598814684f7e33424675e204316e8ef /arch/powerpc/kernel/process.c
parentde79f7b9f6f92ec1bd6f61fa1f20de60728a5b5e (diff)
powerpc: Provide for giveup_fpu/altivec to save state in alternate location
This provides a facility which is intended for use by KVM, where the contents of the FP/VSX and VMX (Altivec) registers can be saved away to somewhere other than the thread_struct when kernel code wants to use floating point or VMX instructions. This is done by providing a pointer in the thread_struct to indicate where the state should be saved to. The giveup_fpu() and giveup_altivec() functions test these pointers and save state to the indicated location if they are non-NULL. Note that the MSR_FP/VEC bits in task->thread.regs->msr are still used to indicate whether the CPU register state is live, even when an alternate save location is being used. This also provides load_fp_state() and load_vr_state() functions, which load up FP/VSX and VMX state from memory into the CPU registers, and corresponding store_fp_state() and store_vr_state() functions, which store FP/VSX and VMX state into memory from the CPU registers. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r--arch/powerpc/kernel/process.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 7a281416affb..8649a3d629e1 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1008,6 +1008,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
1008 p->thread.ptrace_bps[0] = NULL; 1008 p->thread.ptrace_bps[0] = NULL;
1009#endif 1009#endif
1010 1010
1011 p->thread.fp_save_area = NULL;
1012#ifdef CONFIG_ALTIVEC
1013 p->thread.vr_save_area = NULL;
1014#endif
1015
1011#ifdef CONFIG_PPC_STD_MMU_64 1016#ifdef CONFIG_PPC_STD_MMU_64
1012 if (mmu_has_feature(MMU_FTR_SLB)) { 1017 if (mmu_has_feature(MMU_FTR_SLB)) {
1013 unsigned long sp_vsid; 1018 unsigned long sp_vsid;
@@ -1114,9 +1119,11 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
1114 current->thread.used_vsr = 0; 1119 current->thread.used_vsr = 0;
1115#endif 1120#endif
1116 memset(&current->thread.fp_state, 0, sizeof(current->thread.fp_state)); 1121 memset(&current->thread.fp_state, 0, sizeof(current->thread.fp_state));
1122 current->thread.fp_save_area = NULL;
1117#ifdef CONFIG_ALTIVEC 1123#ifdef CONFIG_ALTIVEC
1118 memset(&current->thread.vr_state, 0, sizeof(current->thread.vr_state)); 1124 memset(&current->thread.vr_state, 0, sizeof(current->thread.vr_state));
1119 current->thread.vr_state.vscr.u[3] = 0x00010000; /* Java mode disabled */ 1125 current->thread.vr_state.vscr.u[3] = 0x00010000; /* Java mode disabled */
1126 current->thread.vr_save_area = NULL;
1120 current->thread.vrsave = 0; 1127 current->thread.vrsave = 0;
1121 current->thread.used_vr = 0; 1128 current->thread.used_vr = 0;
1122#endif /* CONFIG_ALTIVEC */ 1129#endif /* CONFIG_ALTIVEC */