The ability to save and restore register state from KVM is required for both migration and the gdbstub. These hooks are mandatory for any KVM implementation.
Signed-off-by: Alex Bennée <[email protected]> --- include/accel/kvm/cpu-ops.h | 11 +++++++++++ include/system/kvm.h | 4 ---- target/i386/kvm/kvm_i386.h | 2 ++ accel/kvm/kvm-all.c | 6 ++++-- target/arm/kvm.c | 6 ++++-- target/i386/kvm/kvm-cpu.c | 2 ++ target/i386/kvm/kvm.c | 4 ++-- target/loongarch/kvm/kvm.c | 7 +++++-- target/ppc/kvm.c | 6 ++++-- target/riscv/kvm/kvm-cpu.c | 7 +++++-- target/s390x/kvm/kvm.c | 7 +++++-- 11 files changed, 44 insertions(+), 18 deletions(-) diff --git a/include/accel/kvm/cpu-ops.h b/include/accel/kvm/cpu-ops.h index cbd3935ba4d..b3f6b8e47b7 100644 --- a/include/accel/kvm/cpu-ops.h +++ b/include/accel/kvm/cpu-ops.h @@ -12,12 +12,21 @@ #include "qom/object.h" #include "hw/core/cpu.h" #include "accel/accel-cpu-target.h" +#include "system/kvm.h" struct kvm_run; /** * struct KVMCPUOps - Target-specific per-vCPU operations for KVM * + * @get_registers: Mandatory callback to synchronize architecture-specific + * vCPU register state from KVM into QEMU's CPUState. + * Returns 0 on success, or a negative errno on failure. + * @put_registers: Mandatory callback to synchronize architecture-specific + * vCPU register state from QEMU's CPUState into KVM. + * The @level parameter specifies whether to write runtime, + * reset, or full state. + * Returns 0 on success, or a negative errno on failure. * @pre_run: Optional callback executed immediately prior to entering the * KVM_RUN ioctl in the vCPU thread loop. Used by architectures * that need to inject pending events (e.g. x86 NMI/SMI) or verify @@ -45,6 +54,8 @@ struct kvm_run; * processing before execution. */ typedef struct KVMCPUOps { + int (*get_registers)(CPUState *cpu, Error **errp); + int (*put_registers)(CPUState *cpu, KvmPutState level, Error **errp); void (*pre_run)(CPUState *cpu, struct kvm_run *run); MemTxAttrs (*post_run)(CPUState *cpu, struct kvm_run *run); int (*handle_exit)(CPUState *cpu, struct kvm_run *run); diff --git a/include/system/kvm.h b/include/system/kvm.h index 8c705d21f79..b2d76f99df0 100644 --- a/include/system/kvm.h +++ b/include/system/kvm.h @@ -333,8 +333,6 @@ extern const KVMCapabilityInfo kvm_arch_required_capabilities[]; void kvm_arch_accel_class_init(ObjectClass *oc); -int kvm_arch_get_registers(CPUState *cpu, Error **errp); - typedef enum kvm_put_state { /* state subset only touched by the VCPU itself during runtime */ KVM_PUT_RUNTIME_STATE = 1, @@ -344,8 +342,6 @@ typedef enum kvm_put_state { KVM_PUT_FULL_STATE = 3, } KvmPutState; -int kvm_arch_put_registers(CPUState *cpu, KvmPutState level, Error **errp); - int kvm_arch_get_default_type(MachineState *ms); int kvm_arch_init(MachineState *ms, KVMState *s); diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h index bff587a56de..2c92afc3320 100644 --- a/target/i386/kvm/kvm_i386.h +++ b/target/i386/kvm/kvm_i386.h @@ -33,6 +33,8 @@ bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp); int kvm_get_vm_type(MachineState *ms); void kvm_arch_reset_vcpu(X86CPU *cs); +int x86_kvm_get_registers(CPUState *cs, Error **errp); +int x86_kvm_put_registers(CPUState *cpu, KvmPutState level, Error **errp); void x86_kvm_pre_run(CPUState *cpu, struct kvm_run *run); MemTxAttrs x86_kvm_post_run(CPUState *cpu, struct kvm_run *run); int x86_kvm_handle_exit(CPUState *cs, struct kvm_run *run); diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index e8a26a9f067..3de05bb8bb8 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3214,8 +3214,9 @@ void kvm_flush_coalesced_mmio_buffer(void) static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg) { if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) { + const KVMCPUOps *ops = kvm_get_cpu_ops(cpu); Error *err = NULL; - int ret = kvm_arch_get_registers(cpu, &err); + int ret = ops->get_registers(cpu, &err); if (ret) { if (err) { error_reportf_err(err, "Failed to synchronize CPU state: "); @@ -3241,8 +3242,9 @@ void kvm_cpu_synchronize_state(CPUState *cpu) static bool kvm_cpu_synchronize_put(CPUState *cpu, KvmPutState state, const char *desc) { + const KVMCPUOps *ops = kvm_get_cpu_ops(cpu); Error *err = NULL; - int ret = kvm_arch_put_registers(cpu, state, &err); + int ret = ops->put_registers(cpu, state, &err); if (ret) { if (err) { error_reportf_err(err, "Restoring resisters %s: ", desc); diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 06b133ebf53..ea8c4d02ee8 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -2198,7 +2198,7 @@ static int kvm_arch_put_sve(CPUState *cs, uint32_t vq, bool have_ffr) return 0; } -int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) +static int arm_kvm_put_registers(CPUState *cs, KvmPutState level, Error **errp) { uint64_t val; uint32_t fpr; @@ -2383,7 +2383,7 @@ static int kvm_arch_get_sve(CPUState *cs, uint32_t vq, bool have_ffr) return 0; } -int kvm_arch_get_registers(CPUState *cs, Error **errp) +static int arm_kvm_get_registers(CPUState *cs, Error **errp) { uint64_t val; unsigned int el; @@ -2661,6 +2661,8 @@ void arm_gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3) } static const KVMCPUOps arm_kvm_cpu_ops = { + .get_registers = arm_kvm_get_registers, + .put_registers = arm_kvm_put_registers, .pre_run = arm_kvm_pre_run, .post_run = arm_kvm_post_run, .handle_exit = arm_kvm_handle_exit, diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c index 163d60a1060..08308ef8a80 100644 --- a/target/i386/kvm/kvm-cpu.c +++ b/target/i386/kvm/kvm-cpu.c @@ -235,6 +235,8 @@ static void kvm_cpu_instance_init(CPUState *cs) } static const KVMCPUOps x86_kvm_cpu_ops = { + .get_registers = x86_kvm_get_registers, + .put_registers = x86_kvm_put_registers, .pre_run = x86_kvm_pre_run, .post_run = x86_kvm_post_run, .handle_exit = x86_kvm_handle_exit, diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 83c4451cf31..7ee6d3d4f38 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -5712,7 +5712,7 @@ static int kvm_get_nested_state(X86CPU *cpu) return ret; } -int kvm_arch_put_registers(CPUState *cpu, KvmPutState level, Error **errp) +int x86_kvm_put_registers(CPUState *cpu, KvmPutState level, Error **errp) { X86CPU *x86_cpu = X86_CPU(cpu); int ret; @@ -5817,7 +5817,7 @@ int kvm_arch_put_registers(CPUState *cpu, KvmPutState level, Error **errp) return 0; } -int kvm_arch_get_registers(CPUState *cs, Error **errp) +int x86_kvm_get_registers(CPUState *cs, Error **errp) { X86CPU *cpu = X86_CPU(cs); int ret; diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c index 600903a2280..1e7565732e8 100644 --- a/target/loongarch/kvm/kvm.c +++ b/target/loongarch/kvm/kvm.c @@ -823,7 +823,7 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs) return ret; } -int kvm_arch_get_registers(CPUState *cs, Error **errp) +static int loongarch_kvm_get_registers(CPUState *cs, Error **errp) { int ret; @@ -861,7 +861,8 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp) return ret; } -int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) +static int loongarch_kvm_put_registers(CPUState *cs, KvmPutState level, + Error **errp) { int ret; static int once; @@ -1643,6 +1644,8 @@ void kvm_arch_accel_class_init(ObjectClass *oc) } static const KVMCPUOps loongarch_kvm_cpu_ops = { + .get_registers = loongarch_kvm_get_registers, + .put_registers = loongarch_kvm_put_registers, .handle_exit = loongarch_kvm_handle_exit, .process_async_events = loongarch_kvm_process_async_events, }; diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index e52f0b84ee3..25f797cb2d8 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -908,7 +908,7 @@ int kvmppc_put_books_sregs(PowerPCCPU *cpu) return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); } -int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) +static int ppc_kvm_put_registers(CPUState *cs, KvmPutState level, Error **errp) { PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = &cpu->env; @@ -1213,7 +1213,7 @@ static int kvmppc_get_books_sregs(PowerPCCPU *cpu) return 0; } -int kvm_arch_get_registers(CPUState *cs, Error **errp) +static int ppc_kvm_get_registers(CPUState *cs, Error **errp) { PowerPCCPU *cpu = POWERPC_CPU(cs); CPUPPCState *env = &cpu->env; @@ -3073,6 +3073,8 @@ void kvm_arch_accel_class_init(ObjectClass *oc) } static const KVMCPUOps ppc_kvm_cpu_ops = { + .get_registers = ppc_kvm_get_registers, + .put_registers = ppc_kvm_put_registers, .handle_exit = ppc_kvm_handle_exit, .process_async_events = ppc_kvm_process_async_events, }; diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index a5333083765..c38c07a563b 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -1389,7 +1389,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; -int kvm_arch_get_registers(CPUState *cs, Error **errp) +static int riscv_kvm_get_registers(CPUState *cs, Error **errp) { int ret = 0; @@ -1444,7 +1444,8 @@ static int kvm_riscv_put_mp_state(CPUState *cs) return kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state); } -int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) +static int riscv_kvm_put_registers(CPUState *cs, KvmPutState level, + Error **errp) { int ret = 0; @@ -2183,6 +2184,8 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) } static const KVMCPUOps riscv_kvm_cpu_ops = { + .get_registers = riscv_kvm_get_registers, + .put_registers = riscv_kvm_put_registers, .handle_exit = riscv_kvm_handle_exit, }; diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c index 420703f7683..c85d286288b 100644 --- a/target/s390x/kvm/kvm.c +++ b/target/s390x/kvm/kvm.c @@ -471,7 +471,8 @@ static int can_sync_regs(CPUState *cs, int regs) KVM_SYNC_CRS | KVM_SYNC_PREFIX | \ KVM_SYNC_PFAULT) -int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) +static int s390x_kvm_put_registers(CPUState *cs, KvmPutState level, + Error **errp) { CPUS390XState *env = cpu_env(cs); struct kvm_fpu fpu = {}; @@ -582,7 +583,7 @@ int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) return 0; } -int kvm_arch_get_registers(CPUState *cs, Error **errp) +static int s390x_kvm_get_registers(CPUState *cs, Error **errp) { CPUS390XState *env = cpu_env(cs); struct kvm_fpu fpu; @@ -2650,6 +2651,8 @@ void kvm_arch_accel_class_init(ObjectClass *oc) } static const KVMCPUOps s390x_kvm_cpu_ops = { + .get_registers = s390x_kvm_get_registers, + .put_registers = s390x_kvm_put_registers, .handle_exit = s390x_kvm_handle_exit, .process_async_events = s390x_kvm_process_async_events, }; -- 2.47.3
