From ad40f1769bbd1e4893106b37295fe6dfef77f102 Mon Sep 17 00:00:00 2001 From: Chen Pei Date: Thu, 22 Aug 2024 20:11:55 +0800 Subject: [PATCH] xuantie: pmu: Support cycles&instructions overflow interrupt The Sscofpmf spec does not define overflow interrupts for cycles & instructions [1]. But this is indispensable in performance profiling. Xuantie added registers mhpmevent0 and mhpmevent2, with addresses 0x7E0 and 0x7E1 respectively, which are used to configure cycles & instructions. At the same time, mxstatus[8] is newly defined as ofint to control whether the cycles and instructions events of HPCP can generate interrupt 13 (lcofip). When it is 1, an interrupt can be generated, and when it is 0, an interrupt cannot be generated. This patch is used to support the above functions. [1] https://github.com/riscvarchive/riscv-count-overflow/issues/5 Signed-off-by: Chen Pei --- include/sbi/riscv_encoding.h | 2 ++ lib/sbi/riscv_asm.c | 4 ++++ lib/sbi/sbi_pmu.c | 27 +++++++++++++++++++++------ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h index 0996d64..cdd27f1 100644 --- a/include/sbi/riscv_encoding.h +++ b/include/sbi/riscv_encoding.h @@ -605,6 +605,8 @@ #define CSR_MCOUNTINHIBIT 0x320 #define CSR_MCYCLECFG 0x321 #define CSR_MINSTRETCFG 0x322 +#define CSR_MHPMEVENT0 0x7E0 +#define CSR_MHPMEVENT2 0x7E1 #define CSR_MHPMEVENT3 0x323 #define CSR_MHPMEVENT4 0x324 #define CSR_MHPMEVENT5 0x325 diff --git a/lib/sbi/riscv_asm.c b/lib/sbi/riscv_asm.c index 05b8c7c..0e2fb6c 100644 --- a/lib/sbi/riscv_asm.c +++ b/lib/sbi/riscv_asm.c @@ -130,6 +130,8 @@ unsigned long csr_read_num(int csr_num) switchcase_csr_read(CSR_MCOUNTINHIBIT, ret) switchcase_csr_read(CSR_MCYCLECFG, ret) switchcase_csr_read(CSR_MINSTRETCFG, ret) + switchcase_csr_read(CSR_MHPMEVENT0, ret) + switchcase_csr_read(CSR_MHPMEVENT2, ret) switchcase_csr_read(CSR_MHPMEVENT3, ret) switchcase_csr_read_4(CSR_MHPMEVENT4, ret) switchcase_csr_read_8(CSR_MHPMEVENT8, ret) @@ -224,6 +226,8 @@ void csr_write_num(int csr_num, unsigned long val) switchcase_csr_write(CSR_MCOUNTINHIBIT, val) switchcase_csr_write(CSR_MCYCLECFG, val) switchcase_csr_write(CSR_MINSTRETCFG, val) + switchcase_csr_write(CSR_MHPMEVENT0, val) + switchcase_csr_write(CSR_MHPMEVENT2, 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_pmu.c b/lib/sbi/sbi_pmu.c index f4c8fc4..e38fb64 100644 --- a/lib/sbi/sbi_pmu.c +++ b/lib/sbi/sbi_pmu.c @@ -304,14 +304,19 @@ static int pmu_ctr_enable_irq_hw(int ctr_idx) unsigned long mip_val; unsigned long of_mask; - if (ctr_idx < 3 || ctr_idx >= SBI_PMU_HW_CTR_MAX) + if (ctr_idx >= SBI_PMU_HW_CTR_MAX) return SBI_EFAIL; #if __riscv_xlen == 32 mhpmevent_csr = CSR_MHPMEVENT3H + ctr_idx - 3; of_mask = (uint32_t)~MHPMEVENTH_OF; #else - mhpmevent_csr = CSR_MHPMEVENT3 + ctr_idx - 3; + if (ctr_idx == 0) + mhpmevent_csr = CSR_MHPMEVENT0; + else if (ctr_idx == 2) + mhpmevent_csr = CSR_MHPMEVENT2; + else + mhpmevent_csr = CSR_MHPMEVENT3 + ctr_idx - 3; of_mask = ~MHPMEVENT_OF; #endif @@ -514,7 +519,7 @@ static int pmu_ctr_stop_fw(struct sbi_pmu_hart_state *phs, static int pmu_reset_hw_mhpmevent(int ctr_idx) { - if (ctr_idx < 3 || ctr_idx >= SBI_PMU_HW_CTR_MAX) + if (ctr_idx >= SBI_PMU_HW_CTR_MAX) return SBI_EFAIL; #if __riscv_xlen == 32 csr_write_num(CSR_MHPMEVENT3 + ctr_idx - 3, 0); @@ -522,7 +527,12 @@ static int pmu_reset_hw_mhpmevent(int ctr_idx) SBI_HART_EXT_SSCOFPMF)) csr_write_num(CSR_MHPMEVENT3H + ctr_idx - 3, 0); #else - csr_write_num(CSR_MHPMEVENT3 + ctr_idx - 3, 0); + if (ctr_idx == 0) + csr_write_num(CSR_MHPMEVENT0, 0); + else if (ctr_idx == 2) + csr_write_num(CSR_MHPMEVENT2, 0); + else + csr_write_num(CSR_MHPMEVENT3 + ctr_idx - 3, 0); #endif return 0; @@ -584,7 +594,7 @@ static int pmu_update_hw_mhpmevent(struct sbi_pmu_hw_event *hw_evt, int ctr_idx, /* Get the final mhpmevent value to be written from platform */ mhpmevent_val = sbi_platform_pmu_xlate_to_mhpmevent(plat, eindex, data); - if (!mhpmevent_val || ctr_idx < 3 || ctr_idx >= SBI_PMU_HW_CTR_MAX) + if (!mhpmevent_val || ctr_idx >= SBI_PMU_HW_CTR_MAX) return SBI_EFAIL; /** @@ -607,7 +617,12 @@ static int pmu_update_hw_mhpmevent(struct sbi_pmu_hw_event *hw_evt, int ctr_idx, csr_write_num(CSR_MHPMEVENT3H + ctr_idx - 3, mhpmevent_val >> BITS_PER_LONG); #else - csr_write_num(CSR_MHPMEVENT3 + ctr_idx - 3, mhpmevent_val); + if (ctr_idx == 0) + csr_write_num(CSR_MHPMEVENT0, mhpmevent_val); + else if (ctr_idx == 2) + csr_write_num(CSR_MHPMEVENT2, mhpmevent_val); + else + csr_write_num(CSR_MHPMEVENT3 + ctr_idx - 3, mhpmevent_val); #endif return 0;