All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiri Olsa <jolsa@kernel.org>
To: Masami Hiramatsu <mhiramat@kernel.org>,
	Naveen N Rao <naveen@kernel.org>,
	"David S. Miller" <davem@davemloft.net>
Cc: Peter Zijlstra <peterz@infradead.org>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Jason Baron <jbaron@akamai.com>,
	Alice Ryhl <aliceryhl@google.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Ard Biesheuvel <ardb@kernel.org>,
	Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
	Alan Maguire <almagui@kernel.org>,
	x86@kernel.org, linux-trace-kernel@vger.kernel.org,
	linux-kernel@vger.kernel.org, bpf@vger.kernel.org
Subject: [PATCH 13/13] samples/kprobes: Add batch probe example
Date: Mon,  9 Nov 2026 20:58:27 +0100	[thread overview]
Message-ID: <20261109195827.1091410-1-jolsa@kernel.org> (raw)
In-Reply-To: <20261109194916.1089703-1-jolsa@kernel.org>

Add a sample module that registers kprobes on a batch of
generated functions and calls each function to trigger
the probes.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 kernel/Makefile                       |  3 +
 kernel/kprobes_many.c                 | 81 ++++++++++++++++++++++++
 samples/Kconfig                       |  8 +++
 samples/kprobes/Makefile              |  1 +
 samples/kprobes/kprobe_many_example.c | 91 +++++++++++++++++++++++++++
 5 files changed, 184 insertions(+)
 create mode 100644 kernel/kprobes_many.c
 create mode 100644 samples/kprobes/kprobe_many_example.c

diff --git a/kernel/Makefile b/kernel/Makefile
index 4ff92e24680c..f307b29d4fef 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -99,6 +99,9 @@ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o audit_fsnotify.o audit_tre
 obj-$(CONFIG_GCOV_KERNEL) += gcov/
 obj-$(CONFIG_KCOV) += kcov.o
 obj-$(CONFIG_KPROBES) += kprobes.o
+ifneq ($(CONFIG_SAMPLE_KPROBES_MANY),)
+obj-y += kprobes_many.o
+endif
 obj-$(CONFIG_FAIL_FUNCTION) += fail_function.o
 obj-$(CONFIG_KGDB) += debug/
 obj-$(CONFIG_DETECT_HUNG_TASK) += hung_task.o
diff --git a/kernel/kprobes_many.c b/kernel/kprobes_many.c
new file mode 100644
index 000000000000..1c31a63309bf
--- /dev/null
+++ b/kernel/kprobes_many.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+ * Generated functions for the batch kprobe sample.
+ */
+
+#include <linux/annotate.h>
+#include <linux/export.h>
+#include <linux/linkage.h>
+#include <linux/stringify.h>
+#include <asm/asm.h>
+#include <asm/ibt.h>
+
+#define KPROBE_MANY_MAX_FUNCS	50000
+#define KPROBE_MANY_FUNC_SIZE	24
+#define KPROBE_MANY_PROBE_OFF	8
+
+#if defined(CONFIG_MITIGATION_RETHUNK)
+#define KPROBE_MANY_RET		ASM_RET
+#define KPROBE_MANY_RET_SIZE	5
+#elif defined(CONFIG_MITIGATION_SLS)
+#define KPROBE_MANY_RET		ASM_RET
+#define KPROBE_MANY_RET_SIZE	2
+#else
+#define KPROBE_MANY_RET		ASM_RET
+#define KPROBE_MANY_RET_SIZE	1
+#endif
+
+#define KPROBE_MANY_TAIL_NOPS \
+	(KPROBE_MANY_FUNC_SIZE - KPROBE_MANY_PROBE_OFF - 7 - \
+	 KPROBE_MANY_RET_SIZE)
+
+extern char kprobes_many_func_0[];
+EXPORT_SYMBOL_GPL(kprobes_many_func_0);
+
+/*
+ * Keep these functions at a fixed size so the sample module can place
+ * probes at the same offset in every function.
+ *
+ * For example, KPROBE_MANY_FUNC kprobes_many_func_0 emits:
+ *
+ * kprobes_many_func_0:		ENDBR
+ * 				NOPS to offset 8
+ * 1:				probe site (offset 8), annotated as NOENDBR
+ * 				7 NOPS for the kprobe optimizer
+ * 				NOPS to fill the function
+ * 				RET
+ *
+ * The NOPS and return sequence keep each function 24 bytes long, including
+ * the ENDBR instruction when enabled.
+ */
+asm (
+	".pushsection .text, \"ax\", @progbits\n"
+	".macro KPROBE_MANY_FUNC name\n"
+	".type \\name, @function\n"
+	"\\name:\n"
+	ASM_ENDBR
+	IBT_NOSEAL("\\name")
+	".rept " __stringify(KPROBE_MANY_PROBE_OFF - ENDBR_INSN_SIZE) "\n"
+	"	nop\n"
+	".endr\n"
+	"1:\n"
+	ASM_ANNOTATE_LABEL(1b, ANNOTYPE_NOENDBR) "\n"
+	".rept 7\n"
+	"	nop\n"
+	".endr\n"
+	".rept " __stringify(KPROBE_MANY_TAIL_NOPS) "\n"
+	"	nop\n"
+	".endr\n"
+	KPROBE_MANY_RET
+	".size \\name, .-\\name\n"
+	".endm\n"
+	".macro KPROBE_MANY_FUNC_LOCAL\n"
+	"KPROBE_MANY_FUNC kprobes_many_func_\\@\n"
+	".endm\n"
+	".globl kprobes_many_func_0\n"
+	"KPROBE_MANY_FUNC kprobes_many_func_0\n"
+	".rept " __stringify(KPROBE_MANY_MAX_FUNCS - 1) "\n"
+	"	KPROBE_MANY_FUNC_LOCAL\n"
+	".endr\n"
+	".popsection\n");
diff --git a/samples/Kconfig b/samples/Kconfig
index 00eed83c07df..92a41c5fdbfd 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -80,6 +80,14 @@ config SAMPLE_KRETPROBES
 	default m
 	depends on SAMPLE_KPROBES && KRETPROBES
 
