[PATCH RFC 2/2] sched/core: Defer preempted remote vCPU task clock updates

From: Dongli Zhang

Date: Sun Aug 23 2026 - 21:38:10 EST


A remote update of a runqueue can advance rq->clock while the owner
vCPU is still preempted by the host. KVM publishes the matching stealtime
when the vCPU is about to re-enter the guest, so the remote CPU can
otherwise charge the stolen interval to rq->clock_task.

Defer clock_task updates made by a remote CPU while the owner vCPU is
reported preempted. Fold the deferred delta back into the next update
that can proceed so IRQ and steal accounting process it together.

This requires the hypervisor to publish up-to-date stealtime before
clearing the preempted data.

Assisted-by: Codex:GPT-5.5
Signed-off-by: Dongli Zhang <dongli.zhang@xxxxxxxxxx>
---
kernel/sched/core.c | 24 ++++++++++++++++++++++++
kernel/sched/sched.h | 1 +
2 files changed, 25 insertions(+)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index f78275192036..56aa439182c7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -816,6 +816,30 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
*/
s64 __maybe_unused steal = 0, irq_delta = 0;

+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
+ if (static_key_false((&paravirt_steal_rq_enabled))) {
+ int rq_cpu = cpu_of(rq);
+
+ /*
+ * A remote CPU can update this rq before the owner vCPU
+ * has re-entered the guest and refreshed its stealtime
+ * state. Do not charge that elapsed time to the current
+ * task until stealtime can be sampled after the vCPU is
+ * no longer preempted.
+ */
+ if (rq_cpu != raw_smp_processor_id() &&
+ vcpu_is_preempted(rq_cpu)) {
+ rq->deferred_clock_task += delta;
+ return;
+ }
+
+ if (rq->deferred_clock_task) {
+ delta += rq->deferred_clock_task;
+ rq->deferred_clock_task = 0;
+ }
+ }
+#endif
+
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
if (irqtime_enabled()) {
irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index e656c7059bf8..4fd00228afef 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1325,6 +1325,7 @@ struct rq {
#endif
#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
u64 prev_steal_time_rq;
+ u64 deferred_clock_task;
#endif

/* calc_load related fields */
--
2.43.5