diff options
author | Anup Patel <anup.patel@wdc.com> | 2019-12-12 20:21:42 +0300 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2019-12-16 12:18:31 +0300 |
commit | 7219477f7b400a2eaa8fac5aedd73ba29eef92d9 (patch) | |
tree | 437690397563c753cdfcafe2e9c9fd76e5310342 /lib/sbi/sbi_misaligned_ldst.c | |
parent | 2be424bd28560d5399788ed16f663f7785a8c5f9 (diff) | |
download | opensbi-7219477f7b400a2eaa8fac5aedd73ba29eef92d9.tar.xz |
lib: Use MTINST CSR in misaligned load/store emulation
We should use MTINST CSR in misaligned load/store emulation whenever
possible to avoid unpriv read in getting trapped instruction. This will
improve preformance on HW having proper implementation of MTINST CSR.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'lib/sbi/sbi_misaligned_ldst.c')
-rw-r--r-- | lib/sbi/sbi_misaligned_ldst.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/lib/sbi/sbi_misaligned_ldst.c b/lib/sbi/sbi_misaligned_ldst.c index 314b2f3..400372c 100644 --- a/lib/sbi/sbi_misaligned_ldst.c +++ b/lib/sbi/sbi_misaligned_ldst.c @@ -26,14 +26,27 @@ int sbi_misaligned_load_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs, struct sbi_scratch *scratch) { + ulong insn; union reg_data val; struct sbi_trap_info uptrap; int i, fp = 0, shift = 0, len = 0; - ulong insn = sbi_get_insn(regs->mepc, scratch, &uptrap); - if (uptrap.cause) { - uptrap.epc = regs->mepc; - return sbi_trap_redirect(regs, &uptrap, scratch); + if (tinst & 0x1) { + /* + * Bit[0] == 1 implies trapped instruction value is + * transformed instruction or custom instruction. + */ + insn = tinst | INSN_16BIT_MASK; + } else { + /* + * Bit[0] == 0 implies trapped instruction value is + * zero or special value. + */ + insn = sbi_get_insn(regs->mepc, scratch, &uptrap); + if (uptrap.cause) { + uptrap.epc = regs->mepc; + return sbi_trap_redirect(regs, &uptrap, scratch); + } } if ((insn & INSN_MASK_LW) == INSN_MATCH_LW) { @@ -135,14 +148,27 @@ int sbi_misaligned_store_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs, struct sbi_scratch *scratch) { + ulong insn; union reg_data val; struct sbi_trap_info uptrap; int i, len = 0; - ulong insn = sbi_get_insn(regs->mepc, scratch, &uptrap); - if (uptrap.cause) { - uptrap.epc = regs->mepc; - return sbi_trap_redirect(regs, &uptrap, scratch); + if (tinst & 0x1) { + /* + * Bit[0] == 1 implies trapped instruction value is + * transformed instruction or custom instruction. + */ + insn = tinst | INSN_16BIT_MASK; + } else { + /* + * Bit[0] == 0 implies trapped instruction value is + * zero or special value. + */ + insn = sbi_get_insn(regs->mepc, scratch, &uptrap); + if (uptrap.cause) { + uptrap.epc = regs->mepc; + return sbi_trap_redirect(regs, &uptrap, scratch); + } } val.data_ulong = GET_RS2(insn, regs); |