]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
LoongArch: KVM: Get VM PMU capability from HW GCFG register
authorBibo Mao <maobibo@loongson.cn>
Thu, 27 Nov 2025 03:00:18 +0000 (11:00 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Thu, 27 Nov 2025 03:00:18 +0000 (11:00 +0800)
Now VM PMU capability comes from host PMU capability directly, instead
bit 23 of HW GCFG CSR register also show PMU capability for VM. It will
be better if it comes from HW GCFG CSR register rather than just host
PMU capability, especially when LVZ feature is emulated in TCG mode, in
which case without PMU capability.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/include/asm/kvm_host.h
arch/loongarch/include/asm/loongarch.h
arch/loongarch/kvm/vm.c

index 0cecbd038bb3c0f85f416ad810c1d19846af77f8..e4fe5b8e8149f55ddfca129c67d2ec8036223204 100644 (file)
@@ -126,6 +126,8 @@ struct kvm_arch {
        struct kvm_phyid_map  *phyid_map;
        /* Enabled PV features */
        unsigned long pv_features;
+       /* Supported KVM features */
+       unsigned long kvm_features;
 
        s64 time_offset;
        struct kvm_context __percpu *vmcs;
@@ -293,6 +295,12 @@ static inline int kvm_get_pmu_num(struct kvm_vcpu_arch *arch)
        return (arch->cpucfg[6] & CPUCFG6_PMNUM) >> CPUCFG6_PMNUM_SHIFT;
 }
 
+/* Check whether KVM support this feature (VMM may disable it) */
+static inline bool kvm_vm_support(struct kvm_arch *arch, int feature)
+{
+       return !!(arch->kvm_features & BIT_ULL(feature));
+}
+
 bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu);
 
 /* Debug: dump vcpu state */
index 3de03cb864b248cd0fb5de9ec5a86b1436ccbdef..58a4a3b6b035d40ed56b209017f9d614fe83736b 100644 (file)
 #define  CSR_GCFG_GPERF_SHIFT          24
 #define  CSR_GCFG_GPERF_WIDTH          3
 #define  CSR_GCFG_GPERF                        (_ULCAST_(0x7) << CSR_GCFG_GPERF_SHIFT)
+#define  CSR_GCFG_GPMP_SHIFT           23
+#define  CSR_GCFG_GPMP                 (_ULCAST_(0x1) << CSR_GCFG_GPMP_SHIFT)
 #define  CSR_GCFG_GCI_SHIFT            20
 #define  CSR_GCFG_GCI_WIDTH            2
 #define  CSR_GCFG_GCI                  (_ULCAST_(0x3) << CSR_GCFG_GCI_SHIFT)
index a49b1c1a3dd1f7c7738237cb76c52a0d68b69879..e4f480342020533f087ab3e5ed60e3121013fe9b 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kvm_host.h>
 #include <asm/kvm_mmu.h>
 #include <asm/kvm_vcpu.h>
+#include <asm/kvm_csr.h>
 #include <asm/kvm_eiointc.h>
 #include <asm/kvm_pch_pic.h>
 
@@ -24,6 +25,23 @@ const struct kvm_stats_header kvm_vm_stats_header = {
                                        sizeof(kvm_vm_stats_desc),
 };
 
+static void kvm_vm_init_features(struct kvm *kvm)
+{
+       unsigned long val;
+
+       val = read_csr_gcfg();
+       if (val & CSR_GCFG_GPMP)
+               kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU);
+
+       /* Enable all PV features by default */
+       kvm->arch.pv_features = BIT(KVM_FEATURE_IPI);
+       kvm->arch.kvm_features = BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI);
+       if (kvm_pvtime_supported()) {
+               kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
+               kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME);
+       }
+}
+
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        int i;
@@ -42,11 +60,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        spin_lock_init(&kvm->arch.phyid_map_lock);
 
        kvm_init_vmcs(kvm);
-
-       /* Enable all PV features by default */
-       kvm->arch.pv_features = BIT(KVM_FEATURE_IPI);
-       if (kvm_pvtime_supported())
-               kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
+       kvm_vm_init_features(kvm);
 
        /*
         * cpu_vabits means user address space only (a half of total).
@@ -136,18 +150,14 @@ static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr
                if (cpu_has_lbt_mips)
                        return 0;
                return -ENXIO;
-       case KVM_LOONGARCH_VM_FEAT_PMU:
-               if (cpu_has_pmp)
+       case KVM_LOONGARCH_VM_FEAT_PTW:
+               if (cpu_has_ptw)
                        return 0;
                return -ENXIO;
+       case KVM_LOONGARCH_VM_FEAT_PMU:
        case KVM_LOONGARCH_VM_FEAT_PV_IPI:
-               return 0;
        case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
-               if (kvm_pvtime_supported())
-                       return 0;
-               return -ENXIO;
-       case KVM_LOONGARCH_VM_FEAT_PTW:
-               if (cpu_has_ptw)
+               if (kvm_vm_support(&kvm->arch, attr->attr))
                        return 0;
                return -ENXIO;
        default: