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>
This commit is contained in:

committed by
Benjamin Herrenschmidt

parent
de79f7b9f6
commit
18461960cb
@@ -211,6 +211,7 @@ struct thread_struct {
|
||||
#endif
|
||||
#endif
|
||||
struct thread_fp_state fp_state;
|
||||
struct thread_fp_state *fp_save_area;
|
||||
int fpexc_mode; /* floating-point exception mode */
|
||||
unsigned int align_ctl; /* alignment handling control */
|
||||
#ifdef CONFIG_PPC64
|
||||
@@ -229,6 +230,7 @@ struct thread_struct {
|
||||
unsigned long trap_nr; /* last trap # on this thread */
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
struct thread_vr_state vr_state;
|
||||
struct thread_vr_state *vr_save_area;
|
||||
unsigned long vrsave;
|
||||
int used_vr; /* set if process has used altivec */
|
||||
#endif /* CONFIG_ALTIVEC */
|
||||
@@ -357,6 +359,11 @@ extern int set_endian(struct task_struct *tsk, unsigned int val);
|
||||
extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
|
||||
extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
|
||||
|
||||
extern void load_fp_state(struct thread_fp_state *fp);
|
||||
extern void store_fp_state(struct thread_fp_state *fp);
|
||||
extern void load_vr_state(struct thread_vr_state *vr);
|
||||
extern void store_vr_state(struct thread_vr_state *vr);
|
||||
|
||||
static inline unsigned int __unpack_fe01(unsigned long msr_bits)
|
||||
{
|
||||
return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
|
||||
|
Reference in New Issue
Block a user