[RFC v1 2/9] KVM: x86: PEBS via Intel PT HW feature detection

From: Luwei Kang
Date: Thu Aug 29 2019 - 01:39:08 EST


PEBS can be enabled in KVM guest by direct PEBS record into the Intel
Processor Trace output buffer. This patch adds a new flag to detect
if PEBS can be supported in KVM guest. It not only need HW support PEBS
output Intel PT (IA32_PERF_CAPABILITIES.PEBS_OUTPUT_PT_AVAIL[16]=1)
but also depends on:
1. PEBS feature is supported by HW (IA32_MISC_ENABLE[Bit12]=0);
2. Intel PT must be working in HOST_GUEST mode.

Signed-off-by: Luwei Kang <luwei.kang@xxxxxxxxx>
---
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/include/asm/msr-index.h | 3 +++
arch/x86/kvm/vmx/capabilities.h | 11 +++++++++++
arch/x86/kvm/vmx/pmu_intel.c | 7 ++++++-
4 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 74e88e5..3463326 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -472,6 +472,7 @@ struct kvm_pmu {
u64 global_ovf_ctrl_mask;
u64 reserved_bits;
u8 version;
+ bool pebs_pt; /* PEBS output to Intel PT */
struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
struct irq_work irq_work;
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 271d837..3dd166a 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -134,6 +134,7 @@
#define MSR_IA32_PEBS_ENABLE 0x000003f1
#define MSR_PEBS_DATA_CFG 0x000003f2
#define MSR_IA32_DS_AREA 0x00000600
+#define MSR_IA32_PERF_CAP_PEBS_OUTPUT_PT (1UL << 16)
#define MSR_IA32_PERF_CAPABILITIES 0x00000345
#define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6

@@ -660,6 +661,8 @@
#define MSR_IA32_MISC_ENABLE_FERR (1ULL << MSR_IA32_MISC_ENABLE_FERR_BIT)
#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT 10
#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX_BIT)
+#define MSR_IA32_MISC_ENABLE_PEBS_BIT 12
+#define MSR_IA32_MISC_ENABLE_PEBS (1ULL << MSR_IA32_MISC_ENABLE_PEBS_BIT)
#define MSR_IA32_MISC_ENABLE_TM2_BIT 13
#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << MSR_IA32_MISC_ENABLE_TM2_BIT)
#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE_BIT 19
diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
index d6664ee..4bcb6b4 100644
--- a/arch/x86/kvm/vmx/capabilities.h
+++ b/arch/x86/kvm/vmx/capabilities.h
@@ -342,4 +342,15 @@ static inline bool cpu_has_vmx_intel_pt(void)
(vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL);
}

+static inline bool cpu_has_vmx_pebs_output_pt(void)
+{
+ u64 misc, perf_cap;
+
+ rdmsrl(MSR_IA32_MISC_ENABLE, misc);
+ rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_cap);
+
+ return (!(misc & MSR_IA32_MISC_ENABLE_PEBS) &&
+ (perf_cap & MSR_IA32_PERF_CAP_PEBS_OUTPUT_PT));
+}
+
#endif /* __KVM_X86_VMX_CAPS_H */
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 01441be..e1c987f 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -12,6 +12,7 @@
#include <linux/kvm_host.h>
#include <linux/perf_event.h>
#include <asm/perf_event.h>
+#include "capabilities.h"
#include "x86.h"
#include "cpuid.h"
#include "lapic.h"
@@ -309,10 +310,14 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
pmu->global_ovf_ctrl_mask = pmu->global_ctrl_mask
& ~(MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF |
MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD);
- if (kvm_x86_ops->pt_supported())
+ if (kvm_x86_ops->pt_supported()) {
pmu->global_ovf_ctrl_mask &=
~MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI;

+ if (cpu_has_vmx_pebs_output_pt())
+ pmu->pebs_pt = true;
+ }
+
entry = kvm_find_cpuid_entry(vcpu, 7, 0);
if (entry &&
(boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) &&
--
1.8.3.1