Skip to content

Commit 08fb07d

Browse files
atishp04avpatel
authored andcommitted
RISC-V: KVM: Support 64 bit firmware counters on RV32
The SBI v2.0 introduced a fw_read_hi function to read 64 bit firmware counters for RV32 based systems. Add infrastructure to support that. Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Anup Patel <anup@brainfault.org> Signed-off-by: Atish Patra <atishp@rivosinc.com> Link: https://lore.kernel.org/r/20240420151741.962500-16-atishp@rivosinc.com Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 16b0bde commit 08fb07d

3 files changed

Lines changed: 52 additions & 2 deletions

File tree

arch/riscv/include/asm/kvm_vcpu_pmu.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ static_assert(RISCV_KVM_MAX_COUNTERS <= 64);
2020

2121
struct kvm_fw_event {
2222
/* Current value of the event */
23-
unsigned long value;
23+
u64 value;
2424

2525
/* Event monitoring status */
2626
bool started;
@@ -91,6 +91,8 @@ int kvm_riscv_vcpu_pmu_ctr_cfg_match(struct kvm_vcpu *vcpu, unsigned long ctr_ba
9191
struct kvm_vcpu_sbi_return *retdata);
9292
int kvm_riscv_vcpu_pmu_ctr_read(struct kvm_vcpu *vcpu, unsigned long cidx,
9393
struct kvm_vcpu_sbi_return *retdata);
94+
int kvm_riscv_vcpu_pmu_fw_ctr_read_hi(struct kvm_vcpu *vcpu, unsigned long cidx,
95+
struct kvm_vcpu_sbi_return *retdata);
9496
void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu);
9597
int kvm_riscv_vcpu_pmu_snapshot_set_shmem(struct kvm_vcpu *vcpu, unsigned long saddr_low,
9698
unsigned long saddr_high, unsigned long flags,

arch/riscv/kvm/vcpu_pmu.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,36 @@ static int pmu_get_pmc_index(struct kvm_pmu *pmu, unsigned long eidx,
197197
return kvm_pmu_get_programmable_pmc_index(pmu, eidx, cbase, cmask);
198198
}
199199

200+
static int pmu_fw_ctr_read_hi(struct kvm_vcpu *vcpu, unsigned long cidx,
201+
unsigned long *out_val)
202+
{
203+
struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu);
204+
struct kvm_pmc *pmc;
205+
int fevent_code;
206+
207+
if (!IS_ENABLED(CONFIG_32BIT)) {
208+
pr_warn("%s: should be invoked for only RV32\n", __func__);
209+
return -EINVAL;
210+
}
211+
212+
if (cidx >= kvm_pmu_num_counters(kvpmu) || cidx == 1) {
213+
pr_warn("Invalid counter id [%ld]during read\n", cidx);
214+
return -EINVAL;
215+
}
216+
217+
pmc = &kvpmu->pmc[cidx];
218+
219+
if (pmc->cinfo.type != SBI_PMU_CTR_TYPE_FW)
220+
return -EINVAL;
221+
222+
fevent_code = get_event_code(pmc->event_idx);
223+
pmc->counter_val = kvpmu->fw_event[fevent_code].value;
224+
225+
*out_val = pmc->counter_val >> 32;
226+
227+
return 0;
228+
}
229+
200230
static int pmu_ctr_read(struct kvm_vcpu *vcpu, unsigned long cidx,
201231
unsigned long *out_val)
202232
{
@@ -705,6 +735,18 @@ int kvm_riscv_vcpu_pmu_ctr_cfg_match(struct kvm_vcpu *vcpu, unsigned long ctr_ba
705735
return 0;
706736
}
707737

738+
int kvm_riscv_vcpu_pmu_fw_ctr_read_hi(struct kvm_vcpu *vcpu, unsigned long cidx,
739+
struct kvm_vcpu_sbi_return *retdata)
740+
{
741+
int ret;
742+
743+
ret = pmu_fw_ctr_read_hi(vcpu, cidx, &retdata->out_val);
744+
if (ret == -EINVAL)
745+
retdata->err_val = SBI_ERR_INVALID_PARAM;
746+
747+
return 0;
748+
}
749+
708750
int kvm_riscv_vcpu_pmu_ctr_read(struct kvm_vcpu *vcpu, unsigned long cidx,
709751
struct kvm_vcpu_sbi_return *retdata)
710752
{
@@ -778,7 +820,7 @@ void kvm_riscv_vcpu_pmu_init(struct kvm_vcpu *vcpu)
778820
pmc->cinfo.csr = CSR_CYCLE + i;
779821
} else {
780822
pmc->cinfo.type = SBI_PMU_CTR_TYPE_FW;
781-
pmc->cinfo.width = BITS_PER_LONG - 1;
823+
pmc->cinfo.width = 63;
782824
}
783825
}
784826

arch/riscv/kvm/vcpu_sbi_pmu.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ static int kvm_sbi_ext_pmu_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
6464
case SBI_EXT_PMU_COUNTER_FW_READ:
6565
ret = kvm_riscv_vcpu_pmu_ctr_read(vcpu, cp->a0, retdata);
6666
break;
67+
case SBI_EXT_PMU_COUNTER_FW_READ_HI:
68+
if (IS_ENABLED(CONFIG_32BIT))
69+
ret = kvm_riscv_vcpu_pmu_fw_ctr_read_hi(vcpu, cp->a0, retdata);
70+
else
71+
retdata->out_val = 0;
72+
break;
6773
case SBI_EXT_PMU_SNAPSHOT_SET_SHMEM:
6874
ret = kvm_riscv_vcpu_pmu_snapshot_set_shmem(vcpu, cp->a0, cp->a1, cp->a2, retdata);
6975
break;

0 commit comments

Comments
 (0)