[PATCH v2] target/loongarch: Add steal time support on migration

Bibo Mao posted 1 patch 1 month, 3 weeks ago
target/loongarch/cpu.h     |  3 ++
target/loongarch/kvm/kvm.c | 65 ++++++++++++++++++++++++++++++++++++++
target/loongarch/machine.c |  6 ++--
3 files changed, 72 insertions(+), 2 deletions(-)
[PATCH v2] target/loongarch: Add steal time support on migration
Posted by Bibo Mao 1 month, 3 weeks ago
With pv steal time supported, VM machine needs get physical address
of each vcpu and notify new host during migration. Here two
functions kvm_get_stealtime/kvm_set_stealtime, and guest steal time
physical address is only updated on KVM_PUT_FULL_STATE stage.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
v1 ... v2:
  1. Call function kvm_set_stealtime() at kvm_arch_put_registers()
     rather than new added cpu_post_load() interface

---
 target/loongarch/cpu.h     |  3 ++
 target/loongarch/kvm/kvm.c | 65 ++++++++++++++++++++++++++++++++++++++
 target/loongarch/machine.c |  6 ++--
 3 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 6c41fafb70..c99b72ae16 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -346,6 +346,9 @@ typedef struct CPUArchState {
     uint64_t CSR_DBG;
     uint64_t CSR_DERA;
     uint64_t CSR_DSAVE;
+    struct {
+        uint64_t guest_addr;
+    } stealtime;
 
 #ifdef CONFIG_TCG
     float_status fp_status;
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 4786cd5efa..27d4a2783b 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -33,6 +33,55 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
 
+static int kvm_get_stealtime(CPUState *cs)
+{
+    CPULoongArchState *env = cpu_env(cs);
+    int err;
+    struct kvm_device_attr attr = {
+        .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
+        .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
+        .addr = (uint64_t)&env->stealtime.guest_addr,
+    };
+
+    err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
+    if (err) {
+        return 0;
+    }
+
+    err = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, attr);
+    if (err) {
+        error_report("PVTIME: KVM_GET_DEVICE_ATTR: %s", strerror(errno));
+        return err;
+    }
+
+    return 0;
+}
+
+static int kvm_set_stealtime(CPUState *cs)
+{
+    CPULoongArchState *env = cpu_env(cs);
+    int err;
+    struct kvm_device_attr attr = {
+        .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
+        .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
+        .addr = (uint64_t)&env->stealtime.guest_addr,
+    };
+
+    err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
+    if (err) {
+        return 0;
+    }
+
+    err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
+    if (err) {
+        error_report("PVTIME: KVM_SET_DEVICE_ATTR %s with gpa "TARGET_FMT_lx,
+                      strerror(errno), env->stealtime.guest_addr);
+        return err;
+    }
+
+    return 0;
+}
+
 static int kvm_loongarch_get_regs_core(CPUState *cs)
 {
     int ret = 0;
@@ -612,6 +661,11 @@ int kvm_arch_get_registers(CPUState *cs)
         return ret;
     }
 
+    ret = kvm_get_stealtime(cs);
+    if (ret) {
+        return ret;
+    }
+
     ret = kvm_loongarch_get_mpstate(cs);
     return ret;
 }
@@ -640,6 +694,17 @@ int kvm_arch_put_registers(CPUState *cs, int level)
         return ret;
     }
 
