diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h index b0f08c87676..5d9ac35eebc 100644 --- a/include/sbi/riscv_encoding.h +++ b/include/sbi/riscv_encoding.h @@ -210,9 +210,11 @@ #if __riscv_xlen > 32 #define ENVCFG_STCE (_ULL(1) << 63) #define ENVCFG_PBMTE (_ULL(1) << 62) +#define ENVCFG_HPMDE (_ULL(1) << 61) #else #define ENVCFGH_STCE (_UL(1) << 31) #define ENVCFGH_PBMTE (_UL(1) << 30) +#define ENVCFGH_HPMDE (_UL(1) << 29) #endif #define ENVCFG_CBZE (_UL(1) << 7) #define ENVCFG_CBCFE (_UL(1) << 6) diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h index 95b40e75933..3c917ee1923 100644 --- a/include/sbi/sbi_hart.h +++ b/include/sbi/sbi_hart.h @@ -36,7 +36,8 @@ enum sbi_hart_extensions { SBI_HART_EXT_SMSTATEEN, /** HART has Sstc extension */ SBI_HART_EXT_SSTC, - + /** HART has Sscountd extension */ + SBI_HART_EXT_SSCOUNTD, /** Maximum index of Hart extension */ SBI_HART_EXT_MAX, }; diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index 5447c523987..16972776371 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -446,6 +446,9 @@ static inline char *sbi_hart_extension_id2string(int ext) case SBI_HART_EXT_SMSTATEEN: estr = "smstateen"; break; + case SBI_HART_EXT_SSCOUNTD: + estr = "sscdeleg"; + break; default: break; } @@ -553,7 +556,8 @@ static int hart_detect_features(struct sbi_scratch *scratch) struct sbi_trap_info trap = {0}; struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); - unsigned long val, oldval; + unsigned long val, oldval, menvcfg_val; + bool sscountd_detected = 0; int rc; /* If hart features already detected then do nothing */ @@ -660,9 +664,39 @@ static int hart_detect_features(struct sbi_scratch *scratch) if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) { /* Detect if hart supports sscofpmf */ csr_read_allowed(CSR_SCOUNTOVF, (unsigned long)&trap); - if (!trap.cause) + menvcfg_val = csr_read(CSR_MENVCFG); + if (!trap.cause) { __sbi_hart_update_extension(hfeatures, SBI_HART_EXT_SSCOFPMF, true); + + /* Detect if hart support sscountd */ +#if __riscv_xlen > 32 + /* + * Set menvcfg.HPMDE == 1 for RV64 or RV128 + * + * If Svpbmt extension is not available then menvcfg.menvcfg.HPMDE + * will be read-only zero. + */ + menvcfg_val |= ENVCFG_HPMDE; + csr_write(CSR_MENVCFG, menvcfg_val); + menvcfg_val = csr_read(CSR_MENVCFG); + sscountd_detected = (menvcfg_val & ENVCFG_HPMDE) != 0; +#else + /* + * Set menvcfg.ENVCFGH_HPMDE == 1 for RV32 + * If Scountd extension is not available then menvcfg.ENVCFGH_HPMDE + * will be read-only zero + */ + menvcfg_val |= ENVCFGH_HPMDE; + csr_write(CSR_MENVCFGH, menvcfg_val); + menvcfg_val = csr_read(CSR_MENVCFGH); + sscountd_detected = (menvcfg_val & ENVCFGH_HPMDE) != 0; +#endif + if (sscountd_detected != 0) { + __sbi_hart_update_extension(hfeatures, + SBI_HART_EXT_SSCOUNTD, true); + } + } } /* Detect if hart supports time CSR */