git: 6f0c2938e895 - main - Fix latency spikes on return from stop on POWER9+
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 21 Jan 2025 23:15:50 UTC
The branch main has been updated by jhibbits:
URL: https://cgit.FreeBSD.org/src/commit/?id=6f0c2938e895bd3ddb14f44acf36dba3c6156a3f
commit 6f0c2938e895bd3ddb14f44acf36dba3c6156a3f
Author: Timothy Pearson <tpearson@raptorengineering.com>
AuthorDate: 2025-01-20 20:03:40 +0000
Commit: Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2025-01-21 23:14:41 +0000
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>
---
sys/powerpc/powerpc/cpu.c | 29 +++++++++++++++++++----------
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c
index 4b8da50cf642..37eb01e2b74f 100644
--- a/sys/powerpc/powerpc/cpu.c
+++ b/sys/powerpc/powerpc/cpu.c
@@ -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