0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef _ASM_SWITCH_TO_H
0013 #define _ASM_SWITCH_TO_H
0014
0015 #include <asm/cpu-features.h>
0016 #include <asm/watch.h>
0017 #include <asm/dsp.h>
0018 #include <asm/cop2.h>
0019 #include <asm/fpu.h>
0020
0021 struct task_struct;
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 extern asmlinkage struct task_struct *resume(struct task_struct *prev,
0033 struct task_struct *next, struct thread_info *next_ti);
0034
0035 extern unsigned int ll_bit;
0036 extern struct task_struct *ll_task;
0037
0038 #ifdef CONFIG_MIPS_MT_FPAFF
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 #define __mips_mt_fpaff_switch_to(prev) \
0053 do { \
0054 struct thread_info *__prev_ti = task_thread_info(prev); \
0055 \
0056 if (cpu_has_fpu && \
0057 test_ti_thread_flag(__prev_ti, TIF_FPUBOUND) && \
0058 (!(KSTK_STATUS(prev) & ST0_CU1))) { \
0059 clear_ti_thread_flag(__prev_ti, TIF_FPUBOUND); \
0060 prev->cpus_mask = prev->thread.user_cpus_allowed; \
0061 } \
0062 next->thread.emulated_fp = 0; \
0063 } while(0)
0064
0065 #else
0066 #define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
0067 #endif
0068
0069
0070
0071
0072
0073 #define __clear_r5_hw_ll_bit() do { \
0074 if (cpu_has_mips_r5 || cpu_has_mips_r6) \
0075 write_c0_lladdr(0); \
0076 } while (0)
0077
0078 #define __clear_software_ll_bit() do { \
0079 if (!__builtin_constant_p(cpu_has_llsc) || !cpu_has_llsc) \
0080 ll_bit = 0; \
0081 } while (0)
0082
0083
0084
0085
0086
0087 #ifdef CONFIG_MIPS_FP_SUPPORT
0088 # define __sanitize_fcr31(next) \
0089 do { \
0090 unsigned long fcr31 = mask_fcr31_x(next->thread.fpu.fcr31); \
0091 void __user *pc; \
0092 \
0093 if (unlikely(fcr31)) { \
0094 pc = (void __user *)task_pt_regs(next)->cp0_epc; \
0095 next->thread.fpu.fcr31 &= ~fcr31; \
0096 force_fcr31_sig(fcr31, pc, next); \
0097 } \
0098 } while (0)
0099 #else
0100 # define __sanitize_fcr31(next)
0101 #endif
0102
0103
0104
0105
0106
0107
0108
0109 #define switch_to(prev, next, last) \
0110 do { \
0111 __mips_mt_fpaff_switch_to(prev); \
0112 lose_fpu_inatomic(1, prev); \
0113 if (tsk_used_math(next)) \
0114 __sanitize_fcr31(next); \
0115 if (cpu_has_dsp) { \
0116 __save_dsp(prev); \
0117 __restore_dsp(next); \
0118 } \
0119 if (cop2_present) { \
0120 u32 status = read_c0_status(); \
0121 \
0122 set_c0_status(ST0_CU2); \
0123 if ((KSTK_STATUS(prev) & ST0_CU2)) { \
0124 if (cop2_lazy_restore) \
0125 KSTK_STATUS(prev) &= ~ST0_CU2; \
0126 cop2_save(prev); \
0127 } \
0128 if (KSTK_STATUS(next) & ST0_CU2 && \
0129 !cop2_lazy_restore) { \
0130 cop2_restore(next); \
0131 } \
0132 write_c0_status(status); \
0133 } \
0134 __clear_r5_hw_ll_bit(); \
0135 __clear_software_ll_bit(); \
0136 if (cpu_has_userlocal) \
0137 write_c0_userlocal(task_thread_info(next)->tp_value); \
0138 __restore_watch(next); \
0139 (last) = resume(prev, next, task_thread_info(next)); \
0140 } while (0)
0141
0142 #endif