diff options
Diffstat (limited to 'include/asm-mips/stackframe.h')
| -rw-r--r-- | include/asm-mips/stackframe.h | 187 |
1 files changed, 184 insertions, 3 deletions
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index 2acf3e844f00..c4856a874965 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h | |||
| @@ -14,9 +14,14 @@ | |||
| 14 | #include <linux/threads.h> | 14 | #include <linux/threads.h> |
| 15 | 15 | ||
| 16 | #include <asm/asm.h> | 16 | #include <asm/asm.h> |
| 17 | #include <asm/asmmacro.h> | ||
| 17 | #include <asm/mipsregs.h> | 18 | #include <asm/mipsregs.h> |
| 18 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> |
| 19 | 20 | ||
| 21 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 22 | #include <asm/mipsmtregs.h> | ||
| 23 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 24 | |||
| 20 | .macro SAVE_AT | 25 | .macro SAVE_AT |
| 21 | .set push | 26 | .set push |
| 22 | .set noat | 27 | .set noat |
| @@ -57,13 +62,30 @@ | |||
| 57 | #ifdef CONFIG_SMP | 62 | #ifdef CONFIG_SMP |
| 58 | .macro get_saved_sp /* SMP variation */ | 63 | .macro get_saved_sp /* SMP variation */ |
| 59 | #ifdef CONFIG_32BIT | 64 | #ifdef CONFIG_32BIT |
| 65 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 66 | .set mips32 | ||
| 67 | mfc0 k0, CP0_TCBIND; | ||
| 68 | .set mips0 | ||
| 69 | lui k1, %hi(kernelsp) | ||
| 70 | srl k0, k0, 19 | ||
| 71 | /* No need to shift down and up to clear bits 0-1 */ | ||
| 72 | #else | ||
| 60 | mfc0 k0, CP0_CONTEXT | 73 | mfc0 k0, CP0_CONTEXT |
| 61 | lui k1, %hi(kernelsp) | 74 | lui k1, %hi(kernelsp) |
| 62 | srl k0, k0, 23 | 75 | srl k0, k0, 23 |
| 76 | #endif | ||
| 63 | addu k1, k0 | 77 | addu k1, k0 |
| 64 | LONG_L k1, %lo(kernelsp)(k1) | 78 | LONG_L k1, %lo(kernelsp)(k1) |
| 65 | #endif | 79 | #endif |
| 66 | #ifdef CONFIG_64BIT | 80 | #ifdef CONFIG_64BIT |
| 81 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 82 | .set mips64 | ||
| 83 | mfc0 k0, CP0_TCBIND; | ||
| 84 | .set mips0 | ||
| 85 | lui k0, %highest(kernelsp) | ||
| 86 | dsrl k1, 19 | ||
| 87 | /* No need to shift down and up to clear bits 0-2 */ | ||
| 88 | #else | ||
| 67 | MFC0 k1, CP0_CONTEXT | 89 | MFC0 k1, CP0_CONTEXT |
| 68 | lui k0, %highest(kernelsp) | 90 | lui k0, %highest(kernelsp) |
| 69 | dsrl k1, 23 | 91 | dsrl k1, 23 |
| @@ -71,20 +93,31 @@ | |||
| 71 | dsll k0, k0, 16 | 93 | dsll k0, k0, 16 |
| 72 | daddiu k0, %hi(kernelsp) | 94 | daddiu k0, %hi(kernelsp) |
| 73 | dsll k0, k0, 16 | 95 | dsll k0, k0, 16 |
| 96 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 74 | daddu k1, k1, k0 | 97 | daddu k1, k1, k0 |
| 75 | LONG_L k1, %lo(kernelsp)(k1) | 98 | LONG_L k1, %lo(kernelsp)(k1) |
| 76 | #endif | 99 | #endif /* CONFIG_64BIT */ |
| 77 | .endm | 100 | .endm |
| 78 | 101 | ||
| 79 | .macro set_saved_sp stackp temp temp2 | 102 | .macro set_saved_sp stackp temp temp2 |
| 80 | #ifdef CONFIG_32BIT | 103 | #ifdef CONFIG_32BIT |
| 104 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 105 | mfc0 \temp, CP0_TCBIND | ||
| 106 | srl \temp, 19 | ||
| 107 | #else | ||
| 81 | mfc0 \temp, CP0_CONTEXT | 108 | mfc0 \temp, CP0_CONTEXT |
| 82 | srl \temp, 23 | 109 | srl \temp, 23 |
| 83 | #endif | 110 | #endif |
| 111 | #endif | ||
| 84 | #ifdef CONFIG_64BIT | 112 | #ifdef CONFIG_64BIT |
| 113 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 114 | mfc0 \temp, CP0_TCBIND | ||
| 115 | dsrl \temp, 19 | ||
| 116 | #else | ||
| 85 | MFC0 \temp, CP0_CONTEXT | 117 | MFC0 \temp, CP0_CONTEXT |
| 86 | dsrl \temp, 23 | 118 | dsrl \temp, 23 |
| 87 | #endif | 119 | #endif |
| 120 | #endif | ||
| 88 | LONG_S \stackp, kernelsp(\temp) | 121 | LONG_S \stackp, kernelsp(\temp) |
| 89 | .endm | 122 | .endm |
| 90 | #else | 123 | #else |
| @@ -122,10 +155,25 @@ | |||
| 122 | PTR_SUBU sp, k1, PT_SIZE | 155 | PTR_SUBU sp, k1, PT_SIZE |
| 123 | LONG_S k0, PT_R29(sp) | 156 | LONG_S k0, PT_R29(sp) |
| 124 | LONG_S $3, PT_R3(sp) | 157 | LONG_S $3, PT_R3(sp) |
| 158 | /* | ||
| 159 | * You might think that you don't need to save $0, | ||
| 160 | * but the FPU emulator and gdb remote debug stub | ||
| 161 | * need it to operate correctly | ||
| 162 | */ | ||
| 125 | LONG_S $0, PT_R0(sp) | 163 | LONG_S $0, PT_R0(sp) |
| 126 | mfc0 v1, CP0_STATUS | 164 | mfc0 v1, CP0_STATUS |
| 127 | LONG_S $2, PT_R2(sp) | 165 | LONG_S $2, PT_R2(sp) |
| 128 | LONG_S v1, PT_STATUS(sp) | 166 | LONG_S v1, PT_STATUS(sp) |
| 167 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 168 | /* | ||
| 169 | * Ideally, these instructions would be shuffled in | ||
| 170 | * to cover the pipeline delay. | ||
| 171 | */ | ||
| 172 | .set mips32 | ||
| 173 | mfc0 v1, CP0_TCSTATUS | ||
| 174 | .set mips0 | ||
| 175 | LONG_S v1, PT_TCSTATUS(sp) | ||
| 176 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 129 | LONG_S $4, PT_R4(sp) | 177 | LONG_S $4, PT_R4(sp) |
| 130 | mfc0 v1, CP0_CAUSE | 178 | mfc0 v1, CP0_CAUSE |
| 131 | LONG_S $5, PT_R5(sp) | 179 | LONG_S $5, PT_R5(sp) |
| @@ -234,14 +282,36 @@ | |||
| 234 | .endm | 282 | .endm |
| 235 | 283 | ||
| 236 | #else | 284 | #else |
| 285 | /* | ||
| 286 | * For SMTC kernel, global IE should be left set, and interrupts | ||
| 287 | * controlled exclusively via IXMT. | ||
| 288 | */ | ||
| 237 | 289 | ||
| 290 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 291 | #define STATMASK 0x1e | ||
| 292 | #else | ||
| 293 | #define STATMASK 0x1f | ||
| 294 | #endif | ||
| 238 | .macro RESTORE_SOME | 295 | .macro RESTORE_SOME |
| 239 | .set push | 296 | .set push |
| 240 | .set reorder | 297 | .set reorder |
| 241 | .set noat | 298 | .set noat |
| 299 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 300 | .set mips32r2 | ||
| 301 | /* | ||
| 302 | * This may not really be necessary if ints are already | ||
| 303 | * inhibited here. | ||
| 304 | */ | ||
| 305 | mfc0 v0, CP0_TCSTATUS | ||
| 306 | ori v0, TCSTATUS_IXMT | ||
| 307 | mtc0 v0, CP0_TCSTATUS | ||
| 308 | ehb | ||
| 309 | DMT 5 # dmt a1 | ||
| 310 | jal mips_ihb | ||
| 311 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 242 | mfc0 a0, CP0_STATUS | 312 | mfc0 a0, CP0_STATUS |
| 243 | ori a0, 0x1f | 313 | ori a0, STATMASK |
| 244 | xori a0, 0x1f | 314 | xori a0, STATMASK |
| 245 | mtc0 a0, CP0_STATUS | 315 | mtc0 a0, CP0_STATUS |
| 246 | li v1, 0xff00 | 316 | li v1, 0xff00 |
| 247 | and a0, v1 | 317 | and a0, v1 |
| @@ -250,6 +320,26 @@ | |||
| 250 | and v0, v1 | 320 | and v0, v1 |
| 251 | or v0, a0 | 321 | or v0, a0 |
| 252 | mtc0 v0, CP0_STATUS | 322 | mtc0 v0, CP0_STATUS |
| 323 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 324 | /* | ||
| 325 | * Only after EXL/ERL have been restored to status can we | ||
| 326 | * restore TCStatus.IXMT. | ||
| 327 | */ | ||
| 328 | LONG_L v1, PT_TCSTATUS(sp) | ||
| 329 | ehb | ||
| 330 | mfc0 v0, CP0_TCSTATUS | ||
| 331 | andi v1, TCSTATUS_IXMT | ||
| 332 | /* We know that TCStatua.IXMT should be set from above */ | ||
| 333 | xori v0, v0, TCSTATUS_IXMT | ||
| 334 | or v0, v0, v1 | ||
| 335 | mtc0 v0, CP0_TCSTATUS | ||
| 336 | ehb | ||
| 337 | andi a1, a1, VPECONTROL_TE | ||
| 338 | beqz a1, 1f | ||
| 339 | emt | ||
| 340 | 1: | ||
| 341 | .set mips0 | ||
| 342 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 253 | LONG_L v1, PT_EPC(sp) | 343 | LONG_L v1, PT_EPC(sp) |
| 254 | MTC0 v1, CP0_EPC | 344 | MTC0 v1, CP0_EPC |
| 255 | LONG_L $31, PT_R31(sp) | 345 | LONG_L $31, PT_R31(sp) |
| @@ -302,11 +392,33 @@ | |||
| 302 | * Set cp0 enable bit as sign that we're running on the kernel stack | 392 | * Set cp0 enable bit as sign that we're running on the kernel stack |
| 303 | */ | 393 | */ |
| 304 | .macro CLI | 394 | .macro CLI |
| 395 | #if !defined(CONFIG_MIPS_MT_SMTC) | ||
| 305 | mfc0 t0, CP0_STATUS | 396 | mfc0 t0, CP0_STATUS |
| 306 | li t1, ST0_CU0 | 0x1f | 397 | li t1, ST0_CU0 | 0x1f |
| 307 | or t0, t1 | 398 | or t0, t1 |
| 308 | xori t0, 0x1f | 399 | xori t0, 0x1f |
| 309 | mtc0 t0, CP0_STATUS | 400 | mtc0 t0, CP0_STATUS |
| 401 | #else /* CONFIG_MIPS_MT_SMTC */ | ||
| 402 | /* | ||
| 403 | * For SMTC, we need to set privilege | ||
| 404 | * and disable interrupts only for the | ||
| 405 | * current TC, using the TCStatus register. | ||
| 406 | */ | ||
| 407 | mfc0 t0,CP0_TCSTATUS | ||
| 408 | /* Fortunately CU 0 is in the same place in both registers */ | ||
| 409 | /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */ | ||
| 410 | li t1, ST0_CU0 | 0x08001c00 | ||
| 411 | or t0,t1 | ||
| 412 | /* Clear TKSU, leave IXMT */ | ||
| 413 | xori t0, 0x00001800 | ||
| 414 | mtc0 t0, CP0_TCSTATUS | ||
| 415 | ehb | ||
| 416 | /* We need to leave the global IE bit set, but clear EXL...*/ | ||
| 417 | mfc0 t0, CP0_STATUS | ||
| 418 | ori t0, ST0_EXL | ST0_ERL | ||
| 419 | xori t0, ST0_EXL | ST0_ERL | ||
| 420 | mtc0 t0, CP0_STATUS | ||
| 421 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 310 | irq_disable_hazard | 422 | irq_disable_hazard |
| 311 | .endm | 423 | .endm |
| 312 | 424 | ||
| @@ -315,11 +427,35 @@ | |||
| 315 | * Set cp0 enable bit as sign that we're running on the kernel stack | 427 | * Set cp0 enable bit as sign that we're running on the kernel stack |
| 316 | */ | 428 | */ |
| 317 | .macro STI | 429 | .macro STI |
| 430 | #if !defined(CONFIG_MIPS_MT_SMTC) | ||
| 318 | mfc0 t0, CP0_STATUS | 431 | mfc0 t0, CP0_STATUS |
| 319 | li t1, ST0_CU0 | 0x1f | 432 | li t1, ST0_CU0 | 0x1f |
| 320 | or t0, t1 | 433 | or t0, t1 |
| 321 | xori t0, 0x1e | 434 | xori t0, 0x1e |
| 322 | mtc0 t0, CP0_STATUS | 435 | mtc0 t0, CP0_STATUS |
| 436 | #else /* CONFIG_MIPS_MT_SMTC */ | ||
| 437 | /* | ||
| 438 | * For SMTC, we need to set privilege | ||
| 439 | * and enable interrupts only for the | ||
| 440 | * current TC, using the TCStatus register. | ||
| 441 | */ | ||
| 442 | ehb | ||
| 443 | mfc0 t0,CP0_TCSTATUS | ||
| 444 | /* Fortunately CU 0 is in the same place in both registers */ | ||
| 445 | /* Set TCU0, TKSU (for later inversion) and IXMT */ | ||
| 446 | li t1, ST0_CU0 | 0x08001c00 | ||
| 447 | or t0,t1 | ||
| 448 | /* Clear TKSU *and* IXMT */ | ||
| 449 | xori t0, 0x00001c00 | ||
| 450 | mtc0 t0, CP0_TCSTATUS | ||
| 451 | ehb | ||
| 452 | /* We need to leave the global IE bit set, but clear EXL...*/ | ||
| 453 | mfc0 t0, CP0_STATUS | ||
| 454 | ori t0, ST0_EXL | ||
| 455 | xori t0, ST0_EXL | ||
| 456 | mtc0 t0, CP0_STATUS | ||
| 457 | /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */ | ||
| 458 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 323 | irq_enable_hazard | 459 | irq_enable_hazard |
| 324 | .endm | 460 | .endm |
| 325 | 461 | ||
| @@ -328,11 +464,56 @@ | |||
| 328 | * Set cp0 enable bit as sign that we're running on the kernel stack | 464 | * Set cp0 enable bit as sign that we're running on the kernel stack |
| 329 | */ | 465 | */ |
| 330 | .macro KMODE | 466 | .macro KMODE |
| 467 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 468 | /* | ||
| 469 | * This gets baroque in SMTC. We want to | ||
| 470 | * protect the non-atomic clearing of EXL | ||
| 471 | * with DMT/EMT, but we don't want to take | ||
| 472 | * an interrupt while DMT is still in effect. | ||
| 473 | */ | ||
| 474 | |||
| 475 | /* KMODE gets invoked from both reorder and noreorder code */ | ||
| 476 | .set push | ||
| 477 | .set mips32r2 | ||
| 478 | .set noreorder | ||
| 479 | mfc0 v0, CP0_TCSTATUS | ||
| 480 | andi v1, v0, TCSTATUS_IXMT | ||
| 481 | ori v0, TCSTATUS_IXMT | ||
| 482 | mtc0 v0, CP0_TCSTATUS | ||
| 483 | ehb | ||
| 484 | DMT 2 # dmt v0 | ||
| 485 | /* | ||
| 486 | * We don't know a priori if ra is "live" | ||
| 487 | */ | ||
| 488 | move t0, ra | ||
| 489 | jal mips_ihb | ||
| 490 | nop /* delay slot */ | ||
| 491 | move ra, t0 | ||
| 492 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 331 | mfc0 t0, CP0_STATUS | 493 | mfc0 t0, CP0_STATUS |
| 332 | li t1, ST0_CU0 | 0x1e | 494 | li t1, ST0_CU0 | 0x1e |
| 333 | or t0, t1 | 495 | or t0, t1 |
| 334 | xori t0, 0x1e | 496 | xori t0, 0x1e |
| 335 | mtc0 t0, CP0_STATUS | 497 | mtc0 t0, CP0_STATUS |
| 498 | #ifdef CONFIG_MIPS_MT_SMTC | ||
| 499 | ehb | ||
| 500 | andi v0, v0, VPECONTROL_TE | ||
| 501 | beqz v0, 2f | ||
| 502 | nop /* delay slot */ | ||
| 503 | emt | ||
| 504 | 2: | ||
| 505 | mfc0 v0, CP0_TCSTATUS | ||
| 506 | /* Clear IXMT, then OR in previous value */ | ||
| 507 | ori v0, TCSTATUS_IXMT | ||
| 508 | xori v0, TCSTATUS_IXMT | ||
| 509 | or v0, v1, v0 | ||
| 510 | mtc0 v0, CP0_TCSTATUS | ||
| 511 | /* | ||
| 512 | * irq_disable_hazard below should expand to EHB | ||
| 513 | * on 24K/34K CPUS | ||
| 514 | */ | ||
| 515 | .set pop | ||
| 516 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
| 336 | irq_disable_hazard | 517 | irq_disable_hazard |
| 337 | .endm | 518 | .endm |
| 338 | 519 | ||
