On Wed, 2026-09-30 at 17:39 +0800, Wang Yechao wrote:
> When a VM reset is requested, KVM needs to reset the register state
> of
> the vCPUs. Without this, stale KVM-internal vCPU state (such as the
> SBI
> STA shared memory address) is preserved across the reset, which can
> cause KVM to keep writing steal-time data to an address that now
> belongs
> to firmware code, corrupting it.
> 
> Add support for the KVM_CAP_RISCV_MP_STATE_RESET capability. When
> enabled, QEMU resets the vCPU by setting MP_STATE_INIT_RECEIVED
> through
> the KVM_SET_MP_STATE ioctl during the KVM_PUT_RESET_STATE phase of
> kvm_arch_put_registers(). KVM performs the register reset while
> preserving the original MP_STATE, so no state restoration is needed
> on
> the QEMU side.
> 
> This reset path is reached both when the guest initiates an SBI
> system
> reset and when userspace (e.g. the QEMU monitor) requests a VM reset,
> covering both reboot scenarios.
> 
> The capability is optional and only activated if the host kernel
> advertises KVM_CAP_RISCV_MP_STATE_RESET, ensuring backward
> compatibility
> with older kernels.
> 
> Signed-off-by: Wang Yechao <[email protected]>

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/kvm/kvm-cpu.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 68e1501b21..30cea19dea 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -58,6 +58,7 @@ void riscv_kvm_aplic_request(void *opaque, int irq,
> int level)
>  }
>  
>  static bool cap_has_mp_state;
> +static bool mp_state_reset;
>  
>  #define KVM_RISCV_REG_ID_U32(type, idx) (KVM_REG_RISCV |
> KVM_REG_SIZE_U32 | \
>                                           type | idx)
> @@ -1405,10 +1406,31 @@ static int kvm_riscv_put_mp_state(CPUState
> *cs)
>      return kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state);
>  }
>  
> +static int kvm_riscv_mp_state_init_received(CPUState *cs)
> +{
> +    struct kvm_mp_state mp_state = {
> +        .mp_state = KVM_MP_STATE_INIT_RECEIVED,
> +    };
> +
> +    if (!cap_has_mp_state || !mp_state_reset) {
> +        return 0;
> +    }
> +
> +    /* Let KVM resets the VCPU, The original MP_STATE is preserved*/
> +    return kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state);
> +}
> +
>  int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error
> **errp)
>  {
>      int ret = 0;
>  
> +    if (KVM_PUT_RESET_STATE == level) {
> +        ret = kvm_riscv_mp_state_init_received(cs);
> +        if (ret) {
> +            return ret;
> +        }
> +    }
> +
>      ret = kvm_riscv_put_regs_core(cs);
>      if (ret) {
>          return ret;
> @@ -1585,6 +1607,11 @@ int kvm_arch_get_default_type(MachineState
> *ms)
>  int kvm_arch_init(MachineState *ms, KVMState *s)
>  {
>      cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
> +
> +    if (cap_has_mp_state) {
> +        mp_state_reset = !kvm_vm_enable_cap(s,
> KVM_CAP_RISCV_MP_STATE_RESET, 0);
> +    }
> +
>      return 0;
>  }
>  

Reply via email to