From: Xiaofeng Yuan <yuanxiaofeng@eswincomputing.com>
To: Paul Walmsley <pjw@kernel.org>, Palmer Dabbelt <palmer@dabbelt.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>, Nam Cao <namcaov@gmail.com>,
linux-riscv@lists.infradead.org, yuanxiaofeng@eswincomputing.com
Subject: [PATCH 1/2] riscv: kprobes: simulate nop and c.nop instructions
Date: Wed, 19 Aug 2026 18:14:18 +0800 [thread overview]
Message-ID: <20260819101419.1367-2-yuanxiaofeng@eswincomputing.com> (raw)
In-Reply-To: <20260819101419.1367-1-yuanxiaofeng@eswincomputing.com>
nop and c.nop have no architectural effect, so allocating an
out-of-line instruction slot and single-stepping through them is
pure overhead. Simulate them directly in the breakpoint handler
by advancing the program counter, following the approach already
used on arm64.
This avoids slot allocation, text patching, IRQ flag save/restore
and the single-step exception for these instructions.
Compile tested on RISC-V, and verified with the RISC-V kprobes
KUnit test which now covers nop and c.nop.
Signed-off-by: Xiaofeng Yuan <yuanxiaofeng@eswincomputing.com>
---
arch/riscv/include/asm/insn.h | 11 +++++++++++
arch/riscv/kernel/probes/decode-insn.c | 6 ++++++
arch/riscv/kernel/probes/simulate-insn.c | 14 ++++++++++++++
arch/riscv/kernel/probes/simulate-insn.h | 2 ++
4 files changed, 33 insertions(+)
diff --git a/arch/riscv/include/asm/insn.h b/arch/riscv/include/asm/insn.h
index c3005573e8..5b3944a5fa 100644
--- a/arch/riscv/include/asm/insn.h
+++ b/arch/riscv/include/asm/insn.h
@@ -228,6 +228,15 @@
#define RVG_MASK_EBREAK 0xffffffff
#define RVG_MASK_SRET 0xffffffff
+/*
+ * NOP and C.NOP have no variable fields, so all bits must match.
+ * NOP is encoded as ADDI x0, x0, 0 (0x00000013), C.NOP as C.ADDI x0, 0 (0x0001).
+ */
+#define RVG_MATCH_NOP 0x00000013
+#define RVG_MASK_NOP 0xffffffff
+#define RVC_MATCH_C_NOP 0x0001
+#define RVC_MASK_C_NOP 0xffff
+
#define __INSN_LENGTH_MASK _UL(0x3)
#define __INSN_LENGTH_GE_32 _UL(0x3)
#define __INSN_OPCODE_MASK _UL(0x7F)
@@ -262,6 +271,8 @@ __RISCV_INSN_FUNCS(c_ebreak, RVC_MASK_C_EBREAK, RVC_MATCH_C_EBREAK)
__RISCV_INSN_FUNCS(ebreak, RVG_MASK_EBREAK, RVG_MATCH_EBREAK)
__RISCV_INSN_FUNCS(sret, RVG_MASK_SRET, RVG_MATCH_SRET)
__RISCV_INSN_FUNCS(fence, RVG_MASK_FENCE, RVG_MATCH_FENCE);
+__RISCV_INSN_FUNCS(nop, RVG_MASK_NOP, RVG_MATCH_NOP)
+__RISCV_INSN_FUNCS(c_nop, RVC_MASK_C_NOP, RVC_MATCH_C_NOP)
/* special case to catch _any_ system instruction */
static __always_inline bool riscv_insn_is_system(u32 code)
diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c
index 65d9590bfb..d28408f0b7 100644
--- a/arch/riscv/kernel/probes/decode-insn.c
+++ b/arch/riscv/kernel/probes/decode-insn.c
@@ -44,5 +44,11 @@ riscv_probe_decode_insn(probe_opcode_t *addr, struct arch_probe_insn *api)
RISCV_INSN_SET_SIMULATE(auipc, insn);
RISCV_INSN_SET_SIMULATE(branch, insn);
+ /* Simulate NOP for better performance */
+ RISCV_INSN_SET_SIMULATE(nop, insn);
+#ifdef CONFIG_RISCV_ISA_C
+ RISCV_INSN_SET_SIMULATE(c_nop, insn);
+#endif
+
return INSN_GOOD;
}
diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c
index fa581590c1..3b22d3ad53 100644
--- a/arch/riscv/kernel/probes/simulate-insn.c
+++ b/arch/riscv/kernel/probes/simulate-insn.c
@@ -237,3 +237,17 @@ bool __kprobes simulate_c_beqz(u32 opcode, unsigned long addr, struct pt_regs *r
{
return simulate_c_bnez_beqz(opcode, addr, regs, false);
}
+
+bool __kprobes simulate_nop(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ instruction_pointer_set(regs, addr + 4);
+
+ return true;
+}
+
+bool __kprobes simulate_c_nop(u32 opcode, unsigned long addr, struct pt_regs *regs)
+{
+ instruction_pointer_set(regs, addr + 2);
+
+ return true;
+}
diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h
index 44ebbc444d..7e0936613f 100644
--- a/arch/riscv/kernel/probes/simulate-insn.h
+++ b/arch/riscv/kernel/probes/simulate-insn.h
@@ -29,5 +29,7 @@ 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);
bool simulate_c_beqz(u32 opcode, unsigned long addr, struct pt_regs *regs);
+bool simulate_nop(u32 opcode, unsigned long addr, struct pt_regs *regs);
+bool simulate_c_nop(u32 opcode, unsigned long addr, struct pt_regs *regs);
#endif /* _RISCV_KERNEL_PROBES_SIMULATE_INSN_H */
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2026-08-19 10:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-19 10:14 [PATCH 0/2] riscv: kprobes: simulate nop and c.nop instructions Xiaofeng Yuan
2026-08-19 10:14 ` Xiaofeng Yuan [this message]
2026-08-19 11:54 ` [PATCH 1/2] " Nam Cao
2026-08-19 10:14 ` [PATCH 2/2] riscv: kprobes: add nop and c.nop to the KUnit test Xiaofeng Yuan
2026-08-19 11:58 ` Nam Cao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260819101419.1367-2-yuanxiaofeng@eswincomputing.com \
--to=yuanxiaofeng@eswincomputing.com \
--cc=aou@eecs.berkeley.edu \
--cc=linux-riscv@lists.infradead.org \
--cc=namcaov@gmail.com \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox