Linux kbuild/kconfig development
 help / color / mirror / Atom feed
* [PATCH v2 04/19] build: Add ELF marker for crypto-objs-m modules
From: Jay Wang @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto, Masahiro Yamada,
	linux-kbuild
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Hazem Mohamed Abuelfotoh, Bjoern Doebel, Martin Pohlack,
	Benjamin Herrenschmidt, Nathan Chancellor, Nicolas Schier,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H . Peter Anvin, Luis Chamberlain,
	Petr Pavlu, Daniel Gomez, Sami Tolvanen, David Howells,
	David Woodhouse, Jarkko Sakkinen, Ignat Korchagin, Lukas Wunner,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-arm-kernel, x86, linux-modules
In-Reply-To: <20260418002032.2877-1-wanjay@amazon.com>

Previously, crypto-objs-$(CONFIG_*) behavior depends on the config value.
When CONFIG_*=y, crypto is built into fips140.ko. When CONFIG_*=m, crypto
is already built as a separate module (e.g., aes.ko), so previous patches
do not affect such modules.

This patch adds an ELF marker to identify modules built with CONFIG_*=m
so they can be distinguished as part of the CONFIG_CRYPTO_FIPS140_EXTMOD
framework. This gives module loaders a way to tell the module is included
in crypto-objs-m.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/fips140/fips140-crypto-module-marker.h |  8 ++++++++
 scripts/Makefile.build                        | 15 +++++++++++++++
 2 files changed, 23 insertions(+)
 create mode 100644 crypto/fips140/fips140-crypto-module-marker.h

diff --git a/crypto/fips140/fips140-crypto-module-marker.h b/crypto/fips140/fips140-crypto-module-marker.h
new file mode 100644
index 0000000000000..eadca087cee20
--- /dev/null
+++ b/crypto/fips140/fips140-crypto-module-marker.h
@@ -0,0 +1,8 @@
+#ifndef _FIPS140_CRYPTO_MODULE_MARKER_H
+#define _FIPS140_CRYPTO_MODULE_MARKER_H
+
+/* Crypto module marker - automatically included for crypto-objs-m modules */
+static const char __fips140_crypto_marker[] 
+    __attribute__((section(".fips140_crypto_marker"), used)) = "FIPS140_CRYPTO_OBJS_M";
+
+#endif /* _FIPS140_CRYPTO_MODULE_MARKER_H */
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index cf021ad77e153..685d9b8fcbf4a 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -69,6 +69,7 @@ obj-m += $(crypto-objs-m)
 ifndef CONFIG_CRYPTO_FIPS140_EXTMOD
 obj-y += $(crypto-objs-y)
 crypto-objs-y :=
+crypto-objs-m := $(filter-out $(crypto-objs-y),$(crypto-objs-m))
 endif
 
 # When an object is listed to be built compiled-in and modular,
@@ -131,6 +132,7 @@ multi-obj-m := $(call multi-search, $(obj-m), .o, -objs -y -m)
 multi-obj-ym := $(multi-obj-y) $(multi-obj-m)
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
 multi-crypto-objs-y := $(call multi-search, $(crypto-objs-y), .o, -objs -y)
+multi-crypto-objs-m := $(call multi-search, $(crypto-objs-m), .o, -objs -y -m)
 endif
 
 # Replace multi-part objects by their individual parts,
@@ -139,6 +141,7 @@ real-obj-y := $(call real-search, $(obj-y), .o, -objs -y)
 real-obj-m := $(call real-search, $(obj-m), .o, -objs -y -m)
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
 real-crypto-objs-y := $(strip $(call real-search, $(crypto-objs-y), .o, -objs -y))
+real-crypto-objs-m := $(strip $(call real-search, $(crypto-objs-m), .o, -objs -y -m))
 endif
 
 always-y += $(always-m)
@@ -166,11 +169,13 @@ real-obj-y	:= $(addprefix $(obj)/, $(real-obj-y))
 real-obj-m	:= $(addprefix $(obj)/, $(real-obj-m))
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
 real-crypto-objs-y := $(addprefix $(obj)/, $(real-crypto-objs-y))
+real-crypto-objs-m := $(addprefix $(obj)/, $(real-crypto-objs-m))
 endif
 multi-obj-m	:= $(addprefix $(obj)/, $(multi-obj-m))
 subdir-ym	:= $(addprefix $(obj)/, $(subdir-ym))
 ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
 multi-crypto-objs-y := $(addprefix $(obj)/, $(multi-crypto-objs-y))
+multi-crypto-objs-m := $(addprefix $(obj)/, $(multi-crypto-objs-m))
 endif
 endif
 
@@ -578,6 +583,16 @@ $(multi-crypto-objs-y): %.o: %.mod FORCE
 $(call multi_depend, $(multi-crypto-objs-y), .o, -objs -y -m)
 endif
 endif
+
+# Individual object compilation with version-specific flags
+$(real-crypto-objs-m): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1 -include $(srctree)/crypto/fips140/fips140-crypto-module-marker.h
+
+# Also set flags for individual objects that make up composite crypto objects
+$(foreach obj,$(multi-crypto-objs-m),$($(obj:.o=-y))): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1
+$(foreach obj,$(multi-crypto-objs-m),$($(obj:.o=-objs))): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1
+
+# Multi-part crypto objects
+$(multi-crypto-objs-m): private KBUILD_CFLAGS += -DFIPS140_CRYPTO_OBJS_M=1 -include $(srctree)/crypto/fips140/fips140-crypto-module-marker.h
 endif
 # This is a list of build artifacts from the current Makefile and its
 # sub-directories. The timestamp should be updated when any of the member files.
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 03/19] build: special compilation rule for building the standalone crypto module
From: Jay Wang @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto, Masahiro Yamada,
	linux-kbuild
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Hazem Mohamed Abuelfotoh, Bjoern Doebel, Martin Pohlack,
	Benjamin Herrenschmidt, Nathan Chancellor, Nicolas Schier,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H . Peter Anvin, Luis Chamberlain,
	Petr Pavlu, Daniel Gomez, Sami Tolvanen, David Howells,
	David Woodhouse, Jarkko Sakkinen, Ignat Korchagin, Lukas Wunner,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-arm-kernel, x86, linux-modules
In-Reply-To: <20260418002032.2877-1-wanjay@amazon.com>

Add special build rules to redirect builtin crypto algorithms into a
standalone module `fips140.ko` instead of the main kernel, by introducing
a new crypto-objs-y compilation rule that collects crypto objects to
fips140.ko when CONFIG_CRYPTO_FIPS140_EXTMOD is enabled. Details as below:

Originally, builtin crypto (i.e., which specified by
CONFIG_CRYPTO_{NAME}=y) are compiled into main kernel by default. On the
contrary, this standalone crypto module feature requires compiling builtin
crypto into modules while ensuring such cryptos are not included into main
kernel anymore.

A naive way is to have a separate makefile containing all compilation
rules for all cryptos for such standalone module, but such makefile could
be too large to be scalable to arbitrary CONFIG_CRYPTO_{NAME}
configuration, plus, this method cannot ensure the builtin crypto is
completely removed from main kernel either.

To tackle this challenge, this patch automates object linking redirection by
introducing special build logic for kernel crypto subsystem. Specifically:

First, to automatically collect crypto objects file while preserving the
original compilation setting (such as flags, headers, path etc), it
introduces a specific compilation rule `crypto-objs-y += *.o` that replaces
the original rule `obj-y += *.o` in the crypto subsystem Makefile. As a
result, when the standalone crypto module feature is turned on, for any
crypto chosen to be builtin (e.g., crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2)
+= *.o where CONFIG_CRYPTO_SKCIPHER2=y), it will be automatically collected
and linked into a final object binary: `fips140.o`, with special
compilation flag (-DFIPS_MODULE=1) to tell each individual obj files
compiled in a specific way (will be used in later patches for generating
pluggable interface on main kernel side and module side respectively from
same source code). The implementation details are: it refers to the
methodology of how obj-y collecting method of vmlinux.o, it places the
`crypto-objs-y` rule in scripts/Makefile.build that will be run in each
directory Makefile, and create crypto-module.a that comprises all captured
`crypto-objs-y += *.o` under same folders. In its parent folders, such
crypto-module.a will be included into parents' crypto-module.a recursively
and eventually used to generate final fips140.o.

Second, to generate the final kernel module fips140.ko with the above
fips140.o, A naïve approach would be to directly inject the fips140.ko
module build into the existing modules generation pipeline (i.e., `make
modules`) by providing our pre-generated fips140.o. However, we choose
not to do this because it would create a circular make rule dependency
(which is invalid in Makefiles and causes build failures), resulting in
mutual dependencies between the modules and vmlinux targets (i.e.,
`modules:vmlinux` and `vmlinux:modules` at the same time).
This happens for the following reasons:

1. Since we will later embed fips140.ko into the final kernel image (as
   described in the later patch), we must make vmlinux depend on
   fips140.ko. In other words: vmlinux: fips140.ko.
2. When the kernel is built with CONFIG_DEBUG_INFO_BTF_MODULES=y, it
   requires: `modules: vmlinux`. This is because
   `CONFIG_DEBUG_INFO_BTF_MODULES=y` will take vmlinux as input to
   generate a `BTF` info for the module, and insert such info into the
   `.ko` module by default.
3. If we choose to inject fips140.ko into make modules, this would
   create a make rule dependency: `fips140.ko: modules`. Combined with
   items 1 and 2, this eventually creates an invalid circular dependency
   between vmlinux and modules.

Due to these reasons, the design choice is to use a separate make
pipeline (defined as `fips140-ready` in the Makefile). This new
pipeline reuses the same module generation scripts used by make
modules but adds additional logic in
scripts/Makefile.{modfinal|modinst|modpost} and scripts/mod/modpost.c
to handle module symbol generation and verification correctly. In such
pipeline, to eliminate the make rule dependency of
`fips140.ko:vmlinux` which imposed by `CONFIG_DEBUG_INFO_BTF_MODULES=y`,
we temporarily not generating BTF info for fips140.ko in this patch,
where the BTF info for fips140.ko will be generated in later patch in
a special manner.

Finally, with these special build rules, crypto/fips140/fips140.ko is generated.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 Makefile                  |  34 +++++++++++-
 crypto/fips140/Makefile   |   4 +-
 scripts/Makefile.build    | 109 +++++++++++++++++++++++++++++++++++++-
 scripts/Makefile.modfinal |  22 ++++++++
 scripts/Makefile.modinst  |  13 ++++-
 scripts/Makefile.modpost  |  25 +++++++++
 scripts/mod/modpost.c     |  24 +++++++--
 7 files changed, 223 insertions(+), 8 deletions(-)

diff --git a/Makefile b/Makefile
index 54e1ae6020001..45218f2b7f51f 100644
--- a/Makefile
+++ b/Makefile
@@ -1329,6 +1329,38 @@ PHONY += vmlinux
 #  vmlinux: private export LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
 vmlinux: private _LDFLAGS_vmlinux := $(LDFLAGS_vmlinux)
 vmlinux: export LDFLAGS_vmlinux = $(_LDFLAGS_vmlinux)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+vmlinux: fips140-ready
+# Ensure fips140.ko is built before embedding
+fips140-ready: crypto/fips140/fips140.o crypto/fips140/.fips140.order crypto/fips140/fips140.mod vmlinux.o | modules_prepare
+	$(Q)$(MAKE) KBUILD_MODULES= -f $(srctree)/scripts/Makefile.modpost
+	$(Q)$(MAKE) KBUILD_MODULES=y crypto-module-gen=1 -f $(srctree)/scripts/Makefile.modpost
+ifneq ($(KBUILD_MODPOST_NOFINAL),1)
+	$(Q)$(MAKE) KBUILD_MODULES=y crypto-module-gen=1 -f $(srctree)/scripts/Makefile.modfinal
+endif
+	@:
+
+# Generate fips140.o from crypto-module.a files
+crypto/fips140/fips140.o: crypto-module.a FORCE
+	$(call if_changed,ld_fips140)
+crypto/fips140/.fips140.order: crypto/fips140/fips140.o
+	echo "crypto/fips140/fips140.o" > $@
+crypto/fips140/fips140.mod: crypto-module.a FORCE
+	$(call if_changed,fips140_mod)
+crypto/fips140/.fips140.symvers: fips140-ready
+	@:
+modpost: crypto/fips140/.fips140.symvers
+quiet_cmd_ld_fips140 = LD [M]  $@
+      cmd_ld_fips140 = $(LD) -r $(KBUILD_LDFLAGS) $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) --build-id=none --whole-archive $< --no-whole-archive -o $@
+
+cmd_fips140_mod = ar -t $< > $@
+
+# Add to targets so .cmd file is included
+targets += crypto/fips140/fips140.o crypto/fips140/fips140.mod
+
+# Bridge rule: crypto-module.a depends on directory build (like built-in.a)
+crypto-module.a: . ;
+endif
 vmlinux: vmlinux.o $(KBUILD_LDS) modpost
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.vmlinux
 
@@ -2136,7 +2168,7 @@ prepare: outputmakefile
 # Error messages still appears in the original language
 PHONY += $(build-dir)
 $(build-dir): prepare
-	$(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1 $(single-goals)
+	$(Q)$(MAKE) $(build)=$@ need-builtin=1 need-modorder=1 need-crypto=1 $(single-goals)
 
 clean-dirs := $(addprefix _clean_, $(clean-dirs))
 PHONY += $(clean-dirs) clean
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
index 364ef52c190fb..3b4a74ccf41ec 100644
--- a/crypto/fips140/Makefile
+++ b/crypto/fips140/Makefile
@@ -1,3 +1,5 @@
 
+crypto-objs-y += \
+	fips140-module.o 
 
-	
\ No newline at end of file
+clean-files:= .fips140.order .fips140.symvers
\ No newline at end of file
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 3498d25b15e85..cf021ad77e153 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -29,6 +29,22 @@ ldflags-y  :=
 subdir-asflags-y :=
 subdir-ccflags-y :=
 
+crypto-objs-flags-y := -DFIPS_MODULE=1
+crypto-objs-y :=
+crypto-module-folders := crypto arch/$(ARCH)/crypto lib/crypto certs
+# Global crypto directory checking logic
+# Use relative paths so this works with both in-tree and O= out-of-tree builds
+define is-crypto-related-dir
+$(eval _obj-rel := $(patsubst ./%,%,$(obj)/$(1)))
+$(eval _obj-rel := $(patsubst %/,%,$(_obj-rel)))
+$(eval check-exact := $(filter $(crypto-module-folders),$(_obj-rel)))
+$(eval check-subdir := $(foreach dir,$(crypto-module-folders),$(filter $(dir)/%,$(_obj-rel))))
+$(eval check-ancestor := $(foreach dir,$(crypto-module-folders),$(if $(filter $(_obj-rel)/%,$(dir)),$(_obj-rel))))
+$(eval result := $(strip $(check-exact) $(check-subdir) $(check-ancestor)))
+$(result)
+endef
+is-crypto-related := $(call is-crypto-related-dir, ./)
+
 # Read auto.conf if it exists, otherwise ignore
 -include $(objtree)/include/config/auto.conf
 
@@ -45,6 +61,16 @@ KBUILD_RUSTFLAGS += $(subdir-rustflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+
+# Add crypto-objs-m to obj-m unconditionally
+obj-m += $(crypto-objs-m)
+
+# When CRYPTO_FIPS140_EXTMOD is not defined, add crypto-objs-y to obj-y and clear crypto-objs-y
+ifndef CONFIG_CRYPTO_FIPS140_EXTMOD
+obj-y += $(crypto-objs-y)
+crypto-objs-y :=
+endif
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 obj-m := $(filter-out $(obj-y),$(obj-m))
@@ -71,12 +97,27 @@ else
 obj-m := $(filter-out %/, $(obj-m))
 endif
 
+# Capture obj-y directories before conversion
+obj-y-dirs := $(filter %/, $(obj-y))
+
 ifdef need-builtin
 obj-y		:= $(patsubst %/, %/built-in.a, $(obj-y))
 else
 obj-y		:= $(filter-out %/, $(obj-y))
 endif
 
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+# Add obj-y directories to crypto-objs-y only if they are crypto-related
+crypto-objs-y	+= $(strip $(foreach dir,$(obj-y-dirs),$(if $(strip $(call is-crypto-related-dir,$(patsubst %/,%,$(dir)))),$(dir))))
+
+ifdef need-crypto
+crypto-objs-y	:= $(patsubst %/, %/crypto-module.a, $(crypto-objs-y))
+else
+crypto-objs-y	:= $(filter-out %/, $(crypto-objs-y))
+endif
+endif
+
+
 # Expand $(foo-objs) $(foo-y) etc. by replacing their individuals
 suffix-search = $(strip $(foreach s, $3, $($(1:%$(strip $2)=%$s))))
 # List composite targets that are constructed by combining other targets
@@ -88,11 +129,17 @@ real-search = $(foreach m, $1, $(if $(call suffix-search, $m, $2, $3 -), $(call
 multi-obj-y := $(call multi-search, $(obj-y), .o, -objs -y)
 multi-obj-m := $(call multi-search, $(obj-m), .o, -objs -y -m)
 multi-obj-ym := $(multi-obj-y) $(multi-obj-m)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+multi-crypto-objs-y := $(call multi-search, $(crypto-objs-y), .o, -objs -y)
+endif
 
 # Replace multi-part objects by their individual parts,
 # including built-in.a from subdirectories
 real-obj-y := $(call real-search, $(obj-y), .o, -objs -y)
 real-obj-m := $(call real-search, $(obj-m), .o, -objs -y -m)
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+real-crypto-objs-y := $(strip $(call real-search, $(crypto-objs-y), .o, -objs -y))
+endif
 
 always-y += $(always-m)
 
@@ -117,8 +164,14 @@ obj-m		:= $(addprefix $(obj)/, $(obj-m))
 lib-y		:= $(addprefix $(obj)/, $(lib-y))
 real-obj-y	:= $(addprefix $(obj)/, $(real-obj-y))
 real-obj-m	:= $(addprefix $(obj)/, $(real-obj-m))
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+real-crypto-objs-y := $(addprefix $(obj)/, $(real-crypto-objs-y))
+endif
 multi-obj-m	:= $(addprefix $(obj)/, $(multi-obj-m))
 subdir-ym	:= $(addprefix $(obj)/, $(subdir-ym))
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+multi-crypto-objs-y := $(addprefix $(obj)/, $(multi-crypto-objs-y))
+endif
 endif
 
 ifndef obj
@@ -137,7 +190,9 @@ endif
 # subdir-builtin and subdir-modorder may contain duplications. Use $(sort ...)
 subdir-builtin := $(sort $(filter %/built-in.a, $(real-obj-y)))
 subdir-modorder := $(sort $(filter %/modules.order, $(obj-m)))
-
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+subdir-crypto := $(sort $(filter %/crypto-module.a, $(real-crypto-objs-y)))
+endif
 targets-for-builtin := $(extra-y)
 
 ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
@@ -148,6 +203,16 @@ ifdef need-builtin
 targets-for-builtin += $(obj)/built-in.a
 endif
 
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+targets-for-crypto :=
+ifneq ($(is-crypto-related),)
+ifdef need-crypto
+targets-for-crypto += $(obj)/crypto-module.a
+endif
+targets += $(obj)/crypto-module.a
+endif
+endif
+
 targets-for-modules := $(foreach x, o mod, \
 				$(patsubst %.o, %.$x, $(filter %.o, $(obj-m))))
 
@@ -222,6 +287,12 @@ $(obj)/%.ll: $(obj)/%.c FORCE
 
 is-single-obj-m = $(and $(part-of-module),$(filter $@, $(obj-m)),y)
 
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+is-single-crypto-obj-y = $(and $(part-of-module),$(filter $@, $(real-crypto-objs-y)),y)
+else
+is-single-crypto-obj-y =
+endif
+
 ifdef CONFIG_MODVERSIONS
 # When module versioning is enabled the following steps are executed:
 # o compile a <file>.o from <file>.c
@@ -277,7 +348,7 @@ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
 is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(target-stem).o)$(OBJECT_FILES_NON_STANDARD)n),$(is-kernel-object))
 
 ifdef CONFIG_OBJTOOL
-$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
+$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(or $(is-single-obj-m),$(is-single-crypto-obj-y)),y))
 endif
 
 ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
