diff options
author | Paul Mackerras <paulus@samba.org> | 2013-09-10 06:21:10 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-10-11 02:26:50 -0400 |
commit | 18461960cbf50bf345ef0667d45d5f64de8fb893 (patch) | |
tree | 58947fe30598814684f7e33424675e204316e8ef /arch/powerpc/kernel/process.c | |
parent | de79f7b9f6f92ec1bd6f61fa1f20de60728a5b5e (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.c | 7 |
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(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state)); | 1121 | memset(¤t->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(¤t->thread.vr_state, 0, sizeof(current->thread.vr_state)); | 1124 | memset(¤t->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 */ |