[PATCH v2 1/4] KVM: Move last_steal to common struct kvm_vcpu

Dongli Zhang dongli.zhang at oracle.com
Fri Sep 4 10:55:23 PDT 2026


KVM caches per-vCPU host task's run_delay in per-architecture struct
kvm_vcpu_arch at last_steal.

Move the cache to struct kvm_vcpu and convert x86, arm64, riscv, and
loongarch to use the common field.

Add HAVE_KVM_PV_STEAL_TIME so last_steal is used only for architectures
that implement KVM stealtime.

Suggested-by: Marc Zyngier <maz at kernel.org>
Signed-off-by: Dongli Zhang <dongli.zhang at oracle.com>
---
Marc suggested reusing CONFIG_HAVE_PV_STEAL_CLOCK_GEN, but I introduced
HAVE_KVM_PV_STEAL_TIME instead.

As I have access to only x86 and arm64 KVM hosts, I created and validated
the selftest on those two architectures only.

 arch/arm64/include/asm/kvm_host.h     |  1 -
 arch/arm64/kvm/Kconfig                |  1 +
 arch/arm64/kvm/pvtime.c               |  8 ++++----
 arch/loongarch/include/asm/kvm_host.h |  1 -
 arch/loongarch/kvm/Kconfig            |  1 +
 arch/loongarch/kvm/exit.c             |  2 +-
 arch/loongarch/kvm/vcpu.c             |  6 +++---
 arch/riscv/include/asm/kvm_host.h     |  1 -
 arch/riscv/kvm/Kconfig                |  1 +
 arch/riscv/kvm/vcpu_sbi_sta.c         | 10 +++++-----
 arch/x86/include/asm/kvm_host.h       |  1 -
 arch/x86/kvm/Kconfig                  |  1 +
 arch/x86/kvm/x86.c                    |  5 ++---
 include/linux/kvm_host.h              |  4 ++++
 virt/kvm/Kconfig                      |  3 +++
 15 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 27fe0cd5b2d7..36cb7dee988c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -937,7 +937,6 @@ struct kvm_vcpu_arch {
 
 	/* Guest PV state */
 	struct {
-		u64 last_steal;
 		gpa_t base;
 	} steal;
 
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 449154f9a485..f5855bfc681c 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -34,6 +34,7 @@ menuconfig KVM
 	select HAVE_KVM_IRQ_BYPASS
 	select HAVE_KVM_READONLY_MEM
 	select HAVE_KVM_VCPU_RUN_PID_CHANGE
+	select HAVE_KVM_PV_STEAL_TIME
 	select SCHED_INFO
 	select GUEST_PERF_EVENTS if PERF_EVENTS
 	select KVM_GUEST_MEMFD
diff --git a/arch/arm64/kvm/pvtime.c b/arch/arm64/kvm/pvtime.c
index 4ceabaa4c30b..a67d93845d79 100644
--- a/arch/arm64/kvm/pvtime.c
+++ b/arch/arm64/kvm/pvtime.c
@@ -14,7 +14,7 @@ void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
 	u64 base = vcpu->arch.steal.base;
-	u64 last_steal = vcpu->arch.steal.last_steal;
+	u64 last_steal = vcpu->last_steal;
 	u64 offset = offsetof(struct pvclock_vcpu_stolen_time, stolen_time);
 	u64 steal = 0;
 	int idx;
@@ -25,8 +25,8 @@ 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;
+		vcpu->last_steal = READ_ONCE(current->sched_info.run_delay);
+		steal += vcpu->last_steal - last_steal;
 		kvm_put_guest(kvm, base + offset, cpu_to_le64(steal));
 	}
 	srcu_read_unlock(&kvm->srcu, idx);
@@ -61,7 +61,7 @@ gpa_t kvm_init_stolen_time(struct kvm_vcpu *vcpu)
 	 * Start counting stolen time from the time the guest requests
 	 * the feature enabled.
 	 */