@@ -435,6 +506,9 @@ $(obj)/%.o: $(obj)/%.S FORCE
 
 targets += $(filter-out $(subdir-builtin), $(real-obj-y))
 targets += $(filter-out $(subdir-modorder), $(real-obj-m))
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+targets += $(filter-out $(subdir-crypto), $(real-crypto-objs-y))
+endif
 targets += $(lib-y) $(always-y)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
@@ -461,6 +535,9 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
 # To build objects in subdirs, we need to descend into the directories
 $(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
 $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+$(subdir-crypto): $(obj)/%/crypto-module.a: $(obj)/% ;
+endif
 
 #
 # Rule to compile a set of .o files into one .a file (without symbol table)
@@ -476,6 +553,32 @@ quiet_cmd_ar_builtin = AR      $@
 $(obj)/built-in.a: $(real-obj-y) FORCE
 	$(call if_changed,ar_builtin)
 
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifneq ($(is-crypto-related),)
+$(obj)/crypto-module.a: $(real-crypto-objs-y) FORCE
+	$(call if_changed,ar_builtin)
+
+# Set module flags for crypto objects when building crypto-module.a
+ifdef need-crypto
+$(real-crypto-objs-y): private part-of-module := y
+$(real-crypto-objs-y): private modname := fips140
+$(real-crypto-objs-y): private KBUILD_CFLAGS += $(crypto-objs-flags-y)
+
+# Also set flags for individual objects that make up composite crypto objects
+$(foreach obj,$(multi-crypto-objs-y),$($(obj:.o=-y))): private part-of-module := y
+$(foreach obj,$(multi-crypto-objs-y),$($(obj:.o=-y))): private modname := fips140
+$(foreach obj,$(multi-crypto-objs-y),$($(obj:.o=-y))): private KBUILD_CFLAGS += $(crypto-objs-flags-y)
+
+# Multi-part crypto objects
+$(multi-crypto-objs-y): private part-of-module := y
+$(multi-crypto-objs-y): private modname := fips140
+$(multi-crypto-objs-y): private KBUILD_CFLAGS += $(crypto-objs-flags-y)
+$(multi-crypto-objs-y): %.o: %.mod FORCE
+	$(call if_changed_rule,ld_multi_m)
+$(call multi_depend, $(multi-crypto-objs-y), .o, -objs -y -m)
+endif
+endif
+endif
 # This is a list of build artifacts from the current Makefile and its
 # sub-directories. The timestamp should be updated when any of the member files.
 
@@ -548,6 +651,7 @@ $(subdir-ym):
 	$(Q)$(MAKE) $(build)=$@ \
 	need-builtin=$(if $(filter $@/built-in.a, $(subdir-builtin)),1) \
 	need-modorder=$(if $(filter $@/modules.order, $(subdir-modorder)),1) \
+	need-crypto=$(if $(and $(CONFIG_CRYPTO_FIPS140_EXTMOD), $(filter $@/crypto-module.a, $(subdir-crypto))),1) \
 	$(filter $@/%, $(single-subdir-goals))
 
 # Add FORCE to the prerequisites of a target to force it to be always rebuilt.
@@ -571,6 +675,7 @@ endif
 
 $(obj)/: $(if $(KBUILD_BUILTIN), $(targets-for-builtin)) \
 	 $(if $(KBUILD_MODULES), $(targets-for-modules)) \
+	 $(targets-for-crypto) \
 	 $(subdir-ym) $(always-y)
 	@:
 
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index adcbcde16a071..2e087355988ba 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -11,7 +11,15 @@ include $(srctree)/scripts/Kbuild.include
 include $(srctree)/scripts/Makefile.lib
 
 # find all modules listed in modules.order
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(crypto-module-gen),1)
+modules := $(call read-file, crypto/fips140/.fips140.order)
+else
 modules := $(call read-file, modules.order)
+endif
+else
+modules := $(call read-file, modules.order)
+endif
 
 __modfinal: $(modules:%.o=%.ko)
 	@:
@@ -55,12 +63,26 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check),      \
 	printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
 
 # Re-generate module BTFs if either module's .ko or vmlinux changed
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(crypto-module-gen),1)
+%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds FORCE
+	+$(call if_changed,ld_ko_o)
+else
 %.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
 	+$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
 ifdef CONFIG_DEBUG_INFO_BTF_MODULES
 	+$(if $(newer-prereqs),$(call cmd,btf_ko))
 endif
 	+$(call cmd,check_tracepoint)
+endif
+else
+%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
+	+$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
+ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+	+$(if $(newer-prereqs),$(call cmd,btf_ko))
+endif
+	+$(call cmd,check_tracepoint)
+endif
 
 targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
 
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 9ba45e5b32b18..32b6d0986922a 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -28,7 +28,12 @@ $(MODLIB)/modules.order: modules.order FORCE
 	$(call cmd,install_modorder)
 
 quiet_cmd_install_modorder = INSTALL $@
-      cmd_install_modorder = sed 's:^\(.*\)\.o$$:kernel/\1.ko:' $< > $@
+      cmd_install_modorder = sed 's:^\(.*\)\.o$$:kernel/\1.ko:' $< > $@; \
+	$(if $(CONFIG_CRYPTO_FIPS140_EXTMOD), \
+		if [ -f crypto/fips140/.fips140.order ]; then \
+			sed 's:^\(.*\)\.o$$:kernel/\1.ko:' crypto/fips140/.fips140.order >> $@; \
+		fi \
+	)
 
 # Install modules.builtin(.modinfo,.ranges) even when CONFIG_MODULES is disabled.
 install-y += $(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo)
@@ -42,6 +47,12 @@ endif
 
 modules := $(call read-file, modules.order)
 
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifneq ($(wildcard crypto/fips140/.fips140.order),)
+modules += $(call read-file, crypto/fips140/.fips140.order)
+endif
+endif
+
 ifeq ($(KBUILD_EXTMOD),)
 dst := $(MODLIB)/kernel
 else
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index d7d45067d08b9..18b5a5de74d93 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -51,6 +51,7 @@ modpost-args =										\
 	$(if $(KBUILD_NSDEPS),-d modules.nsdeps)					\
 	$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N)	\
 	$(if $(findstring 1, $(KBUILD_EXTRA_WARN)),-W)					\
+	$(if $(crypto-module-gen),-c)							\
 	-o $@
 
 modpost-deps := $(MODPOST)
@@ -63,10 +64,22 @@ endif
 # Read out modules.order to pass in modpost.
 # Otherwise, allmodconfig would fail with "Argument list too long".
 ifdef KBUILD_MODULES
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(crypto-module-gen),1)
+# For crypto-module-gen, use .fips140.order instead of modules.order
+modpost-args += -T crypto/fips140/.fips140.order
+modpost-deps += crypto/fips140/.fips140.order
+else
+modpost-args += -T modules.order
+modpost-deps += modules.order
+endif
+else
 modpost-args += -T modules.order
 modpost-deps += modules.order
 endif
 
+endif
+
 ifeq ($(KBUILD_EXTMOD),)
 
 # Generate the list of in-tree objects in vmlinux
@@ -110,6 +123,18 @@ modpost-deps += vmlinux.o
 output-symdump := $(if $(KBUILD_MODULES), Module.symvers, vmlinux.symvers)
 endif
 
+# Include .fips140.symvers for regular module builds if it exists
+ifdef CONFIG_CRYPTO_FIPS140_EXTMOD
+ifeq ($(KBUILD_MODULES),y)
+ifneq ($(crypto-module-gen),1)
+ifneq ($(wildcard crypto/fips140/.fips140.symvers),)
+modpost-args += -i crypto/fips140/.fips140.symvers
+modpost-deps += crypto/fips140/.fips140.symvers
+endif
+endif
+endif
+endif
+
 else
 
 # set src + obj - they may be used in the modules's Makefile
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index abbcd3fc13949..74d249d75d6b5 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -43,6 +43,8 @@ static bool extended_modversions;
 static bool external_module;
 /* Only warn about unresolved symbols */
 static bool warn_unresolved;
+/* Crypto module generation mode */
+static bool crypto_module_gen;
 
 static int sec_mismatch_count;
 static bool sec_mismatch_warn_only = true;
