[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