aboutsummaryrefslogtreecommitdiff
path: root/lib/sbi/sbi_illegal_insn.c
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2019-08-12 11:50:22 +0530
committerAnup Patel <anup.patel@wdc.com>2019-08-13 09:48:40 +0530
commita88e424f6c3a42a38e9395726d9fd4e50a96abd2 (patch)
tree74804eabd44a8007c7a3a1ea62f710d68af53fbd /lib/sbi/sbi_illegal_insn.c
parent2e0f3ac758da99fb6d1b4c651643999d83cd0a7f (diff)
lib: Handle traps when doing unpriv load/store in get_insn()
We can get a page/access trap when doing unpriv load/store in get_insn() function because on a SMP system Linux swapper running on HART A can unmap pages from page table used by HART B. To tackle this we extend get_insn() implementation so that if we get trap in get_insn() then we redirect it to S-mode as fetch page/access fault. Signed-off-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'lib/sbi/sbi_illegal_insn.c')
-rw-r--r--lib/sbi/sbi_illegal_insn.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c
index 5541838..b6ba4b0 100644
--- a/lib/sbi/sbi_illegal_insn.c
+++ b/lib/sbi/sbi_illegal_insn.c
@@ -117,10 +117,15 @@ int sbi_illegal_insn_handler(u32 hartid, ulong mcause,
struct sbi_scratch *scratch)
{
ulong insn = csr_read(mbadaddr);
+ struct unpriv_trap uptrap;
if (unlikely((insn & 3) != 3)) {
- if (insn == 0)
- insn = get_insn(regs->mepc, NULL);
+ if (insn == 0) {
+ insn = get_insn(regs->mepc, scratch, &uptrap);
+ if (uptrap.cause)
+ return sbi_trap_redirect(regs, scratch,
+ regs->mepc, uptrap.cause, uptrap.tval);
+ }
if ((insn & 3) != 3)
return truly_illegal_insn(insn, hartid, mcause, regs,
scratch);