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:
Timothy Pearson 2025-01-20 14:03:40 -06:00 committed by Justin Hibbits
parent 58f77309c4
commit 6f0c2938e8

View file

@ -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