162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * KVM PMU support for Intel CPUs 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011 Red Hat, Inc. and/or its affiliates. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: 862306a36Sopenharmony_ci * Avi Kivity <avi@redhat.com> 962306a36Sopenharmony_ci * Gleb Natapov <gleb@redhat.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/types.h> 1462306a36Sopenharmony_ci#include <linux/kvm_host.h> 1562306a36Sopenharmony_ci#include <linux/perf_event.h> 1662306a36Sopenharmony_ci#include <asm/perf_event.h> 1762306a36Sopenharmony_ci#include "x86.h" 1862306a36Sopenharmony_ci#include "cpuid.h" 1962306a36Sopenharmony_ci#include "lapic.h" 2062306a36Sopenharmony_ci#include "nested.h" 2162306a36Sopenharmony_ci#include "pmu.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define MSR_PMC_FULL_WIDTH_BIT (MSR_IA32_PMC0 - MSR_IA32_PERFCTR0) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cienum intel_pmu_architectural_events { 2662306a36Sopenharmony_ci /* 2762306a36Sopenharmony_ci * The order of the architectural events matters as support for each 2862306a36Sopenharmony_ci * event is enumerated via CPUID using the index of the event. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci INTEL_ARCH_CPU_CYCLES, 3162306a36Sopenharmony_ci INTEL_ARCH_INSTRUCTIONS_RETIRED, 3262306a36Sopenharmony_ci INTEL_ARCH_REFERENCE_CYCLES, 3362306a36Sopenharmony_ci INTEL_ARCH_LLC_REFERENCES, 3462306a36Sopenharmony_ci INTEL_ARCH_LLC_MISSES, 3562306a36Sopenharmony_ci INTEL_ARCH_BRANCHES_RETIRED, 3662306a36Sopenharmony_ci INTEL_ARCH_BRANCHES_MISPREDICTED, 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci NR_REAL_INTEL_ARCH_EVENTS, 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* 4162306a36Sopenharmony_ci * Pseudo-architectural event used to implement IA32_FIXED_CTR2, a.k.a. 4262306a36Sopenharmony_ci * TSC reference cycles. The architectural reference cycles event may 4362306a36Sopenharmony_ci * or may not actually use the TSC as the reference, e.g. might use the 4462306a36Sopenharmony_ci * core crystal clock or the bus clock (yeah, "architectural"). 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ci PSEUDO_ARCH_REFERENCE_CYCLES = NR_REAL_INTEL_ARCH_EVENTS, 4762306a36Sopenharmony_ci NR_INTEL_ARCH_EVENTS, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic struct { 5162306a36Sopenharmony_ci u8 eventsel; 5262306a36Sopenharmony_ci u8 unit_mask; 5362306a36Sopenharmony_ci} const intel_arch_events[] = { 5462306a36Sopenharmony_ci [INTEL_ARCH_CPU_CYCLES] = { 0x3c, 0x00 }, 5562306a36Sopenharmony_ci [INTEL_ARCH_INSTRUCTIONS_RETIRED] = { 0xc0, 0x00 }, 5662306a36Sopenharmony_ci [INTEL_ARCH_REFERENCE_CYCLES] = { 0x3c, 0x01 }, 5762306a36Sopenharmony_ci [INTEL_ARCH_LLC_REFERENCES] = { 0x2e, 0x4f }, 5862306a36Sopenharmony_ci [INTEL_ARCH_LLC_MISSES] = { 0x2e, 0x41 }, 5962306a36Sopenharmony_ci [INTEL_ARCH_BRANCHES_RETIRED] = { 0xc4, 0x00 }, 6062306a36Sopenharmony_ci [INTEL_ARCH_BRANCHES_MISPREDICTED] = { 0xc5, 0x00 }, 6162306a36Sopenharmony_ci [PSEUDO_ARCH_REFERENCE_CYCLES] = { 0x00, 0x03 }, 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* mapping between fixed pmc index and intel_arch_events array */ 6562306a36Sopenharmony_cistatic int fixed_pmc_events[] = { 6662306a36Sopenharmony_ci [0] = INTEL_ARCH_INSTRUCTIONS_RETIRED, 6762306a36Sopenharmony_ci [1] = INTEL_ARCH_CPU_CYCLES, 6862306a36Sopenharmony_ci [2] = PSEUDO_ARCH_REFERENCE_CYCLES, 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct kvm_pmc *pmc; 7462306a36Sopenharmony_ci u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl; 7562306a36Sopenharmony_ci int i; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci pmu->fixed_ctr_ctrl = data; 7862306a36Sopenharmony_ci for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { 7962306a36Sopenharmony_ci u8 new_ctrl = fixed_ctrl_field(data, i); 8062306a36Sopenharmony_ci u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (old_ctrl == new_ctrl) 8362306a36Sopenharmony_ci continue; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci __set_bit(INTEL_PMC_IDX_FIXED + i, pmu->pmc_in_use); 8862306a36Sopenharmony_ci kvm_pmu_request_counter_reprogram(pmc); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic struct kvm_pmc *intel_pmc_idx_to_pmc(struct kvm_pmu *pmu, int pmc_idx) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci if (pmc_idx < INTEL_PMC_IDX_FIXED) { 9562306a36Sopenharmony_ci return get_gp_pmc(pmu, MSR_P6_EVNTSEL0 + pmc_idx, 9662306a36Sopenharmony_ci MSR_P6_EVNTSEL0); 9762306a36Sopenharmony_ci } else { 9862306a36Sopenharmony_ci u32 idx = pmc_idx - INTEL_PMC_IDX_FIXED; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return get_fixed_pmc(pmu, idx + MSR_CORE_PERF_FIXED_CTR0); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic bool intel_hw_event_available(struct kvm_pmc *pmc) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci struct kvm_pmu *pmu = pmc_to_pmu(pmc); 10762306a36Sopenharmony_ci u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT; 10862306a36Sopenharmony_ci u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8; 10962306a36Sopenharmony_ci int i; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(intel_arch_events) != NR_INTEL_ARCH_EVENTS); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci /* 11462306a36Sopenharmony_ci * Disallow events reported as unavailable in guest CPUID. Note, this 11562306a36Sopenharmony_ci * doesn't apply to pseudo-architectural events. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci for (i = 0; i < NR_REAL_INTEL_ARCH_EVENTS; i++) { 11862306a36Sopenharmony_ci if (intel_arch_events[i].eventsel != event_select || 11962306a36Sopenharmony_ci intel_arch_events[i].unit_mask != unit_mask) 12062306a36Sopenharmony_ci continue; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return pmu->available_event_types & BIT(i); 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci return true; 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic bool intel_is_valid_rdpmc_ecx(struct kvm_vcpu *vcpu, unsigned int idx) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 13162306a36Sopenharmony_ci bool fixed = idx & (1u << 30); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci idx &= ~(3u << 30); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci return fixed ? idx < pmu->nr_arch_fixed_counters 13662306a36Sopenharmony_ci : idx < pmu->nr_arch_gp_counters; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu, 14062306a36Sopenharmony_ci unsigned int idx, u64 *mask) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 14362306a36Sopenharmony_ci bool fixed = idx & (1u << 30); 14462306a36Sopenharmony_ci struct kvm_pmc *counters; 14562306a36Sopenharmony_ci unsigned int num_counters; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci idx &= ~(3u << 30); 14862306a36Sopenharmony_ci if (fixed) { 14962306a36Sopenharmony_ci counters = pmu->fixed_counters; 15062306a36Sopenharmony_ci num_counters = pmu->nr_arch_fixed_counters; 15162306a36Sopenharmony_ci } else { 15262306a36Sopenharmony_ci counters = pmu->gp_counters; 15362306a36Sopenharmony_ci num_counters = pmu->nr_arch_gp_counters; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci if (idx >= num_counters) 15662306a36Sopenharmony_ci return NULL; 15762306a36Sopenharmony_ci *mask &= pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_PMC_GP]; 15862306a36Sopenharmony_ci return &counters[array_index_nospec(idx, num_counters)]; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic inline u64 vcpu_get_perf_capabilities(struct kvm_vcpu *vcpu) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci if (!guest_cpuid_has(vcpu, X86_FEATURE_PDCM)) 16462306a36Sopenharmony_ci return 0; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci return vcpu->arch.perf_capabilities; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic inline bool fw_writes_is_enabled(struct kvm_vcpu *vcpu) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci return (vcpu_get_perf_capabilities(vcpu) & PMU_CAP_FW_WRITES) != 0; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic inline struct kvm_pmc *get_fw_gp_pmc(struct kvm_pmu *pmu, u32 msr) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci if (!fw_writes_is_enabled(pmu_to_vcpu(pmu))) 17762306a36Sopenharmony_ci return NULL; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci return get_gp_pmc(pmu, msr, MSR_IA32_PMC0); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic bool intel_pmu_is_valid_lbr_msr(struct kvm_vcpu *vcpu, u32 index) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct x86_pmu_lbr *records = vcpu_to_lbr_records(vcpu); 18562306a36Sopenharmony_ci bool ret = false; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (!intel_pmu_lbr_is_enabled(vcpu)) 18862306a36Sopenharmony_ci return ret; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci ret = (index == MSR_LBR_SELECT) || (index == MSR_LBR_TOS) || 19162306a36Sopenharmony_ci (index >= records->from && index < records->from + records->nr) || 19262306a36Sopenharmony_ci (index >= records->to && index < records->to + records->nr); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci if (!ret && records->info) 19562306a36Sopenharmony_ci ret = (index >= records->info && index < records->info + records->nr); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return ret; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 20362306a36Sopenharmony_ci u64 perf_capabilities; 20462306a36Sopenharmony_ci int ret; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci switch (msr) { 20762306a36Sopenharmony_ci case MSR_CORE_PERF_FIXED_CTR_CTRL: 20862306a36Sopenharmony_ci return kvm_pmu_has_perf_global_ctrl(pmu); 20962306a36Sopenharmony_ci case MSR_IA32_PEBS_ENABLE: 21062306a36Sopenharmony_ci ret = vcpu_get_perf_capabilities(vcpu) & PERF_CAP_PEBS_FORMAT; 21162306a36Sopenharmony_ci break; 21262306a36Sopenharmony_ci case MSR_IA32_DS_AREA: 21362306a36Sopenharmony_ci ret = guest_cpuid_has(vcpu, X86_FEATURE_DS); 21462306a36Sopenharmony_ci break; 21562306a36Sopenharmony_ci case MSR_PEBS_DATA_CFG: 21662306a36Sopenharmony_ci perf_capabilities = vcpu_get_perf_capabilities(vcpu); 21762306a36Sopenharmony_ci ret = (perf_capabilities & PERF_CAP_PEBS_BASELINE) && 21862306a36Sopenharmony_ci ((perf_capabilities & PERF_CAP_PEBS_FORMAT) > 3); 21962306a36Sopenharmony_ci break; 22062306a36Sopenharmony_ci default: 22162306a36Sopenharmony_ci ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) || 22262306a36Sopenharmony_ci get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0) || 22362306a36Sopenharmony_ci get_fixed_pmc(pmu, msr) || get_fw_gp_pmc(pmu, msr) || 22462306a36Sopenharmony_ci intel_pmu_is_valid_lbr_msr(vcpu, msr); 22562306a36Sopenharmony_ci break; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return ret; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic struct kvm_pmc *intel_msr_idx_to_pmc(struct kvm_vcpu *vcpu, u32 msr) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 23462306a36Sopenharmony_ci struct kvm_pmc *pmc; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci pmc = get_fixed_pmc(pmu, msr); 23762306a36Sopenharmony_ci pmc = pmc ? pmc : get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0); 23862306a36Sopenharmony_ci pmc = pmc ? pmc : get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci return pmc; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic inline void intel_pmu_release_guest_lbr_event(struct kvm_vcpu *vcpu) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (lbr_desc->event) { 24862306a36Sopenharmony_ci perf_event_release_kernel(lbr_desc->event); 24962306a36Sopenharmony_ci lbr_desc->event = NULL; 25062306a36Sopenharmony_ci vcpu_to_pmu(vcpu)->event_count--; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ciint intel_pmu_create_guest_lbr_event(struct kvm_vcpu *vcpu) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 25762306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 25862306a36Sopenharmony_ci struct perf_event *event; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* 26162306a36Sopenharmony_ci * The perf_event_attr is constructed in the minimum efficient way: 26262306a36Sopenharmony_ci * - set 'pinned = true' to make it task pinned so that if another 26362306a36Sopenharmony_ci * cpu pinned event reclaims LBR, the event->oncpu will be set to -1; 26462306a36Sopenharmony_ci * - set '.exclude_host = true' to record guest branches behavior; 26562306a36Sopenharmony_ci * 26662306a36Sopenharmony_ci * - set '.config = INTEL_FIXED_VLBR_EVENT' to indicates host perf 26762306a36Sopenharmony_ci * schedule the event without a real HW counter but a fake one; 26862306a36Sopenharmony_ci * check is_guest_lbr_event() and __intel_get_event_constraints(); 26962306a36Sopenharmony_ci * 27062306a36Sopenharmony_ci * - set 'sample_type = PERF_SAMPLE_BRANCH_STACK' and 27162306a36Sopenharmony_ci * 'branch_sample_type = PERF_SAMPLE_BRANCH_CALL_STACK | 27262306a36Sopenharmony_ci * PERF_SAMPLE_BRANCH_USER' to configure it as a LBR callstack 27362306a36Sopenharmony_ci * event, which helps KVM to save/restore guest LBR records 27462306a36Sopenharmony_ci * during host context switches and reduces quite a lot overhead, 27562306a36Sopenharmony_ci * check branch_user_callstack() and intel_pmu_lbr_sched_task(); 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ci struct perf_event_attr attr = { 27862306a36Sopenharmony_ci .type = PERF_TYPE_RAW, 27962306a36Sopenharmony_ci .size = sizeof(attr), 28062306a36Sopenharmony_ci .config = INTEL_FIXED_VLBR_EVENT, 28162306a36Sopenharmony_ci .sample_type = PERF_SAMPLE_BRANCH_STACK, 28262306a36Sopenharmony_ci .pinned = true, 28362306a36Sopenharmony_ci .exclude_host = true, 28462306a36Sopenharmony_ci .branch_sample_type = PERF_SAMPLE_BRANCH_CALL_STACK | 28562306a36Sopenharmony_ci PERF_SAMPLE_BRANCH_USER, 28662306a36Sopenharmony_ci }; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (unlikely(lbr_desc->event)) { 28962306a36Sopenharmony_ci __set_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use); 29062306a36Sopenharmony_ci return 0; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci event = perf_event_create_kernel_counter(&attr, -1, 29462306a36Sopenharmony_ci current, NULL, NULL); 29562306a36Sopenharmony_ci if (IS_ERR(event)) { 29662306a36Sopenharmony_ci pr_debug_ratelimited("%s: failed %ld\n", 29762306a36Sopenharmony_ci __func__, PTR_ERR(event)); 29862306a36Sopenharmony_ci return PTR_ERR(event); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci lbr_desc->event = event; 30162306a36Sopenharmony_ci pmu->event_count++; 30262306a36Sopenharmony_ci __set_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use); 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci/* 30762306a36Sopenharmony_ci * It's safe to access LBR msrs from guest when they have not 30862306a36Sopenharmony_ci * been passthrough since the host would help restore or reset 30962306a36Sopenharmony_ci * the LBR msrs records when the guest LBR event is scheduled in. 31062306a36Sopenharmony_ci */ 31162306a36Sopenharmony_cistatic bool intel_pmu_handle_lbr_msrs_access(struct kvm_vcpu *vcpu, 31262306a36Sopenharmony_ci struct msr_data *msr_info, bool read) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 31562306a36Sopenharmony_ci u32 index = msr_info->index; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci if (!intel_pmu_is_valid_lbr_msr(vcpu, index)) 31862306a36Sopenharmony_ci return false; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (!lbr_desc->event && intel_pmu_create_guest_lbr_event(vcpu) < 0) 32162306a36Sopenharmony_ci goto dummy; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* 32462306a36Sopenharmony_ci * Disable irq to ensure the LBR feature doesn't get reclaimed by the 32562306a36Sopenharmony_ci * host at the time the value is read from the msr, and this avoids the 32662306a36Sopenharmony_ci * host LBR value to be leaked to the guest. If LBR has been reclaimed, 32762306a36Sopenharmony_ci * return 0 on guest reads. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci local_irq_disable(); 33062306a36Sopenharmony_ci if (lbr_desc->event->state == PERF_EVENT_STATE_ACTIVE) { 33162306a36Sopenharmony_ci if (read) 33262306a36Sopenharmony_ci rdmsrl(index, msr_info->data); 33362306a36Sopenharmony_ci else 33462306a36Sopenharmony_ci wrmsrl(index, msr_info->data); 33562306a36Sopenharmony_ci __set_bit(INTEL_PMC_IDX_FIXED_VLBR, vcpu_to_pmu(vcpu)->pmc_in_use); 33662306a36Sopenharmony_ci local_irq_enable(); 33762306a36Sopenharmony_ci return true; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci clear_bit(INTEL_PMC_IDX_FIXED_VLBR, vcpu_to_pmu(vcpu)->pmc_in_use); 34062306a36Sopenharmony_ci local_irq_enable(); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cidummy: 34362306a36Sopenharmony_ci if (read) 34462306a36Sopenharmony_ci msr_info->data = 0; 34562306a36Sopenharmony_ci return true; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 35162306a36Sopenharmony_ci struct kvm_pmc *pmc; 35262306a36Sopenharmony_ci u32 msr = msr_info->index; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci switch (msr) { 35562306a36Sopenharmony_ci case MSR_CORE_PERF_FIXED_CTR_CTRL: 35662306a36Sopenharmony_ci msr_info->data = pmu->fixed_ctr_ctrl; 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci case MSR_IA32_PEBS_ENABLE: 35962306a36Sopenharmony_ci msr_info->data = pmu->pebs_enable; 36062306a36Sopenharmony_ci break; 36162306a36Sopenharmony_ci case MSR_IA32_DS_AREA: 36262306a36Sopenharmony_ci msr_info->data = pmu->ds_area; 36362306a36Sopenharmony_ci break; 36462306a36Sopenharmony_ci case MSR_PEBS_DATA_CFG: 36562306a36Sopenharmony_ci msr_info->data = pmu->pebs_data_cfg; 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci default: 36862306a36Sopenharmony_ci if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || 36962306a36Sopenharmony_ci (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { 37062306a36Sopenharmony_ci u64 val = pmc_read_counter(pmc); 37162306a36Sopenharmony_ci msr_info->data = 37262306a36Sopenharmony_ci val & pmu->counter_bitmask[KVM_PMC_GP]; 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci } else if ((pmc = get_fixed_pmc(pmu, msr))) { 37562306a36Sopenharmony_ci u64 val = pmc_read_counter(pmc); 37662306a36Sopenharmony_ci msr_info->data = 37762306a36Sopenharmony_ci val & pmu->counter_bitmask[KVM_PMC_FIXED]; 37862306a36Sopenharmony_ci break; 37962306a36Sopenharmony_ci } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) { 38062306a36Sopenharmony_ci msr_info->data = pmc->eventsel; 38162306a36Sopenharmony_ci break; 38262306a36Sopenharmony_ci } else if (intel_pmu_handle_lbr_msrs_access(vcpu, msr_info, true)) { 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci return 1; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 39462306a36Sopenharmony_ci struct kvm_pmc *pmc; 39562306a36Sopenharmony_ci u32 msr = msr_info->index; 39662306a36Sopenharmony_ci u64 data = msr_info->data; 39762306a36Sopenharmony_ci u64 reserved_bits, diff; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci switch (msr) { 40062306a36Sopenharmony_ci case MSR_CORE_PERF_FIXED_CTR_CTRL: 40162306a36Sopenharmony_ci if (data & pmu->fixed_ctr_ctrl_mask) 40262306a36Sopenharmony_ci return 1; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (pmu->fixed_ctr_ctrl != data) 40562306a36Sopenharmony_ci reprogram_fixed_counters(pmu, data); 40662306a36Sopenharmony_ci break; 40762306a36Sopenharmony_ci case MSR_IA32_PEBS_ENABLE: 40862306a36Sopenharmony_ci if (data & pmu->pebs_enable_mask) 40962306a36Sopenharmony_ci return 1; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (pmu->pebs_enable != data) { 41262306a36Sopenharmony_ci diff = pmu->pebs_enable ^ data; 41362306a36Sopenharmony_ci pmu->pebs_enable = data; 41462306a36Sopenharmony_ci reprogram_counters(pmu, diff); 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci break; 41762306a36Sopenharmony_ci case MSR_IA32_DS_AREA: 41862306a36Sopenharmony_ci if (is_noncanonical_address(data, vcpu)) 41962306a36Sopenharmony_ci return 1; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci pmu->ds_area = data; 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci case MSR_PEBS_DATA_CFG: 42462306a36Sopenharmony_ci if (data & pmu->pebs_data_cfg_mask) 42562306a36Sopenharmony_ci return 1; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci pmu->pebs_data_cfg = data; 42862306a36Sopenharmony_ci break; 42962306a36Sopenharmony_ci default: 43062306a36Sopenharmony_ci if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || 43162306a36Sopenharmony_ci (pmc = get_gp_pmc(pmu, msr, MSR_IA32_PMC0))) { 43262306a36Sopenharmony_ci if ((msr & MSR_PMC_FULL_WIDTH_BIT) && 43362306a36Sopenharmony_ci (data & ~pmu->counter_bitmask[KVM_PMC_GP])) 43462306a36Sopenharmony_ci return 1; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (!msr_info->host_initiated && 43762306a36Sopenharmony_ci !(msr & MSR_PMC_FULL_WIDTH_BIT)) 43862306a36Sopenharmony_ci data = (s64)(s32)data; 43962306a36Sopenharmony_ci pmc_write_counter(pmc, data); 44062306a36Sopenharmony_ci pmc_update_sample_period(pmc); 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci } else if ((pmc = get_fixed_pmc(pmu, msr))) { 44362306a36Sopenharmony_ci pmc_write_counter(pmc, data); 44462306a36Sopenharmony_ci pmc_update_sample_period(pmc); 44562306a36Sopenharmony_ci break; 44662306a36Sopenharmony_ci } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) { 44762306a36Sopenharmony_ci reserved_bits = pmu->reserved_bits; 44862306a36Sopenharmony_ci if ((pmc->idx == 2) && 44962306a36Sopenharmony_ci (pmu->raw_event_mask & HSW_IN_TX_CHECKPOINTED)) 45062306a36Sopenharmony_ci reserved_bits ^= HSW_IN_TX_CHECKPOINTED; 45162306a36Sopenharmony_ci if (data & reserved_bits) 45262306a36Sopenharmony_ci return 1; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (data != pmc->eventsel) { 45562306a36Sopenharmony_ci pmc->eventsel = data; 45662306a36Sopenharmony_ci kvm_pmu_request_counter_reprogram(pmc); 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci break; 45962306a36Sopenharmony_ci } else if (intel_pmu_handle_lbr_msrs_access(vcpu, msr_info, false)) { 46062306a36Sopenharmony_ci break; 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci /* Not a known PMU MSR. */ 46362306a36Sopenharmony_ci return 1; 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic void setup_fixed_pmc_eventsel(struct kvm_pmu *pmu) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci int i; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(fixed_pmc_events) != KVM_PMC_MAX_FIXED); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { 47662306a36Sopenharmony_ci int index = array_index_nospec(i, KVM_PMC_MAX_FIXED); 47762306a36Sopenharmony_ci struct kvm_pmc *pmc = &pmu->fixed_counters[index]; 47862306a36Sopenharmony_ci u32 event = fixed_pmc_events[index]; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci pmc->eventsel = (intel_arch_events[event].unit_mask << 8) | 48162306a36Sopenharmony_ci intel_arch_events[event].eventsel; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic void intel_pmu_refresh(struct kvm_vcpu *vcpu) 48662306a36Sopenharmony_ci{ 48762306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 48862306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 48962306a36Sopenharmony_ci struct kvm_cpuid_entry2 *entry; 49062306a36Sopenharmony_ci union cpuid10_eax eax; 49162306a36Sopenharmony_ci union cpuid10_edx edx; 49262306a36Sopenharmony_ci u64 perf_capabilities; 49362306a36Sopenharmony_ci u64 counter_mask; 49462306a36Sopenharmony_ci int i; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci pmu->nr_arch_gp_counters = 0; 49762306a36Sopenharmony_ci pmu->nr_arch_fixed_counters = 0; 49862306a36Sopenharmony_ci pmu->counter_bitmask[KVM_PMC_GP] = 0; 49962306a36Sopenharmony_ci pmu->counter_bitmask[KVM_PMC_FIXED] = 0; 50062306a36Sopenharmony_ci pmu->version = 0; 50162306a36Sopenharmony_ci pmu->reserved_bits = 0xffffffff00200000ull; 50262306a36Sopenharmony_ci pmu->raw_event_mask = X86_RAW_EVENT_MASK; 50362306a36Sopenharmony_ci pmu->global_ctrl_mask = ~0ull; 50462306a36Sopenharmony_ci pmu->global_status_mask = ~0ull; 50562306a36Sopenharmony_ci pmu->fixed_ctr_ctrl_mask = ~0ull; 50662306a36Sopenharmony_ci pmu->pebs_enable_mask = ~0ull; 50762306a36Sopenharmony_ci pmu->pebs_data_cfg_mask = ~0ull; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci memset(&lbr_desc->records, 0, sizeof(lbr_desc->records)); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* 51262306a36Sopenharmony_ci * Setting passthrough of LBR MSRs is done only in the VM-Entry loop, 51362306a36Sopenharmony_ci * and PMU refresh is disallowed after the vCPU has run, i.e. this code 51462306a36Sopenharmony_ci * should never be reached while KVM is passing through MSRs. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_ci if (KVM_BUG_ON(lbr_desc->msr_passthrough, vcpu->kvm)) 51762306a36Sopenharmony_ci return; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci entry = kvm_find_cpuid_entry(vcpu, 0xa); 52062306a36Sopenharmony_ci if (!entry || !vcpu->kvm->arch.enable_pmu) 52162306a36Sopenharmony_ci return; 52262306a36Sopenharmony_ci eax.full = entry->eax; 52362306a36Sopenharmony_ci edx.full = entry->edx; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci pmu->version = eax.split.version_id; 52662306a36Sopenharmony_ci if (!pmu->version) 52762306a36Sopenharmony_ci return; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters, 53062306a36Sopenharmony_ci kvm_pmu_cap.num_counters_gp); 53162306a36Sopenharmony_ci eax.split.bit_width = min_t(int, eax.split.bit_width, 53262306a36Sopenharmony_ci kvm_pmu_cap.bit_width_gp); 53362306a36Sopenharmony_ci pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << eax.split.bit_width) - 1; 53462306a36Sopenharmony_ci eax.split.mask_length = min_t(int, eax.split.mask_length, 53562306a36Sopenharmony_ci kvm_pmu_cap.events_mask_len); 53662306a36Sopenharmony_ci pmu->available_event_types = ~entry->ebx & 53762306a36Sopenharmony_ci ((1ull << eax.split.mask_length) - 1); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci if (pmu->version == 1) { 54062306a36Sopenharmony_ci pmu->nr_arch_fixed_counters = 0; 54162306a36Sopenharmony_ci } else { 54262306a36Sopenharmony_ci pmu->nr_arch_fixed_counters = min_t(int, edx.split.num_counters_fixed, 54362306a36Sopenharmony_ci kvm_pmu_cap.num_counters_fixed); 54462306a36Sopenharmony_ci edx.split.bit_width_fixed = min_t(int, edx.split.bit_width_fixed, 54562306a36Sopenharmony_ci kvm_pmu_cap.bit_width_fixed); 54662306a36Sopenharmony_ci pmu->counter_bitmask[KVM_PMC_FIXED] = 54762306a36Sopenharmony_ci ((u64)1 << edx.split.bit_width_fixed) - 1; 54862306a36Sopenharmony_ci setup_fixed_pmc_eventsel(pmu); 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci for (i = 0; i < pmu->nr_arch_fixed_counters; i++) 55262306a36Sopenharmony_ci pmu->fixed_ctr_ctrl_mask &= ~(0xbull << (i * 4)); 55362306a36Sopenharmony_ci counter_mask = ~(((1ull << pmu->nr_arch_gp_counters) - 1) | 55462306a36Sopenharmony_ci (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED)); 55562306a36Sopenharmony_ci pmu->global_ctrl_mask = counter_mask; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci /* 55862306a36Sopenharmony_ci * GLOBAL_STATUS and GLOBAL_OVF_CONTROL (a.k.a. GLOBAL_STATUS_RESET) 55962306a36Sopenharmony_ci * share reserved bit definitions. The kernel just happens to use 56062306a36Sopenharmony_ci * OVF_CTRL for the names. 56162306a36Sopenharmony_ci */ 56262306a36Sopenharmony_ci pmu->global_status_mask = pmu->global_ctrl_mask 56362306a36Sopenharmony_ci & ~(MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF | 56462306a36Sopenharmony_ci MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD); 56562306a36Sopenharmony_ci if (vmx_pt_mode_is_host_guest()) 56662306a36Sopenharmony_ci pmu->global_status_mask &= 56762306a36Sopenharmony_ci ~MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci entry = kvm_find_cpuid_entry_index(vcpu, 7, 0); 57062306a36Sopenharmony_ci if (entry && 57162306a36Sopenharmony_ci (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) && 57262306a36Sopenharmony_ci (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM))) { 57362306a36Sopenharmony_ci pmu->reserved_bits ^= HSW_IN_TX; 57462306a36Sopenharmony_ci pmu->raw_event_mask |= (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED); 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci bitmap_set(pmu->all_valid_pmc_idx, 57862306a36Sopenharmony_ci 0, pmu->nr_arch_gp_counters); 57962306a36Sopenharmony_ci bitmap_set(pmu->all_valid_pmc_idx, 58062306a36Sopenharmony_ci INTEL_PMC_MAX_GENERIC, pmu->nr_arch_fixed_counters); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci perf_capabilities = vcpu_get_perf_capabilities(vcpu); 58362306a36Sopenharmony_ci if (cpuid_model_is_consistent(vcpu) && 58462306a36Sopenharmony_ci (perf_capabilities & PMU_CAP_LBR_FMT)) 58562306a36Sopenharmony_ci x86_perf_get_lbr(&lbr_desc->records); 58662306a36Sopenharmony_ci else 58762306a36Sopenharmony_ci lbr_desc->records.nr = 0; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci if (lbr_desc->records.nr) 59062306a36Sopenharmony_ci bitmap_set(pmu->all_valid_pmc_idx, INTEL_PMC_IDX_FIXED_VLBR, 1); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci if (perf_capabilities & PERF_CAP_PEBS_FORMAT) { 59362306a36Sopenharmony_ci if (perf_capabilities & PERF_CAP_PEBS_BASELINE) { 59462306a36Sopenharmony_ci pmu->pebs_enable_mask = counter_mask; 59562306a36Sopenharmony_ci pmu->reserved_bits &= ~ICL_EVENTSEL_ADAPTIVE; 59662306a36Sopenharmony_ci for (i = 0; i < pmu->nr_arch_fixed_counters; i++) { 59762306a36Sopenharmony_ci pmu->fixed_ctr_ctrl_mask &= 59862306a36Sopenharmony_ci ~(1ULL << (INTEL_PMC_IDX_FIXED + i * 4)); 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci pmu->pebs_data_cfg_mask = ~0xff00000full; 60162306a36Sopenharmony_ci } else { 60262306a36Sopenharmony_ci pmu->pebs_enable_mask = 60362306a36Sopenharmony_ci ~((1ull << pmu->nr_arch_gp_counters) - 1); 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic void intel_pmu_init(struct kvm_vcpu *vcpu) 60962306a36Sopenharmony_ci{ 61062306a36Sopenharmony_ci int i; 61162306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 61262306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci for (i = 0; i < KVM_INTEL_PMC_MAX_GENERIC; i++) { 61562306a36Sopenharmony_ci pmu->gp_counters[i].type = KVM_PMC_GP; 61662306a36Sopenharmony_ci pmu->gp_counters[i].vcpu = vcpu; 61762306a36Sopenharmony_ci pmu->gp_counters[i].idx = i; 61862306a36Sopenharmony_ci pmu->gp_counters[i].current_config = 0; 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci for (i = 0; i < KVM_PMC_MAX_FIXED; i++) { 62262306a36Sopenharmony_ci pmu->fixed_counters[i].type = KVM_PMC_FIXED; 62362306a36Sopenharmony_ci pmu->fixed_counters[i].vcpu = vcpu; 62462306a36Sopenharmony_ci pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED; 62562306a36Sopenharmony_ci pmu->fixed_counters[i].current_config = 0; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci lbr_desc->records.nr = 0; 62962306a36Sopenharmony_ci lbr_desc->event = NULL; 63062306a36Sopenharmony_ci lbr_desc->msr_passthrough = false; 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic void intel_pmu_reset(struct kvm_vcpu *vcpu) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci intel_pmu_release_guest_lbr_event(vcpu); 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci/* 63962306a36Sopenharmony_ci * Emulate LBR_On_PMI behavior for 1 < pmu.version < 4. 64062306a36Sopenharmony_ci * 64162306a36Sopenharmony_ci * If Freeze_LBR_On_PMI = 1, the LBR is frozen on PMI and 64262306a36Sopenharmony_ci * the KVM emulates to clear the LBR bit (bit 0) in IA32_DEBUGCTL. 64362306a36Sopenharmony_ci * 64462306a36Sopenharmony_ci * Guest needs to re-enable LBR to resume branches recording. 64562306a36Sopenharmony_ci */ 64662306a36Sopenharmony_cistatic void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) { 65162306a36Sopenharmony_ci data &= ~DEBUGCTLMSR_LBR; 65262306a36Sopenharmony_ci vmcs_write64(GUEST_IA32_DEBUGCTL, data); 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic void intel_pmu_deliver_pmi(struct kvm_vcpu *vcpu) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci u8 version = vcpu_to_pmu(vcpu)->version; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (!intel_pmu_lbr_is_enabled(vcpu)) 66162306a36Sopenharmony_ci return; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (version > 1 && version < 4) 66462306a36Sopenharmony_ci intel_pmu_legacy_freezing_lbrs_on_pmi(vcpu); 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic void vmx_update_intercept_for_lbr_msrs(struct kvm_vcpu *vcpu, bool set) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci struct x86_pmu_lbr *lbr = vcpu_to_lbr_records(vcpu); 67062306a36Sopenharmony_ci int i; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci for (i = 0; i < lbr->nr; i++) { 67362306a36Sopenharmony_ci vmx_set_intercept_for_msr(vcpu, lbr->from + i, MSR_TYPE_RW, set); 67462306a36Sopenharmony_ci vmx_set_intercept_for_msr(vcpu, lbr->to + i, MSR_TYPE_RW, set); 67562306a36Sopenharmony_ci if (lbr->info) 67662306a36Sopenharmony_ci vmx_set_intercept_for_msr(vcpu, lbr->info + i, MSR_TYPE_RW, set); 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci vmx_set_intercept_for_msr(vcpu, MSR_LBR_SELECT, MSR_TYPE_RW, set); 68062306a36Sopenharmony_ci vmx_set_intercept_for_msr(vcpu, MSR_LBR_TOS, MSR_TYPE_RW, set); 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cistatic inline void vmx_disable_lbr_msrs_passthrough(struct kvm_vcpu *vcpu) 68462306a36Sopenharmony_ci{ 68562306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci if (!lbr_desc->msr_passthrough) 68862306a36Sopenharmony_ci return; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci vmx_update_intercept_for_lbr_msrs(vcpu, true); 69162306a36Sopenharmony_ci lbr_desc->msr_passthrough = false; 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic inline void vmx_enable_lbr_msrs_passthrough(struct kvm_vcpu *vcpu) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci if (lbr_desc->msr_passthrough) 69962306a36Sopenharmony_ci return; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci vmx_update_intercept_for_lbr_msrs(vcpu, false); 70262306a36Sopenharmony_ci lbr_desc->msr_passthrough = true; 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci/* 70662306a36Sopenharmony_ci * Higher priority host perf events (e.g. cpu pinned) could reclaim the 70762306a36Sopenharmony_ci * pmu resources (e.g. LBR) that were assigned to the guest. This is 70862306a36Sopenharmony_ci * usually done via ipi calls (more details in perf_install_in_context). 70962306a36Sopenharmony_ci * 71062306a36Sopenharmony_ci * Before entering the non-root mode (with irq disabled here), double 71162306a36Sopenharmony_ci * confirm that the pmu features enabled to the guest are not reclaimed 71262306a36Sopenharmony_ci * by higher priority host events. Otherwise, disallow vcpu's access to 71362306a36Sopenharmony_ci * the reclaimed features. 71462306a36Sopenharmony_ci */ 71562306a36Sopenharmony_civoid vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci struct kvm_pmu *pmu = vcpu_to_pmu(vcpu); 71862306a36Sopenharmony_ci struct lbr_desc *lbr_desc = vcpu_to_lbr_desc(vcpu); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci if (!lbr_desc->event) { 72162306a36Sopenharmony_ci vmx_disable_lbr_msrs_passthrough(vcpu); 72262306a36Sopenharmony_ci if (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR) 72362306a36Sopenharmony_ci goto warn; 72462306a36Sopenharmony_ci if (test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use)) 72562306a36Sopenharmony_ci goto warn; 72662306a36Sopenharmony_ci return; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci if (lbr_desc->event->state < PERF_EVENT_STATE_ACTIVE) { 73062306a36Sopenharmony_ci vmx_disable_lbr_msrs_passthrough(vcpu); 73162306a36Sopenharmony_ci __clear_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use); 73262306a36Sopenharmony_ci goto warn; 73362306a36Sopenharmony_ci } else 73462306a36Sopenharmony_ci vmx_enable_lbr_msrs_passthrough(vcpu); 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci return; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ciwarn: 73962306a36Sopenharmony_ci pr_warn_ratelimited("vcpu-%d: fail to passthrough LBR.\n", vcpu->vcpu_id); 74062306a36Sopenharmony_ci} 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_cistatic void intel_pmu_cleanup(struct kvm_vcpu *vcpu) 74362306a36Sopenharmony_ci{ 74462306a36Sopenharmony_ci if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)) 74562306a36Sopenharmony_ci intel_pmu_release_guest_lbr_event(vcpu); 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_civoid intel_pmu_cross_mapped_check(struct kvm_pmu *pmu) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct kvm_pmc *pmc = NULL; 75162306a36Sopenharmony_ci int bit, hw_idx; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci for_each_set_bit(bit, (unsigned long *)&pmu->global_ctrl, 75462306a36Sopenharmony_ci X86_PMC_IDX_MAX) { 75562306a36Sopenharmony_ci pmc = intel_pmc_idx_to_pmc(pmu, bit); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci if (!pmc || !pmc_speculative_in_use(pmc) || 75862306a36Sopenharmony_ci !pmc_is_globally_enabled(pmc) || !pmc->perf_event) 75962306a36Sopenharmony_ci continue; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci /* 76262306a36Sopenharmony_ci * A negative index indicates the event isn't mapped to a 76362306a36Sopenharmony_ci * physical counter in the host, e.g. due to contention. 76462306a36Sopenharmony_ci */ 76562306a36Sopenharmony_ci hw_idx = pmc->perf_event->hw.idx; 76662306a36Sopenharmony_ci if (hw_idx != pmc->idx && hw_idx > -1) 76762306a36Sopenharmony_ci pmu->host_cross_mapped_mask |= BIT_ULL(hw_idx); 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci} 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_cistruct kvm_pmu_ops intel_pmu_ops __initdata = { 77262306a36Sopenharmony_ci .hw_event_available = intel_hw_event_available, 77362306a36Sopenharmony_ci .pmc_idx_to_pmc = intel_pmc_idx_to_pmc, 77462306a36Sopenharmony_ci .rdpmc_ecx_to_pmc = intel_rdpmc_ecx_to_pmc, 77562306a36Sopenharmony_ci .msr_idx_to_pmc = intel_msr_idx_to_pmc, 77662306a36Sopenharmony_ci .is_valid_rdpmc_ecx = intel_is_valid_rdpmc_ecx, 77762306a36Sopenharmony_ci .is_valid_msr = intel_is_valid_msr, 77862306a36Sopenharmony_ci .get_msr = intel_pmu_get_msr, 77962306a36Sopenharmony_ci .set_msr = intel_pmu_set_msr, 78062306a36Sopenharmony_ci .refresh = intel_pmu_refresh, 78162306a36Sopenharmony_ci .init = intel_pmu_init, 78262306a36Sopenharmony_ci .reset = intel_pmu_reset, 78362306a36Sopenharmony_ci .deliver_pmi = intel_pmu_deliver_pmi, 78462306a36Sopenharmony_ci .cleanup = intel_pmu_cleanup, 78562306a36Sopenharmony_ci .EVENTSEL_EVENT = ARCH_PERFMON_EVENTSEL_EVENT, 78662306a36Sopenharmony_ci .MAX_NR_GP_COUNTERS = KVM_INTEL_PMC_MAX_GENERIC, 78762306a36Sopenharmony_ci .MIN_NR_GP_COUNTERS = 1, 78862306a36Sopenharmony_ci}; 789