LoongArch: Add larch_insn_gen_break() to generate break insns
authorTiezhu Yang <yangtiezhu@loongson.cn>
Thu, 29 Jun 2023 12:58:44 +0000 (20:58 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Thu, 29 Jun 2023 12:58:44 +0000 (20:58 +0800)
There exist various break insns such as BRK_KPROBE_BP, BRK_KPROBE_SSTEPBP,
BRK_UPROBE_BP and BRK_UPROBE_XOLBP, add larch_insn_gen_break() to generate
break insns simpler, this is preparation for later patch.

Tested-by: Jeff Xie <xiehuan09@gmail.com>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/include/asm/inst.h
arch/loongarch/kernel/inst.c

index a8b88a0..71e1ed4 100644 (file)
@@ -482,6 +482,8 @@ u32 larch_insn_gen_nop(void);
 u32 larch_insn_gen_b(unsigned long pc, unsigned long dest);
 u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest);
 
+u32 larch_insn_gen_break(int imm);
+
 u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk);
 u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj);
 
@@ -500,6 +502,16 @@ static inline bool unsigned_imm_check(unsigned long val, unsigned int bit)
        return val < (1UL << bit);
 }
 
+#define DEF_EMIT_REG0I15_FORMAT(NAME, OP)                              \
+static inline void emit_##NAME(union loongarch_instruction *insn,      \
+                              int imm)                                 \
+{                                                                      \
+       insn->reg0i15_format.opcode = OP;                               \
+       insn->reg0i15_format.immediate = imm;                           \
+}
+
+DEF_EMIT_REG0I15_FORMAT(break, break_op)
+
 #define DEF_EMIT_REG0I26_FORMAT(NAME, OP)                              \
 static inline void emit_##NAME(union loongarch_instruction *insn,      \
                               int offset)                              \
index a3169cf..3050329 100644 (file)
@@ -253,6 +253,20 @@ u32 larch_insn_gen_bl(unsigned long pc, unsigned long dest)
        return insn.word;
 }
 
+u32 larch_insn_gen_break(int imm)
+{
+       union loongarch_instruction insn;
+
+       if (imm < 0 || imm >= SZ_32K) {
+               pr_warn("The generated break instruction is out of range.\n");
+               return INSN_BREAK;
+       }
+
+       emit_break(&insn, imm);
+
+       return insn.word;
+}
+
 u32 larch_insn_gen_or(enum loongarch_gpr rd, enum loongarch_gpr rj, enum loongarch_gpr rk)
 {
        union loongarch_instruction insn;