* [PATCH v6 0/2] riscv: add c.jal instruction simulation for kprobes
@ 2026-07-01 8:10 Xiaofeng Yuan
2026-07-01 8:10 ` [PATCH v6 1/2] riscv: probes: simulate c.jal instruction Xiaofeng Yuan
2026-07-01 8:10 ` [PATCH v6 2/2] riscv: kprobes: add test case for c.jal instruction simulation Xiaofeng Yuan
0 siblings, 2 replies; 4+ messages in thread
From: Xiaofeng Yuan @ 2026-07-01 8:10 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou
Cc: Charlie Jenkins, Nam Cao, linux-riscv, linux-kernel, xiaofengmian
The c.jal instruction is part of the RISC-V compressed instruction set
and is defined only on RV32. Currently kprobes rejects it, causing
probes placed on c.jal to fail.
This series adds simulation support for c.jal and includes a test
case by Nam Cao.
Changes since v5:
- Removed the #if __riscv_xlen == 32 guards around simulate_c_jal()
as both Charlie Jenkins and Nam Cao agreed they are unnecessary.
On RV64, riscv_insn_is_c_jal() always returns 0 so the simulation
code is never invoked, and the small overhead in kernel size is
acceptable.
- Included Nam Cao's test case for c.jal instruction simulation.
Changes since v4:
- Reuse simulate_c_j() for the jump logic (Nam Cao)
- Use direct register assignment instead of rv_insn_reg_set_val()
- Move RISCV_INSN_SET_SIMULATE(c_jal) to group with other compressed
jump instructions
Nam Cao (1):
riscv: kprobes: add test case for c.jal instruction simulation
Xiaofeng Yuan (1):
riscv: probes: simulate c.jal instruction
Nam Cao (1):
riscv: kprobes: add test case for c.jal instruction simulation
Xiaofeng Yuan (1):
riscv: probes: simulate c.jal instruction
arch/riscv/kernel/probes/decode-insn.c | 2 +-
arch/riscv/kernel/probes/simulate-insn.c | 7 ++++++
arch/riscv/kernel/probes/simulate-insn.h | 1 +
.../kernel/tests/kprobes/test-kprobes-asm.S | 24 +++++++++++++++++++
4 files changed, 33 insertions(+), 1 deletion(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v6 1/2] riscv: probes: simulate c.jal instruction
2026-07-01 8:10 [PATCH v6 0/2] riscv: add c.jal instruction simulation for kprobes Xiaofeng Yuan
@ 2026-07-01 8:10 ` Xiaofeng Yuan
2026-07-02 9:49 ` Nam Cao
2026-07-01 8:10 ` [PATCH v6 2/2] riscv: kprobes: add test case for c.jal instruction simulation Xiaofeng Yuan
1 sibling, 1 reply; 4+ messages in thread
From: Xiaofeng Yuan @ 2026-07-01 8:10 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou
Cc: Charlie Jenkins, Nam Cao, linux-riscv, linux-kernel, xiaofengmian
The c.jal instruction is currently marked REJECTED in kprobes
instruction decoding, but it should be SIMULATED like other
compressed jump instructions.
Add simulate_c_jal() which saves the return address to RA and
sets the program counter to the target offset, reusing
simulate_c_j for the common jump logic.
Although c.jal is RV32-only, the function compiles unconditionally.
On RV64, riscv_insn_is_c_jal() always returns 0, so the simulation
code is never invoked and the small overhead in kernel size is
acceptable.
Signed-off-by: Xiaofeng Yuan <xiaofengmian@163.com>
---
arch/riscv/kernel/probes/decode-insn.c | 2 +-
arch/riscv/kernel/probes/simulate-insn.c | 7 +++++++
arch/riscv/kernel/probes/simulate-insn.h | 1 +
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 65d9590bf..433d9035b 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -29,12 +29,12 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
* TODO: the REJECTED ones below need to be implemented
*/
#ifdef CONFIG_RISCV_ISA_C
- RISCV_INSN_REJECTED(c_jal, insn);
RISCV_INSN_REJECTED(c_ebreak, insn);
RISCV_INSN_SET_SIMULATE(c_j, insn);
RISCV_INSN_SET_SIMULATE(c_jr, insn);
RISCV_INSN_SET_SIMULATE(c_jalr, insn);
+ RISCV_INSN_SET_SIMULATE(c_jal, insn);
RISCV_INSN_SET_SIMULATE(c_beqz, insn);
RISCV_INSN_SET_SIMULATE(c_bnez, insn);
#endif
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index fa581590c..f8a2f6857 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -163,6 +163,13 @@ bool __kprobes simulate_c_j(u32 opcode, unsigned long addr, struct pt_regs *regs
return true;
}
+bool __kprobes simulate_c_jal(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ regs->ra = addr + 2;
+
+ return simulate_c_j(opcode, addr, regs);
+}
+
static bool __kprobes simulate_c_jr_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs,
bool is_jalr)
{
diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h
index 44ebbc444..b89e1bb01 100644
--- a/arch/riscv/kernel/probes/simulate-insn.h
+++ b/arch/riscv/kernel/probes/simulate-insn.h
@@ -25,6 +25,7 @@ bool simulate_branch(u32 opcode, unsigned long addr, struct pt_regs *regs);
bool simulate_jal(u32 opcode, unsigned long addr, struct pt_regs *regs);
bool simulate_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs);
bool simulate_c_j(u32 opcode, unsigned long addr, struct pt_regs *regs);
+bool simulate_c_jal(u32 opcode, unsigned long addr, struct pt_regs *regs);
bool simulate_c_jr(u32 opcode, unsigned long addr, struct pt_regs *regs);
bool simulate_c_jalr(u32 opcode, unsigned long addr, struct pt_regs *regs);
bool simulate_c_bnez(u32 opcode, unsigned long addr, struct pt_regs *regs);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v6 2/2] riscv: kprobes: add test case for c.jal instruction simulation
2026-07-01 8:10 [PATCH v6 0/2] riscv: add c.jal instruction simulation for kprobes Xiaofeng Yuan
2026-07-01 8:10 ` [PATCH v6 1/2] riscv: probes: simulate c.jal instruction Xiaofeng Yuan
@ 2026-07-01 8:10 ` Xiaofeng Yuan
1 sibling, 0 replies; 4+ messages in thread
From: Xiaofeng Yuan @ 2026-07-01 8:10 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou
Cc: Charlie Jenkins, Nam Cao, linux-riscv, linux-kernel, xiaofengmian
From: Nam Cao <namcao@linutronix.de>
Add a test case validating that kprobes correctly simulates the
c.jal instruction on RV32.
The test uses two probe points: a forward c.jal and a backward
c.jal, and verifies that the containing function returns the
expected magic value KPROBE_TEST_MAGIC after kprobe interception.
Co-developed-by: Xiaofeng Yuan <xiaofengmian@163.com>
Signed-off-by: Nam Cao <namcao@linutronix.de>
Signed-off-by: Xiaofeng Yuan <xiaofengmian@163.com>
---
.../kernel/tests/kprobes/test-kprobes-asm.S | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S b/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S
index f16deee9e..15e50934b 100644
--- a/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S
+++ b/arch/riscv/kernel/tests/kprobes/test-kprobes-asm.S
@@ -179,6 +179,23 @@ test_kprobes_c_bnez_addr3:
ret
SYM_FUNC_END(test_kprobes_c_bnez)
+#ifdef CONFIG_32BIT
+SYM_FUNC_START(test_kprobes_c_jal)
+ li a0, 0
+ mv a1, ra
+test_kprobes_c_jal_addr1:
+ c.jal 2f
+ ret
+1: li a0, KPROBE_TEST_MAGIC_UPPER
+ ret
+test_kprobes_c_jal_addr2:
+2: c.jal 1b
+ li a2, KPROBE_TEST_MAGIC_LOWER
+ add a0, a0, a2
+ jr a1
+SYM_FUNC_END(test_kprobes_c_jal)
+#endif
+
#endif /* CONFIG_RISCV_ISA_C */
.section .rodata
@@ -209,6 +226,10 @@ SYM_DATA_START(test_kprobes_addresses)
RISCV_PTR test_kprobes_c_bnez_addr1
RISCV_PTR test_kprobes_c_bnez_addr2
RISCV_PTR test_kprobes_c_bnez_addr3
+#ifdef CONFIG_32BIT
+ RISCV_PTR test_kprobes_c_jal_addr1
+ RISCV_PTR test_kprobes_c_jal_addr2
+#endif
#endif /* CONFIG_RISCV_ISA_C */
RISCV_PTR 0
SYM_DATA_END(test_kprobes_addresses)
@@ -226,6 +247,9 @@ SYM_DATA_START(test_kprobes_functions)
RISCV_PTR test_kprobes_c_jalr
RISCV_PTR test_kprobes_c_beqz
RISCV_PTR test_kprobes_c_bnez
+#ifdef CONFIG_32BIT
+ RISCV_PTR test_kprobes_c_jal
+#endif
#endif /* CONFIG_RISCV_ISA_C */
RISCV_PTR 0
SYM_DATA_END(test_kprobes_functions)
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v6 1/2] riscv: probes: simulate c.jal instruction
2026-07-01 8:10 ` [PATCH v6 1/2] riscv: probes: simulate c.jal instruction Xiaofeng Yuan
@ 2026-07-02 9:49 ` Nam Cao
0 siblings, 0 replies; 4+ messages in thread
From: Nam Cao @ 2026-07-02 9:49 UTC (permalink / raw)
To: Xiaofeng Yuan, Paul Walmsley, Palmer Dabbelt, Albert Ou
Cc: Charlie Jenkins, linux-riscv, linux-kernel, xiaofengmian
Xiaofeng Yuan <xiaofengmian@163.com> writes:
> The c.jal instruction is currently marked REJECTED in kprobes
> instruction decoding, but it should be SIMULATED like other
> compressed jump instructions.
>
> Add simulate_c_jal() which saves the return address to RA and
> sets the program counter to the target offset, reusing
> simulate_c_j for the common jump logic.
>
> Although c.jal is RV32-only, the function compiles unconditionally.
> On RV64, riscv_insn_is_c_jal() always returns 0, so the simulation
> code is never invoked and the small overhead in kernel size is
> acceptable.
>
> Signed-off-by: Xiaofeng Yuan <xiaofengmian@163.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
Tested-by: Nam Cao <namcao@linutronix.de>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-02 9:49 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 8:10 [PATCH v6 0/2] riscv: add c.jal instruction simulation for kprobes Xiaofeng Yuan
2026-07-01 8:10 ` [PATCH v6 1/2] riscv: probes: simulate c.jal instruction Xiaofeng Yuan
2026-07-02 9:49 ` Nam Cao
2026-07-01 8:10 ` [PATCH v6 2/2] riscv: kprobes: add test case for c.jal instruction simulation Xiaofeng Yuan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox