[PATCH AUTOSEL 6.18-6.1] sched/fair: Reject misfit pulls onto busy SMT siblings on asym-capacity

From: Sasha Levin

Date: Mon Aug 31 2026 - 10:22:57 EST


From: Andrea Righi <arighi@xxxxxxxxxx>

[ Upstream commit bf6aa722198d3c06e4236e8c5a480f30a64e1513 ]

When SD_ASYM_CPUCAPACITY load balancing considers pulling a misfit task,
capacity_of(dst_cpu) can overstate available compute if the SMT sibling is
busy: the core does not deliver its full nominal capacity.

If SMT is active and dst_cpu is not on a fully idle core, skip this
destination so we do not migrate a misfit expecting a capacity upgrade we
cannot actually provide.

Reported-by: Felix Abecassis <fabecassis@xxxxxxxxxx>
Signed-off-by: Andrea Righi <arighi@xxxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Reviewed-by: Vincent Guittot <vincent.guittot@xxxxxxxxxx>
Link: https://patch.msgid.link/20260509180955.1840064-5-arighi@xxxxxxxxxx
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---

LLM Generated explanations, may be completely bogus:

Connection lost, reconnecting to https://agentn.us.api5.cursor.sh
(attempt 1)...
Retry attempt 1...
The background `git log --grep` search finished without finding this
commit in the 6.18.43 tree — which matches what we saw in code
(`dst_core_idle` is absent from `kernel/sched/fair.c`).

**Verdict for 6.18.y: YES.** It's a small, maintainer-reviewed
scheduling correctness fix for misfit task migration on asymmetric-
capacity + SMT systems. The buggy logic is present in this tree and the
patch should apply cleanly.

kernel/sched/fair.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index ac5f08cd01a83..fee58d01ae0f9 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -9395,6 +9395,7 @@ struct lb_env {

int dst_cpu;
struct rq *dst_rq;
+ bool dst_core_idle;

struct cpumask *dst_grpmask;
int new_dst_cpu;
@@ -10636,10 +10637,16 @@ static bool update_sd_pick_busiest(struct lb_env *env,
* We can use max_capacity here as reduction in capacity on some
* CPUs in the group should either be possible to resolve
* internally or be covered by avg_load imbalance (eventually).
+ *
+ * When SMT is active, only pull a misfit to dst_cpu if it is on a
+ * fully idle core; otherwise the effective capacity of the core is
+ * reduced and we may not actually provide more capacity than the
+ * source.
*/
if ((env->sd->flags & SD_ASYM_CPUCAPACITY) &&
(sgs->group_type == group_misfit_task) &&
- (!capacity_greater(capacity_of(env->dst_cpu), sg->sgc->max_capacity) ||
+ (!env->dst_core_idle ||
+ !capacity_greater(capacity_of(env->dst_cpu), sg->sgc->max_capacity) ||
sds->local_stat.group_type != group_has_spare))
return false;

@@ -11206,6 +11213,8 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd
unsigned long sum_util = 0;
bool sg_overloaded = 0, sg_overutilized = 0;

+ env->dst_core_idle = !sched_smt_active() || is_core_idle(env->dst_cpu);
+
do {
struct sg_lb_stats *sgs = &tmp_sgs;
int local_group;
--
2.53.0