diff mbox series

[RFC,v2] target/loongarch/kvm: Add pmu support

Message ID 20240515040611.998507-1-gaosong@loongson.cn
State New
Headers show
Series [RFC,v2] target/loongarch/kvm: Add pmu support | expand

Commit Message

gaosong May 15, 2024, 4:06 a.m. UTC
This patch adds PMU support, We just sets some cpucfg6 default value
to PMU config on kvm mode, and then check the PMU config with kvm ioctl
KVM_GET_DEVICE_ATTR.
  e.g
    '...  -cpu max,pmu=on' (enable PMU)'
    '...  -cpu max,pmu=off' (disable PMU)'

Signed-off-by: Song Gao <gaosong@loongson.cn>
---
v2:
 - Drop the property 'pmnum'.
 - Link to v1: https://patchew.org/QEMU/20240514094630.988617-1-gaosong@loongson.cn/

This patch adds the 'RFC' heading because it requires
the kernel to merge into patch[1] first

[1]: https://lore.kernel.org/all/20240507120140.3119714-1-gaosong@loongson.cn/

 target/loongarch/cpu.c                | 27 ++++++++++++++
 target/loongarch/kvm/kvm.c            | 53 ++++++++++++++++++++++++++-
 target/loongarch/loongarch-qmp-cmds.c |  2 +-
 3 files changed, 80 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index a0cad53676..fde0d2a816 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -421,6 +421,14 @@  static void loongarch_la464_initfn(Object *obj)
     data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
     env->cpucfg[5] = data;
 
+    if (kvm_enabled()) {
+        data = 0;
+        data = FIELD_DP32(data, CPUCFG6, PMP, 1);
+        data = FIELD_DP32(data, CPUCFG6, PMNUM, 3);
+        data = FIELD_DP32(data, CPUCFG6, PMBITS, 63);
+        env->cpucfg[6] = data;
+    }
+
     data = 0;
     data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
     data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
@@ -643,6 +651,20 @@  static void loongarch_set_lasx(Object *obj, bool value, Error **errp)
     }
 }
 
+static bool loongarch_get_pmu(Object *obj, Error **errp)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+    return  !!(FIELD_EX32(cpu->env.cpucfg[6], CPUCFG6, PMP));
+}
+
+static void loongarch_set_pmu(Object *obj, bool value,  Error **errp)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+
+    cpu->env.cpucfg[6] = FIELD_DP32(cpu->env.cpucfg[6], CPUCFG6, PMP, value);
+}
+
 void loongarch_cpu_post_init(Object *obj)
 {
     LoongArchCPU *cpu = LOONGARCH_CPU(obj);
@@ -655,6 +677,11 @@  void loongarch_cpu_post_init(Object *obj)
         object_property_add_bool(obj, "lasx", loongarch_get_lasx,
                                  loongarch_set_lasx);
     }
+
+    if (kvm_enabled()) {
+        object_property_add_bool(obj, "pmu", loongarch_get_pmu,
+                                 loongarch_set_pmu);
+    }
 }
 
 static void loongarch_cpu_init(Object *obj)
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
index bc75552d0f..3e46203b15 100644
--- a/target/loongarch/kvm/kvm.c
+++ b/target/loongarch/kvm/kvm.c
@@ -556,6 +556,51 @@  static int kvm_check_cpucfg2(CPUState *cs)
     return ret;
 }
 
+static int kvm_check_cpucfg6(CPUState *cs)
+{
+    int ret;
+    uint64_t val;
+    struct kvm_device_attr attr = {
+        .group = KVM_LOONGARCH_VCPU_CPUCFG,
+        .attr = 6,
+        .addr = (uint64_t)&val,
+    };
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+
+    ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
+    if (!ret) {
+        kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
+
+        if (FIELD_EX32(env->cpucfg[6], CPUCFG6, PMP)) {
+             /* Check PMP */
+             if (!FIELD_EX32(val, CPUCFG6, PMP)) {
+                 error_report("'pmu' feature not supported by KVM on this host"
+                              " Please disable 'pmu' with "
+                              "'... -cpu XXX,pmu=off ...'\n");
+                 exit(EXIT_FAILURE);
+             }
+             /* Check PMNUM */
+             int guest_pmnum = FIELD_EX32(env->cpucfg[6], CPUCFG6, PMNUM);
+             int host_pmnum = FIELD_EX32(val, CPUCFG6, PMNUM);
+             if (guest_pmnum > host_pmnum){
+                 error_report("The guest pmnum %d larger than KVM support %d\n",
+                              guest_pmnum, host_pmnum);
+                 exit(EXIT_FAILURE);
+             }
+             /* Check PMBITS */
+             int guest_pmbits = FIELD_EX32(env->cpucfg[6], CPUCFG6, PMBITS);
+             int host_pmbits = FIELD_EX32(val, CPUCFG6, PMBITS);
+             if (guest_pmbits != host_pmbits) {
+                 exit_report("The host not support PMBITS %d\n", guest_pmbits);
+                 exit(EXIT_FAILURE);
+             }
+        }
+    }
+
+    return ret;
+}
+
 static int kvm_loongarch_put_cpucfg(CPUState *cs)
 {
     int i, ret = 0;
@@ -568,7 +613,13 @@  static int kvm_loongarch_put_cpucfg(CPUState *cs)
             if (ret) {
                 return ret;
             }
-	}
+        }
+        if (i == 6) {
+            ret = kvm_check_cpucfg6(cs);
+            if (ret) {
+                return ret;
+            }
+        }
         val = env->cpucfg[i];
         ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
         if (ret < 0) {
diff --git a/target/loongarch/loongarch-qmp-cmds.c b/target/loongarch/loongarch-qmp-cmds.c
index 8721a5eb13..7e1a6fd734 100644
--- a/target/loongarch/loongarch-qmp-cmds.c
+++ b/target/loongarch/loongarch-qmp-cmds.c
@@ -40,7 +40,7 @@  CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
 }
 
 static const char *cpu_model_advertised_features[] = {
-    "lsx", "lasx", NULL
+    "lsx", "lasx", "pmu", NULL
 };
 
 CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,