aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2015-10-28 20:43:57 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-11-30 21:52:24 -0500
commitaf1bbc3dd3d501d27da72e1764afe5f5b0d3882d (patch)
tree99e12a987162dce90c51b7f7ccb2b3e23b154c4b
parent68bfa962bff5783ad65de9dc7f3b9e16ea466766 (diff)
powerpc: Remove UP only lazy floating point and vector optimisations
The UP only lazy floating point and vector optimisations were written back when SMP was not common, and neither glibc nor gcc used vector instructions. Now SMP is very common, glibc aggressively uses vector instructions and gcc autovectorises. We want to add new optimisations that apply to both UP and SMP, but in preparation for that remove these UP only optimisations. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/processor.h6
-rw-r--r--arch/powerpc/include/asm/switch_to.h8
-rw-r--r--arch/powerpc/kernel/fpu.S35
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S32
-rw-r--r--arch/powerpc/kernel/idle_power7.S7
-rw-r--r--arch/powerpc/kernel/process.c113
-rw-r--r--arch/powerpc/kernel/signal_32.c18
-rw-r--r--arch/powerpc/kernel/signal_64.c18
-rw-r--r--arch/powerpc/kernel/vector.S68
9 files changed, 1 insertions, 304 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index c273f3e0ba84..a2e891840806 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -88,12 +88,6 @@ struct task_struct;
88void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); 88void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
89void release_thread(struct task_struct *); 89void release_thread(struct task_struct *);
90 90
91/* Lazy FPU handling on uni-processor */
92extern struct task_struct *last_task_used_math;
93extern struct task_struct *last_task_used_altivec;
94extern struct task_struct *last_task_used_vsx;
95extern struct task_struct *last_task_used_spe;
96
97#ifdef CONFIG_PPC32 91#ifdef CONFIG_PPC32
98 92
99#if CONFIG_TASK_SIZE > CONFIG_KERNEL_START 93#if CONFIG_TASK_SIZE > CONFIG_KERNEL_START
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 33a071d24ba8..bd1d93318350 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -27,14 +27,6 @@ extern void giveup_spe(struct task_struct *);
27extern void load_up_spe(struct task_struct *); 27extern void load_up_spe(struct task_struct *);
28extern void switch_booke_debug_regs(struct debug_reg *new_debug); 28extern void switch_booke_debug_regs(struct debug_reg *new_debug);
29 29
30#ifndef CONFIG_SMP
31extern void discard_lazy_cpu_state(void);
32#else
33static inline void discard_lazy_cpu_state(void)
34{
35}
36#endif
37
38#ifdef CONFIG_PPC_FPU 30#ifdef CONFIG_PPC_FPU
39extern void flush_fp_to_thread(struct task_struct *); 31extern void flush_fp_to_thread(struct task_struct *);
40extern void giveup_fpu(struct task_struct *); 32extern void giveup_fpu(struct task_struct *);
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 38eb79b8a034..50d2352f2cf4 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -132,31 +132,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
132 SYNC 132 SYNC
133 MTMSRD(r5) /* enable use of fpu now */ 133 MTMSRD(r5) /* enable use of fpu now */
134 isync 134 isync
135/*
136 * For SMP, we don't do lazy FPU switching because it just gets too
137 * horrendously complex, especially when a task switches from one CPU
138 * to another. Instead we call giveup_fpu in switch_to.
139 */
140#ifndef CONFIG_SMP
141 LOAD_REG_ADDRBASE(r3, last_task_used_math)
142 toreal(r3)
143 PPC_LL r4,ADDROFF(last_task_used_math)(r3)
144 PPC_LCMPI 0,r4,0
145 beq 1f
146 toreal(r4)
147 addi r4,r4,THREAD /* want last_task_used_math->thread */
148 addi r10,r4,THREAD_FPSTATE
149 SAVE_32FPVSRS(0, R5, R10)
150 mffs fr0
151 stfd fr0,FPSTATE_FPSCR(r10)
152 PPC_LL r5,PT_REGS(r4)
153 toreal(r5)
154 PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
155 li r10,MSR_FP|MSR_FE0|MSR_FE1
156 andc r4,r4,r10 /* disable FP for previous task */
157 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1581:
159#endif /* CONFIG_SMP */
160 /* enable use of FP after return */ 135 /* enable use of FP after return */
161#ifdef CONFIG_PPC32 136#ifdef CONFIG_PPC32
162 mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ 137 mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */
@@ -175,11 +150,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
175 lfd fr0,FPSTATE_FPSCR(r10) 150 lfd fr0,FPSTATE_FPSCR(r10)
176 MTFSF_L(fr0) 151 MTFSF_L(fr0)
177 REST_32FPVSRS(0, R4, R10) 152 REST_32FPVSRS(0, R4, R10)
178#ifndef CONFIG_SMP
179 subi r4,r5,THREAD
180 fromreal(r4)
181 PPC_STL r4,ADDROFF(last_task_used_math)(r3)
182#endif /* CONFIG_SMP */
183 /* restore registers and return */ 153 /* restore registers and return */
184 /* we haven't used ctr or xer or lr */ 154 /* we haven't used ctr or xer or lr */
185 blr 155 blr
@@ -226,11 +196,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
226 andc r4,r4,r3 /* disable FP for previous task */ 196 andc r4,r4,r3 /* disable FP for previous task */
227 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 197 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
2281: 1981:
229#ifndef CONFIG_SMP
230 li r5,0
231 LOAD_REG_ADDRBASE(r4,last_task_used_math)
232 PPC_STL r5,ADDROFF(last_task_used_math)(r4)
233#endif /* CONFIG_SMP */
234 blr 199 blr
235 200
236/* 201/*
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index fffd1f96bb1d..ec936abbcadc 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -857,29 +857,6 @@ _GLOBAL(load_up_spe)
857 oris r5,r5,MSR_SPE@h 857 oris r5,r5,MSR_SPE@h
858 mtmsr r5 /* enable use of SPE now */ 858 mtmsr r5 /* enable use of SPE now */
859 isync 859 isync
860/*
861 * For SMP, we don't do lazy SPE switching because it just gets too
862 * horrendously complex, especially when a task switches from one CPU
863 * to another. Instead we call giveup_spe in switch_to.
864 */
865#ifndef CONFIG_SMP
866 lis r3,last_task_used_spe@ha
867 lwz r4,last_task_used_spe@l(r3)
868 cmpi 0,r4,0
869 beq 1f
870 addi r4,r4,THREAD /* want THREAD of last_task_used_spe */
871 SAVE_32EVRS(0,r10,r4,THREAD_EVR0)
872 evxor evr10, evr10, evr10 /* clear out evr10 */
873 evmwumiaa evr10, evr10, evr10 /* evr10 <- ACC = 0 * 0 + ACC */
874 li r5,THREAD_ACC
875 evstddx evr10, r4, r5 /* save off accumulator */
876 lwz r5,PT_REGS(r4)
877 lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
878 lis r10,MSR_SPE@h
879 andc r4,r4,r10 /* disable SPE for previous task */
880 stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
8811:
882#endif /* !CONFIG_SMP */
883 /* enable use of SPE after return */ 860 /* enable use of SPE after return */
884 oris r9,r9,MSR_SPE@h 861 oris r9,r9,MSR_SPE@h
885 mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ 862 mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */
@@ -889,10 +866,6 @@ _GLOBAL(load_up_spe)
889 evlddx evr4,r10,r5 866 evlddx evr4,r10,r5
890 evmra evr4,evr4 867 evmra evr4,evr4
891 REST_32EVRS(0,r10,r5,THREAD_EVR0) 868 REST_32EVRS(0,r10,r5,THREAD_EVR0)
892#ifndef CONFIG_SMP
893 subi r4,r5,THREAD
894 stw r4,last_task_used_spe@l(r3)
895#endif /* !CONFIG_SMP */
896 blr 869 blr
897 870
898/* 871/*
@@ -1035,11 +1008,6 @@ _GLOBAL(giveup_spe)
1035 andc r4,r4,r3 /* disable SPE for previous task */ 1008 andc r4,r4,r3 /* disable SPE for previous task */
1036 stw r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1009 stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
10371: 10101:
1038#ifndef CONFIG_SMP
1039 li r5,0
1040 lis r4,last_task_used_spe@ha
1041 stw r5,last_task_used_spe@l(r4)
1042#endif /* !CONFIG_SMP */
1043 blr 1011 blr
1044#endif /* CONFIG_SPE */ 1012#endif /* CONFIG_SPE */
1045 1013
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S
index 112ccf497562..cf4fb5429cf1 100644
--- a/arch/powerpc/kernel/idle_power7.S
+++ b/arch/powerpc/kernel/idle_power7.S
@@ -89,13 +89,6 @@ _GLOBAL(power7_powersave_common)
89 std r0,_LINK(r1) 89 std r0,_LINK(r1)
90 std r0,_NIP(r1) 90 std r0,_NIP(r1)
91 91
92#ifndef CONFIG_SMP
93 /* Make sure FPU, VSX etc... are flushed as we may lose
94 * state when going to nap mode
95 */
96 bl discard_lazy_cpu_state
97#endif /* CONFIG_SMP */
98
99 /* Hard disable interrupts */ 92 /* Hard disable interrupts */
100 mfmsr r9 93 mfmsr r9
101 rldicl r9,r9,48,1 94 rldicl r9,r9,48,1
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 3aabed4a60a9..e098f4315643 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -67,13 +67,6 @@
67 67
68extern unsigned long _get_SP(void); 68extern unsigned long _get_SP(void);
69 69
70#ifndef CONFIG_SMP
71struct task_struct *last_task_used_math = NULL;
72struct task_struct *last_task_used_altivec = NULL;
73struct task_struct *last_task_used_vsx = NULL;
74struct task_struct *last_task_used_spe = NULL;
75#endif
76
77#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 70#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
78void giveup_fpu_maybe_transactional(struct task_struct *tsk) 71void giveup_fpu_maybe_transactional(struct task_struct *tsk)
79{ 72{
@@ -134,16 +127,14 @@ void flush_fp_to_thread(struct task_struct *tsk)
134 */ 127 */
135 preempt_disable(); 128 preempt_disable();
136 if (tsk->thread.regs->msr & MSR_FP) { 129 if (tsk->thread.regs->msr & MSR_FP) {
137#ifdef CONFIG_SMP
138 /* 130 /*
139 * This should only ever be called for current or 131 * This should only ever be called for current or
140 * for a stopped child process. Since we save away 132 * for a stopped child process. Since we save away
141 * the FP register state on context switch on SMP, 133 * the FP register state on context switch,
142 * there is something wrong if a stopped child appears 134 * there is something wrong if a stopped child appears
143 * to still have its FP state in the CPU registers. 135 * to still have its FP state in the CPU registers.
144 */ 136 */
145 BUG_ON(tsk != current); 137 BUG_ON(tsk != current);
146#endif
147 giveup_fpu_maybe_transactional(tsk); 138 giveup_fpu_maybe_transactional(tsk);
148 } 139 }
149 preempt_enable(); 140 preempt_enable();
@@ -156,14 +147,10 @@ void enable_kernel_fp(void)
156{ 147{
157 WARN_ON(preemptible()); 148 WARN_ON(preemptible());
158 149
159#ifdef CONFIG_SMP
160 if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) 150 if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
161 giveup_fpu_maybe_transactional(current); 151 giveup_fpu_maybe_transactional(current);
162 else 152 else
163 giveup_fpu(NULL); /* just enables FP for kernel */ 153 giveup_fpu(NULL); /* just enables FP for kernel */
164#else
165 giveup_fpu_maybe_transactional(last_task_used_math);
166#endif /* CONFIG_SMP */
167} 154}
168EXPORT_SYMBOL(enable_kernel_fp); 155EXPORT_SYMBOL(enable_kernel_fp);
169 156
@@ -172,14 +159,10 @@ void enable_kernel_altivec(void)
172{ 159{
173 WARN_ON(preemptible()); 160 WARN_ON(preemptible());
174 161
175#ifdef CONFIG_SMP
176 if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) 162 if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
177 giveup_altivec_maybe_transactional(current); 163 giveup_altivec_maybe_transactional(current);
178 else 164 else
179 giveup_altivec_notask(); 165 giveup_altivec_notask();
180#else
181 giveup_altivec_maybe_transactional(last_task_used_altivec);
182#endif /* CONFIG_SMP */
183} 166}
184EXPORT_SYMBOL(enable_kernel_altivec); 167EXPORT_SYMBOL(enable_kernel_altivec);
185 168
@@ -192,9 +175,7 @@ void flush_altivec_to_thread(struct task_struct *tsk)
192 if (tsk->thread.regs) { 175 if (tsk->thread.regs) {
193 preempt_disable(); 176 preempt_disable();
194 if (tsk->thread.regs->msr & MSR_VEC) { 177 if (tsk->thread.regs->msr & MSR_VEC) {
195#ifdef CONFIG_SMP
196 BUG_ON(tsk != current); 178 BUG_ON(tsk != current);
197#endif
198 giveup_altivec_maybe_transactional(tsk); 179 giveup_altivec_maybe_transactional(tsk);
199 } 180 }
200 preempt_enable(); 181 preempt_enable();
@@ -208,14 +189,10 @@ void enable_kernel_vsx(void)
208{ 189{
209 WARN_ON(preemptible()); 190 WARN_ON(preemptible());
210 191
211#ifdef CONFIG_SMP
212 if (current->thread.regs && (current->thread.regs->msr & MSR_VSX)) 192 if (current->thread.regs && (current->thread.regs->msr & MSR_VSX))
213 giveup_vsx(current); 193 giveup_vsx(current);
214 else 194 else
215 giveup_vsx(NULL); /* just enable vsx for kernel - force */ 195 giveup_vsx(NULL); /* just enable vsx for kernel - force */
216#else
217 giveup_vsx(last_task_used_vsx);
218#endif /* CONFIG_SMP */
219} 196}
220EXPORT_SYMBOL(enable_kernel_vsx); 197EXPORT_SYMBOL(enable_kernel_vsx);
221 198
@@ -232,9 +209,7 @@ void flush_vsx_to_thread(struct task_struct *tsk)
232 if (tsk->thread.regs) { 209 if (tsk->thread.regs) {
233 preempt_disable(); 210 preempt_disable();
234 if (tsk->thread.regs->msr & MSR_VSX) { 211 if (tsk->thread.regs->msr & MSR_VSX) {
235#ifdef CONFIG_SMP
236 BUG_ON(tsk != current); 212 BUG_ON(tsk != current);
237#endif
238 giveup_vsx(tsk); 213 giveup_vsx(tsk);
239 } 214 }
240 preempt_enable(); 215 preempt_enable();
@@ -249,14 +224,10 @@ void enable_kernel_spe(void)
249{ 224{
250 WARN_ON(preemptible()); 225 WARN_ON(preemptible());
251 226
252#ifdef CONFIG_SMP
253 if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) 227 if (current->thread.regs && (current->thread.regs->msr & MSR_SPE))
254 giveup_spe(current); 228 giveup_spe(current);
255 else 229 else
256 giveup_spe(NULL); /* just enable SPE for kernel - force */ 230 giveup_spe(NULL); /* just enable SPE for kernel - force */
257#else
258 giveup_spe(last_task_used_spe);
259#endif /* __SMP __ */
260} 231}
261EXPORT_SYMBOL(enable_kernel_spe); 232EXPORT_SYMBOL(enable_kernel_spe);
262 233
@@ -265,9 +236,7 @@ void flush_spe_to_thread(struct task_struct *tsk)
265 if (tsk->thread.regs) { 236 if (tsk->thread.regs) {
266 preempt_disable(); 237 preempt_disable();
267 if (tsk->thread.regs->msr & MSR_SPE) { 238 if (tsk->thread.regs->msr & MSR_SPE) {
268#ifdef CONFIG_SMP
269 BUG_ON(tsk != current); 239 BUG_ON(tsk != current);
270#endif
271 tsk->thread.spefscr = mfspr(SPRN_SPEFSCR); 240 tsk->thread.spefscr = mfspr(SPRN_SPEFSCR);
272 giveup_spe(tsk); 241 giveup_spe(tsk);
273 } 242 }
@@ -276,32 +245,6 @@ void flush_spe_to_thread(struct task_struct *tsk)
276} 245}
277#endif /* CONFIG_SPE */ 246#endif /* CONFIG_SPE */
278 247
279#ifndef CONFIG_SMP
280/*
281 * If we are doing lazy switching of CPU state (FP, altivec or SPE),
282 * and the current task has some state, discard it.
283 */
284void discard_lazy_cpu_state(void)
285{
286 preempt_disable();
287 if (last_task_used_math == current)
288 last_task_used_math = NULL;
289#ifdef CONFIG_ALTIVEC
290 if (last_task_used_altivec == current)
291 last_task_used_altivec = NULL;
292#endif /* CONFIG_ALTIVEC */
293#ifdef CONFIG_VSX
294 if (last_task_used_vsx == current)
295 last_task_used_vsx = NULL;
296#endif /* CONFIG_VSX */
297#ifdef CONFIG_SPE
298 if (last_task_used_spe == current)
299 last_task_used_spe = NULL;
300#endif
301 preempt_enable();
302}
303#endif /* CONFIG_SMP */
304
305#ifdef CONFIG_PPC_ADV_DEBUG_REGS 248#ifdef CONFIG_PPC_ADV_DEBUG_REGS
306void do_send_trap(struct pt_regs *regs, unsigned long address, 249void do_send_trap(struct pt_regs *regs, unsigned long address,
307 unsigned long error_code, int signal_code, int breakpt) 250 unsigned long error_code, int signal_code, int breakpt)
@@ -831,30 +774,9 @@ struct task_struct *__switch_to(struct task_struct *prev,
831 774
832 __switch_to_tm(prev); 775 __switch_to_tm(prev);
833 776
834#ifdef CONFIG_SMP
835 /* avoid complexity of lazy save/restore of fpu
836 * by just saving it every time we switch out if
837 * this task used the fpu during the last quantum.
838 *
839 * If it tries to use the fpu again, it'll trap and
840 * reload its fp regs. So we don't have to do a restore
841 * every switch, just a save.
842 * -- Cort
843 */
844 if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) 777 if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
845 giveup_fpu(prev); 778 giveup_fpu(prev);
846#ifdef CONFIG_ALTIVEC 779#ifdef CONFIG_ALTIVEC
847 /*
848 * If the previous thread used altivec in the last quantum
849 * (thus changing altivec regs) then save them.
850 * We used to check the VRSAVE register but not all apps
851 * set it, so we don't rely on it now (and in fact we need
852 * to save & restore VSCR even if VRSAVE == 0). -- paulus
853 *
854 * On SMP we always save/restore altivec regs just to avoid the
855 * complexity of changing processors.
856 * -- Cort
857 */
858 if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) 780 if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))
859 giveup_altivec(prev); 781 giveup_altivec(prev);
860#endif /* CONFIG_ALTIVEC */ 782#endif /* CONFIG_ALTIVEC */
@@ -864,39 +786,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
864 __giveup_vsx(prev); 786 __giveup_vsx(prev);
865#endif /* CONFIG_VSX */ 787#endif /* CONFIG_VSX */
866#ifdef CONFIG_SPE 788#ifdef CONFIG_SPE
867 /*
868 * If the previous thread used spe in the last quantum
869 * (thus changing spe regs) then save them.
870 *
871 * On SMP we always save/restore spe regs just to avoid the
872 * complexity of changing processors.
873 */
874 if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) 789 if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE)))
875 giveup_spe(prev); 790 giveup_spe(prev);
876#endif /* CONFIG_SPE */ 791#endif /* CONFIG_SPE */
877 792
878#else /* CONFIG_SMP */
879#ifdef CONFIG_ALTIVEC
880 /* Avoid the trap. On smp this this never happens since
881 * we don't set last_task_used_altivec -- Cort
882 */
883 if (new->thread.regs && last_task_used_altivec == new)
884 new->thread.regs->msr |= MSR_VEC;
885#endif /* CONFIG_ALTIVEC */
886#ifdef CONFIG_VSX
887 if (new->thread.regs && last_task_used_vsx == new)
888 new->thread.regs->msr |= MSR_VSX;
889#endif /* CONFIG_VSX */
890#ifdef CONFIG_SPE
891 /* Avoid the trap. On smp this this never happens since
892 * we don't set last_task_used_spe
893 */
894 if (new->thread.regs && last_task_used_spe == new)
895 new->thread.regs->msr |= MSR_SPE;
896#endif /* CONFIG_SPE */
897
898#endif /* CONFIG_SMP */
899
900#ifdef CONFIG_PPC_ADV_DEBUG_REGS 793#ifdef CONFIG_PPC_ADV_DEBUG_REGS
901 switch_booke_debug_regs(&new->thread.debug); 794 switch_booke_debug_regs(&new->thread.debug);
902#else 795#else
@@ -1111,13 +1004,10 @@ void show_regs(struct pt_regs * regs)
1111 1004
1112void exit_thread(void) 1005void exit_thread(void)
1113{ 1006{
1114 discard_lazy_cpu_state();
1115} 1007}
1116 1008
1117void flush_thread(void) 1009void flush_thread(void)
1118{ 1010{
1119 discard_lazy_cpu_state();
1120
1121#ifdef CONFIG_HAVE_HW_BREAKPOINT 1011#ifdef CONFIG_HAVE_HW_BREAKPOINT
1122 flush_ptrace_hw_breakpoint(current); 1012 flush_ptrace_hw_breakpoint(current);
1123#else /* CONFIG_HAVE_HW_BREAKPOINT */ 1013#else /* CONFIG_HAVE_HW_BREAKPOINT */
@@ -1355,7 +1245,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
1355 regs->msr = MSR_USER32; 1245 regs->msr = MSR_USER32;
1356 } 1246 }
1357#endif 1247#endif
1358 discard_lazy_cpu_state();
1359#ifdef CONFIG_VSX 1248#ifdef CONFIG_VSX
1360 current->thread.used_vsr = 0; 1249 current->thread.used_vsr = 0;
1361#endif 1250#endif
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 0dbee465af7a..3cd7a32c8ff4 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -687,15 +687,6 @@ static long restore_user_regs(struct pt_regs *regs,
687 if (sig) 687 if (sig)
688 regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); 688 regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
689 689
690 /*
691 * Do this before updating the thread state in
692 * current->thread.fpr/vr/evr. That way, if we get preempted
693 * and another task grabs the FPU/Altivec/SPE, it won't be
694 * tempted to save the current CPU state into the thread_struct
695 * and corrupt what we are writing there.
696 */
697 discard_lazy_cpu_state();
698
699#ifdef CONFIG_ALTIVEC 690#ifdef CONFIG_ALTIVEC
700 /* 691 /*
701 * Force the process to reload the altivec registers from 692 * Force the process to reload the altivec registers from
@@ -798,15 +789,6 @@ static long restore_tm_user_regs(struct pt_regs *regs,
798 /* Restore the previous little-endian mode */ 789 /* Restore the previous little-endian mode */
799 regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); 790 regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
800 791
801 /*
802 * Do this before updating the thread state in
803 * current->thread.fpr/vr/evr. That way, if we get preempted
804 * and another task grabs the FPU/Altivec/SPE, it won't be
805 * tempted to save the current CPU state into the thread_struct
806 * and corrupt what we are writing there.
807 */
808 discard_lazy_cpu_state();
809
810#ifdef CONFIG_ALTIVEC 792#ifdef CONFIG_ALTIVEC
811 regs->msr &= ~MSR_VEC; 793 regs->msr &= ~MSR_VEC;
812 if (msr & MSR_VEC) { 794 if (msr & MSR_VEC) {
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 20756dfb9f34..6f2b555516e6 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -350,15 +350,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
350 err |= __get_user(set->sig[0], &sc->oldmask); 350 err |= __get_user(set->sig[0], &sc->oldmask);
351 351
352 /* 352 /*
353 * Do this before updating the thread state in
354 * current->thread.fpr/vr. That way, if we get preempted
355 * and another task grabs the FPU/Altivec, it won't be
356 * tempted to save the current CPU state into the thread_struct
357 * and corrupt what we are writing there.
358 */
359 discard_lazy_cpu_state();
360
361 /*
362 * Force reload of FP/VEC. 353 * Force reload of FP/VEC.
363 * This has to be done before copying stuff into current->thread.fpr/vr 354 * This has to be done before copying stuff into current->thread.fpr/vr
364 * for the reasons explained in the previous comment. 355 * for the reasons explained in the previous comment.
@@ -465,15 +456,6 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
465 err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]); 456 err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]);
466 457
467 /* 458 /*
468 * Do this before updating the thread state in
469 * current->thread.fpr/vr. That way, if we get preempted
470 * and another task grabs the FPU/Altivec, it won't be
471 * tempted to save the current CPU state into the thread_struct
472 * and corrupt what we are writing there.
473 */
474 discard_lazy_cpu_state();
475
476 /*
477 * Force reload of FP/VEC. 459 * Force reload of FP/VEC.
478 * This has to be done before copying stuff into current->thread.fpr/vr 460 * This has to be done before copying stuff into current->thread.fpr/vr
479 * for the reasons explained in the previous comment. 461 * for the reasons explained in the previous comment.
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 1c5425966204..1757c0c936c1 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -80,39 +80,6 @@ _GLOBAL(load_up_altivec)
80 MTMSRD(r5) /* enable use of AltiVec now */ 80 MTMSRD(r5) /* enable use of AltiVec now */
81 isync 81 isync
82 82
83/*
84 * For SMP, we don't do lazy VMX switching because it just gets too
85 * horrendously complex, especially when a task switches from one CPU
86 * to another. Instead we call giveup_altvec in switch_to.
87 * VRSAVE isn't dealt with here, that is done in the normal context
88 * switch code. Note that we could rely on vrsave value to eventually
89 * avoid saving all of the VREGs here...
90 */
91#ifndef CONFIG_SMP
92 LOAD_REG_ADDRBASE(r3, last_task_used_altivec)
93 toreal(r3)
94 PPC_LL r4,ADDROFF(last_task_used_altivec)(r3)
95 PPC_LCMPI 0,r4,0
96 beq 1f
97
98 /* Save VMX state to last_task_used_altivec's THREAD struct */
99 toreal(r4)
100 addi r4,r4,THREAD
101 addi r6,r4,THREAD_VRSTATE
102 SAVE_32VRS(0,r5,r6)
103 mfvscr v0
104 li r10,VRSTATE_VSCR
105 stvx v0,r10,r6
106 /* Disable VMX for last_task_used_altivec */
107 PPC_LL r5,PT_REGS(r4)
108 toreal(r5)
109 PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
110 lis r10,MSR_VEC@h
111 andc r4,r4,r10
112 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1131:
114#endif /* CONFIG_SMP */
115
116 /* Hack: if we get an altivec unavailable trap with VRSAVE 83 /* Hack: if we get an altivec unavailable trap with VRSAVE
117 * set to all zeros, we assume this is a broken application 84 * set to all zeros, we assume this is a broken application
118 * that fails to set it properly, and thus we switch it to 85 * that fails to set it properly, and thus we switch it to
@@ -141,12 +108,6 @@ _GLOBAL(load_up_altivec)
141 lvx v0,r10,r6 108 lvx v0,r10,r6
142 mtvscr v0 109 mtvscr v0
143 REST_32VRS(0,r4,r6) 110 REST_32VRS(0,r4,r6)
144#ifndef CONFIG_SMP
145 /* Update last_task_used_altivec to 'current' */
146 subi r4,r5,THREAD /* Back to 'current' */
147 fromreal(r4)
148 PPC_STL r4,ADDROFF(last_task_used_altivec)(r3)
149#endif /* CONFIG_SMP */
150 /* restore registers and return */ 111 /* restore registers and return */
151 blr 112 blr
152 113
@@ -199,11 +160,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX)
199 andc r4,r4,r3 /* disable FP for previous task */ 160 andc r4,r4,r3 /* disable FP for previous task */
200 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) 161 PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5)
2011: 1621:
202#ifndef CONFIG_SMP
203 li r5,0
204 LOAD_REG_ADDRBASE(r4,last_task_used_altivec)
205 PPC_STL r5,ADDROFF(last_task_used_altivec)(r4)
206#endif /* CONFIG_SMP */
207 blr 163 blr
208 164
209#ifdef CONFIG_VSX 165#ifdef CONFIG_VSX
@@ -226,20 +182,6 @@ _GLOBAL(load_up_vsx)
226 andis. r5,r12,MSR_VEC@h 182 andis. r5,r12,MSR_VEC@h
227 beql+ load_up_altivec /* skip if already loaded */ 183 beql+ load_up_altivec /* skip if already loaded */
228 184
229#ifndef CONFIG_SMP
230 ld r3,last_task_used_vsx@got(r2)
231 ld r4,0(r3)
232 cmpdi 0,r4,0
233 beq 1f
234 /* Disable VSX for last_task_used_vsx */
235 addi r4,r4,THREAD
236 ld r5,PT_REGS(r4)
237 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
238 lis r6,MSR_VSX@h
239 andc r6,r4,r6
240 std r6,_MSR-STACK_FRAME_OVERHEAD(r5)
2411:
242#endif /* CONFIG_SMP */
243 ld r4,PACACURRENT(r13) 185 ld r4,PACACURRENT(r13)
244 addi r4,r4,THREAD /* Get THREAD */ 186 addi r4,r4,THREAD /* Get THREAD */
245 li r6,1 187 li r6,1
@@ -247,11 +189,6 @@ _GLOBAL(load_up_vsx)
247 /* enable use of VSX after return */ 189 /* enable use of VSX after return */
248 oris r12,r12,MSR_VSX@h 190 oris r12,r12,MSR_VSX@h
249 std r12,_MSR(r1) 191 std r12,_MSR(r1)
250#ifndef CONFIG_SMP
251 /* Update last_task_used_vsx to 'current' */
252 ld r4,PACACURRENT(r13)
253 std r4,0(r3)
254#endif /* CONFIG_SMP */
255 b fast_exception_return 192 b fast_exception_return
256 193
257/* 194/*
@@ -277,11 +214,6 @@ _GLOBAL(__giveup_vsx)
277 andc r4,r4,r3 /* disable VSX for previous task */ 214 andc r4,r4,r3 /* disable VSX for previous task */
278 std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 215 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
2791: 2161:
280#ifndef CONFIG_SMP
281 li r5,0
282 ld r4,last_task_used_vsx@got(r2)
283 std r5,0(r4)
284#endif /* CONFIG_SMP */
285 blr 217 blr
286 218
287#endif /* CONFIG_VSX */ 219#endif /* CONFIG_VSX */