git: 58f77309c4e0 - main - Add machdep.cpu_idle_max_stop_state tunable
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 21 Jan 2025 23:15:48 UTC
The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=58f77309c4e0d3373705582e9ca7649fe74dd267 commit 58f77309c4e0d3373705582e9ca7649fe74dd267 Author: Timothy Pearson <tpearson@raptorengineering.com> AuthorDate: 2025-01-20 20:03:55 +0000 Commit: Justin Hibbits <jhibbits@FreeBSD.org> CommitDate: 2025-01-21 23:14:40 +0000 Add machdep.cpu_idle_max_stop_state tunable Multiple idle and deep sleep states are supported on Power7+ platforms, with each state having a characteristic latency and effect on system real-time performance. Add a tunable to allow a maximum sleep state (maximum theoretical sleep-related latency) to be set, in order to better support specific latency-sensitive applications / real time workloads. Signed-off-by: Timothy Pearson <tpearson@raptorengineering.com> --- sys/powerpc/powerpc/cpu.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c index f73ed25c8924..4b8da50cf642 100644 --- a/sys/powerpc/powerpc/cpu.c +++ b/sys/powerpc/powerpc/cpu.c @@ -95,6 +95,9 @@ static void cpu_idle_booke(sbintime_t); static void cpu_idle_e500mc(sbintime_t sbt); #endif #if defined(__powerpc64__) && defined(AIM) +static int cpu_idle_max_stop_state = 2; +SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_max_stop_state, + CTLFLAG_RW, &cpu_idle_max_stop_state, 0, ""); static void cpu_idle_powerx(sbintime_t); static void cpu_idle_power9(sbintime_t); #endif @@ -815,6 +818,22 @@ cpu_idle_booke(sbintime_t sbt) static void cpu_idle_powerx(sbintime_t sbt) { + int max_stop_state = cpu_idle_max_stop_state; + + /* Limit maximum stop state to valid values */ + if (max_stop_state < 0) { + /* Don't nap at all, busy wait instead */ + cpu_idle_max_stop_state = -1; + return; + } + if (max_stop_state > 1) { + /* POWER8 and below only support the one stop state, + * i.e. 'nap' + */ + max_stop_state = 1; + cpu_idle_max_stop_state = max_stop_state; + } + /* Sleeping when running on one cpu gives no advantages - avoid it */ if (smp_started == 0) return; @@ -837,9 +856,28 @@ static void cpu_idle_power9(sbintime_t sbt) { register_t msr; + int max_stop_state = cpu_idle_max_stop_state; - msr = mfmsr(); + /* Limit maximum stop state to valid values */ + if (max_stop_state < 0) { + /* Don't stop at all, busy wait instead */ + cpu_idle_max_stop_state = -1; + return; + } + + /* Set maximum transition level to 3, for deepest lossless sleep. + * On POWER9 this is automatically downgraded to the next supported + * stop state (stop2), but other CPUs may support stop3. + */ + if (max_stop_state > 3) { + /* Stop states greater than 3 require register state save and + * restore functionality that is not yet implemented + */ + max_stop_state = 3; + cpu_idle_max_stop_state = max_stop_state; + } + msr = mfmsr(); /* Suspend external interrupts until stop instruction completes. */ mtmsr(msr & ~PSL_EE); /* Set the stop state to lowest latency, wake up to next instruction */