+    if (level >= KVM_PUT_FULL_STATE) {
+        /*
+         * only KVM_PUT_FULL_STATE is required, kvm kernel will clear
+         * guest_addr for KVM_PUT_RESET_STATE
+         */
+        ret = kvm_set_stealtime(cs);
+        if (ret) {
+            return ret;
+        }
+    }
+
     ret = kvm_loongarch_put_mpstate(cs);
     return ret;
 }
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index 08a7fa5370..0b6f4f5551 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -145,8 +145,8 @@ static const VMStateDescription vmstate_tlb = {
 /* LoongArch CPU state */
 const VMStateDescription vmstate_loongarch_cpu = {
     .name = "cpu",
-    .version_id = 2,
-    .minimum_version_id = 2,
+    .version_id = 3,
+    .minimum_version_id = 3,
     .fields = (const VMStateField[]) {
         VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
         VMSTATE_UINTTL(env.pc, LoongArchCPU),
@@ -209,6 +209,8 @@ const VMStateDescription vmstate_loongarch_cpu = {
         VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU),
 
         VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
+        /* PV steal time */
+        VMSTATE_UINT64(env.stealtime.guest_addr, LoongArchCPU),
 
         VMSTATE_END_OF_LIST()
     },

base-commit: 3b14a767eaca3df5534a162851f04787b363670e
-- 
2.39.3
Re: [PATCH v2] target/loongarch: Add steal time support on migration
Posted by gaosong 1 month ago
在 2024/9/30 下午2:40, Bibo Mao 写道:
> With pv steal time supported, VM machine needs get physical address
> of each vcpu and notify new host during migration. Here two
> functions kvm_get_stealtime/kvm_set_stealtime, and guest steal time
> physical address is only updated on KVM_PUT_FULL_STATE stage.
>
> Signed-off-by: Bibo Mao <maobibo@loongson.cn>
> ---
> v1 ... v2:
>    1. Call function kvm_set_stealtime() at kvm_arch_put_registers()
>       rather than new added cpu_post_load() interface
>
> ---
>   target/loongarch/cpu.h     |  3 ++
>   target/loongarch/kvm/kvm.c | 65 ++++++++++++++++++++++++++++++++++++++
>   target/loongarch/machine.c |  6 ++--
>   3 files changed, 72 insertions(+), 2 deletions(-)
Reviewed-by: Song Gao <gaosong@loongson.cn>

Thanks.
Song Gao
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 6c41fafb70..c99b72ae16 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -346,6 +346,9 @@ typedef struct CPUArchState {
>       uint64_t CSR_DBG;
>       uint64_t CSR_DERA;
>       uint64_t CSR_DSAVE;
> +    struct {
> +        uint64_t guest_addr;
> +    } stealtime;
>   
>   #ifdef CONFIG_TCG
>       float_status fp_status;
> diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
> index 4786cd5efa..27d4a2783b 100644
> --- a/target/loongarch/kvm/kvm.c
> +++ b/target/loongarch/kvm/kvm.c
> @@ -33,6 +33,55 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>       KVM_CAP_LAST_INFO
>   };
>   
> +static int kvm_get_stealtime(CPUState *cs)
> +{
> +    CPULoongArchState *env = cpu_env(cs);
> +    int err;
> +    struct kvm_device_attr attr = {
> +        .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
> +        .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
> +        .addr = (uint64_t)&env->stealtime.guest_addr,
> +    };
> +
> +    err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
> +    if (err) {
> +        return 0;
> +    }
> +
> +    err = kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, attr);
> +    if (err) {
> +        error_report("PVTIME: KVM_GET_DEVICE_ATTR: %s", strerror(errno));
> +        return err;
> +    }
> +
> +    return 0;
> +}
> +
> +static int kvm_set_stealtime(CPUState *cs)
> +{
> +    CPULoongArchState *env = cpu_env(cs);
> +    int err;
> +    struct kvm_device_attr attr = {
> +        .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
> +        .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
> +        .addr = (uint64_t)&env->stealtime.guest_addr,
> +    };
> +
> +    err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
> +    if (err) {
> +        return 0;
> +    }
> +
> +    err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
> +    if (err) {
> +        error_report("PVTIME: KVM_SET_DEVICE_ATTR %s with gpa "TARGET_FMT_lx,
> +                      strerror(errno), env->stealtime.guest_addr);
> +        return err;
> +    }
> +
> +    return 0;
> +}
> +
>   static int kvm_loongarch_get_regs_core(CPUState *cs)
>   {
>       int ret = 0;
> @@ -612,6 +661,11 @@ int kvm_arch_get_registers(CPUState *cs)
>           return ret;
>       }
>   
> +    ret = kvm_get_stealtime(cs);
> +    if (ret) {
> +        return ret;
> +    }
> +
>       ret = kvm_loongarch_get_mpstate(cs);
>       return ret;
>   }
> @@ -640,6 +694,17 @@ int kvm_arch_put_registers(CPUState *cs, int level)
>           return ret;
>       }
>   
> +    if (level >= KVM_PUT_FULL_STATE) {
> +        /*
> +         * only KVM_PUT_FULL_STATE is required, kvm kernel will clear
> +         * guest_addr for KVM_PUT_RESET_STATE
> +         */
> +        ret = kvm_set_stealtime(cs);
> +        if (ret) {
> +            return ret;
> +        }
> +    }
> +
>       ret = kvm_loongarch_put_mpstate(cs);
>       return ret;
>   }
> diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
> index 08a7fa5370..0b6f4f5551 100644
> --- a/target/loongarch/machine.c
> +++ b/target/loongarch/machine.c
> @@ -145,8 +145,8 @@ static const VMStateDescription vmstate_tlb = {
>   /* LoongArch CPU state */
>   const VMStateDescription vmstate_loongarch_cpu = {
>       .name = "cpu",
> -    .version_id = 2,
> -    .minimum_version_id = 2,
> +    .version_id = 3,
> +    .minimum_version_id = 3,
>       .fields = (const VMStateField[]) {
>           VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
>           VMSTATE_UINTTL(env.pc, LoongArchCPU),
> @@ -209,6 +209,8 @@ const VMStateDescription vmstate_loongarch_cpu = {
>           VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU),
>   
>           VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
> +        /* PV steal time */
> +        VMSTATE_UINT64(env.stealtime.guest_addr, LoongArchCPU),
>   
>           VMSTATE_END_OF_LIST()
>       },
>
> base-commit: 3b14a767eaca3df5534a162851f04787b363670e