From c104c60912a4ed26093f00a9675ad0286e8dcd29 Mon Sep 17 00:00:00 2001 From: Kaiwen Xue Date: Thu, 20 Jul 2023 14:07:02 -0700 Subject: lib: sbi: Add support for smcntrpmf This adds the support for ISA extension smcntrpmf. When some inhibit flags are set by a lower privilege mode for new CSRs added by smcntrpmf, OpenSBI sets the appropriate values correspondingly. Signed-off-by: Kaiwen Xue Signed-off-by: Kaiwen Xue Reviewed-by: Anup Patel Reviewed-by: Atish Patra --- lib/sbi/riscv_asm.c | 12 ++++++++++++ lib/sbi/sbi_hart.c | 11 +++++++++++ lib/sbi/sbi_pmu.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c index 881dea3e..05b8c7ce 100644 --- a/lib/sbi/riscv_asm.c +++ b/lib/sbi/riscv_asm.c @@ -128,6 +128,8 @@ unsigned long csr_read_num(int csr_num) switchcase_csr_read_8(CSR_MHPMCOUNTER8, ret) switchcase_csr_read_16(CSR_MHPMCOUNTER16, ret) switchcase_csr_read(CSR_MCOUNTINHIBIT, ret) + switchcase_csr_read(CSR_MCYCLECFG, ret) + switchcase_csr_read(CSR_MINSTRETCFG, ret) switchcase_csr_read(CSR_MHPMEVENT3, ret) switchcase_csr_read_4(CSR_MHPMEVENT4, ret) switchcase_csr_read_8(CSR_MHPMEVENT8, ret) @@ -139,6 +141,12 @@ unsigned long csr_read_num(int csr_num) switchcase_csr_read_4(CSR_MHPMCOUNTER4H, ret) switchcase_csr_read_8(CSR_MHPMCOUNTER8H, ret) switchcase_csr_read_16(CSR_MHPMCOUNTER16H, ret) + /** + * The CSR range M[CYCLE, INSTRET]CFGH are available only if smcntrpmf + * extension is present. The caller must ensure that. + */ + switchcase_csr_read(CSR_MCYCLECFGH, ret) + switchcase_csr_read(CSR_MINSTRETCFGH, ret) /** * The CSR range MHPMEVENT[3-16]H are available only if sscofpmf * extension is present. The caller must ensure that. @@ -206,12 +214,16 @@ void csr_write_num(int csr_num, unsigned long val) switchcase_csr_write_4(CSR_MHPMCOUNTER4H, val) switchcase_csr_write_8(CSR_MHPMCOUNTER8H, val) switchcase_csr_write_16(CSR_MHPMCOUNTER16H, val) + switchcase_csr_write(CSR_MCYCLECFGH, val) + switchcase_csr_write(CSR_MINSTRETCFGH, val) switchcase_csr_write(CSR_MHPMEVENT3H, val) switchcase_csr_write_4(CSR_MHPMEVENT4H, val) switchcase_csr_write_8(CSR_MHPMEVENT8H, val) switchcase_csr_write_16(CSR_MHPMEVENT16H, val) #endif switchcase_csr_write(CSR_MCOUNTINHIBIT, val) + switchcase_csr_write(CSR_MCYCLECFG, val) + switchcase_csr_write(CSR_MINSTRETCFG, val) switchcase_csr_write(CSR_MHPMEVENT3, val) switchcase_csr_write_4(CSR_MHPMEVENT4, val) switchcase_csr_write_8(CSR_MHPMEVENT8, val) diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index 252f33d8..be795f56 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -606,6 +606,9 @@ static inline char *sbi_hart_extension_id2string(int ext) case SBI_HART_EXT_SMEPMP: estr = "smepmp"; break; + case SBI_HART_EXT_SMCNTRPMF: + estr = "smcntrpmf"; + break; default: break; } @@ -872,6 +875,14 @@ __pmp_skip: SBI_HART_EXT_SMSTATEEN, true); } + /* Detect if hart supports smcntrpmf */ + if (hfeatures->priv_version >= SBI_HART_PRIV_VER_1_12) { + csr_read_allowed(CSR_MCYCLECFG, (unsigned long)&trap); + if (!trap.cause) + __sbi_hart_update_extension(hfeatures, + SBI_HART_EXT_SMCNTRPMF, true); + } + /* Let platform populate extensions */ rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(), hfeatures); diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c index adb9f187..e8bed49f 100644 --- a/lib/sbi/sbi_pmu.c +++ b/lib/sbi/sbi_pmu.c @@ -608,6 +608,44 @@ static int pmu_update_hw_mhpmevent(struct sbi_pmu_hw_event *hw_evt, int ctr_idx, return 0; } +static int pmu_fixed_ctr_update_inhibit_bits(int fixed_ctr, unsigned long flags) +{ + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); + uint64_t cfg_val = 0, cfg_csr_no; +#if __riscv_xlen == 32 + uint64_t cfgh_csr_no; +#endif + if (!sbi_hart_has_extension(scratch, SBI_HART_EXT_SMCNTRPMF)) + return fixed_ctr; + + switch (fixed_ctr) { + case 0: + cfg_csr_no = CSR_MCYCLECFG; +#if __riscv_xlen == 32 + cfgh_csr_no = CSR_MCYCLECFGH; +#endif + break; + case 2: + cfg_csr_no = CSR_MINSTRETCFG; +#if __riscv_xlen == 32 + cfgh_csr_no = CSR_MINSTRETCFGH; +#endif + break; + default: + return SBI_EFAIL; + } + + cfg_val |= MHPMEVENT_MINH; + pmu_update_inhibit_flags(flags, &cfg_val); +#if __riscv_xlen == 32 + csr_write_num(cfg_csr_no, cfg_val & 0xFFFFFFFF); + csr_write_num(cfgh_csr_no, cfg_val >> BITS_PER_LONG); +#else + csr_write_num(cfg_csr_no, cfg_val); +#endif + return fixed_ctr; +} + static int pmu_ctr_find_fixed_hw(unsigned long evt_idx_code) { /* Non-programmables counters are enabled always. No need to do lookup */ @@ -640,7 +678,7 @@ static int pmu_ctr_find_hw(struct sbi_pmu_hart_state *phs, fixed_ctr = pmu_ctr_find_fixed_hw(event_idx); if (fixed_ctr >= 0 && !sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCOFPMF)) - return fixed_ctr; + return pmu_fixed_ctr_update_inhibit_bits(fixed_ctr, flags); if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_11) mctr_inhbt = csr_read(CSR_MCOUNTINHIBIT); @@ -683,7 +721,7 @@ static int pmu_ctr_find_hw(struct sbi_pmu_hart_state *phs, * Return the fixed counter as they are mandatory anyways. */ if (fixed_ctr >= 0) - return fixed_ctr; + return pmu_fixed_ctr_update_inhibit_bits(fixed_ctr, flags); else return SBI_EFAIL; } -- cgit v1.3.1