lib: Use MTINST CSR in misaligned load/store emulation
authorAnup Patel <anup.patel@wdc.com>
Thu, 12 Dec 2019 17:21:42 +0000 (22:51 +0530)
committerAnup Patel <anup@brainfault.org>
Mon, 16 Dec 2019 09:18:31 +0000 (14:48 +0530)
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>
lib/sbi/sbi_misaligned_ldst.c

index 314b2f3..400372c 100644 (file)
@@ -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);