From cb8271c8e43e3c317436b7377c4fa0ac669f8fb5 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 29 May 2022 13:25:30 -0500 Subject: lib: sbi_illegal_insn: Add emulation for fence.tso While OpenC906 appears to properly decode `fence.tso` as a fence instruction[1], the version of the C906 taped out in the Allwinner D1 does not, and raises illegal instruction. Handle this errata by emulating `fence.tso` as `fence rw, rw`. [1]: https://github.com/T-head-Semi/openc906/blob/30827e7f/C906_RTL_FACTORY/gen_rtl/idu/rtl/aq_idu_id_decd.v#L2097 Signed-off-by: Samuel Holland Reviewed-by: Anup Patel --- include/sbi/riscv_encoding.h | 3 +++ lib/sbi/sbi_illegal_insn.c | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) 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 +#include #include #include #include @@ -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 */ -- cgit v1.2.3