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) { 268e26d11fSMarc Zyngier case ID_AA64DFR0_PMUVER_8_0: 27fd65a3b5SMarc Zyngier return GENMASK(9, 0); 288e26d11fSMarc Zyngier case ID_AA64DFR0_PMUVER_8_1: 298e26d11fSMarc Zyngier case ID_AA64DFR0_PMUVER_8_4: 308e26d11fSMarc 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 } 3779ed24f4bSMarc Zyngier 3789ed24f4bSMarc Zyngier return reg; 3799ed24f4bSMarc Zyngier } 3809ed24f4bSMarc Zyngier 3819ed24f4bSMarc Zyngier static void kvm_pmu_update_state(struct kvm_vcpu *vcpu) 3829ed24f4bSMarc Zyngier { 3839ed24f4bSMarc Zyngier struct kvm_pmu *pmu = &vcpu->arch.pmu; 3849ed24f4bSMarc Zyngier bool overflow; 3859ed24f4bSMarc Zyngier 38646acf89dSMarc Zyngier if (!kvm_vcpu_has_pmu(vcpu)) 3879ed24f4bSMarc Zyngier return; 3889ed24f4bSMarc Zyngier 3899ed24f4bSMarc Zyngier overflow = !!kvm_pmu_overflow_status(vcpu); 3909ed24f4bSMarc Zyngier if (pmu->irq_level == overflow) 3919ed24f4bSMarc Zyngier return; 3929ed24f4bSMarc Zyngier 3939ed24f4bSMarc Zyngier pmu->irq_level = overflow; 3949ed24f4bSMarc Zyngier 3959ed24f4bSMarc Zyngier if (likely(irqchip_in_kernel(vcpu->kvm))) { 3969ed24f4bSMarc Zyngier int ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, 3979ed24f4bSMarc Zyngier pmu->irq_num, overflow, pmu); 3989ed24f4bSMarc Zyngier WARN_ON(ret); 3999ed24f4bSMarc Zyngier } 4009ed24f4bSMarc Zyngier } 4019ed24f4bSMarc Zyngier 4029ed24f4bSMarc Zyngier bool kvm_pmu_should_notify_user(struct kvm_vcpu *vcpu) 4039ed24f4bSMarc Zyngier { 4049ed24f4bSMarc Zyngier struct kvm_pmu *pmu = &vcpu->arch.pmu; 4059ed24f4bSMarc Zyngier struct kvm_sync_regs *sregs = &vcpu->run->s.regs; 4069ed24f4bSMarc Zyngier bool run_level = sregs->device_irq_level & KVM_ARM_DEV_PMU; 4079ed24f4bSMarc Zyngier 4089ed24f4bSMarc Zyngier if (likely(irqchip_in_kernel(vcpu->kvm))) 4099ed24f4bSMarc Zyngier return false; 4109ed24f4bSMarc Zyngier 4119ed24f4bSMarc Zyngier return pmu->irq_level != run_level; 4129ed24f4bSMarc Zyngier } 4139ed24f4bSMarc Zyngier 4149ed24f4bSMarc Zyngier /* 4159ed24f4bSMarc Zyngier * Reflect the PMU overflow interrupt output level into the kvm_run structure 4169ed24f4bSMarc Zyngier */ 4179ed24f4bSMarc Zyngier void kvm_pmu_update_run(struct kvm_vcpu *vcpu) 4189ed24f4bSMarc Zyngier { 4199ed24f4bSMarc Zyngier struct kvm_sync_regs *regs = &vcpu->run->s.regs; 4209ed24f4bSMarc Zyngier 4219ed24f4bSMarc Zyngier /* Populate the timer bitmap for user space */ 4229ed24f4bSMarc Zyngier regs->device_irq_level &= ~KVM_ARM_DEV_PMU; 4239ed24f4bSMarc Zyngier if (vcpu->arch.pmu.irq_level) 4249ed24f4bSMarc Zyngier regs->device_irq_level |= KVM_ARM_DEV_PMU; 4259ed24f4bSMarc Zyngier } 4269ed24f4bSMarc Zyngier 4279ed24f4bSMarc Zyngier /** 4289ed24f4bSMarc Zyngier * kvm_pmu_flush_hwstate - flush pmu state to cpu 4299ed24f4bSMarc Zyngier * @vcpu: The vcpu pointer 4309ed24f4bSMarc Zyngier * 4319ed24f4bSMarc Zyngier * Check if the PMU has overflowed while we were running in the host, and inject 4329ed24f4bSMarc Zyngier * an interrupt if that was the case. 4339ed24f4bSMarc Zyngier */ 4349ed24f4bSMarc Zyngier void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu) 4359ed24f4bSMarc Zyngier { 4369ed24f4bSMarc Zyngier kvm_pmu_update_state(vcpu); 4379ed24f4bSMarc Zyngier } 4389ed24f4bSMarc Zyngier 4399ed24f4bSMarc Zyngier /** 4409ed24f4bSMarc Zyngier * kvm_pmu_sync_hwstate - sync pmu state from cpu 4419ed24f4bSMarc Zyngier * @vcpu: The vcpu pointer 4429ed24f4bSMarc Zyngier * 4439ed24f4bSMarc Zyngier * Check if the PMU has overflowed while we were running in the guest, and 4449ed24f4bSMarc Zyngier * inject an interrupt if that was the case. 4459ed24f4bSMarc Zyngier */ 4469ed24f4bSMarc Zyngier void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu) 4479ed24f4bSMarc Zyngier { 4489ed24f4bSMarc Zyngier kvm_pmu_update_state(vcpu); 4499ed24f4bSMarc Zyngier } 4509ed24f4bSMarc Zyngier 4519ed24f4bSMarc Zyngier /** 45295e92e45SJulien Thierry * When perf interrupt is an NMI, we cannot safely notify the vcpu corresponding 45395e92e45SJulien Thierry * to the event. 45495e92e45SJulien Thierry * This is why we need a callback to do it once outside of the NMI context. 45595e92e45SJulien Thierry */ 45695e92e45SJulien Thierry static void kvm_pmu_perf_overflow_notify_vcpu(struct irq_work *work) 45795e92e45SJulien Thierry { 45895e92e45SJulien Thierry struct kvm_vcpu *vcpu; 45995e92e45SJulien Thierry struct kvm_pmu *pmu; 46095e92e45SJulien Thierry 46195e92e45SJulien Thierry pmu = container_of(work, struct kvm_pmu, overflow_work); 46295e92e45SJulien Thierry vcpu = kvm_pmc_to_vcpu(pmu->pmc); 46395e92e45SJulien Thierry 46495e92e45SJulien Thierry kvm_vcpu_kick(vcpu); 46595e92e45SJulien Thierry } 46695e92e45SJulien Thierry 46795e92e45SJulien Thierry /** 4689ed24f4bSMarc Zyngier * When the perf event overflows, set the overflow status and inform the vcpu. 4699ed24f4bSMarc Zyngier */ 4709ed24f4bSMarc Zyngier static void kvm_pmu_perf_overflow(struct perf_event *perf_event, 4719ed24f4bSMarc Zyngier struct perf_sample_data *data, 4729ed24f4bSMarc Zyngier struct pt_regs *regs) 4739ed24f4bSMarc Zyngier { 4749ed24f4bSMarc Zyngier struct kvm_pmc *pmc = perf_event->overflow_handler_context; 4759ed24f4bSMarc Zyngier struct arm_pmu *cpu_pmu = to_arm_pmu(perf_event->pmu); 4769ed24f4bSMarc Zyngier struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc); 4779ed24f4bSMarc Zyngier int idx = pmc->idx; 4789ed24f4bSMarc Zyngier u64 period; 4799ed24f4bSMarc Zyngier 4809ed24f4bSMarc Zyngier cpu_pmu->pmu.stop(perf_event, PERF_EF_UPDATE); 4819ed24f4bSMarc Zyngier 4829ed24f4bSMarc Zyngier /* 4839ed24f4bSMarc Zyngier * Reset the sample period to the architectural limit, 4849ed24f4bSMarc Zyngier * i.e. the point where the counter overflows. 4859ed24f4bSMarc Zyngier */ 4869ed24f4bSMarc Zyngier period = -(local64_read(&perf_event->count)); 4879ed24f4bSMarc Zyngier 4889ed24f4bSMarc Zyngier if (!kvm_pmu_idx_is_64bit(vcpu, pmc->idx)) 4899ed24f4bSMarc Zyngier period &= GENMASK(31, 0); 4909ed24f4bSMarc Zyngier 4919ed24f4bSMarc Zyngier local64_set(&perf_event->hw.period_left, 0); 4929ed24f4bSMarc Zyngier perf_event->attr.sample_period = period; 4939ed24f4bSMarc Zyngier perf_event->hw.sample_period = period; 4949ed24f4bSMarc Zyngier 4959ed24f4bSMarc Zyngier __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx); 4969ed24f4bSMarc Zyngier 4979ed24f4bSMarc Zyngier if (kvm_pmu_overflow_status(vcpu)) { 4989ed24f4bSMarc Zyngier kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu); 49995e92e45SJulien Thierry 50095e92e45SJulien Thierry if (!in_nmi()) 5019ed24f4bSMarc Zyngier kvm_vcpu_kick(vcpu); 50295e92e45SJulien Thierry else 50395e92e45SJulien Thierry irq_work_queue(&vcpu->arch.pmu.overflow_work); 5049ed24f4bSMarc Zyngier } 5059ed24f4bSMarc Zyngier 5069ed24f4bSMarc Zyngier cpu_pmu->pmu.start(perf_event, PERF_EF_RELOAD); 5079ed24f4bSMarc Zyngier } 5089ed24f4bSMarc Zyngier 5099ed24f4bSMarc Zyngier /** 5109ed24f4bSMarc Zyngier * kvm_pmu_software_increment - do software increment 5119ed24f4bSMarc Zyngier * @vcpu: The vcpu pointer 5129ed24f4bSMarc Zyngier * @val: the value guest writes to PMSWINC register 5139ed24f4bSMarc Zyngier */ 5149ed24f4bSMarc Zyngier void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val) 5159ed24f4bSMarc Zyngier { 5169ed24f4bSMarc Zyngier struct kvm_pmu *pmu = &vcpu->arch.pmu; 5179ed24f4bSMarc Zyngier int i; 5189ed24f4bSMarc Zyngier 5199ed24f4bSMarc Zyngier if (!(__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E)) 5209ed24f4bSMarc Zyngier return; 5219ed24f4bSMarc Zyngier 5229ed24f4bSMarc Zyngier /* Weed out disabled counters */ 5239ed24f4bSMarc Zyngier val &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0); 5249ed24f4bSMarc Zyngier 5259ed24f4bSMarc Zyngier for (i = 0; i < ARMV8_PMU_CYCLE_IDX; i++) { 5269ed24f4bSMarc Zyngier u64 type, reg; 5279ed24f4bSMarc Zyngier 5289ed24f4bSMarc Zyngier if (!(val & BIT(i))) 5299ed24f4bSMarc Zyngier continue; 5309ed24f4bSMarc Zyngier 5319ed24f4bSMarc Zyngier /* PMSWINC only applies to ... SW_INC! */ 5329ed24f4bSMarc Zyngier type = __vcpu_sys_reg(vcpu, PMEVTYPER0_EL0 + i); 533fd65a3b5SMarc Zyngier type &= kvm_pmu_event_mask(vcpu->kvm); 5349ed24f4bSMarc Zyngier if (type != ARMV8_PMUV3_PERFCTR_SW_INCR) 5359ed24f4bSMarc Zyngier continue; 5369ed24f4bSMarc Zyngier 5379ed24f4bSMarc Zyngier /* increment this even SW_INC counter */ 5389ed24f4bSMarc Zyngier reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) + 1; 5399ed24f4bSMarc Zyngier reg = lower_32_bits(reg); 5409ed24f4bSMarc Zyngier __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) = reg; 5419ed24f4bSMarc Zyngier 5429ed24f4bSMarc Zyngier if (reg) /* no overflow on the low part */ 5439ed24f4bSMarc Zyngier continue; 5449ed24f4bSMarc Zyngier 5459ed24f4bSMarc Zyngier if (kvm_pmu_pmc_is_chained(&pmu->pmc[i])) { 5469ed24f4bSMarc Zyngier /* increment the high counter */ 5479ed24f4bSMarc Zyngier reg = __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i + 1) + 1; 5489ed24f4bSMarc Zyngier reg = lower_32_bits(reg); 5499ed24f4bSMarc Zyngier __vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i + 1) = reg; 5509ed24f4bSMarc Zyngier if (!reg) /* mark overflow on the high counter */ 5519ed24f4bSMarc Zyngier __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i + 1); 5529ed24f4bSMarc Zyngier } else { 5539ed24f4bSMarc Zyngier /* mark overflow on low counter */ 5549ed24f4bSMarc Zyngier __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i); 5559ed24f4bSMarc Zyngier } 5569ed24f4bSMarc Zyngier } 5579ed24f4bSMarc Zyngier } 5589ed24f4bSMarc Zyngier 5599ed24f4bSMarc Zyngier /** 5609ed24f4bSMarc Zyngier * kvm_pmu_handle_pmcr - handle PMCR register 5619ed24f4bSMarc Zyngier * @vcpu: The vcpu pointer 5629ed24f4bSMarc Zyngier * @val: the value guest writes to PMCR register 5639ed24f4bSMarc Zyngier */ 5649ed24f4bSMarc Zyngier void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) 5659ed24f4bSMarc Zyngier { 5669ed24f4bSMarc Zyngier int i; 5679ed24f4bSMarc Zyngier 5689ed24f4bSMarc Zyngier if (val & ARMV8_PMU_PMCR_E) { 5699ed24f4bSMarc Zyngier kvm_pmu_enable_counter_mask(vcpu, 570f5eff400SMarc Zyngier __vcpu_sys_reg(vcpu, PMCNTENSET_EL0)); 5719ed24f4bSMarc Zyngier } else { 572ca4f202dSAlexandre Chartre kvm_pmu_disable_counter_mask(vcpu, 573ca4f202dSAlexandre Chartre __vcpu_sys_reg(vcpu, PMCNTENSET_EL0)); 5749ed24f4bSMarc Zyngier } 5759ed24f4bSMarc Zyngier 5769ed24f4bSMarc Zyngier if (val & ARMV8_PMU_PMCR_C) 5779ed24f4bSMarc Zyngier kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0); 5789ed24f4bSMarc Zyngier 5799ed24f4bSMarc Zyngier if (val & ARMV8_PMU_PMCR_P) { 580ca4f202dSAlexandre Chartre unsigned long mask = kvm_pmu_valid_counter_mask(vcpu); 5812a71fabfSAlexandru Elisei mask &= ~BIT(ARMV8_PMU_CYCLE_IDX); 5829ed24f4bSMarc Zyngier for_each_set_bit(i, &mask, 32) 5839ed24f4bSMarc Zyngier kvm_pmu_set_counter_value(vcpu, i, 0); 5849ed24f4bSMarc Zyngier } 5859ed24f4bSMarc Zyngier } 5869ed24f4bSMarc Zyngier 5879ed24f4bSMarc Zyngier static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u64 select_idx) 5889ed24f4bSMarc Zyngier { 5899ed24f4bSMarc Zyngier return (__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) && 5909ed24f4bSMarc Zyngier (__vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(select_idx)); 5919ed24f4bSMarc Zyngier } 5929ed24f4bSMarc Zyngier 5939ed24f4bSMarc Zyngier /** 5949ed24f4bSMarc Zyngier * kvm_pmu_create_perf_event - create a perf event for a counter 5959ed24f4bSMarc Zyngier * @vcpu: The vcpu pointer 5969ed24f4bSMarc Zyngier * @select_idx: The number of selected counter 5979ed24f4bSMarc Zyngier */ 5989ed24f4bSMarc Zyngier static void kvm_pmu_create_perf_event(struct kvm_vcpu *vcpu, u64 select_idx) 5999ed24f4bSMarc Zyngier { 6009ed24f4bSMarc Zyngier struct kvm_pmu *pmu = &vcpu->arch.pmu; 6019ed24f4bSMarc Zyngier struct kvm_pmc *pmc; 6029ed24f4bSMarc Zyngier struct perf_event *event; 6039ed24f4bSMarc Zyngier struct perf_event_attr attr; 6049ed24f4bSMarc Zyngier u64 eventsel, counter, reg, data; 6059ed24f4bSMarc Zyngier 6069ed24f4bSMarc Zyngier /* 6079ed24f4bSMarc Zyngier * For chained counters the event type and filtering attributes are 6089ed24f4bSMarc Zyngier * obtained from the low/even counter. We also use this counter to 6099ed24f4bSMarc Zyngier * determine if the event is enabled/disabled. 6109ed24f4bSMarc Zyngier */ 6119ed24f4bSMarc Zyngier pmc = kvm_pmu_get_canonical_pmc(&pmu->pmc[select_idx]); 6129ed24f4bSMarc Zyngier 6139ed24f4bSMarc Zyngier reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX) 6149ed24f4bSMarc Zyngier ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + pmc->idx; 6159ed24f4bSMarc Zyngier data = __vcpu_sys_reg(vcpu, reg); 6169ed24f4bSMarc Zyngier 6179ed24f4bSMarc Zyngier kvm_pmu_stop_counter(vcpu, pmc); 618d7eec236SMarc Zyngier if (pmc->idx == ARMV8_PMU_CYCLE_IDX) 619d7eec236SMarc Zyngier eventsel = ARMV8_PMUV3_PERFCTR_CPU_CYCLES; 620d7eec236SMarc Zyngier else 621d7eec236SMarc Zyngier eventsel = data & kvm_pmu_event_mask(vcpu->kvm); 6229ed24f4bSMarc Zyngier 623d7eec236SMarc Zyngier /* Software increment event doesn't need to be backed by a perf event */ 624d7eec236SMarc Zyngier if (eventsel == ARMV8_PMUV3_PERFCTR_SW_INCR) 625d7eec236SMarc Zyngier return; 626d7eec236SMarc Zyngier 627d7eec236SMarc Zyngier /* 628d7eec236SMarc Zyngier * If we have a filter in place and that the event isn't allowed, do 629d7eec236SMarc Zyngier * not install a perf event either. 630d7eec236SMarc Zyngier */ 631d7eec236SMarc Zyngier if (vcpu->kvm->arch.pmu_filter && 632d7eec236SMarc Zyngier !test_bit(eventsel, vcpu->kvm->arch.pmu_filter)) 6339ed24f4bSMarc Zyngier return; 6349ed24f4bSMarc Zyngier 6359ed24f4bSMarc Zyngier memset(&attr, 0, sizeof(struct perf_event_attr)); 6369ed24f4bSMarc Zyngier attr.type = PERF_TYPE_RAW; 6379ed24f4bSMarc Zyngier attr.size = sizeof(attr); 6389ed24f4bSMarc Zyngier attr.pinned = 1; 6399ed24f4bSMarc Zyngier attr.disabled = !kvm_pmu_counter_is_enabled(vcpu, pmc->idx); 6409ed24f4bSMarc Zyngier attr.exclude_user = data & ARMV8_PMU_EXCLUDE_EL0 ? 1 : 0; 6419ed24f4bSMarc Zyngier attr.exclude_kernel = data & ARMV8_PMU_EXCLUDE_EL1 ? 1 : 0; 6429ed24f4bSMarc Zyngier attr.exclude_hv = 1; /* Don't count EL2 events */ 6439ed24f4bSMarc Zyngier attr.exclude_host = 1; /* Don't count host events */ 644d7eec236SMarc Zyngier attr.config = eventsel; 6459ed24f4bSMarc Zyngier 6469ed24f4bSMarc Zyngier counter = kvm_pmu_get_pair_counter_value(vcpu, pmc); 6479ed24f4bSMarc Zyngier 6489ed24f4bSMarc Zyngier if (kvm_pmu_pmc_is_chained(pmc)) { 6499ed24f4bSMarc Zyngier /** 6509ed24f4bSMarc Zyngier * The initial sample period (overflow count) of an event. For 6519ed24f4bSMarc Zyngier * chained counters we only support overflow interrupts on the 6529ed24f4bSMarc Zyngier * high counter. 6539ed24f4bSMarc Zyngier */ 6549ed24f4bSMarc Zyngier attr.sample_period = (-counter) & GENMASK(63, 0); 6559ed24f4bSMarc Zyngier attr.config1 |= PERF_ATTR_CFG1_KVM_PMU_CHAINED; 6569ed24f4bSMarc Zyngier 6579ed24f4bSMarc Zyngier event = perf_event_create_kernel_counter(&attr, -1, current, 6589ed24f4bSMarc Zyngier kvm_pmu_perf_overflow, 6599ed24f4bSMarc Zyngier pmc + 1); 6609ed24f4bSMarc Zyngier } else { 6619ed24f4bSMarc Zyngier /* The initial sample period (overflow count) of an event. */ 6629ed24f4bSMarc Zyngier if (kvm_pmu_idx_is_64bit(vcpu, pmc->idx)) 6639ed24f4bSMarc Zyngier attr.sample_period = (-counter) & GENMASK(63, 0); 6649ed24f4bSMarc Zyngier else 6659ed24f4bSMarc Zyngier attr.sample_period = (-counter) & GENMASK(31, 0); 6669ed24f4bSMarc Zyngier 6679ed24f4bSMarc Zyngier event = perf_event_create_kernel_counter(&attr, -1, current, 6689ed24f4bSMarc Zyngier kvm_pmu_perf_overflow, pmc); 6699ed24f4bSMarc Zyngier } 6709ed24f4bSMarc Zyngier 6719ed24f4bSMarc Zyngier if (IS_ERR(event)) { 6729ed24f4bSMarc Zyngier pr_err_once("kvm: pmu event creation failed %ld\n", 6739ed24f4bSMarc Zyngier PTR_ERR(event)); 6749ed24f4bSMarc Zyngier return; 6759ed24f4bSMarc Zyngier } 6769ed24f4bSMarc Zyngier 6779ed24f4bSMarc Zyngier pmc->perf_event = event; 6789ed24f4bSMarc Zyngier } 6799ed24f4bSMarc Zyngier 6809ed24f4bSMarc Zyngier /** 6819ed24f4bSMarc Zyngier * kvm_pmu_update_pmc_chained - update chained bitmap 6829ed24f4bSMarc Zyngier * @vcpu: The vcpu pointer 6839ed24f4bSMarc Zyngier * @select_idx: The number of selected counter 6849ed24f4bSMarc Zyngier * 6859ed24f4bSMarc Zyngier * Update the chained bitmap based on the event type written in the 6869ed24f4bSMarc Zyngier * typer register and the enable state of the odd register. 6879ed24f4bSMarc Zyngier */ 6889ed24f4bSMarc Zyngier static void kvm_pmu_update_pmc_chained(struct kvm_vcpu *vcpu, u64 select_idx) 6899ed24f4bSMarc Zyngier { 6909ed24f4bSMarc Zyngier struct kvm_pmu *pmu = &vcpu->arch.pmu; 6919ed24f4bSMarc Zyngier struct kvm_pmc *pmc = &pmu->pmc[select_idx], *canonical_pmc; 6929ed24f4bSMarc Zyngier bool new_state, old_state; 6939ed24f4bSMarc Zyngier 6949ed24f4bSMarc Zyngier old_state = kvm_pmu_pmc_is_chained(pmc); 6959ed24f4bSMarc Zyngier new_state = kvm_pmu_idx_has_chain_evtype(vcpu, pmc->idx) && 6969ed24f4bSMarc Zyngier kvm_pmu_counter_is_enabled(vcpu, pmc->idx | 0x1); 6979ed24f4bSMarc Zyngier 6989ed24f4bSMarc Zyngier if (old_state == new_state) 6999ed24f4bSMarc Zyngier return; 7009ed24f4bSMarc Zyngier 7019ed24f4bSMarc Zyngier canonical_pmc = kvm_pmu_get_canonical_pmc(pmc); 7029ed24f4bSMarc Zyngier kvm_pmu_stop_counter(vcpu, canonical_pmc); 7039ed24f4bSMarc Zyngier if (new_state) { 7049ed24f4bSMarc Zyngier /* 7059ed24f4bSMarc Zyngier * During promotion from !chained to chained we must ensure 7069ed24f4bSMarc Zyngier * the adjacent counter is stopped and its event destroyed 7079ed24f4bSMarc Zyngier */ 7089ed24f4bSMarc Zyngier kvm_pmu_stop_counter(vcpu, kvm_pmu_get_alternate_pmc(pmc)); 7099ed24f4bSMarc Zyngier set_bit(pmc->idx >> 1, vcpu->arch.pmu.chained); 7109ed24f4bSMarc Zyngier return; 7119ed24f4bSMarc Zyngier } 7129ed24f4bSMarc Zyngier clear_bit(pmc->idx >> 1, vcpu->arch.pmu.chained); 7139ed24f4bSMarc Zyngier } 7149ed24f4bSMarc Zyngier 7159ed24f4bSMarc Zyngier /** 7169ed24f4bSMarc Zyngier * kvm_pmu_set_counter_event_type - set selected counter to monitor some event 7179ed24f4bSMarc Zyngier * @vcpu: The vcpu pointer 7189ed24f4bSMarc Zyngier * @data: The data guest writes to PMXEVTYPER_EL0 7199ed24f4bSMarc Zyngier * @select_idx: The number of selected counter 7209ed24f4bSMarc Zyngier * 7219ed24f4bSMarc Zyngier * When OS accesses PMXEVTYPER_EL0, that means it wants to set a PMC to count an 7229ed24f4bSMarc Zyngier * event with given hardware event number. Here we call perf_event API to 7239ed24f4bSMarc Zyngier * emulate this action and create a kernel perf event for it. 7249ed24f4bSMarc Zyngier */ 7259ed24f4bSMarc Zyngier void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, 7269ed24f4bSMarc Zyngier u64 select_idx) 7279ed24f4bSMarc Zyngier { 728fd65a3b5SMarc Zyngier u64 reg, mask; 729fd65a3b5SMarc Zyngier 730fd65a3b5SMarc Zyngier mask = ARMV8_PMU_EVTYPE_MASK; 731fd65a3b5SMarc Zyngier mask &= ~ARMV8_PMU_EVTYPE_EVENT; 732fd65a3b5SMarc Zyngier mask |= kvm_pmu_event_mask(vcpu->kvm); 7339ed24f4bSMarc Zyngier 7349ed24f4bSMarc Zyngier reg = (select_idx == ARMV8_PMU_CYCLE_IDX) 7359ed24f4bSMarc Zyngier ? PMCCFILTR_EL0 : PMEVTYPER0_EL0 + select_idx; 7369ed24f4bSMarc Zyngier 737fd65a3b5SMarc Zyngier __vcpu_sys_reg(vcpu, reg) = data & mask; 7389ed24f4bSMarc Zyngier 7399ed24f4bSMarc Zyngier kvm_pmu_update_pmc_chained(vcpu, select_idx); 7409ed24f4bSMarc Zyngier kvm_pmu_create_perf_event(vcpu, select_idx); 7419ed24f4bSMarc Zyngier } 7429ed24f4bSMarc Zyngier 743e840f42aSMarc Zyngier void kvm_host_pmu_init(struct arm_pmu *pmu) 744e840f42aSMarc Zyngier { 745e840f42aSMarc Zyngier if (pmu->pmuver != 0 && pmu->pmuver != ID_AA64DFR0_PMUVER_IMP_DEF && 746e840f42aSMarc Zyngier !kvm_arm_support_pmu_v3() && !is_protected_kvm_enabled()) 747e840f42aSMarc Zyngier static_branch_enable(&kvm_arm_pmu_available); 748e840f42aSMarc Zyngier } 749e840f42aSMarc Zyngier 750e840f42aSMarc Zyngier static int kvm_pmu_probe_pmuver(void) 751fd65a3b5SMarc Zyngier { 752fd65a3b5SMarc Zyngier struct perf_event_attr attr = { }; 753fd65a3b5SMarc Zyngier struct perf_event *event; 754fd65a3b5SMarc Zyngier struct arm_pmu *pmu; 7556fadc124SAnshuman Khandual int pmuver = ID_AA64DFR0_PMUVER_IMP_DEF; 756fd65a3b5SMarc Zyngier 757fd65a3b5SMarc Zyngier /* 758fd65a3b5SMarc Zyngier * Create a dummy event that only counts user cycles. As we'll never 759fd65a3b5SMarc Zyngier * leave this function with the event being live, it will never 760fd65a3b5SMarc Zyngier * count anything. But it allows us to probe some of the PMU 761fd65a3b5SMarc Zyngier * details. Yes, this is terrible. 762fd65a3b5SMarc Zyngier */ 763fd65a3b5SMarc Zyngier attr.type = PERF_TYPE_RAW; 764fd65a3b5SMarc Zyngier attr.size = sizeof(attr); 765fd65a3b5SMarc Zyngier attr.pinned = 1; 766fd65a3b5SMarc Zyngier attr.disabled = 0; 767fd65a3b5SMarc Zyngier attr.exclude_user = 0; 768fd65a3b5SMarc Zyngier attr.exclude_kernel = 1; 769fd65a3b5SMarc Zyngier attr.exclude_hv = 1; 770fd65a3b5SMarc Zyngier attr.exclude_host = 1; 771fd65a3b5SMarc Zyngier attr.config = ARMV8_PMUV3_PERFCTR_CPU_CYCLES; 772fd65a3b5SMarc Zyngier attr.sample_period = GENMASK(63, 0); 773fd65a3b5SMarc Zyngier 774fd65a3b5SMarc Zyngier event = perf_event_create_kernel_counter(&attr, -1, current, 775fd65a3b5SMarc Zyngier kvm_pmu_perf_overflow, &attr); 776fd65a3b5SMarc Zyngier 777fd65a3b5SMarc Zyngier if (IS_ERR(event)) { 778fd65a3b5SMarc Zyngier pr_err_once("kvm: pmu event creation failed %ld\n", 779fd65a3b5SMarc Zyngier PTR_ERR(event)); 7806fadc124SAnshuman Khandual return ID_AA64DFR0_PMUVER_IMP_DEF; 781fd65a3b5SMarc Zyngier } 782fd65a3b5SMarc Zyngier 783fd65a3b5SMarc Zyngier if (event->pmu) { 784fd65a3b5SMarc Zyngier pmu = to_arm_pmu(event->pmu); 785fd65a3b5SMarc Zyngier if (pmu->pmuver) 786fd65a3b5SMarc Zyngier pmuver = pmu->pmuver; 787fd65a3b5SMarc Zyngier } 788fd65a3b5SMarc Zyngier 789fd65a3b5SMarc Zyngier perf_event_disable(event); 790fd65a3b5SMarc Zyngier perf_event_release_kernel(event); 791fd65a3b5SMarc Zyngier 792fd65a3b5SMarc Zyngier return pmuver; 793fd65a3b5SMarc Zyngier } 794fd65a3b5SMarc Zyngier 79588865becSMarc Zyngier u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1) 79688865becSMarc Zyngier { 79788865becSMarc Zyngier unsigned long *bmap = vcpu->kvm->arch.pmu_filter; 79888865becSMarc Zyngier u64 val, mask = 0; 7999529aaa0SMarc Zyngier int base, i, nr_events; 80088865becSMarc Zyngier 80188865becSMarc Zyngier if (!pmceid1) { 80288865becSMarc Zyngier val = read_sysreg(pmceid0_el0); 80388865becSMarc Zyngier base = 0; 80488865becSMarc Zyngier } else { 80588865becSMarc Zyngier val = read_sysreg(pmceid1_el0); 80646081078SMarc Zyngier /* 80746081078SMarc Zyngier * Don't advertise STALL_SLOT, as PMMIR_EL0 is handled 80846081078SMarc Zyngier * as RAZ 80946081078SMarc Zyngier */ 81046081078SMarc Zyngier if (vcpu->kvm->arch.pmuver >= ID_AA64DFR0_PMUVER_8_4) 81146081078SMarc Zyngier val &= ~BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32); 81288865becSMarc Zyngier base = 32; 81388865becSMarc Zyngier } 81488865becSMarc Zyngier 81588865becSMarc Zyngier if (!bmap) 81688865becSMarc Zyngier return val; 81788865becSMarc Zyngier 8189529aaa0SMarc Zyngier nr_events = kvm_pmu_event_mask(vcpu->kvm) + 1; 8199529aaa0SMarc Zyngier 82088865becSMarc Zyngier for (i = 0; i < 32; i += 8) { 82188865becSMarc Zyngier u64 byte; 82288865becSMarc Zyngier 82388865becSMarc Zyngier byte = bitmap_get_value8(bmap, base + i); 82488865becSMarc Zyngier mask |= byte << i; 8259529aaa0SMarc Zyngier if (nr_events >= (0x4000 + base + 32)) { 82688865becSMarc Zyngier byte = bitmap_get_value8(bmap, 0x4000 + base + i); 82788865becSMarc Zyngier mask |= byte << (32 + i); 82888865becSMarc Zyngier } 8299529aaa0SMarc Zyngier } 83088865becSMarc Zyngier 83188865becSMarc Zyngier return val & mask; 83288865becSMarc Zyngier } 83388865becSMarc Zyngier 8349ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu) 8359ed24f4bSMarc Zyngier { 8369bbfa4b5SAlexandru Elisei if (!kvm_vcpu_has_pmu(vcpu)) 8379ed24f4bSMarc Zyngier return 0; 8389ed24f4bSMarc Zyngier 8399bbfa4b5SAlexandru Elisei if (!vcpu->arch.pmu.created) 8409bbfa4b5SAlexandru Elisei return -EINVAL; 8419bbfa4b5SAlexandru Elisei 8429ed24f4bSMarc Zyngier /* 8439ed24f4bSMarc Zyngier * A valid interrupt configuration for the PMU is either to have a 8449ed24f4bSMarc Zyngier * properly configured interrupt number and using an in-kernel 8459ed24f4bSMarc Zyngier * irqchip, or to not have an in-kernel GIC and not set an IRQ. 8469ed24f4bSMarc Zyngier */ 8479ed24f4bSMarc Zyngier if (irqchip_in_kernel(vcpu->kvm)) { 8489ed24f4bSMarc Zyngier int irq = vcpu->arch.pmu.irq_num; 8499ed24f4bSMarc Zyngier /* 8509ed24f4bSMarc Zyngier * If we are using an in-kernel vgic, at this point we know 8519ed24f4bSMarc Zyngier * the vgic will be initialized, so we can check the PMU irq 8529ed24f4bSMarc Zyngier * number against the dimensions of the vgic and make sure 8539ed24f4bSMarc Zyngier * it's valid. 8549ed24f4bSMarc Zyngier */ 8559ed24f4bSMarc Zyngier if (!irq_is_ppi(irq) && !vgic_valid_spi(vcpu->kvm, irq)) 8569ed24f4bSMarc Zyngier return -EINVAL; 8579ed24f4bSMarc Zyngier } else if (kvm_arm_pmu_irq_initialized(vcpu)) { 8589ed24f4bSMarc Zyngier return -EINVAL; 8599ed24f4bSMarc Zyngier } 8609ed24f4bSMarc Zyngier 861d0c94c49SMarc Zyngier /* One-off reload of the PMU on first run */ 862d0c94c49SMarc Zyngier kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); 863d0c94c49SMarc Zyngier 8649ed24f4bSMarc Zyngier return 0; 8659ed24f4bSMarc Zyngier } 8669ed24f4bSMarc Zyngier 8679ed24f4bSMarc Zyngier static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu) 8689ed24f4bSMarc Zyngier { 8699ed24f4bSMarc Zyngier if (irqchip_in_kernel(vcpu->kvm)) { 8709ed24f4bSMarc Zyngier int ret; 8719ed24f4bSMarc Zyngier 8729ed24f4bSMarc Zyngier /* 8739ed24f4bSMarc Zyngier * If using the PMU with an in-kernel virtual GIC 8749ed24f4bSMarc Zyngier * implementation, we require the GIC to be already 8759ed24f4bSMarc Zyngier * initialized when initializing the PMU. 8769ed24f4bSMarc Zyngier */ 8779ed24f4bSMarc Zyngier if (!vgic_initialized(vcpu->kvm)) 8789ed24f4bSMarc Zyngier return -ENODEV; 8799ed24f4bSMarc Zyngier 8809ed24f4bSMarc Zyngier if (!kvm_arm_pmu_irq_initialized(vcpu)) 8819ed24f4bSMarc Zyngier return -ENXIO; 8829ed24f4bSMarc Zyngier 8839ed24f4bSMarc Zyngier ret = kvm_vgic_set_owner(vcpu, vcpu->arch.pmu.irq_num, 8849ed24f4bSMarc Zyngier &vcpu->arch.pmu); 8859ed24f4bSMarc Zyngier if (ret) 8869ed24f4bSMarc Zyngier return ret; 8879ed24f4bSMarc Zyngier } 8889ed24f4bSMarc Zyngier 88995e92e45SJulien Thierry init_irq_work(&vcpu->arch.pmu.overflow_work, 89095e92e45SJulien Thierry kvm_pmu_perf_overflow_notify_vcpu); 89195e92e45SJulien Thierry 8929ed24f4bSMarc Zyngier vcpu->arch.pmu.created = true; 8939ed24f4bSMarc Zyngier return 0; 8949ed24f4bSMarc Zyngier } 8959ed24f4bSMarc Zyngier 8969ed24f4bSMarc Zyngier /* 8979ed24f4bSMarc Zyngier * For one VM the interrupt type must be same for each vcpu. 8989ed24f4bSMarc Zyngier * As a PPI, the interrupt number is the same for all vcpus, 8999ed24f4bSMarc Zyngier * while as an SPI it must be a separate number per vcpu. 9009ed24f4bSMarc Zyngier */ 9019ed24f4bSMarc Zyngier static bool pmu_irq_is_valid(struct kvm *kvm, int irq) 9029ed24f4bSMarc Zyngier { 9039ed24f4bSMarc Zyngier int i; 9049ed24f4bSMarc Zyngier struct kvm_vcpu *vcpu; 9059ed24f4bSMarc Zyngier 9069ed24f4bSMarc Zyngier kvm_for_each_vcpu(i, vcpu, kvm) { 9079ed24f4bSMarc Zyngier if (!kvm_arm_pmu_irq_initialized(vcpu)) 9089ed24f4bSMarc Zyngier continue; 9099ed24f4bSMarc Zyngier 9109ed24f4bSMarc Zyngier if (irq_is_ppi(irq)) { 9119ed24f4bSMarc Zyngier if (vcpu->arch.pmu.irq_num != irq) 9129ed24f4bSMarc Zyngier return false; 9139ed24f4bSMarc Zyngier } else { 9149ed24f4bSMarc Zyngier if (vcpu->arch.pmu.irq_num == irq) 9159ed24f4bSMarc Zyngier return false; 9169ed24f4bSMarc Zyngier } 9179ed24f4bSMarc Zyngier } 9189ed24f4bSMarc Zyngier 9199ed24f4bSMarc Zyngier return true; 9209ed24f4bSMarc Zyngier } 9219ed24f4bSMarc Zyngier 9229ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) 9239ed24f4bSMarc Zyngier { 92477da4303SMarc Zyngier if (!kvm_vcpu_has_pmu(vcpu)) 92542223fb1SMarc Zyngier return -ENODEV; 92642223fb1SMarc Zyngier 92742223fb1SMarc Zyngier if (vcpu->arch.pmu.created) 92842223fb1SMarc Zyngier return -EBUSY; 92942223fb1SMarc Zyngier 930fd65a3b5SMarc Zyngier if (!vcpu->kvm->arch.pmuver) 931fd65a3b5SMarc Zyngier vcpu->kvm->arch.pmuver = kvm_pmu_probe_pmuver(); 932fd65a3b5SMarc Zyngier 9336fadc124SAnshuman Khandual if (vcpu->kvm->arch.pmuver == ID_AA64DFR0_PMUVER_IMP_DEF) 934fd65a3b5SMarc Zyngier return -ENODEV; 935fd65a3b5SMarc Zyngier 9369ed24f4bSMarc Zyngier switch (attr->attr) { 9379ed24f4bSMarc Zyngier case KVM_ARM_VCPU_PMU_V3_IRQ: { 9389ed24f4bSMarc Zyngier int __user *uaddr = (int __user *)(long)attr->addr; 9399ed24f4bSMarc Zyngier int irq; 9409ed24f4bSMarc Zyngier 9419ed24f4bSMarc Zyngier if (!irqchip_in_kernel(vcpu->kvm)) 9429ed24f4bSMarc Zyngier return -EINVAL; 9439ed24f4bSMarc Zyngier 9449ed24f4bSMarc Zyngier if (get_user(irq, uaddr)) 9459ed24f4bSMarc Zyngier return -EFAULT; 9469ed24f4bSMarc Zyngier 9479ed24f4bSMarc Zyngier /* The PMU overflow interrupt can be a PPI or a valid SPI. */ 9489ed24f4bSMarc Zyngier if (!(irq_is_ppi(irq) || irq_is_spi(irq))) 9499ed24f4bSMarc Zyngier return -EINVAL; 9509ed24f4bSMarc Zyngier 9519ed24f4bSMarc Zyngier if (!pmu_irq_is_valid(vcpu->kvm, irq)) 9529ed24f4bSMarc Zyngier return -EINVAL; 9539ed24f4bSMarc Zyngier 9549ed24f4bSMarc Zyngier if (kvm_arm_pmu_irq_initialized(vcpu)) 9559ed24f4bSMarc Zyngier return -EBUSY; 9569ed24f4bSMarc Zyngier 9579ed24f4bSMarc Zyngier kvm_debug("Set kvm ARM PMU irq: %d\n", irq); 9589ed24f4bSMarc Zyngier vcpu->arch.pmu.irq_num = irq; 9599ed24f4bSMarc Zyngier return 0; 9609ed24f4bSMarc Zyngier } 961d7eec236SMarc Zyngier case KVM_ARM_VCPU_PMU_V3_FILTER: { 962d7eec236SMarc Zyngier struct kvm_pmu_event_filter __user *uaddr; 963d7eec236SMarc Zyngier struct kvm_pmu_event_filter filter; 964d7eec236SMarc Zyngier int nr_events; 965d7eec236SMarc Zyngier 966d7eec236SMarc Zyngier nr_events = kvm_pmu_event_mask(vcpu->kvm) + 1; 967d7eec236SMarc Zyngier 968d7eec236SMarc Zyngier uaddr = (struct kvm_pmu_event_filter __user *)(long)attr->addr; 969d7eec236SMarc Zyngier 970d7eec236SMarc Zyngier if (copy_from_user(&filter, uaddr, sizeof(filter))) 971d7eec236SMarc Zyngier return -EFAULT; 972d7eec236SMarc Zyngier 973d7eec236SMarc Zyngier if (((u32)filter.base_event + filter.nevents) > nr_events || 974d7eec236SMarc Zyngier (filter.action != KVM_PMU_EVENT_ALLOW && 975d7eec236SMarc Zyngier filter.action != KVM_PMU_EVENT_DENY)) 976d7eec236SMarc Zyngier return -EINVAL; 977d7eec236SMarc Zyngier 978d7eec236SMarc Zyngier mutex_lock(&vcpu->kvm->lock); 979d7eec236SMarc Zyngier 980d7eec236SMarc Zyngier if (!vcpu->kvm->arch.pmu_filter) { 981*115bae92SJia He vcpu->kvm->arch.pmu_filter = bitmap_alloc(nr_events, GFP_KERNEL_ACCOUNT); 982d7eec236SMarc Zyngier if (!vcpu->kvm->arch.pmu_filter) { 983d7eec236SMarc Zyngier mutex_unlock(&vcpu->kvm->lock); 984d7eec236SMarc Zyngier return -ENOMEM; 985d7eec236SMarc Zyngier } 986d7eec236SMarc Zyngier 987d7eec236SMarc Zyngier /* 988d7eec236SMarc Zyngier * The default depends on the first applied filter. 989d7eec236SMarc Zyngier * If it allows events, the default is to deny. 990d7eec236SMarc Zyngier * Conversely, if the first filter denies a set of 991d7eec236SMarc Zyngier * events, the default is to allow. 992d7eec236SMarc Zyngier */ 993d7eec236SMarc Zyngier if (filter.action == KVM_PMU_EVENT_ALLOW) 994d7eec236SMarc Zyngier bitmap_zero(vcpu->kvm->arch.pmu_filter, nr_events); 995d7eec236SMarc Zyngier else 996d7eec236SMarc Zyngier bitmap_fill(vcpu->kvm->arch.pmu_filter, nr_events); 997d7eec236SMarc Zyngier } 998d7eec236SMarc Zyngier 999d7eec236SMarc Zyngier if (filter.action == KVM_PMU_EVENT_ALLOW) 1000d7eec236SMarc Zyngier bitmap_set(vcpu->kvm->arch.pmu_filter, filter.base_event, filter.nevents); 1001d7eec236SMarc Zyngier else 1002d7eec236SMarc Zyngier bitmap_clear(vcpu->kvm->arch.pmu_filter, filter.base_event, filter.nevents); 1003d7eec236SMarc Zyngier 1004d7eec236SMarc Zyngier mutex_unlock(&vcpu->kvm->lock); 1005d7eec236SMarc Zyngier 1006d7eec236SMarc Zyngier return 0; 1007d7eec236SMarc Zyngier } 10089ed24f4bSMarc Zyngier case KVM_ARM_VCPU_PMU_V3_INIT: 10099ed24f4bSMarc Zyngier return kvm_arm_pmu_v3_init(vcpu); 10109ed24f4bSMarc Zyngier } 10119ed24f4bSMarc Zyngier 10129ed24f4bSMarc Zyngier return -ENXIO; 10139ed24f4bSMarc Zyngier } 10149ed24f4bSMarc Zyngier 10159ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) 10169ed24f4bSMarc Zyngier { 10179ed24f4bSMarc Zyngier switch (attr->attr) { 10189ed24f4bSMarc Zyngier case KVM_ARM_VCPU_PMU_V3_IRQ: { 10199ed24f4bSMarc Zyngier int __user *uaddr = (int __user *)(long)attr->addr; 10209ed24f4bSMarc Zyngier int irq; 10219ed24f4bSMarc Zyngier 10229ed24f4bSMarc Zyngier if (!irqchip_in_kernel(vcpu->kvm)) 10239ed24f4bSMarc Zyngier return -EINVAL; 10249ed24f4bSMarc Zyngier 102514bda7a9SMarc Zyngier if (!kvm_vcpu_has_pmu(vcpu)) 10269ed24f4bSMarc Zyngier return -ENODEV; 10279ed24f4bSMarc Zyngier 10289ed24f4bSMarc Zyngier if (!kvm_arm_pmu_irq_initialized(vcpu)) 10299ed24f4bSMarc Zyngier return -ENXIO; 10309ed24f4bSMarc Zyngier 10319ed24f4bSMarc Zyngier irq = vcpu->arch.pmu.irq_num; 10329ed24f4bSMarc Zyngier return put_user(irq, uaddr); 10339ed24f4bSMarc Zyngier } 10349ed24f4bSMarc Zyngier } 10359ed24f4bSMarc Zyngier 10369ed24f4bSMarc Zyngier return -ENXIO; 10379ed24f4bSMarc Zyngier } 10389ed24f4bSMarc Zyngier 10399ed24f4bSMarc Zyngier int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) 10409ed24f4bSMarc Zyngier { 10419ed24f4bSMarc Zyngier switch (attr->attr) { 10429ed24f4bSMarc Zyngier case KVM_ARM_VCPU_PMU_V3_IRQ: 10439ed24f4bSMarc Zyngier case KVM_ARM_VCPU_PMU_V3_INIT: 1044d7eec236SMarc Zyngier case KVM_ARM_VCPU_PMU_V3_FILTER: 104577da4303SMarc Zyngier if (kvm_vcpu_has_pmu(vcpu)) 10469ed24f4bSMarc Zyngier return 0; 10479ed24f4bSMarc Zyngier } 10489ed24f4bSMarc Zyngier 10499ed24f4bSMarc Zyngier return -ENXIO; 10509ed24f4bSMarc Zyngier } 1051