diff options
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 fc4925b5..74ccdd84 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 998a9a67..4088a597 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); |
