diff options
-rw-r--r-- | include/sbi/riscv_encoding.h | 3 | ||||
-rw-r--r-- | lib/sbi/sbi_illegal_insn.c | 14 |
2 files changed, 16 insertions, 1 deletions
diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h index 7cfbace..a164768 100644 --- a/include/sbi/riscv_encoding.h +++ b/include/sbi/riscv_encoding.h @@ -838,6 +838,9 @@ #define INSN_MASK_WFI 0xffffff00 #define INSN_MATCH_WFI 0x10500000 +#define INSN_MASK_FENCE_TSO 0xffffffff +#define INSN_MATCH_FENCE_TSO 0x8330000f + #define INSN_16BIT_MASK 0x3 #define INSN_32BIT_MASK 0x1c diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c index 386b48a..84c04f8 100644 --- a/lib/sbi/sbi_illegal_insn.c +++ b/lib/sbi/sbi_illegal_insn.c @@ -8,6 +8,7 @@ */ #include <sbi/riscv_asm.h> +#include <sbi/riscv_barrier.h> #include <sbi/riscv_encoding.h> #include <sbi/sbi_bitops.h> #include <sbi/sbi_emulate_csr.h> @@ -33,6 +34,17 @@ static int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs) return sbi_trap_redirect(regs, &trap); } +static int misc_mem_opcode_insn(ulong insn, struct sbi_trap_regs *regs) +{ + /* Errata workaround: emulate `fence.tso` as `fence rw, rw`. */ + if ((insn & INSN_MASK_FENCE_TSO) == INSN_MATCH_FENCE_TSO) { + smp_mb(); + return 0; + } + + return truly_illegal_insn(insn, regs); +} + static int system_opcode_insn(ulong insn, struct sbi_trap_regs *regs) { int do_write, rs1_num = (insn >> 15) & 0x1f; @@ -92,7 +104,7 @@ static const illegal_insn_func illegal_insn_table[32] = { truly_illegal_insn, /* 0 */ truly_illegal_insn, /* 1 */ truly_illegal_insn, /* 2 */ - truly_illegal_insn, /* 3 */ + misc_mem_opcode_insn, /* 3 */ truly_illegal_insn, /* 4 */ truly_illegal_insn, /* 5 */ truly_illegal_insn, /* 6 */ |