-	vcpu->arch.steal.last_steal = current->sched_info.run_delay;
+	vcpu->last_steal = current->sched_info.run_delay;
 	kvm_write_guest_lock(kvm, base, &init_values, sizeof(init_values));
 
 	return base;
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 23cfbecebbd7..14514a25b261 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -253,7 +253,6 @@ struct kvm_vcpu_arch {
 	/* paravirt steal time */
 	struct {
 		u64 guest_addr;
-		u64 last_steal;
 		struct gfn_to_hva_cache cache;
 		u8  preempted;
 	} st;
diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig
index 15da2d88c0c1..4996ec9c07f9 100644
--- a/arch/loongarch/kvm/Kconfig
+++ b/arch/loongarch/kvm/Kconfig
@@ -26,6 +26,7 @@ config KVM
 	select HAVE_KVM_MSI
 	select HAVE_KVM_READONLY_MEM
 	select KVM_COMMON
+	select HAVE_KVM_PV_STEAL_TIME
 	select KVM_GENERIC_DIRTYLOG_READ_PROTECT
 	select KVM_GENERIC_HARDWARE_ENABLING
 	select KVM_MMIO
diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
index 4f58e6e2cf86..56ae6b18f8c1 100644
--- a/arch/loongarch/kvm/exit.c
+++ b/arch/loongarch/kvm/exit.c
@@ -773,7 +773,7 @@ static long kvm_save_notify(struct kvm_vcpu *vcpu)
 		if (!(data & KVM_STEAL_PHYS_VALID))
 			return 0;
 
-		vcpu->arch.st.last_steal = current->sched_info.run_delay;
+		vcpu->last_steal = current->sched_info.run_delay;
 		kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
 		return 0;
 	default:
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index ed9e092c97ba..728d29eba8e0 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -187,8 +187,8 @@ static void kvm_update_stolen_time(struct kvm_vcpu *vcpu)
 	smp_wmb();
 
 	unsafe_get_user(steal, &st->steal, out);
-	steal += current->sched_info.run_delay - vcpu->arch.st.last_steal;
-	vcpu->arch.st.last_steal = current->sched_info.run_delay;
+	steal += current->sched_info.run_delay - vcpu->last_steal;
+	vcpu->last_steal = current->sched_info.run_delay;
 	unsafe_put_user(steal, &st->steal, out);
 
 	smp_wmb();
@@ -1205,7 +1205,7 @@ static int kvm_loongarch_pvtime_set_attr(struct kvm_vcpu *vcpu,
 
 	if (!ret) {
 		vcpu->arch.st.guest_addr = gpa;
-		vcpu->arch.st.last_steal = current->sched_info.run_delay;
+		vcpu->last_steal = current->sched_info.run_delay;
 		kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
 	}
 
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index a30600579231..305875301c04 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -273,7 +273,6 @@ struct kvm_vcpu_arch {
 	/* SBI steal-time accounting */
 	struct {
 		gpa_t shmem;
-		u64 last_steal;
 	} sta;
 };
 
diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig
index ec2cee0a39e0..1ff07a904a02 100644
--- a/arch/riscv/kvm/Kconfig
+++ b/arch/riscv/kvm/Kconfig
@@ -26,6 +26,7 @@ config KVM
 	select HAVE_KVM_READONLY_MEM
 	select HAVE_KVM_DIRTY_RING_ACQ_REL
 	select KVM_COMMON
+	select HAVE_KVM_PV_STEAL_TIME
 	select KVM_GENERIC_DIRTYLOG_READ_PROTECT
 	select KVM_GENERIC_HARDWARE_ENABLING
 	select KVM_MMIO
diff --git a/arch/riscv/kvm/vcpu_sbi_sta.c b/arch/riscv/kvm/vcpu_sbi_sta.c
index 60e50296a008..9a77d3bde7c7 100644
--- a/arch/riscv/kvm/vcpu_sbi_sta.c
+++ b/arch/riscv/kvm/vcpu_sbi_sta.c
@@ -19,13 +19,13 @@
 static void kvm_riscv_vcpu_sbi_sta_reset(struct kvm_vcpu *vcpu)
 {
 	vcpu->arch.sta.shmem = INVALID_GPA;
-	vcpu->arch.sta.last_steal = 0;
+	vcpu->last_steal = 0;
 }
 
 void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu)
 {
 	gpa_t shmem = vcpu->arch.sta.shmem;
-	u64 last_steal = vcpu->arch.sta.last_steal;
+	u64 last_steal = vcpu->last_steal;
 	__le32 __user *sequence_ptr;
 	__le64 __user *steal_ptr;
 	__le32 sequence_le;
@@ -67,8 +67,8 @@ void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu)
 
 	if (!WARN_ON(get_user(steal_le, steal_ptr))) {
 		steal = le64_to_cpu(steal_le);
-		vcpu->arch.sta.last_steal = READ_ONCE(current->sched_info.run_delay);
-		steal += vcpu->arch.sta.last_steal - last_steal;
+		vcpu->last_steal = READ_ONCE(current->sched_info.run_delay);
+		steal += vcpu->last_steal - last_steal;
 		WARN_ON(put_user(cpu_to_le64(steal), steal_ptr));
 	}
 
@@ -115,7 +115,7 @@ static int kvm_sbi_sta_steal_time_set_shmem(struct kvm_vcpu *vcpu)
 		return SBI_ERR_INVALID_ADDRESS;
 
 	vcpu->arch.sta.shmem = shmem;
-	vcpu->arch.sta.last_steal = current->sched_info.run_delay;
+	vcpu->last_steal = current->sched_info.run_delay;
 
 	return 0;
 }
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 683bb8bf43a9..ebdd8526ae12 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -872,7 +872,6 @@ struct kvm_vcpu_arch {
 	struct {
 		u8 preempted;
 		u64 msr_val;
-		u64 last_steal;
 		struct gfn_to_hva_cache cache;
 	} st;
 
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 538ed1e80332..b2aea8058841 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -40,6 +40,7 @@ config KVM_X86
 	select HAVE_KVM_MSI
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	select HAVE_KVM_NO_POLL
+	select HAVE_KVM_PV_STEAL_TIME
 	select VIRT_XFER_TO_GUEST_WORK
 	select KVM_GENERIC_DIRTYLOG_READ_PROTECT
 	select KVM_VFIO
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 79468ddfe473..927c8b1ed83d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2129,9 +2129,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
 	smp_wmb();
 
 	unsafe_get_user(steal, &st->steal, out);
-	steal += current->sched_info.run_delay -
-		vcpu->arch.st.last_steal;
-	vcpu->arch.st.last_steal = current->sched_info.run_delay;
+	steal += current->sched_info.run_delay - vcpu->last_steal;
+	vcpu->last_steal = current->sched_info.run_delay;
 	unsafe_put_user(steal, &st->steal, out);
 
 	version += 1;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 03bfc92864b6..ff9d423b6a7c 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -398,6 +398,10 @@ struct kvm_vcpu {
 	 */
 	struct kvm_memory_slot *last_used_slot;
 	u64 last_used_slot_gen;
+
+#ifdef CONFIG_HAVE_KVM_PV_STEAL_TIME
+	u64 last_steal;
+#endif
 };
 
 /*
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index c3c0ee253fc7..f42a3a0fc5ba 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -82,6 +82,9 @@ config HAVE_KVM_IRQ_BYPASS
 config HAVE_KVM_VCPU_RUN_PID_CHANGE
        bool
 
+config HAVE_KVM_PV_STEAL_TIME
+       bool
+
 config HAVE_KVM_NO_POLL
        bool
 
-- 
2.43.7




More information about the kvm-riscv mailing list