diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h index e1256e31..e0070da5 100644 --- a/include/sbi/riscv_encoding.h +++ b/include/sbi/riscv_encoding.h @@ -265,6 +265,10 @@ #define CSR_CYCLE 0xc00 #define CSR_TIME 0xc01 #define CSR_INSTRET 0xc02 + +/* Sscpuutil: CPU active time counter (address TBD, using placeholder) */ +#define CSR_ACTTIME 0xc31 +#define CSR_ACTTIMEH 0xcb1 #define CSR_HPMCOUNTER3 0xc03 #define CSR_HPMCOUNTER4 0xc04 #define CSR_HPMCOUNTER5 0xc05 @@ -612,6 +616,12 @@ #define CSR_MHPMCOUNTER29 0xb1d #define CSR_MHPMCOUNTER30 0xb1e #define CSR_MHPMCOUNTER31 0xb1f + +/* Sscpuutil: M-mode CPU active time counter (address TBD, using placeholder) */ +#define CSR_MACTTIME 0xb31 +#define CSR_MACTTIMEH 0xbb1 +#define CSR_MCPUUTILEN 0x320 +#define CSR_SCPUUTILEN 0x120 #define CSR_MCYCLEH 0xb80 #define CSR_MINSTRETH 0xb82 #define CSR_MHPMCOUNTER3H 0xb83 @@ -827,6 +837,14 @@ #define SMSTATEEN0_HSENVCFG (_ULL(1) << SMSTATEEN0_HSENVCFG_SHIFT) #define SMSTATEEN_STATEN_SHIFT 63 #define SMSTATEEN_STATEN (_ULL(1) << SMSTATEEN_STATEN_SHIFT) +/* Sscpuutil: acttime access control (bit position TBD) */ +#define SMSTATEEN0_CPUUTIL_SHIFT 55 +#define SMSTATEEN0_CPUUTIL (_ULL(1) << SMSTATEEN0_CPUUTIL_SHIFT) + +/* Sscpuutil mcpuutilen enable bits */ +#define CPUUTILEN_CORECYC (1UL << 0) +#define CPUUTILEN_ACTTIME (1UL << 1) +#define CPUUTILEN_ALL (CPUUTILEN_CORECYC | CPUUTILEN_ACTTIME) /* ===== Instruction Encodings ===== */ diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h index dfbe8e4c..8310f756 100644 --- a/include/sbi/sbi_hart.h +++ b/include/sbi/sbi_hart.h @@ -81,6 +81,8 @@ enum sbi_hart_extensions { SBI_HART_EXT_SSCTR, /** HART has Ssstateen extension **/ SBI_HART_EXT_SSSTATEEN, + /** Hart has Sscpuutil extension (CPU utilization) */ + SBI_HART_EXT_SSCPUUTIL, /** Maximum index of Hart extension */ SBI_HART_EXT_MAX, diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index 054a405c..72eb44b1 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -63,8 +63,17 @@ static void mstatus_init(struct sbi_scratch *scratch) csr_write(CSR_MCOUNTEREN, -1); /* All programmable counters will start running at runtime after S-mode request */ - if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_11) - csr_write(CSR_MCOUNTINHIBIT, 0xFFFFFFF8); + if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_11) { + unsigned long inhibit_val = 0xFFFFFFF8; + /* + * When Sscpuutil is available, keep cycle running + * (clear mcountinhibit.CY) so that the frequency ratio + * Dcycle/Dacttime remains valid. + */ + if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCPUUTIL)) + inhibit_val &= ~(1UL << 0); + csr_write(CSR_MCOUNTINHIBIT, inhibit_val); + } /** * The mhpmeventn[h] CSR should be initialized with interrupt disabled @@ -110,12 +119,37 @@ static void mstatus_init(struct sbi_scratch *scratch) else mstateen_val &= ~SMSTATEEN0_CTR; + if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCPUUTIL)) + mstateen_val |= SMSTATEEN0_CPUUTIL; + else + mstateen_val &= ~SMSTATEEN0_CPUUTIL; + csr_write64(CSR_MSTATEEN0, mstateen_val); csr_write64(CSR_MSTATEEN1, SMSTATEEN_STATEN); csr_write64(CSR_MSTATEEN2, SMSTATEEN_STATEN); csr_write64(CSR_MSTATEEN3, SMSTATEEN_STATEN); } + /* + * For platforms with dedicated mcpuutilen (Sscpuutil-style), + * enable both counters for S/U-mode access. + * Directly probe the CSR since extension detection may not + * cover all naming variants (sscpuutil vs sscpuutil). + */ + { + struct sbi_trap_info __trap = {0}; + csr_read_allowed(CSR_MCPUUTILEN, &__trap); + if (!__trap.cause) { + csr_write(CSR_MCPUUTILEN, CPUUTILEN_ALL); + csr_write(CSR_SCPUUTILEN, CPUUTILEN_ALL); + sbi_printf("mcpuutilen/scpuutilen: set to 0x%lx (direct probe)\n", + (unsigned long)CPUUTILEN_ALL); + } else { + sbi_printf("mcpuutilen: CSR not present (cause=%lu)\n", + __trap.cause); + } + } + if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSSTATEEN)) { if (misa_extension('S')) { csr_write(CSR_SSTATEEN0, 0); @@ -715,6 +749,7 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = { __SBI_HART_EXT_DATA(smctr, SBI_HART_EXT_SMCTR), __SBI_HART_EXT_DATA(ssctr, SBI_HART_EXT_SSCTR), __SBI_HART_EXT_DATA(ssstateen, SBI_HART_EXT_SSSTATEEN), + __SBI_HART_EXT_DATA(sscpuutil, SBI_HART_EXT_SSCPUUTIL), }; _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext), @@ -959,6 +994,13 @@ static int hart_detect_features(struct sbi_scratch *scratch) } /* Counter overflow/filtering is not useful without mcounter/inhibit */ + /* Detect if hart supports Sscpuutil (CPU utilization) */ + csr_read_allowed(CSR_MACTTIME, &trap); + sbi_printf("SSCPUUTIL: CSR_MACTTIME(0xb21) probe: trap.cause=%lu\n", + trap.cause); + __check_ext_csr(SBI_HART_PRIV_VER_1_12, + CSR_MACTTIME, SBI_HART_EXT_SSCPUUTIL); + /* Detect if hart supports sscofpmf */ __check_ext_csr(SBI_HART_PRIV_VER_1_11, CSR_SCOUNTOVF, SBI_HART_EXT_SSCOFPMF);