riscv: misaligned: Add handling for ZCB instructions
authorNylon Chen <nylon.chen@sifive.com>
Fri, 11 Apr 2025 07:38:49 +0000 (15:38 +0800)
committerPalmer Dabbelt <palmer@rivosinc.com>
Fri, 18 Apr 2025 17:52:26 +0000 (10:52 -0700)
Add support for the Zcb extension's compressed half-word instructions
(C.LHU, C.LH, and C.SH) in the RISC-V misaligned access trap handler.

Signed-off-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Nylon Chen <nylon.chen@sifive.com>
Link: https://lore.kernel.org/r/20250411073850.3699180-2-nylon.chen@sifive.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/kernel/traps_misaligned.c

index 0173ed80818cbf8e8b70867176444a169d4ec8d0..7443632445d44f92904c739cb33ee8cc3da4aeaf 100644 (file)
 #define INSN_MATCH_C_FSWSP             0xe002
 #define INSN_MASK_C_FSWSP              0xe003
 
+#define INSN_MATCH_C_LHU               0x8400
+#define INSN_MASK_C_LHU                        0xfc43
+#define INSN_MATCH_C_LH                        0x8440
+#define INSN_MASK_C_LH                 0xfc43
+#define INSN_MATCH_C_SH                        0x8c00
+#define INSN_MASK_C_SH                 0xfc43
+
 #define INSN_LEN(insn)                 ((((insn) & 0x3) < 0x3) ? 2 : 4)
 
 #if defined(CONFIG_64BIT)
@@ -431,6 +438,13 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
                fp = 1;
                len = 4;
 #endif
+       } else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) {
+               len = 2;
+               insn = RVC_RS2S(insn) << SH_RD;
+       } else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) {
+               len = 2;
+               shift = 8 * (sizeof(ulong) - len);
+               insn = RVC_RS2S(insn) << SH_RD;
        } else {
                regs->epc = epc;
                return -1;
@@ -530,6 +544,9 @@ static int handle_scalar_misaligned_store(struct pt_regs *regs)
                len = 4;
                val.data_ulong = GET_F32_RS2C(insn, regs);
 #endif
+       } else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) {
+               len = 2;
+               val.data_ulong = GET_RS2S(insn, regs);
        } else {
                regs->epc = epc;
                return -1;