Re: [PATCH v4] target/riscv: Clearing the CSR values at reset and syncing the MPSTATE with the host

Philippe Mathieu-Daudé <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
Hi,

(old patch committed as 8633951530cc923f1e7a6cd250f670f24c0ed817)

On 13/9/23 11:13, liguang.zhang wrote:
> From: "liguang.zhang" <[email protected]>
> 
> Fix the guest reboot error when using KVM
> There are two issues when rebooting a guest using KVM
> 1. When the guest initiates a reboot the host is unable to stop the vcpu
> 2. When running a SMP guest the qemu monitor system_reset causes a vcpu crash
> 
> This can be fixed by clearing the CSR values at reset and syncing the
> MPSTATE with the host.
> 
> v4 update:
> rebase on riscv-to-apply
> 
> Signed-off-by: liguang.zhang <[email protected]>
> ---
>   target/riscv/kvm.c       | 42 ++++++++++++++++++++++++++++++++++++++++
>   target/riscv/kvm_riscv.h |  1 +
>   2 files changed, 43 insertions(+)
> 
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index c01cfb03f4..8ee410b9b1 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -51,6 +51,8 @@ void riscv_kvm_aplic_request(void *opaque, int irq, int level)
>       kvm_set_irq(kvm_state, irq, !!level);
>   }
>   
> +static bool cap_has_mp_state;
> +
>   static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
>                                    uint64_t idx)
>   {
> @@ -797,6 +799,24 @@ int kvm_arch_get_registers(CPUState *cs)
>       return ret;
>   }
>   
> +int kvm_riscv_sync_mpstate_to_kvm(RISCVCPU *cpu, int state)
> +{
> +    if (cap_has_mp_state) {
> +        struct kvm_mp_state mp_state = {
> +            .mp_state = state
> +        };
> +
> +        int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state);
> +        if (ret) {
> +            fprintf(stderr, "%s: failed to sync MP_STATE %d/%s\n",
> +                    __func__, ret, strerror(-ret));
> +            return -1;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
>   int kvm_arch_put_registers(CPUState *cs, int level)
>   {
>       int ret = 0;
> @@ -816,6 +836,18 @@ int kvm_arch_put_registers(CPUState *cs, int level)
>           return ret;
>       }
>   
> +    if (KVM_PUT_RESET_STATE == level) {

Why only RESET_STATE? Don't we also want that for FULL_STATE? IOW:

        if (level >= KVM_PUT_RESET_STATE) {

> +        RISCVCPU *cpu = RISCV_CPU(cs);
> +        if (cs->cpu_index == 0) {
> +            ret = kvm_riscv_sync_mpstate_to_kvm(cpu, KVM_MP_STATE_RUNNABLE);
> +        } else {
> +            ret = kvm_riscv_sync_mpstate_to_kvm(cpu, KVM_MP_STATE_STOPPED);
> +        }
> +        if (ret) {
> +            return ret;
> +        }
> +    }
> +
>       return ret;
>   }
>   
> @@ -928,6 +960,7 @@ 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);
>       return 0;
>   }
>   
> @@ -1014,10 +1047,19 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
>       if (!kvm_enabled()) {
>           return;
>       }
> +    for (int i=0; i<32; i++)
> +        env->gpr[i] = 0;
>       env->pc = cpu->env.kernel_addr;
>       env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */
>       env->gpr[11] = cpu->env.fdt_addr;          /* a1 */
>       env->satp = 0;
> +    env->mie = 0;
> +    env->stvec = 0;
> +    env->sscratch = 0;
> +    env->sepc = 0;
> +    env->scause = 0;
> +    env->stval = 0;
> +    env->mip = 0;
>   }
>   
>   void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
> index de8c209ebc..8f8c1f969a 100644
> --- a/target/riscv/kvm_riscv.h
> +++ b/target/riscv/kvm_riscv.h
> @@ -27,5 +27,6 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
>                             uint64_t aplic_base, uint64_t imsic_base,
>                             uint64_t guest_num);
>   void riscv_kvm_aplic_request(void *opaque, int irq, int level);
> +int kvm_riscv_sync_mpstate_to_kvm(RISCVCPU *cpu, int state);
>   
>   #endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.