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


Reply via email to