[PATCH v7 12/12] sched, virt/steal_monitor: Keep tick on for faster push on nohz_full CPU

From: Shrikanth Hegde

Date: Thu Jul 09 2026 - 17:59:16 EST


Enable tick on nohz full CPU when it is marked as non-preferred.
This helps to push the task out faster and in more predictable
manner on nohz_full CPUs.

Steal time handling code will call tick_nohz_dep_set_cpu with
TICK_DEP_BIT_SCHED. This helps to push the task out of nohz_full
faster as push task depends on tick.

If there is pinned task on non-preferred CPU, it may not stop the tick.
That is rare case. Even then, this preferred CPU state change can
happen only inside the guest. So even if guest stop the tick,
it may not necessary mean power saving since host disabling the
tick is what matters more.

sched_can_stop_tick flow doesn't change if cpu_preferred. On disabling
the feature, module ensure it restores the CPU as preferred.

Signed-off-by: Shrikanth Hegde <sshegde@xxxxxxxxxxxxx>
---
v6->v7:
- Split into own patch as it is a optimization.

drivers/virt/steal_monitor/defaults.c | 9 ++++++++-
drivers/virt/steal_monitor/sm_core.h | 1 +
kernel/sched/core.c | 4 ++++
3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/virt/steal_monitor/defaults.c b/drivers/virt/steal_monitor/defaults.c
index d4b016317554..1d6197eda5eb 100644
--- a/drivers/virt/steal_monitor/defaults.c
+++ b/drivers/virt/steal_monitor/defaults.c
@@ -70,9 +70,16 @@ void decrease_preferred_cpus(struct steal_monitor *ctx)
if (target_cpu >= nr_cpu_ids)
return;

+ /*
+ * set tick bit for nohz_full CPU to push the task out. Once the tasks
+ * are pushed out, bit will be cleared if there are no tasks.
+ */
for_each_cpu_and(tmp_cpu, topology_sibling_cpumask(target_cpu),
- cpu_preferred_mask)
+ cpu_active_mask) {
set_cpu_preferred(tmp_cpu, false);
+ if (tick_nohz_full_cpu(tmp_cpu))
+ tick_nohz_dep_set_cpu(tmp_cpu, TICK_DEP_BIT_SCHED);
+ }
}

/*
diff --git a/drivers/virt/steal_monitor/sm_core.h b/drivers/virt/steal_monitor/sm_core.h
index 7c7a9bced682..bf3f82f3e0cb 100644
--- a/drivers/virt/steal_monitor/sm_core.h
+++ b/drivers/virt/steal_monitor/sm_core.h
@@ -15,6 +15,7 @@
#include <linux/topology.h>
#include <linux/sched/isolation.h>
#include <linux/math64.h>
+#include <linux/tick.h>

struct steal_monitor {
struct delayed_work work;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 1ca1eefbdaf9..6ed61182b19f 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1473,6 +1473,10 @@ bool sched_can_stop_tick(struct rq *rq)
return false;
}

+ /* Keep the tick running until CFS tasks are pushed out */
+ if (!cpu_preferred(rq->cpu) && rq->cfs.h_nr_queued)
+ return false;
+
return true;
}
#endif /* CONFIG_NO_HZ_FULL */
--
2.47.3