@@ -1751,6 +1753,9 @@ static void check_exports(struct module *mod)
 		const char *basename;
 		exp = find_symbol(s->name);
 		if (!exp) {
+			/* Skip undefined symbol errors for crypto module generation */
+			if (crypto_module_gen)
+				continue;
 			if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS)
 				modpost_log(!warn_unresolved,
 					    "\"%s\" [%s.ko] undefined!\n",
@@ -2210,10 +2215,14 @@ static void write_dump(const char *fname)
 	struct buffer buf = { };
 	struct module *mod;
 	struct symbol *sym;
+	bool is_fips_symvers = crypto_module_gen && (strcmp(fname, "crypto/fips140/.fips140.symvers") == 0);
 
 	list_for_each_entry(mod, &modules, list) {
 		if (mod->dump_file)
 			continue;
+		/* Skip vmlinux symbols when writing .fips140.symvers */
+		if (is_fips_symvers && mod->is_vmlinux)
+			continue;
 		list_for_each_entry(sym, &mod->exported_symbols, list) {
 			if (trim_unused_exports && !sym->used)
 				continue;
@@ -2285,7 +2294,7 @@ int main(int argc, char **argv)
 	LIST_HEAD(dump_lists);
 	struct dump_list *dl, *dl2;
 
-	while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:xb")) != -1) {
+	while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:xbc")) != -1) {
 		switch (opt) {
 		case 'e':
 			external_module = true;
@@ -2340,6 +2349,9 @@ int main(int argc, char **argv)
 		case 'x':
 			extended_modversions = true;
 			break;
+		case 'c':
+			crypto_module_gen = true;
+			break;
 		default:
 			exit(1);
 		}
@@ -2385,8 +2397,14 @@ int main(int argc, char **argv)
 	if (missing_namespace_deps)
 		write_namespace_deps_files(missing_namespace_deps);
 
-	if (dump_write)
-		write_dump(dump_write);
+	if (dump_write) {
+		if (crypto_module_gen) {
+		 	/* generate .fips140.symvers for FIPS crypto modules */
+			write_dump("crypto/fips140/.fips140.symvers");
+		}else {
+			write_dump(dump_write);
+		}
+	}
 	if (sec_mismatch_count && !sec_mismatch_warn_only)
 		error("Section mismatches detected.\n"
 		      "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 02/19] crypto: add module entry for standalone crypto kernel module
From: Jay Wang @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto, Masahiro Yamada,
	linux-kbuild
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Hazem Mohamed Abuelfotoh, Bjoern Doebel, Martin Pohlack,
	Benjamin Herrenschmidt, Nathan Chancellor, Nicolas Schier,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H . Peter Anvin, Luis Chamberlain,
	Petr Pavlu, Daniel Gomez, Sami Tolvanen, David Howells,
	David Woodhouse, Jarkko Sakkinen, Ignat Korchagin, Lukas Wunner,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-arm-kernel, x86, linux-modules
In-Reply-To: <20260418002032.2877-1-wanjay@amazon.com>

Add the module entry for the standalone FIPS kernel crypto module.
This creates the basic structure for fips140.ko that will be linked
with built-in crypto implementations in later patches.

The implementation includes module initialization and exit functions
and add into build system.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Makefile                 |  5 +++++
 crypto/fips140/Makefile         |  3 +++
 crypto/fips140/fips140-module.c | 36 +++++++++++++++++++++++++++++++++
 crypto/fips140/fips140-module.h | 14 +++++++++++++
 4 files changed, 58 insertions(+)
 create mode 100644 crypto/fips140/Makefile
 create mode 100644 crypto/fips140/fips140-module.c
 create mode 100644 crypto/fips140/fips140-module.h

diff --git a/crypto/Makefile b/crypto/Makefile
index d9bec7c6dc417..b48017ca84cc0 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -207,3 +207,8 @@ obj-$(CONFIG_CRYPTO_KDF800108_CTR) += kdf_sp800108.o
 obj-$(CONFIG_CRYPTO_DF80090A) += df_sp80090a.o
 
 obj-$(CONFIG_CRYPTO_KRB5) += krb5/
+
+# FIPS 140 kernel module
+obj-$(CONFIG_CRYPTO_FIPS140_EXTMOD) += fips140/
+
+
diff --git a/crypto/fips140/Makefile b/crypto/fips140/Makefile
new file mode 100644
index 0000000000000..364ef52c190fb
--- /dev/null
+++ b/crypto/fips140/Makefile
@@ -0,0 +1,3 @@
+
+
+	
\ No newline at end of file
diff --git a/crypto/fips140/fips140-module.c b/crypto/fips140/fips140-module.c
new file mode 100644
index 0000000000000..a942de8780efb
--- /dev/null
+++ b/crypto/fips140/fips140-module.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * FIPS 140 Kernel Cryptographic Module
+ *
+ * This file is the module entry point for fips140.ko, which is linked with previously built-in cryptos
+ * to generate the fips140.ko module.
+ * At load time, this module plugs the previously built-in implementations contained within itself back to the kernel.
+ * It also runs self-tests on these algorithms and verifies the integrity of its code and data.
+ * If either of these steps fails, the kernel will panic.
+ */
+
+#include "fips140-module.h"
+
+#define FIPS140_MODULE_NAME "FIPS 140 Kernel Cryptographic Module"
+#define FIPS140_MODULE_VERSION "1.0.0"
+
+#define CRYPTO_INTERNAL "CRYPTO_INTERNAL"
+
+/* Initialize the FIPS 140 module */
+static int __init fips140_init(void)
+{
+    return 0;
+}
+
+static void __exit fips140_exit(void)
+{
+    pr_info("Unloading " FIPS140_MODULE_NAME "\n");
+}
+
+module_init(fips140_init);
+module_exit(fips140_exit);
+
+MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(FIPS140_MODULE_NAME);
+MODULE_VERSION(FIPS140_MODULE_VERSION);
diff --git a/crypto/fips140/fips140-module.h b/crypto/fips140/fips140-module.h
new file mode 100644
index 0000000000000..ed2b6e17969fc
--- /dev/null
+++ b/crypto/fips140/fips140-module.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * FIPS 140 Kernel Cryptographic Module - Header File
+ */
+
+#ifndef _CRYPTO_FIPS140_MODULE_H
+#define _CRYPTO_FIPS140_MODULE_H
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <linux/init.h>
+
+#endif /* _CRYPTO_FIPS140_MODULE_H */
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 01/19] crypto: add Kconfig options for standalone crypto module
From: Jay Wang @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto, Masahiro Yamada,
	linux-kbuild
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Hazem Mohamed Abuelfotoh, Bjoern Doebel, Martin Pohlack,
	Benjamin Herrenschmidt, Nathan Chancellor, Nicolas Schier,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H . Peter Anvin, Luis Chamberlain,
	Petr Pavlu, Daniel Gomez, Sami Tolvanen, David Howells,
	David Woodhouse, Jarkko Sakkinen, Ignat Korchagin, Lukas Wunner,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-arm-kernel, x86, linux-modules
In-Reply-To: <20260418002032.2877-1-wanjay@amazon.com>

Add Kconfig option `CRYPTO_FIPS140_EXTMOD` to enable standalone crypto
module support that can override built-in cryptographic implementations.

Currently supports X86_64 and ARM64 architectures and requires CRYPTO
and MODULES to be enabled.

Signed-off-by: Jay Wang <wanjay@amazon.com>
---
 crypto/Kconfig         |  1 +
 crypto/fips140/Kconfig | 15 +++++++++++++++
 2 files changed, 16 insertions(+)
 create mode 100644 crypto/fips140/Kconfig

diff --git a/crypto/Kconfig b/crypto/Kconfig
index b54a1bef6adef..d792ff01298b7 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1387,6 +1387,7 @@ endif
 endif
 
 source "drivers/crypto/Kconfig"
+source "crypto/fips140/Kconfig"
 source "crypto/asymmetric_keys/Kconfig"
 source "certs/Kconfig"
 source "crypto/krb5/Kconfig"
diff --git a/crypto/fips140/Kconfig b/crypto/fips140/Kconfig
new file mode 100644
index 0000000000000..0665e94b9fe05
--- /dev/null
+++ b/crypto/fips140/Kconfig
@@ -0,0 +1,15 @@
+config CRYPTO_FIPS140_EXTMOD
+	bool "FIPS 140 compliant algorithms as a kernel module"
+	depends on CRYPTO && (X86_64 || ARM64) && MODULES
+	select CRYPTO_FIPS
+	help
+	  This option enables building a kernel module that contains
+	  copies of crypto algorithms that are built in a way that
+	  complies with the FIPS 140 standard.
+
+	  The module registers the algorithms it contains with the
+	  kernel crypto API, and the kernel crypto API's FIPS 140 mode
+	  can be enabled to restrict crypto algorithm usage to only
+	  those provided by this module.
+
+	  If unsure, say N.
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 00/19] crypto: Standalone crypto module
From: Jay Wang @ 2026-04-18  0:20 UTC (permalink / raw)
  To: Herbert Xu, David S . Miller, linux-crypto, Masahiro Yamada,
	linux-kbuild
  Cc: Jay Wang, Vegard Nossum, Nicolai Stange, Ilia Okomin,
	Hazem Mohamed Abuelfotoh, Bjoern Doebel, Martin Pohlack,
	Benjamin Herrenschmidt, Nathan Chancellor, Nicolas Schier,
	Catalin Marinas, Will Deacon, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H . Peter Anvin, Luis Chamberlain,
	Petr Pavlu, Daniel Gomez, Sami Tolvanen, David Howells,
	David Woodhouse, Jarkko Sakkinen, Ignat Korchagin, Lukas Wunner,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-arm-kernel, x86, linux-modules

This patch series is V2 of the previously submitted standalone crypto kernel module feature patch series.

Major update:
V2 is an improved implementation that reduces 3,000 lines of code (~70%) (shrinking patch numbers from ~160 (V1) down to ~20 (V2)), making the patch set significantly less intrusive to the mainline kernel source tree. (For details on how this reduction is achieved, see Section 4 & 7.)
Therefore, compared to the V1 submission where it was organized into 4 patch series, the entire feature is now shipped in one patch series.

Other updates:
1. Update cover letter: Elaborate on how this feature can be used and benefit downstream distros in practice (Section 6). It also clarifies that a stable kernel internal API is not required.
2. Rebase to latest mainline (up to "Merge tag 'v7.1-rc-part1-smbdirect-fixes' of git://git.samba.org/ksmbd").

This feature has been officially launched on the AWS platform, starting from Amazon Linux Kernel 6.18 and later.
The full source code is available at https://github.com/amazonlinux/linux/tree/fips-kernel-module.
Details on this feature and what each patch covers can be found below.

## 1. Introduction

Amazon Linux has released a new kernel feature that converts the previously built-in kernel crypto subsystem into a standalone kernel module. This module becomes the carrier of the kernel crypto subsystem and can be loaded at early boot to provide the same functionality as the original built-in crypto. The primary motivation for this modularization is to streamline Federal Information Processing Standards (FIPS) validation, a critical cryptographic certification for cloud computing users doing business with the U.S. government. This feature is publicly available on the AWS platform.
 
In a bit more detail, previously, FIPS certification was tied to the entire kernel image, meaning non-crypto updates could potentially invalidate certification. With this feature, FIPS certification is tied only to the crypto module. Therefore, once the module is certified, loading this certified module on newer kernels automatically makes those kernels FIPS-certified. As a result, this approach can save re-certification costs and 12-18 months of waiting time by reducing the need for repeated FIPS re-certification cycles.

This document provides technical details on how this feature is designed and implemented for users or developers who are interested in developing upon it, and is organized as follows:
- Section 2 - Getting Started: Quick start on how to enable the feature
- Section 3 - Workflow Overview: Changes this feature brings to build and runtime
- Section 4 - Design Implementation Details: Technical deep-dive into each component
- Section 5 - Customizing and Extending Crypto Module: How to select crypto to be included and extend to new crypto/architectures
- Section 6 - Reusing a Certified Module in Practice: Different reuse and maintenance strategies and their tradeoffs
- Section 7 - Related Work and Comparison
- Section 8 - Summary

## 2. Getting Started

This section provides a quick start guide for developers on how to enable, compile and use the standalone cryptography module feature.

### 2.1 Basic Configuration

The feature is controlled by a single configuration option:
```
CONFIG_CRYPTO_FIPS140_EXTMOD=y
```
What it does: When enabled, automatically redirects a set of cryptographic algorithms from the main kernel into a standalone module `crypto/fips140/fips140.ko`. The cryptographic algorithms that are redirected need to satisfy all the following conditions, otherwise the cryptography will remain in its original form:
1. Must be configured as built-in (i.e., `CONFIG_CRYPTO_*=y`). This means cryptography already configured as modular (i.e., `CONFIG_CRYPTO_*=m`) are not redirected as they are already modularized.
2. Must be among a list, which can be customized by developers as described in Section 5.

When disabled, the kernel behaves as before.

### 2.2 Build Process

Once `CONFIG_CRYPTO_FIPS140_EXTMOD=y` is set, no additional steps are required. The standalone module will be built automatically as part of the standard kernel build process:
```
make -j$(nproc)
# or
make vmlinux
```
**What happens automatically (No user action required):**
1. Build the module as `crypto/fips140/fips140.ko`
2. The cryptography module will be loaded at boot time
3. All kernel cryptographic services will provide the same functionality as before (i.e., prior to introducing this new feature) once boot completes.

### 2.3 Advanced Configuration Options

**Using External Cryptography Module:**
```
CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE=y
```
By default, `CONFIG_CRYPTO_FIPS140_EXTMOD_SOURCE` is not set, meaning the freshly built cryptography module is used. Otherwise, the pre-built standalone cryptography module from `fips140_build/crypto/fips140/fips140.ko` and modular cryptography such as `fips140_build/crypto/aes.ko` (need to manually place pre-built modules in these locations before the build) are included in kernel packaging (e.g., during `make modules_install`) and are used at later boot time.

**Dual Version Support:**
```
CONFIG_CRYPTO_FIPS140_DUAL_VERSION=y
```
Encapsulate two versions of `fips140.ko` into kernel: one is freshly built for non-FIPS mode usage, another is pre-built specified by `fips140_build/crypto/fips140/fips140.ko` for FIPS mode usage. The appropriate version is selected and loaded at boot time based on boot time FIPS mode status.

### 2.4 Verification

To verify the feature is working, after install and boot with the new kernel:
```
# Check if fips140.ko module is loaded
lsmod | grep fips140
# Check if crypto algorithms are served by the fips140 module
cat /proc/crypto | grep module | grep fips140
```

## 3. Workflow Overview

This section provides an overview without delving into deep technical details of the changes the standalone cryptography module feature introduces. When this feature is enabled, it introduces changes to both the kernel build and booting process. 

3.1 Build-Time Changes

Kernel cryptography subsystem consists of both cryptography management infrastructure (e.g., `crypto/api.c`, `crypto/algapi.c`, etc), along with hundreds of different cryptography algorithms (e.g., `crypto/arc4.c`).

**Traditional Build Process:**
Traditionally, cryptography management infrastructure are always built-in to the kernel, while cryptographic algorithms can be configured to be built either as built-in (`CONFIG_CRYPTO_*=y`) or as separate modular (`CONFIG_CRYPTO_*=m`) `.ko` file depending on kernel configuration:
As a result, the builtin cryptography management infrastructure and cryptographic algorithms are statically linked into the kernel binary:
```
cryptographic algorithms source files → compiled as .o objfiles →  linked into vmlinux → single kernel binary
```
**With Standalone Cryptography Module:**
This feature automatically transforms the builtin cryptographic components into a standalone cryptography module, `fips140.ko`. To do so, it develops a new kernel build rule `crypto-objs-$(CONFIG_CRYPTO_*)` such that, once this build rule is applied to a cryptographic algorithm, such cryptographic algorithm will be automatically collected into the cryptography module if it is configured as built-in (i.e, `CONFIG_CRYPTO_*=y`), for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
```
Such build change allows the modularization transformation to only affect selected cryptographic algorithms (i.e, where the `crypto-objs-$(CONFIG_CRYPTO_*`) is applied).

Then, after the `fips140.ko` is generated, it will be embedded back into main kernel vmlinux as a replacement part. The purpose of this embedding, instead of traditionally putting the `fips140.ko` into filesystem, is a preparation to allow the module to be loaded early enough even before the filesystem is ready.

The new build process is illustrated below.
```
cryptographic algorithms source files → compiled as .o objfiles → automatically collected and linked into fips140.ko → embedded fips140.ko into vmlinux as a replaceable binary
```

### 3.2 Runtime Changes

**Traditional Boot Process:**
The kernel initializes the cryptographic subsystem early during boot, executing each cryptographic initialization routine accordingly. These initialization routines may depend on other cryptographic components or other kernel subsystems, so their invocation follows a well-defined execution order to ensure they are initialized before their first use.
```
kernel starts → cryptography subsystem initialization → cryptography subsystem available → other components use cryptography
```
**With Standalone Cryptography Module:**
At the start of kernel boot, compared to a regular kernel, the first major change introduced by this feature is that no cryptography services are initially available — since the entire cryptography subsystem has been decoupled from the main kernel.
To ensure that the cryptography subsystem becomes available early enough (before the first kernel component that requires cryptography services), the standalone cryptography kernel module must be loaded at a very early stage, even before the filesystem becomes available.

However, the regular module loading mechanism relies on placing kernel modules in the filesystem and loading them from there, which creates a chicken-and-egg problem — the cryptography module cannot be loaded until the filesystem is ready, yet some kernel components may require cryptography services even before that point.

To address this, the second change introduced by this feature is that the cryptography kernel module is loaded directly from memory, leveraging the earlier compilation changes that embed the module binary into the main kernel image. Afterward, the feature includes a “plug-in” mechanism that connects the decoupled cryptography subsystem back to the main kernel, ensuring that kernel cryptography users can correctly locate and invoke the cryptography routine entry points.

Finally, to ensure proper initialization, the feature guarantees that all cryptography algorithms and the cryptography management infra execute their initialization routines in the exact same order as they would if they were built-in.

The process described above is illustrated below.
```
kernel starts → no cryptography available → load fips140.ko from memory → plug cryptography back to kernel → module initialization → cryptographic services available → other components use cryptography
```

## 4. Design Implementation Details

While the earlier sections provide a holistic view of how this feature shapes the kernel, this section provides deeper design details on how these functionalities are realized. There are three key design components:
1. A specialized compile rule that automatically compiles and collects all built-in cryptographic algorithm object files to generate the final module binary under arbitrary kernel configurations, and then embeds the generated binary into the main kernel image for early loading.
2. A mechanism to convert interactions between the cryptography subsystem and the main kernel into a pluggable interface.
3. A module loading and initialization process that ensures the cryptography subsystem is properly initialized as if it were built-in.

### 4.1. Specialized Compilation System

**Automatic Collection and Linking of Built-in Cryptographic Algorithm Objects:**
The first step in generating the `fips140.ko` module is to compile and collect built-in cryptographic components (i.e., those specified by `CONFIG_CRYPTO_*=y`).
Traditionally, the existing module build process requires all module components (e.g., source files) to reside in a single directory. However, this approach is not suitable for our case, where hundreds of cryptographic algorithm source files are scattered across multiple directories.

A naïve approach would be to create a separate Makefile that duplicates the original build rules with adjusted paths.
However, this method is not scalable due to the large number of cryptographic build rules, many of which are highly customized and can vary under different Kconfig settings, making such a separate Makefile even more complex.
Moreover, this approach cannot ensure that built-in cryptographic algorithms are completely removed from the main kernel, which would result in redundant cryptographic code being included in both the kernel and the module.

To tackle this challenge, we automated the object collection and linking process by introducing special build logic for the kernel cryptography subsystem.
Specifically, to automatically collect cryptography object files while preserving their original compilation settings (such as flags, headers, and paths), we introduced a new compilation rule:
```
crypto-objs-y += *.o
```
This replaces the original `obj-y += *.o` rule in cryptography Makefiles later, for example:
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \
    asymmetric_type.o \
    restrict.o \
    signature.o
```
in the cryptography subsystem Makefiles, allowing most of the existing Makefile logic to be reused.
As a result, when the standalone cryptography module feature is enabled, any cryptographic algorithm configured as built-in (for example, `crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o` where `CONFIG_ASYMMETRIC_KEY_TYPE=y`) will be automatically collected and linked into a single final object binary, `fips140.o`.
During this process, a special compilation flag (`-DFIPS_MODULE=1`) is applied to instruct each object file to be compiled in a module-specific manner. This flag will later be used to generate the pluggable interface on both the main kernel side and the module side from the same source code.

The implementation details are as follows: it follows a similar methodology used by the `obj-y` collection process for building `vmlinux.o`. The `crypto-objs-y` rule is placed in `scripts/Makefile.build`, which is executed by each directory Makefile to collect the corresponding crypto object files. Each directory then creates a `crypto-module.a` archive that contains all `crypto-objs-y += <object>.o` files under that directory. In the parent directories, these `crypto-module.a` archives are recursively included into the parent’s own `crypto-module.a`, and this process continues upward until the final `fips140.o` is generated.

**A Separate Module Generation Pipeline for Building the Final Kernel Module from Linked Cryptographic Algorithm Object:**
With the linked cryptographic algorithm object (i.e., `fips140.o`), the next step is to generate the final kernel module, `fips140.ko`.

A direct approach would be to inject the `fips140.ko` module build into the existing modules generation pipeline (i.e., `make modules`) by providing our pre-generated `fips140.o`. However, we choose not to do this because it would create a circular make rule dependency (which is invalid in Makefiles and causes build failures), resulting in mutual dependencies between the modules and vmlinux targets (i.e., `modules:vmlinux` and `vmlinux:modules` at the same time).
This happens for the following reasons:
1. Since we will later embed `fips140.ko` into the final kernel image (as described in the next section), we must make vmlinux depend on `fips140.ko`. In other words: `vmlinux: fips140.ko`.
2. When the kernel is built with `CONFIG_DEBUG_INFO_BTF_MODULES=y`, it requires: modules: vmlinux. This is because `CONFIG_DEBUG_INFO_BTF_MODULES=y` takes vmlinux as input to generate BTF info for the module, and inserts such info into the `.ko` module by default.
3. If we choose to inject `fips140.ko` into make modules, this would create a make rule dependency: `fips140.ko: modules`. Combined with items 1 and 2, this eventually creates an invalid circular dependency between vmlinux and modules.

Due to these reasons, the design choice is to use a separate make pipeline (defined as `fips140-ready` in the Makefile). This new pipeline reuses the same module generation scripts used by make modules but adds additional logic in `scripts/Makefile.{modfinal|modinst|modpost}` and `scripts/mod/modpost.c` to handle module symbol generation and verification correctly. 

**A Seamless Process That Embeds the Generated Binary Into the Main Kernel Image for Early Loading:**
As mentioned earlier, in order to load the standalone cryptography module early in the boot process—before the filesystem is ready—the module binary must be embedded into the final kernel image (i.e., vmlinux) so that it can be loaded directly from memory.
We intend for this embedding process to be completely seamless and automatically triggered whenever vmlinux is built (i.e., during `make vmlinux`).

To achieve this, the feature adds a Make dependency rule so that vmlinux depends on `fips140.ko`.
It also modifies the vmlinux link rules (i.e., `arch/<arch>/kernel/vmlinux.lds.S`, `scripts/Makefile.vmlinux`, and `scripts/link-vmlinux.sh`) so that the generated module binary is finally combined with `vmlinux.o`.

In addition, we allow multiple cryptography module binary versions (for example, a certified cryptography binary and a latest, up-to-date but uncertified one) to be embedded into the main kernel image to serve different user needs. This design allows regular (non-FIPS) users to benefit from the latest cryptographic updates, while FIPS-mode users continue to use the certified cryptography module.

To support this, we introduce an optional configuration, `CONFIG_CRYPTO_FIPS140_DUAL_VERSION`. When enabled, this option allows two cryptography module versions to be embedded within a single kernel build and ensures that the appropriate module is selected and loaded at boot time based on the system’s FIPS mode status.

### 4.2. Pluggable Interface Between the Built-in Cryptography Subsystem and the Main Kernel

Although the module binary (`fips140.ko`) has been embedded into the final kernel image (`vmlinux`) as described in the previous section, it is not linked to the kernel in any way. This is because `fips140.ko` is embedded in a data-only manner, so the main kernel cannot directly call any functions or access any data defined in the module binary. Since the main kernel and modules can only interact through exported symbols (i.e., via `EXPORT_SYMBOL()`), this also applies to the crypto kernel module — the main kernel can only interact with the crypto functions and variables defined in the crypto module through exported symbols, meaning these functions and variables must also have their symbols exported in the module after they are moved from the main kernel to the module.

However, simply making these crypto symbols symbol-exported in the module without additional handling would cause the kernel to fail to compile. This is because the existing kernel module symbol resolution mechanism is essentially one-way: it supports symbols defined in the main kernel and referenced by kernel modules. However, it does not support the reverse case — symbols defined in a kernel module but used by the main kernel — which is exactly the crypto module case, as there are many crypto users still residing in the main kernel. The reason is that compilation of the main kernel requires all symbol addresses to be known to achieve a successful linking phase.

To address this, we introduce a pluggable interface to support this reverse-direction symbol resolution between crypto symbols defined in the module and referenced by the main kernel, by placing **address placeholders** at all crypto usage points in the main kernel. These address placeholders are initially set to NULL during compilation to provide a concrete address that satisfies the linking phase. Then, during runtime, once the cryptography kernel module is loaded, these placeholders are updated to the correct addresses before their first use in the main kernel. In the rest of this section, we first introduce this pluggable interface mechanism, and then explain how to apply it to the built-in cryptographic algorithms and variables.

**The Pluggable Interface Mechanism:**
There are two types of address holders used to achieve this pluggable interface:
- Function addresses (the majority): We use a trampoline to redirect the original jump instruction to another location whose target destination is held by the value of a function pointer. To avoid additional security concerns, such as the function pointer being arbitrarily modified, these function pointers are made `__ro_after_init` to ensure they cannot be modified after kernel init. We implement this function-address placeholder as the `DEFINE_CRYPTO_FN_REDIRECT()` wrapper.
- Variable addresses (the remaining smaller portion): For these, we use a pointer of the corresponding data type. We implement this address placeholder as the `DECLARE_CRYPTO_VAR()` and `DEFINE_CRYPTO_API_STUB()` wrappers:

These wrappers are applied to each symbol-exported (i.e., `EXPORT_SYMBOL()`) cryptographic function and variable (details on how to apply them are described later). Once applied, the wrappers are compiled differently for the main kernel and for the built-in cryptographic algorithm source code—acting as the “outlet” and the “plug,” respectively—using different compilation flags (`-DFIPS_MODULE`) introduced by our customized build rules described earlier.

As a result, the kernel can successfully compile even when the built-in cryptographic algorithms are removed, thanks to these address placeholders. At boot time, the placeholders initially hold NULL, but since no cryptography users exist at that stage, the kernel can still start booting correctly. After the cryptography module is loaded, the placeholders are dynamically updated to the correct addresses later (by `do_crypto_var()` and `do_crypto_fn()`, described in a later section).

**Applying the Pluggable Interface Mechanism to Cryptographic Algorithms:**

To apply these pluggable interface wrappers to a cryptographic algorithm and make them take effect, we follow the steps below (using `crypto/asymmetric_keys/asymmetric_type.c` as an example):
1. **Apply `crypto-objs-y` compile rule to the cryptographic algorithm:**
```
// in crypto/asymmetric_keys/Makefile
- obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
+ crypto-objs-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := \
    asymmetric_type.o \
    restrict.o \
    signature.o
```
2. **Locate the communication point between the cryptographic algorithm and the main kernel:**

The cryptography subsystem is designed such that most interactions between the main kernel and cryptographic algorithms occur through exported symbols using `EXPORT_SYMBOL()` wrappers.
This kernel design exists because most cryptographic algorithm implementations must support both built-in and modular modes. 

Consequently, the cryptographic functions and variables exported by `EXPORT_SYMBOL()` are a well-defined and identifiable interface between the cryptography subsystem and the main kernel: 
```
// in crypto/asymmetric_keys/asymmetric_type.c 
//Exported cryptographic function:
bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
                const struct asymmetric_key_id *kid2) {...}
EXPORT_SYMBOL_GPL(asymmetric_key_id_same); 
//Exported cryptographic variable:
struct key_type key_type_asymmetric = {...};
EXPORT_SYMBOL_GPL(key_type_asymmetric); 
```

3. **Redirect crypto symbol references in the main kernel to address placeholders:**

With the placeholders in place, the remaining problem is directing the main kernel to use them rather than the original symbols. Since all crypto users must include the corresponding header files to obtain function and variable declarations, the headers are a natural place to perform this redirection. Each declaration is transformed using a macro that hooks it to the corresponding placeholder.

For exported variable symbols (a small number, ~10 symbols), their declaration in the header file is replaced with the `DECLARE_CRYPTO_VAR()` wrapper to redirect variable access from a concrete address to a placeholder:
```
// in include/keys/asymmetric-type.h
// for exported cryptographic variables:
- struct key_type key_type_asymmetric;
+ DECLARE_CRYPTO_VAR(CONFIG_ASYMMETRIC_KEY_TYPE, key_type_asymmetric, struct key_type, );
+ #if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(FIPS_MODULE) && IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #define key_type_asymmetric (*((struct key_type*)CRYPTO_VAR_NAME(key_type_asymmetric)))
+ #endif 
```
By doing so, we can automatically force all cryptography users to go through the placeholders, because those users already include the same header file.
The wrapper also takes the cryptographic algorithm Kconfig symbol as a parameter, so that when a cryptographic algorithm is built as a module (for example, `CONFIG_ASYMMETRIC_KEY_TYPE=m`), the original function declarations remain unchanged and are not affected.

For exported function symbols (the majority, ~hundreds), a similar approach could be taken, but instead we use an automated method to redirect function address usage to placeholders during the kernel compilation process. This makes the crypto module implementation less intrusive to the kernel source tree, as no header file modifications are needed. To achieve this, a linker option `--wrap=<symbols-to-redirect>` is leveraged to rename all uses of crypto functions in the main kernel to dedicated trampolines that act as address placeholders. As a consequence, all references to crypto function symbols are automatically redirected to the address placeholders, avoiding mass intrusive changes to the mainline kernel source tree.

4. **Add the address-placeholder definition wrappers into a dedicated file `fips140-var-redirect.c`:**

After redirecting crypto users to use address placeholders, we also need to add the definitions of those address placeholders.

For exported variable symbols (a small number, ~10 symbols), add the placeholder definition wrapper `DEFINE_CRYPTO_VAR_STUB` to a dedicated file `fips140-var-redirect.c`.
```
// in crypto/fips140/fips140-var-redirect.c
// for exported cryptographic variables:
+ #undef key_type_asymmetric
+ DEFINE_CRYPTO_VAR_STUB(key_type_asymmetric);
+ #endif
```
This file will be compiled separately and acts as both the “outlet” and the “plug” for the main kernel and the cryptography module, respectively.

For exported function symbols (the majority, ~hundreds), a similar wrapper `DEFINE_CRYPTO_FN_REDIRECT()` is used, but again, the application of this wrapper is automated, so there is no need to manually apply it. Instead, it is generated automatically by the script `crypto/fips140/gen-fips140-fn-redirect.sh` on every kernel build.

We apply the above steps to both architecture-independent and architecture-specific cryptographic algorithms.

### 4.3. Initialization Synchronization

To ensure the embedded `fips140.ko` module binary provides the same cryptography functionality as the regular kernel, the kernel needs:
1. A module loader to load the module binary directly from memory,
2. A mechanism to plug the module back into the kernel by updating the address placeholders, and
3. Correct cryptography subsystem initialization, as if the cryptographic algorithms were still built-in.

**Directly Load Module Binary from Memory:**
Regular modules are loaded from the filesystem and undergo signature verification on the module binary, which relies on cryptographic operations. However, since we have already fully decoupled the cryptography subsystem, we must skip this step for this `fips140.ko` module.
To achieve this, we add a new loader function `load_crypto_module_mem()` that can load the module binary directly from memory at the designed address without checking the signature. Since the module binary is embedded into main kernel in an ELF section, as specified in the linker script:
```
// in arch/<arch>/kernel/vmlinux.lds.S
    .fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
        . = ALIGN(8);
        _binary_fips140_ko_start = .;
        KEEP(*(.fips140_module_data))
        _binary_fips140_ko_end = .;
    }
```
Therefore, the runtime memory address of the module can be accessed directly by the module loader to invoke the new loader function `load_crypto_module_mem()`.

**Plug Back the Module by Updating Address Placeholder Values:**
To update the address placeholders in the main kernel to the correct addresses matching the loaded module, after compilation the placeholder values are placed into dedicated key-value data structures, which reside in ELF sections `__crypto_fn_keys` and `__crypto_var_keys`.
This can be seen from the definition of the placeholder's key-value data structure:
```
#define __CRYPTO_FN_KEY(sym)					\
	extern void *__fips140_fn_ptr_##sym;			\
	static struct _crypto_fn_key __##sym##_fn_key		\
		__used						\
		__section("__crypto_fn_keys")			\ // Place in a dedicated ELF Section
		__aligned(__alignof__(struct _crypto_fn_key)) = {	\
		.ptr = (void **)&__fips140_fn_ptr_##sym,		\
		.func = (void *)&sym,				\
	};

#define DEFINE_CRYPTO_VAR_STUB(name) \
    static struct crypto_var_key __crypto_##name##_var_key \
        __used \
        __section("__crypto_var_keys") \ // Place in a dedicated ELF Section
        __aligned(__alignof__(struct crypto_var_key)) = \
    { \
        .ptr = &CRYPTO_VAR_NAME(name), \
        .var = (void*)&name, \
    };
```
The purpose of doing this is to allow the main kernel to quickly locate the placeholders and update them to the correct addresses. The update functions are defined as `do_crypto_var()` and `do_crypto_fn()`, which are executed at module load.

As a result, all cryptography users in the main kernel can now call the cryptographic functions as if they were built-in.

**Initialize Cryptography Subsystem as if it Were Built-in:**
Cryptographic components must be properly initialized before use, and this initialization is typically achieved through dedicated initialization functions (e.g., `module_init(crypto_init_func)` or `late_initcall(crypto_init_func)`). Traditionally, these init functions are executed automatically as part of the kernel boot phase. However, now that they are moved to a crypto module, there needs to be a way to collect and execute them.

To collect these init functions, the init wrappers (e.g., `module_init()` and `late_initcall`) are modified to automatically place the wrapped crypto init function into a dedicated list in the crypto module, for example:
```
// in include/linux/module.h
#define subsys_initcall(fn) \
	static initcall_t __used __section(".fips_initcall0") \ // a dedicated list
		__fips_##fn = fn;

#define module_init(initfn) \
	static initcall_t __used __section(".fips_initcall1") \ // a dedicated list
		__fips_##initfn = initfn;
```
By doing so, all init functions are now aggregated for execution by `run_initcalls()` at module load.

Besides collecting these crypto init functions, rather than simply executing them, another key consideration is that their execution order often has strict requirements. In other words, for these collected crypto init functions, we must ensure that their initialization order is preserved as before because failure to follow the correct order can result in kernel panic.

To address this, we introduce a synchronization mechanism between the main kernel and the module to ensure all cryptographic algorithms are executed in the correct kernel boot phase. In more details, we spawn the module initialization process `fips_loader_init()` as an async thread `fips140_sync_thread()`, in which we call `run_initcalls()` to execute the initialization calls of each cryptographic algorithm.
Then, we introduce synchronization helpers such as `wait_until_fips140_level_sync(int level)` to ensure the initialization order of all cryptographic algorithms is synchronized with the main kernel.

## 5. Customization and Extension of Cryptography Module

This section describes how developers can customize which cryptographic algorithms are included in the standalone cryptography module, as well as extend this feature to other cryptographic algorithms or hardware architectures.

### 5.1. Cryptography Selection Mechanism

The feature automatically includes cryptographic algorithms that meet specific criteria:
1. **Built-in Configuration**: Only cryptographic algorithms configured as `CONFIG_CRYPTO_*=y` are candidates for inclusion
2. **Explicit Inclusion**: Cryptographic algorithms must be explicitly converted using the `crypto-objs-$(CONFIG__CRYPTO_*`) build rule

### 5.2. Extend Support to New Cryptographic Algorithms

To extend support to a new cryptographic algorithm in the standalone module, follow these steps:

**Step 1: Update the Makefile**
```
# in crypto/[algorithm]/Makefile
- obj-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
+ crypto-objs-$(CONFIG_CRYPTO_ALGORITHM) += algorithm.o
```
For Architecture-Specific Cryptographic Algorithms:
- Apply the `crypto-objs-` rule in the appropriate `arch/*/crypto/Makefile`

**Step 2: Add Pluggable Interface Support**
If the cryptographic algorithm has symbol-exported variables via `EXPORT_SYMBOL()`, add the pluggable interface wrappers. There is no need to manually apply wrappers for symbol-exported functions:
```
// Example: in include/keys/asymmetric-type.h
// for exported cryptographic variables:
- struct key_type key_type_asymmetric;
+ DECLARE_CRYPTO_VAR(CONFIG_ASYMMETRIC_KEY_TYPE, key_type_asymmetric, struct key_type, );
+ #if defined(CONFIG_CRYPTO_FIPS140_EXTMOD) && !defined(FIPS_MODULE) && IS_BUILTIN(CONFIG_ASYMMETRIC_KEY_TYPE)
+ #define key_type_asymmetric (*((struct key_type*)CRYPTO_VAR_NAME(key_type_asymmetric)))
+ #endif 
```
Then, add the corresponding stubs in `crypto/fips140/fips140-var-redirect.c`:
```
+ #undef key_type_asymmetric
+ DEFINE_CRYPTO_VAR_STUB(key_type_asymmetric);
+ #endif
```
For Architecture-Specific Cryptographic Algorithms:
- Include architecture-specific stubs in `arch/*/crypto/fips140/fips140-var-redirect.c`:

### 5.3. Architecture-Specific Extensions

**Extending to New Architectures:**
Currently supported architectures are x86_64 and ARM64. To extend this feature to additional architectures:
1. **Update Linker Scripts**: Add ELF sections in `arch/[new-arch]/kernel/vmlinux.lds.S`:
```
.fips140_embedded : AT(ADDR(.fips140_embedded) - LOAD_OFFSET) {
    . = ALIGN(8);
    _binary_fips140_ko_start = .;
    KEEP(*(.fips140_module_data))
    _binary_fips140_ko_end = .;
}
```
2. **Create Architecture-Specific Files**: Set up `arch/[new-arch]/crypto/fips140/` directory with Makefile and `fips140-var-redirect.c` following the pattern used in x86_64 and ARM64.

## 6. Reusing a certified module in practice

With the crypto subsystem restructured as a loadable module, a previously certified module can be reused across kernel updates. Crypto development does not freeze in the meantime — updated modules can always be submitted for fresh certification. The reuse of an already-certified module is intended to simply bridge the gap until the new certification arrives, that is, using the old one before the new one gets certified. How much of the certified module to reuse, however, involves a tradeoff between crypto feature availability, certification turnaround time, and engineering effort.

The most conservative option is no reuse at all: abandon the previous certification and submit the updated crypto module for a full FIPS certification. This allows the crypto subsystem to benefit from the latest upstream changes, but at the cost of the full 12-to-18-month waiting period, according to experiences from downstream distributions.

At the opposite end, distributions can choose to reuse the certified module binary entirely on a newer kernel. This enables the new kernel to be validated on day one. The tradeoff is clear: besides forgoing crypto updates, engineers must ensure ABI compatibility between the updated kernel and the module.

A middle ground is to reuse only the source code of the certified module, freezing it and recompiling against the updated main kernel. Since the source code remains unchanged, the new module can go through a Non-Security Relevant ([NSRL](https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS-140-3-CMVP%20Management%20Manual.pdf)) process — a simpler FIPS re-certification that typically reduces the waiting time from 12–18 months down to 3–4 months. Compared to reusing the binary entirely, this option requires less engineering effort, since engineers need only maintain source-level API compatibility (i.e., by patching the main kernel source code, not touching the crypto module source code) rather than binary-level ABI compatibility between the crypto module and the main kernel.

In summary, converting the kernel crypto subsystem into a loadable module enables reuse of a certified module across kernel updates. Whether through binary reuse, source-code reuse, or fresh certification, different choices represent different tradeoffs, and distributions can balance crypto feature availability, certification turnaround time, and engineering effort according to their needs.

## 7. Related Work and Comparison

The idea of modularizing kernel cryptographic functionality has also attracted attention from other Linux distributions as well as Linux-kernel-based platforms that are not traditional distributions. Specifically, there are two related efforts: one from [Android's GKI kernel](https://source.android.com/docs/core/architecture/kernel/gki-fips140-module) and another from [Oracle Linux](https://git.kernel.org/pub/scm/linux/kernel/git/vegard/linux-fips140.git/log/?h=fips140). While Amazon Linux incorporated several valuable ideas from these efforts (and have acknowledged them in the patch commits—thank you again!), this section highlights the key differences between those approaches and this approach. The goal is to describe the trade-offs and design choices objectively, rather than to criticize other implementations.

### 7.1. Comparison with Android's GKI

Android's work is the earliest one on modularizing kernel cryptographic code, and it targets a non-intrusive approach to the core GKI kernel, with the goal of minimizing modifications to the kernel source. To achieve this, the crypto module relies on several interception or "hijacking" techniques that intervene in the core kernel execution path.

While this approach minimizes kernel code changes, we don't adopt such an approach for several reasons. First, these interception mechanisms tightly depend on internal kernel crypto subsystem behavior, making them fragile across major kernel updates thus less suitable to reuse the same module on newer major kernel versions. Second, this design requires substantial additional cryptographic code duplication, which impacts maintainability. Finally, the solution only supports a fixed set of cryptographic algorithms, making it non-general and difficult to extend.

In contrast, our design integrates directly into the Linux kernel source tree, avoids duplicated cryptographic implementations, supports arbitrary kernel configuration settings, and works with any chosen set of cryptographic algorithms.

### 7.2. Comparison with Oracle Linux

Oracle’s work was developed concurrently with this approach. The primary differences between Oracle’s approach and Amazon's lie in build integration, pluggable interface design, and module initialization.

**Build Integration:**
Oracle's module is implemented as an out-of-tree module with a separate Makefile. This introduces three major reasons we don't adopt such an approach: 

*First*, the separate Makefile duplicates many kernel build rules, which increases maintenance cost, as upstream kernel build changes must be tracked and replicated. One concrete example can be seen below:

in Oracle's module makefile
```
fips140-y += crypto/skcipher.o
fips140-y += crypto/lskcipher.o
```
However, in upstream, the corresponding build logic is more complex and configuration-dependent:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As shown above, when `CONFIG_BPF_SYSCALL` is enabled, `bpf_crypto_skcipher.o` must also be included. Tracking such dependencies is hard in the duplicated Makefile approach. In contrast, our approach integrates seamlessly into the kernel build system by introducing a customized build rule (`crypto-objs-*`) rather than relying on a duplicated Makefile, such that this is handled correctly by reusing the existing kernel build logic:
```
crypto_skcipher-y += lskcipher.o
crypto_skcipher-y += skcipher.o
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += crypto_skcipher.o
ifeq ($(CONFIG_BPF_SYSCALL),y)
- obj-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
+ crypto-objs-$(CONFIG_CRYPTO_SKCIPHER2) += bpf_crypto_skcipher.o
endif
```
As a result, such a Makefile-duplication approach does not scale well across all kernel configurations and does not easily support arbitrary sets of cryptographic algorithms.

*Second*, since the module is to be embedded as part of the kernel image (i.e., `vmlinux`) as described earlier, the module build must be triggered automatically as part of the `vmlinux` build process to achieve a seamless build workflow. However, Oracle's module build is not tightly integrated into the kernel build framework and requires special build commands (e.g., first do `make M=fips140/` specifically, then do some shell command and finally `make`). 

In contrast, our approach improves this aspect by integrating the module build tightly into the regular kernel build, so the build process is seamless and automatic with regular build and packaging processes such as `make` or `make vmlinux` or `make install`.

**Pluggable Interface:**
There are several differences in the pluggable interface design.

*First*, the approach we use avoids massive intrusion to the main kernel source tree (i.e., significantly fewer lines of source code modification), making it easier to maintain and merge to mainline. This reduction is mainly achieved by automating the conversion process of crypto function symbols to pluggable symbols. Specifically, the existing approach requires modifications to the cryptographic implementation (.c) files and the declaration (.h) header files of crypto function symbols, as well as the code pattern of crypto's initialization routine (e.g., replace `module_init(init_fn)` with `crypto_module_init(init_fn)`). In contrast, our approach fully automates this process without requiring any source code modification. As a result, our method achieves a reduction of ~3K lines of code (~70% of total), making it easier to maintain and merge to mainline.

*Second*, we avoid duplicate crypto code so only keep one crypto code in kernel memory, while existing work keeps two crypto code even if these crypto code are from the same source code. This is due to the way Oracle defines pluggable interface macros in `crypto/api`, where its design requires some cryptographic code to remain compiled into the main kernel image in addition to the code inside the standalone cryptography module. Keeping two crypto code is ok if these code are different and designed to be used for different runtime modes (i.e., FIPS/non-FIPS mode), but will be unnecessary if both crypto code are the same.

In contrast, the approach we use can flexibly support both choices: keep one cryptography subsystem, or two different crypto subsystems. To do so, we introduce an option `CRYPTO_FIPS140_DUAL_VERSION` such that when it is disabled, we only keep one cryptographic subsystem in the cryptography module while completely removing it from the main kernel; and when it is enabled, we allow having two different modules carrying different cryptography for different kernel runtime modes (i.e., FIPS and non-FIPS mode).

*Third*, prior approaches mainly support making cryptographic function calls pluggable, while our approach extends pluggability to cryptographic variables as well.

*Fourth*, prior approach requires all cryptographics that we care (for any purpose such as those within FIPS boundary) to be included within a single kernel module `fips140.ko` (e.g., when `CONFIG_CRYPTO_AES=m`, it cannot be `aes.ko` but must be within fips140.ko). However, this requirement limits the inherent benefit of a kernel module (i.e., on-demand loading for memory efficiency). In contrast, our approach allows the cryptographic we care remain its original modular if it is configured as being so (i.e., if `CONFIG_CRYPTO_AES=m`, the aes will still be as `aes.ko` but not forced to `fips140.ko`) up to the `.config` setting. One benefit of this design is that it does not impose strict requirements on `.config` setting (i.e., a cryptography `.config` can be set to both `=y|m` while existing work must be set as `=y`), preserving configuration flexibility.

To support so, for any cryptography within the interest (i.e., whose makerule has been replaced with `crypto-objs-*`) but configured as build-as-module (i.e., `CONFIG_CRYPTO_*=m`), its compiled `.ko` binary will be marked automatically, such that the loader will have a way to recognize to perform some interest-specific processing (e.g., registered as FIPS-required flag) if needed. And the pluggable interface can also adjust its coverage automatically based on different `CONFIG_CRYPTO_*=y|=m` settings. This is achieved by letting the pluggable interface macro to take `CONFIG_CRYPTO_*` option as a parameter to recognize the `.config` setting.

**Module Initialization:**
Oracle's initialization routine does not guarantee preservation of the original crypto initialization order (i.e., the order they should follow if they were originally built-in in the main kernel), which limits its ability to support arbitrary combinations of cryptographic algorithms. This is because the crypto initialization routine in the module is executed too early, such that all module crypto is initialized before the cryptography init in the main kernel. So if there is a crypto in the module (e.g., a crypto init defined as `late_init()`) that depends on a cryptography (whose init is defined as `module_init()`) in the main kernel, since the one in the main kernel should be executed earlier (but because the module init is too early, it makes the crypto in the main kernel executed too late), such a case will break the kernel boot process.

Our design, on the other hand, introduces explicit initialization synchronization mechanisms between cryptography's init routine in the module and in the main kernel that can preserve the original built-in initialization order. As a result, our module supports any chosen crypto set to be included in the module.

### 7.3. Comparison Summary

Overall, combined with differences in coding style and integration strategy, the proposed approach has less source-code modification, is more seamlessly integrated with the upstream Linux kernel, making it more generalizable across different kernel configuration settings, and the changed behavior more invisible to kernel users.

## 8. Summary
In this patch series, Amazon Linux proposes a new kernel feature that decouples the built-in crypto subsystem into a dedicated kernel module. To achieve this, several key mechanisms are designed, including specialized compile rules, a novel pluggable interface mechanism, and a module-loading initialization process. This feature is designed in an upstream-friendly manner so that it can support arbitrary kernel configuration settings and arbitrary chosen sets of cryptographic algorithms. It has been officially launched with the Amazon Linux Kernel 6.18 as well as future kernels.

---
Written by Jay Wang <wanjay@amazon.com> <jay.wang.upstream@gmail.com>, Amazon Linux

Jay Wang (17):
      crypto: add Kconfig options for standalone crypto module
      crypto: add module entry for standalone crypto kernel module
      build: special compilation rule for building the standalone crypto module
      build: Add ELF marker for crypto-objs-m modules
      crypto: add pluggable interface for module symbols referenced by the main kernel
      crypto: dedicated ELF sections for collected crypto initcalls
      crypto: fips140: add crypto module loader
      build: embed the standalone crypto module into vmlinux
      module: skip modversion checks for crypto modules
      build: add CONFIG_DEBUG_INFO_BTF_MODULES support for the standalone crypto kernel module
      Allow selective crypto module loading at boot based on FIPS mode
      Execute crypto initcalls during module initialization
      crypto: fips140: add module integrity self-check
      crypto: convert exported symbols in architecture-independent crypto to pluggable symbols
      x86/crypto: convert exported symbols in x86 crypto to pluggable symbols
      arm64/crypto: convert exported symbols in arm64 crypto to pluggable symbols
      Add standalone crypto kernel module technical documentation

Vegard Nossum (2):
      module: allow kernel module loading directly from memory
      crypto/algapi.c: skip crypto_check_module_sig() for the standalone crypto module

 Makefile                                         | 106 +++++-
 arch/arm64/crypto/Makefile                       |  23 +-
 arch/arm64/crypto/fips140/Makefile               |  14 +
 arch/arm64/crypto/fips140/fips140-var-redirect.c |   0
 arch/arm64/kernel/vmlinux.lds.S                  |  40 +++
 arch/x86/crypto/Makefile                         |  41 +--
 arch/x86/crypto/fips140/Makefile                 |  14 +
 arch/x86/crypto/fips140/fips140-var-redirect.c   |   0
 arch/x86/kernel/vmlinux.lds.S                    |  40 +++
 certs/system_keyring.c                           |   1 +
 crypto/Kconfig                                   |   1 +
 crypto/Makefile                                  | 207 ++++++------
 crypto/algapi.c                                  |  14 +-
 crypto/asymmetric_keys/Makefile                  |  16 +-
 crypto/asymmetric_keys/restrict.c                |   2 +
 crypto/asymmetric_keys/verify_pefile.c           |   1 +
 crypto/async_tx/Makefile                         |  12 +-
 crypto/fips140/Kconfig                           |  70 ++++
 crypto/fips140/Makefile                          |  25 ++
 crypto/fips140/README                            | 404 +++++++++++++++++++++++
 crypto/fips140/fips140-crypto-module-marker.h    |   8 +
 crypto/fips140/fips140-fn-redirect.c             |  10 +
 crypto/fips140/fips140-loader.c                  | 195 +++++++++++
 crypto/fips140/fips140-module.c                  | 155 +++++++++
 crypto/fips140/fips140-module.h                  |  30 ++
 crypto/fips140/fips140-var-redirect.c            |  78 +++++
 crypto/fips140/fips140.lds                       |  38 +++
 crypto/fips140/gen-fips140-fn-redirect.sh        |  28 ++
 crypto/krb5/Makefile                             |   2 +-
 include/asm-generic/vmlinux.lds.h                |   2 +
 include/crypto/cast_common.h                     |  17 +-
 include/crypto/fips140-fn-redirect.h             |  63 ++++
 include/crypto/fips140-redirect.h                |  92 ++++++
 include/crypto/md5.h                             |   8 +-
 include/crypto/public_key.h                      |   7 +-
 include/crypto/rng.h                             |   1 +
 include/crypto/sm4.h                             |  13 +-
 include/keys/asymmetric-type.h                   |   7 +-
 include/linux/export.h                           |  22 ++
 include/linux/init.h                             |  10 +
 include/linux/module.h                           |  25 ++
 include/uapi/linux/module.h                      |   6 +
 init/main.c                                      |   4 +
 kernel/bpf/btf.c                                 |  20 ++
 kernel/module/internal.h                         |   1 +
 kernel/module/main.c                             | 185 +++++++++--
 kernel/module/version.c                          |   9 +
 kernel/params.c                                  |   3 +-
 scripts/Makefile.build                           | 124 ++++++-
 scripts/Makefile.modfinal                        |  38 +++
 scripts/Makefile.modinst                         |  13 +-
 scripts/Makefile.modpost                         |  25 ++
 scripts/Makefile.vmlinux                         |  59 +++-
 scripts/link-vmlinux.sh                          |  26 ++
 scripts/mod/modpost.c                            |  24 +-
 55 files changed, 2182 insertions(+), 197 deletions(-)
 create mode 100644 arch/arm64/crypto/fips140/Makefile
 create mode 100644 arch/arm64/crypto/fips140/fips140-var-redirect.c
 create mode 100644 arch/x86/crypto/fips140/Makefile
 create mode 100644 arch/x86/crypto/fips140/fips140-var-redirect.c
 create mode 100644 crypto/fips140/Kconfig
 create mode 100644 crypto/fips140/Makefile
 create mode 100644 crypto/fips140/README
 create mode 100644 crypto/fips140/fips140-crypto-module-marker.h
 create mode 100644 crypto/fips140/fips140-fn-redirect.c
 create mode 100644 crypto/fips140/fips140-loader.c
 create mode 100644 crypto/fips140/fips140-module.c
 create mode 100644 crypto/fips140/fips140-module.h
 create mode 100644 crypto/fips140/fips140-var-redirect.c
 create mode 100644 crypto/fips140/fips140.lds
 create mode 100755 crypto/fips140/gen-fips140-fn-redirect.sh
 create mode 100644 include/crypto/fips140-fn-redirect.h
 create mode 100644 include/crypto/fips140-redirect.h

-- 
2.47.3


^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Shuah Khan @ 2026-04-17 17:27 UTC (permalink / raw)
  To: Mark Brown
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci, Shuah Khan
In-Reply-To: <e54a02b1-dd0b-4dd4-93aa-0484bb2cd8fe@sirena.org.uk>

On 4/17/26 07:30, Mark Brown wrote:
> On Thu, Apr 16, 2026 at 03:15:30PM -0600, Shuah Khan wrote:
> 
>> Just a quick note to say I applied all 3 patches and will send pr tomorrow.
> 
> Confirmed that everything seems to be running fine in -next for me.  I
> am seeing the test number duplicated in the log messages from the
> wrapper:
> 
>    ok 59 59 selftests: arm64: syscall-abi
> 
> which is confusing my parser a little but is less of an emergency, I'll
> take a look.

Just about to send pr when I noticed your patch to fix the above.
I applied it to linux-kselftest next and will send a combined pr
with all 4 patches tomorrow.

Thanks for fixing these regressions.

thanks,
-- Shuah

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Mark Brown @ 2026-04-17 13:30 UTC (permalink / raw)
  To: Shuah Khan
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci
In-Reply-To: <0420ebf1-2598-4f4f-bd09-95774156b48b@linuxfoundation.org>

[-- Attachment #1: Type: text/plain, Size: 414 bytes --]

On Thu, Apr 16, 2026 at 03:15:30PM -0600, Shuah Khan wrote:

> Just a quick note to say I applied all 3 patches and will send pr tomorrow.

Confirmed that everything seems to be running fine in -next for me.  I
am seeing the test number duplicated in the log messages from the
wrapper:

  ok 59 59 selftests: arm64: syscall-abi

which is confusing my parser a little but is less of an emergency, I'll
take a look.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Mark Brown @ 2026-04-17 10:36 UTC (permalink / raw)
  To: Shuah Khan
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci
In-Reply-To: <0420ebf1-2598-4f4f-bd09-95774156b48b@linuxfoundation.org>

[-- Attachment #1: Type: text/plain, Size: 441 bytes --]

On Thu, Apr 16, 2026 at 03:15:30PM -0600, Shuah Khan wrote:
> On 4/16/26 09:21, Shuah Khan wrote:

> > Yes 2964f6b816c2 is my first suspect with ktap_helpers.sh no such file.
> > Thank you for fixing this. That way we can patch it and not revert it.

> Just a quick note to say I applied all 3 patches and will send pr tomorrow.

Thanks Shuah!  I'll try to confirm everything looks good when they're
all merged together after today's -next.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v7] kbuild: host: use single executable for rustc -C linker
From: Yoann Congal @ 2026-04-17  7:59 UTC (permalink / raw)
  To: Mohamad Alsadhan, Nathan Chancellor, Nicolas Schier, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: linux-kbuild, linux-kernel, rust-for-linux
In-Reply-To: <20260416211525.13847-1-mo@sdhn.cc>

On Thu Apr 16, 2026 at 11:15 PM CEST, Mohamad Alsadhan wrote:
> rustc's -C linker= option expects a single executable path. When
> HOSTCC contains a wrapper (e.g. "ccache gcc"), passing
> `-Clinker=$(HOSTCC)` results in the shell splitting the value into
> multiple words, and rustc interprets the additional word as an
> input filename:
>
>   error: multiple input filenames provided ...
>
> Generate a small wrapper script and pass it to -Clinker e.g.
>
>   ```
>   #!/bin/sh
>   exec ccache gcc "$@"
>   ```
>
> This fix should be general enough to address most if not all cases
> (incl. wrappers or subcommands) and avoids surprises of simpler fixes
> like just defaulting to gcc.
>
> This avoids passing the user command as an environment variable as
> that would be more challenging to trace and debug shell expansions.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1224
> Suggested-by: Yoann Congal <yoann.congal@smile.fr>
> Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>

This does work on my ccache-enabled Yocto build, so:
Tested-by: Yoann Congal <yoann.congal@smile.fr>

Thanks!

> ---
> v6 -> v7:
>   - Always generate `scripts/rustc-wrapper` when `CONFIG_RUST=y`,
>     including cases with no Rust host programs in `scripts/`.
>   - Use `$(obj)/rustc-wrapper` for host Rust programs, fixing builds
>     outside `scripts/`, e.g. `samples/rust/hostprogs/`.
>   - remove leading exec (again) to allow leading env vars e.g.
>     HOSTRUSTC_LD="VAR=VAL ccache gcc".
>   - Track, clean and ignore generated wrapper as needed.
>
> v5 -> v6:
>   - Add fix to `rust/Makefile` as well (Yoann)
>   - Include script to `.gitignore` and make clean (Nicolas)
>   - Add back the outer `exec` to the command
>
> v4 -> v5:
>   - Fix word splitting issues
>   - Remove unnecessary `exec sh -c` and simplify generated script
>
> v3 -> v4:
>   - Use filechk instead of if_changed macro to regenerate script
>   - Remove trailing space at EOL
>
> v2 -> v3:
>   - Scrap previous hacky approaches (e.g. using lastword) and go with
>     a proper fix (Gary) which turned out not that complex to
>     implement.
>
> v1 -> v2:
>   - Rename HOSTRUSTC_LINKER to HOSTRUSTC_LD for consistency
>   - Introduce explicit HOSTRUSTC_LD override
>   - Warn when falling back due to multi-argument HOSTCC
>   - Error out if a user-specified HOSTRUSTC_LD is not an executable
>
> v1: https://lore.kernel.org/all/20260225102819.16553-1-mo@sdhn.cc/
> v2: https://lore.kernel.org/all/20260227132713.23106-1-mo@sdhn.cc/
> v3: https://lore.kernel.org/all/20260312002852.11292-1-mo@sdhn.cc/
> v4: https://lore.kernel.org/all/20260317112021.14353-1-mo@sdhn.cc/
> v5: https://lore.kernel.org/all/20260321150034.9915-1-mo@sdhn.cc/
> v6: https://lore.kernel.org/all/20260331000802.380-1-mo@sdhn.cc/
> ---
>  Makefile                          |  3 ++-
>  rust/Makefile                     |  8 +++++---
>  samples/rust/hostprogs/.gitignore |  1 +
>  samples/rust/hostprogs/Makefile   |  2 ++
>  scripts/.gitignore                |  1 +
>  scripts/Makefile                  |  3 +++
>  scripts/Makefile.host             | 26 +++++++++++++++++++++++---
>  7 files changed, 37 insertions(+), 7 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 1a219bf1c..5ebeef67f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1651,7 +1651,8 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
>  	       modules.builtin.ranges vmlinux.o.map vmlinux.unstripped \
>  	       compile_commands.json rust/test \
>  	       rust-project.json .vmlinux.objs .vmlinux.export.c \
> -               .builtin-dtbs-list .builtin-dtb.S
> +               .builtin-dtbs-list .builtin-dtb.S \
> +	       scripts/rustc-wrapper
>  
>  # Directories & files removed with 'make mrproper'
>  MRPROPER_FILES += include/config include/generated          \
> diff --git a/rust/Makefile b/rust/Makefile
> index 5eca6a817..6bc761a31 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -565,7 +565,7 @@ $(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE
>  quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
>        cmd_rustc_procmacro = \
>  	$(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
> -		-Clinker-flavor=gcc -Clinker=$(HOSTCC) \
> +		-Clinker-flavor=gcc -Clinker=scripts/rustc-wrapper \
>  		-Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \
>  		--emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \
>  		--crate-type proc-macro -L$(objtree)/$(obj) \
> @@ -576,12 +576,14 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
>  $(obj)/$(libmacros_name): private rustc_target_flags = \
>      --extern proc_macro2 --extern quote --extern syn
>  $(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \
> -    $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
> +    $(obj)/libquote.rlib $(obj)/libsyn.rlib \
> +    scripts/rustc-wrapper FORCE
>  	+$(call if_changed_dep,rustc_procmacro)
>  
>  $(obj)/$(libpin_init_internal_name): private rustc_target_flags = $(pin_init_internal-flags)
>  $(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/lib.rs \
> -    $(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
> +    $(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib \
> +    scripts/rustc-wrapper FORCE
>  	+$(call if_changed_dep,rustc_procmacro)
>  
>  # `rustc` requires `-Zunstable-options` to use custom target specifications
> diff --git a/samples/rust/hostprogs/.gitignore b/samples/rust/hostprogs/.gitignore
> index a6c173da5..d88a75790 100644
> --- a/samples/rust/hostprogs/.gitignore
> +++ b/samples/rust/hostprogs/.gitignore
> @@ -1,3 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0
>  
>  single
> +rustc-wrapper
> diff --git a/samples/rust/hostprogs/Makefile b/samples/rust/hostprogs/Makefile
> index 8ddcbd741..9c9663a77 100644
> --- a/samples/rust/hostprogs/Makefile
> +++ b/samples/rust/hostprogs/Makefile
> @@ -3,3 +3,5 @@
>  hostprogs-always-y := single
>  
>  single-rust := y
> +
> +clean-files += rustc-wrapper
> diff --git a/scripts/.gitignore b/scripts/.gitignore
> index 4215c2208..b3948b148 100644
> --- a/scripts/.gitignore
> +++ b/scripts/.gitignore
> @@ -6,6 +6,7 @@
>  /kallsyms
>  /module.lds
>  /recordmcount
> +/rustc-wrapper
>  /rustdoc_test_builder
>  /rustdoc_test_gen
>  /sign-file
> diff --git a/scripts/Makefile b/scripts/Makefile
> index 0941e5ce7..287421322 100644
> --- a/scripts/Makefile
> +++ b/scripts/Makefile
> @@ -29,6 +29,9 @@ generate_rust_target-rust := y
>  rustdoc_test_builder-rust := y
>  rustdoc_test_gen-rust := y
>  
> +always-$(CONFIG_RUST) += rustc-wrapper
> +clean-files += rustc-wrapper
> +
>  HOSTCFLAGS_tracepoint-update.o = -I$(srctree)/tools/include
>  HOSTCFLAGS_elf-parse.o = -I$(srctree)/tools/include
>  HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
> diff --git a/scripts/Makefile.host b/scripts/Makefile.host
> index c1dedf646..84fd87a53 100644
> --- a/scripts/Makefile.host
> +++ b/scripts/Makefile.host
> @@ -87,11 +87,30 @@ hostcxx_flags  = -Wp,-MMD,$(depfile) \
>                   $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
>                   $(HOSTCXXFLAGS_$(target-stem).o)
>  
> +# rustc's `-Clinker=` expects a single executable path, not a command line.
> +# `HOSTCC` may be a multi-word command when wrapped (e.g. "ccache gcc"), which
> +# would otherwise be split by the shell and mis-parsed by rustc.
> +# To work around this, we generate a wrapper script that forwards arguments to
> +# `HOSTRUSTC_LD` so that such commands can be used safely.
> +#
> +# Set `HOSTRUSTC_LD` for a different rustc linker command than `HOSTCC`
> +HOSTRUSTC_LD ?= $(HOSTCC)
> +
> +define filechk_rustc-wrapper
> +	printf "%s\n" \
> +		'#!/bin/sh' \
> +		'$(call escsq,$(HOSTRUSTC_LD)) "$$@"'
> +endef
> +
> +$(obj)/rustc-wrapper: FORCE
> +	$(call filechk,rustc-wrapper)
> +	$(Q)chmod +x $@
> +
>  # `--out-dir` is required to avoid temporaries being created by `rustc` in the
>  # current working directory, which may be not accessible in the out-of-tree
>  # modules case.
>  hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
> -		 -Clinker-flavor=gcc -Clinker=$(HOSTCC) \
> +		 -Clinker-flavor=gcc -Clinker=$(obj)/rustc-wrapper \
>  		 -Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \
>                   $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
>                   $(HOSTRUSTFLAGS_$(target-stem))
> @@ -153,10 +172,11 @@ $(host-cxxobjs): $(obj)/%.o: $(obj)/%.cc FORCE
>  quiet_cmd_host-rust	= HOSTRUSTC $@
>        cmd_host-rust	= \
>  	$(HOSTRUSTC) $(hostrust_flags) --emit=link=$@ $<
> -$(host-rust): $(obj)/%: $(src)/%.rs FORCE
> +$(host-rust): $(obj)/%: $(src)/%.rs $(obj)/rustc-wrapper FORCE
>  	+$(call if_changed_dep,host-rust)
>  
> -targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \
> +targets += $(obj)/rustc-wrapper \
> +	   $(host-csingle) $(host-cmulti) $(host-cobjs) \
>  	   $(host-cxxmulti) $(host-cxxobjs) $(host-rust)
>  
>  # %.lex.o <- %.lex.c <- %.l


-- 
Yoann Congal
Smile ECS


^ permalink raw reply

* [PATCH v7] kbuild: host: use single executable for rustc -C linker
From: Mohamad Alsadhan @ 2026-04-16 21:15 UTC (permalink / raw)
  To: Nathan Chancellor, Nicolas Schier, Miguel Ojeda, Boqun Feng,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: Mohamad Alsadhan, Yoann Congal, linux-kbuild, linux-kernel,
	rust-for-linux

rustc's -C linker= option expects a single executable path. When
HOSTCC contains a wrapper (e.g. "ccache gcc"), passing
`-Clinker=$(HOSTCC)` results in the shell splitting the value into
multiple words, and rustc interprets the additional word as an
input filename:

  error: multiple input filenames provided ...

Generate a small wrapper script and pass it to -Clinker e.g.

  ```
  #!/bin/sh
  exec ccache gcc "$@"
  ```

This fix should be general enough to address most if not all cases
(incl. wrappers or subcommands) and avoids surprises of simpler fixes
like just defaulting to gcc.

This avoids passing the user command as an environment variable as
that would be more challenging to trace and debug shell expansions.

Link: https://github.com/Rust-for-Linux/linux/issues/1224
Suggested-by: Yoann Congal <yoann.congal@smile.fr>
Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
---
v6 -> v7:
  - Always generate `scripts/rustc-wrapper` when `CONFIG_RUST=y`,
    including cases with no Rust host programs in `scripts/`.
  - Use `$(obj)/rustc-wrapper` for host Rust programs, fixing builds
    outside `scripts/`, e.g. `samples/rust/hostprogs/`.
  - remove leading exec (again) to allow leading env vars e.g.
    HOSTRUSTC_LD="VAR=VAL ccache gcc".
  - Track, clean and ignore generated wrapper as needed.

v5 -> v6:
  - Add fix to `rust/Makefile` as well (Yoann)
  - Include script to `.gitignore` and make clean (Nicolas)
  - Add back the outer `exec` to the command

v4 -> v5:
  - Fix word splitting issues
  - Remove unnecessary `exec sh -c` and simplify generated script

v3 -> v4:
  - Use filechk instead of if_changed macro to regenerate script
  - Remove trailing space at EOL

v2 -> v3:
  - Scrap previous hacky approaches (e.g. using lastword) and go with
    a proper fix (Gary) which turned out not that complex to
    implement.

v1 -> v2:
  - Rename HOSTRUSTC_LINKER to HOSTRUSTC_LD for consistency
  - Introduce explicit HOSTRUSTC_LD override
  - Warn when falling back due to multi-argument HOSTCC
  - Error out if a user-specified HOSTRUSTC_LD is not an executable

v1: https://lore.kernel.org/all/20260225102819.16553-1-mo@sdhn.cc/
v2: https://lore.kernel.org/all/20260227132713.23106-1-mo@sdhn.cc/
v3: https://lore.kernel.org/all/20260312002852.11292-1-mo@sdhn.cc/
v4: https://lore.kernel.org/all/20260317112021.14353-1-mo@sdhn.cc/
v5: https://lore.kernel.org/all/20260321150034.9915-1-mo@sdhn.cc/
v6: https://lore.kernel.org/all/20260331000802.380-1-mo@sdhn.cc/
---
 Makefile                          |  3 ++-
 rust/Makefile                     |  8 +++++---
 samples/rust/hostprogs/.gitignore |  1 +
 samples/rust/hostprogs/Makefile   |  2 ++
 scripts/.gitignore                |  1 +
 scripts/Makefile                  |  3 +++
 scripts/Makefile.host             | 26 +++++++++++++++++++++++---
 7 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile
index 1a219bf1c..5ebeef67f 100644
--- a/Makefile
+++ b/Makefile
@@ -1651,7 +1651,8 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
 	       modules.builtin.ranges vmlinux.o.map vmlinux.unstripped \
 	       compile_commands.json rust/test \
 	       rust-project.json .vmlinux.objs .vmlinux.export.c \
-               .builtin-dtbs-list .builtin-dtb.S
+               .builtin-dtbs-list .builtin-dtb.S \
+	       scripts/rustc-wrapper
 
 # Directories & files removed with 'make mrproper'
 MRPROPER_FILES += include/config include/generated          \
diff --git a/rust/Makefile b/rust/Makefile
index 5eca6a817..6bc761a31 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -565,7 +565,7 @@ $(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE
 quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
       cmd_rustc_procmacro = \
 	$(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
-		-Clinker-flavor=gcc -Clinker=$(HOSTCC) \
+		-Clinker-flavor=gcc -Clinker=scripts/rustc-wrapper \
 		-Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \
 		--emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \
 		--crate-type proc-macro -L$(objtree)/$(obj) \
@@ -576,12 +576,14 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
 $(obj)/$(libmacros_name): private rustc_target_flags = \
     --extern proc_macro2 --extern quote --extern syn
 $(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \
-    $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
+    $(obj)/libquote.rlib $(obj)/libsyn.rlib \
+    scripts/rustc-wrapper FORCE
 	+$(call if_changed_dep,rustc_procmacro)
 
 $(obj)/$(libpin_init_internal_name): private rustc_target_flags = $(pin_init_internal-flags)
 $(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/lib.rs \
-    $(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
+    $(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib \
+    scripts/rustc-wrapper FORCE
 	+$(call if_changed_dep,rustc_procmacro)
 
 # `rustc` requires `-Zunstable-options` to use custom target specifications
diff --git a/samples/rust/hostprogs/.gitignore b/samples/rust/hostprogs/.gitignore
index a6c173da5..d88a75790 100644
--- a/samples/rust/hostprogs/.gitignore
+++ b/samples/rust/hostprogs/.gitignore
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
 single
+rustc-wrapper
diff --git a/samples/rust/hostprogs/Makefile b/samples/rust/hostprogs/Makefile
index 8ddcbd741..9c9663a77 100644
--- a/samples/rust/hostprogs/Makefile
+++ b/samples/rust/hostprogs/Makefile
@@ -3,3 +3,5 @@
 hostprogs-always-y := single
 
 single-rust := y
+
+clean-files += rustc-wrapper
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 4215c2208..b3948b148 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -6,6 +6,7 @@
 /kallsyms
 /module.lds
 /recordmcount
+/rustc-wrapper
 /rustdoc_test_builder
 /rustdoc_test_gen
 /sign-file
diff --git a/scripts/Makefile b/scripts/Makefile
index 0941e5ce7..287421322 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -29,6 +29,9 @@ generate_rust_target-rust := y
 rustdoc_test_builder-rust := y
 rustdoc_test_gen-rust := y
 
+always-$(CONFIG_RUST) += rustc-wrapper
+clean-files += rustc-wrapper
+
 HOSTCFLAGS_tracepoint-update.o = -I$(srctree)/tools/include
 HOSTCFLAGS_elf-parse.o = -I$(srctree)/tools/include
 HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index c1dedf646..84fd87a53 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -87,11 +87,30 @@ hostcxx_flags  = -Wp,-MMD,$(depfile) \
                  $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
                  $(HOSTCXXFLAGS_$(target-stem).o)
 
+# rustc's `-Clinker=` expects a single executable path, not a command line.
+# `HOSTCC` may be a multi-word command when wrapped (e.g. "ccache gcc"), which
+# would otherwise be split by the shell and mis-parsed by rustc.
+# To work around this, we generate a wrapper script that forwards arguments to
+# `HOSTRUSTC_LD` so that such commands can be used safely.
+#
+# Set `HOSTRUSTC_LD` for a different rustc linker command than `HOSTCC`
+HOSTRUSTC_LD ?= $(HOSTCC)
+
+define filechk_rustc-wrapper
+	printf "%s\n" \
+		'#!/bin/sh' \
+		'$(call escsq,$(HOSTRUSTC_LD)) "$$@"'
+endef
+
+$(obj)/rustc-wrapper: FORCE
+	$(call filechk,rustc-wrapper)
+	$(Q)chmod +x $@
+
 # `--out-dir` is required to avoid temporaries being created by `rustc` in the
 # current working directory, which may be not accessible in the out-of-tree
 # modules case.
 hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
-		 -Clinker-flavor=gcc -Clinker=$(HOSTCC) \
+		 -Clinker-flavor=gcc -Clinker=$(obj)/rustc-wrapper \
 		 -Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \
                  $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
                  $(HOSTRUSTFLAGS_$(target-stem))
@@ -153,10 +172,11 @@ $(host-cxxobjs): $(obj)/%.o: $(obj)/%.cc FORCE
 quiet_cmd_host-rust	= HOSTRUSTC $@
       cmd_host-rust	= \
 	$(HOSTRUSTC) $(hostrust_flags) --emit=link=$@ $<
-$(host-rust): $(obj)/%: $(src)/%.rs FORCE
+$(host-rust): $(obj)/%: $(src)/%.rs $(obj)/rustc-wrapper FORCE
 	+$(call if_changed_dep,host-rust)
 
-targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \
+targets += $(obj)/rustc-wrapper \
+	   $(host-csingle) $(host-cmulti) $(host-cobjs) \
 	   $(host-cxxmulti) $(host-cxxobjs) $(host-rust)
 
 # %.lex.o <- %.lex.c <- %.l
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Shuah Khan @ 2026-04-16 21:15 UTC (permalink / raw)
  To: Mark Brown
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci, Shuah Khan
In-Reply-To: <9c9f9851-5962-4281-9f34-a1f2e012b13e@linuxfoundation.org>

On 4/16/26 09:21, Shuah Khan wrote:
> On 4/16/26 09:15, Mark Brown wrote:
>> On Thu, Apr 16, 2026 at 09:08:17AM -0600, Shuah Khan wrote:
>>> On 4/16/26 07:16, Mark Brown wrote:
>>
>>>> Sending shortly, FWIW I'm also seeing a buch of issues with:
>>
>>>> ./run_kselftest.sh: 5: ./kselftest/runner.sh: Bad substitution
>>>> ./run_kselftest.sh: 5: .: cannot open ./ktap_helpers.sh: No such file
>>
>>> I will take a look and isolate the two commits that changes
>>> run_kselftest.sh - sorry for the trouble with CI this time
>>> around.
>>
>> Pretty sure it's 2964f6b816c2 (selftests: Use ktap helpers for
>> runner.sh) - I've just put together a fix for that one, will throw it at
>> my testing and send it later today all being well.  It uses readlink -e
>> which isn't implemented by busybox.
> 
> Yes 2964f6b816c2 is my first suspect with ktap_helpers.sh no such file.
> Thank you for fixing this. That way we can patch it and not revert it.
> 

Just a quick note to say I applied all 3 patches and will send pr tomorrow.

thanks,
-- Shuah

^ permalink raw reply

* Re: [PATCH v6] kbuild: host: use single executable for rustc -C linker
From: Mohamad Alsadhan @ 2026-04-16 21:00 UTC (permalink / raw)
  To: Yoann Congal, Nathan Chancellor, Nicolas Schier, Miguel Ojeda,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
  Cc: linux-kbuild, linux-kernel, rust-for-linux
In-Reply-To: <DHHL2VVCVYHU.5RMX7GJ73MDR@smile.fr>

Apologies for getting back to you late, I was busy with other things
and I wanted to double-check things before replying.

On 26/04/01 07:53am, Yoann Congal wrote:
> 
> Does using "scripts/" without a $(obj)/$(srctree)/... prefix always works?
> I know I've suggested this as a quick fix. But I did not think about it
> a lot.
> 

You're in fact correct, it's not always correct. Thanks for pointing
it out :)

I assumed it was fine since the top-level build runs the scripts pass
before rust/, and existing Kbuild commands commonly refer to generated
tools under scripts/ using paths relative to the object tree.

That misses some cases:

- On e.g. ARM64 with `CONFIG_RUST_KERNEL_DOCTESTS=n`, no Rust hostprog
  may be built in `scripts/`, so `scripts/rustc-wrapper` may never be
  generated before `rust/Makefile` needs it.

- `scripts/Makefile.host` is also used outside `scripts/`. For example,
  `samples/rust/hostprogs/` generates
  `samples/rust/hostprogs/rustc-wrapper`, but the hardcoded path
   made rustc look for `scripts/rustc-wrapper`.

A v7 patch is on the way that should fix this issue, by always
generating `scripts/rustc-wrapper` for `CONFIG_RUST=y` and using
`$(obj)/rustc-wrapper` for generic host Rust builds (+ some little
hardening and cleaning).

Best regards,
Mo

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Shuah Khan @ 2026-04-16 15:21 UTC (permalink / raw)
  To: Mark Brown
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci, Shuah Khan
In-Reply-To: <a73aa838-d194-4867-86fb-42bc8d057fd9@sirena.org.uk>

On 4/16/26 09:15, Mark Brown wrote:
> On Thu, Apr 16, 2026 at 09:08:17AM -0600, Shuah Khan wrote:
>> On 4/16/26 07:16, Mark Brown wrote:
> 
>>> Sending shortly, FWIW I'm also seeing a buch of issues with:
> 
>>> ./run_kselftest.sh: 5: ./kselftest/runner.sh: Bad substitution
>>> ./run_kselftest.sh: 5: .: cannot open ./ktap_helpers.sh: No such file
> 
>> I will take a look and isolate the two commits that changes
>> run_kselftest.sh - sorry for the trouble with CI this time
>> around.
> 
> Pretty sure it's 2964f6b816c2 (selftests: Use ktap helpers for
> runner.sh) - I've just put together a fix for that one, will throw it at
> my testing and send it later today all being well.  It uses readlink -e
> which isn't implemented by busybox.

Yes 2964f6b816c2 is my first suspect with ktap_helpers.sh no such file.
Thank you for fixing this. That way we can patch it and not revert it.

thanks,
-- SHuah

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Mark Brown @ 2026-04-16 15:15 UTC (permalink / raw)
  To: Shuah Khan
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci
In-Reply-To: <c834846c-96d5-405c-97d9-f182b8fe1569@linuxfoundation.org>

[-- Attachment #1: Type: text/plain, Size: 685 bytes --]

On Thu, Apr 16, 2026 at 09:08:17AM -0600, Shuah Khan wrote:
> On 4/16/26 07:16, Mark Brown wrote:

> > Sending shortly, FWIW I'm also seeing a buch of issues with:

> > ./run_kselftest.sh: 5: ./kselftest/runner.sh: Bad substitution
> > ./run_kselftest.sh: 5: .: cannot open ./ktap_helpers.sh: No such file

> I will take a look and isolate the two commits that changes
> run_kselftest.sh - sorry for the trouble with CI this time
> around.

Pretty sure it's 2964f6b816c2 (selftests: Use ktap helpers for
runner.sh) - I've just put together a fix for that one, will throw it at
my testing and send it later today all being well.  It uses readlink -e
which isn't implemented by busybox.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Shuah Khan @ 2026-04-16 15:08 UTC (permalink / raw)
  To: Mark Brown
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci, Shuah Khan
In-Reply-To: <e4b82973-7d9e-454d-8f69-6d2a1a8ec7dc@sirena.org.uk>

On 4/16/26 07:16, Mark Brown wrote:
> On Wed, Apr 15, 2026 at 05:25:40PM +0100, Mark Brown wrote:
>> On Wed, Apr 15, 2026 at 09:40:37AM -0600, Shuah Khan wrote:
> 
>>> Mark, would you like to a revert for this?
> 
>> Yes, I'll massage the text from my report into a changelog send
>> something - it'll probably be tomorrow now.
> 
> Sending shortly, FWIW I'm also seeing a buch of issues with:
> 
> ./run_kselftest.sh: 5: ./kselftest/runner.sh: Bad substitution
> ./run_kselftest.sh: 5: .: cannot open ./ktap_helpers.sh: No such file

I will take a look and isolate the two commits that changes
run_kselftest.sh - sorry for the trouble with CI this time
around.

thanks,
-- Shuah

^ permalink raw reply

* Re: [PATCH v2] slab: support for compiler-assisted type-based slab cache partitioning
From: Marco Elver @ 2026-04-16 13:42 UTC (permalink / raw)
  To: elver, Vlastimil Babka, Andrew Morton
  Cc: Nathan Chancellor, Nicolas Schier, Dennis Zhou, Tejun Heo,
	Christoph Lameter, Harry Yoo, Hao Li, David Rientjes,
	Roman Gushchin, Kees Cook, Gustavo A. R. Silva, David Hildenbrand,
	Lorenzo Stoakes, Liam R. Howlett, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Alexander Potapenko,
	Dmitry Vyukov, Nick Desaulniers, Bill Wendling, Justin Stitt,
	linux-kbuild, linux-kernel, linux-mm, linux-hardening, kasan-dev,
	llvm, Andrey Konovalov, Florent Revest, Jann Horn, KP Singh,
	Matteo Rizzo, GONG Ruiqi
In-Reply-To: <20260415143735.2974230-1-elver@google.com>

On Wed, 15 Apr 2026 at 16:37, Marco Elver <elver@google.com> wrote:
>
> Rework the general infrastructure around RANDOM_KMALLOC_CACHES into more
> flexible PARTITION_KMALLOC_CACHES, with the former being a partitioning
> mode of the latter.
>
> Introduce a new mode, TYPED_KMALLOC_CACHES, which leverages a feature
> available in Clang 22 and later, called "allocation tokens" via
> __builtin_infer_alloc_token [1]. Unlike RANDOM_KMALLOC_CACHES, this mode
> deterministically assigns a slab cache to an allocation of type T,
> regardless of allocation site.
>
> The builtin __builtin_infer_alloc_token(<malloc-args>, ...) instructs
> the compiler to infer an allocation type from arguments commonly passed
> to memory-allocating functions and returns a type-derived token ID. The
> implementation passes kmalloc-args to the builtin: the compiler performs
> best-effort type inference, and then recognizes common patterns such as
> `kmalloc(sizeof(T), ...)`, `kmalloc(sizeof(T) * n, ...)`, but also
> `(T *)kmalloc(...)`. Where the compiler fails to infer a type the
> fallback token (default: 0) is chosen.
>
> Note: kmalloc_obj(..) APIs fix the pattern how size and result type are
> expressed, and therefore ensures there's not much drift in which
> patterns the compiler needs to recognize. Specifically, kmalloc_obj()
> and friends expand to `(TYPE *)KMALLOC(__obj_size, GFP)`, which the
> compiler recognizes via the cast to TYPE*.
>
> Clang's default token ID calculation is described as [1]:
>
>    typehashpointersplit: This mode assigns a token ID based on the hash
>    of the allocated type's name, where the top half ID-space is reserved
>    for types that contain pointers and the bottom half for types that do
>    not contain pointers.
>
> Separating pointer-containing objects from pointerless objects and data
> allocations can help mitigate certain classes of memory corruption
> exploits [2]: attackers who gains a buffer overflow on a primitive
> buffer cannot use it to directly corrupt pointers or other critical
> metadata in an object residing in a different, isolated heap region.
>
> It is important to note that heap isolation strategies offer a
> best-effort approach, and do not provide a 100% security guarantee,
> albeit achievable at relatively low performance cost. Note that this
> also does not prevent cross-cache attacks: while waiting for future
> features like SLAB_VIRTUAL [3] to provide physical page isolation, this
> feature should be deployed alongside SHUFFLE_PAGE_ALLOCATOR and
> init_on_free=1 to mitigate cross-cache attacks and page-reuse attacks as
> much as possible today.
>
> With all that, my kernel (x86 defconfig) shows me a histogram of slab
> cache object distribution per /proc/slabinfo (after boot):
>
>   <slab cache>      <objs> <hist>
>   kmalloc-part-15    1465  ++++++++++++++
>   kmalloc-part-14    2988  +++++++++++++++++++++++++++++
>   kmalloc-part-13    1656  ++++++++++++++++
>   kmalloc-part-12    1045  ++++++++++
>   kmalloc-part-11    1697  ++++++++++++++++
>   kmalloc-part-10    1489  ++++++++++++++
>   kmalloc-part-09     965  +++++++++
>   kmalloc-part-08     710  +++++++
>   kmalloc-part-07     100  +
>   kmalloc-part-06     217  ++
>   kmalloc-part-05     105  +
>   kmalloc-part-04    4047  ++++++++++++++++++++++++++++++++++++++++
>   kmalloc-part-03     183  +
>   kmalloc-part-02     283  ++
>   kmalloc-part-01     316  +++
>   kmalloc            1422  ++++++++++++++
>
> The above /proc/slabinfo snapshot shows me there are 6673 allocated
> objects (slabs 00 - 07) that the compiler claims contain no pointers or
> it was unable to infer the type of, and 12015 objects that contain
> pointers (slabs 08 - 15). On a whole, this looks relatively sane.
>
> Additionally, when I compile my kernel with -Rpass=alloc-token, which
> provides diagnostics where (after dead-code elimination) type inference
> failed, I see 186 allocation sites where the compiler failed to identify
> a type (down from 966 when I sent the RFC [4]). Some initial review
> confirms these are mostly variable sized buffers, but also include
> structs with trailing flexible length arrays.
>
> Link: https://clang.llvm.org/docs/AllocToken.html [1]
> Link: https://blog.dfsec.com/ios/2025/05/30/blasting-past-ios-18/ [2]
> Link: https://lwn.net/Articles/944647/ [3]
> Link: https://lore.kernel.org/all/20250825154505.1558444-1-elver@google.com/ [4]
> Link: https://discourse.llvm.org/t/rfc-a-framework-for-allocator-partitioning-hints/87434
> Acked-by: GONG Ruiqi <gongruiqi1@huawei.com>
> Co-developed-by: Harry Yoo (Oracle) <harry@kernel.org>
> Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
> Signed-off-by: Marco Elver <elver@google.com>

Sashiko found 2 latent issues in the diff context :
https://sashiko.dev/#/patchset/20260415143735.2974230-1-elver%40google.com
The fix is here:
https://lore.kernel.org/all/20260416132837.3787694-1-elver@google.com/

The irony is that TYPED_KMALLOC_CACHES would have helped mitigate this
kind of overflow bug.

^ permalink raw reply

* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Herve Codina @ 2026-04-16 13:34 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Chen-Yu Tsai, Andy Shevchenko, Manivannan Sadhasivam, Rob Herring,
	Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor, Nicolas Schier,
	Hans de Goede, Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Bartosz Golaszewski,
	linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
	linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
	Stephan Gerhold, Dmitry Baryshkov, linux-acpi, Hans de Goede,
	Bartosz Golaszewski, Luca Ceresoli
In-Reply-To: <4yockfx5rjcvfh2n2excrgsknnhi72rv2w7wf7onks2ryt33sm@w7zkcxuc6vem>

Hi Manivannan,

On Thu, 16 Apr 2026 14:25:39 +0530
Manivannan Sadhasivam <mani@kernel.org> wrote:

> On Wed, Apr 15, 2026 at 04:56:51PM +0200, Herve Codina wrote:
> > Hi Chen, all,
> > 
> > ...
> >    
> > > 
> > > I'm not arguing for a even more generic "M.2" connector. The "key" is
> > > already described in the compatible. I'm saying we should have some way
> > > of describing the individual interfaces (PCIe, SDIO, USB, UART, I2S, I2C)
> > > on the connector so further nodes or properties can be attached to them,
> > > either with overlays or dynamically within the kernel. Right now the
> > > are only described as individual ports, but we can't actually tie a
> > > device to a OF graph port.
> > > 
> > > But maybe I'm overthinking the representation part. AFAICT for Qualcomm's
> > > UART-based BT bit part, Mani just had the driver create a device node
> > > under the UART (by traversing the OF graph to find the UART). If that's
> > > the desired way then the connector binding should mention it. And that
> > > works for me. But I think it's messier and also we're missing an
> > > opportunity to make the M.2 connector a standardized attachment point
> > > for overlays.
> > > 
> > > Mani, could you also chime in a bit on what you envisioned?
> > > 
> > > (Added Luca from Bootlin to CC, as I think there are parallels to the
> > >  "Hotplug of Non-discoverable Hardware" work)
> > >  
> > 
> > Related to "Hotplug of Non-discoverable Hardware",
> > 
> > I would add entries for busses in the connector without using an OF graph.
> >   
> 
> I don't think this is a correct representation. It is non-standard to describe
> the device nodes in some other connectors. While it may work with your series in
> the future, not something I would bet-on at this point.
> 
> Using OF graph to link the connector nodes look like the cleaner solution to me.

In your DT binding, there is the i2c-parent property at connector level.

How it is used or planned to be used in order to handle devices available on the
board connected to the M2 connector ?

> 
> > For I2C and later SPI, this was is done.
> > 
> > You already have an i2c-parent property but no node where an i2c device
> > can be added.
> > 
> > The last discussion related to hotplug, connectors and DT led to the RFC
> > series [1].
> > 
> > It is a huge series. The last patch give a real example of representation:
> >   https://lore.kernel.org/all/20260112142009.1006236-78-herve.codina@bootlin.com/
> > 
> > In your case I would see some thing like:
> > 
> >     connector {
> >         compatible = "pcie-m2-e-connector";
> >         vpcie3v3-supply = <&vreg_wcn_3p3>;
> >         vpcie1v8-supply = <&vreg_l15b_1p8>;
> > 
> > 	/*
> > 	 * If those GPIOs have to be used by components available in
> > 	 * the connected board, a Nexus node should be used.
> >          */
> >         w-disable1-gpios = <&tlmm 115 GPIO_ACTIVE_LOW>;
> >         w-disable2-gpios = <&tlmm 116 GPIO_ACTIVE_LOW>;
> >         viocfg-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>;
> >         uart-wake-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>;
> >         sdio-wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>;
> >         sdio-reset-gpios = <&tlmm 120 GPIO_ACTIVE_LOW>;
> > 
> > 	conn-i2c {
> > 		i2c-parent = <&i2c0>;
> > 
> > 		/*
> >  		 * Here i2c devices available on the board
> > 		 * connected to the connector can be described.
> > 		 */
> > 	};
> > 
> > 	/* Same kind to description for other busses */
> > 	conn-pcie {
> > 		pci-parent = <&xxxxx>;
> > 
> > 		/*
> > 		 * The PCIe bus has abilities to discover devices.
> > 		 * Not sure this node is needed.
> > 		 *
> > 		 * If a PCI device need a DT description to describe
> > 		 * stuffs behind the device, what has been done for LAN966x
> > 		 * could be re-used [2] and [3]
> > 		 */  
> 
> I don't think anyone would connect something like LAN966x to the M.2 connector.
> M.2 cards have a defined purpose, like NVMe, WLAN etc... If anyone wants to
> connect another SoC like LAN966x, they would use non-M.2 connectors.

Hum, maybe yes, maybe not. I don't know what kind of hardware could be available
on a M2 connector.

One think sure is that a PCIe bus is available on the connector and so, potentially
all PCI devices could be wired on a M2 form factor.

LAN966x in PCI version is just a PCI device.

Anyway, Is it allowed to have sub-nodes in a port node ?

I mean, can we describe devices connected to a bus described by the port node ?

For USB and PCI it is probably not needed for common use cases but having a DT
description for devices on PCI and/or USB exists and is supported in the current
kernel

On SDIO, wireless devices can be described:
  Documentation/devicetree/bindings/net/wireless/

and so, sub-nodes will be needed.

As those devices need an address (reg property), #address-cells and
#size-cells will be needed.

This will end in a mix of sub-nodes describing devices and a sub-node
describing the endpoint connection.

#address-cells and #size-cells will conflict at some points.

Is a reg value for endpoints has the same characteristics as a reg value
for a SDIO device ?

How a BT devices is described under the UART available in the M2
connector ?

Best regards,
Hervé

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Mark Brown @ 2026-04-16 13:16 UTC (permalink / raw)
  To: Shuah Khan
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci
In-Reply-To: <ad-8BIkw_ijCLqcF@sirena.co.uk>

[-- Attachment #1: Type: text/plain, Size: 479 bytes --]

On Wed, Apr 15, 2026 at 05:25:40PM +0100, Mark Brown wrote:
> On Wed, Apr 15, 2026 at 09:40:37AM -0600, Shuah Khan wrote:

> > Mark, would you like to a revert for this?

> Yes, I'll massage the text from my report into a changelog send
> something - it'll probably be tomorrow now.

Sending shortly, FWIW I'm also seeing a buch of issues with:

./run_kselftest.sh: 5: ./kselftest/runner.sh: Bad substitution
./run_kselftest.sh: 5: .: cannot open ./ktap_helpers.sh: No such file

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Manivannan Sadhasivam @ 2026-04-16  8:55 UTC (permalink / raw)
  To: Herve Codina
  Cc: Chen-Yu Tsai, Andy Shevchenko, Manivannan Sadhasivam, Rob Herring,
	Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor, Nicolas Schier,
	Hans de Goede, Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Bartosz Golaszewski,
	linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
	linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
	Stephan Gerhold, Dmitry Baryshkov, linux-acpi, Hans de Goede,
	Bartosz Golaszewski, Luca Ceresoli
In-Reply-To: <20260415165651.153b573d@bootlin.com>

On Wed, Apr 15, 2026 at 04:56:51PM +0200, Herve Codina wrote:
> Hi Chen, all,
> 
> ...
>  
> > 
> > I'm not arguing for a even more generic "M.2" connector. The "key" is
> > already described in the compatible. I'm saying we should have some way
> > of describing the individual interfaces (PCIe, SDIO, USB, UART, I2S, I2C)
> > on the connector so further nodes or properties can be attached to them,
> > either with overlays or dynamically within the kernel. Right now the
> > are only described as individual ports, but we can't actually tie a
> > device to a OF graph port.
> > 
> > But maybe I'm overthinking the representation part. AFAICT for Qualcomm's
> > UART-based BT bit part, Mani just had the driver create a device node
> > under the UART (by traversing the OF graph to find the UART). If that's
> > the desired way then the connector binding should mention it. And that
> > works for me. But I think it's messier and also we're missing an
> > opportunity to make the M.2 connector a standardized attachment point
> > for overlays.
> > 
> > Mani, could you also chime in a bit on what you envisioned?
> > 
> > (Added Luca from Bootlin to CC, as I think there are parallels to the
> >  "Hotplug of Non-discoverable Hardware" work)
> >
> 
> Related to "Hotplug of Non-discoverable Hardware",
> 
> I would add entries for busses in the connector without using an OF graph.
> 

I don't think this is a correct representation. It is non-standard to describe
the device nodes in some other connectors. While it may work with your series in
the future, not something I would bet-on at this point.

Using OF graph to link the connector nodes look like the cleaner solution to me.

> For I2C and later SPI, this was is done.
> 
> You already have an i2c-parent property but no node where an i2c device
> can be added.
> 
> The last discussion related to hotplug, connectors and DT led to the RFC
> series [1].
> 
> It is a huge series. The last patch give a real example of representation:
>   https://lore.kernel.org/all/20260112142009.1006236-78-herve.codina@bootlin.com/
> 
> In your case I would see some thing like:
> 
>     connector {
>         compatible = "pcie-m2-e-connector";
>         vpcie3v3-supply = <&vreg_wcn_3p3>;
>         vpcie1v8-supply = <&vreg_l15b_1p8>;
> 
> 	/*
> 	 * If those GPIOs have to be used by components available in
> 	 * the connected board, a Nexus node should be used.
>          */
>         w-disable1-gpios = <&tlmm 115 GPIO_ACTIVE_LOW>;
>         w-disable2-gpios = <&tlmm 116 GPIO_ACTIVE_LOW>;
>         viocfg-gpios = <&tlmm 117 GPIO_ACTIVE_HIGH>;
>         uart-wake-gpios = <&tlmm 118 GPIO_ACTIVE_LOW>;
>         sdio-wake-gpios = <&tlmm 119 GPIO_ACTIVE_LOW>;
>         sdio-reset-gpios = <&tlmm 120 GPIO_ACTIVE_LOW>;
> 
> 	conn-i2c {
> 		i2c-parent = <&i2c0>;
> 
> 		/*
>  		 * Here i2c devices available on the board
> 		 * connected to the connector can be described.
> 		 */
> 	};
> 
> 	/* Same kind to description for other busses */
> 	conn-pcie {
> 		pci-parent = <&xxxxx>;
> 
> 		/*
> 		 * The PCIe bus has abilities to discover devices.
> 		 * Not sure this node is needed.
> 		 *
> 		 * If a PCI device need a DT description to describe
> 		 * stuffs behind the device, what has been done for LAN966x
> 		 * could be re-used [2] and [3]
> 		 */

I don't think anyone would connect something like LAN966x to the M.2 connector.
M.2 cards have a defined purpose, like NVMe, WLAN etc... If anyone wants to
connect another SoC like LAN966x, they would use non-M.2 connectors.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [PATCH v7 0/8] Add support for handling PCIe M.2 Key E connectors in devicetree
From: Manivannan Sadhasivam @ 2026-04-16  8:34 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Andy Shevchenko, Manivannan Sadhasivam, Rob Herring,
	Greg Kroah-Hartman, Jiri Slaby, Nathan Chancellor, Nicolas Schier,
	Hans de Goede, Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Bartosz Golaszewski,
	linux-serial, linux-kernel, linux-kbuild, platform-driver-x86,
	linux-pci, devicetree, linux-arm-msm, linux-bluetooth, linux-pm,
	Stephan Gerhold, Dmitry Baryshkov, linux-acpi, Hans de Goede,
	Bartosz Golaszewski, Luca Ceresoli
In-Reply-To: <CAGXv+5EPA29G-fsH=wWOD8AK6TZFezFhsE0NHPYj_Pt3nT+d_w@mail.gmail.com>

On Wed, Apr 15, 2026 at 04:31:24PM +0800, Chen-Yu Tsai wrote:
> On Tue, Apr 14, 2026 at 8:03 PM Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> >
> > On Tue, Apr 14, 2026 at 06:29:02PM +0800, Chen-Yu Tsai wrote:
> > > On Tue, Apr 14, 2026 at 4:28 PM Andy Shevchenko
> > > <andriy.shevchenko@linux.intel.com> wrote:
> > > > On Tue, Apr 14, 2026 at 01:03:19PM +0800, Chen-Yu Tsai wrote:
> > > > > On Tue, Apr 14, 2026 at 12:08 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > > > > > On Mon, Apr 13, 2026 at 07:33:12PM +0530, Manivannan Sadhasivam wrote:
> > > > > > > On Mon, Apr 13, 2026 at 03:54:59PM +0800, Chen-Yu Tsai wrote:
> > > > > > > > On Thu, Mar 26, 2026 at 01:36:28PM +0530, Manivannan Sadhasivam wrote:
> >
> > ...
> >
> > > > > > > > - Given that this connector actually represents two devices, how do I
> > > > > > > >   say I want the BT part to be a wakeup source, but not the WiFi part?
> > > > > > > >   Does wakeup-source even work at this point?
> > > > > > >
> > > > > > > You can't use the DT property since the devices are not described in DT
> > > > > > > statically. But you can still use the per-device 'wakeup' sysfs knob to enable
> > > > > > > wakeup.
> > > > >
> > > > > I see. I think not being able to specify generic properties for the devices
> > > > > on the connector is going to be a bit problematic.
> > > >
> > > > This is nature of the open-connectors, especially on the busses that are
> > > > hotpluggable, like PCIe. We never know what is connected there _ahead_.
> > >
> > > I believe what you mean by "hotpluggable" is "user replaceable".
> >
> > From the OS perspective it's the same. From platform perspective
> > there is a difference, granted.
> 
> Yes. I just wanted to clarify.
> 
> > > > In other words you can't describe in DT something that may not exist.
> > >
> > > But this is actually doable with the PCIe slot representation. The
> > > properties are put in the device node for the slot. If no card is
> > > actually inserted in the slot, then no device is created, and the
> > > device node is left as not associated with anything.
> >
> > But you need to list all devices in the world if you want to support this
> 
> Why would I need to? The PCIe slot representation just describes a
> PCIe bridge. Granted this might not be entirely correct, but it's
> what we currently have.
> 
> And even then, there are properties like memory-region or wakeup-source
> that are generic and aren't tied to specific devices.
> 
> > somehow. Yes, probably many of them (or majority) will be enumerated as is,
> > but some may need an assistance via (dynamic) properties or similar mechanisms.
> 
> Even if we wanted to add dynamic properties, there is currently no proper
> device node to attach them to.
> 

There are dynamic device nodes that we need to create for hotpluggable devices,
if we need to pass the DT properties to the driver. Like how we do it for PCIe,
serdev. You cannot describe static device nodes in DT for devices attached to
swappable cards like M.2.

> > > It's just that for this new M.2 E-key connector, there aren't separate
> > > nodes for each interface. And the system doesn't associate the device
> > > node with the device, because it's no longer a child node of the
> > > controller or hierarchy, but connected over the OF graph.
> > >
> > > Moving over to the E-key connector representation seems like one step
> > > forward and one step backward in descriptive ability. We gain proper
> > > power sequencing, but lose generic properties.
> >
> > The "key" is property of the connector. Hence if you have an idea what can be
> > common for ALL "key":s, that's probably can be abstracted. Note, I'm not
> > familiar with the connector framework in the Linux kernel, perhaps it's already
> > that kind of abstraction.
> 
> I'm not arguing for a even more generic "M.2" connector. The "key" is
> already described in the compatible. I'm saying we should have some way
> of describing the individual interfaces (PCIe, SDIO, USB, UART, I2S, I2C)
> on the connector so further nodes or properties can be attached to them,
> either with overlays or dynamically within the kernel. Right now the
> are only described as individual ports, but we can't actually tie a
> device to a OF graph port.
> 

If there are properties that apply to the interfaces, *not devices*, then you
can add them to the relevant endpoint node:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml#n167

> But maybe I'm overthinking the representation part. AFAICT for Qualcomm's
> UART-based BT bit part, Mani just had the driver create a device node
> under the UART (by traversing the OF graph to find the UART). If that's
> the desired way then the connector binding should mention it.

What do you mean by 'connector binding should mention it'? You cannot hardcode
the device node in the connector binding, because it is not part of the
connector binding itself. For example, the UART device node that is created for
the WCN7850, already has a binding:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/net/bluetooth/qcom,wcn7850-bt.yaml

What the driver does is, just creating that node under the serdev controller as
if the device was described statically in the DT.

For the wakeup property you asked earlier, it depends on the interface. If the
interface supports "in-band" wakeup like USB/SDIO, you can add the property in
the relevant controller node statically itself. For example, with USB XHCI
controller, you would know that the controller will support wakeup or not
statically. So you will add that property to the controller node. Then, if the
user has enabled the wakeup for a specific USB device like keyboard/mouse
through sysfs, then wakeup will just work. Here, we don't need to create the
USB device node at all.

But if the interface supports physical wakeup, like UART_WAKE# in M.2 SDIO Key
E, then based on the presence of that property, you would configure wakeup in
the connector driver itself. But this is not present as of now.

> And that
> works for me. But I think it's messier and also we're missing an
> opportunity to make the M.2 connector a standardized attachment point
> for overlays.
> 

I don't envision using overlays for the M.2 connectors. It is not strictly
needed, unless the connector is non-standard.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Shuah Khan @ 2026-04-15 16:39 UTC (permalink / raw)
  To: Mark Brown
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci, Shuah Khan
In-Reply-To: <ad-8BIkw_ijCLqcF@sirena.co.uk>

On 4/15/26 10:25, Mark Brown wrote:
> On Wed, Apr 15, 2026 at 09:40:37AM -0600, Shuah Khan wrote:
>> On 4/15/26 07:58, Mark Brown wrote:
> 
>>> This wasn't showing up in my -next build tests since I set FORCE_TARGETS
>>> and explicitly choose a restricted set of kselftests which actually
>>> build with my system and configuration.  It was less obvious than it
>>> should have been with the other systems since they did not expect there
>>> to be a complete failure to generate a kselftest tarball and variously
>>> masked the error or reported it in a manner that looked like an
>>> infrastructure issue.
> 
>> I didn't see it when I did test on linux-next and my repo. I did install
>> to catch problems.
> 
>> Sorry for not catching this. We can drop this patch.
> 
> Yeah, it's easy to miss if you're set up to build everything.
> 
>> Mark, would you like to a revert for this?
> 
> Yes, I'll massage the text from my report into a changelog send
> something - it'll probably be tomorrow now.

Thank you Mark

-- Shuah

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Mark Brown @ 2026-04-15 16:25 UTC (permalink / raw)
  To: Shuah Khan
  Cc: Ricardo B. Marlière, torvalds, Shuah Khan, Nathan Chancellor,
	Nicolas Schier, linux-kselftest, linux-kernel, linux-kbuild,
	Aishwarya.TCV, ben.copeland, kernelci
In-Reply-To: <3cdf8e79-7c59-4831-9b38-e9c2cef97fe1@linuxfoundation.org>

[-- Attachment #1: Type: text/plain, Size: 937 bytes --]

On Wed, Apr 15, 2026 at 09:40:37AM -0600, Shuah Khan wrote:
> On 4/15/26 07:58, Mark Brown wrote:

> > This wasn't showing up in my -next build tests since I set FORCE_TARGETS
> > and explicitly choose a restricted set of kselftests which actually
> > build with my system and configuration.  It was less obvious than it
> > should have been with the other systems since they did not expect there
> > to be a complete failure to generate a kselftest tarball and variously
> > masked the error or reported it in a manner that looked like an
> > infrastructure issue.

> I didn't see it when I did test on linux-next and my repo. I did install
> to catch problems.

> Sorry for not catching this. We can drop this patch.

Yeah, it's easy to miss if you're set up to build everything.

> Mark, would you like to a revert for this?

Yes, I'll massage the text from my report into a changelog send
something - it'll probably be tomorrow now.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Ricardo B. Marlière @ 2026-04-15 15:53 UTC (permalink / raw)
  To: Shuah Khan, Ricardo B. Marlière, Mark Brown, torvalds,
	Shuah Khan
  Cc: Nathan Chancellor, Nicolas Schier, linux-kselftest, linux-kernel,
	linux-kbuild, Aishwarya.TCV, ben.copeland, kernelci
In-Reply-To: <b80e905d-67bf-4c52-9b61-e52f3acc5b35@linuxfoundation.org>

On Wed Apr 15, 2026 at 12:52 PM -03, Shuah Khan wrote:
> On 4/15/26 09:42, Ricardo B. Marlière wrote:
>> On Wed Apr 15, 2026 at 12:40 PM -03, Shuah Khan wrote:
>>> On 4/15/26 07:58, Mark Brown wrote:
>>>> On Fri, Mar 20, 2026 at 03:29:20PM -0300, Ricardo B. Marlière wrote:
>>>>> Track failures explicitly in the top-level selftests all/install loops.
>>>>>
>>>>> The current code multiplies `ret` by each sub-make exit status. For
>>>>> example, with `TARGETS=net`, the implicit `net/lib` dependency runs after
>>>>> `net`, so a failed `net` build can be followed by a successful `net/lib`
>>>>> build and reset the final result to success.
>>>>>
>>>>> Set `ret` to 1 on any non-zero sub-make exit code and keep it sticky, so
>>>>> the top-level make returns failure when any selected selftest target
>>>>> fails.
>>>>
>>>> This patch, which is now in mainline as 7e47389142b8, is breaking a
>>>> bunch of CI systems - at least KernelCI, our Arm internal CI and my
>>>> personal stuff.  It causes the equivalent of FORCE_TARGETS behaviour in
>>>> the top level Makefile, the prior behaviour where the exit status of the
>>>> top level Makefile ignores failures from individual directories is
>>>> desirable since by default we try to build almost all the selftests but
>>>> between quality issues and build time dependencies it's very common for
>>>> at least one of them to fail.  With this commit unless the user has
>>>> configured a more restricted set of selftests it would be surprising if
>>>> we manage to get a successful build and install.
>>>>
>>>> As well as being a poor default due to the very high likelyhood of build
>>>> failures this also has the undesirable effect of causing a build failure
>>>> in one selftest to cause the whole install target to fail, meaning that
>>>> the build failure is escallated to a complete lost of coverge for all
>>>> selftests in common CI usage.
>>>>
>>>> This wasn't showing up in my -next build tests since I set FORCE_TARGETS
>>>> and explicitly choose a restricted set of kselftests which actually
>>>> build with my system and configuration.  It was less obvious than it
>>>> should have been with the other systems since they did not expect there
>>>> to be a complete failure to generate a kselftest tarball and variously
>>>> masked the error or reported it in a manner that looked like an
>>>> infrastructure issue.
>>>
>>> I didn't see it when I did test on linux-next and my repo. I did install
>>> to catch problems.
>>>
>>> Sorry for not catching this. We can drop this patch.
>>>
>>>>
>>>> It would be really nice to get to the point where we can reasonably do
>>>> this but we're simply not there at the current time.  At the moment if
>>>> people want to see build failures reported at the top level that really
>>>> needs to be opt in, we have FORCE_TARGETS for that.
>>>
>>> Good point - I will go look and see if we document this in kselftest doc
>>> and add it.
>> 
>> It's not documented. It would have solved my issue, sorry for
>> overlooking this!
>
> Ricardo, Would you like to send me doc patch for this?

Sure, thanks!

>
> thanks,
> -- Shuah


^ permalink raw reply

* Re: [PATCH 5/6] selftests: Preserve subtarget failures in all/install
From: Shuah Khan @ 2026-04-15 15:52 UTC (permalink / raw)
  To: Ricardo B. Marlière, Mark Brown, torvalds, Shuah Khan
  Cc: Nathan Chancellor, Nicolas Schier, linux-kselftest, linux-kernel,
	linux-kbuild, Aishwarya.TCV, ben.copeland, kernelci, Shuah Khan
In-Reply-To: <DHTUDCIYT34R.3VKGNDGUUKS84@suse.com>

On 4/15/26 09:42, Ricardo B. Marlière wrote:
> On Wed Apr 15, 2026 at 12:40 PM -03, Shuah Khan wrote:
>> On 4/15/26 07:58, Mark Brown wrote:
>>> On Fri, Mar 20, 2026 at 03:29:20PM -0300, Ricardo B. Marlière wrote:
>>>> Track failures explicitly in the top-level selftests all/install loops.
>>>>
>>>> The current code multiplies `ret` by each sub-make exit status. For
>>>> example, with `TARGETS=net`, the implicit `net/lib` dependency runs after
>>>> `net`, so a failed `net` build can be followed by a successful `net/lib`
>>>> build and reset the final result to success.
>>>>
>>>> Set `ret` to 1 on any non-zero sub-make exit code and keep it sticky, so
>>>> the top-level make returns failure when any selected selftest target
>>>> fails.
>>>
>>> This patch, which is now in mainline as 7e47389142b8, is breaking a
>>> bunch of CI systems - at least KernelCI, our Arm internal CI and my
>>> personal stuff.  It causes the equivalent of FORCE_TARGETS behaviour in
>>> the top level Makefile, the prior behaviour where the exit status of the
>>> top level Makefile ignores failures from individual directories is
>>> desirable since by default we try to build almost all the selftests but
>>> between quality issues and build time dependencies it's very common for
>>> at least one of them to fail.  With this commit unless the user has
>>> configured a more restricted set of selftests it would be surprising if
>>> we manage to get a successful build and install.
>>>
>>> As well as being a poor default due to the very high likelyhood of build
>>> failures this also has the undesirable effect of causing a build failure
>>> in one selftest to cause the whole install target to fail, meaning that
>>> the build failure is escallated to a complete lost of coverge for all
>>> selftests in common CI usage.
>>>
>>> This wasn't showing up in my -next build tests since I set FORCE_TARGETS
>>> and explicitly choose a restricted set of kselftests which actually
>>> build with my system and configuration.  It was less obvious than it
>>> should have been with the other systems since they did not expect there
>>> to be a complete failure to generate a kselftest tarball and variously
>>> masked the error or reported it in a manner that looked like an
>>> infrastructure issue.
>>
>> I didn't see it when I did test on linux-next and my repo. I did install
>> to catch problems.
>>
>> Sorry for not catching this. We can drop this patch.
>>
>>>
>>> It would be really nice to get to the point where we can reasonably do
>>> this but we're simply not there at the current time.  At the moment if
>>> people want to see build failures reported at the top level that really
>>> needs to be opt in, we have FORCE_TARGETS for that.
>>
>> Good point - I will go look and see if we document this in kselftest doc
>> and add it.
> 
> It's not documented. It would have solved my issue, sorry for
> overlooking this!

Ricardo, Would you like to send me doc patch for this?

thanks,
-- Shuah

^ permalink raw reply

* Re: [PATCH] kbuild/btf: Remove broken module relinking exclusion
From: Ihor Solodrai @ 2026-04-15 15:47 UTC (permalink / raw)
  To: Petr Pavlu, Nathan Chancellor, Nicolas Schier, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko
  Cc: Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
	John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
	Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
	Masahiro Yamada, Sasha Levin, linux-kbuild, bpf, linux-modules,
	linux-kernel
In-Reply-To: <20260410131343.2519532-1-petr.pavlu@suse.com>

On 4/10/26 6:13 AM, Petr Pavlu wrote:
> Commit 5f9ae91f7c0d ("kbuild: Build kernel module BTFs if BTF is enabled
> and pahole supports it") in 2020 introduced CONFIG_DEBUG_INFO_BTF_MODULES
> to enable generation of split BTF for kernel modules. This change required
> the %.ko Makefile rule to additionally depend on vmlinux, which is used as
> a base for deduplication. The regular ld_ko_o command executed by the rule
> was then modified to be skipped if only vmlinux changes. This was done by
> introducing a new if_changed_except command and updating the original call
> to '+$(call if_changed_except,ld_ko_o,vmlinux)'.
> 
> Later, commit 214c0eea43b2 ("kbuild: add $(objtree)/ prefix to some
> in-kernel build artifacts") in 2024 updated the rule's reference to vmlinux
> from 'vmlinux' to '$(objtree)/vmlinux'. This accidentally broke the
> previous logic to skip relinking modules if only vmlinux changes. The issue
> is that '$(objtree)' is typically '.' and GNU Make normalizes the resulting
> prerequisite './vmlinux' to just 'vmlinux', while the exclusion logic
> retains the raw './vmlinux'. As a result, if_changed_except doesn't
> correctly filter out vmlinux. Consequently, with
> CONFIG_DEBUG_INFO_BTF_MODULES=y, modules are relinked even if only vmlinux
> changes.
> 
> It is possible to fix this Makefile issue. However, having the %.ko rule
> update the resulting file in place without starting from the original
> inputs is rather fragile. The logic is harder to debug if something breaks
> during a subsequent .ko update because the old input is lost due to the
> overwrite. Additionally, it requires that the BTF processing is idempotent.
> For example, sorting id+flags BTF_SET8 pairs in .BTF_ids by resolve_btfids
> currently doesn't have this property.
> 
> One option is to split the %.ko target into two rules: the first for
> partial linking and the second one for generating the BTF data. However,
> this approach runs into an issue with requiring additional intermediate
> files, which increases the size of the build directory. On my system, when
> using a large distribution config with ~5500 modules, the size of the build
> directory with debuginfo enabled is already ~25 GB, with .ko files
> occupying ~8 GB. Duplicating these .ko files doesn't seem practical.
> 
> Measuring the speed of the %.ko processing shows that the link step is
> actually relatively fast. It takes about 20% of the overall rule time,
> while the BTF processing accounts for 80%. Moreover, skipping the link part
> becomes relevant only during local development. In such cases, developers
> typically use configs that enable a limited number of modules, so having
> the %.ko rule slightly slower doesn't significantly impact the total
> rebuild time. This is supported by the fact that no one has complained
> about this optimization being broken for the past two years.
> 
> Therefore, remove the logic that prevents module relinking when only
> vmlinux changes and simplify Makefile.modfinal.

The change makes sense to me.

Acked-by: Ihor Solodrai <ihor.solodrai@linux.dev>

Thank you!

> 
> Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
> ---
> My previous attempt to fix this logic can be found at
> https://lore.kernel.org/linux-modules/20260402141911.1577711-1-petr.pavlu@suse.com/
> ---
>  scripts/Makefile.modfinal | 10 +---------
>  1 file changed, 1 insertion(+), 9 deletions(-)
> 
> diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> index adcbcde16a07..01a37ec872b9 100644
> --- a/scripts/Makefile.modfinal
> +++ b/scripts/Makefile.modfinal
> @@ -46,17 +46,9 @@ quiet_cmd_btf_ko = BTF [M] $@
>  		$(CONFIG_SHELL) $(srctree)/scripts/gen-btf.sh --btf_base $(objtree)/vmlinux $@; \
>  	fi;
>  
> -# Same as newer-prereqs, but allows to exclude specified extra dependencies
> -newer_prereqs_except = $(filter-out $(PHONY) $(1),$?)
> -
> -# Same as if_changed, but allows to exclude specified extra dependencies
> -if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check),      \
> -	$(cmd);                                                              \
> -	printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
> -
>  # Re-generate module BTFs if either module's .ko or vmlinux changed
>  %.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
> -	+$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
> +	+$(call if_changed,ld_ko_o)
>  ifdef CONFIG_DEBUG_INFO_BTF_MODULES
>  	+$(if $(newer-prereqs),$(call cmd,btf_ko))
>  endif
> 
> base-commit: 591cd656a1bf5ea94a222af5ef2ee76df029c1d2


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox