lib: sbi: Disable m/scounteren & enable mcountinhibit
authorAtish Patra <atish.patra@wdc.com>
Sat, 10 Jul 2021 16:18:06 +0000 (09:18 -0700)
committerAnup Patel <anup@brainfault.org>
Sun, 11 Jul 2021 04:44:26 +0000 (10:14 +0530)
Currently, all bits in mcountern are enabled unconditionally at boot time.
With SBI PMU extension, all the programmable counters should enabled only
during performance monitoring for a particular event. However, this is done
only if mcountinhibit is implemented because the supervisor mode can not
start/stop any event without mcountinhibit.

Similarly, supervisor should take care enabling scounteren which allows
U-mode to access programmable pmu counters. All the non-programmable ones
(CY, TM, IR) should be enabled in M-mode because some userspace may rely on
builtins such as __builtin_readcyclecounter. Supervisor OS can still disable
them during initial configuration.

Reviewed-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Atish Patra <atish.patra@wdc.com>
lib/sbi/sbi_hart.c

index e8cd042..6254452 100644 (file)
@@ -51,12 +51,29 @@ static void mstatus_init(struct sbi_scratch *scratch)
 
        csr_write(CSR_MSTATUS, mstatus_val);
 
-       /* Enable user/supervisor use of perf counters */
+       /* Disable user mode usage of all perf counters except default ones (CY, TM, IR) */
        if (misa_extension('S') &&
            sbi_hart_has_feature(scratch, SBI_HART_HAS_SCOUNTEREN))
-               csr_write(CSR_SCOUNTEREN, -1);
-       if (sbi_hart_has_feature(scratch, SBI_HART_HAS_MCOUNTEREN))
-               csr_write(CSR_MCOUNTEREN, -1);
+               csr_write(CSR_SCOUNTEREN, 7);
+
+       if (sbi_hart_has_feature(scratch, SBI_HART_HAS_MCOUNTEREN)) {
+               if (sbi_hart_has_feature(scratch, SBI_HART_HAS_MCOUNTINHIBIT))
+                       /**
+                        * Just enable the default counters (CY, TM, IR) because
+                        * some OS (e.g FreeBSD) expect them to be enabled.
+                        *
+                        * All other counters will be enabled at runtime after
+                        * S-mode request.
+                        */
+                       csr_write(CSR_MCOUNTEREN, 7);
+               else
+                       /* Supervisor mode usage are enabled by default */
+                       csr_write(CSR_MCOUNTEREN, -1);
+       }
+
+       /* All programmable counters will start running at runtime after S-mode request */
+       if (sbi_hart_has_feature(scratch, SBI_HART_HAS_MCOUNTINHIBIT))
+               csr_write(CSR_MCOUNTINHIBIT, 0xFFFFFFF8);
 
        /* Disable all interrupts */
        csr_write(CSR_MIE, 0);