…lines 1–6 unchanged (6 lines)
7 */
8
9#define pr_fmt(fmt) "riscv-kvm-pmu: " fmt
10#include <linux/errno.h>
11#include <linux/err.h>
12#include <linux/kvm_host.h>
13#include <linux/nospec.h>
14#include <linux/perf/riscv_pmu.h>
15#include <asm/csr.h>
16#include <asm/kvm_vcpu_sbi.h>
17#include <asm/kvm_vcpu_pmu.h>
18#include <asm/sbi.h>
19#include <linux/bitops.h>
…lines 20–84 unchanged (65 lines)
85 pmc->perf_event = NULL;
86 }
87}
88
89static u64 kvm_pmu_get_perf_event_hw_config(u32 sbi_event_code)
90{
91 return hw_event_perf_map[array_index_nospec(sbi_event_code,
92 SBI_PMU_HW_GENERAL_MAX)];
93}
94
95static u64 kvm_pmu_get_perf_event_cache_config(u32 sbi_event_code)
96{
97 u64 config = U64_MAX;
98 unsigned int cache_type, cache_op, cache_result;
…lines 99–216 unchanged (118 lines)
217
218 if (cidx >= kvm_pmu_num_counters(kvpmu) || cidx == 1) {
219 pr_warn("Invalid counter id [%ld]during read\n", cidx);
220 return -EINVAL;
221 }
222
223 cidx = array_index_nospec(cidx, RISCV_KVM_MAX_COUNTERS);
224 pmc = &kvpmu->pmc[cidx];
225
226 if (pmc->cinfo.type != SBI_PMU_CTR_TYPE_FW)
227 return -EINVAL;
228
229 fevent_code = get_event_code(pmc->event_idx);
…lines 230–243 unchanged (14 lines)
244
245 if (cidx >= kvm_pmu_num_counters(kvpmu) || cidx == 1) {
246 pr_warn("Invalid counter id [%ld] during read\n", cidx);
247 return -EINVAL;
248 }
249
250 cidx = array_index_nospec(cidx, RISCV_KVM_MAX_COUNTERS);
251 pmc = &kvpmu->pmc[cidx];
252
253 if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) {
254 fevent_code = get_event_code(pmc->event_idx);
255 pmc->counter_val = kvpmu->fw_event[fevent_code].value;
256 } else if (pmc->perf_event) {
…lines 257–525 unchanged (269 lines)
526
527 if (cidx >= RISCV_KVM_MAX_COUNTERS || cidx == 1) {
528 retdata->err_val = SBI_ERR_INVALID_PARAM;
529 return 0;
530 }
531
532 cidx = array_index_nospec(cidx, RISCV_KVM_MAX_COUNTERS);
533 retdata->out_val = kvpmu->pmc[cidx].cinfo.value;
534
535 return 0;
536}
537
538int kvm_riscv_vcpu_pmu_ctr_start(struct kvm_vcpu *vcpu, unsigned long ctr_base,
…lines 539–560 unchanged (22 lines)
561 sbiret = SBI_ERR_FAILURE;
562 goto out;
563 }
564 }
565 /* Start the counters that have been configured and requested by the guest */
566 for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
567 pmc_index = array_index_nospec(i + ctr_base,
568 RISCV_KVM_MAX_COUNTERS);
569 if (!test_bit(pmc_index, kvpmu->pmc_in_use))
570 continue;
571 /* The guest started the counter again. Reset the overflow status */
572 clear_bit(pmc_index, kvpmu->pmc_overflown);
573 pmc = &kvpmu->pmc[pmc_index];
574 if (flags & SBI_PMU_START_FLAG_SET_INIT_VALUE) {
…lines 575–632 unchanged (58 lines)
633 sbiret = SBI_ERR_NO_SHMEM;
634 goto out;
635 }
636
637 /* Stop the counters that have been configured and requested by the guest */
638 for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
639 pmc_index = array_index_nospec(i + ctr_base,
640 RISCV_KVM_MAX_COUNTERS);
641 if (!test_bit(pmc_index, kvpmu->pmc_in_use))
642 continue;
643 pmc = &kvpmu->pmc[pmc_index];
644 if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) {
645 fevent_code = get_event_code(pmc->event_idx);
646 if (fevent_code >= SBI_PMU_FW_MAX) {
…lines 647–764 unchanged (118 lines)
765 if (ctr_idx < 0) {
766 sbiret = SBI_ERR_NOT_SUPPORTED;
767 goto out;
768 }
769 }
770
771 ctr_idx = array_index_nospec(ctr_idx, RISCV_KVM_MAX_COUNTERS);
772 pmc = &kvpmu->pmc[ctr_idx];
773 pmc->idx = ctr_idx;
774
775 if (is_fevent) {
776 if (flags & SBI_PMU_CFG_FLAG_AUTO_START)
777 kvpmu->fw_event[event_code].started = true;
…lines 778–912 unchanged (135 lines)