diff options
| -rw-r--r-- | arch/mips/kernel/entry.S | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/smtc.c | 2 | ||||
| -rw-r--r-- | include/asm-mips/stackframe.h | 72 |
3 files changed, 67 insertions, 17 deletions
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index e29598ae939d..ffa331029e08 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S | |||
| @@ -79,11 +79,6 @@ FEXPORT(syscall_exit) | |||
| 79 | 79 | ||
| 80 | FEXPORT(restore_all) # restore full frame | 80 | FEXPORT(restore_all) # restore full frame |
| 81 | #ifdef CONFIG_MIPS_MT_SMTC | 81 | #ifdef CONFIG_MIPS_MT_SMTC |
| 82 | /* Detect and execute deferred IPI "interrupts" */ | ||
| 83 | LONG_L s0, TI_REGS($28) | ||
| 84 | LONG_S sp, TI_REGS($28) | ||
| 85 | jal deferred_smtc_ipi | ||
| 86 | LONG_S s0, TI_REGS($28) | ||
| 87 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP | 82 | #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP |
| 88 | /* Re-arm any temporarily masked interrupts not explicitly "acked" */ | 83 | /* Re-arm any temporarily masked interrupts not explicitly "acked" */ |
| 89 | mfc0 v0, CP0_TCSTATUS | 84 | mfc0 v0, CP0_TCSTATUS |
| @@ -112,6 +107,11 @@ FEXPORT(restore_all) # restore full frame | |||
| 112 | xor t0, t0, t3 | 107 | xor t0, t0, t3 |
| 113 | mtc0 t0, CP0_TCCONTEXT | 108 | mtc0 t0, CP0_TCCONTEXT |
| 114 | #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ | 109 | #endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ |
| 110 | /* Detect and execute deferred IPI "interrupts" */ | ||
| 111 | LONG_L s0, TI_REGS($28) | ||
| 112 | LONG_S sp, TI_REGS($28) | ||
| 113 | jal deferred_smtc_ipi | ||
| 114 | LONG_S s0, TI_REGS($28) | ||
| 115 | #endif /* CONFIG_MIPS_MT_SMTC */ | 115 | #endif /* CONFIG_MIPS_MT_SMTC */ |
| 116 | .set noat | 116 | .set noat |
| 117 | RESTORE_TEMP | 117 | RESTORE_TEMP |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 05f2708a9029..39b491b9ad87 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
| @@ -70,7 +70,7 @@ static atomic_t ipi_timer_latch[NR_CPUS]; | |||
| 70 | 70 | ||
| 71 | #define IPIBUF_PER_CPU 4 | 71 | #define IPIBUF_PER_CPU 4 |
| 72 | 72 | ||
| 73 | static struct smtc_ipi_q IPIQ[NR_CPUS]; | 73 | struct smtc_ipi_q IPIQ[NR_CPUS]; |
| 74 | static struct smtc_ipi_q freeIPIq; | 74 | static struct smtc_ipi_q freeIPIq; |
| 75 | 75 | ||
| 76 | 76 | ||
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) |
