|
4 | 4 |
|
5 | 5 | #include <linux/nospec.h> |
6 | 6 |
|
| 7 | +#include <asm/kvm_host.h> |
| 8 | + |
7 | 9 | #define vcpu_to_pmu(vcpu) (&(vcpu)->arch.pmu) |
8 | 10 | #define pmu_to_vcpu(pmu) (container_of((pmu), struct kvm_vcpu, arch.pmu)) |
9 | 11 | #define pmc_to_pmu(pmc) (&(pmc)->vcpu->arch.pmu) |
|
21 | 23 | #define KVM_FIXED_PMC_BASE_IDX INTEL_PMC_IDX_FIXED |
22 | 24 |
|
23 | 25 | struct kvm_pmu_ops { |
24 | | - struct kvm_pmc *(*pmc_idx_to_pmc)(struct kvm_pmu *pmu, int pmc_idx); |
25 | 26 | struct kvm_pmc *(*rdpmc_ecx_to_pmc)(struct kvm_vcpu *vcpu, |
26 | 27 | unsigned int idx, u64 *mask); |
27 | 28 | struct kvm_pmc *(*msr_idx_to_pmc)(struct kvm_vcpu *vcpu, u32 msr); |
@@ -56,6 +57,32 @@ static inline bool kvm_pmu_has_perf_global_ctrl(struct kvm_pmu *pmu) |
56 | 57 | return pmu->version > 1; |
57 | 58 | } |
58 | 59 |
|
| 60 | +/* |
| 61 | + * KVM tracks all counters in 64-bit bitmaps, with general purpose counters |
| 62 | + * mapped to bits 31:0 and fixed counters mapped to 63:32, e.g. fixed counter 0 |
| 63 | + * is tracked internally via index 32. On Intel, (AMD doesn't support fixed |
| 64 | + * counters), this mirrors how fixed counters are mapped to PERF_GLOBAL_CTRL |
| 65 | + * and similar MSRs, i.e. tracking fixed counters at base index 32 reduces the |
| 66 | + * amounter of boilerplate needed to iterate over PMCs *and* simplifies common |
| 67 | + * enabling/disable/reset operations. |
| 68 | + * |
| 69 | + * WARNING! This helper is only for lookups that are initiated by KVM, it is |
| 70 | + * NOT safe for guest lookups, e.g. will do the wrong thing if passed a raw |
| 71 | + * ECX value from RDPMC (fixed counters are accessed by setting bit 30 in ECX |
| 72 | + * for RDPMC, not by adding 32 to the fixed counter index). |
| 73 | + */ |
| 74 | +static inline struct kvm_pmc *kvm_pmc_idx_to_pmc(struct kvm_pmu *pmu, int idx) |
| 75 | +{ |
| 76 | + if (idx < pmu->nr_arch_gp_counters) |
| 77 | + return &pmu->gp_counters[idx]; |
| 78 | + |
| 79 | + idx -= KVM_FIXED_PMC_BASE_IDX; |
| 80 | + if (idx >= 0 && idx < pmu->nr_arch_fixed_counters) |
| 81 | + return &pmu->fixed_counters[idx]; |
| 82 | + |
| 83 | + return NULL; |
| 84 | +} |
| 85 | + |
59 | 86 | static inline u64 pmc_bitmask(struct kvm_pmc *pmc) |
60 | 87 | { |
61 | 88 | struct kvm_pmu *pmu = pmc_to_pmu(pmc); |
|
0 commit comments