Skip to content

Commit 465dd5e

Browse files
committed
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. Signed-off-by: Atish Patra <[email protected]>
1 parent f902c4e commit 465dd5e

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-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: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,72 @@ int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long s
453453
return 0;
454454
}
455455

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

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)