mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-24 15:31:22 +01:00
lib: sbi: hart: Detect existence of cycle and instret CSRs for Zicntr
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@brainfault.org> Signed-off-by: Yao Zi <ziyao@disroot.org> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20250516133352.36617-3-ziyao@disroot.org Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
@@ -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)
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user