[PATCH v2 1/4] KVM: Move last_steal to common struct kvm_vcpu
Fuad Tabba
fuad.tabba at linux.dev
Sun Sep 6 10:13:32 PDT 2026
On Fri, 4 Sept 2026 at 18:56, Dongli Zhang <dongli.zhang at oracle.com> wrote:
>
> 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.
FWIW, I think HAVE_KVM_PV_STEAL_TIME is the right choice here, since
it's about what KVM itself supports. HAVE_PV_STEAL_CLOCK_GEN is the
guest-side paravirt_steal_clock() config, so a KVM-side symbol fits
the host field better.
Reviewed-by: Fuad Tabba <fuad.tabba at linux.dev>
Cheers,
/fuad
> 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