diff options
author | Bo Gan <ganboing@gmail.com> | 2024-03-05 18:35:40 -0800 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2024-03-11 10:56:02 +0530 |
commit | 81e3ba77a6dae8763972fffb6e4a833adccbeb1b (patch) | |
tree | 9609952f22d5fa24ebeb95c5836d9ea881a5e72a /lib/sbi | |
parent | ddf3b649f1edd9eb5ad171c7faadf34acfb942f0 (diff) | |
download | opensbi-81e3ba77a6dae8763972fffb6e4a833adccbeb1b.zip opensbi-81e3ba77a6dae8763972fffb6e4a833adccbeb1b.tar.gz opensbi-81e3ba77a6dae8763972fffb6e4a833adccbeb1b.tar.bz2 |
lib: sbi: call platform load/store emulators
sbi_load/store_access_handler now tries to call platform emulators
if defined. Otherwise, redirects the fault. If the platform code
returns failure, this means the H/S/U has accessed the emulated
devices in an unexpected manner, which is very likely caused by
buggy code in H/S/U. We redirect the fault, so lower privileged
level can get notified, and act accordingly. (E.g., oops in Linux)
We let the handler truly fail if the trap was originated from M mode.
In this case, something must be very wrong and we should just fail.
Signed-off-by: Bo Gan <ganboing@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Diffstat (limited to 'lib/sbi')
-rw-r--r-- | lib/sbi/sbi_trap_ldst.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/lib/sbi/sbi_trap_ldst.c b/lib/sbi/sbi_trap_ldst.c index b9dc7ea..d864ad1 100644 --- a/lib/sbi/sbi_trap_ldst.c +++ b/lib/sbi/sbi_trap_ldst.c @@ -15,6 +15,7 @@ #include <sbi/sbi_pmu.h> #include <sbi/sbi_trap.h> #include <sbi/sbi_unpriv.h> +#include <sbi/sbi_platform.h> /** * Load emulator callback: @@ -319,14 +320,46 @@ int sbi_misaligned_store_handler(struct sbi_trap_regs *regs, sbi_misaligned_st_emulator); } +static int sbi_ld_access_emulator(int rlen, union sbi_ldst_data *out_val, + struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + /* If fault came from M mode, just fail */ + if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) == PRV_M) + return SBI_EINVAL; + + /* If platform emulator failed, we redirect instead of fail */ + if (sbi_platform_emulate_load(sbi_platform_thishart_ptr(), rlen, + orig_trap->tval, out_val)) + return sbi_trap_redirect(regs, orig_trap); + + return rlen; +} + int sbi_load_access_handler(struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap) { - return sbi_trap_redirect(regs, orig_trap); + return sbi_trap_emulate_load(regs, orig_trap, sbi_ld_access_emulator); +} + +static int sbi_st_access_emulator(int wlen, union sbi_ldst_data in_val, + struct sbi_trap_regs *regs, + const struct sbi_trap_info *orig_trap) +{ + /* If fault came from M mode, just fail */ + if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) == PRV_M) + return SBI_EINVAL; + + /* If platform emulator failed, we redirect instead of fail */ + if (sbi_platform_emulate_store(sbi_platform_thishart_ptr(), wlen, + orig_trap->tval, in_val)) + return sbi_trap_redirect(regs, orig_trap); + + return wlen; } int sbi_store_access_handler(struct sbi_trap_regs *regs, const struct sbi_trap_info *orig_trap) { - return sbi_trap_redirect(regs, orig_trap); + return sbi_trap_emulate_store(regs, orig_trap, sbi_st_access_emulator); } |