1/* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 1994, 1995, 1996, 1998, 1999, 2002, 2003 Ralf Baechle 7 * Copyright (C) 1996 David S. Miller (davem@davemloft.net) 8 * Copyright (C) 1994, 1995, 1996, by Andreas Busse 9 * Copyright (C) 1999 Silicon Graphics, Inc. 10 * Copyright (C) 2000 MIPS Technologies, Inc. 11 * written by Carsten Langgaard, carstenl@mips.com 12 */ 13#include <asm/asm.h> 14#include <asm/cachectl.h> 15#include <asm/fpregdef.h> 16#include <asm/mipsregs.h> 17#include <asm/asm-offsets.h> 18#include <asm/pgtable-bits.h> 19#include <asm/regdef.h> 20#include <asm/stackframe.h> 21#include <asm/thread_info.h> 22 23#include <asm/asmmacro.h> 24 25/* 26 * Offset to the current process status flags, the first 32 bytes of the 27 * stack are not used. 28 */ 29#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) 30 31/* 32 * FPU context is saved iff the process has used it's FPU in the current 33 * time slice as indicated by _TIF_USEDFPU. In any case, the CU1 bit for user 34 * space STATUS register should be 0, so that a process *always* starts its 35 * userland with FPU disabled after each context switch. 36 * 37 * FPU will be enabled as soon as the process accesses FPU again, through 38 * do_cpu() trap. 39 */ 40 41/* 42 * task_struct *resume(task_struct *prev, task_struct *next, 43 * struct thread_info *next_ti, int usedfpu) 44 */ 45 .align 5 46 LEAF(resume) 47 mfc0 t1, CP0_STATUS 48 LONG_S t1, THREAD_STATUS(a0) 49 cpu_save_nonscratch a0 50 LONG_S ra, THREAD_REG31(a0) 51 52 /* 53 * check if we need to save FPU registers 54 */ 55 56 beqz a3, 1f 57 58 PTR_L t3, TASK_THREAD_INFO(a0) 59 /* 60 * clear saved user stack CU1 bit 61 */ 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 fpu_save_double a0 t0 t1 # c0_status passed in t0 68 # clobbers t1 691: 70 71 /* 72 * The order of restoring the registers takes care of the race 73 * updating $28, $29 and kernelsp without disabling ints. 74 */ 75 move $28, a2 76 cpu_restore_nonscratch a1 77 78 PTR_ADDU t0, $28, _THREAD_SIZE - 32 79 set_saved_sp t0, t1, t2 80#ifdef CONFIG_MIPS_MT_SMTC 81 /* Read-modify-writes of Status must be atomic on a VPE */ 82 mfc0 t2, CP0_TCSTATUS 83 ori t1, t2, TCSTATUS_IXMT 84 mtc0 t1, CP0_TCSTATUS 85 andi t2, t2, TCSTATUS_IXMT 86 _ehb 87 DMT 8 # dmt t0 88 move t1,ra 89 jal mips_ihb 90 move ra,t1 91#endif /* CONFIG_MIPS_MT_SMTC */ 92 mfc0 t1, CP0_STATUS /* Do we really need this? */ 93 li a3, 0xff01 94 and t1, a3 95 LONG_L a2, THREAD_STATUS(a1) 96 nor a3, $0, a3 97 and a2, a3 98 or a2, t1 99 mtc0 a2, CP0_STATUS 100#ifdef CONFIG_MIPS_MT_SMTC 101 _ehb 102 andi t0, t0, VPECONTROL_TE 103 beqz t0, 1f 104 emt 1051: 106 mfc0 t1, CP0_TCSTATUS 107 xori t1, t1, TCSTATUS_IXMT 108 or t1, t1, t2 109 mtc0 t1, CP0_TCSTATUS 110 _ehb 111#endif /* CONFIG_MIPS_MT_SMTC */ 112 move v0, a0 113 jr ra 114 END(resume) 115 116/* 117 * Save a thread's fp context. 118 */ 119LEAF(_save_fp) 120#ifdef CONFIG_64BIT 121 mfc0 t0, CP0_STATUS 122#endif 123 fpu_save_double a0 t0 t1 # clobbers t1 124 jr ra 125 END(_save_fp) 126 127/* 128 * Restore a thread's fp context. 129 */ 130LEAF(_restore_fp) 131#ifdef CONFIG_64BIT 132 mfc0 t0, CP0_STATUS 133#endif 134 fpu_restore_double a0 t0 t1 # clobbers t1 135 jr ra 136 END(_restore_fp) 137 138/* 139 * Load the FPU with signalling NANS. This bit pattern we're using has 140 * the property that no matter whether considered as single or as double 141 * precision represents signaling NANS. 142 * 143 * We initialize fcr31 to rounding to nearest, no exceptions. 144 */ 145 146#define FPU_DEFAULT 0x00000000 147 148LEAF(_init_fpu) 149#ifdef CONFIG_MIPS_MT_SMTC 150 /* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */ 151 mfc0 t0, CP0_TCSTATUS 152 /* Bit position is the same for Status, TCStatus */ 153 li t1, ST0_CU1 154 or t0, t1 155 mtc0 t0, CP0_TCSTATUS 156#else /* Normal MIPS CU1 enable */ 157 mfc0 t0, CP0_STATUS 158 li t1, ST0_CU1 159 or t0, t1 160 mtc0 t0, CP0_STATUS 161#endif /* CONFIG_MIPS_MT_SMTC */ 162 enable_fpu_hazard 163 164 li t1, FPU_DEFAULT 165 ctc1 t1, fcr31 166 167 li t1, -1 # SNaN 168 169#ifdef CONFIG_64BIT 170 sll t0, t0, 5 171 bgez t0, 1f # 16 / 32 register mode? 172 173 dmtc1 t1, $f1 174 dmtc1 t1, $f3 175 dmtc1 t1, $f5 176 dmtc1 t1, $f7 177 dmtc1 t1, $f9 178 dmtc1 t1, $f11 179 dmtc1 t1, $f13 180 dmtc1 t1, $f15 181 dmtc1 t1, $f17 182 dmtc1 t1, $f19 183 dmtc1 t1, $f21 184 dmtc1 t1, $f23 185 dmtc1 t1, $f25 186 dmtc1 t1, $f27 187 dmtc1 t1, $f29 188 dmtc1 t1, $f31 1891: 190#endif 191 192#ifdef CONFIG_CPU_MIPS32 193 mtc1 t1, $f0 194 mtc1 t1, $f1 195 mtc1 t1, $f2 196 mtc1 t1, $f3 197 mtc1 t1, $f4 198 mtc1 t1, $f5 199 mtc1 t1, $f6 200 mtc1 t1, $f7 201 mtc1 t1, $f8 202 mtc1 t1, $f9 203 mtc1 t1, $f10 204 mtc1 t1, $f11 205 mtc1 t1, $f12 206 mtc1 t1, $f13 207 mtc1 t1, $f14 208 mtc1 t1, $f15 209 mtc1 t1, $f16 210 mtc1 t1, $f17 211 mtc1 t1, $f18 212 mtc1 t1, $f19 213 mtc1 t1, $f20 214 mtc1 t1, $f21 215 mtc1 t1, $f22 216 mtc1 t1, $f23 217 mtc1 t1, $f24 218 mtc1 t1, $f25 219 mtc1 t1, $f26 220 mtc1 t1, $f27 221 mtc1 t1, $f28 222 mtc1 t1, $f29 223 mtc1 t1, $f30 224 mtc1 t1, $f31 225#else 226 .set mips3 227 dmtc1 t1, $f0 228 dmtc1 t1, $f2 229 dmtc1 t1, $f4 230 dmtc1 t1, $f6 231 dmtc1 t1, $f8 232 dmtc1 t1, $f10 233 dmtc1 t1, $f12 234 dmtc1 t1, $f14 235 dmtc1 t1, $f16 236 dmtc1 t1, $f18 237 dmtc1 t1, $f20 238 dmtc1 t1, $f22 239 dmtc1 t1, $f24 240 dmtc1 t1, $f26 241 dmtc1 t1, $f28 242 dmtc1 t1, $f30 243#endif 244 jr ra 245 END(_init_fpu) 246