@@ -1402,6 +1402,7 @@ struct kvm_arch {
bool bus_lock_detection_enabled;
bool enable_pmu;
+ bool enable_passthrough_pmu;
u32 notify_window;
u32 notify_vmexit_flags;
@@ -208,6 +208,20 @@ static inline void kvm_init_pmu_capability(const struct kvm_pmu_ops *pmu_ops)
enable_pmu = false;
}
+ /* Pass-through vPMU is only supported in Intel CPUs. */
+ if (!is_intel)
+ enable_passthrough_pmu = false;
+
+ /*
+ * Pass-through vPMU requires at least PerfMon version 4 because the
+ * implementation requires the usage of MSR_CORE_PERF_GLOBAL_STATUS_SET
+ * for counter emulation as well as PMU context switch. In addition, it
+ * requires host PMU support on passthrough mode. Disable pass-through
+ * vPMU if any condition fails.
+ */
+ if (!enable_pmu || kvm_pmu_cap.version < 4 || !kvm_pmu_cap.passthrough)
+ enable_passthrough_pmu = false;
+
if (!enable_pmu) {
memset(&kvm_pmu_cap, 0, sizeof(kvm_pmu_cap));
return;
@@ -144,6 +144,8 @@ module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
extern bool __read_mostly allow_smaller_maxphyaddr;
module_param(allow_smaller_maxphyaddr, bool, S_IRUGO);
+module_param(enable_passthrough_pmu, bool, 0444);
+
#define KVM_VM_CR0_ALWAYS_OFF (X86_CR0_NW | X86_CR0_CD)
#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST X86_CR0_NE
#define KVM_VM_CR0_ALWAYS_ON \
@@ -7874,13 +7876,14 @@ static u64 vmx_get_perf_capabilities(void)
if (boot_cpu_has(X86_FEATURE_PDCM))
rdmsrl(MSR_IA32_PERF_CAPABILITIES, host_perf_cap);
- if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) {
+ if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR) &&
+ !enable_passthrough_pmu) {
x86_perf_get_lbr(&lbr);
if (lbr.nr)
perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
}
- if (vmx_pebs_supported()) {
+ if (vmx_pebs_supported() && !enable_passthrough_pmu) {
perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK;
if ((perf_cap & PERF_CAP_PEBS_FORMAT) < 4)
perf_cap &= ~PERF_CAP_PEBS_BASELINE;
@@ -193,6 +193,10 @@ bool __read_mostly enable_pmu = true;
EXPORT_SYMBOL_GPL(enable_pmu);
module_param(enable_pmu, bool, 0444);
+/* Enable/disable mediated passthrough PMU virtualization */
+bool __read_mostly enable_passthrough_pmu;
+EXPORT_SYMBOL_GPL(enable_passthrough_pmu);
+
bool __read_mostly eager_page_split = true;
module_param(eager_page_split, bool, 0644);
@@ -6666,6 +6670,9 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
mutex_lock(&kvm->lock);
if (!kvm->created_vcpus) {
kvm->arch.enable_pmu = !(cap->args[0] & KVM_PMU_CAP_DISABLE);
+ /* Disable passthrough PMU if enable_pmu is false. */
+ if (!kvm->arch.enable_pmu)
+ kvm->arch.enable_passthrough_pmu = false;
r = 0;
}
mutex_unlock(&kvm->lock);
@@ -12564,6 +12571,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm->arch.default_tsc_khz = max_tsc_khz ? : tsc_khz;
kvm->arch.guest_can_read_msr_platform_info = true;
kvm->arch.enable_pmu = enable_pmu;
+ kvm->arch.enable_passthrough_pmu = enable_passthrough_pmu;
#if IS_ENABLED(CONFIG_HYPERV)
spin_lock_init(&kvm->arch.hv_root_tdp_lock);
@@ -330,6 +330,7 @@ extern u64 host_arch_capabilities;
extern struct kvm_caps kvm_caps;
extern bool enable_pmu;
+extern bool enable_passthrough_pmu;
/*
* Get a filtered version of KVM's supported XCR0 that strips out dynamic