[PATCH v4 1/2] KVM: RISC-V: Clear former VCPU cache on virtualization disable
Nutty.Liu
nutty.liu at hotmail.com
Thu Jul 23 00:58:40 PDT 2026
On 7/22/2026 1:52 PM, Yong-Xuan Wang wrote:
> When a CPU is taken offline or enters deep idle states, hypervisor CSR
> state is lost. The kvm_former_vcpu fast-path optimization caches the
> last VCPU that ran on each CPU to avoid expensive CSR restoration when
> the same VCPU is re-scheduled on the same CPU. However, if this cache
> is not cleared when CSR state is lost, the next VCPU entry will
> incorrectly skip CSR restoration, leading to corrupt hypervisor state.
>
> Add kvm_riscv_clear_former_vcpu() to invalidate the per-CPU cache and
> call it from kvm_arch_disable_virtualization_cpu() to ensure proper CSR
> restoration after CPU offline or system suspend events.
>
> Fixes: 1323a5cfe52c ("KVM: riscv: Skip CSR restore if VCPU is reloaded on the same core")
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang at sifive.com>
Reviewed-by: Nutty Liu <nutty.liu at hotmail.com>
Thanks,
Nutty
> ---
> arch/riscv/include/asm/kvm_host.h | 2 ++
> arch/riscv/kvm/main.c | 2 ++
> arch/riscv/kvm/vcpu.c | 11 +++++++++++
> 3 files changed, 15 insertions(+)
>
> diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
> index 60017ceec9d2..808b4ee1bd10 100644
> --- a/arch/riscv/include/asm/kvm_host.h
> +++ b/arch/riscv/include/asm/kvm_host.h
> @@ -319,6 +319,8 @@ bool kvm_riscv_vcpu_stopped(struct kvm_vcpu *vcpu);
>
> void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu);
>
> +void kvm_riscv_clear_former_vcpu(void);
> +
> /* Flags representing implementation specific details */
> DECLARE_STATIC_KEY_FALSE(kvm_riscv_vsstage_tlb_no_gpa);
>
> diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c
> index 0924c75100a2..350e4f097d6e 100644
> --- a/arch/riscv/kvm/main.c
> +++ b/arch/riscv/kvm/main.c
> @@ -69,6 +69,8 @@ void kvm_arch_disable_virtualization_cpu(void)
> csr_write(CSR_HEDELEG, 0);
> csr_write(CSR_HIDELEG, 0);
>
> + kvm_riscv_clear_former_vcpu();
> +
> kvm_riscv_nacl_disable();
> }
>
> diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
> index cf6e231e76e2..e48338f907f4 100644
> --- a/arch/riscv/kvm/vcpu.c
> +++ b/arch/riscv/kvm/vcpu.c
> @@ -26,6 +26,17 @@
>
> static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_former_vcpu);
>
> +void kvm_riscv_clear_former_vcpu(void)
> +{
> + /*
> + * Clear the per-CPU former VCPU pointer because hypervisor CSR state
> + * will be lost. This ensures that the next VCPU entry will properly
> + * restore all CSRs instead of incorrectly skipping CSR restoration
> + * via the fast-path optimization.
> + */
> + __this_cpu_write(kvm_former_vcpu, NULL);
> +}
> +
> const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
> KVM_GENERIC_VCPU_STATS(),
> STATS_DESC_COUNTER(VCPU, ecall_exit_stat),
>
More information about the linux-riscv
mailing list