Skip to content

Commit 1a3d595

Browse files
paulburtonralfbaechle
authored andcommitted
MIPS: Tidy up FPU context switching
Rather than saving the scalar FP or vector context in the assembly resume function, reuse the existing C code we have in fpu.h to do exactly that. This reduces duplication, results in a much easier to read resume function & should allow the compiler to optimise out more MSA code due to is_msa_enabled()/cpu_has_msa being known-zero at compile time for kernels without MSA support. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Cc: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com> Cc: Maciej W. Rozycki <macro@linux-mips.org> Cc: linux-kernel@vger.kernel.org Cc: James Hogan <james.hogan@imgtec.com> Cc: Markos Chandras <markos.chandras@imgtec.com> Cc: Manuel Lauss <manuel.lauss@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/10830/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
1 parent 23eb6f4 commit 1a3d595

File tree

3 files changed

+18
-65
lines changed

3 files changed

+18
-65
lines changed

arch/mips/include/asm/fpu.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,25 +164,30 @@ static inline int own_fpu(int restore)
164164
return ret;
165165
}
166166

167-
static inline void lose_fpu(int save)
167+
static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
168168
{
169-
preempt_disable();
170169
if (is_msa_enabled()) {
171170
if (save) {
172-
save_msa(current);
173-
current->thread.fpu.fcr31 =
171+
save_msa(tsk);
172+
tsk->thread.fpu.fcr31 =
174173
read_32bit_cp1_register(CP1_STATUS);
175174
}
176175
disable_msa();
177-
clear_thread_flag(TIF_USEDMSA);
176+
clear_tsk_thread_flag(tsk, TIF_USEDMSA);
178177
__disable_fpu();
179178
} else if (is_fpu_owner()) {
180179
if (save)
181-
_save_fp(current);
180+
_save_fp(tsk);
182181
__disable_fpu();
183182
}
184-
KSTK_STATUS(current) &= ~ST0_CU1;
185-
clear_thread_flag(TIF_USEDFPU);
183+
KSTK_STATUS(tsk) &= ~ST0_CU1;
184+
clear_tsk_thread_flag(tsk, TIF_USEDFPU);
185+
}
186+
187+
static inline void lose_fpu(int save)
188+
{
189+
preempt_disable();
190+
lose_fpu_inatomic(save, current);
186191
preempt_enable();
187192
}
188193

arch/mips/include/asm/switch_to.h

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,21 @@
1616
#include <asm/watch.h>
1717
#include <asm/dsp.h>
1818
#include <asm/cop2.h>
19-
#include <asm/msa.h>
19+
#include <asm/fpu.h>
2020

2121
struct task_struct;
2222

23-
enum {
24-
FP_SAVE_NONE = 0,
25-
FP_SAVE_VECTOR = -1,
26-
FP_SAVE_SCALAR = 1,
27-
};
28-
2923
/**
3024
* resume - resume execution of a task
3125
* @prev: The task previously executed.
3226
* @next: The task to begin executing.
3327
* @next_ti: task_thread_info(next).
34-
* @fp_save: Which, if any, FP context to save for prev.
3528
*
3629
* This function is used whilst scheduling to save the context of prev & load
3730
* the context of next. Returns prev.
3831
*/
3932
extern asmlinkage struct task_struct *resume(struct task_struct *prev,
40-
struct task_struct *next, struct thread_info *next_ti,
41-
s32 fp_save);
33+
struct task_struct *next, struct thread_info *next_ti);
4234

4335
extern unsigned int ll_bit;
4436
extern struct task_struct *ll_task;
@@ -91,8 +83,8 @@ do { if (cpu_has_rw_llb) { \
9183
*/
9284
#define switch_to(prev, next, last) \
9385
do { \
94-
s32 __fpsave = FP_SAVE_NONE; \
9586
__mips_mt_fpaff_switch_to(prev); \
87+
lose_fpu_inatomic(1, prev); \
9688
if (cpu_has_dsp) { \
9789
__save_dsp(prev); \
9890
__restore_dsp(next); \
@@ -111,15 +103,10 @@ do { \
111103
clear_c0_status(ST0_CU2); \
112104
} \
113105
__clear_software_ll_bit(); \
114-
if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU)) \
115-
__fpsave = FP_SAVE_SCALAR; \
116-
if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA)) \
117-
__fpsave = FP_SAVE_VECTOR; \
118106
if (cpu_has_userlocal) \
119107
write_c0_userlocal(task_thread_info(next)->tp_value); \
120108
__restore_watch(); \
121-
disable_msa(); \
122-
(last) = resume(prev, next, task_thread_info(next), __fpsave); \
109+
(last) = resume(prev, next, task_thread_info(next)); \
123110
} while (0)
124111

125112
#endif /* _ASM_SWITCH_TO_H */

arch/mips/kernel/r4k_switch.S

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#ifndef USE_ALTERNATE_RESUME_IMPL
3535
/*
3636
* task_struct *resume(task_struct *prev, task_struct *next,
37-
* struct thread_info *next_ti, s32 fp_save)
37+
* struct thread_info *next_ti)
3838
*/
3939
.align 5
4040
LEAF(resume)
@@ -43,45 +43,6 @@
4343
cpu_save_nonscratch a0
4444
LONG_S ra, THREAD_REG31(a0)
4545

46-
/*
47-
* Check whether we need to save any FP context. FP context is saved
48-
* iff the process has used the context with the scalar FPU or the MSA
49-
* ASE in the current time slice, as indicated by _TIF_USEDFPU and
50-
* _TIF_USEDMSA respectively. switch_to will have set fp_save
51-
* accordingly to an FP_SAVE_ enum value.
52-
*/
53-
beqz a3, 2f
54-
55-
/*
56-
* We do. Clear the saved CU1 bit for prev, such that next time it is
57-
* scheduled it will start in userland with the FPU disabled. If the
58-
* task uses the FPU then it will be enabled again via the do_cpu trap.
59-
* This allows us to lazily restore the FP context.
60-
*/
61-
PTR_L t3, TASK_THREAD_INFO(a0)
62-
LONG_L t0, ST_OFF(t3)
63-
li t1, ~ST0_CU1
64-
and t0, t0, t1
65-
LONG_S t0, ST_OFF(t3)
66-
67-
/* Check whether we're saving scalar or vector context. */
68-
bgtz a3, 1f
69-
70-
/* Save 128b MSA vector context + scalar FP control & status. */
71-
.set push
72-
SET_HARDFLOAT
73-
cfc1 t1, fcr31
74-
msa_save_all a0
75-
.set pop /* SET_HARDFLOAT */
76-
77-
sw t1, THREAD_FCR31(a0)
78-
b 2f
79-
80-
1: /* Save 32b/64b scalar FP context. */
81-
fpu_save_double a0 t0 t1 # c0_status passed in t0
82-
# clobbers t1
83-
2:
84-
8546
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
8647
PTR_LA t8, __stack_chk_guard
8748
LONG_L t9, TASK_STACK_CANARY(a1)

0 commit comments

Comments
 (0)