diff options
author | Yao Zi <ziyao@disroot.org> | 2025-05-16 13:33:52 +0000 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2025-05-20 13:25:53 +0530 |
commit | 7e31dc80525f752d97c2c5a97eb4b9583054e8bc (patch) | |
tree | a04b28f15cf9b349459c50509549ca2da6fad906 /lib | |
parent | 2bb76326496440996b44bf20f3ceab127c7f72ae (diff) | |
download | opensbi-7e31dc80525f752d97c2c5a97eb4b9583054e8bc.zip opensbi-7e31dc80525f752d97c2c5a97eb4b9583054e8bc.tar.gz opensbi-7e31dc80525f752d97c2c5a97eb4b9583054e8bc.tar.bz2 |
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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sbi/sbi_hart.c | 35 | ||||
-rw-r--r-- | lib/sbi/sbi_timer.c | 2 |
2 files changed, 29 insertions, 8 deletions
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); |