xref: /openbmc/linux/arch/arm64/kvm/pmu-emul.c (revision 8e26d11f)
19ed24f4bSMarc Zyngier // SPDX-License-Identifier: GPL-2.0-only
29ed24f4bSMarc Zyngier /*
39ed24f4bSMarc Zyngier  * Copyright (C) 2015 Linaro Ltd.
49ed24f4bSMarc Zyngier  * Author: Shannon Zhao <shannon.zhao@linaro.org>
59ed24f4bSMarc Zyngier  */
69ed24f4bSMarc Zyngier 
79ed24f4bSMarc Zyngier #include <linux/cpu.h>
89ed24f4bSMarc Zyngier #include <linux/kvm.h>
99ed24f4bSMarc Zyngier #include <linux/kvm_host.h>
109ed24f4bSMarc Zyngier #include <linux/perf_event.h>
119ed24f4bSMarc Zyngier #include <linux/perf/arm_pmu.h>
129ed24f4bSMarc Zyngier #include <linux/uaccess.h>
139ed24f4bSMarc Zyngier #include <asm/kvm_emulate.h>
149ed24f4bSMarc Zyngier #include <kvm/arm_pmu.h>
159ed24f4bSMarc Zyngier #include <kvm/arm_vgic.h>
169ed24f4bSMarc Zyngier 
179ed24f4bSMarc Zyngier static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx);
189ed24f4bSMarc Zyngier static void kvm_pmu_update_pmc_chained(struct kvm_vcpu *vcpu, u64 select_idx);
199ed24f4bSMarc Zyngier static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc);
209ed24f4bSMarc Zyngier 
219ed24f4bSMarc Zyngier #define PERF_ATTR_CFG1_KVM_PMU_CHAINED 0x1
229ed24f4bSMarc Zyngier 
23fd65a3b5SMarc Zyngier static u32 kvm_pmu_event_mask(struct kvm *kvm)
24fd65a3b5SMarc Zyngier {
25fd65a3b5SMarc Zyngier 	switch (kvm->arch.pmuver) {
26*8e26d11fSMarc Zyngier 	case ID_AA64DFR0_PMUVER_8_0:
27fd65a3b5SMarc Zyngier 		return GENMASK(9, 0);
28*8e26d11fSMarc Zyngier 	case ID_AA64DFR0_PMUVER_8_1:
29*8e26d11fSMarc Zyngier 	case ID_AA64DFR0_PMUVER_8_4:
30*8e26d11fSMarc Zyngier 	case ID_AA64DFR0_PMUVER_8_5:
31fd65a3b5SMarc Zyngier 		return GENMASK(15, 0);
32fd65a3b5SMarc Zyngier 	default:		/* Shouldn't be here, just for sanity */
33fd65a3b5SMarc Zyngier 		WARN_ONCE(1, "Unknown PMU version %d\n", kvm->arch.pmuver);
34fd65a3b5SMarc Zyngier 		return 0;
35fd65a3b5SMarc Zyngier 	}
36fd65a3b5SMarc Zyngier }
37fd65a3b5SMarc Zyngier 
389ed24f4bSMarc Zyngier /**
399ed24f4bSMarc Zyngier  * kvm_pmu_idx_is_64bit - determine if select_idx is a 64bit counter
409ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
419ed24f4bSMarc Zyngier  * @select_idx: The counter index
429ed24f4bSMarc Zyngier  */
439ed24f4bSMarc Zyngier static bool kvm_pmu_idx_is_64bit(struct kvm_vcpu *vcpu, u64 select_idx)
449ed24f4bSMarc Zyngier {
459ed24f4bSMarc Zyngier 	return (select_idx == ARMV8_PMU_CYCLE_IDX &&
469ed24f4bSMarc Zyngier 		__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_LC);
479ed24f4bSMarc Zyngier }
489ed24f4bSMarc Zyngier 
499ed24f4bSMarc Zyngier static struct kvm_vcpu *kvm_pmc_to_vcpu(struct kvm_pmc *pmc)
509ed24f4bSMarc Zyngier {
519ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu;
529ed24f4bSMarc Zyngier 	struct kvm_vcpu_arch *vcpu_arch;
539ed24f4bSMarc Zyngier 
549ed24f4bSMarc Zyngier 	pmc -= pmc->idx;
559ed24f4bSMarc Zyngier 	pmu = container_of(pmc, struct kvm_pmu, pmc[0]);
569ed24f4bSMarc Zyngier 	vcpu_arch = container_of(pmu, struct kvm_vcpu_arch, pmu);
579ed24f4bSMarc Zyngier 	return container_of(vcpu_arch, struct kvm_vcpu, arch);
589ed24f4bSMarc Zyngier }
599ed24f4bSMarc Zyngier 
609ed24f4bSMarc Zyngier /**
619ed24f4bSMarc Zyngier  * kvm_pmu_pmc_is_chained - determine if the pmc is chained
629ed24f4bSMarc Zyngier  * @pmc: The PMU counter pointer
639ed24f4bSMarc Zyngier  */
649ed24f4bSMarc Zyngier static bool kvm_pmu_pmc_is_chained(struct kvm_pmc *pmc)
659ed24f4bSMarc Zyngier {
669ed24f4bSMarc Zyngier 	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
679ed24f4bSMarc Zyngier 
689ed24f4bSMarc Zyngier 	return test_bit(pmc->idx >> 1, vcpu->arch.pmu.chained);
699ed24f4bSMarc Zyngier }
709ed24f4bSMarc Zyngier 
719ed24f4bSMarc Zyngier /**
729ed24f4bSMarc Zyngier  * kvm_pmu_idx_is_high_counter - determine if select_idx is a high/low counter
739ed24f4bSMarc Zyngier  * @select_idx: The counter index
749ed24f4bSMarc Zyngier  */
759ed24f4bSMarc Zyngier static bool kvm_pmu_idx_is_high_counter(u64 select_idx)
769ed24f4bSMarc Zyngier {
779ed24f4bSMarc Zyngier 	return select_idx & 0x1;
789ed24f4bSMarc Zyngier }
799ed24f4bSMarc Zyngier 
809ed24f4bSMarc Zyngier /**
819ed24f4bSMarc Zyngier  * kvm_pmu_get_canonical_pmc - obtain the canonical pmc
829ed24f4bSMarc Zyngier  * @pmc: The PMU counter pointer
839ed24f4bSMarc Zyngier  *
849ed24f4bSMarc Zyngier  * When a pair of PMCs are chained together we use the low counter (canonical)
859ed24f4bSMarc Zyngier  * to hold the underlying perf event.
869ed24f4bSMarc Zyngier  */
879ed24f4bSMarc Zyngier static struct kvm_pmc *kvm_pmu_get_canonical_pmc(struct kvm_pmc *pmc)
889ed24f4bSMarc Zyngier {
899ed24f4bSMarc Zyngier 	if (kvm_pmu_pmc_is_chained(pmc) &&
909ed24f4bSMarc Zyngier 	    kvm_pmu_idx_is_high_counter(pmc->idx))
919ed24f4bSMarc Zyngier 		return pmc - 1;
929ed24f4bSMarc Zyngier 
939ed24f4bSMarc Zyngier 	return pmc;
949ed24f4bSMarc Zyngier }
959ed24f4bSMarc Zyngier static struct kvm_pmc *kvm_pmu_get_alternate_pmc(struct kvm_pmc *pmc)
969ed24f4bSMarc Zyngier {
979ed24f4bSMarc Zyngier 	if (kvm_pmu_idx_is_high_counter(pmc->idx))
989ed24f4bSMarc Zyngier 		return pmc - 1;
999ed24f4bSMarc Zyngier 	else
1009ed24f4bSMarc Zyngier 		return pmc + 1;
1019ed24f4bSMarc Zyngier }
1029ed24f4bSMarc Zyngier 
1039ed24f4bSMarc Zyngier /**
1049ed24f4bSMarc Zyngier  * kvm_pmu_idx_has_chain_evtype - determine if the event type is chain
1059ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
1069ed24f4bSMarc Zyngier  * @select_idx: The counter index
1079ed24f4bSMarc Zyngier  */
1089ed24f4bSMarc Zyngier static bool kvm_pmu_idx_has_chain_evtype(struct kvm_vcpu *vcpu, u64 select_idx)
1099ed24f4bSMarc Zyngier {
1109ed24f4bSMarc Zyngier 	u64 eventsel, reg;
1119ed24f4bSMarc Zyngier 
1129ed24f4bSMarc Zyngier 	select_idx |= 0x1;
1139ed24f4bSMarc Zyngier 
1149ed24f4bSMarc Zyngier 	if (select_idx == ARMV8_PMU_CYCLE_IDX)
1159ed24f4bSMarc Zyngier 		return false;
1169ed24f4bSMarc Zyngier 
1179ed24f4bSMarc Zyngier 	reg = PMEVTYPER0_EL0 + select_idx;
118fd65a3b5SMarc Zyngier 	eventsel = __vcpu_sys_reg(vcpu, reg) & kvm_pmu_event_mask(vcpu->kvm);
1199ed24f4bSMarc Zyngier 
1209ed24f4bSMarc Zyngier 	return eventsel == ARMV8_PMUV3_PERFCTR_CHAIN;
1219ed24f4bSMarc Zyngier }
1229ed24f4bSMarc Zyngier 
1239ed24f4bSMarc Zyngier /**
1249ed24f4bSMarc Zyngier  * kvm_pmu_get_pair_counter_value - get PMU counter value
1259ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
1269ed24f4bSMarc Zyngier  * @pmc: The PMU counter pointer
1279ed24f4bSMarc Zyngier  */
1289ed24f4bSMarc Zyngier static u64 kvm_pmu_get_pair_counter_value(struct kvm_vcpu *vcpu,
1299ed24f4bSMarc Zyngier 					  struct kvm_pmc *pmc)
1309ed24f4bSMarc Zyngier {
1319ed24f4bSMarc Zyngier 	u64 counter, counter_high, reg, enabled, running;
1329ed24f4bSMarc Zyngier 
1339ed24f4bSMarc Zyngier 	if (kvm_pmu_pmc_is_chained(pmc)) {
1349ed24f4bSMarc Zyngier 		pmc = kvm_pmu_get_canonical_pmc(pmc);
1359ed24f4bSMarc Zyngier 		reg = PMEVCNTR0_EL0 + pmc->idx;
1369ed24f4bSMarc Zyngier 
1379ed24f4bSMarc Zyngier 		counter = __vcpu_sys_reg(vcpu, reg);
1389ed24f4bSMarc Zyngier 		counter_high = __vcpu_sys_reg(vcpu, reg + 1);
1399ed24f4bSMarc Zyngier 
1409ed24f4bSMarc Zyngier 		counter = lower_32_bits(counter) | (counter_high << 32);
1419ed24f4bSMarc Zyngier 	} else {
1429ed24f4bSMarc Zyngier 		reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
1439ed24f4bSMarc Zyngier 		      ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx;
1449ed24f4bSMarc Zyngier 		counter = __vcpu_sys_reg(vcpu, reg);
1459ed24f4bSMarc Zyngier 	}
1469ed24f4bSMarc Zyngier 
1479ed24f4bSMarc Zyngier 	/*
1489ed24f4bSMarc Zyngier 	 * The real counter value is equal to the value of counter register plus
1499ed24f4bSMarc Zyngier 	 * the value perf event counts.
1509ed24f4bSMarc Zyngier 	 */
1519ed24f4bSMarc Zyngier 	if (pmc->perf_event)
1529ed24f4bSMarc Zyngier 		counter += perf_event_read_value(pmc->perf_event, &enabled,
1539ed24f4bSMarc Zyngier 						 &running);
1549ed24f4bSMarc Zyngier 
1559ed24f4bSMarc Zyngier 	return counter;
1569ed24f4bSMarc Zyngier }
1579ed24f4bSMarc Zyngier 
1589ed24f4bSMarc Zyngier /**
1599ed24f4bSMarc Zyngier  * kvm_pmu_get_counter_value - get PMU counter value
1609ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
1619ed24f4bSMarc Zyngier  * @select_idx: The counter index
1629ed24f4bSMarc Zyngier  */
1639ed24f4bSMarc Zyngier u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
1649ed24f4bSMarc Zyngier {
1659ed24f4bSMarc Zyngier 	u64 counter;
1669ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
1679ed24f4bSMarc Zyngier 	struct kvm_pmc *pmc = &pmu->pmc[select_idx];
1689ed24f4bSMarc Zyngier 
1699ed24f4bSMarc Zyngier 	counter = kvm_pmu_get_pair_counter_value(vcpu, pmc);
1709ed24f4bSMarc Zyngier 
1719ed24f4bSMarc Zyngier 	if (kvm_pmu_pmc_is_chained(pmc) &&
1729ed24f4bSMarc Zyngier 	    kvm_pmu_idx_is_high_counter(select_idx))
1739ed24f4bSMarc Zyngier 		counter = upper_32_bits(counter);
1749ed24f4bSMarc Zyngier 	else if (select_idx != ARMV8_PMU_CYCLE_IDX)
1759ed24f4bSMarc Zyngier 		counter = lower_32_bits(counter);
1769ed24f4bSMarc Zyngier 
1779ed24f4bSMarc Zyngier 	return counter;
1789ed24f4bSMarc Zyngier }
1799ed24f4bSMarc Zyngier 
1809ed24f4bSMarc Zyngier /**
1819ed24f4bSMarc Zyngier  * kvm_pmu_set_counter_value - set PMU counter value
1829ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
1839ed24f4bSMarc Zyngier  * @select_idx: The counter index
1849ed24f4bSMarc Zyngier  * @val: The counter value
1859ed24f4bSMarc Zyngier  */
1869ed24f4bSMarc Zyngier void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
1879ed24f4bSMarc Zyngier {
1889ed24f4bSMarc Zyngier 	u64 reg;
1899ed24f4bSMarc Zyngier 
1909ed24f4bSMarc Zyngier 	reg = (select_idx == ARMV8_PMU_CYCLE_IDX)
1919ed24f4bSMarc Zyngier 	      ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx;
1929ed24f4bSMarc Zyngier 	__vcpu_sys_reg(vcpu, reg) += (s64)val - kvm_pmu_get_counter_value(vcpu, select_idx);
1939ed24f4bSMarc Zyngier 
1949ed24f4bSMarc Zyngier 	/* Recreate the perf event to reflect the updated sample_period */
1959ed24f4bSMarc Zyngier 	kvm_pmu_create_perf_event(vcpu, select_idx);
1969ed24f4bSMarc Zyngier }
1979ed24f4bSMarc Zyngier 
1989ed24f4bSMarc Zyngier /**
1999ed24f4bSMarc Zyngier  * kvm_pmu_release_perf_event - remove the perf event
2009ed24f4bSMarc Zyngier  * @pmc: The PMU counter pointer
2019ed24f4bSMarc Zyngier  */
2029ed24f4bSMarc Zyngier static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc)
2039ed24f4bSMarc Zyngier {
2049ed24f4bSMarc Zyngier 	pmc = kvm_pmu_get_canonical_pmc(pmc);
2059ed24f4bSMarc Zyngier 	if (pmc->perf_event) {
2069ed24f4bSMarc Zyngier 		perf_event_disable(pmc->perf_event);
2079ed24f4bSMarc Zyngier 		perf_event_release_kernel(pmc->perf_event);
2089ed24f4bSMarc Zyngier 		pmc->perf_event = NULL;
2099ed24f4bSMarc Zyngier 	}
2109ed24f4bSMarc Zyngier }
2119ed24f4bSMarc Zyngier 
2129ed24f4bSMarc Zyngier /**
2139ed24f4bSMarc Zyngier  * kvm_pmu_stop_counter - stop PMU counter
2149ed24f4bSMarc Zyngier  * @pmc: The PMU counter pointer
2159ed24f4bSMarc Zyngier  *
2169ed24f4bSMarc Zyngier  * If this counter has been configured to monitor some event, release it here.
2179ed24f4bSMarc Zyngier  */
2189ed24f4bSMarc Zyngier static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
2199ed24f4bSMarc Zyngier {
2209ed24f4bSMarc Zyngier 	u64 counter, reg, val;
2219ed24f4bSMarc Zyngier 
2229ed24f4bSMarc Zyngier 	pmc = kvm_pmu_get_canonical_pmc(pmc);
2239ed24f4bSMarc Zyngier 	if (!pmc->perf_event)
2249ed24f4bSMarc Zyngier 		return;
2259ed24f4bSMarc Zyngier 
2269ed24f4bSMarc Zyngier 	counter = kvm_pmu_get_pair_counter_value(vcpu, pmc);
2279ed24f4bSMarc Zyngier 
2289ed24f4bSMarc Zyngier 	if (pmc->idx == ARMV8_PMU_CYCLE_IDX) {
2299ed24f4bSMarc Zyngier 		reg = PMCCNTR_EL0;
2309ed24f4bSMarc Zyngier 		val = counter;
2319ed24f4bSMarc Zyngier 	} else {
2329ed24f4bSMarc Zyngier 		reg = PMEVCNTR0_EL0 + pmc->idx;
2339ed24f4bSMarc Zyngier 		val = lower_32_bits(counter);
2349ed24f4bSMarc Zyngier 	}
2359ed24f4bSMarc Zyngier 
2369ed24f4bSMarc Zyngier 	__vcpu_sys_reg(vcpu, reg) = val;
2379ed24f4bSMarc Zyngier 
2389ed24f4bSMarc Zyngier 	if (kvm_pmu_pmc_is_chained(pmc))
2399ed24f4bSMarc Zyngier 		__vcpu_sys_reg(vcpu, reg + 1) = upper_32_bits(counter);
2409ed24f4bSMarc Zyngier 
2419ed24f4bSMarc Zyngier 	kvm_pmu_release_perf_event(pmc);
2429ed24f4bSMarc Zyngier }
2439ed24f4bSMarc Zyngier 
2449ed24f4bSMarc Zyngier /**
2459ed24f4bSMarc Zyngier  * kvm_pmu_vcpu_init - assign pmu counter idx for cpu
2469ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
2479ed24f4bSMarc Zyngier  *
2489ed24f4bSMarc Zyngier  */
2499ed24f4bSMarc Zyngier void kvm_pmu_vcpu_init(struct kvm_vcpu *vcpu)
2509ed24f4bSMarc Zyngier {
2519ed24f4bSMarc Zyngier 	int i;
2529ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
2539ed24f4bSMarc Zyngier 
2549ed24f4bSMarc Zyngier 	for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
2559ed24f4bSMarc Zyngier 		pmu->pmc[i].idx = i;
2569ed24f4bSMarc Zyngier }
2579ed24f4bSMarc Zyngier 
2589ed24f4bSMarc Zyngier /**
2599ed24f4bSMarc Zyngier  * kvm_pmu_vcpu_reset - reset pmu state for cpu
2609ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
2619ed24f4bSMarc Zyngier  *
2629ed24f4bSMarc Zyngier  */
2639ed24f4bSMarc Zyngier void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
2649ed24f4bSMarc Zyngier {
2659ed24f4bSMarc Zyngier 	unsigned long mask = kvm_pmu_valid_counter_mask(vcpu);
2669ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
2679ed24f4bSMarc Zyngier 	int i;
2689ed24f4bSMarc Zyngier 
2699ed24f4bSMarc Zyngier 	for_each_set_bit(i, &mask, 32)
2709ed24f4bSMarc Zyngier 		kvm_pmu_stop_counter(vcpu, &pmu->pmc[i]);
2719ed24f4bSMarc Zyngier 
2729ed24f4bSMarc Zyngier 	bitmap_zero(vcpu->arch.pmu.chained, ARMV8_PMU_MAX_COUNTER_PAIRS);
2739ed24f4bSMarc Zyngier }
2749ed24f4bSMarc Zyngier 
2759ed24f4bSMarc Zyngier /**
2769ed24f4bSMarc Zyngier  * kvm_pmu_vcpu_destroy - free perf event of PMU for cpu
2779ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
2789ed24f4bSMarc Zyngier  *
2799ed24f4bSMarc Zyngier  */
2809ed24f4bSMarc Zyngier void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
2819ed24f4bSMarc Zyngier {
2829ed24f4bSMarc Zyngier 	int i;
2839ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
2849ed24f4bSMarc Zyngier 
2859ed24f4bSMarc Zyngier 	for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++)
2869ed24f4bSMarc Zyngier 		kvm_pmu_release_perf_event(&pmu->pmc[i]);
28795e92e45SJulien Thierry 	irq_work_sync(&vcpu->arch.pmu.overflow_work);
2889ed24f4bSMarc Zyngier }
2899ed24f4bSMarc Zyngier 
2909ed24f4bSMarc Zyngier u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
2919ed24f4bSMarc Zyngier {
2929ed24f4bSMarc Zyngier 	u64 val = __vcpu_sys_reg(vcpu, PMCR_EL0) >> ARMV8_PMU_PMCR_N_SHIFT;
2939ed24f4bSMarc Zyngier 
2949ed24f4bSMarc Zyngier 	val &= ARMV8_PMU_PMCR_N_MASK;
2959ed24f4bSMarc Zyngier 	if (val == 0)
2969ed24f4bSMarc Zyngier 		return BIT(ARMV8_PMU_CYCLE_IDX);
2979ed24f4bSMarc Zyngier 	else
2989ed24f4bSMarc Zyngier 		return GENMASK(val - 1, 0) | BIT(ARMV8_PMU_CYCLE_IDX);
2999ed24f4bSMarc Zyngier }
3009ed24f4bSMarc Zyngier 
3019ed24f4bSMarc Zyngier /**
3029ed24f4bSMarc Zyngier  * kvm_pmu_enable_counter_mask - enable selected PMU counters
3039ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
3049ed24f4bSMarc Zyngier  * @val: the value guest writes to PMCNTENSET register
3059ed24f4bSMarc Zyngier  *
3069ed24f4bSMarc Zyngier  * Call perf_event_enable to start counting the perf event
3079ed24f4bSMarc Zyngier  */
3089ed24f4bSMarc Zyngier void kvm_pmu_enable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
3099ed24f4bSMarc Zyngier {
3109ed24f4bSMarc Zyngier 	int i;
3119ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
3129ed24f4bSMarc Zyngier 	struct kvm_pmc *pmc;
3139ed24f4bSMarc Zyngier 
3149ed24f4bSMarc Zyngier 	if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val)
3159ed24f4bSMarc Zyngier 		return;
3169ed24f4bSMarc Zyngier 
3179ed24f4bSMarc Zyngier 	for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
3189ed24f4bSMarc Zyngier 		if (!(val & BIT(i)))
3199ed24f4bSMarc Zyngier 			continue;
3209ed24f4bSMarc Zyngier 
3219ed24f4bSMarc Zyngier 		pmc = &pmu->pmc[i];
3229ed24f4bSMarc Zyngier 
3239ed24f4bSMarc Zyngier 		/* A change in the enable state may affect the chain state */
3249ed24f4bSMarc Zyngier 		kvm_pmu_update_pmc_chained(vcpu, i);
3259ed24f4bSMarc Zyngier 		kvm_pmu_create_perf_event(vcpu, i);
3269ed24f4bSMarc Zyngier 
3279ed24f4bSMarc Zyngier 		/* At this point, pmc must be the canonical */
3289ed24f4bSMarc Zyngier 		if (pmc->perf_event) {
3299ed24f4bSMarc Zyngier 			perf_event_enable(pmc->perf_event);
3309ed24f4bSMarc Zyngier 			if (pmc->perf_event->state != PERF_EVENT_STATE_ACTIVE)
3319ed24f4bSMarc Zyngier 				kvm_debug("fail to enable perf event\n");
3329ed24f4bSMarc Zyngier 		}
3339ed24f4bSMarc Zyngier 	}
3349ed24f4bSMarc Zyngier }
3359ed24f4bSMarc Zyngier 
3369ed24f4bSMarc Zyngier /**
3379ed24f4bSMarc Zyngier  * kvm_pmu_disable_counter_mask - disable selected PMU counters
3389ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
3399ed24f4bSMarc Zyngier  * @val: the value guest writes to PMCNTENCLR register
3409ed24f4bSMarc Zyngier  *
3419ed24f4bSMarc Zyngier  * Call perf_event_disable to stop counting the perf event
3429ed24f4bSMarc Zyngier  */
3439ed24f4bSMarc Zyngier void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
3449ed24f4bSMarc Zyngier {
3459ed24f4bSMarc Zyngier 	int i;
3469ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
3479ed24f4bSMarc Zyngier 	struct kvm_pmc *pmc;
3489ed24f4bSMarc Zyngier 
3499ed24f4bSMarc Zyngier 	if (!val)
3509ed24f4bSMarc Zyngier 		return;
3519ed24f4bSMarc Zyngier 
3529ed24f4bSMarc Zyngier 	for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
3539ed24f4bSMarc Zyngier 		if (!(val & BIT(i)))
3549ed24f4bSMarc Zyngier 			continue;
3559ed24f4bSMarc Zyngier 
3569ed24f4bSMarc Zyngier 		pmc = &pmu->pmc[i];
3579ed24f4bSMarc Zyngier 
3589ed24f4bSMarc Zyngier 		/* A change in the enable state may affect the chain state */
3599ed24f4bSMarc Zyngier 		kvm_pmu_update_pmc_chained(vcpu, i);
3609ed24f4bSMarc Zyngier 		kvm_pmu_create_perf_event(vcpu, i);
3619ed24f4bSMarc Zyngier 
3629ed24f4bSMarc Zyngier 		/* At this point, pmc must be the canonical */
3639ed24f4bSMarc Zyngier 		if (pmc->perf_event)
3649ed24f4bSMarc Zyngier 			perf_event_disable(pmc->perf_event);
3659ed24f4bSMarc Zyngier 	}
3669ed24f4bSMarc Zyngier }
3679ed24f4bSMarc Zyngier 
3689ed24f4bSMarc Zyngier static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
3699ed24f4bSMarc Zyngier {
3709ed24f4bSMarc Zyngier 	u64 reg = 0;
3719ed24f4bSMarc Zyngier 
3729ed24f4bSMarc Zyngier 	if ((__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E)) {
3739ed24f4bSMarc Zyngier 		reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
3749ed24f4bSMarc Zyngier 		reg &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
3759ed24f4bSMarc Zyngier 		reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
3769ed24f4bSMarc Zyngier 		reg &= kvm_pmu_valid_counter_mask(vcpu);
3779ed24f4bSMarc Zyngier 	}
3789ed24f4bSMarc Zyngier 
3799ed24f4bSMarc Zyngier 	return reg;
3809ed24f4bSMarc Zyngier }
3819ed24f4bSMarc Zyngier 
3829ed24f4bSMarc Zyngier static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
3839ed24f4bSMarc Zyngier {
3849ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
3859ed24f4bSMarc Zyngier 	bool overflow;
3869ed24f4bSMarc Zyngier 
38746acf89dSMarc Zyngier 	if (!kvm_vcpu_has_pmu(vcpu))
3889ed24f4bSMarc Zyngier 		return;
3899ed24f4bSMarc Zyngier 
3909ed24f4bSMarc Zyngier 	overflow = !!kvm_pmu_overflow_status(vcpu);
3919ed24f4bSMarc Zyngier 	if (pmu->irq_level == overflow)
3929ed24f4bSMarc Zyngier 		return;
3939ed24f4bSMarc Zyngier 
3949ed24f4bSMarc Zyngier 	pmu->irq_level = overflow;
3959ed24f4bSMarc Zyngier 
3969ed24f4bSMarc Zyngier 	if (likely(irqchip_in_kernel(vcpu->kvm))) {
3979ed24f4bSMarc Zyngier 		int ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
3989ed24f4bSMarc Zyngier 					      pmu->irq_num, overflow, pmu);
3999ed24f4bSMarc Zyngier 		WARN_ON(ret);
4009ed24f4bSMarc Zyngier 	}
4019ed24f4bSMarc Zyngier }
4029ed24f4bSMarc Zyngier 
4039ed24f4bSMarc Zyngier bool kvm_pmu_should_notify_user(struct kvm_vcpu *vcpu)
4049ed24f4bSMarc Zyngier {
4059ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
4069ed24f4bSMarc Zyngier 	struct kvm_sync_regs *sregs = &vcpu->run->s.regs;
4079ed24f4bSMarc Zyngier 	bool run_level = sregs->device_irq_level & KVM_ARM_DEV_PMU;
4089ed24f4bSMarc Zyngier 
4099ed24f4bSMarc Zyngier 	if (likely(irqchip_in_kernel(vcpu->kvm)))
4109ed24f4bSMarc Zyngier 		return false;
4119ed24f4bSMarc Zyngier 
4129ed24f4bSMarc Zyngier 	return pmu->irq_level != run_level;
4139ed24f4bSMarc Zyngier }
4149ed24f4bSMarc Zyngier 
4159ed24f4bSMarc Zyngier /*
4169ed24f4bSMarc Zyngier  * Reflect the PMU overflow interrupt output level into the kvm_run structure
4179ed24f4bSMarc Zyngier  */
4189ed24f4bSMarc Zyngier void kvm_pmu_update_run(struct kvm_vcpu *vcpu)
4199ed24f4bSMarc Zyngier {
4209ed24f4bSMarc Zyngier 	struct kvm_sync_regs *regs = &vcpu->run->s.regs;
4219ed24f4bSMarc Zyngier 
4229ed24f4bSMarc Zyngier 	/* Populate the timer bitmap for user space */
4239ed24f4bSMarc Zyngier 	regs->device_irq_level &= ~KVM_ARM_DEV_PMU;
4249ed24f4bSMarc Zyngier 	if (vcpu->arch.pmu.irq_level)
4259ed24f4bSMarc Zyngier 		regs->device_irq_level |= KVM_ARM_DEV_PMU;
4269ed24f4bSMarc Zyngier }
4279ed24f4bSMarc Zyngier 
4289ed24f4bSMarc Zyngier /**
4299ed24f4bSMarc Zyngier  * kvm_pmu_flush_hwstate - flush pmu state to cpu
4309ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
4319ed24f4bSMarc Zyngier  *
4329ed24f4bSMarc Zyngier  * Check if the PMU has overflowed while we were running in the host, and inject
4339ed24f4bSMarc Zyngier  * an interrupt if that was the case.
4349ed24f4bSMarc Zyngier  */
4359ed24f4bSMarc Zyngier void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu)
4369ed24f4bSMarc Zyngier {
4379ed24f4bSMarc Zyngier 	kvm_pmu_update_state(vcpu);
4389ed24f4bSMarc Zyngier }
4399ed24f4bSMarc Zyngier 
4409ed24f4bSMarc Zyngier /**
4419ed24f4bSMarc Zyngier  * kvm_pmu_sync_hwstate - sync pmu state from cpu
4429ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
4439ed24f4bSMarc Zyngier  *
4449ed24f4bSMarc Zyngier  * Check if the PMU has overflowed while we were running in the guest, and
4459ed24f4bSMarc Zyngier  * inject an interrupt if that was the case.
4469ed24f4bSMarc Zyngier  */
4479ed24f4bSMarc Zyngier void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu)
4489ed24f4bSMarc Zyngier {
4499ed24f4bSMarc Zyngier 	kvm_pmu_update_state(vcpu);
4509ed24f4bSMarc Zyngier }
4519ed24f4bSMarc Zyngier 
4529ed24f4bSMarc Zyngier /**
45395e92e45SJulien Thierry  * When perf interrupt is an NMI, we cannot safely notify the vcpu corresponding
45495e92e45SJulien Thierry  * to the event.
45595e92e45SJulien Thierry  * This is why we need a callback to do it once outside of the NMI context.
45695e92e45SJulien Thierry  */
45795e92e45SJulien Thierry static void kvm_pmu_perf_overflow_notify_vcpu(struct irq_work *work)
45895e92e45SJulien Thierry {
45995e92e45SJulien Thierry 	struct kvm_vcpu *vcpu;
46095e92e45SJulien Thierry 	struct kvm_pmu *pmu;
46195e92e45SJulien Thierry 
46295e92e45SJulien Thierry 	pmu = container_of(work, struct kvm_pmu, overflow_work);
46395e92e45SJulien Thierry 	vcpu = kvm_pmc_to_vcpu(pmu->pmc);
46495e92e45SJulien Thierry 
46595e92e45SJulien Thierry 	kvm_vcpu_kick(vcpu);
46695e92e45SJulien Thierry }
46795e92e45SJulien Thierry 
46895e92e45SJulien Thierry /**
4699ed24f4bSMarc Zyngier  * When the perf event overflows, set the overflow status and inform the vcpu.
4709ed24f4bSMarc Zyngier  */
4719ed24f4bSMarc Zyngier static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
4729ed24f4bSMarc Zyngier 				  struct perf_sample_data *data,
4739ed24f4bSMarc Zyngier 				  struct pt_regs *regs)
4749ed24f4bSMarc Zyngier {
4759ed24f4bSMarc Zyngier 	struct kvm_pmc *pmc = perf_event->overflow_handler_context;
4769ed24f4bSMarc Zyngier 	struct arm_pmu *cpu_pmu = to_arm_pmu(perf_event->pmu);
4779ed24f4bSMarc Zyngier 	struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
4789ed24f4bSMarc Zyngier 	int idx = pmc->idx;
4799ed24f4bSMarc Zyngier 	u64 period;
4809ed24f4bSMarc Zyngier 
4819ed24f4bSMarc Zyngier 	cpu_pmu->pmu.stop(perf_event, PERF_EF_UPDATE);
4829ed24f4bSMarc Zyngier 
4839ed24f4bSMarc Zyngier 	/*
4849ed24f4bSMarc Zyngier 	 * Reset the sample period to the architectural limit,
4859ed24f4bSMarc Zyngier 	 * i.e. the point where the counter overflows.
4869ed24f4bSMarc Zyngier 	 */
4879ed24f4bSMarc Zyngier 	period = -(local64_read(&perf_event->count));
4889ed24f4bSMarc Zyngier 
4899ed24f4bSMarc Zyngier 	if (!kvm_pmu_idx_is_64bit(vcpu, pmc->idx))
4909ed24f4bSMarc Zyngier 		period &= GENMASK(31, 0);
4919ed24f4bSMarc Zyngier 
4929ed24f4bSMarc Zyngier 	local64_set(&perf_event->hw.period_left, 0);
4939ed24f4bSMarc Zyngier 	perf_event->attr.sample_period = period;
4949ed24f4bSMarc Zyngier 	perf_event->hw.sample_period = period;
4959ed24f4bSMarc Zyngier 
4969ed24f4bSMarc Zyngier 	__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx);
4979ed24f4bSMarc Zyngier 
4989ed24f4bSMarc Zyngier 	if (kvm_pmu_overflow_status(vcpu)) {
4999ed24f4bSMarc Zyngier 		kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
50095e92e45SJulien Thierry 
50195e92e45SJulien Thierry 		if (!in_nmi())
5029ed24f4bSMarc Zyngier 			kvm_vcpu_kick(vcpu);
50395e92e45SJulien Thierry 		else
50495e92e45SJulien Thierry 			irq_work_queue(&vcpu->arch.pmu.overflow_work);
5059ed24f4bSMarc Zyngier 	}
5069ed24f4bSMarc Zyngier 
5079ed24f4bSMarc Zyngier 	cpu_pmu->pmu.start(perf_event, PERF_EF_RELOAD);
5089ed24f4bSMarc Zyngier }
5099ed24f4bSMarc Zyngier 
5109ed24f4bSMarc Zyngier /**
5119ed24f4bSMarc Zyngier  * kvm_pmu_software_increment - do software increment
5129ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
5139ed24f4bSMarc Zyngier  * @val: the value guest writes to PMSWINC register
5149ed24f4bSMarc Zyngier  */
5159ed24f4bSMarc Zyngier void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val)
5169ed24f4bSMarc Zyngier {
5179ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
5189ed24f4bSMarc Zyngier 	int i;
5199ed24f4bSMarc Zyngier 
5209ed24f4bSMarc Zyngier 	if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E))
5219ed24f4bSMarc Zyngier 		return;
5229ed24f4bSMarc Zyngier 
5239ed24f4bSMarc Zyngier 	/* Weed out disabled counters */
5249ed24f4bSMarc Zyngier 	val &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
5259ed24f4bSMarc Zyngier 
5269ed24f4bSMarc Zyngier 	for (i = 0; i < ARMV8_PMU_CYCLE_IDX; i++) {
5279ed24f4bSMarc Zyngier 		u64 type, reg;
5289ed24f4bSMarc Zyngier 
5299ed24f4bSMarc Zyngier 		if (!(val & BIT(i)))
5309ed24f4bSMarc Zyngier 			continue;
5319ed24f4bSMarc Zyngier 
5329ed24f4bSMarc Zyngier 		/* PMSWINC only applies to ... SW_INC! */
5339ed24f4bSMarc Zyngier 		type = __vcpu_sys_reg(vcpu, PMEVTYPER0_EL0 + i);
534fd65a3b5SMarc Zyngier 		type &= kvm_pmu_event_mask(vcpu->kvm);
5359ed24f4bSMarc Zyngier 		if (type != ARMV8_PMUV3_PERFCTR_SW_INCR)
5369ed24f4bSMarc Zyngier 			continue;
5379ed24f4bSMarc Zyngier 
5389ed24f4bSMarc Zyngier 		/* increment this even SW_INC counter */
5399ed24f4bSMarc Zyngier 		reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) + 1;
5409ed24f4bSMarc Zyngier 		reg = lower_32_bits(reg);
5419ed24f4bSMarc Zyngier 		__vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) = reg;
5429ed24f4bSMarc Zyngier 
5439ed24f4bSMarc Zyngier 		if (reg) /* no overflow on the low part */
5449ed24f4bSMarc Zyngier 			continue;
5459ed24f4bSMarc Zyngier 
5469ed24f4bSMarc Zyngier 		if (kvm_pmu_pmc_is_chained(&pmu->pmc[i])) {
5479ed24f4bSMarc Zyngier 			/* increment the high counter */
5489ed24f4bSMarc Zyngier 			reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i + 1) + 1;
5499ed24f4bSMarc Zyngier 			reg = lower_32_bits(reg);
5509ed24f4bSMarc Zyngier 			__vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i + 1) = reg;
5519ed24f4bSMarc Zyngier 			if (!reg) /* mark overflow on the high counter */
5529ed24f4bSMarc Zyngier 				__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i + 1);
5539ed24f4bSMarc Zyngier 		} else {
5549ed24f4bSMarc Zyngier 			/* mark overflow on low counter */
5559ed24f4bSMarc Zyngier 			__vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i);
5569ed24f4bSMarc Zyngier 		}
5579ed24f4bSMarc Zyngier 	}
5589ed24f4bSMarc Zyngier }
5599ed24f4bSMarc Zyngier 
5609ed24f4bSMarc Zyngier /**
5619ed24f4bSMarc Zyngier  * kvm_pmu_handle_pmcr - handle PMCR register
5629ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
5639ed24f4bSMarc Zyngier  * @val: the value guest writes to PMCR register
5649ed24f4bSMarc Zyngier  */
5659ed24f4bSMarc Zyngier void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
5669ed24f4bSMarc Zyngier {
5679ed24f4bSMarc Zyngier 	unsigned long mask = kvm_pmu_valid_counter_mask(vcpu);
5689ed24f4bSMarc Zyngier 	int i;
5699ed24f4bSMarc Zyngier 
5709ed24f4bSMarc Zyngier 	if (val & ARMV8_PMU_PMCR_E) {
5719ed24f4bSMarc Zyngier 		kvm_pmu_enable_counter_mask(vcpu,
5729ed24f4bSMarc Zyngier 		       __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask);
5739ed24f4bSMarc Zyngier 	} else {
5749ed24f4bSMarc Zyngier 		kvm_pmu_disable_counter_mask(vcpu, mask);
5759ed24f4bSMarc Zyngier 	}
5769ed24f4bSMarc Zyngier 
5779ed24f4bSMarc Zyngier 	if (val & ARMV8_PMU_PMCR_C)
5789ed24f4bSMarc Zyngier 		kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0);
5799ed24f4bSMarc Zyngier 
5809ed24f4bSMarc Zyngier 	if (val & ARMV8_PMU_PMCR_P) {
5819ed24f4bSMarc Zyngier 		for_each_set_bit(i, &mask, 32)
5829ed24f4bSMarc Zyngier 			kvm_pmu_set_counter_value(vcpu, i, 0);
5839ed24f4bSMarc Zyngier 	}
5849ed24f4bSMarc Zyngier }
5859ed24f4bSMarc Zyngier 
5869ed24f4bSMarc Zyngier static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u64 select_idx)
5879ed24f4bSMarc Zyngier {
5889ed24f4bSMarc Zyngier 	return (__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) &&
5899ed24f4bSMarc Zyngier 	       (__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(select_idx));
5909ed24f4bSMarc Zyngier }
5919ed24f4bSMarc Zyngier 
5929ed24f4bSMarc Zyngier /**
5939ed24f4bSMarc Zyngier  * kvm_pmu_create_perf_event - create a perf event for a counter
5949ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
5959ed24f4bSMarc Zyngier  * @select_idx: The number of selected counter
5969ed24f4bSMarc Zyngier  */
5979ed24f4bSMarc Zyngier static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx)
5989ed24f4bSMarc Zyngier {
5999ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
6009ed24f4bSMarc Zyngier 	struct kvm_pmc *pmc;
6019ed24f4bSMarc Zyngier 	struct perf_event *event;
6029ed24f4bSMarc Zyngier 	struct perf_event_attr attr;
6039ed24f4bSMarc Zyngier 	u64 eventsel, counter, reg, data;
6049ed24f4bSMarc Zyngier 
6059ed24f4bSMarc Zyngier 	/*
6069ed24f4bSMarc Zyngier 	 * For chained counters the event type and filtering attributes are
6079ed24f4bSMarc Zyngier 	 * obtained from the low/even counter. We also use this counter to
6089ed24f4bSMarc Zyngier 	 * determine if the event is enabled/disabled.
6099ed24f4bSMarc Zyngier 	 */
6109ed24f4bSMarc Zyngier 	pmc = kvm_pmu_get_canonical_pmc(&pmu->pmc[select_idx]);
6119ed24f4bSMarc Zyngier 
6129ed24f4bSMarc Zyngier 	reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
6139ed24f4bSMarc Zyngier 	      ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + pmc->idx;
6149ed24f4bSMarc Zyngier 	data = __vcpu_sys_reg(vcpu, reg);
6159ed24f4bSMarc Zyngier 
6169ed24f4bSMarc Zyngier 	kvm_pmu_stop_counter(vcpu, pmc);
617d7eec236SMarc Zyngier 	if (pmc->idx == ARMV8_PMU_CYCLE_IDX)
618d7eec236SMarc Zyngier 		eventsel = ARMV8_PMUV3_PERFCTR_CPU_CYCLES;
619d7eec236SMarc Zyngier 	else
620d7eec236SMarc Zyngier 		eventsel = data & kvm_pmu_event_mask(vcpu->kvm);
6219ed24f4bSMarc Zyngier 
622d7eec236SMarc Zyngier 	/* Software increment event doesn't need to be backed by a perf event */
623d7eec236SMarc Zyngier 	if (eventsel == ARMV8_PMUV3_PERFCTR_SW_INCR)
624d7eec236SMarc Zyngier 		return;
625d7eec236SMarc Zyngier 
626d7eec236SMarc Zyngier 	/*
627d7eec236SMarc Zyngier 	 * If we have a filter in place and that the event isn't allowed, do
628d7eec236SMarc Zyngier 	 * not install a perf event either.
629d7eec236SMarc Zyngier 	 */
630d7eec236SMarc Zyngier 	if (vcpu->kvm->arch.pmu_filter &&
631d7eec236SMarc Zyngier 	    !test_bit(eventsel, vcpu->kvm->arch.pmu_filter))
6329ed24f4bSMarc Zyngier 		return;
6339ed24f4bSMarc Zyngier 
6349ed24f4bSMarc Zyngier 	memset(&attr, 0, sizeof(struct perf_event_attr));
6359ed24f4bSMarc Zyngier 	attr.type = PERF_TYPE_RAW;
6369ed24f4bSMarc Zyngier 	attr.size = sizeof(attr);
6379ed24f4bSMarc Zyngier 	attr.pinned = 1;
6389ed24f4bSMarc Zyngier 	attr.disabled = !kvm_pmu_counter_is_enabled(vcpu, pmc->idx);
6399ed24f4bSMarc Zyngier 	attr.exclude_user = data & ARMV8_PMU_EXCLUDE_EL0 ? 1 : 0;
6409ed24f4bSMarc Zyngier 	attr.exclude_kernel = data & ARMV8_PMU_EXCLUDE_EL1 ? 1 : 0;
6419ed24f4bSMarc Zyngier 	attr.exclude_hv = 1; /* Don't count EL2 events */
6429ed24f4bSMarc Zyngier 	attr.exclude_host = 1; /* Don't count host events */
643d7eec236SMarc Zyngier 	attr.config = eventsel;
6449ed24f4bSMarc Zyngier 
6459ed24f4bSMarc Zyngier 	counter = kvm_pmu_get_pair_counter_value(vcpu, pmc);
6469ed24f4bSMarc Zyngier 
6479ed24f4bSMarc Zyngier 	if (kvm_pmu_pmc_is_chained(pmc)) {
6489ed24f4bSMarc Zyngier 		/**
6499ed24f4bSMarc Zyngier 		 * The initial sample period (overflow count) of an event. For
6509ed24f4bSMarc Zyngier 		 * chained counters we only support overflow interrupts on the
6519ed24f4bSMarc Zyngier 		 * high counter.
6529ed24f4bSMarc Zyngier 		 */
6539ed24f4bSMarc Zyngier 		attr.sample_period = (-counter) & GENMASK(63, 0);
6549ed24f4bSMarc Zyngier 		attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED;
6559ed24f4bSMarc Zyngier 
6569ed24f4bSMarc Zyngier 		event = perf_event_create_kernel_counter(&attr, -1, current,
6579ed24f4bSMarc Zyngier 							 kvm_pmu_perf_overflow,
6589ed24f4bSMarc Zyngier 							 pmc + 1);
6599ed24f4bSMarc Zyngier 	} else {
6609ed24f4bSMarc Zyngier 		/* The initial sample period (overflow count) of an event. */
6619ed24f4bSMarc Zyngier 		if (kvm_pmu_idx_is_64bit(vcpu, pmc->idx))
6629ed24f4bSMarc Zyngier 			attr.sample_period = (-counter) & GENMASK(63, 0);
6639ed24f4bSMarc Zyngier 		else
6649ed24f4bSMarc Zyngier 			attr.sample_period = (-counter) & GENMASK(31, 0);
6659ed24f4bSMarc Zyngier 
6669ed24f4bSMarc Zyngier 		event = perf_event_create_kernel_counter(&attr, -1, current,
6679ed24f4bSMarc Zyngier 						 kvm_pmu_perf_overflow, pmc);
6689ed24f4bSMarc Zyngier 	}
6699ed24f4bSMarc Zyngier 
6709ed24f4bSMarc Zyngier 	if (IS_ERR(event)) {
6719ed24f4bSMarc Zyngier 		pr_err_once("kvm: pmu event creation failed %ld\n",
6729ed24f4bSMarc Zyngier 			    PTR_ERR(event));
6739ed24f4bSMarc Zyngier 		return;
6749ed24f4bSMarc Zyngier 	}
6759ed24f4bSMarc Zyngier 
6769ed24f4bSMarc Zyngier 	pmc->perf_event = event;
6779ed24f4bSMarc Zyngier }
6789ed24f4bSMarc Zyngier 
6799ed24f4bSMarc Zyngier /**
6809ed24f4bSMarc Zyngier  * kvm_pmu_update_pmc_chained - update chained bitmap
6819ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
6829ed24f4bSMarc Zyngier  * @select_idx: The number of selected counter
6839ed24f4bSMarc Zyngier  *
6849ed24f4bSMarc Zyngier  * Update the chained bitmap based on the event type written in the
6859ed24f4bSMarc Zyngier  * typer register and the enable state of the odd register.
6869ed24f4bSMarc Zyngier  */
6879ed24f4bSMarc Zyngier static void kvm_pmu_update_pmc_chained(struct kvm_vcpu *vcpu, u64 select_idx)
6889ed24f4bSMarc Zyngier {
6899ed24f4bSMarc Zyngier 	struct kvm_pmu *pmu = &vcpu->arch.pmu;
6909ed24f4bSMarc Zyngier 	struct kvm_pmc *pmc = &pmu->pmc[select_idx], *canonical_pmc;
6919ed24f4bSMarc Zyngier 	bool new_state, old_state;
6929ed24f4bSMarc Zyngier 
6939ed24f4bSMarc Zyngier 	old_state = kvm_pmu_pmc_is_chained(pmc);
6949ed24f4bSMarc Zyngier 	new_state = kvm_pmu_idx_has_chain_evtype(vcpu, pmc->idx) &&
6959ed24f4bSMarc Zyngier 		    kvm_pmu_counter_is_enabled(vcpu, pmc->idx | 0x1);
6969ed24f4bSMarc Zyngier 
6979ed24f4bSMarc Zyngier 	if (old_state == new_state)
6989ed24f4bSMarc Zyngier 		return;
6999ed24f4bSMarc Zyngier 
7009ed24f4bSMarc Zyngier 	canonical_pmc = kvm_pmu_get_canonical_pmc(pmc);
7019ed24f4bSMarc Zyngier 	kvm_pmu_stop_counter(vcpu, canonical_pmc);
7029ed24f4bSMarc Zyngier 	if (new_state) {
7039ed24f4bSMarc Zyngier 		/*
7049ed24f4bSMarc Zyngier 		 * During promotion from !chained to chained we must ensure
7059ed24f4bSMarc Zyngier 		 * the adjacent counter is stopped and its event destroyed
7069ed24f4bSMarc Zyngier 		 */
7079ed24f4bSMarc Zyngier 		kvm_pmu_stop_counter(vcpu, kvm_pmu_get_alternate_pmc(pmc));
7089ed24f4bSMarc Zyngier 		set_bit(pmc->idx >> 1, vcpu->arch.pmu.chained);
7099ed24f4bSMarc Zyngier 		return;
7109ed24f4bSMarc Zyngier 	}
7119ed24f4bSMarc Zyngier 	clear_bit(pmc->idx >> 1, vcpu->arch.pmu.chained);
7129ed24f4bSMarc Zyngier }
7139ed24f4bSMarc Zyngier 
7149ed24f4bSMarc Zyngier /**
7159ed24f4bSMarc Zyngier  * kvm_pmu_set_counter_event_type - set selected counter to monitor some event
7169ed24f4bSMarc Zyngier  * @vcpu: The vcpu pointer
7179ed24f4bSMarc Zyngier  * @data: The data guest writes to PMXEVTYPER_EL0
7189ed24f4bSMarc Zyngier  * @select_idx: The number of selected counter
7199ed24f4bSMarc Zyngier  *
7209ed24f4bSMarc Zyngier  * When OS accesses PMXEVTYPER_EL0, that means it wants to set a PMC to count an
7219ed24f4bSMarc Zyngier  * event with given hardware event number. Here we call perf_event API to
7229ed24f4bSMarc Zyngier  * emulate this action and create a kernel perf event for it.
7239ed24f4bSMarc Zyngier  */
7249ed24f4bSMarc Zyngier void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
7259ed24f4bSMarc Zyngier 				    u64 select_idx)
7269ed24f4bSMarc Zyngier {
727fd65a3b5SMarc Zyngier 	u64 reg, mask;
728fd65a3b5SMarc Zyngier 
729fd65a3b5SMarc Zyngier 	mask  =  ARMV8_PMU_EVTYPE_MASK;
730fd65a3b5SMarc Zyngier 	mask &= ~ARMV8_PMU_EVTYPE_EVENT;
731fd65a3b5SMarc Zyngier 	mask |= kvm_pmu_event_mask(vcpu->kvm);
7329ed24f4bSMarc Zyngier 
7339ed24f4bSMarc Zyngier 	reg = (select_idx == ARMV8_PMU_CYCLE_IDX)
7349ed24f4bSMarc Zyngier 	      ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + select_idx;
7359ed24f4bSMarc Zyngier 
736fd65a3b5SMarc Zyngier 	__vcpu_sys_reg(vcpu, reg) = data & mask;
7379ed24f4bSMarc Zyngier 
7389ed24f4bSMarc Zyngier 	kvm_pmu_update_pmc_chained(vcpu, select_idx);
7399ed24f4bSMarc Zyngier 	kvm_pmu_create_perf_event(vcpu, select_idx);
7409ed24f4bSMarc Zyngier }
7419ed24f4bSMarc Zyngier 
742fd65a3b5SMarc Zyngier static int kvm_pmu_probe_pmuver(void)
743fd65a3b5SMarc Zyngier {
744fd65a3b5SMarc Zyngier 	struct perf_event_attr attr = { };
745fd65a3b5SMarc Zyngier 	struct perf_event *event;
746fd65a3b5SMarc Zyngier 	struct arm_pmu *pmu;
747fd65a3b5SMarc Zyngier 	int pmuver = 0xf;
748fd65a3b5SMarc Zyngier 
749fd65a3b5SMarc Zyngier 	/*
750fd65a3b5SMarc Zyngier 	 * Create a dummy event that only counts user cycles. As we'll never
751fd65a3b5SMarc Zyngier 	 * leave this function with the event being live, it will never
752fd65a3b5SMarc Zyngier 	 * count anything. But it allows us to probe some of the PMU
753fd65a3b5SMarc Zyngier 	 * details. Yes, this is terrible.
754fd65a3b5SMarc Zyngier 	 */
755fd65a3b5SMarc Zyngier 	attr.type = PERF_TYPE_RAW;
756fd65a3b5SMarc Zyngier 	attr.size = sizeof(attr);
757fd65a3b5SMarc Zyngier 	attr.pinned = 1;
758fd65a3b5SMarc Zyngier 	attr.disabled = 0;
759fd65a3b5SMarc Zyngier 	attr.exclude_user = 0;
760fd65a3b5SMarc Zyngier 	attr.exclude_kernel = 1;
761fd65a3b5SMarc Zyngier 	attr.exclude_hv = 1;
762fd65a3b5SMarc Zyngier 	attr.exclude_host = 1;
763fd65a3b5SMarc Zyngier 	attr.config = ARMV8_PMUV3_PERFCTR_CPU_CYCLES;
764fd65a3b5SMarc Zyngier 	attr.sample_period = GENMASK(63, 0);
765fd65a3b5SMarc Zyngier 
766fd65a3b5SMarc Zyngier 	event = perf_event_create_kernel_counter(&attr, -1, current,
767fd65a3b5SMarc Zyngier 						 kvm_pmu_perf_overflow, &attr);
768fd65a3b5SMarc Zyngier 
769fd65a3b5SMarc Zyngier 	if (IS_ERR(event)) {
770fd65a3b5SMarc Zyngier 		pr_err_once("kvm: pmu event creation failed %ld\n",
771fd65a3b5SMarc Zyngier 			    PTR_ERR(event));
772fd65a3b5SMarc Zyngier 		return 0xf;
773fd65a3b5SMarc Zyngier 	}
774fd65a3b5SMarc Zyngier 
775fd65a3b5SMarc Zyngier 	if (event->pmu) {
776fd65a3b5SMarc Zyngier 		pmu = to_arm_pmu(event->pmu);
777fd65a3b5SMarc Zyngier 		if (pmu->pmuver)
778fd65a3b5SMarc Zyngier 			pmuver = pmu->pmuver;
779fd65a3b5SMarc Zyngier 	}
780fd65a3b5SMarc Zyngier 
781fd65a3b5SMarc Zyngier 	perf_event_disable(event);
782fd65a3b5SMarc Zyngier 	perf_event_release_kernel(event);
783fd65a3b5SMarc Zyngier 
784fd65a3b5SMarc Zyngier 	return pmuver;
785fd65a3b5SMarc Zyngier }
786fd65a3b5SMarc Zyngier 
78788865becSMarc Zyngier u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
78888865becSMarc Zyngier {
78988865becSMarc Zyngier 	unsigned long *bmap = vcpu->kvm->arch.pmu_filter;
79088865becSMarc Zyngier 	u64 val, mask = 0;
79188865becSMarc Zyngier 	int base, i;
79288865becSMarc Zyngier 
79388865becSMarc Zyngier 	if (!pmceid1) {
79488865becSMarc Zyngier 		val = read_sysreg(pmceid0_el0);
79588865becSMarc Zyngier 		base = 0;
79688865becSMarc Zyngier 	} else {
79788865becSMarc Zyngier 		val = read_sysreg(pmceid1_el0);
79846081078SMarc Zyngier 		/*
79946081078SMarc Zyngier 		 * Don't advertise STALL_SLOT, as PMMIR_EL0 is handled
80046081078SMarc Zyngier 		 * as RAZ
80146081078SMarc Zyngier 		 */
80246081078SMarc Zyngier 		if (vcpu->kvm->arch.pmuver >= ID_AA64DFR0_PMUVER_8_4)
80346081078SMarc Zyngier 			val &= ~BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32);
80488865becSMarc Zyngier 		base = 32;
80588865becSMarc Zyngier 	}
80688865becSMarc Zyngier 
80788865becSMarc Zyngier 	if (!bmap)
80888865becSMarc Zyngier 		return val;
80988865becSMarc Zyngier 
81088865becSMarc Zyngier 	for (i = 0; i < 32; i += 8) {
81188865becSMarc Zyngier 		u64 byte;
81288865becSMarc Zyngier 
81388865becSMarc Zyngier 		byte = bitmap_get_value8(bmap, base + i);
81488865becSMarc Zyngier 		mask |= byte << i;
81588865becSMarc Zyngier 		byte = bitmap_get_value8(bmap, 0x4000 + base + i);
81688865becSMarc Zyngier 		mask |= byte << (32 + i);
81788865becSMarc Zyngier 	}
81888865becSMarc Zyngier 
81988865becSMarc Zyngier 	return val & mask;
82088865becSMarc Zyngier }
82188865becSMarc Zyngier 
8229ed24f4bSMarc Zyngier bool kvm_arm_support_pmu_v3(void)
8239ed24f4bSMarc Zyngier {
8249ed24f4bSMarc Zyngier 	/*
8259ed24f4bSMarc Zyngier 	 * Check if HW_PERF_EVENTS are supported by checking the number of
8269ed24f4bSMarc Zyngier 	 * hardware performance counters. This could ensure the presence of
8279ed24f4bSMarc Zyngier 	 * a physical PMU and CONFIG_PERF_EVENT is selected.
8289ed24f4bSMarc Zyngier 	 */
8299ed24f4bSMarc Zyngier 	return (perf_num_counters() > 0);
8309ed24f4bSMarc Zyngier }
8319ed24f4bSMarc Zyngier 
8329ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
8339ed24f4bSMarc Zyngier {
8349bbfa4b5SAlexandru Elisei 	if (!kvm_vcpu_has_pmu(vcpu))
8359ed24f4bSMarc Zyngier 		return 0;
8369ed24f4bSMarc Zyngier 
8379bbfa4b5SAlexandru Elisei 	if (!vcpu->arch.pmu.created)
8389bbfa4b5SAlexandru Elisei 		return -EINVAL;
8399bbfa4b5SAlexandru Elisei 
8409ed24f4bSMarc Zyngier 	/*
8419ed24f4bSMarc Zyngier 	 * A valid interrupt configuration for the PMU is either to have a
8429ed24f4bSMarc Zyngier 	 * properly configured interrupt number and using an in-kernel
8439ed24f4bSMarc Zyngier 	 * irqchip, or to not have an in-kernel GIC and not set an IRQ.
8449ed24f4bSMarc Zyngier 	 */
8459ed24f4bSMarc Zyngier 	if (irqchip_in_kernel(vcpu->kvm)) {
8469ed24f4bSMarc Zyngier 		int irq = vcpu->arch.pmu.irq_num;
8479ed24f4bSMarc Zyngier 		/*
8489ed24f4bSMarc Zyngier 		 * If we are using an in-kernel vgic, at this point we know
8499ed24f4bSMarc Zyngier 		 * the vgic will be initialized, so we can check the PMU irq
8509ed24f4bSMarc Zyngier 		 * number against the dimensions of the vgic and make sure
8519ed24f4bSMarc Zyngier 		 * it's valid.
8529ed24f4bSMarc Zyngier 		 */
8539ed24f4bSMarc Zyngier 		if (!irq_is_ppi(irq) && !vgic_valid_spi(vcpu->kvm, irq))
8549ed24f4bSMarc Zyngier 			return -EINVAL;
8559ed24f4bSMarc Zyngier 	} else if (kvm_arm_pmu_irq_initialized(vcpu)) {
8569ed24f4bSMarc Zyngier 		   return -EINVAL;
8579ed24f4bSMarc Zyngier 	}
8589ed24f4bSMarc Zyngier 
8599ed24f4bSMarc Zyngier 	kvm_pmu_vcpu_reset(vcpu);
8609ed24f4bSMarc Zyngier 
8619ed24f4bSMarc Zyngier 	return 0;
8629ed24f4bSMarc Zyngier }
8639ed24f4bSMarc Zyngier 
8649ed24f4bSMarc Zyngier static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
8659ed24f4bSMarc Zyngier {
8669ed24f4bSMarc Zyngier 	if (irqchip_in_kernel(vcpu->kvm)) {
8679ed24f4bSMarc Zyngier 		int ret;
8689ed24f4bSMarc Zyngier 
8699ed24f4bSMarc Zyngier 		/*
8709ed24f4bSMarc Zyngier 		 * If using the PMU with an in-kernel virtual GIC
8719ed24f4bSMarc Zyngier 		 * implementation, we require the GIC to be already
8729ed24f4bSMarc Zyngier 		 * initialized when initializing the PMU.
8739ed24f4bSMarc Zyngier 		 */
8749ed24f4bSMarc Zyngier 		if (!vgic_initialized(vcpu->kvm))
8759ed24f4bSMarc Zyngier 			return -ENODEV;
8769ed24f4bSMarc Zyngier 
8779ed24f4bSMarc Zyngier 		if (!kvm_arm_pmu_irq_initialized(vcpu))
8789ed24f4bSMarc Zyngier 			return -ENXIO;
8799ed24f4bSMarc Zyngier 
8809ed24f4bSMarc Zyngier 		ret = kvm_vgic_set_owner(vcpu, vcpu->arch.pmu.irq_num,
8819ed24f4bSMarc Zyngier 					 &vcpu->arch.pmu);
8829ed24f4bSMarc Zyngier 		if (ret)
8839ed24f4bSMarc Zyngier 			return ret;
8849ed24f4bSMarc Zyngier 	}
8859ed24f4bSMarc Zyngier 
88695e92e45SJulien Thierry 	init_irq_work(&vcpu->arch.pmu.overflow_work,
88795e92e45SJulien Thierry 		      kvm_pmu_perf_overflow_notify_vcpu);
88895e92e45SJulien Thierry 
8899ed24f4bSMarc Zyngier 	vcpu->arch.pmu.created = true;
8909ed24f4bSMarc Zyngier 	return 0;
8919ed24f4bSMarc Zyngier }
8929ed24f4bSMarc Zyngier 
8939ed24f4bSMarc Zyngier /*
8949ed24f4bSMarc Zyngier  * For one VM the interrupt type must be same for each vcpu.
8959ed24f4bSMarc Zyngier  * As a PPI, the interrupt number is the same for all vcpus,
8969ed24f4bSMarc Zyngier  * while as an SPI it must be a separate number per vcpu.
8979ed24f4bSMarc Zyngier  */
8989ed24f4bSMarc Zyngier static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
8999ed24f4bSMarc Zyngier {
9009ed24f4bSMarc Zyngier 	int i;
9019ed24f4bSMarc Zyngier 	struct kvm_vcpu *vcpu;
9029ed24f4bSMarc Zyngier 
9039ed24f4bSMarc Zyngier 	kvm_for_each_vcpu(i, vcpu, kvm) {
9049ed24f4bSMarc Zyngier 		if (!kvm_arm_pmu_irq_initialized(vcpu))
9059ed24f4bSMarc Zyngier 			continue;
9069ed24f4bSMarc Zyngier 
9079ed24f4bSMarc Zyngier 		if (irq_is_ppi(irq)) {
9089ed24f4bSMarc Zyngier 			if (vcpu->arch.pmu.irq_num != irq)
9099ed24f4bSMarc Zyngier 				return false;
9109ed24f4bSMarc Zyngier 		} else {
9119ed24f4bSMarc Zyngier 			if (vcpu->arch.pmu.irq_num == irq)
9129ed24f4bSMarc Zyngier 				return false;
9139ed24f4bSMarc Zyngier 		}
9149ed24f4bSMarc Zyngier 	}
9159ed24f4bSMarc Zyngier 
9169ed24f4bSMarc Zyngier 	return true;
9179ed24f4bSMarc Zyngier }
9189ed24f4bSMarc Zyngier 
9199ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
9209ed24f4bSMarc Zyngier {
92177da4303SMarc Zyngier 	if (!kvm_vcpu_has_pmu(vcpu))
92242223fb1SMarc Zyngier 		return -ENODEV;
92342223fb1SMarc Zyngier 
92442223fb1SMarc Zyngier 	if (vcpu->arch.pmu.created)
92542223fb1SMarc Zyngier 		return -EBUSY;
92642223fb1SMarc Zyngier 
927fd65a3b5SMarc Zyngier 	if (!vcpu->kvm->arch.pmuver)
928fd65a3b5SMarc Zyngier 		vcpu->kvm->arch.pmuver = kvm_pmu_probe_pmuver();
929fd65a3b5SMarc Zyngier 
930fd65a3b5SMarc Zyngier 	if (vcpu->kvm->arch.pmuver == 0xf)
931fd65a3b5SMarc Zyngier 		return -ENODEV;
932fd65a3b5SMarc Zyngier 
9339ed24f4bSMarc Zyngier 	switch (attr->attr) {
9349ed24f4bSMarc Zyngier 	case KVM_ARM_VCPU_PMU_V3_IRQ: {
9359ed24f4bSMarc Zyngier 		int __user *uaddr = (int __user *)(long)attr->addr;
9369ed24f4bSMarc Zyngier 		int irq;
9379ed24f4bSMarc Zyngier 
9389ed24f4bSMarc Zyngier 		if (!irqchip_in_kernel(vcpu->kvm))
9399ed24f4bSMarc Zyngier 			return -EINVAL;
9409ed24f4bSMarc Zyngier 
9419ed24f4bSMarc Zyngier 		if (get_user(irq, uaddr))
9429ed24f4bSMarc Zyngier 			return -EFAULT;
9439ed24f4bSMarc Zyngier 
9449ed24f4bSMarc Zyngier 		/* The PMU overflow interrupt can be a PPI or a valid SPI. */
9459ed24f4bSMarc Zyngier 		if (!(irq_is_ppi(irq) || irq_is_spi(irq)))
9469ed24f4bSMarc Zyngier 			return -EINVAL;
9479ed24f4bSMarc Zyngier 
9489ed24f4bSMarc Zyngier 		if (!pmu_irq_is_valid(vcpu->kvm, irq))
9499ed24f4bSMarc Zyngier 			return -EINVAL;
9509ed24f4bSMarc Zyngier 
9519ed24f4bSMarc Zyngier 		if (kvm_arm_pmu_irq_initialized(vcpu))
9529ed24f4bSMarc Zyngier 			return -EBUSY;
9539ed24f4bSMarc Zyngier 
9549ed24f4bSMarc Zyngier 		kvm_debug("Set kvm ARM PMU irq: %d\n", irq);
9559ed24f4bSMarc Zyngier 		vcpu->arch.pmu.irq_num = irq;
9569ed24f4bSMarc Zyngier 		return 0;
9579ed24f4bSMarc Zyngier 	}
958d7eec236SMarc Zyngier 	case KVM_ARM_VCPU_PMU_V3_FILTER: {
959d7eec236SMarc Zyngier 		struct kvm_pmu_event_filter __user *uaddr;
960d7eec236SMarc Zyngier 		struct kvm_pmu_event_filter filter;
961d7eec236SMarc Zyngier 		int nr_events;
962d7eec236SMarc Zyngier 
963d7eec236SMarc Zyngier 		nr_events = kvm_pmu_event_mask(vcpu->kvm) + 1;
964d7eec236SMarc Zyngier 
965d7eec236SMarc Zyngier 		uaddr = (struct kvm_pmu_event_filter __user *)(long)attr->addr;
966d7eec236SMarc Zyngier 
967d7eec236SMarc Zyngier 		if (copy_from_user(&filter, uaddr, sizeof(filter)))
968d7eec236SMarc Zyngier 			return -EFAULT;
969d7eec236SMarc Zyngier 
970d7eec236SMarc Zyngier 		if (((u32)filter.base_event + filter.nevents) > nr_events ||
971d7eec236SMarc Zyngier 		    (filter.action != KVM_PMU_EVENT_ALLOW &&
972d7eec236SMarc Zyngier 		     filter.action != KVM_PMU_EVENT_DENY))
973d7eec236SMarc Zyngier 			return -EINVAL;
974d7eec236SMarc Zyngier 
975d7eec236SMarc Zyngier 		mutex_lock(&vcpu->kvm->lock);
976d7eec236SMarc Zyngier 
977d7eec236SMarc Zyngier 		if (!vcpu->kvm->arch.pmu_filter) {
978d7eec236SMarc Zyngier 			vcpu->kvm->arch.pmu_filter = bitmap_alloc(nr_events, GFP_KERNEL);
979d7eec236SMarc Zyngier 			if (!vcpu->kvm->arch.pmu_filter) {
980d7eec236SMarc Zyngier 				mutex_unlock(&vcpu->kvm->lock);
981d7eec236SMarc Zyngier 				return -ENOMEM;
982d7eec236SMarc Zyngier 			}
983d7eec236SMarc Zyngier 
984d7eec236SMarc Zyngier 			/*
985d7eec236SMarc Zyngier 			 * The default depends on the first applied filter.
986d7eec236SMarc Zyngier 			 * If it allows events, the default is to deny.
987d7eec236SMarc Zyngier 			 * Conversely, if the first filter denies a set of
988d7eec236SMarc Zyngier 			 * events, the default is to allow.
989d7eec236SMarc Zyngier 			 */
990d7eec236SMarc Zyngier 			if (filter.action == KVM_PMU_EVENT_ALLOW)
991d7eec236SMarc Zyngier 				bitmap_zero(vcpu->kvm->arch.pmu_filter, nr_events);
992d7eec236SMarc Zyngier 			else
993d7eec236SMarc Zyngier 				bitmap_fill(vcpu->kvm->arch.pmu_filter, nr_events);
994d7eec236SMarc Zyngier 		}
995d7eec236SMarc Zyngier 
996d7eec236SMarc Zyngier 		if (filter.action == KVM_PMU_EVENT_ALLOW)
997d7eec236SMarc Zyngier 			bitmap_set(vcpu->kvm->arch.pmu_filter, filter.base_event, filter.nevents);
998d7eec236SMarc Zyngier 		else
999d7eec236SMarc Zyngier 			bitmap_clear(vcpu->kvm->arch.pmu_filter, filter.base_event, filter.nevents);
1000d7eec236SMarc Zyngier 
1001d7eec236SMarc Zyngier 		mutex_unlock(&vcpu->kvm->lock);
1002d7eec236SMarc Zyngier 
1003d7eec236SMarc Zyngier 		return 0;
1004d7eec236SMarc Zyngier 	}
10059ed24f4bSMarc Zyngier 	case KVM_ARM_VCPU_PMU_V3_INIT:
10069ed24f4bSMarc Zyngier 		return kvm_arm_pmu_v3_init(vcpu);
10079ed24f4bSMarc Zyngier 	}
10089ed24f4bSMarc Zyngier 
10099ed24f4bSMarc Zyngier 	return -ENXIO;
10109ed24f4bSMarc Zyngier }
10119ed24f4bSMarc Zyngier 
10129ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
10139ed24f4bSMarc Zyngier {
10149ed24f4bSMarc Zyngier 	switch (attr->attr) {
10159ed24f4bSMarc Zyngier 	case KVM_ARM_VCPU_PMU_V3_IRQ: {
10169ed24f4bSMarc Zyngier 		int __user *uaddr = (int __user *)(long)attr->addr;
10179ed24f4bSMarc Zyngier 		int irq;
10189ed24f4bSMarc Zyngier 
10199ed24f4bSMarc Zyngier 		if (!irqchip_in_kernel(vcpu->kvm))
10209ed24f4bSMarc Zyngier 			return -EINVAL;
10219ed24f4bSMarc Zyngier 
102214bda7a9SMarc Zyngier 		if (!kvm_vcpu_has_pmu(vcpu))
10239ed24f4bSMarc Zyngier 			return -ENODEV;
10249ed24f4bSMarc Zyngier 
10259ed24f4bSMarc Zyngier 		if (!kvm_arm_pmu_irq_initialized(vcpu))
10269ed24f4bSMarc Zyngier 			return -ENXIO;
10279ed24f4bSMarc Zyngier 
10289ed24f4bSMarc Zyngier 		irq = vcpu->arch.pmu.irq_num;
10299ed24f4bSMarc Zyngier 		return put_user(irq, uaddr);
10309ed24f4bSMarc Zyngier 	}
10319ed24f4bSMarc Zyngier 	}
10329ed24f4bSMarc Zyngier 
10339ed24f4bSMarc Zyngier 	return -ENXIO;
10349ed24f4bSMarc Zyngier }
10359ed24f4bSMarc Zyngier 
10369ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
10379ed24f4bSMarc Zyngier {
10389ed24f4bSMarc Zyngier 	switch (attr->attr) {
10399ed24f4bSMarc Zyngier 	case KVM_ARM_VCPU_PMU_V3_IRQ:
10409ed24f4bSMarc Zyngier 	case KVM_ARM_VCPU_PMU_V3_INIT:
1041d7eec236SMarc Zyngier 	case KVM_ARM_VCPU_PMU_V3_FILTER:
104277da4303SMarc Zyngier 		if (kvm_vcpu_has_pmu(vcpu))
10439ed24f4bSMarc Zyngier 			return 0;
10449ed24f4bSMarc Zyngier 	}
10459ed24f4bSMarc Zyngier 
10469ed24f4bSMarc Zyngier 	return -ENXIO;
10479ed24f4bSMarc Zyngier }
1048