In general counter-data is auto-detected but some platforms
may implement counters in a way that breaks this detection.
Implement an abstraction that those platforms can hook into
and override the counter-data.
Signed-off-by: Heiko Stuebner <heiko@...>
include/sbi/sbi_pmu.h | 8 ++++++++
lib/sbi/sbi_hart.c | 7 +++++++
lib/sbi/sbi_pmu.c | 7 +++++++
3 files changed, 22 insertions(+)
@@ -78,6 +78,11 @@ struct sbi_pmu_device {
* Custom function returning the machine-specific irq-bit.
*/
int (*hw_counter_irq_bit)(void);
+
+ /**
+ * Override autodetected counter data.
+ */
+ void (*hw_counter_data)(unsigned int *count, unsigned int *bits);
};
/** Get the PMU platform device */
@@ -95,6 +100,9 @@ void sbi_pmu_exit(struct sbi_scratch *scratch);
/** Return the pmu irq bit depending on extension existence */
int sbi_pmu_irq_bit(void);
+/** Allow non-standard platforms to override probed counter information */
+void sbi_pmu_override_counter_data(unsigned int *count, unsigned int *bits);
+
/**
* Add the hardware event to counter mapping information. This should be called
* from the platform code to update the mapping table.
@@ -632,6 +632,13 @@ __mhpm_skip:
#undef __check_csr_2
#undef __check_csr
+ /**
+ * Allow non-standard implementations to override the detected
+ * values for number of counters and bits.
+ */
+ sbi_pmu_override_counter_data(&hfeatures->mhpm_count,
+ &hfeatures->mhpm_bits);
+
/* Detect if hart supports Priv v1.10 */
val = csr_read_allowed(CSR_MCOUNTEREN, (unsigned long)&trap);
if (!trap.cause)
@@ -852,3 +852,10 @@ int sbi_pmu_init(struct sbi_scratch *scratch, bool cold_boot)
return 0;
}
+
+void sbi_pmu_override_counter_data(unsigned int *count,
+ unsigned int *bits)
+{
+ if (pmu_dev && pmu_dev->hw_counter_data)
+ pmu_dev->hw_counter_data(count, bits);
+}