From: Davidlohr Bueso <dave@stgolabs.net>
To: pjw@kernel.org, palmer@dabbelt.com, aou@eecs.berkeley.edu
Cc: oleg@redhat.com, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org, dave@stgolabs.net
Subject: [PATCH] riscv: uprobes: Avoid redundant icache flushes for the XOL slot
Date: Fri, 16 Oct 2026 13:30:09 -0700 [thread overview]
Message-ID: <20261016203009.745042-1-dave@stgolabs.net> (raw)
arch_uprobe_copy_ixol() unconditionally calls flush_icache_range(),
which has no range form on riscv and is a flush_icache_all(). It
runs once per single-step, as the generic code allocates and frees
an out-of-line slot around each one.
The allocator hands out the lowest free slot and the free path leaves
the slot contents alone, so a hot probe keeps getting the same slot
back holding the instruction it already wrote there. Rewriting it
costs a broadcast for nothing.
Return early when the slot already holds this instruction and its
breakpoint, similar to commit bdf94836c22a ("arm64: uprobes: Optimize
cache flushes for xol slot"). arm64 can compare against the source,
but riscv appends an ebreak after the opcode, so compare the
instruction and that breakpoint word instead.
Measured with the selftests/bpf bench on a SiFive P550, with one
producer pinned to a hart:
before after
trig-uprobe-nop 0.075 M/s 0.514 M/s 6.9x
trig-uprobe-push 0.079 M/s 0.425 M/s 5.4x
trig-uprobe-ret 0.075 M/s 0.514 M/s 6.9x
trig-uprobe-multi-nop 0.079 M/s 0.548 M/s 6.9x
trig-uprobe-multi-push 0.078 M/s 0.545 M/s 7.0x
trig-uprobe-multi-ret 0.081 M/s 0.549 M/s 6.8x
The uretprobe variants gain 4.8x to 6.0x.
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
arch/riscv/kernel/probes/uprobes.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/kernel/probes/uprobes.c b/arch/riscv/kernel/probes/uprobes.c
index eb177d0ce8ab..44e566f6b75b 100644
--- a/arch/riscv/kernel/probes/uprobes.c
+++ b/arch/riscv/kernel/probes/uprobes.c
@@ -168,15 +168,26 @@ void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
void *kaddr = kmap_local_page(page);
void *dst = kaddr + (vaddr & ~PAGE_MASK);
unsigned long start = (unsigned long)dst;
+ unsigned long insn_len;
+
+ insn_len = vaddr ? GET_INSN_LENGTH(*(probe_opcode_t *)src) : len;
+
+ /*
+ * Slots are reused without being cleared, so a hot probe usually gets
+ * one back already holding this instruction and its breakpoint. Skip
+ * the rewrite and the flush then.
+ */
+ if (!memcmp(dst, src, insn_len) &&
+ (!vaddr || *(uprobe_opcode_t *)(dst + insn_len) == __BUG_INSN_32))
+ goto done;
memcpy(dst, src, len);
/* Add ebreak behind opcode to simulate singlestep */
- if (vaddr) {
- dst += GET_INSN_LENGTH(*(probe_opcode_t *)src);
- *(uprobe_opcode_t *)dst = __BUG_INSN_32;
- }
+ if (vaddr)
+ *(uprobe_opcode_t *)(dst + insn_len) = __BUG_INSN_32;
flush_icache_range(start, start + len);
+done:
kunmap_local(kaddr);
}
--
2.39.5
next reply other threads:[~2026-10-16 20:30 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 20:30 Davidlohr Bueso [this message]
2026-11-06 14:27 ` Davidlohr Bueso
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=20261016203009.745042-1-dave@stgolabs.net \
--to=dave@stgolabs.net \
--cc=aou@eecs.berkeley.edu \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=oleg@redhat.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
all inboxes | Powered by JetHome®