Skip to content

Commit b18256d

Browse files
covanampalmer-dabbelt
authored andcommitted
riscv: kprobes: simulate c.jr and c.jalr instructions
kprobes currently rejects c.jr and c.jalr instructions. Implement them. Signed-off-by: Nam Cao <[email protected]> Reviewed-by: Charlie Jenkins <[email protected]> Link: https://lore.kernel.org/r/db8b7787e9208654cca50484f68334f412be2ea9.1690704360.git.namcaov@gmail.com Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent a938929 commit b18256d

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

arch/riscv/kernel/probes/decode-insn.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
2929
* TODO: the REJECTED ones below need to be implemented
3030
*/
3131
#ifdef CONFIG_RISCV_ISA_C
32-
RISCV_INSN_REJECTED(c_jr, insn);
3332
RISCV_INSN_REJECTED(c_jal, insn);
34-
RISCV_INSN_REJECTED(c_jalr, insn);
3533
RISCV_INSN_REJECTED(c_beqz, insn);
3634
RISCV_INSN_REJECTED(c_bnez, insn);
3735
RISCV_INSN_REJECTED(c_ebreak, insn);
3836

3937
RISCV_INSN_SET_SIMULATE(c_j, insn);
38+
RISCV_INSN_SET_SIMULATE(c_jr, insn);
39+
RISCV_INSN_SET_SIMULATE(c_jalr, insn);
4040
#endif
4141

4242
RISCV_INSN_SET_SIMULATE(jal, insn);

arch/riscv/kernel/probes/simulate-insn.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,40 @@ bool __kprobes simulate_c_j(u32 opcode, unsigned long addr, struct pt_regs *regs
212212

213213
return true;
214214
}
215+
216+
static bool __kprobes simulate_c_jr_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs,
217+
bool is_jalr)
218+
{
219+
/*
220+
* 15 12 11 7 6 2 1 0
221+
* | funct4 | rs1 | rs2 | op |
222+
* 4 5 5 2
223+
*/
224+
225+
unsigned long jump_addr;
226+
227+
u32 rs1 = (opcode >> 7) & 0x1f;
228+
229+
if (rs1 == 0) /* C.JR is only valid when rs1 != x0 */
230+
return false;
231+
232+
if (!rv_insn_reg_get_val(regs, rs1, &jump_addr))
233+
return false;
234+
235+
if (is_jalr && !rv_insn_reg_set_val(regs, 1, addr + 2))
236+
return false;
237+
238+
instruction_pointer_set(regs, jump_addr);
239+
240+
return true;
241+
}
242+
243+
bool __kprobes simulate_c_jr(u32 opcode, unsigned long addr, struct pt_regs *regs)
244+
{
245+
return simulate_c_jr_jalr(opcode, addr, regs, false);
246+
}
247+
248+
bool __kprobes simulate_c_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs)
249+
{
250+
return simulate_c_jr_jalr(opcode, addr, regs, true);
251+
}

arch/riscv/kernel/probes/simulate-insn.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ bool simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs);
2525
bool simulate_jal(u32 opcode, unsigned long addr, struct pt_regs *regs);
2626
bool simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs);
2727
bool simulate_c_j(u32 opcode, unsigned long addr, struct pt_regs *regs);
28+
bool simulate_c_jr(u32 opcode, unsigned long addr, struct pt_regs *regs);
29+
bool simulate_c_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs);
2830

2931
#endif /* _RISCV_KERNEL_PROBES_SIMULATE_INSN_H */

0 commit comments

Comments
 (0)