+config SAMPLE_KPROBES_MANY
+	tristate "Build batch kprobe example -- x86 loadable module only"
+	depends on SAMPLE_KPROBES && X86 && m
+	help
+	  This builds a sample module that registers kprobes in the middle of
+	  50000 generated x86 kernel functions using the batch kprobe
+	  interface.
+
 config SAMPLE_HW_BREAKPOINT
 	tristate "Build kernel hardware breakpoint examples -- loadable module only"
 	depends on HAVE_HW_BREAKPOINT && m
diff --git a/samples/kprobes/Makefile b/samples/kprobes/Makefile
index e774592718d6..2fd2150e523c 100644
--- a/samples/kprobes/Makefile
+++ b/samples/kprobes/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_SAMPLE_KPROBES) += kprobe_example.o
 obj-$(CONFIG_SAMPLE_KRETPROBES) += kretprobe_example.o
+obj-$(CONFIG_SAMPLE_KPROBES_MANY) += kprobe_many_example.o
diff --git a/samples/kprobes/kprobe_many_example.c b/samples/kprobes/kprobe_many_example.c
new file mode 100644
index 000000000000..5a58908c840c
--- /dev/null
+++ b/samples/kprobes/kprobe_many_example.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Sample module that registers a batch of kprobes in generated kernel
+ * functions.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/module.h>
+
+#define KPROBE_MANY_MAX_FUNCS 50000
+#define KPROBE_MANY_FUNC_SIZE 24
+#define KPROBE_MANY_PROBE_OFF 8
+
+extern char kprobes_many_func_0[];
+
+static unsigned int nr_functions = 20000;
+module_param(nr_functions, uint, 0444);
+MODULE_PARM_DESC(nr_functions, "number of generated functions to probe (1-50000)");
+
+static struct kprobe probes[KPROBE_MANY_MAX_FUNCS];
+static struct kprobe *probe_ptrs[KPROBE_MANY_MAX_FUNCS];
+static unsigned int kprobe_many_pre_handler_count;
+
+static int __kprobes kprobe_many_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_many_pre_handler_count++;
+	return 0;
+}
+
+/* The generated assembly functions have no CFI type metadata. */
+static noinline __nocfi void
+kprobe_many_call_function(char *functions, unsigned int index)
+{
+	void (*function)(void);
+
+	function = (void (*)(void))(functions + index * KPROBE_MANY_FUNC_SIZE);
+	function();
+}
+
+static int __init kprobe_many_init(void)
+{
+	char *functions;
+	unsigned int i;
+	unsigned int hit_count;
+	int ret;
+
+	if (!nr_functions || nr_functions > KPROBE_MANY_MAX_FUNCS)
+		return -EINVAL;
+
+	functions = kprobes_many_func_0;
+
+	for (i = 0; i < nr_functions; i++) {
+		probes[i].addr = (void *)(functions + i * KPROBE_MANY_FUNC_SIZE +
+					  KPROBE_MANY_PROBE_OFF);
+		probes[i].pre_handler = kprobe_many_pre_handler;
+		probe_ptrs[i] = &probes[i];
+	}
+
+	ret = register_kprobes(probe_ptrs, nr_functions);
+	if (ret) {
+		pr_err("register_kprobes failed, returned %d\n", ret);
+		return ret;
+	}
+
+	pr_info("registered %u probes\n", nr_functions);
+	for (i = 0; i < nr_functions; i++)
+		kprobe_many_call_function(functions, i);
+
+	hit_count = kprobe_many_pre_handler_count;
+	if (hit_count != nr_functions) {
+		pr_err("pre-handler triggered %u times, expected %u\n",
+		       hit_count, nr_functions);
+		unregister_kprobes(probe_ptrs, nr_functions);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __exit kprobe_many_exit(void)
+{
+	unregister_kprobes(probe_ptrs, nr_functions);
+	pr_info("unregistered %u probes\n", nr_functions);
+}
+
+module_init(kprobe_many_init);
+module_exit(kprobe_many_exit);
+
+MODULE_DESCRIPTION("sample module registering kprobes in generated functions");
+MODULE_LICENSE("GPL");
-- 
2.43.0


  parent reply	other threads:[~2026-11-09 19:58 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 19:49 [PATCH 00/13] kprobes: Reduce registration and optimization lookup costs Jiri Olsa
2026-11-09 19:49 ` [PATCH 01/13] static_call: Index code text reservation lookups Jiri Olsa
2026-11-12  8:27   ` Peter Zijlstra
2026-11-12 18:33     ` Jiri Olsa
2026-11-12  8:34   ` Peter Zijlstra
2026-11-12 18:33     ` Jiri Olsa
2026-11-12  9:07   ` Peter Zijlstra
2026-11-12 10:11     ` Peter Zijlstra
2026-11-12 18:33       ` Jiri Olsa
2026-11-09 19:49 ` [PATCH 02/13] jump_label: Index " Jiri Olsa
2026-11-12  8:33   ` Peter Zijlstra
2026-11-12 18:33     ` Jiri Olsa
2026-11-09 19:49 ` [PATCH 03/13] jump_label/x86: Avoid decoding instructions for jump entry size Jiri Olsa
2026-11-12  8:39   ` Peter Zijlstra
2026-11-12 18:33     ` Jiri Olsa
2026-11-09 19:55 ` [PATCH 04/13] kprobes: Maintain an rbtree of registered probes Jiri Olsa
2026-11-10  8:12   ` Masami Hiramatsu (Google)
2026-11-10 10:37     ` Jiri Olsa
2026-11-10 15:38       ` Masami Hiramatsu (Google)
2026-11-11 10:49         ` Jiri Olsa
2026-11-10 23:45   ` sashiko-bot
2026-11-12  8:50   ` Peter Zijlstra
2026-11-09 19:56 ` [PATCH 05/13] kprobes: Add an iterator for address ranges Jiri Olsa
2026-11-09 19:56 ` [PATCH 06/13] kprobes: Add an address iterator for probe lookup Jiri Olsa
2026-11-09 19:56 ` [PATCH 07/13] kprobes: Use kprobe iterator in get_optimized_kprobe Jiri Olsa
2026-11-09 19:57 ` [PATCH 08/13] x86/kprobes: Use kprobe iterator in __recover_optprobed_insn Jiri Olsa
2026-11-09 19:57 ` [PATCH 09/13] x86/kprobes: Use kprobe iterator in arch_check_optimized_kprobe Jiri Olsa
2026-11-11  0:17   ` sashiko-bot
2026-11-09 19:57 ` [PATCH 10/13] x86/kprobes: Use kprobe address iterator in can_optimize Jiri Olsa
2026-11-09 19:57 ` [PATCH 11/13] x86/kprobes: Use kprobe address iterator in can_probe Jiri Olsa
2026-11-09 19:58 ` [PATCH 12/13] x86/kprobes: Use kprobe address iterator in in copy_optimized_instructions Jiri Olsa
2026-11-09 19:58 ` Jiri Olsa [this message]
2026-11-11  0:49   ` [PATCH 13/13] samples/kprobes: Add batch probe example sashiko-bot
2026-11-11  2:20   ` kernel test robot

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=20261109195827.1091410-1-jolsa@kernel.org \
    --to=jolsa@kernel.org \
    --cc=aliceryhl@google.com \
    --cc=almagui@kernel.org \
    --cc=ardb@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=davem@davemloft.net \
    --cc=jbaron@akamai.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=naveen@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@kernel.org \
    --cc=x86@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.