Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

LoongArch: KVM: Get VM PMU capability from HW GCFG register

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>

authored by

Bibo Mao and committed by
Huacai Chen
74087611 ac3fd01e

+35 -15
+8
arch/loongarch/include/asm/kvm_host.h
··· 126 126 struct kvm_phyid_map *phyid_map; 127 127 /* Enabled PV features */ 128 128 unsigned long pv_features; 129 + /* Supported KVM features */ 130 + unsigned long kvm_features; 129 131 130 132 s64 time_offset; 131 133 struct kvm_context __percpu *vmcs; ··· 293 291 static inline int kvm_get_pmu_num(struct kvm_vcpu_arch *arch) 294 292 { 295 293 return (arch->cpucfg[6] & CPUCFG6_PMNUM) >> CPUCFG6_PMNUM_SHIFT; 294 + } 295 + 296 + /* Check whether KVM support this feature (VMM may disable it) */ 297 + static inline bool kvm_vm_support(struct kvm_arch *arch, int feature) 298 + { 299 + return !!(arch->kvm_features & BIT_ULL(feature)); 296 300 } 297 301 298 302 bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu);
+2
arch/loongarch/include/asm/loongarch.h
··· 511 511 #define CSR_GCFG_GPERF_SHIFT 24 512 512 #define CSR_GCFG_GPERF_WIDTH 3 513 513 #define CSR_GCFG_GPERF (_ULCAST_(0x7) << CSR_GCFG_GPERF_SHIFT) 514 + #define CSR_GCFG_GPMP_SHIFT 23 515 + #define CSR_GCFG_GPMP (_ULCAST_(0x1) << CSR_GCFG_GPMP_SHIFT) 514 516 #define CSR_GCFG_GCI_SHIFT 20 515 517 #define CSR_GCFG_GCI_WIDTH 2 516 518 #define CSR_GCFG_GCI (_ULCAST_(0x3) << CSR_GCFG_GCI_SHIFT)
+25 -15
arch/loongarch/kvm/vm.c
··· 6 6 #include <linux/kvm_host.h> 7 7 #include <asm/kvm_mmu.h> 8 8 #include <asm/kvm_vcpu.h> 9 + #include <asm/kvm_csr.h> 9 10 #include <asm/kvm_eiointc.h> 10 11 #include <asm/kvm_pch_pic.h> 11 12 ··· 24 23 .data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE + 25 24 sizeof(kvm_vm_stats_desc), 26 25 }; 26 + 27 + static void kvm_vm_init_features(struct kvm *kvm) 28 + { 29 + unsigned long val; 30 + 31 + val = read_csr_gcfg(); 32 + if (val & CSR_GCFG_GPMP) 33 + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); 34 + 35 + /* Enable all PV features by default */ 36 + kvm->arch.pv_features = BIT(KVM_FEATURE_IPI); 37 + kvm->arch.kvm_features = BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); 38 + if (kvm_pvtime_supported()) { 39 + kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); 40 + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME); 41 + } 42 + } 27 43 28 44 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) 29 45 { ··· 60 42 spin_lock_init(&kvm->arch.phyid_map_lock); 61 43 62 44 kvm_init_vmcs(kvm); 63 - 64 - /* Enable all PV features by default */ 65 - kvm->arch.pv_features = BIT(KVM_FEATURE_IPI); 66 - if (kvm_pvtime_supported()) 67 - kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); 45 + kvm_vm_init_features(kvm); 68 46 69 47 /* 70 48 * cpu_vabits means user address space only (a half of total). ··· 150 136 if (cpu_has_lbt_mips) 151 137 return 0; 152 138 return -ENXIO; 153 - case KVM_LOONGARCH_VM_FEAT_PMU: 154 - if (cpu_has_pmp) 155 - return 0; 156 - return -ENXIO; 157 - case KVM_LOONGARCH_VM_FEAT_PV_IPI: 158 - return 0; 159 - case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME: 160 - if (kvm_pvtime_supported()) 161 - return 0; 162 - return -ENXIO; 163 139 case KVM_LOONGARCH_VM_FEAT_PTW: 164 140 if (cpu_has_ptw) 141 + return 0; 142 + return -ENXIO; 143 + case KVM_LOONGARCH_VM_FEAT_PMU: 144 + case KVM_LOONGARCH_VM_FEAT_PV_IPI: 145 + case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME: 146 + if (kvm_vm_support(&kvm->arch, attr->attr)) 165 147 return 0; 166 148 return -ENXIO; 167 149 default: