Introduce eventsel_hw and fixed_ctr_ctrl_hw to store the actual HW value in
PMU event selector MSRs. In mediated PMU checks events before allowing the
event values written to the PMU MSRs. However, to match the HW behavior,
when PMU event checks fails, KVM should allow guest to read the value back.
This essentially requires an extra variable to separate the guest requested
value from actual PMU MSR value. Note this only applies to event selectors.
Signed-off-by: Mingwei Zhang <mizhang@google.com>
Co-developed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Tested-by: Xudong Hao <xudong.hao@intel.com>
Tested-by: Manali Shukla <manali.shukla@amd.com>
Link: https://patch.msgid.link/20251206001720.468579-25-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
*/
u64 emulated_counter;
u64 eventsel;
+ u64 eventsel_hw;
struct perf_event *perf_event;
struct kvm_vcpu *vcpu;
/*
unsigned nr_arch_fixed_counters;
unsigned available_event_types;
u64 fixed_ctr_ctrl;
+ u64 fixed_ctr_ctrl_hw;
u64 fixed_ctr_ctrl_rsvd;
u64 global_ctrl;
u64 global_status;
pmc->counter = 0;
pmc->emulated_counter = 0;
- if (pmc_is_gp(pmc))
+ if (pmc_is_gp(pmc)) {
pmc->eventsel = 0;
+ pmc->eventsel_hw = 0;
+ }
}
- pmu->fixed_ctr_ctrl = pmu->global_ctrl = pmu->global_status = 0;
+ pmu->fixed_ctr_ctrl = pmu->fixed_ctr_ctrl_hw = 0;
+ pmu->global_ctrl = pmu->global_status = 0;
kvm_pmu_call(reset)(vcpu);
}
data &= ~pmu->reserved_bits;
if (data != pmc->eventsel) {
pmc->eventsel = data;
+ pmc->eventsel_hw = data;
kvm_pmu_request_counter_reprogram(pmc);
}
return 0;
int i;
pmu->fixed_ctr_ctrl = data;
+ pmu->fixed_ctr_ctrl_hw = data;
for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
u8 new_ctrl = fixed_ctrl_field(data, i);
u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
if (data != pmc->eventsel) {
pmc->eventsel = data;
+ pmc->eventsel_hw = data;
kvm_pmu_request_counter_reprogram(pmc);
}
break;