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