powerpc: fix giveup_vsx to save registers correctly
giveup_vsx didn't save the FPU and VMX regsiters. Change it to be like giveup_fpr/altivec which save these registers. Also update call sites where FPU and VMX are already saved to use the original giveup_vsx (renamed to __giveup_vsx). Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
committed by
Benjamin Herrenschmidt
parent
01f4b8b8b8
commit
7c29217096
@@ -508,12 +508,12 @@ _GLOBAL(giveup_altivec)
|
|||||||
|
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
/*
|
/*
|
||||||
* giveup_vsx(tsk)
|
* __giveup_vsx(tsk)
|
||||||
* Disable VSX for the task given as the argument,
|
* Disable VSX for the task given as the argument.
|
||||||
* and save the vector registers in its thread_struct.
|
* Does NOT save vsx registers.
|
||||||
* Enables the VSX for use in the kernel on return.
|
* Enables the VSX for use in the kernel on return.
|
||||||
*/
|
*/
|
||||||
_GLOBAL(giveup_vsx)
|
_GLOBAL(__giveup_vsx)
|
||||||
mfmsr r5
|
mfmsr r5
|
||||||
oris r5,r5,MSR_VSX@h
|
oris r5,r5,MSR_VSX@h
|
||||||
mtmsrd r5 /* enable use of VSX now */
|
mtmsrd r5 /* enable use of VSX now */
|
||||||
|
@@ -159,6 +159,13 @@ void enable_kernel_vsx(void)
|
|||||||
EXPORT_SYMBOL(enable_kernel_vsx);
|
EXPORT_SYMBOL(enable_kernel_vsx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void giveup_vsx(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
giveup_fpu(tsk);
|
||||||
|
giveup_altivec(tsk);
|
||||||
|
__giveup_vsx(tsk);
|
||||||
|
}
|
||||||
|
|
||||||
void flush_vsx_to_thread(struct task_struct *tsk)
|
void flush_vsx_to_thread(struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
if (tsk->thread.regs) {
|
if (tsk->thread.regs) {
|
||||||
@@ -290,7 +297,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
|||||||
#endif /* CONFIG_ALTIVEC */
|
#endif /* CONFIG_ALTIVEC */
|
||||||
#ifdef CONFIG_VSX
|
#ifdef CONFIG_VSX
|
||||||
if (prev->thread.regs && (prev->thread.regs->msr & MSR_VSX))
|
if (prev->thread.regs && (prev->thread.regs->msr & MSR_VSX))
|
||||||
giveup_vsx(prev);
|
/* VMX and FPU registers are already save here */
|
||||||
|
__giveup_vsx(prev);
|
||||||
#endif /* CONFIG_VSX */
|
#endif /* CONFIG_VSX */
|
||||||
#ifdef CONFIG_SPE
|
#ifdef CONFIG_SPE
|
||||||
/*
|
/*
|
||||||
|
@@ -452,7 +452,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
|
|||||||
* contains valid data
|
* contains valid data
|
||||||
*/
|
*/
|
||||||
if (current->thread.used_vsr) {
|
if (current->thread.used_vsr) {
|
||||||
flush_vsx_to_thread(current);
|
__giveup_vsx(current);
|
||||||
if (copy_vsx_to_user(&frame->mc_vsregs, current))
|
if (copy_vsx_to_user(&frame->mc_vsregs, current))
|
||||||
return 1;
|
return 1;
|
||||||
msr |= MSR_VSX;
|
msr |= MSR_VSX;
|
||||||
|
@@ -122,7 +122,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
|||||||
* VMX data.
|
* VMX data.
|
||||||
*/
|
*/
|
||||||
if (current->thread.used_vsr) {
|
if (current->thread.used_vsr) {
|
||||||
flush_vsx_to_thread(current);
|
__giveup_vsx(current);
|
||||||
v_regs += ELF_NVRREG;
|
v_regs += ELF_NVRREG;
|
||||||
err |= copy_vsx_to_user(v_regs, current);
|
err |= copy_vsx_to_user(v_regs, current);
|
||||||
/* set MSR_VSX in the MSR value in the frame to
|
/* set MSR_VSX in the MSR value in the frame to
|
||||||
|
@@ -139,6 +139,7 @@ extern void enable_kernel_altivec(void);
|
|||||||
extern void giveup_altivec(struct task_struct *);
|
extern void giveup_altivec(struct task_struct *);
|
||||||
extern void load_up_altivec(struct task_struct *);
|
extern void load_up_altivec(struct task_struct *);
|
||||||
extern int emulate_altivec(struct pt_regs *);
|
extern int emulate_altivec(struct pt_regs *);
|
||||||
|
extern void __giveup_vsx(struct task_struct *);
|
||||||
extern void giveup_vsx(struct task_struct *);
|
extern void giveup_vsx(struct task_struct *);
|
||||||
extern void enable_kernel_spe(void);
|
extern void enable_kernel_spe(void);
|
||||||
extern void giveup_spe(struct task_struct *);
|
extern void giveup_spe(struct task_struct *);
|
||||||
|
Reference in New Issue
Block a user