Now that SBI STA support is detected, synchronize the shared memory address (shmem_lo and shmem_hi) between KVM and QEMU using the KVM_REG_RISCV_SBI_STA one-reg interface.
The shmem address is configured by the guest, so QEMU does not need to perform put reg operations during reset. Signed-off-by: Wang Yechao <[email protected]> --- target/riscv/cpu.h | 6 +++ target/riscv/kvm/kvm-cpu.c | 97 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index b65d631994..4da7963d3d 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -34,6 +34,9 @@ #include "cpu_cfg.h" #include "qapi/qapi-types-common.h" #include "cpu-qom.h" +#ifdef CONFIG_KVM +#include <linux/kvm.h> +#endif typedef struct CPUArchState CPURISCVState; @@ -550,6 +553,9 @@ struct CPUArchState { /* KVM multiprocessor state */ uint32_t kvm_mp_state; bool kvm_mp_state_loaded; + + /* kvm sbi state */ + struct kvm_riscv_sbi_sta kvm_sbi_sta; #endif /* CONFIG_KVM */ }; diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 8ab43432dd..ba5ba63854 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -123,6 +123,11 @@ static uint64_t kvm_riscv_vector_reg_id(RISCVCPU *cpu, KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_VECTOR, \ KVM_REG_RISCV_VECTOR_CSR_REG(name)) +#define RISCV_SBI_STA_REG(name) \ + KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_SBI_STATE, \ + KVM_REG_RISCV_SBI_STA | \ + KVM_REG_RISCV_SBI_STA_REG(name)) + #define KVM_RISCV_GET_TIMER(cs, name, reg) \ do { \ int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(name), ®); \ @@ -1010,6 +1015,88 @@ static int kvm_riscv_put_regs_vector(CPUState *cs) return ret; } +static int kvm_riscv_get_regs_sbi_sta(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + target_ulong reg; + int ret = 0; + + if (!kvm_sbi_sta.supported) { + return 0; + } + + ret = kvm_get_one_reg(cs, RISCV_SBI_STA_REG(shmem_lo), ®); + if (ret) { + return ret; + } + env->kvm_sbi_sta.shmem_lo = reg; + + ret = kvm_get_one_reg(cs, RISCV_SBI_STA_REG(shmem_hi), ®); + if (ret) { + return ret; + } + env->kvm_sbi_sta.shmem_hi = reg; + + return ret; +} + +static int kvm_riscv_get_regs_sbi_state(CPUState *cs) +{ + int ret = 0; + + ret = kvm_riscv_get_regs_sbi_sta(cs); + if (ret) { + return ret; + } + + return 0; +} + +static int kvm_riscv_put_regs_sbi_sta(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + target_ulong reg; + int ret = 0; + + if (!kvm_sbi_sta.supported) { + return 0; + } + + reg = env->kvm_sbi_sta.shmem_lo; + ret = kvm_set_one_reg(cs, RISCV_SBI_STA_REG(shmem_lo), ®); + if (ret) { + return ret; + } + + reg = env->kvm_sbi_sta.shmem_hi; + ret = kvm_set_one_reg(cs, RISCV_SBI_STA_REG(shmem_hi), ®); + if (ret) { + return ret; + } + + return ret; +} + +static int kvm_riscv_put_regs_sbi_state(CPUState *cs, KvmPutState level) +{ + int ret = 0; + + /* + * The shmem address of SBI STA is configured by the guest. During reset, + * QEMU does not need to perform put reg operations. + */ + if (level != KVM_PUT_RESET_STATE) { + ret = kvm_riscv_put_regs_sbi_sta(cs); + if (ret) { + return ret; + } + } + + return ret; +} + typedef struct KVMScratchCPU { int kvmfd; int vmfd; @@ -1433,6 +1520,11 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp) return ret; } + ret = kvm_riscv_get_regs_sbi_state(cs); + if (ret) { + return ret; + } + if (cap_has_mp_state) { struct kvm_mp_state mp_state; @@ -1520,6 +1612,11 @@ int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) return ret; } + ret = kvm_riscv_put_regs_sbi_state(cs, level); + if (ret) { + return ret; + } + if (KVM_PUT_RESET_STATE == level) { CPURISCVState *env = &RISCV_CPU(cs)->env; -- 2.27.0
