[PATCH v4 1/2] lib: sbi: hart: Detect existence of cycle and instret CSRs for Zicntr
Yao Zi
ziyao at disroot.org
Fri May 16 06:33:52 PDT 2025
Zicntr extension specifies three read-only CSRs, time, cycle and
instret. It isn't sufficient to report Zicntr is fully supported with
only time CSR detected.
This patch introduces a bitmap to sbi_hart_features to record
availability of these CSRs, which are detected using traps. Zicntr is
reported as present if and only if three CSRs are all available on the
HARTs.
Sites originally depending on SBI_HART_EXT_ZICNTR for detecting
existence of time CSR are switched to detect SBI_HART_CSR_TIME instead.
Suggested-by: Anup Patel <anup at brainfault.org>
Signed-off-by: Yao Zi <ziyao at disroot.org>
---
include/sbi/sbi_hart.h | 10 ++++++++++
lib/sbi/sbi_hart.c | 35 ++++++++++++++++++++++++++++-------
lib/sbi/sbi_timer.c | 2 +-
3 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index bce88c5..dfbe8e4 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -93,6 +93,14 @@ struct sbi_hart_ext_data {
extern const struct sbi_hart_ext_data sbi_hart_ext[];
+/** CSRs should be detected by access and trapping */
+enum sbi_hart_csrs {
+ SBI_HART_CSR_CYCLE = 0,
+ SBI_HART_CSR_TIME,
+ SBI_HART_CSR_INSTRET,
+ SBI_HART_CSR_MAX,
+};
+
/*
* Smepmp enforces access boundaries between M-mode and
* S/U-mode. When it is enabled, the PMPs are programmed
@@ -112,6 +120,7 @@ struct sbi_hart_features {
bool detected;
int priv_version;
unsigned long extensions[BITS_TO_LONGS(SBI_HART_EXT_MAX)];
+ unsigned long csrs[BITS_TO_LONGS(SBI_HART_CSR_MAX)];
unsigned int pmp_count;
unsigned int pmp_addr_bits;
unsigned int pmp_log2gran;
@@ -150,6 +159,7 @@ bool sbi_hart_has_extension(struct sbi_scratch *scratch,
enum sbi_hart_extensions ext);
void sbi_hart_get_extensions_str(struct sbi_scratch *scratch,
char *extension_str, int nestr);
+bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr);
void __attribute__((noreturn)) sbi_hart_hang(void);
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index fc4925b..74ccdd8 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -747,6 +747,20 @@ void sbi_hart_get_extensions_str(struct sbi_scratch *scratch,
sbi_strncpy(extensions_str, "none", nestr);
}
+/**
+ * Check whether a particular CSR is present on the HART
+ *
+ * @param scratch pointer to the HART scratch space
+ * @param csr the CSR number to check
+ */
+bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr)
+{
+ struct sbi_hart_features *hfeatures =
+ sbi_scratch_offset_ptr(scratch, hart_features_offset);
+
+ return __test_bit(csr, hfeatures->csrs);
+}
+
static unsigned long hart_pmp_get_allowed_addr(void)
{
unsigned long val = 0;
@@ -803,7 +817,6 @@ static int hart_detect_features(struct sbi_scratch *scratch)
struct sbi_hart_features *hfeatures =
sbi_scratch_offset_ptr(scratch, hart_features_offset);
unsigned long val, oldval;
- bool has_zicntr = false;
int rc;
/* If hart features already detected then do nothing */
@@ -812,6 +825,7 @@ static int hart_detect_features(struct sbi_scratch *scratch)
/* Clear hart features */
sbi_memset(hfeatures->extensions, 0, sizeof(hfeatures->extensions));
+ sbi_memset(hfeatures->csrs, 0, sizeof(hfeatures->csrs));
hfeatures->pmp_count = 0;
hfeatures->mhpm_mask = 0;
hfeatures->priv_version = SBI_HART_PRIV_VER_UNKNOWN;
@@ -938,9 +952,6 @@ __pmp_skip:
/* Detect if hart supports sscofpmf */
__check_ext_csr(SBI_HART_PRIV_VER_1_11,
CSR_SCOUNTOVF, SBI_HART_EXT_SSCOFPMF);
- /* Detect if hart supports time CSR */
- __check_ext_csr(SBI_HART_PRIV_VER_UNKNOWN,
- CSR_TIME, SBI_HART_EXT_ZICNTR);
/* Detect if hart has AIA local interrupt CSRs */
__check_ext_csr(SBI_HART_PRIV_VER_UNKNOWN,
CSR_MTOPI, SBI_HART_EXT_SMAIA);
@@ -962,8 +973,16 @@ __pmp_skip:
#undef __check_ext_csr
- /* Save trap based detection of Zicntr */
- has_zicntr = sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICNTR);
+#define __check_csr_existence(__csr, __csr_id) \
+ csr_read_allowed(__csr, &trap); \
+ if (!trap.cause) \
+ __set_bit(__csr_id, hfeatures->csrs);
+
+ __check_csr_existence(CSR_CYCLE, SBI_HART_CSR_CYCLE);
+ __check_csr_existence(CSR_TIME, SBI_HART_CSR_TIME);
+ __check_csr_existence(CSR_INSTRET, SBI_HART_CSR_INSTRET);
+
+#undef __check_csr_existence
/* Let platform populate extensions */
rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(),
@@ -973,7 +992,9 @@ __pmp_skip:
/* Zicntr should only be detected using traps */
__sbi_hart_update_extension(hfeatures, SBI_HART_EXT_ZICNTR,
- has_zicntr);
+ sbi_hart_has_csr(scratch, SBI_HART_CSR_CYCLE) &&
+ sbi_hart_has_csr(scratch, SBI_HART_CSR_TIME) &&
+ sbi_hart_has_csr(scratch, SBI_HART_CSR_INSTRET));
/* Extensions implied by other extensions and features */
if (hfeatures->mhpm_mask)
diff --git a/lib/sbi/sbi_timer.c b/lib/sbi/sbi_timer.c
index 998a9a6..4088a59 100644
--- a/lib/sbi/sbi_timer.c
+++ b/lib/sbi/sbi_timer.c
@@ -185,7 +185,7 @@ int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot)
if (!time_delta_off)
return SBI_ENOMEM;
- if (sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICNTR))
+ if (sbi_hart_has_csr(scratch, SBI_HART_CSR_TIME))
get_time_val = get_ticks;
ret = sbi_platform_timer_init(plat);
--
2.49.0
More information about the opensbi
mailing list