diff options
-rw-r--r-- | lib/sbi/sbi_hart.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index e8cd042..6254452 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -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); |