Skip to content

Commit e309fd1

Browse files
atishp04avpatel
authored andcommitted
RISC-V: KVM: Implement get event info function
The new get_event_info funciton allows the guest to query the presence of multiple events with single SBI call. Currently, the perf driver in linux guest invokes it for all the standard SBI PMU events. Support the SBI function implementation in KVM as well. Reviewed-by: Anup Patel <[email protected]> Signed-off-by: Atish Patra <[email protected]> Acked-by: Paul Walmsley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Anup Patel <[email protected]>
1 parent 41f4d0c commit e309fd1

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

arch/riscv/include/asm/kvm_vcpu_pmu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu);
9898
int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long saddr_low,
9999
unsigned long saddr_high, unsigned long flags,
100100
struct kvm_vcpu_sbi_return *retdata);
101+
int kvm_riscv_vcpu_pmu_event_info(struct kvm_vcpu *vcpu, unsigned long saddr_low,
102+
unsigned long saddr_high, unsigned long num_events,
103+
unsigned long flags, struct kvm_vcpu_sbi_return *retdata);
101104
void kvm_riscv_vcpu_pmu_deinit(struct kvm_vcpu *vcpu);
102105
void kvm_riscv_vcpu_pmu_reset(struct kvm_vcpu *vcpu);
103106

arch/riscv/kvm/vcpu_pmu.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,65 @@ int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long s
449449
return 0;
450450
}
451451

452+
int kvm_riscv_vcpu_pmu_event_info(struct kvm_vcpu *vcpu, unsigned long saddr_low,
453+
unsigned long saddr_high, unsigned long num_events,
454+
unsigned long flags, struct kvm_vcpu_sbi_return *retdata)
455+
{
456+
struct riscv_pmu_event_info *einfo = NULL;
457+
int shmem_size = num_events * sizeof(*einfo);
458+
gpa_t shmem;
459+
u32 eidx, etype;
460+
u64 econfig;
461+
int ret;
462+
463+
if (flags != 0 || (saddr_low & (SZ_16 - 1) || num_events == 0)) {
464+
ret = SBI_ERR_INVALID_PARAM;
465+
goto out;
466+
}
467+
468+
shmem = saddr_low;
469+
if (saddr_high != 0) {
470+
if (IS_ENABLED(CONFIG_32BIT)) {
471+
shmem |= ((gpa_t)saddr_high << 32);
472+
} else {
473+
ret = SBI_ERR_INVALID_ADDRESS;
474+
goto out;
475+
}
476+
}
477+
478+
einfo = kzalloc(shmem_size, GFP_KERNEL);
479+
if (!einfo)
480+
return -ENOMEM;
481+
482+
ret = kvm_vcpu_read_guest(vcpu, shmem, einfo, shmem_size);
483+
if (ret) {
484+
ret = SBI_ERR_FAILURE;
485+
goto free_mem;
486+
}
487+
488+
for (int i = 0; i < num_events; i++) {
489+
eidx = einfo[i].event_idx;
490+
etype = kvm_pmu_get_perf_event_type(eidx);
491+
econfig = kvm_pmu_get_perf_event_config(eidx, einfo[i].event_data);
492+
ret = riscv_pmu_get_event_info(etype, econfig, NULL);
493+
einfo[i].output = (ret > 0) ? 1 : 0;
494+
}
495+
496+
ret = kvm_vcpu_write_guest(vcpu, shmem, einfo, shmem_size);
497+
if (ret) {
498+
ret = SBI_ERR_INVALID_ADDRESS;
499+
goto free_mem;
500+
}
501+
502+
ret = 0;
503+
free_mem:
504+
kfree(einfo);
505+
out:
506+
retdata->err_val = ret;
507+
508+
return 0;
509+
}
510+
452511
int kvm_riscv_vcpu_pmu_num_ctrs(struct kvm_vcpu *vcpu,
453512
struct kvm_vcpu_sbi_return *retdata)
454513
{

arch/riscv/kvm/vcpu_sbi_pmu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ static int kvm_sbi_ext_pmu_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
7373
case SBI_EXT_PMU_SNAPSHOT_SET_SHMEM:
7474
ret = kvm_riscv_vcpu_pmu_snapshot_set_shmem(vcpu, cp->a0, cp->a1, cp->a2, retdata);
7575
break;
76+
case SBI_EXT_PMU_EVENT_GET_INFO:
77+
ret = kvm_riscv_vcpu_pmu_event_info(vcpu, cp->a0, cp->a1, cp->a2, cp->a3, retdata);
78+
break;
7679
default:
7780
retdata->err_val = SBI_ERR_NOT_SUPPORTED;
7881
}

0 commit comments

Comments
 (0)