diff options
Diffstat (limited to 'include/asm-mips/stackframe.h')
| -rw-r--r-- | include/asm-mips/stackframe.h | 72 | 
1 files changed, 61 insertions, 11 deletions
| diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index 051e1af0bb95..4c37c4e5f72e 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h | |||
| @@ -297,14 +297,31 @@ | |||
| 297 | #ifdef CONFIG_MIPS_MT_SMTC | 297 | #ifdef CONFIG_MIPS_MT_SMTC | 
| 298 | .set mips32r2 | 298 | .set mips32r2 | 
| 299 | /* | 299 | /* | 
| 300 | * This may not really be necessary if ints are already | 300 | * We need to make sure the read-modify-write | 
| 301 | * inhibited here. | 301 | * of Status below isn't perturbed by an interrupt | 
| 302 | * or cross-TC access, so we need to do at least a DMT, | ||
| 303 | * protected by an interrupt-inhibit. But setting IXMT | ||
| 304 | * also creates a few-cycle window where an IPI could | ||
| 305 | * be queued and not be detected before potentially | ||
| 306 | * returning to a WAIT or user-mode loop. It must be | ||
| 307 | * replayed. | ||
| 308 | * | ||
| 309 | * We're in the middle of a context switch, and | ||
| 310 | * we can't dispatch it directly without trashing | ||
| 311 | * some registers, so we'll try to detect this unlikely | ||
| 312 | * case and program a software interrupt in the VPE, | ||
| 313 | * as would be done for a cross-VPE IPI. To accomodate | ||
| 314 | * the handling of that case, we're doing a DVPE instead | ||
| 315 | * of just a DMT here to protect against other threads. | ||
| 316 | * This is a lot of cruft to cover a tiny window. | ||
| 317 | * If you can find a better design, implement it! | ||
| 318 | * | ||
| 302 | */ | 319 | */ | 
| 303 | mfc0 v0, CP0_TCSTATUS | 320 | mfc0 v0, CP0_TCSTATUS | 
| 304 | ori v0, TCSTATUS_IXMT | 321 | ori v0, TCSTATUS_IXMT | 
| 305 | mtc0 v0, CP0_TCSTATUS | 322 | mtc0 v0, CP0_TCSTATUS | 
| 306 | _ehb | 323 | _ehb | 
| 307 | DMT 5 # dmt a1 | 324 | DVPE 5 # dvpe a1 | 
| 308 | jal mips_ihb | 325 | jal mips_ihb | 
| 309 | #endif /* CONFIG_MIPS_MT_SMTC */ | 326 | #endif /* CONFIG_MIPS_MT_SMTC */ | 
| 310 | mfc0 a0, CP0_STATUS | 327 | mfc0 a0, CP0_STATUS | 
| @@ -325,17 +342,50 @@ | |||
| 325 | */ | 342 | */ | 
| 326 | LONG_L v1, PT_TCSTATUS(sp) | 343 | LONG_L v1, PT_TCSTATUS(sp) | 
| 327 | _ehb | 344 | _ehb | 
| 328 | mfc0 v0, CP0_TCSTATUS | 345 | mfc0 a0, CP0_TCSTATUS | 
| 329 | andi v1, TCSTATUS_IXMT | 346 | andi v1, TCSTATUS_IXMT | 
| 330 | /* We know that TCStatua.IXMT should be set from above */ | 347 | bnez v1, 0f | 
| 331 | xori v0, v0, TCSTATUS_IXMT | 348 | |
| 332 | or v0, v0, v1 | 349 | /* | 
| 333 | mtc0 v0, CP0_TCSTATUS | 350 | * We'd like to detect any IPIs queued in the tiny window | 
| 334 | _ehb | 351 | * above and request an software interrupt to service them | 
| 335 | andi a1, a1, VPECONTROL_TE | 352 | * when we ERET. | 
| 353 | * | ||
| 354 | * Computing the offset into the IPIQ array of the executing | ||
| 355 | * TC's IPI queue in-line would be tedious. We use part of | ||
| 356 | * the TCContext register to hold 16 bits of offset that we | ||
| 357 | * can add in-line to find the queue head. | ||
| 358 | */ | ||
| 359 | mfc0 v0, CP0_TCCONTEXT | ||
| 360 | la a2, IPIQ | ||
| 361 | srl v0, v0, 16 | ||
| 362 | addu a2, a2, v0 | ||
| 363 | LONG_L v0, 0(a2) | ||
| 364 | beqz v0, 0f | ||
| 365 | /* | ||
| 366 | * If we have a queue, provoke dispatch within the VPE by setting C_SW1 | ||
| 367 | */ | ||
| 368 | mfc0 v0, CP0_CAUSE | ||
| 369 | ori v0, v0, C_SW1 | ||
| 370 | mtc0 v0, CP0_CAUSE | ||
| 371 | 0: | ||
| 372 | /* | ||
| 373 | * This test should really never branch but | ||
| 374 | * let's be prudent here. Having atomized | ||
| 375 | * the shared register modifications, we can | ||
| 376 | * now EVPE, and must do so before interrupts | ||
| 377 | * are potentially re-enabled. | ||
| 378 | */ | ||
| 379 | andi a1, a1, MVPCONTROL_EVP | ||
| 336 | beqz a1, 1f | 380 | beqz a1, 1f | 
| 337 | emt | 381 | evpe | 
| 338 | 1: | 382 | 1: | 
| 383 | /* We know that TCStatua.IXMT should be set from above */ | ||
| 384 | xori a0, a0, TCSTATUS_IXMT | ||
| 385 | or a0, a0, v1 | ||
| 386 | mtc0 a0, CP0_TCSTATUS | ||
| 387 | _ehb | ||
| 388 | |||
| 339 | .set mips0 | 389 | .set mips0 | 
| 340 | #endif /* CONFIG_MIPS_MT_SMTC */ | 390 | #endif /* CONFIG_MIPS_MT_SMTC */ | 
| 341 | LONG_L v1, PT_EPC(sp) | 391 | LONG_L v1, PT_EPC(sp) | 
