Re: [PATCH v4 4/6] sched/core: Pause KCOV in __schedule()

From: Andrew Morton

Date: Fri Oct 30 2026 - 17:34:09 EST


On Mon, 5 Oct 2026 20:58:01 +0200 Karl Mehltretter <kmehltretter@xxxxxxxxx> wrote:

> kernel/sched/ is built without KCOV instrumentation, but it calls code
> that is instrumented with KCOV, such as sched_clock(), architecture
> CPU-capacity helpers and profile_hits().
>
> During preemption and schedule() calls, these callees can add
> nondeterministic scheduler coverage to current.
>
> With CONFIG_KCOV_SELFTEST added to x86_64 defconfig, the interrupt
> selftest fails under QEMU, detecting spurious coverage in
> arch_scale_cpu_capacity().
>
> Annotating each callee would spread exclusions across architectures.
> Pause across __schedule() instead, extending the scheduler exclusion to
> its callees.
>
> KCOV_PAUSED remains set while a task is switched out. The guard in its
> resumed __schedule() frame restores the prior state.
>
> ...
>
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c

I applied this series and poked around in kernel/sched/core.i, with CONFIG_KCOV=n:

> @@ -7123,6 +7123,9 @@ static void __sched notrace __schedule(int sched_mode)
> struct rq *rq;
> int cpu;
>
> + /* Callees instrumented with KCOV would leak coverage into current. */
> + guard(kcov_pause)();
> +
> /* Trace preemptions consistently with task switches */
> trace_sched_entry_tp(sched_mode == SM_PREEMPT);

This expands to

class_kcov_pause_t __UNIQUE_ID_guard_1782 __attribute__((__cleanup__(class_kcov_pause_destructor))) = class_kcov_pause_constructor();

and class_kcov_pause_constructor() is

static inline __attribute__((__gnu_inline__))
__attribute__((__unused__))
__attribute__((no_instrument_function))
__attribute__((__always_inline__))
class_kcov_pause_t class_kcov_pause_constructor(void)
{
class_kcov_pause_t _t = { .lock = (void*)1 },
*_T __attribute__((__unused__)) = &_t;
_T->paused = __kcov_pause();
return _t;
}

Adding all this goop to core scheduler functions on non-KCOV kernels
won't be terribly popular!

A bit of macro magic can trivially make all this go away for non-KCOV
kernels. The overhead is probably acceptable with CONFIG_KCOV=y
kernels - seems it's only enabled for debug/research/fuzzing kernels.

Ditto the hrtimer change. Aim to make these patches produce no change
in generated code with CONFIG_KCOV=n.