diff --git a/kernel/bpf/preload/bpf_preload_kern.c b/kernel/bpf/preload/bpf_preload_kern.c
index c6d97872225b..048bca3ba499 100644
--- a/kernel/bpf/preload/bpf_preload_kern.c
+++ b/kernel/bpf/preload/bpf_preload_kern.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+/* THIS FILE IS AUTOGENERATED! */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/kernel/bpf/preload/iterators/Makefile b/kernel/bpf/preload/iterators/Makefile
index d36a822d3e16..9dcad1c5c44b 100644
--- a/kernel/bpf/preload/iterators/Makefile
+++ b/kernel/bpf/preload/iterators/Makefile
@@ -35,17 +35,20 @@ endif
 
 .PHONY: all clean
 
-all: iterators.lskel.h
+all: iterators.lskel.h bpf_preload_kern.c
 
 clean:
 	$(call msg,CLEAN)
 	$(Q)rm -rf $(OUTPUT) iterators
 
+bpf_preload_kern.c: iterators.lskel.h $(BPFTOOL)
+	$(call msg,GEN-PRELOAD,$@)
+	$(Q)$(BPFTOOL) gen module iterators/iterators.lskel.h $< > ../$@
+
 iterators.lskel.h: $(OUTPUT)/iterators.bpf.o | $(BPFTOOL)
 	$(call msg,GEN-SKEL,$@)
 	$(Q)$(BPFTOOL) gen skeleton -L -P $< > $@
 
-
 $(OUTPUT)/iterators.bpf.o: iterators.bpf.c $(BPFOBJ) | $(OUTPUT)
 	$(call msg,BPF,$@)
 	$(Q)$(CLANG) -g -O2 -target bpf $(INCLUDES)			      \
diff --git a/tools/bpf/bpftool/Documentation/bpftool-gen.rst b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
index 74bbefa28212..6d29d2b1e4e2 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-gen.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
@@ -27,6 +27,7 @@ GEN COMMANDS
 |	**bpftool** **gen skeleton** *FILE* [**name** *OBJECT_NAME*]
 |	**bpftool** **gen subskeleton** *FILE* [**name** *OBJECT_NAME*]
 |	**bpftool** **gen min_core_btf** *INPUT* *OUTPUT* *OBJECT* [*OBJECT*...]
+|	**bpftool** **gen module** *FILE*
 |	**bpftool** **gen help**
 
 DESCRIPTION
@@ -195,6 +196,13 @@ DESCRIPTION
 
 		  Check examples bellow for more information how to use it.
 
+	**bpftool** **gen module** *FILE*
+		  Generate the code of a kernel module including the light
+		  skeleton of an eBPF program to preload. The only variable part
+		  is the path of the light skeleton. All kernel modules call
+		  load_skel() and free_objs_and_skel() respectively in the init
+		  and fini module entrypoints.
+
 	**bpftool gen help**
 		  Print short help message.
 
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 6e433e86fb26..82e8716fd3ad 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -1019,6 +1019,10 @@ _bpftool()
                     _filedir
                     return 0
                     ;;
+                module)
+                    _filedir
+                    return 0
+                    ;;
                 *)
                     [[ $prev == $object ]] && \
                         COMPREPLY=( $( compgen -W 'object skeleton subskeleton help min_core_btf' -- "$cur" ) )
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index af939183f57a..77ab78884285 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -1898,6 +1898,35 @@ static int do_object(int argc, char **argv)
 	return err;
 }
 
+static int do_module(int argc, char **argv)
+{
+	const char *skeleton_file;
+
+	if (!REQ_ARGS(1)) {
+		usage();
+		return -1;
+	}
+
+	skeleton_file = GET_ARG();
+
+	codegen("\
+		\n\
+		// SPDX-License-Identifier: GPL-2.0			    \n\
+		/* THIS FILE IS AUTOGENERATED! */			    \n\
+		#define pr_fmt(fmt) KBUILD_MODNAME \": \" fmt		    \n\
+		#include <linux/init.h>					    \n\
+		#include <linux/module.h>				    \n\
+		#include <linux/bpf_preload.h>				    \n\
+		#include \"%s\"						    \n\
+		\n\
+		late_initcall(load_skel);				    \n\
+		module_exit(free_objs_and_skel);			    \n\
+		MODULE_LICENSE(\"GPL\");				    \n\
+		", skeleton_file);
+
+	return 0;
+}
+
 static int do_help(int argc, char **argv)
 {
 	if (json_output) {
@@ -1910,6 +1939,7 @@ static int do_help(int argc, char **argv)
 		"       %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
 		"       %1$s %2$s subskeleton FILE [name OBJECT_NAME]\n"
 		"       %1$s %2$s min_core_btf INPUT OUTPUT OBJECT [OBJECT...]\n"
+		"       %1$s %2$s module SKELETON_FILE\n"
 		"       %1$s %2$s help\n"
 		"\n"
 		"       " HELP_SPEC_OPTIONS " |\n"
@@ -2508,6 +2538,7 @@ static const struct cmd cmds[] = {
 	{ "skeleton",		do_skeleton },
 	{ "subskeleton",	do_subskeleton },
 	{ "min_core_btf",	do_min_core_btf},
+	{ "module",		do_module},
 	{ "help",		do_help },
 	{ 0 }
 };
