summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2021-03-19 13:04:50 +0300
committerAnup Patel <anup@brainfault.org>2021-03-22 06:48:56 +0300
commitddad02d62550ca8884a2bd21345dad8c6c216777 (patch)
treefe035e650ab80c17f97c4b7154e4a85b77ad58e9
parent0f20e8adcf42d31bc478d6700b625d00a68cb30e (diff)
downloadopensbi-ddad02d62550ca8884a2bd21345dad8c6c216777.tar.xz
lib: sbi: illegal CSR 0x306 access in hpm_allowed()
The trap handler sbi_emulate_csr_read() invokes hpm_allowed() which reads CSR 0x306 (mcounteren). The K210 does not support CSR 0x306. While trying to handle a trap occurring in S-mode code this creates an additional trap in M-mode. This results in failure to redirect to S-mode and the system hanging in sbi_hart_hang(). In hart_detect_features() we have already determined if CSR 0x306 is available and stored that information in the scratch area. We can use this information to decide if CSR 0x306 shall be accessed in hpm_allowed() and thus avoid the M-mode trap. Likewise if CSR scounteren is not available we have to avoid reading CSR 0x106. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Reviewed-by: Anup Patel <anup.patel@wdc.com>
-rw-r--r--lib/sbi/sbi_emulate_csr.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/lib/sbi/sbi_emulate_csr.c b/lib/sbi/sbi_emulate_csr.c
index bee7761..dbb1755 100644
--- a/lib/sbi/sbi_emulate_csr.c
+++ b/lib/sbi/sbi_emulate_csr.c
@@ -21,14 +21,23 @@
static bool hpm_allowed(int hpm_num, ulong prev_mode, bool virt)
{
ulong cen = -1UL;
+ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
if (prev_mode <= PRV_S) {
- cen &= csr_read(CSR_MCOUNTEREN);
- if (virt)
- cen &= csr_read(CSR_HCOUNTEREN);
+ if (sbi_hart_has_feature(scratch, SBI_HART_HAS_MCOUNTEREN)) {
+ cen &= csr_read(CSR_MCOUNTEREN);
+ if (virt)
+ cen &= csr_read(CSR_HCOUNTEREN);
+ } else {
+ cen = 0;
+ }
+ }
+ if (prev_mode == PRV_U) {
+ if (sbi_hart_has_feature(scratch, SBI_HART_HAS_SCOUNTEREN))
+ cen &= csr_read(CSR_SCOUNTEREN);
+ else
+ cen = 0;
}
- if (prev_mode == PRV_U)
- cen &= csr_read(CSR_SCOUNTEREN);
return ((cen >> hpm_num) & 1) ? TRUE : FALSE;
}