#include <sbi/sbi_pmu.h>
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_string.h>
+#include <sbi/sbi_sse.h>
/** Information about hardware counters */
struct sbi_pmu_hw_event {
uint32_t active_events[SBI_PMU_HW_CTR_MAX + SBI_PMU_FW_CTR_MAX];
/* Bitmap of firmware counters started */
unsigned long fw_counters_started;
+ /* if true, SSE is enabled */
+ bool sse_enabled;
/*
* Counter values for SBI firmware events and event codes
* for platform firmware events. Both are mutually exclusive
SBI_PMU_EVENT_RAW_IDX, cmap, select, select_mask);
}
+void sbi_pmu_ovf_irq()
+{
+ /*
+ * We need to disable LCOFIP before returning to S-mode or we will loop
+ * on LCOFIP being triggered
+ */
+ csr_clear(CSR_MIE, MIP_LCOFIP);
+ sbi_sse_inject_event(SBI_SSE_EVENT_LOCAL_PMU);
+}
+
static int pmu_ctr_enable_irq_hw(int ctr_idx)
{
unsigned long mhpmevent_csr;
}
}
+ /* Clear MIP_LCOFIP to avoid spurious interrupts */
+ if (phs->sse_enabled)
+ csr_clear(CSR_MIP, MIP_LCOFIP);
+
return ret;
}
for (j = 0; j < SBI_PMU_FW_CTR_MAX; j++)
phs->fw_counters_data[j] = 0;
phs->fw_counters_started = 0;
+ phs->sse_enabled = 0;
}
const struct sbi_pmu_device *sbi_pmu_get_device(void)
pmu_reset_event_map(phs);
}
+static void pmu_sse_enable(uint32_t event_id)
+{
+ struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
+
+ phs->sse_enabled = true;
+ csr_clear(CSR_MIDELEG, sbi_pmu_irq_bit());
+ csr_clear(CSR_MIP, MIP_LCOFIP);
+ csr_set(CSR_MIE, MIP_LCOFIP);
+}
+
+static void pmu_sse_disable(uint32_t event_id)
+{
+ struct sbi_pmu_hart_state *phs = pmu_thishart_state_ptr();
+
+ csr_clear(CSR_MIE, MIP_LCOFIP);
+ csr_clear(CSR_MIP, MIP_LCOFIP);
+ csr_set(CSR_MIDELEG, sbi_pmu_irq_bit());
+ phs->sse_enabled = false;
+}
+
+static void pmu_sse_complete(uint32_t event_id)
+{
+ csr_set(CSR_MIE, MIP_LCOFIP);
+}
+
+static const struct sbi_sse_cb_ops pmu_sse_cb_ops = {
+ .enable_cb = pmu_sse_enable,
+ .disable_cb = pmu_sse_disable,
+ .complete_cb = pmu_sse_complete,
+};
+
int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot)
{
int hpm_count = sbi_fls(sbi_hart_mhpm_mask(scratch));
total_ctrs = num_hw_ctrs + SBI_PMU_FW_CTR_MAX;
}
+ sbi_sse_set_cb_ops(SBI_SSE_EVENT_LOCAL_PMU, &pmu_sse_cb_ops);
+
phs = pmu_get_hart_state_ptr(scratch);
if (!phs) {
phs = sbi_zalloc(sizeof(*phs));