Re: [PATCH RESEND] sched/fair: Fix overflow in vruntime_eligible()

Peter Zijlstra
2026-05-01T10:48:16Z

On Fri, May 01, 2026 at 12:40:06PM +0200, Peter Zijlstra wrote:

> Anyway, I had a poke around with godbolt, and the below seems to
> generate the best code for things like x86_64 and arm64.

https://godbolt.org/z/T389jd7bn

> Specifically, the __builtin_mul_overflow() already has to compute the
> 128 bit product anyway for most architectures, so using that directly
> then leads to saner asm and easier to understand code.
>
> AFAICT HPPA64 is the only 64bit architecture that doesn't implement
> __int128 and will thus be demoted to doing what we do on 32bit.
>
> Now all I need to do is write a coherent Changelog to go with it ...
> *sigh*
>
> ---
> diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
> index 728965851842..214fe9d99834 100644
> --- a/kernel/sched/fair.c
> +++ b/kernel/sched/fair.c
> @@ -904,7 +904,7 @@ static int vruntime_eligible(struct cfs_rq *cfs_rq, u64 vruntime)
> load += weight;
> }
>
> - return avg >= vruntime_op(vruntime, "-", cfs_rq->zero_vruntime) * load;
> + return avg >= (sched_double_long_t)vruntime_op(vruntime, "-", cfs_rq->zero_vruntime) * load;
> }
>
> int entity_eligible(struct cfs_rq *cfs_rq, struct sched_entity *se)
> diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
> index 9f63b15d309d..f15f4468efe5 100644
> --- a/kernel/sched/sched.h
> +++ b/kernel/sched/sched.h
> @@ -146,7 +146,7 @@ extern struct list_head asym_cap_list;
> * Really only required when CONFIG_FAIR_GROUP_SCHED=y is also set, but to
> * increase coverage and consistency always enable it on 64-bit platforms.
> */
> -#ifdef CONFIG_64BIT
> +#if defined(CONFIG_64BIT) && defined(__SIZEOF_INT128__)
> # define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT + SCHED_FIXEDPOINT_SHIFT)
> # define scale_load(w) ((w) << SCHED_FIXEDPOINT_SHIFT)
> # define scale_load_down(w) \
> @@ -157,10 +157,12 @@ extern struct list_head asym_cap_list;
> __w = max(2UL, __w >> SCHED_FIXEDPOINT_SHIFT); \
> __w; \
> })
> +typedef __int128 sched_double_long_t;
> #else
> # define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT)
> # define scale_load(w) (w)
> # define scale_load_down(w) (w)
> +typedef s64 sched_double_long_t;
> #endif
>
> /*