diff options
author | Anup Patel <anup.patel@wdc.com> | 2019-08-12 11:50:22 +0530 |
---|---|---|
committer | Anup Patel <anup.patel@wdc.com> | 2019-08-13 09:48:40 +0530 |
commit | a88e424f6c3a42a38e9395726d9fd4e50a96abd2 (patch) | |
tree | 74804eabd44a8007c7a3a1ea62f710d68af53fbd /lib/sbi/sbi_illegal_insn.c | |
parent | 2e0f3ac758da99fb6d1b4c651643999d83cd0a7f (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.c | 9 |
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); |