@@ -390,6 +390,9 @@ typedef struct CPUArchState {
struct loongarch_boot_info *boot_info;
#endif
+ struct {
+ uint64_t guest_addr;
+ } st;
} CPULoongArchState;
/**
@@ -626,6 +626,55 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs)
return ret;
}
+int kvm_loongarch_get_stealtime(LoongArchCPU *cpu)
+{
+ CPULoongArchState *env = &cpu->env;
+ int err;
+ struct kvm_device_attr attr = {
+ .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
+ .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
+ .addr = (uint64_t)&env->st.guest_addr,
+ };
+
+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr);
+ if (err) {
+ return 0;
+ }
+
+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEVICE_ATTR, attr);
+ if (err) {
+ error_report("PVTIME: KVM_GET_DEVICE_ATTR: %s", strerror(errno));
+ return err;
+ }
+
+ return 0;
+}
+
+int kvm_loongarch_put_stealtime(LoongArchCPU *cpu)
+{
+ CPULoongArchState *env = &cpu->env;
+ int err;
+ struct kvm_device_attr attr = {
+ .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
+ .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
+ .addr = (uint64_t)&env->st.guest_addr,
+ };
+
+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr);
+ if (err) {
+ return 0;
+ }
+
+ err = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEVICE_ATTR, attr);
+ if (err) {
+ error_report("PVTIME: KVM_SET_DEVICE_ATTR %s with gpa "TARGET_FMT_lx,
+ strerror(errno), env->st.guest_addr);
+ return err;
+ }
+
+ return 0;
+}
+
int kvm_arch_get_registers(CPUState *cs)
{
int ret;
@@ -12,6 +12,8 @@
int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
void kvm_arch_reset_vcpu(CPULoongArchState *env);
+int kvm_loongarch_get_stealtime(LoongArchCPU *cpu);
+int kvm_loongarch_put_stealtime(LoongArchCPU *cpu);
#ifdef CONFIG_KVM
/*
@@ -27,6 +29,16 @@ static inline bool kvm_feature_supported(CPUState *cs,
{
return false;
}
+
+static inline int kvm_loongarch_get_stealtime(LoongArchCPU *cpu)
+{
+ return 0;
+}
+
+static inline int kvm_loongarch_put_stealtime(LoongArchCPU *cpu)
+{
+ return 0;
+}
#endif
#endif
@@ -7,7 +7,9 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "kvm/kvm_loongarch.h"
#include "migration/cpu.h"
+#include "sysemu/kvm.h"
#include "sysemu/tcg.h"
#include "vec.h"
@@ -165,11 +167,29 @@ static const VMStateDescription vmstate_tlb = {
};
#endif
+static int cpu_post_load(void *opaque, int version_id)
+{
+ LoongArchCPU *cpu = opaque;
+
+ kvm_loongarch_put_stealtime(cpu);
+ return 0;
+}
+
+static int cpu_pre_save(void *opaque)
+{
+ LoongArchCPU *cpu = opaque;
+
+ kvm_loongarch_get_stealtime(cpu);
+ return 0;
+}
+
/* LoongArch CPU state */
const VMStateDescription vmstate_loongarch_cpu = {
.name = "cpu",
- .version_id = 2,
+ .version_id = 3,
.minimum_version_id = 2,
+ .post_load = cpu_post_load,
+ .pre_save = cpu_pre_save,
.fields = (const VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
VMSTATE_UINTTL(env.pc, LoongArchCPU),
@@ -232,6 +252,8 @@ const VMStateDescription vmstate_loongarch_cpu = {
VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU),
VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
+ /* PV steal time */
+ VMSTATE_UINT64(env.st.guest_addr, LoongArchCPU),
VMSTATE_END_OF_LIST()
},
With pv steal time supported, VM machine needs get physical address of each vcpu and notify to new host during migration. Here two functions kvm_loongarch_get_stealtime/kvm_loongarch_put_stealtime are provided and they are called in cpu_pre_save/cpu_post_load separately. Signed-off-by: Bibo Mao <maobibo@loongson.cn> --- target/loongarch/cpu.h | 3 ++ target/loongarch/kvm/kvm.c | 49 ++++++++++++++++++++++++++++ target/loongarch/kvm/kvm_loongarch.h | 12 +++++++ target/loongarch/machine.c | 24 +++++++++++++- 4 files changed, 87 insertions(+), 1 deletion(-) base-commit: ffdd099a782556b9ead26551a6f1d070a595306d