diff options
author | Anup Patel <anup.patel@wdc.com> | 2020-08-15 19:47:58 +0300 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2020-08-21 17:05:31 +0300 |
commit | 4f3bad6e43f0e5a1a124847edf910e309ae9d59a (patch) | |
tree | 369be374aa21a7c2c77eee0e6feecdd8461a2d9c /lib | |
parent | e435ba05248a10a5085858c46fe11854373d5dbc (diff) | |
download | opensbi-4f3bad6e43f0e5a1a124847edf910e309ae9d59a.tar.xz |
lib: sbi: Handle the case where MTVAL has illegal instruction address
The Kendryte K210 follows RISC-V v1.9 spec so MTVAL has instruction
address (instead of instruction encoding) on illegal instruction trap.
To handle above case, we fix sbi_illegal_insn_handler() without any
impact on RISC-V v1.10 (or higher) systems. This achieved by exploiting
the fact that program counter (and instruction address) is always 2-byte
aligned in RISC-V world.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sbi/sbi_illegal_insn.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c index 0e5523f..9af3d24 100644 --- a/lib/sbi/sbi_illegal_insn.c +++ b/lib/sbi/sbi_illegal_insn.c @@ -118,13 +118,22 @@ int sbi_illegal_insn_handler(ulong insn, struct sbi_trap_regs *regs) { struct sbi_trap_info uptrap; + /* + * We only deal with 32-bit (or longer) illegal instructions. If we + * see instruction is zero OR instruction is 16-bit then we fetch and + * check the instruction encoding using unprivilege access. + * + * The program counter (PC) in RISC-V world is always 2-byte aligned + * so handling only 32-bit (or longer) illegal instructions also help + * the case where MTVAL CSR contains instruction address for illegal + * instruction trap. + */ + if (unlikely((insn & 3) != 3)) { - if (insn == 0) { - insn = sbi_get_insn(regs->mepc, &uptrap); - if (uptrap.cause) { - uptrap.epc = regs->mepc; - return sbi_trap_redirect(regs, &uptrap); - } + insn = sbi_get_insn(regs->mepc, &uptrap); + if (uptrap.cause) { + uptrap.epc = regs->mepc; + return sbi_trap_redirect(regs, &uptrap); } if ((insn & 3) != 3) return truly_illegal_insn(insn, regs); |