lib: sbi: Disable interrupt and inhibit counting in M-mode during init
authorAtish Patra <atishp@rivosinc.com>
Fri, 7 Jan 2022 18:54:09 +0000 (10:54 -0800)
committerAnup Patel <anup@brainfault.org>
Fri, 4 Feb 2022 04:40:28 +0000 (10:10 +0530)
Currently, the mhpmevent CSRs are untouched during hart init during
cold/warm boot. Ideally, we should clear out all the bits except
overflow and MINH bit. That is required to disable overflow
interrupt and inhibit counting in M-mode to avoid any spurious
interrupts before perf start.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
lib/sbi/sbi_hart.c

index d9a15d9..0a65175 100644 (file)
@@ -40,6 +40,9 @@ static unsigned long hart_features_offset;
 static void mstatus_init(struct sbi_scratch *scratch)
 {
        unsigned long mstatus_val = 0;
+       int cidx;
+       unsigned int num_mhpm = sbi_hart_mhpm_count(scratch);
+       uint64_t mhpmevent_init_val = 0;
 
        /* Enable FPU */
        if (misa_extension('D') || misa_extension('F'))
@@ -68,6 +71,21 @@ static void mstatus_init(struct sbi_scratch *scratch)
        if (sbi_hart_has_feature(scratch, SBI_HART_HAS_MCOUNTINHIBIT))
                csr_write(CSR_MCOUNTINHIBIT, 0xFFFFFFF8);
 
+       /**
+        * The mhpmeventn[h] CSR should be initialized with interrupt disabled
+        * and inhibited running in M-mode during init.
+        * To keep it simple, only contiguous mhpmcounters are supported as a
+        * platform with discontiguous mhpmcounters may not make much sense.
+        */
+       mhpmevent_init_val |= (MHPMEVENT_OF | MHPMEVENT_MINH);
+       for (cidx = 0; cidx < num_mhpm; cidx++) {
+#if __riscv_xlen == 32
+               csr_write_num(CSR_MHPMEVENT3 + cidx, mhpmevent_init_val & 0xFFFFFFFF);
+               csr_write_num(CSR_MHPMEVENT3H + cidx, mhpmevent_init_val >> BITS_PER_LONG);
+#else
+               csr_write_num(CSR_MHPMEVENT3 + cidx, mhpmevent_init_val);
+#endif
+       }
        /* Disable all interrupts */
        csr_write(CSR_MIE, 0);