[RFC 13/14] lib: sbi: Implement firmware counters

Atish Patra atish.patra at wdc.com
Fri Mar 19 22:13:04 GMT 2021


RISC-V SBI v0.3 specification defines a set of firmware events that can
provide additional information about the current firmware context. All
of the firmware event monitoring are enabled now. The firmware
events must be defined as raw perf event with MSB set as specified in the
specification.

Signed-off-by: Atish Patra <atish.patra at wdc.com>
---
 include/sbi/sbi_tlb.h       |  1 +
 lib/sbi/sbi_ecall_replace.c |  2 ++
 lib/sbi/sbi_ipi.c           |  7 +++++++
 lib/sbi/sbi_tlb.c           | 36 ++++++++++++++++++++++++++++++++++++
 lib/sbi/sbi_trap.c          |  9 +++++++++
 5 files changed, 55 insertions(+)

diff --git a/include/sbi/sbi_tlb.h b/include/sbi/sbi_tlb.h
index 48f1962d7dcf..680fcc758072 100644
--- a/include/sbi/sbi_tlb.h
+++ b/include/sbi/sbi_tlb.h
@@ -33,6 +33,7 @@ struct sbi_tlb_info {
 	struct sbi_hartmask smask;
 };
 
+void sbi_tlb_pmu_incr_fw_ctr(struct sbi_tlb_info *data);
 void sbi_tlb_local_hfence_vvma(struct sbi_tlb_info *tinfo);
 void sbi_tlb_local_hfence_gvma(struct sbi_tlb_info *tinfo);
 void sbi_tlb_local_sfence_vma(struct sbi_tlb_info *tinfo);
diff --git a/lib/sbi/sbi_ecall_replace.c b/lib/sbi/sbi_ecall_replace.c
index a7935d97300d..83544bb6e05f 100644
--- a/lib/sbi/sbi_ecall_replace.c
+++ b/lib/sbi/sbi_ecall_replace.c
@@ -14,6 +14,7 @@
 #include <sbi/sbi_error.h>
 #include <sbi/sbi_hart.h>
 #include <sbi/sbi_ipi.h>
+#include <sbi/sbi_pmu.h>
 #include <sbi/sbi_system.h>
 #include <sbi/sbi_timer.h>
 #include <sbi/sbi_tlb.h>
@@ -27,6 +28,7 @@ static int sbi_ecall_time_handler(unsigned long extid, unsigned long funcid,
 	int ret = 0;
 
 	if (funcid == SBI_EXT_TIME_SET_TIMER) {
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_SET_TIMER);
 #if __riscv_xlen == 32
 		sbi_timer_event_start((((u64)regs->a1 << 32) | (u64)regs->a0));
 #else
diff --git a/lib/sbi/sbi_ipi.c b/lib/sbi/sbi_ipi.c
index b50735e4099a..cd998ac7acfa 100644
--- a/lib/sbi/sbi_ipi.c
+++ b/lib/sbi/sbi_ipi.c
@@ -19,6 +19,9 @@
 #include <sbi/sbi_init.h>
 #include <sbi/sbi_ipi.h>
 #include <sbi/sbi_platform.h>
+#include <sbi/sbi_pmu.h>
+#include <sbi/sbi_string.h>
+#include <sbi/sbi_tlb.h>
 
 struct sbi_ipi_data {
 	unsigned long ipi_type;
@@ -61,6 +64,10 @@ static int sbi_ipi_send(struct sbi_scratch *scratch, u32 remote_hartid,
 	 */
 	atomic_raw_set_bit(event, &ipi_data->ipi_type);
 	smp_wmb();
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_IPI_SENT);
+	if (sbi_strncmp(ipi_ops->name, "IPI_TLB", 7))
+		sbi_tlb_pmu_incr_fw_ctr(data);
+
 	sbi_platform_ipi_send(plat, remote_hartid);
 
 	if (ipi_ops->sync)
diff --git a/lib/sbi/sbi_tlb.c b/lib/sbi/sbi_tlb.c
index 73f59e8681e2..36b21a74a713 100644
--- a/lib/sbi/sbi_tlb.c
+++ b/lib/sbi/sbi_tlb.c
@@ -21,6 +21,7 @@
 #include <sbi/sbi_string.h>
 #include <sbi/sbi_console.h>
 #include <sbi/sbi_platform.h>
+#include <sbi/sbi_pmu.h>
 
 static unsigned long tlb_sync_off;
 static unsigned long tlb_fifo_off;
@@ -39,6 +40,8 @@ void sbi_tlb_local_hfence_vvma(struct sbi_tlb_info *tinfo)
 	unsigned long vmid  = tinfo->vmid;
 	unsigned long i, hgatp;
 
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_VVMA_RCVD);
+
 	hgatp = csr_swap(CSR_HGATP,
 			 (vmid << HGATP_VMID_SHIFT) & HGATP_VMID_MASK);
 
@@ -61,6 +64,8 @@ void sbi_tlb_local_hfence_gvma(struct sbi_tlb_info *tinfo)
 	unsigned long size  = tinfo->size;
 	unsigned long i;
 
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_GVMA_RCVD);
+
 	if ((start == 0 && size == 0) || (size == SBI_TLB_FLUSH_ALL)) {
 		__sbi_hfence_gvma_all();
 		return;
@@ -77,6 +82,8 @@ void sbi_tlb_local_sfence_vma(struct sbi_tlb_info *tinfo)
 	unsigned long size  = tinfo->size;
 	unsigned long i;
 
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_SFENCE_VMA_RCVD);
+
 	if ((start == 0 && size == 0) || (size == SBI_TLB_FLUSH_ALL)) {
 		sbi_tlb_flush_all();
 		return;
@@ -98,6 +105,8 @@ void sbi_tlb_local_hfence_vvma_asid(struct sbi_tlb_info *tinfo)
 	unsigned long vmid  = tinfo->vmid;
 	unsigned long i, hgatp;
 
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD);
+
 	hgatp = csr_swap(CSR_HGATP,
 			 (vmid << HGATP_VMID_SHIFT) & HGATP_VMID_MASK);
 
