@@ -546,6 +546,7 @@ struct kvm_pmu {
unsigned nr_arch_fixed_counters;
unsigned available_event_types;
u64 fixed_ctr_ctrl;
+ u64 fixed_ctr_ctrl_hw;
u64 fixed_ctr_ctrl_mask;
u64 global_ctrl;
u64 global_status;
@@ -34,6 +34,25 @@
#define MSR_PMC_FULL_WIDTH_BIT (MSR_IA32_PMC0 - MSR_IA32_PERFCTR0)
+static void reprogram_fixed_counters_in_passthrough_pmu(struct kvm_pmu *pmu, u64 data)
+{
+ struct kvm_pmc *pmc;
+ u64 new_data = 0;
+ int i;
+
+ for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
+ pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
+ if (check_pmu_event_filter(pmc)) {
+ pmc->current_config = fixed_ctrl_field(data, i);
+ new_data |= (pmc->current_config << (i * 4));
+ } else {
+ pmc->counter = 0;
+ }
+ }
+ pmu->fixed_ctr_ctrl_hw = new_data;
+ pmu->fixed_ctr_ctrl = data;
+}
+
static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
{
struct kvm_pmc *pmc;
@@ -351,7 +370,9 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (data & pmu->fixed_ctr_ctrl_mask)
return 1;
- if (pmu->fixed_ctr_ctrl != data)
+ if (is_passthrough_pmu_enabled(vcpu))
+ reprogram_fixed_counters_in_passthrough_pmu(pmu, data);
+ else if (pmu->fixed_ctr_ctrl != data)
reprogram_fixed_counters(pmu, data);
break;
case MSR_IA32_PEBS_ENABLE:
@@ -820,13 +841,12 @@ static void intel_save_guest_pmu_context(struct kvm_vcpu *vcpu)
if (pmu->global_status)
wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, pmu->global_status);
- rdmsrl(MSR_CORE_PERF_FIXED_CTR_CTRL, pmu->fixed_ctr_ctrl);
/*
* Clear hardware FIXED_CTR_CTRL MSR to avoid information leakage and
* also avoid these guest fixed counters get accidentially enabled
* during host running when host enable global ctrl.
*/
- if (pmu->fixed_ctr_ctrl)
+ if (pmu->fixed_ctr_ctrl_hw)
wrmsrl(MSR_CORE_PERF_FIXED_CTR_CTRL, 0);
}
@@ -844,7 +864,7 @@ static void intel_restore_guest_pmu_context(struct kvm_vcpu *vcpu)
if (pmu->global_status & toggle)
wrmsrl(MSR_CORE_PERF_GLOBAL_STATUS_SET, pmu->global_status & toggle);
- wrmsrl(MSR_CORE_PERF_FIXED_CTR_CTRL, pmu->fixed_ctr_ctrl);
+ wrmsrl(MSR_CORE_PERF_FIXED_CTR_CTRL, pmu->fixed_ctr_ctrl_hw);
}
struct kvm_pmu_ops intel_pmu_ops __initdata = {