Skip to content

Commit

Permalink
xuantie: pmu: Support cycles&instructions overflow interrupt
Browse files Browse the repository at this point in the history
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] riscvarchive/riscv-count-overflow#5

Signed-off-by: Chen Pei <[email protected]>
  • Loading branch information
cp0613 authored and guoren83 committed Nov 18, 2024
1 parent 66251fb commit ad40f17
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 6 deletions.
2 changes: 2 additions & 0 deletions include/sbi/riscv_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions lib/sbi/riscv_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
27 changes: 21 additions & 6 deletions lib/sbi/sbi_pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -514,15 +519,20 @@ 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);
if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
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;
Expand Down Expand Up @@ -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;

/**
Expand All @@ -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;
Expand Down

0 comments on commit ad40f17

Please sign in to comment.