[PATCH 1/3] target/loongarch: Add PMU migration support in KVM mode

Bibo Mao posted 3 patches 3 weeks, 1 day ago
Maintainers: Song Gao <gaosong@loongson.cn>
There is a newer version of this series
[PATCH 1/3] target/loongarch: Add PMU migration support in KVM mode
Posted by Bibo Mao 3 weeks, 1 day ago
PMU is supported in KVM mode. When VM is migrated, PMU register should
be migrated also, otherwise PMU will be disabled after migration.

Here add PMU register save and restore interface and PMU register
state migration is added also.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 target/loongarch/cpu-csr.h | 10 ++++++
 target/loongarch/cpu.h     |  8 +++++
 target/loongarch/kvm/kvm.c | 64 ++++++++++++++++++++++++++++++++++++++
 target/loongarch/machine.c | 26 ++++++++++++++++
 4 files changed, 108 insertions(+)

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 9097fddee1..91c01c5ccc 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -203,6 +203,16 @@ FIELD(CSR_DMW_32, PSEG, 25, 3)
 FIELD(CSR_DMW_32, VSEG, 29, 3)
 FIELD(CSR_DMW_64, VSEG, 60, 4)
 
+/* Performance Counter registers */
+#define LOONGARCH_CSR_PERFCTRL0      0x200
+#define LOONGARCH_CSR_PERFCNTR0      0x201
+#define LOONGARCH_CSR_PERFCTRL1      0x202
+#define LOONGARCH_CSR_PERFCNTR1      0x203
+#define LOONGARCH_CSR_PERFCTRL2      0x204
+#define LOONGARCH_CSR_PERFCNTR2      0x205
+#define LOONGARCH_CSR_PERFCTRL3      0x206
+#define LOONGARCH_CSR_PERFCNTR3      0x207
+
 /* Debug CSRs */
 #define LOONGARCH_CSR_DBG            0x500 /* debug config */
 FIELD(CSR_DBG, DST, 0, 1)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index b8e3b46c3a..264297df3e 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -355,6 +355,14 @@ typedef struct CPUArchState {
     uint64_t CSR_MERRSAVE;
     uint64_t CSR_CTAG;
     uint64_t CSR_DMW[4];
+    uint64_t CSR_PERFCTRL0;
+    uint64_t CSR_PERFCNTR0;
+    uint64_t CSR_PERFCTRL1;
+    uint64_t CSR_PERFCNTR1;
+    uint64_t CSR_PERFCTRL2;
+    uint64_t CSR_PERFCNTR2;
+    uint64_t CSR_PERFCTRL3;
+    uint64_t CSR_PERFCNTR3;
     uint64_t CSR_DBG;
     uint64_t CSR_DERA;
     uint64_t CSR_DSAVE;
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index 4e4f4e79f6..53b2103502 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -155,6 +155,64 @@ static int kvm_loongarch_put_regs_core(CPUState *cs)
     return ret;
 }
 
+static int kvm_loongarch_put_pmu(CPUState *cs)
+{
+    int ret;
+    CPULoongArchState *env = cpu_env(cs);
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+    if (cpu->pmu != ON_OFF_AUTO_ON) {
+        return 0;
+    }
+
+    ret  = kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL0),
+                           &env->CSR_PERFCTRL0);
+    ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR0),
+                           &env->CSR_PERFCNTR0);
+    ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL1),
+                           &env->CSR_PERFCTRL1);
+    ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR1),
+                           &env->CSR_PERFCNTR1);
+    ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL2),
+                           &env->CSR_PERFCTRL2);
+    ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR2),
+                           &env->CSR_PERFCNTR2);
+    ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL3),
+                           &env->CSR_PERFCTRL3);
+    ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR3),
+                           &env->CSR_PERFCNTR3);
+    return ret;
+}
+
+static int kvm_loongarch_get_pmu(CPUState *cs)
+{
+    int ret;
+    CPULoongArchState *env = cpu_env(cs);
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+
+    if (cpu->pmu != ON_OFF_AUTO_ON) {
+        return 0;
+    }
+
+    ret  = kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL0),
+                           &env->CSR_PERFCTRL0);
+    ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR0),
+                           &env->CSR_PERFCNTR0);
+    ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL1),
+                           &env->CSR_PERFCTRL1);
+    ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR1),
+                           &env->CSR_PERFCNTR1);
+    ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL2),
+                           &env->CSR_PERFCTRL2);
+    ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR2),
+                           &env->CSR_PERFCNTR2);
+    ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCTRL3),
+                           &env->CSR_PERFCTRL3);
+    ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PERFCNTR3),
+                           &env->CSR_PERFCNTR3);
+    return ret;
+}
+
 static int kvm_loongarch_get_csr(CPUState *cs)
 {
     int ret = 0;
@@ -316,6 +374,8 @@ static int kvm_loongarch_get_csr(CPUState *cs)
     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
                            &env->CSR_DMW[3]);
 
+    ret |= kvm_loongarch_get_pmu(cs);
+
     ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
                            &env->CSR_TVAL);
 
@@ -488,6 +548,9 @@ static int kvm_loongarch_put_csr(CPUState *cs, KvmPutState level)
 
     ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
                            &env->CSR_DMW[3]);
+
+    ret |= kvm_loongarch_put_pmu(cs);
+
     /*
      * timer cfg must be put at last since it is used to enable
      * guest timer
@@ -1021,6 +1084,7 @@ static int kvm_cpu_check_pmu(CPUState *cs, Error **errp)
     }
 
     if (kvm_supported) {
+        cpu->pmu = ON_OFF_AUTO_ON;
         env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMP, 1);
         env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMNUM, 3);
         env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6, PMBITS, 63);
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index 0366a50763..0a3febf36d 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -153,6 +153,31 @@ static const VMStateDescription vmstate_lbt = {
     },
 };
 
+static bool pmu_needed(void *opaque)
+{
+    LoongArchCPU *cpu = opaque;
+
+    return cpu->pmu == ON_OFF_AUTO_ON;
+}
+
+static const VMStateDescription vmstate_pmu = {
+    .name = "cpu/pmu",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .needed = pmu_needed,
+    .fields = (const VMStateField[]) {
+        VMSTATE_UINT64(env.CSR_PERFCTRL0,   LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR0,   LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCTRL1,   LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR1,   LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCTRL2,   LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR2,   LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCTRL3,   LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR3,   LoongArchCPU),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
 static bool tlb_needed(void *opaque)
 {
@@ -266,6 +291,7 @@ const VMStateDescription vmstate_loongarch_cpu = {
 #endif
         &vmstate_lbt,
         &vmstate_msgint,
+        &vmstate_pmu,
         NULL
     }
 };
-- 
2.39.3