[PATCH 1/2] KVM: arm64: pvtime: Don't lose stolen time on failed updates

Hao Zhang hao_zhang_kdev at 163.com
Mon Sep 21 02:20:34 PDT 2026


From: Hao Zhang <zhanghao1 at kylinos.cn>

kvm_update_stolen_time() advances last_steal before checking whether
kvm_put_guest() successfully writes the updated value to guest memory.

If the write fails, the updated stolen time is not visible to the guest,
but the corresponding run delay has already been consumed from KVM's
accounting state.  A later successful update therefore starts from the
advanced last_steal value and permanently loses that interval.

Stolen-time updates are best-effort, but a failed update must not
consume accounting state.  Otherwise, a transient write failure turns
into a permanent loss even if a later update succeeds.

Read the current run delay into a local variable and update last_steal
only after kvm_put_guest() succeeds.  This leaves the unreported delay
pending so that a later update can account for it.

Fixes: 53f985584e3c ("KVM: arm64: pvtime: Fix stolen time accounting across migration")
Signed-off-by: Hao Zhang <zhanghao1 at kylinos.cn>
---
 arch/arm64/kvm/pvtime.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/pvtime.c b/arch/arm64/kvm/pvtime.c
index 4ceabaa4c30b..9b4f0645d92b 100644
--- a/arch/arm64/kvm/pvtime.c
+++ b/arch/arm64/kvm/pvtime.c
@@ -17,6 +17,7 @@ void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
 	u64 last_steal = vcpu->arch.steal.last_steal;
 	u64 offset = offsetof(struct pvclock_vcpu_stolen_time, stolen_time);
 	u64 steal = 0;
+	u64 run_delay;
 	int idx;
 
 	if (base == INVALID_GPA)
@@ -25,9 +26,10 @@ void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
 	idx = srcu_read_lock(&kvm->srcu);
 	if (!kvm_get_guest(kvm, base + offset, steal)) {
 		steal = le64_to_cpu(steal);
-		vcpu->arch.steal.last_steal = READ_ONCE(current->sched_info.run_delay);
-		steal += vcpu->arch.steal.last_steal - last_steal;
-		kvm_put_guest(kvm, base + offset, cpu_to_le64(steal));
+		run_delay = READ_ONCE(current->sched_info.run_delay);
+		steal += run_delay - last_steal;
+		if (!kvm_put_guest(kvm, base + offset, cpu_to_le64(steal)))
+			vcpu->arch.steal.last_steal = run_delay;
 	}
 	srcu_read_unlock(&kvm->srcu, idx);
 }

base-commit: 93f51579e7df248780214094418f205253383cc5
-- 
2.15.0




More information about the linux-arm-kernel mailing list