Commit 7dda24ba authored by Atish Patra's avatar Atish Patra Committed by Anup Patel

drivers/perf: riscv: Read upper bits of a firmware counter

SBI v2.0 introduced a explicit function to read the upper 32 bits
for any firmware counter width that is longer than 32bits.
This is only applicable for RV32 where firmware counter can be
64 bit.
Reviewed-by: default avatarAndrew Jones <ajones@ventanamicro.com>
Acked-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
Reviewed-by: default avatarConor Dooley <conor.dooley@microchip.com>
Reviewed-by: default avatarAnup Patel <anup@brainfault.org>
Signed-off-by: default avatarAtish Patra <atishp@rivosinc.com>
Link: https://lore.kernel.org/r/20240420151741.962500-4-atishp@rivosinc.comSigned-off-by: default avatarAnup Patel <anup@brainfault.org>
parent 5d4acb7f
......@@ -57,6 +57,8 @@ asm volatile(ALTERNATIVE( \
PMU_FORMAT_ATTR(event, "config:0-47");
PMU_FORMAT_ATTR(firmware, "config:63");
static bool sbi_v2_available;
static struct attribute *riscv_arch_formats_attr[] = {
&format_attr_event.attr,
&format_attr_firmware.attr,
......@@ -511,19 +513,29 @@ static u64 pmu_sbi_ctr_read(struct perf_event *event)
struct hw_perf_event *hwc = &event->hw;
int idx = hwc->idx;
struct sbiret ret;
union sbi_pmu_ctr_info info;
u64 val = 0;
union sbi_pmu_ctr_info info = pmu_ctr_list[idx];
if (pmu_sbi_is_fw_event(event)) {
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ,
hwc->idx, 0, 0, 0, 0, 0);
if (!ret.error)
val = ret.value;
if (ret.error)
return 0;
val = ret.value;
if (IS_ENABLED(CONFIG_32BIT) && sbi_v2_available && info.width >= 32) {
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ_HI,
hwc->idx, 0, 0, 0, 0, 0);
if (!ret.error)
val |= ((u64)ret.value << 32);
else
WARN_ONCE(1, "Unable to read upper 32 bits of firmware counter error: %ld\n",
ret.error);
}
} else {
info = pmu_ctr_list[idx];
val = riscv_pmu_ctr_read_csr(info.csr);
if (IS_ENABLED(CONFIG_32BIT))
val = ((u64)riscv_pmu_ctr_read_csr(info.csr + 0x80)) << 31 | val;
val |= ((u64)riscv_pmu_ctr_read_csr(info.csr + 0x80)) << 32;
}
return val;
......@@ -1135,6 +1147,9 @@ static int __init pmu_sbi_devinit(void)
return 0;
}
if (sbi_spec_version >= sbi_mk_version(2, 0))
sbi_v2_available = true;
ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_RISCV_STARTING,
"perf/riscv/pmu:starting",
pmu_sbi_starting_cpu, pmu_sbi_dying_cpu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment