[PATCH 2/2] KVM: x86: pmu: Enabling PMU v3

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently the guest PMU version number 3 is not supported (versions up to 2 are
reported).  The features PMU v3 presents are: AnyThread, extend reporting of
capabilities in CPUID leaf 0AH and varible number of perfomrance counters.
While most of the support is already present, the version reported is still 2,
since dealing with AnyThread is complicated. Nonetheless, OSes may assume other
features than AnyThread are not supported since the version report is 2.

This patch checks if the guest vCPU uses SMT. If not, it reports PMU v3.  When
PMU v3 is used, the AnyThread bit is ignored, but does not trigger faults.

Signed-off-by: Nadav Amit <namit@xxxxxxxxxxxxxxxxx>
---
 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/cpuid.c            |  2 +-
 arch/x86/kvm/pmu.c              | 11 +++++++++--
 arch/x86/kvm/svm.c              | 15 +++++++++++++++
 arch/x86/kvm/vmx.c              | 16 ++++++++++++++++
 5 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4bda61b..8c8401b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -327,6 +327,7 @@ struct kvm_pmu {
 	u64 counter_bitmask[2];
 	u64 global_ctrl_mask;
 	u64 reserved_bits;
+	u64 fixed_ctrl_reserved_bits;
 	u8 version;
 	struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
 	struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 38a0afe..0d7b729 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -406,7 +406,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		if (!cap.version)
 			memset(&cap, 0, sizeof(cap));
 
-		eax.split.version_id = min(cap.version, 2);
+		eax.split.version_id = min(cap.version, 3);
 		eax.split.num_counters = cap.num_counters_gp;
 		eax.split.bit_width = cap.bit_width_gp;
 		eax.split.mask_length = cap.events_mask_len;
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 8e6b7d8..2ad7101 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -383,7 +383,7 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_CORE_PERF_FIXED_CTR_CTRL:
 		if (pmu->fixed_ctr_ctrl == data)
 			return 0;
-		if (!(data & 0xfffffffffffff444ull)) {
+		if (!(data & pmu->fixed_ctrl_reserved_bits)) {
 			reprogram_fixed_counters(pmu, data);
 			return 0;
 		}
@@ -472,7 +472,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
 	pmu->counter_bitmask[KVM_PMC_GP] = 0;
 	pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
 	pmu->version = 0;
-	pmu->reserved_bits = 0xffffffff00200000ull;
+	pmu->reserved_bits = 0xffffffff00000000ull;
 
 	entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
 	if (!entry)
@@ -504,6 +504,13 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
 		(((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
 	pmu->global_ctrl_mask = ~pmu->global_ctrl;
 
+	pmu->fixed_ctrl_reserved_bits =
+		~((1ull << pmu->nr_arch_fixed_counters * 4) - 1);
+	if (pmu->version == 2) {
+		/* No support for anythread */
+		pmu->reserved_bits |= 0x200000;
+		pmu->fixed_ctrl_reserved_bits |= 0x4444444444444444ull;
+	}
 	entry = kvm_find_cpuid_entry(vcpu, 7, 0);
 	if (entry &&
 	    (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 1f49c86..963a9c0 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -4057,6 +4057,21 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
 
 static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 {
+	struct kvm_cpuid_entry2 *best;
+
+	/* If SMT, then PMU v3 is unsupported because of the anythread bit */
+	best = kvm_find_cpuid_entry(vcpu, 0x8000001e, 0);
+	if (best && ((best->ebx >> 8) & 3) > 0) {
+		best = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+		if (best) {
+			union cpuid10_eax eax;
+
+			eax.full = best->eax;
+			eax.split.version_id =
+				min_t(int, eax.split.version_id, 2);
+			best->eax = eax.full;
+		}
+	}
 }
 
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index cad37d5..437b131 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -7726,6 +7726,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 	struct kvm_cpuid_entry2 *best;
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u32 exec_control;
+	bool smt = false;
 
 	vmx->rdtscp_enabled = false;
 	if (vmx_rdtscp_supported()) {
@@ -7761,6 +7762,21 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 		if (best)
 			best->ebx &= ~bit(X86_FEATURE_INVPCID);
 	}
+
+	/* If SMT, then PMU v3 is unsupported because of the anythread bit */
+	best = kvm_find_cpuid_entry(vcpu, 0xb, 0);
+	smt = best && ((best->ecx >> 8) & 0xff) == 1 &&
+		((best->ebx & 0xffff) > 1);
+	best = kvm_find_cpuid_entry(vcpu, 0x1, 0);
+	smt |= best && (best->edx & bit(X86_FEATURE_HT));
+	best = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+	if (smt && best) {
+		union cpuid10_eax eax;
+
+		eax.full = best->eax;
+		eax.split.version_id = min_t(int, eax.split.version_id, 2);
+		best->eax = eax.full;
+	}
 }
 
 static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux