mirror of
https://git.freebsd.org/src.git
synced 2026-01-16 23:02:24 +00:00
Fix latency spikes on return from stop on POWER9+
On POWER9 and higher platforms, cpu_idle_power9() directly control the external interrupt enable lines when entering / exiting stop states. This does not provide needed information to the rest of the kernel regarding the core going into a stop state, and results in random, significant latency spikes (>200ms) due to the stopped core not receiving wakeup interrupts in a deterministic manner. Bring cpu_idle_power9() in line with cpu_idle_powerx() by using spinlock entry / exit to control the interrupt state vs. direct MSR read / write. Signed-off-by: Timothy Pearson <tpearson@raptorengineering.com>
This commit is contained in:
parent
58f77309c4
commit
6f0c2938e8
1 changed files with 19 additions and 10 deletions
|
|
@ -855,7 +855,6 @@ cpu_idle_powerx(sbintime_t sbt)
|
|||
static void
|
||||
cpu_idle_power9(sbintime_t sbt)
|
||||
{
|
||||
register_t msr;
|
||||
int max_stop_state = cpu_idle_max_stop_state;
|
||||
|
||||
/* Limit maximum stop state to valid values */
|
||||
|
|
@ -877,20 +876,30 @@ cpu_idle_power9(sbintime_t sbt)
|
|||
cpu_idle_max_stop_state = max_stop_state;
|
||||
}
|
||||
|
||||
msr = mfmsr();
|
||||
/* Suspend external interrupts until stop instruction completes. */
|
||||
mtmsr(msr & ~PSL_EE);
|
||||
/*
|
||||
* Enter spinlock and suspend external interrupts until the stop
|
||||
* instruction completes.
|
||||
*/
|
||||
spinlock_enter();
|
||||
|
||||
/* Final scheduler checks before core shutdown */
|
||||
if (sched_runnable()) {
|
||||
/* Exit spinlock and re-enable external interrupts */
|
||||
spinlock_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the stop state to lowest latency, wake up to next instruction */
|
||||
/* Set maximum transition level to 2, for deepest lossless sleep. */
|
||||
mtspr(SPR_PSSCR, (2 << PSSCR_MTL_S) | (0 << PSSCR_RL_S));
|
||||
/* "stop" instruction (PowerISA 3.0) */
|
||||
mtspr(SPR_PSSCR, (max_stop_state << PSSCR_MTL_S) | (0 << PSSCR_RL_S));
|
||||
|
||||
/* Shut down core using "stop" instruction (PowerISA 3.0) */
|
||||
__asm __volatile (".long 0x4c0002e4");
|
||||
|
||||
/*
|
||||
* Re-enable external interrupts to capture the interrupt that caused
|
||||
* the wake up.
|
||||
* the wake up. Exit spinlock.
|
||||
*/
|
||||
mtmsr(msr);
|
||||
|
||||
spinlock_exit();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue