kbuild: add generic support for built-in boot DTBs
authorMasahiro Yamada <masahiroy@kernel.org>
Mon, 23 Sep 2024 07:56:03 +0000 (16:56 +0900)
committerMasahiro Yamada <masahiroy@kernel.org>
Mon, 4 Nov 2024 08:53:09 +0000 (17:53 +0900)
Some architectures embed boot DTBs in vmlinux. A potential issue for
these architectures is a race condition during parallel builds because
Kbuild descends into arch/*/boot/dts/ twice.

One build thread is initiated by the 'dtbs' target, which is a
prerequisite of the 'all' target in the top-level Makefile:

  ifdef CONFIG_OF_EARLY_FLATTREE
  all: dtbs
  endif

For architectures that support the built-in boot dtb, arch/*/boot/dts/
is visited also during the ordinary directory traversal in order to
build obj-y objects that wrap DTBs.

Since these build threads are unaware of each other, they can run
simultaneously during parallel builds.

This commit introduces a generic build rule to scripts/Makefile.vmlinux
to support embedded boot DTBs in a race-free way. Architectures that
want to use this rule need to select CONFIG_GENERIC_BUILTIN_DTB.

After the migration, Makefiles under arch/*/boot/dts/ will be visited
only once to build only *.dtb files.

This change also aims to unify the CONFIG options used for built-in DTBs
support. Currently, different architectures use different CONFIG options
for the same purposes.

With this commit, the CONFIG options will be unified as follows:

 - CONFIG_GENERIC_BUILTIN_DTB

   This enables the generic rule for built-in boot DTBs. This will be
   renamed to CONFIG_BUILTIN_DTB after all architectures migrate to the
   generic rule.

 - CONFIG_BUILTIN_DTB_NAME

   This specifies the path to the embedded DTB.
   (relative to arch/*/boot/dts/)

 - CONFIG_BUILTIN_DTB_ALL

   If this is enabled, all DTB files compiled under arch/*/boot/dts/ are
   embedded into vmlinux. Only used by MIPS.

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Makefile
drivers/of/Kconfig
scripts/Makefile.vmlinux
scripts/link-vmlinux.sh

index 9b30c42..855913b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1433,6 +1433,10 @@ ifdef CONFIG_OF_EARLY_FLATTREE
 all: dtbs
 endif
 
+ifdef CONFIG_GENERIC_BUILTIN_DTB
+vmlinux: dtbs
+endif
+
 endif
 
 PHONY += scripts_dtc
@@ -1500,7 +1504,8 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
               modules.builtin modules.builtin.modinfo modules.nsdeps \
               modules.builtin.ranges vmlinux.o.map \
               compile_commands.json rust/test \
-              rust-project.json .vmlinux.objs .vmlinux.export.c
+              rust-project.json .vmlinux.objs .vmlinux.export.c \
+               .builtin-dtbs-list .builtin-dtb.S
 
 # Directories & files removed with 'make mrproper'
 MRPROPER_FILES += include/config include/generated          \
index 0e2d608..6a53cba 100644 (file)
@@ -2,6 +2,12 @@
 config DTC
        bool
 
+config GENERIC_BUILTIN_DTB
+       bool
+
+config BUILTIN_DTB_ALL
+       bool
+
 menuconfig OF
        bool "Device Tree and Open Firmware support"
        help
index 1284f05..9ef0480 100644 (file)
@@ -17,6 +17,50 @@ quiet_cmd_cc_o_c = CC      $@
 %.o: %.c FORCE
        $(call if_changed_dep,cc_o_c)
 
+quiet_cmd_as_o_S = AS      $@
+      cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
+
+%.o: %.S FORCE
+       $(call if_changed_dep,as_o_S)
+
+# Built-in dtb
+# ---------------------------------------------------------------------------
+
+quiet_cmd_wrap_dtbs = WRAP    $@
+      cmd_wrap_dtbs = {                                                        \
+       echo '\#include <asm-generic/vmlinux.lds.h>';                   \
+       echo '.section .dtb.init.rodata,"a"';                           \
+       while read dtb; do                                              \
+               symbase=__dtb_$$(basename -s .dtb "$${dtb}" | tr - _);  \
+               echo '.balign STRUCT_ALIGNMENT';                        \
+               echo ".global $${symbase}_begin";                       \
+               echo "$${symbase}_begin:";                              \
+               echo '.incbin "'$$dtb'" ';                              \
+               echo ".global $${symbase}_end";                         \
+               echo "$${symbase}_end:";                                \
+       done < $<;                                                      \
+       } > $@
+
+.builtin-dtbs.S: .builtin-dtbs-list FORCE
+       $(call if_changed,wrap_dtbs)
+
+quiet_cmd_gen_dtbs_list = GEN     $@
+      cmd_gen_dtbs_list = \
+       $(if $(CONFIG_BUILTIN_DTB_NAME), echo "arch/$(SRCARCH)/boot/dts/$(CONFIG_BUILTIN_DTB_NAME).dtb",:) > $@
+
+.builtin-dtbs-list: arch/$(SRCARCH)/boot/dts/dtbs-list FORCE
+       $(call if_changed,$(if $(CONFIG_BUILTIN_DTB_ALL),copy,gen_dtbs_list))
+
+targets += .builtin-dtbs-list
+
+ifdef CONFIG_GENERIC_BUILTIN_DTB
+targets += .builtin-dtbs.S .builtin-dtbs.o
+vmlinux: .builtin-dtbs.o
+endif
+
+# vmlinux
+# ---------------------------------------------------------------------------
+
 ifdef CONFIG_MODULES
 targets += .vmlinux.export.o
 vmlinux: .vmlinux.export.o
index a9b3f34..53bd4b7 100755 (executable)
@@ -68,6 +68,10 @@ vmlinux_link()
                libs="${KBUILD_VMLINUX_LIBS}"
        fi
 
+       if is_enabled CONFIG_GENERIC_BUILTIN_DTB; then
+               objs="${objs} .builtin-dtbs.o"
+       fi
+
        if is_enabled CONFIG_MODULES; then
                objs="${objs} .vmlinux.export.o"
        fi