Skip to content

Commit 06fc453

Browse files
clementlegeravpatel
authored andcommitted
lib: sbi: Add SSE support for PMU events
Add SSE callbacks registration to PMU driver in order to disable interrupt delegation for PMU interrupts. When interrupts are undelegated send the PMU SSE event upon LCOFIP IRQ. Signed-off-by: Clément Léger <cleger@rivosinc.com> Reviewed-by: Anup Patel <anup@brainfault.org>
1 parent 09ad214 commit 06fc453

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

include/sbi/sbi_pmu.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define __SBI_PMU_H__
1212

1313
#include <sbi/sbi_types.h>
14+
#include <sbi/sbi_trap.h>
1415

1516
struct sbi_scratch;
1617

@@ -150,4 +151,6 @@ int sbi_pmu_ctr_cfg_match(unsigned long cidx_base, unsigned long cidx_mask,
150151

151152
int sbi_pmu_ctr_incr_fw(enum sbi_pmu_fw_event_code_id fw_id);
152153

154+
void sbi_pmu_ovf_irq();
155+
153156
#endif

lib/sbi/sbi_pmu.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <sbi/sbi_pmu.h>
1818
#include <sbi/sbi_scratch.h>
1919
#include <sbi/sbi_string.h>
20+
#include <sbi/sbi_sse.h>
2021

2122
/** Information about hardware counters */
2223
struct sbi_pmu_hw_event {
@@ -62,6 +63,8 @@ struct sbi_pmu_hart_state {
6263
uint32_t active_events[SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX];
6364
/* Bitmap of firmware counters started */
6465
unsigned long fw_counters_started;
66+
/* if true, SSE is enabled */
67+
bool sse_enabled;
6568
/*
6669
* Counter values for SBI firmware events and event codes
6770
* for platform firmware events. Both are mutually exclusive
@@ -300,6 +303,16 @@ int sbi_pmu_add_raw_event_counter_map(uint64_t select, uint64_t select_mask, u32
300303
SBI_PMU_EVENT_RAW_IDX, cmap, select, select_mask);
301304
}
302305

306+
void sbi_pmu_ovf_irq()
307+
{
308+
/*
309+
* We need to disable LCOFIP before returning to S-mode or we will loop
310+
* on LCOFIP being triggered
311+
*/
312+
csr_clear(CSR_MIE, MIP_LCOFIP);
313+
sbi_sse_inject_event(SBI_SSE_EVENT_LOCAL_PMU);
314+
}
315+
303316
static int pmu_ctr_enable_irq_hw(int ctr_idx)
304317
{
305318
unsigned long mhpmevent_csr;
@@ -575,6 +588,10 @@ int sbi_pmu_ctr_stop(unsigned long cbase, unsigned long cmask,
575588
}
576589
}
577590

591+
/* Clear MIP_LCOFIP to avoid spurious interrupts */
592+
if (phs->sse_enabled)
593+
csr_clear(CSR_MIP, MIP_LCOFIP);
594+
578595
return ret;
579596
}
580597

@@ -962,6 +979,7 @@ static void pmu_reset_event_map(struct sbi_pmu_hart_state *phs)
962979
for (j = 0; j < SBI_PMU_FW_CTR_MAX; j++)
963980
phs->fw_counters_data[j] = 0;
964981
phs->fw_counters_started = 0;
982+
phs->sse_enabled = 0;
965983
}
966984

967985
const struct sbi_pmu_device *sbi_pmu_get_device(void)
@@ -993,6 +1011,37 @@ void sbi_pmu_exit(struct sbi_scratch *scratch)
9931011
pmu_reset_event_map(phs);
9941012
}
9951013

1014+
static void pmu_sse_enable(uint32_t event_id)
1015+
{
1016+
struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
1017+
1018+
phs->sse_enabled = true;
1019+
csr_clear(CSR_MIDELEG, sbi_pmu_irq_bit());
1020+
csr_clear(CSR_MIP, MIP_LCOFIP);
1021+
csr_set(CSR_MIE, MIP_LCOFIP);
1022+
}
1023+
1024+
static void pmu_sse_disable(uint32_t event_id)
1025+
{
1026+
struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
1027+
1028+
csr_clear(CSR_MIE, MIP_LCOFIP);
1029+
csr_clear(CSR_MIP, MIP_LCOFIP);
1030+
csr_set(CSR_MIDELEG, sbi_pmu_irq_bit());
1031+
phs->sse_enabled = false;
1032+
}
1033+
1034+
static void pmu_sse_complete(uint32_t event_id)
1035+
{
1036+
csr_set(CSR_MIE, MIP_LCOFIP);
1037+
}
1038+
1039+
static const struct sbi_sse_cb_ops pmu_sse_cb_ops = {
1040+
.enable_cb = pmu_sse_enable,
1041+
.disable_cb = pmu_sse_disable,
1042+
.complete_cb = pmu_sse_complete,
1043+
};
1044+
9961045
int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot)
9971046
{
9981047
int hpm_count = sbi_fls(sbi_hart_mhpm_mask(scratch));
@@ -1032,6 +1081,8 @@ int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot)
10321081
total_ctrs = num_hw_ctrs + SBI_PMU_FW_CTR_MAX;
10331082
}
10341083

1084+
sbi_sse_set_cb_ops(SBI_SSE_EVENT_LOCAL_PMU, &pmu_sse_cb_ops);
1085+
10351086
phs = pmu_get_hart_state_ptr(scratch);
10361087
if (!phs) {
10371088
phs = sbi_zalloc(sizeof(*phs));

lib/sbi/sbi_trap.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ static int sbi_trap_nonaia_irq(unsigned long irq)
223223
case IRQ_M_SOFT:
224224
sbi_ipi_process();
225225
break;
226+
case IRQ_PMU_OVF:
227+
sbi_pmu_ovf_irq();
228+
break;
226229
case IRQ_M_EXT:
227230
return sbi_irqchip_process();
228231
default:
@@ -246,6 +249,9 @@ static int sbi_trap_aia_irq(void)
246249
case IRQ_M_SOFT:
247250
sbi_ipi_process();
248251
break;
252+
case IRQ_PMU_OVF:
253+
sbi_pmu_ovf_irq();
254+
break;
249255
case IRQ_M_EXT:
250256
rc = sbi_irqchip_process();
251257
if (rc)

0 commit comments

Comments
 (0)