@@ -126,6 +135,8 @@ void sbi_tlb_local_hfence_gvma_vmid(struct sbi_tlb_info *tinfo)
 	unsigned long vmid  = tinfo->vmid;
 	unsigned long i;
 
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_GVMA_VMID_RCVD);
+
 	if (start == 0 && size == 0) {
 		__sbi_hfence_gvma_all();
 		return;
@@ -148,6 +159,8 @@ void sbi_tlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo)
 	unsigned long asid  = tinfo->asid;
 	unsigned long i;
 
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_SFENCE_VMA_ASID_RCVD);
+
 	if (start == 0 && size == 0) {
 		sbi_tlb_flush_all();
 		return;
@@ -172,9 +185,32 @@ void sbi_tlb_local_sfence_vma_asid(struct sbi_tlb_info *tinfo)
 
 void sbi_tlb_local_fence_i(struct sbi_tlb_info *tinfo)
 {
+	sbi_pmu_incr_fw_ctr(SBI_PMU_FW_FENCE_I_RECVD);
+
 	__asm__ __volatile("fence.i");
 }
 
+void sbi_tlb_pmu_incr_fw_ctr(struct sbi_tlb_info *data)
+{
+	if (unlikely(!data))
+		return;
+
+	if (data->local_fn == sbi_tlb_local_fence_i)
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_FENCE_I_SENT);
+	else if (data->local_fn == sbi_tlb_local_sfence_vma)
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_SFENCE_VMA_SENT);
+	else if (data->local_fn == sbi_tlb_local_sfence_vma_asid)
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_SFENCE_VMA_ASID_SENT);
+	else if (data->local_fn == sbi_tlb_local_hfence_gvma)
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_GVMA_SENT);
+	else if (data->local_fn == sbi_tlb_local_hfence_gvma_vmid)
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_GVMA_VMID_SENT);
+	else if (data->local_fn == sbi_tlb_local_hfence_vvma)
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_VVMA_SENT);
+	else if (data->local_fn == sbi_tlb_local_hfence_vvma_asid)
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_HFENCE_VVMA_ASID_SENT);
+}
+
 static void sbi_tlb_entry_process(struct sbi_tlb_info *tinfo)
 {
 	u32 rhartid;
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index b7349d2c914e..3b540ea7f76c 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -16,6 +16,7 @@
 #include <sbi/sbi_illegal_insn.h>
 #include <sbi/sbi_ipi.h>
 #include <sbi/sbi_misaligned_ldst.h>
+#include <sbi/sbi_pmu.h>
 #include <sbi/sbi_scratch.h>
 #include <sbi/sbi_timer.h>
 #include <sbi/sbi_trap.h>
@@ -230,6 +231,7 @@ void sbi_trap_handler(struct sbi_trap_regs *regs)
 			sbi_timer_process();
 			break;
 		case IRQ_M_SOFT:
+			sbi_pmu_incr_fw_ctr(SBI_PMU_FW_IPI_RECVD);
 			sbi_ipi_process();
 			break;
 		default:
@@ -241,14 +243,17 @@ void sbi_trap_handler(struct sbi_trap_regs *regs)
 
 	switch (mcause) {
 	case CAUSE_ILLEGAL_INSTRUCTION:
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_ILLEGAL_INSN);
 		rc  = sbi_illegal_insn_handler(mtval, regs);
 		msg = "illegal instruction handler failed";
 		break;
 	case CAUSE_MISALIGNED_LOAD:
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_MISALIGNED_LOAD);
 		rc = sbi_misaligned_load_handler(mtval, mtval2, mtinst, regs);
 		msg = "misaligned load handler failed";
 		break;
 	case CAUSE_MISALIGNED_STORE:
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_MISALIGNED_STORE);
 		rc  = sbi_misaligned_store_handler(mtval, mtval2, mtinst, regs);
 		msg = "misaligned store handler failed";
 		break;
@@ -257,6 +262,10 @@ void sbi_trap_handler(struct sbi_trap_regs *regs)
 		rc  = sbi_ecall_handler(regs);
 		msg = "ecall handler failed";
 		break;
+	case CAUSE_LOAD_ACCESS:
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_ACCESS_LOAD);
+	case CAUSE_STORE_ACCESS:
+		sbi_pmu_incr_fw_ctr(SBI_PMU_FW_ACCESS_STORE);
 	default:
 		/* If the trap came from S or U mode, redirect it there */
 		trap.epc = regs->mepc;
-- 
2.25.1




More information about the opensbi mailing list