diff options
| author | Anup Patel <[email protected]> | 2019-04-05 18:17:11 +0530 |
|---|---|---|
| committer | Anup Patel <[email protected]> | 2019-09-30 15:32:00 +0530 |
| commit | a14e7ee82c2723f18cf2d1c7f1a88d88766a6018 (patch) | |
| tree | 04a6f02cd406a9a1adf2356c64508fd45921fe1c | |
| parent | bbeb8e619d1cc528d2d56531512d6ea406f9738b (diff) | |
lib: Redirect WFI trapped from VS/VU mode to HS-mode
The WFI will trap as illegal instruction trap when executed
in VS/VU mode so we just forward/redirect it to HS-mode so
that hypervisor can deal with it appropriately.
Signed-off-by: Anup Patel <[email protected]>
| -rw-r--r-- | include/sbi/riscv_encoding.h | 3 | ||||
| -rw-r--r-- | lib/sbi/sbi_illegal_insn.c | 20 |
2 files changed, 20 insertions, 3 deletions
diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h index 0e1ea59c..5aab9d26 100644 --- a/include/sbi/riscv_encoding.h +++ b/include/sbi/riscv_encoding.h @@ -544,6 +544,9 @@ #define INSN_MATCH_C_FSWSP 0xe002 #define INSN_MASK_C_FSWSP 0xe003 +#define INSN_MASK_WFI 0xffffff00 +#define INSN_MATCH_WFI 0x10500000 + #define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4) #if __riscv_xlen == 64 diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c index b6ba4b05..7ea42f71 100644 --- a/lib/sbi/sbi_illegal_insn.c +++ b/lib/sbi/sbi_illegal_insn.c @@ -36,9 +36,23 @@ static int system_opcode_insn(ulong insn, u32 hartid, ulong mcause, int csr_num = (u32)insn >> 20; ulong csr_val, new_csr_val; - if (sbi_emulate_csr_read(csr_num, hartid, regs->mstatus, scratch, - &csr_val)) - return truly_illegal_insn(insn, hartid, mcause, regs, scratch); + /* + * WFI always traps as illegal instruction when executed from + * VS/VU mode so we just forward it to HS-mode. + */ +#if __riscv_xlen == 32 + if ((regs->mstatusH & MSTATUSH_MPV) && +#else + if ((regs->mstatus & MSTATUS_MPV) && +#endif + (insn & INSN_MASK_WFI) == INSN_MATCH_WFI) + return sbi_trap_redirect(regs, scratch, + regs->mepc, mcause, insn); + + if (sbi_emulate_csr_read(csr_num, hartid, regs->mstatus, + scratch, &csr_val)) + return truly_illegal_insn(insn, hartid, mcause, + regs, scratch); do_write = rs1_num; switch (GET_RM(insn)) { |
