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 * task_struct *resume(task_struct *prev, task_struct *next, 33 * struct thread_info *next_ti, int usedfpu) 34 */ 35 .align 7 36 LEAF(resume) 37 .set arch=octeon 38 mfc0 t1, CP0_STATUS 39 LONG_S t1, THREAD_STATUS(a0) 40 cpu_save_nonscratch a0 41 LONG_S ra, THREAD_REG31(a0) 42 43#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 44 /* Check if we need to store CVMSEG state */ 45 mfc0 t0, $11,7 /* CvmMemCtl */ 46 bbit0 t0, 6, 3f /* Is user access enabled? */ 47 48 /* Store the CVMSEG state */ 49 /* Extract the size of CVMSEG */ 50 andi t0, 0x3f 51 /* Multiply * (cache line size/sizeof(long)/2) */ 52 sll t0, 7-LONGLOG-1 53 li t1, -32768 /* Base address of CVMSEG */ 54 LONG_ADDI t2, a0, THREAD_CVMSEG /* Where to store CVMSEG to */ 55 synciobdma 562: 57 .set noreorder 58 LONG_L t8, 0(t1) /* Load from CVMSEG */ 59 subu t0, 1 /* Decrement loop var */ 60 LONG_L t9, LONGSIZE(t1)/* Load from CVMSEG */ 61 LONG_ADDU t1, LONGSIZE*2 /* Increment loc in CVMSEG */ 62 LONG_S t8, 0(t2) /* Store CVMSEG to thread storage */ 63 LONG_ADDU t2, LONGSIZE*2 /* Increment loc in thread storage */ 64 bnez t0, 2b /* Loop until we've copied it all */ 65 LONG_S t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */ 66 .set reorder 67 68 /* Disable access to CVMSEG */ 69 mfc0 t0, $11,7 /* CvmMemCtl */ 70 xori t0, t0, 0x40 /* Bit 6 is CVMSEG user enable */ 71 mtc0 t0, $11,7 /* CvmMemCtl */ 72#endif 733: 74 75#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) 76 PTR_LA t8, __stack_chk_guard 77 LONG_L t9, TASK_STACK_CANARY(a1) 78 LONG_S t9, 0(t8) 79#endif 80 81 /* 82 * The order of restoring the registers takes care of the race 83 * updating $28, $29 and kernelsp without disabling ints. 84 */ 85 move $28, a2 86 cpu_restore_nonscratch a1 87 88#if (_THREAD_SIZE - 32) < 0x8000 89 PTR_ADDIU t0, $28, _THREAD_SIZE - 32 90#else 91 PTR_LI t0, _THREAD_SIZE - 32 92 PTR_ADDU t0, $28 93#endif 94 set_saved_sp t0, t1, t2 95 96 mfc0 t1, CP0_STATUS /* Do we really need this? */ 97 li a3, 0xff01 98 and t1, a3 99 LONG_L a2, THREAD_STATUS(a1) 100 nor a3, $0, a3 101 and a2, a3 102 or a2, t1 103 mtc0 a2, CP0_STATUS 104 move v0, a0 105 jr ra 106 END(resume) 107 108/* 109 * void octeon_cop2_save(struct octeon_cop2_state *a0) 110 */ 111 .align 7 112 LEAF(octeon_cop2_save) 113 114 dmfc0 t9, $9,7 /* CvmCtl register. */ 115 116 /* Save the COP2 CRC state */ 117 dmfc2 t0, 0x0201 118 dmfc2 t1, 0x0202 119 dmfc2 t2, 0x0200 120 sd t0, OCTEON_CP2_CRC_IV(a0) 121 sd t1, OCTEON_CP2_CRC_LENGTH(a0) 122 sd t2, OCTEON_CP2_CRC_POLY(a0) 123 /* Skip next instructions if CvmCtl[NODFA_CP2] set */ 124 bbit1 t9, 28, 1f 125 126 /* Save the LLM state */ 127 dmfc2 t0, 0x0402 128 dmfc2 t1, 0x040A 129 sd t0, OCTEON_CP2_LLM_DAT(a0) 130 sd t1, OCTEON_CP2_LLM_DAT+8(a0) 131 1321: bbit1 t9, 26, 3f /* done if CvmCtl[NOCRYPTO] set */ 133 134 /* Save the COP2 crypto state */ 135 /* this part is mostly common to both pass 1 and later revisions */ 136 dmfc2 t0, 0x0084 137 dmfc2 t1, 0x0080 138 dmfc2 t2, 0x0081 139 dmfc2 t3, 0x0082 140 sd t0, OCTEON_CP2_3DES_IV(a0) 141 dmfc2 t0, 0x0088 142 sd t1, OCTEON_CP2_3DES_KEY(a0) 143 dmfc2 t1, 0x0111 /* only necessary for pass 1 */ 144 sd t2, OCTEON_CP2_3DES_KEY+8(a0) 145 dmfc2 t2, 0x0102 146 sd t3, OCTEON_CP2_3DES_KEY+16(a0) 147 dmfc2 t3, 0x0103 148 sd t0, OCTEON_CP2_3DES_RESULT(a0) 149 dmfc2 t0, 0x0104 150 sd t1, OCTEON_CP2_AES_INP0(a0) /* only necessary for pass 1 */ 151 dmfc2 t1, 0x0105 152 sd t2, OCTEON_CP2_AES_IV(a0) 153 dmfc2 t2, 0x0106 154 sd t3, OCTEON_CP2_AES_IV+8(a0) 155 dmfc2 t3, 0x0107 156 sd t0, OCTEON_CP2_AES_KEY(a0) 157 dmfc2 t0, 0x0110 158 sd t1, OCTEON_CP2_AES_KEY+8(a0) 159 dmfc2 t1, 0x0100 160 sd t2, OCTEON_CP2_AES_KEY+16(a0) 161 dmfc2 t2, 0x0101 162 sd t3, OCTEON_CP2_AES_KEY+24(a0) 163 mfc0 t3, $15,0 /* Get the processor ID register */ 164 sd t0, OCTEON_CP2_AES_KEYLEN(a0) 165 li t0, 0x000d0000 /* This is the processor ID of Octeon Pass1 */ 166 sd t1, OCTEON_CP2_AES_RESULT(a0) 167 sd t2, OCTEON_CP2_AES_RESULT+8(a0) 168 /* Skip to the Pass1 version of the remainder of the COP2 state */ 169 beq t3, t0, 2f 170 171 /* the non-pass1 state when !CvmCtl[NOCRYPTO] */ 172 dmfc2 t1, 0x0240 173 dmfc2 t2, 0x0241 174 dmfc2 t3, 0x0242 175 dmfc2 t0, 0x0243 176 sd t1, OCTEON_CP2_HSH_DATW(a0) 177 dmfc2 t1, 0x0244 178 sd t2, OCTEON_CP2_HSH_DATW+8(a0) 179 dmfc2 t2, 0x0245 180 sd t3, OCTEON_CP2_HSH_DATW+16(a0) 181 dmfc2 t3, 0x0246 182 sd t0, OCTEON_CP2_HSH_DATW+24(a0) 183 dmfc2 t0, 0x0247 184 sd t1, OCTEON_CP2_HSH_DATW+32(a0) 185 dmfc2 t1, 0x0248 186 sd t2, OCTEON_CP2_HSH_DATW+40(a0) 187 dmfc2 t2, 0x0249 188 sd t3, OCTEON_CP2_HSH_DATW+48(a0) 189 dmfc2 t3, 0x024A 190 sd t0, OCTEON_CP2_HSH_DATW+56(a0) 191 dmfc2 t0, 0x024B 192 sd t1, OCTEON_CP2_HSH_DATW+64(a0) 193 dmfc2 t1, 0x024C 194 sd t2, OCTEON_CP2_HSH_DATW+72(a0) 195 dmfc2 t2, 0x024D 196 sd t3, OCTEON_CP2_HSH_DATW+80(a0) 197 dmfc2 t3, 0x024E 198 sd t0, OCTEON_CP2_HSH_DATW+88(a0) 199 dmfc2 t0, 0x0250 200 sd t1, OCTEON_CP2_HSH_DATW+96(a0) 201 dmfc2 t1, 0x0251 202 sd t2, OCTEON_CP2_HSH_DATW+104(a0) 203 dmfc2 t2, 0x0252 204 sd t3, OCTEON_CP2_HSH_DATW+112(a0) 205 dmfc2 t3, 0x0253 206 sd t0, OCTEON_CP2_HSH_IVW(a0) 207 dmfc2 t0, 0x0254 208 sd t1, OCTEON_CP2_HSH_IVW+8(a0) 209 dmfc2 t1, 0x0255 210 sd t2, OCTEON_CP2_HSH_IVW+16(a0) 211 dmfc2 t2, 0x0256 212 sd t3, OCTEON_CP2_HSH_IVW+24(a0) 213 dmfc2 t3, 0x0257 214 sd t0, OCTEON_CP2_HSH_IVW+32(a0) 215 dmfc2 t0, 0x0258 216 sd t1, OCTEON_CP2_HSH_IVW+40(a0) 217 dmfc2 t1, 0x0259 218 sd t2, OCTEON_CP2_HSH_IVW+48(a0) 219 dmfc2 t2, 0x025E 220 sd t3, OCTEON_CP2_HSH_IVW+56(a0) 221 dmfc2 t3, 0x025A 222 sd t0, OCTEON_CP2_GFM_MULT(a0) 223 dmfc2 t0, 0x025B 224 sd t1, OCTEON_CP2_GFM_MULT+8(a0) 225 sd t2, OCTEON_CP2_GFM_POLY(a0) 226 sd t3, OCTEON_CP2_GFM_RESULT(a0) 227 sd t0, OCTEON_CP2_GFM_RESULT+8(a0) 228 jr ra 229 2302: /* pass 1 special stuff when !CvmCtl[NOCRYPTO] */ 231 dmfc2 t3, 0x0040 232 dmfc2 t0, 0x0041 233 dmfc2 t1, 0x0042 234 dmfc2 t2, 0x0043 235 sd t3, OCTEON_CP2_HSH_DATW(a0) 236 dmfc2 t3, 0x0044 237 sd t0, OCTEON_CP2_HSH_DATW+8(a0) 238 dmfc2 t0, 0x0045 239 sd t1, OCTEON_CP2_HSH_DATW+16(a0) 240 dmfc2 t1, 0x0046 241 sd t2, OCTEON_CP2_HSH_DATW+24(a0) 242 dmfc2 t2, 0x0048 243 sd t3, OCTEON_CP2_HSH_DATW+32(a0) 244 dmfc2 t3, 0x0049 245 sd t0, OCTEON_CP2_HSH_DATW+40(a0) 246 dmfc2 t0, 0x004A 247 sd t1, OCTEON_CP2_HSH_DATW+48(a0) 248 sd t2, OCTEON_CP2_HSH_IVW(a0) 249 sd t3, OCTEON_CP2_HSH_IVW+8(a0) 250 sd t0, OCTEON_CP2_HSH_IVW+16(a0) 251 2523: /* pass 1 or CvmCtl[NOCRYPTO] set */ 253 jr ra 254 END(octeon_cop2_save) 255 256/* 257 * void octeon_cop2_restore(struct octeon_cop2_state *a0) 258 */ 259 .align 7 260 .set push 261 .set noreorder 262 LEAF(octeon_cop2_restore) 263 /* First cache line was prefetched before the call */ 264 pref 4, 128(a0) 265 dmfc0 t9, $9,7 /* CvmCtl register. */ 266 267 pref 4, 256(a0) 268 ld t0, OCTEON_CP2_CRC_IV(a0) 269 pref 4, 384(a0) 270 ld t1, OCTEON_CP2_CRC_LENGTH(a0) 271 ld t2, OCTEON_CP2_CRC_POLY(a0) 272 273 /* Restore the COP2 CRC state */ 274 dmtc2 t0, 0x0201 275 dmtc2 t1, 0x1202 276 bbit1 t9, 28, 2f /* Skip LLM if CvmCtl[NODFA_CP2] is set */ 277 dmtc2 t2, 0x4200 278 279 /* Restore the LLM state */ 280 ld t0, OCTEON_CP2_LLM_DAT(a0) 281 ld t1, OCTEON_CP2_LLM_DAT+8(a0) 282 dmtc2 t0, 0x0402 283 dmtc2 t1, 0x040A 284 2852: 286 bbit1 t9, 26, done_restore /* done if CvmCtl[NOCRYPTO] set */ 287 nop 288 289 /* Restore the COP2 crypto state common to pass 1 and pass 2 */ 290 ld t0, OCTEON_CP2_3DES_IV(a0) 291 ld t1, OCTEON_CP2_3DES_KEY(a0) 292 ld t2, OCTEON_CP2_3DES_KEY+8(a0) 293 dmtc2 t0, 0x0084 294 ld t0, OCTEON_CP2_3DES_KEY+16(a0) 295 dmtc2 t1, 0x0080 296 ld t1, OCTEON_CP2_3DES_RESULT(a0) 297 dmtc2 t2, 0x0081 298 ld t2, OCTEON_CP2_AES_INP0(a0) /* only really needed for pass 1 */ 299 dmtc2 t0, 0x0082 300 ld t0, OCTEON_CP2_AES_IV(a0) 301 dmtc2 t1, 0x0098 302 ld t1, OCTEON_CP2_AES_IV+8(a0) 303 dmtc2 t2, 0x010A /* only really needed for pass 1 */ 304 ld t2, OCTEON_CP2_AES_KEY(a0) 305 dmtc2 t0, 0x0102 306 ld t0, OCTEON_CP2_AES_KEY+8(a0) 307 dmtc2 t1, 0x0103 308 ld t1, OCTEON_CP2_AES_KEY+16(a0) 309 dmtc2 t2, 0x0104 310 ld t2, OCTEON_CP2_AES_KEY+24(a0) 311 dmtc2 t0, 0x0105 312 ld t0, OCTEON_CP2_AES_KEYLEN(a0) 313 dmtc2 t1, 0x0106 314 ld t1, OCTEON_CP2_AES_RESULT(a0) 315 dmtc2 t2, 0x0107 316 ld t2, OCTEON_CP2_AES_RESULT+8(a0) 317 mfc0 t3, $15,0 /* Get the processor ID register */ 318 dmtc2 t0, 0x0110 319 li t0, 0x000d0000 /* This is the processor ID of Octeon Pass1 */ 320 dmtc2 t1, 0x0100 321 bne t0, t3, 3f /* Skip the next stuff for non-pass1 */ 322 dmtc2 t2, 0x0101 323 324 /* this code is specific for pass 1 */ 325 ld t0, OCTEON_CP2_HSH_DATW(a0) 326 ld t1, OCTEON_CP2_HSH_DATW+8(a0) 327 ld t2, OCTEON_CP2_HSH_DATW+16(a0) 328 dmtc2 t0, 0x0040 329 ld t0, OCTEON_CP2_HSH_DATW+24(a0) 330 dmtc2 t1, 0x0041 331 ld t1, OCTEON_CP2_HSH_DATW+32(a0) 332 dmtc2 t2, 0x0042 333 ld t2, OCTEON_CP2_HSH_DATW+40(a0) 334 dmtc2 t0, 0x0043 335 ld t0, OCTEON_CP2_HSH_DATW+48(a0) 336 dmtc2 t1, 0x0044 337 ld t1, OCTEON_CP2_HSH_IVW(a0) 338 dmtc2 t2, 0x0045 339 ld t2, OCTEON_CP2_HSH_IVW+8(a0) 340 dmtc2 t0, 0x0046 341 ld t0, OCTEON_CP2_HSH_IVW+16(a0) 342 dmtc2 t1, 0x0048 343 dmtc2 t2, 0x0049 344 b done_restore /* unconditional branch */ 345 dmtc2 t0, 0x004A 346 3473: /* this is post-pass1 code */ 348 ld t2, OCTEON_CP2_HSH_DATW(a0) 349 ld t0, OCTEON_CP2_HSH_DATW+8(a0) 350 ld t1, OCTEON_CP2_HSH_DATW+16(a0) 351 dmtc2 t2, 0x0240 352 ld t2, OCTEON_CP2_HSH_DATW+24(a0) 353 dmtc2 t0, 0x0241 354 ld t0, OCTEON_CP2_HSH_DATW+32(a0) 355 dmtc2 t1, 0x0242 356 ld t1, OCTEON_CP2_HSH_DATW+40(a0) 357 dmtc2 t2, 0x0243 358 ld t2, OCTEON_CP2_HSH_DATW+48(a0) 359 dmtc2 t0, 0x0244 360 ld t0, OCTEON_CP2_HSH_DATW+56(a0) 361 dmtc2 t1, 0x0245 362 ld t1, OCTEON_CP2_HSH_DATW+64(a0) 363 dmtc2 t2, 0x0246 364 ld t2, OCTEON_CP2_HSH_DATW+72(a0) 365 dmtc2 t0, 0x0247 366 ld t0, OCTEON_CP2_HSH_DATW+80(a0) 367 dmtc2 t1, 0x0248 368 ld t1, OCTEON_CP2_HSH_DATW+88(a0) 369 dmtc2 t2, 0x0249 370 ld t2, OCTEON_CP2_HSH_DATW+96(a0) 371 dmtc2 t0, 0x024A 372 ld t0, OCTEON_CP2_HSH_DATW+104(a0) 373 dmtc2 t1, 0x024B 374 ld t1, OCTEON_CP2_HSH_DATW+112(a0) 375 dmtc2 t2, 0x024C 376 ld t2, OCTEON_CP2_HSH_IVW(a0) 377 dmtc2 t0, 0x024D 378 ld t0, OCTEON_CP2_HSH_IVW+8(a0) 379 dmtc2 t1, 0x024E 380 ld t1, OCTEON_CP2_HSH_IVW+16(a0) 381 dmtc2 t2, 0x0250 382 ld t2, OCTEON_CP2_HSH_IVW+24(a0) 383 dmtc2 t0, 0x0251 384 ld t0, OCTEON_CP2_HSH_IVW+32(a0) 385 dmtc2 t1, 0x0252 386 ld t1, OCTEON_CP2_HSH_IVW+40(a0) 387 dmtc2 t2, 0x0253 388 ld t2, OCTEON_CP2_HSH_IVW+48(a0) 389 dmtc2 t0, 0x0254 390 ld t0, OCTEON_CP2_HSH_IVW+56(a0) 391 dmtc2 t1, 0x0255 392 ld t1, OCTEON_CP2_GFM_MULT(a0) 393 dmtc2 t2, 0x0256 394 ld t2, OCTEON_CP2_GFM_MULT+8(a0) 395 dmtc2 t0, 0x0257 396 ld t0, OCTEON_CP2_GFM_POLY(a0) 397 dmtc2 t1, 0x0258 398 ld t1, OCTEON_CP2_GFM_RESULT(a0) 399 dmtc2 t2, 0x0259 400 ld t2, OCTEON_CP2_GFM_RESULT+8(a0) 401 dmtc2 t0, 0x025E 402 dmtc2 t1, 0x025A 403 dmtc2 t2, 0x025B 404 405done_restore: 406 jr ra 407 nop 408 END(octeon_cop2_restore) 409 .set pop 410 411/* 412 * void octeon_mult_save() 413 * sp is assumed to point to a struct pt_regs 414 * 415 * NOTE: This is called in SAVE_SOME in stackframe.h. It can only 416 * safely modify k0 and k1. 417 */ 418 .align 7 419 .set push 420 .set noreorder 421 LEAF(octeon_mult_save) 422 dmfc0 k0, $9,7 /* CvmCtl register. */ 423 bbit1 k0, 27, 1f /* Skip CvmCtl[NOMUL] */ 424 nop 425 426 /* Save the multiplier state */ 427 v3mulu k0, $0, $0 428 v3mulu k1, $0, $0 429 sd k0, PT_MTP(sp) /* PT_MTP has P0 */ 430 v3mulu k0, $0, $0 431 sd k1, PT_MTP+8(sp) /* PT_MTP+8 has P1 */ 432 ori k1, $0, 1 433 v3mulu k1, k1, $0 434 sd k0, PT_MTP+16(sp) /* PT_MTP+16 has P2 */ 435 v3mulu k0, $0, $0 436 sd k1, PT_MPL(sp) /* PT_MPL has MPL0 */ 437 v3mulu k1, $0, $0 438 sd k0, PT_MPL+8(sp) /* PT_MPL+8 has MPL1 */ 439 jr ra 440 sd k1, PT_MPL+16(sp) /* PT_MPL+16 has MPL2 */ 441 4421: /* Resume here if CvmCtl[NOMUL] */ 443 jr ra 444 END(octeon_mult_save) 445 .set pop 446 447/* 448 * void octeon_mult_restore() 449 * sp is assumed to point to a struct pt_regs 450 * 451 * NOTE: This is called in RESTORE_SOME in stackframe.h. 452 */ 453 .align 7 454 .set push 455 .set noreorder 456 LEAF(octeon_mult_restore) 457 dmfc0 k1, $9,7 /* CvmCtl register. */ 458 ld v0, PT_MPL(sp) /* MPL0 */ 459 ld v1, PT_MPL+8(sp) /* MPL1 */ 460 ld k0, PT_MPL+16(sp) /* MPL2 */ 461 bbit1 k1, 27, 1f /* Skip CvmCtl[NOMUL] */ 462 /* Normally falls through, so no time wasted here */ 463 nop 464 465 /* Restore the multiplier state */ 466 ld k1, PT_MTP+16(sp) /* P2 */ 467 MTM0 v0 /* MPL0 */ 468 ld v0, PT_MTP+8(sp) /* P1 */ 469 MTM1 v1 /* MPL1 */ 470 ld v1, PT_MTP(sp) /* P0 */ 471 MTM2 k0 /* MPL2 */ 472 MTP2 k1 /* P2 */ 473 MTP1 v0 /* P1 */ 474 jr ra 475 MTP0 v1 /* P0 */ 476 4771: /* Resume here if CvmCtl[NOMUL] */ 478 jr ra 479 nop 480 END(octeon_mult_restore) 481 .set pop 482