summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO50
-rw-r--r--0001-bitfield.h-don-t-compile-time-validate-_val-in-FIELD.patch53
-rw-r--r--0002-objtool-use-sh_info-to-find-the-base-for-.rela-secti.patch37
-rw-r--r--0003-objtool-don-t-autodetect-vmlinux.o.patch56
-rw-r--r--0004-kbuild-add-support-for-Clang-LTO.patch361
-rw-r--r--0005-kbuild-lto-fix-module-versioning.patch219
-rw-r--r--0006-kbuild-lto-fix-recordmcount.patch238
-rw-r--r--0007-kbuild-lto-postpone-objtool.patch87
-rw-r--r--0008-kbuild-lto-limit-inlining.patch38
-rw-r--r--0009-kbuild-lto-merge-module-sections.patch65
-rw-r--r--0010-kbuild-lto-remove-duplicate-dependencies-from-.mod-f.patch38
-rw-r--r--0011-init-lto-ensure-initcall-ordering.patch442
-rw-r--r--0012-init-lto-fix-PREL32-relocations.patch77
-rw-r--r--0013-PCI-Fix-PREL32-relocations-for-LTO.patch59
-rw-r--r--0014-modpost-lto-strip-.lto-from-module-names.patch116
-rw-r--r--0015-scripts-mod-disable-LTO-for-empty.c.patch28
-rw-r--r--0016-efi-libstub-disable-LTO.patch30
-rw-r--r--0017-drivers-misc-lkdtm-disable-LTO-for-rodata.o.patch29
-rw-r--r--0018-arm64-export-CC_USING_PATCHABLE_FUNCTION_ENTRY.patch29
-rw-r--r--0019-arm64-vdso-disable-LTO.patch31
-rw-r--r--0020-arm64-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch28
-rw-r--r--0021-g86-vdso-disable-LTO-only-for-vDSO.patch48
-rw-r--r--0022-x86-ftrace-disable-recordmcount-for-ftrace_make_nop.patch27
-rw-r--r--0023-x86-relocs-Ignore-L4_PAGE_OFFSET-relocations.patch28
-rw-r--r--0024-x86-build-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch45
-rw-r--r--PKGBUILD53
-rw-r--r--config3
27 files changed, 2313 insertions, 2 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 37d043cb7e69..6a33111cab94 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -29,9 +29,33 @@ pkgbase = linux-llvm
source = 0005-x86-bump-ZO_z_extra_bytes-margin-for-zstd.patch
source = 0006-x86-Add-support-for-ZSTD-compressed-kernel.patch
source = 0007-.gitignore-add-ZSTD-compressed-files.patch
+ source = 0001-bitfield.h-don-t-compile-time-validate-_val-in-FIELD.patch
+ source = 0002-objtool-use-sh_info-to-find-the-base-for-.rela-secti.patch
+ source = 0003-objtool-don-t-autodetect-vmlinux.o.patch
+ source = 0004-kbuild-add-support-for-Clang-LTO.patch
+ source = 0005-kbuild-lto-fix-module-versioning.patch
+ source = 0006-kbuild-lto-fix-recordmcount.patch
+ source = 0007-kbuild-lto-postpone-objtool.patch
+ source = 0008-kbuild-lto-limit-inlining.patch
+ source = 0009-kbuild-lto-merge-module-sections.patch
+ source = 0010-kbuild-lto-remove-duplicate-dependencies-from-.mod-f.patch
+ source = 0011-init-lto-ensure-initcall-ordering.patch
+ source = 0012-init-lto-fix-PREL32-relocations.patch
+ source = 0013-PCI-Fix-PREL32-relocations-for-LTO.patch
+ source = 0014-modpost-lto-strip-.lto-from-module-names.patch
+ source = 0015-scripts-mod-disable-LTO-for-empty.c.patch
+ source = 0016-efi-libstub-disable-LTO.patch
+ source = 0017-drivers-misc-lkdtm-disable-LTO-for-rodata.o.patch
+ source = 0018-arm64-export-CC_USING_PATCHABLE_FUNCTION_ENTRY.patch
+ source = 0019-arm64-vdso-disable-LTO.patch
+ source = 0020-arm64-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
+ source = 0021-g86-vdso-disable-LTO-only-for-vDSO.patch
+ source = 0022-x86-ftrace-disable-recordmcount-for-ftrace_make_nop.patch
+ source = 0023-x86-relocs-Ignore-L4_PAGE_OFFSET-relocations.patch
+ source = 0024-x86-build-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
source = enable_additional_cpu_optimizations_for_gcc_v10.1+_kernel_v5.8+.patch
sha256sums = SKIP
- sha256sums = 7748dbdc1d0ff9efa8358268e82b21b338acfb7ebbd2876753bf23c4e71da44c
+ sha256sums = 639e5ac559832b05d1b3be611faedab33aa65059eb8cd76879d2b92ecd17d7fa
sha256sums = 8cb21e0b3411327b627a9dd15b8eb773295a0d2782b1a41b2a8839d1b2f5778c
sha256sums = 2f0090ec0c9a72e6241bbea05faaef979405119ce8ef669d84dead36c8e2246e
sha256sums = 5f21c12f002e71ec5b5db96832b415ce291a7e230fa07b328c21760274e72e9d
@@ -40,6 +64,30 @@ pkgbase = linux-llvm
sha256sums = 2b558cc58e95343bb2e3cfd96c668b671251c543124176b8687baf12cdf999d5
sha256sums = 84c275eb98fb908b742ffe51faa7feb0312550712b0cd729bf72941a2f633a65
sha256sums = f88df9ee297e229792e516ac9fb6f35ddc1aa13c3fdeb9ba15fb4de8b1dcd7c7
+ sha256sums = 524b329a965f1b983fd4b78e1827854727d4ebb9c21cc9f245bf2ce91c2bed1d
+ sha256sums = 053582c4fa855a9219f45f864d7a03b3a28cfd04ec798b0cc47080c836669184
+ sha256sums = 7e155527495f8a009efc6edc43d44c1775de64c750c9c112f6964d599eada3ef
+ sha256sums = 2ef22d6b576ebf452238ae48658515d5d484b3ab7448b9d62fc1295570bb8f14
+ sha256sums = 9bbda700ef98d75ce24c43f5bf191f77f51d5587ea06ad5c763d9ac10d39c96e
+ sha256sums = 5684845b4c0a516fc907a1f24d420760f2cd2a53ab977fb409a6378f9b1f473e
+ sha256sums = 438c34b332cb3d67e31856f11ed71052974a869f8fd71da637343da7de0c1bf2
+ sha256sums = efaa62f8d18463141958fdeb495b58c03e49f62ef7bca30e5cd261821bff4ca6
+ sha256sums = c44e6e4de658ba682cba3b24f766af5bb70572869c8419c0091767726439bfa1
+ sha256sums = 75939f2da39a5644e407aaee060ea00fa6b8e06bf5cc361af793affe5a660243
+ sha256sums = 407e9262ed5cf234172f3048ae79513030589022acba42039ad709f490c6d139
+ sha256sums = e89ceb6f4cda3fa9ae59c3482b27118df18c98d0a74665d0fe07f05017c1144e
+ sha256sums = eacb3b5cd7380a48ae50f38c57153a3f90a6dd890b573bf172c0d0585e4f1ab9
+ sha256sums = 7854b55ff44f5ec0a94d295075679aaaf1ff3baf9039bd8a7ea73e4e9ae4f8dd
+ sha256sums = 4668748669f31e3535e02c11f2f4554412d5bd29279ebdbe241f515d7f34aafc
+ sha256sums = 729f41453d3607c6c055ae1f52e476d09a4b49169897fe136ad37a451c7872bb
+ sha256sums = e3d865689bc4c3ab52b9d0a897278bde415a7cd4892c0e7006ce7998c6e97fe7
+ sha256sums = 4c2bc4f796ef21d1f5cbc7e4a7600a250c66de329819795f77cad3e52106b2fe
+ sha256sums = 85bf687909b628e36ea8a2c973cdd3ef2819f57422d5405cf338abce9037ef9a
+ sha256sums = 0c269cb936eec02fc767f1d4f2ca4436582f5c4f046a3b4c53608d4232a09809
+ sha256sums = 0feb6c229e75c5a4ed532840bbe3ab1426ae255c0897f7852a93537e7661b461
+ sha256sums = bd3f17cbb1da5293bb54a5bdeaa613098d41fe676ee327ba35867c18732ee80c
+ sha256sums = 539794c1dc9b8e35a73e2e165040f363d0c7f32bc5da415ae6b27a9ffe57dde2
+ sha256sums = 3b956c3768e59f2d5fb0546a855138319eff60e077822667befed734c7ac84af
sha256sums = 5ab29eb64e57df83b395a29a6a4f89030d142feffbfbf73b3afc6d97a2a7fd12
pkgname = linux-llvm
diff --git a/0001-bitfield.h-don-t-compile-time-validate-_val-in-FIELD.patch b/0001-bitfield.h-don-t-compile-time-validate-_val-in-FIELD.patch
new file mode 100644
index 000000000000..2c24d961384b
--- /dev/null
+++ b/0001-bitfield.h-don-t-compile-time-validate-_val-in-FIELD.patch
@@ -0,0 +1,53 @@
+From 28fca8bb1d95ebb3c3a7367ee60b0f1ef6d83475 Mon Sep 17 00:00:00 2001
+From: Jakub Kicinski <kuba@kernel.org>
+Date: Tue, 7 Jul 2020 14:16:41 -0700
+Subject: [PATCH 01/24] bitfield.h: don't compile-time validate _val in
+ FIELD_FIT
+
+When ur_load_imm_any() is inlined into jeq_imm(), it's possible for the
+compiler to deduce a case where _val can only have the value of -1 at
+compile time. Specifically,
+
+/* struct bpf_insn: _s32 imm */
+u64 imm = insn->imm; /* sign extend */
+if (imm >> 32) { /* non-zero only if insn->imm is negative */
+ /* inlined from ur_load_imm_any */
+ u32 __imm = imm >> 32; /* therefore, always 0xffffffff */
+ if (__builtin_constant_p(__imm) && __imm > 255)
+ compiletime_assert_XXX()
+
+This can result in tripping a BUILD_BUG_ON() in __BF_FIELD_CHECK() that
+checks that a given value is representable in one byte (interpreted as
+unsigned).
+
+FIELD_FIT() should return true or false at runtime for whether a value
+can fit for not. Don't break the build over a value that's too large for
+the mask. We'd prefer to keep the inlining and compiler optimizations
+though we know this case will always return false.
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/kernel-hardening/CAK7LNASvb0UDJ0U5wkYYRzTAdnEs64HjXpEUL7d=V0CXiAXcNw@mail.gmail.com/
+Reported-by: Masahiro Yamada <masahiroy@kernel.org>
+Debugged-by: Sami Tolvanen <samitolvanen@google.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
+---
+ include/linux/bitfield.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h
+index 48ea093ff04c..4e035aca6f7e 100644
+--- a/include/linux/bitfield.h
++++ b/include/linux/bitfield.h
+@@ -77,7 +77,7 @@
+ */
+ #define FIELD_FIT(_mask, _val) \
+ ({ \
+- __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: "); \
++ __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_FIT: "); \
+ !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \
+ })
+
+--
+2.28.0
+
diff --git a/0002-objtool-use-sh_info-to-find-the-base-for-.rela-secti.patch b/0002-objtool-use-sh_info-to-find-the-base-for-.rela-secti.patch
new file mode 100644
index 000000000000..0d42e403b30b
--- /dev/null
+++ b/0002-objtool-use-sh_info-to-find-the-base-for-.rela-secti.patch
@@ -0,0 +1,37 @@
+From 32e8f91f5bb6bc82e198233a85ef7c2ae68742c9 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Mon, 13 Apr 2020 13:40:11 -0700
+Subject: [PATCH 02/24] objtool: use sh_info to find the base for .rela
+ sections
+
+ELF doesn't require .rela section names to match the base section. Use
+the section index in sh_info to find the section instead of looking it
+up by name.
+
+LLD, for example, generates a .rela section that doesn't match the base
+section name when we merge sections in a linker script for a binary
+compiled with -ffunction-sections.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+---
+ tools/objtool/elf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
+index 26d11d821941..72bfde4bc5de 100644
+--- a/tools/objtool/elf.c
++++ b/tools/objtool/elf.c
+@@ -502,7 +502,7 @@ static int read_relas(struct elf *elf)
+ if (sec->sh.sh_type != SHT_RELA)
+ continue;
+
+- sec->base = find_section_by_name(elf, sec->name + 5);
++ sec->base = find_section_by_index(elf, sec->sh.sh_info);
+ if (!sec->base) {
+ WARN("can't find base section for rela section %s",
+ sec->name);
+--
+2.28.0
+
diff --git a/0003-objtool-don-t-autodetect-vmlinux.o.patch b/0003-objtool-don-t-autodetect-vmlinux.o.patch
new file mode 100644
index 000000000000..8841edc6aec3
--- /dev/null
+++ b/0003-objtool-don-t-autodetect-vmlinux.o.patch
@@ -0,0 +1,56 @@
+From 8f1687630f5771b2257fa5ca0a233634065703f0 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Fri, 17 Jul 2020 12:04:27 -0700
+Subject: [PATCH 03/24] objtool: don't autodetect vmlinux.o
+
+With LTO, we run objtool on vmlinux.o, but don't want noinstr
+validation. This change requires --vmlinux to be passed to objtool
+explicitly.
+
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ scripts/link-vmlinux.sh | 2 +-
+ tools/objtool/builtin-check.c | 10 +---------
+ 2 files changed, 2 insertions(+), 10 deletions(-)
+
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index 92dd745906f4..00c6e4f28a1a 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -60,7 +60,7 @@ objtool_link()
+ local objtoolopt;
+
+ if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then
+- objtoolopt="check"
++ objtoolopt="check --vmlinux"
+ if [ -z "${CONFIG_FRAME_POINTER}" ]; then
+ objtoolopt="${objtoolopt} --no-fp"
+ fi
+diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
+index 7a44174967b5..1109dd69f953 100644
+--- a/tools/objtool/builtin-check.c
++++ b/tools/objtool/builtin-check.c
+@@ -40,18 +40,10 @@ const struct option check_options[] = {
+
+ int cmd_check(int argc, const char **argv)
+ {
+- const char *objname, *s;
+-
+ argc = parse_options(argc, argv, check_options, check_usage, 0);
+
+ if (argc != 1)
+ usage_with_options(check_usage, check_options);
+
+- objname = argv[0];
+-
+- s = strstr(objname, "vmlinux.o");
+- if (s && !s[9])
+- vmlinux = true;
+-
+- return check(objname, false);
++ return check(argv[0], false);
+ }
+--
+2.28.0
+
diff --git a/0004-kbuild-add-support-for-Clang-LTO.patch b/0004-kbuild-add-support-for-Clang-LTO.patch
new file mode 100644
index 000000000000..789b6e88a689
--- /dev/null
+++ b/0004-kbuild-add-support-for-Clang-LTO.patch
@@ -0,0 +1,361 @@
+From e8a6f455578b17e04ad08f15b76486e06f812400 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Fri, 6 Mar 2020 14:14:03 -0800
+Subject: [PATCH 04/24] kbuild: add support for Clang LTO
+
+This change adds build system support for Clang's Link Time
+Optimization (LTO). With -flto, instead of ELF object files, Clang
+produces LLVM bitcode, which is compiled into native code at link
+time, allowing the final binary to be optimized globally. For more
+details, see:
+
+ https://llvm.org/docs/LinkTimeOptimization.html
+
+The Kconfig option CONFIG_LTO_CLANG is implemented as a choice,
+which defaults to LTO being disabled. To use LTO, the architecture
+must select ARCH_SUPPORTS_LTO_CLANG and support:
+
+ - compiling with Clang,
+ - compiling inline assembly with Clang's integrated assembler,
+ - and linking with LLD.
+
+While using full LTO results in the best runtime performance, the
+compilation is not scalable in time or memory. CONFIG_THINLTO
+enables ThinLTO, which allows parallel optimization and faster
+incremental builds. ThinLTO is used by default if the architecture
+also selects ARCH_SUPPORTS_THINLTO:
+
+ https://clang.llvm.org/docs/ThinLTO.html
+
+To enable LTO, LLVM tools must be used to handle bitcode files. The
+easiest way is to pass the LLVM=1 option to make:
+
+ $ make LLVM=1 defconfig
+ $ scripts/config -e LTO_CLANG
+ $ make LLVM=1
+
+Alternatively, at least the following LLVM tools must be used:
+
+ CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm
+
+To prepare for LTO support with other compilers, common parts are
+gated behind the CONFIG_LTO option, and LTO can be disabled for
+specific files by filtering out CC_FLAGS_LTO.
+
+Note that support for DYNAMIC_FTRACE and MODVERSIONS are added in
+follow-up patches.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ Makefile | 18 ++++++++-
+ arch/Kconfig | 67 +++++++++++++++++++++++++++++++
+ include/asm-generic/vmlinux.lds.h | 11 +++--
+ scripts/Makefile.build | 9 ++++-
+ scripts/Makefile.modfinal | 9 ++++-
+ scripts/Makefile.modpost | 24 ++++++++++-
+ scripts/link-vmlinux.sh | 32 +++++++++++----
+ 7 files changed, 153 insertions(+), 17 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 38acd65aa651..44615ea079e5 100644
+--- a/Makefile
++++ b/Makefile
+@@ -887,6 +887,22 @@ KBUILD_CFLAGS += $(CC_FLAGS_SCS)
+ export CC_FLAGS_SCS
+ endif
+
++ifdef CONFIG_LTO_CLANG
++ifdef CONFIG_THINLTO
++CC_FLAGS_LTO_CLANG := -flto=thin -fsplit-lto-unit
++KBUILD_LDFLAGS += --thinlto-cache-dir=.thinlto-cache
++else
++CC_FLAGS_LTO_CLANG := -flto
++endif
++CC_FLAGS_LTO_CLANG += -fvisibility=default
++endif
++
++ifdef CONFIG_LTO
++CC_FLAGS_LTO := $(CC_FLAGS_LTO_CLANG)
++KBUILD_CFLAGS += $(CC_FLAGS_LTO)
++export CC_FLAGS_LTO
++endif
++
+ # arch Makefile may override CC so keep this after arch Makefile is included
+ NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+
+@@ -1446,7 +1462,7 @@ MRPROPER_FILES += include/config include/generated \
+ *.spec
+
+ # Directories & files removed with 'make distclean'
+-DISTCLEAN_FILES += tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
++DISTCLEAN_FILES += tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS .thinlto-cache
+
+ # clean - Delete most, but leave enough to build external modules
+ #
+diff --git a/arch/Kconfig b/arch/Kconfig
+index 8cc35dc556c7..df5a42854a51 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -552,6 +552,73 @@ config SHADOW_CALL_STACK
+ reading and writing arbitrary memory may be able to locate them
+ and hijack control flow by modifying the stacks.
+
++config LTO
++ bool
++
++config ARCH_SUPPORTS_LTO_CLANG
++ bool
++ help
++ An architecture should select this option if it supports:
++ - compiling with Clang,
++ - compiling inline assembly with Clang's integrated assembler,
++ - and linking with LLD.
++
++config ARCH_SUPPORTS_THINLTO
++ bool
++ help
++ An architecture should select this option if it supports Clang's
++ ThinLTO.
++
++config THINLTO
++ bool "Clang ThinLTO"
++ depends on LTO_CLANG && ARCH_SUPPORTS_THINLTO
++ default y
++ help
++ This option enables Clang's ThinLTO, which allows for parallel
++ optimization and faster incremental compiles. More information
++ can be found from Clang's documentation:
++
++ https://clang.llvm.org/docs/ThinLTO.html
++
++choice
++ prompt "Link Time Optimization (LTO)"
++ default LTO_NONE
++ help
++ This option enables Link Time Optimization (LTO), which allows the
++ compiler to optimize binaries globally.
++
++ If unsure, select LTO_NONE.
++
++config LTO_NONE
++ bool "None"
++
++config LTO_CLANG
++ bool "Clang's Link Time Optimization (EXPERIMENTAL)"
++ # https://github.com/ClangBuiltLinux/linux/issues/510
++ depends on CC_IS_CLANG && CLANG_VERSION >= 110000 && LD_IS_LLD
++ depends on $(success,$(NM) --help | head -n 1 | grep -qi llvm)
++ depends on $(success,$(AR) --help | head -n 1 | grep -qi llvm)
++ depends on ARCH_SUPPORTS_LTO_CLANG
++ depends on !FTRACE_MCOUNT_RECORD
++ depends on !KASAN
++ depends on !MODVERSIONS
++ select LTO
++ help
++ This option enables Clang's Link Time Optimization (LTO), which
++ allows the compiler to optimize the kernel globally. If you enable
++ this option, the compiler generates LLVM bitcode instead of ELF
++ object files, and the actual compilation from bitcode happens at
++ the LTO link step, which may take several minutes depending on the
++ kernel configuration. More information can be found from LLVM's
++ documentation:
++
++ https://llvm.org/docs/LinkTimeOptimization.html
++
++ To select this option, you also need to use LLVM tools to handle
++ the bitcode by passing LLVM=1 to make.
++
++endchoice
++
+ config HAVE_ARCH_WITHIN_STACK_FRAMES
+ bool
+ help
+diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+index 052e0f05a984..7f62f7eef94c 100644
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -89,15 +89,18 @@
+ * .data. We don't want to pull in .data..other sections, which Linux
+ * has defined. Same for text and bss.
+ *
++ * With LTO_CLANG, the linker also splits sections by default, so we need
++ * these macros to combine the sections during the final link.
++ *
+ * RODATA_MAIN is not used because existing code already defines .rodata.x
+ * sections to be brought in with rodata.
+ */
+-#ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
++#if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG)
+ #define TEXT_MAIN .text .text.[0-9a-zA-Z_]*
+-#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..LPBX*
++#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..L* .data..compoundliteral*
+ #define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]*
+-#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]*
+-#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]*
++#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]* .rodata..L*
++#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* .bss..compoundliteral*
+ #define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]*
+ #else
+ #define TEXT_MAIN .text
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index 2e8810b7e5ed..f307e708a1b7 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -108,7 +108,7 @@ endif
+ # ---------------------------------------------------------------------------
+
+ quiet_cmd_cc_s_c = CC $(quiet_modtag) $@
+- cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) $(DISABLE_LTO) -fverbose-asm -S -o $@ $<
++ cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS) $(CC_FLAGS_LTO), $(c_flags)) -fverbose-asm -S -o $@ $<
+
+ $(obj)/%.s: $(src)/%.c FORCE
+ $(call if_changed_dep,cc_s_c)
+@@ -424,8 +424,15 @@ $(obj)/lib.a: $(lib-y) FORCE
+ # Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
+ # module is turned into a multi object module, $^ will contain header file
+ # dependencies recorded in the .*.cmd file.
++ifdef CONFIG_LTO_CLANG
++quiet_cmd_link_multi-m = AR [M] $@
++cmd_link_multi-m = \
++ rm -f $@; \
++ $(AR) rcsTP$(KBUILD_ARFLAGS) $@ $(filter %.o,$^)
++else
+ quiet_cmd_link_multi-m = LD [M] $@
+ cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
++endif
+
+ $(multi-used-m): FORCE
+ $(call if_changed,link_multi-m)
+diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
+index 411c1e600e7d..1005b147abd0 100644
+--- a/scripts/Makefile.modfinal
++++ b/scripts/Makefile.modfinal
+@@ -6,6 +6,7 @@
+ PHONY := __modfinal
+ __modfinal:
+
++include $(objtree)/include/config/auto.conf
+ include $(srctree)/scripts/Kbuild.include
+
+ # for c_flags
+@@ -29,6 +30,12 @@ quiet_cmd_cc_o_c = CC [M] $@
+
+ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
+
++ifdef CONFIG_LTO_CLANG
++# With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to
++# avoid a second slow LTO link
++prelink-ext := .lto
++endif
++
+ quiet_cmd_ld_ko_o = LD [M] $@
+ cmd_ld_ko_o = \
+ $(LD) -r $(KBUILD_LDFLAGS) \
+@@ -37,7 +44,7 @@ quiet_cmd_ld_ko_o = LD [M] $@
+ -o $@ $(filter %.o, $^); \
+ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+
+-$(modules): %.ko: %.o %.mod.o $(KBUILD_LDS_MODULE) FORCE
++$(modules): %.ko: %$(prelink-ext).o %.mod.o $(KBUILD_LDS_MODULE) FORCE
+ +$(call if_changed,ld_ko_o)
+
+ targets += $(modules) $(modules:.ko=.mod.o)
+diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
+index f54b6ac37ac2..a70f1f7da6aa 100644
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -102,12 +102,32 @@ $(input-symdump):
+ @echo >&2 'WARNING: Symbol version dump "$@" is missing.'
+ @echo >&2 ' Modules may not have dependencies or modversions.'
+
++ifdef CONFIG_LTO_CLANG
++# With CONFIG_LTO_CLANG, .o files might be LLVM bitcode, so we need to run
++# LTO to compile them into native code before running modpost
++prelink-ext = .lto
++
++quiet_cmd_cc_lto_link_modules = LTO [M] $@
++cmd_cc_lto_link_modules = \
++ $(LD) $(ld_flags) -r -o $@ \
++ --whole-archive $(filter-out FORCE,$^)
++
++%.lto.o: %.o FORCE
++ $(call if_changed,cc_lto_link_modules)
++
++PHONY += FORCE
++FORCE:
++
++endif
++
++modules := $(sort $(shell cat $(MODORDER)))
++
+ # Read out modules.order to pass in modpost.
+ # Otherwise, allmodconfig would fail with "Argument list too long".
+ quiet_cmd_modpost = MODPOST $@
+- cmd_modpost = sed 's/ko$$/o/' $< | $(MODPOST) -T -
++ cmd_modpost = sed 's/\.ko$$/$(prelink-ext)\.o/' $< | $(MODPOST) -T -
+
+-$(output-symdump): $(MODORDER) $(input-symdump) FORCE
++$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(prelink-ext).o) FORCE
+ $(call if_changed,modpost)
+
+ targets += $(output-symdump)
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index 00c6e4f28a1a..4b9ae7751b63 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -52,6 +52,14 @@ modpost_link()
+ ${KBUILD_VMLINUX_LIBS} \
+ --end-group"
+
++ if [ -n "${CONFIG_LTO_CLANG}" ]; then
++ # This might take a while, so indicate that we're doing
++ # an LTO link
++ info LTO ${1}
++ else
++ info LD ${1}
++ fi
++
+ ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
+ }
+
+@@ -99,13 +107,22 @@ vmlinux_link()
+ fi
+
+ if [ "${SRCARCH}" != "um" ]; then
+- objects="--whole-archive \
+- ${KBUILD_VMLINUX_OBJS} \
+- --no-whole-archive \
+- --start-group \
+- ${KBUILD_VMLINUX_LIBS} \
+- --end-group \
+- ${@}"
++ if [ -n "${CONFIG_LTO_CLANG}" ]; then
++ # Use vmlinux.o instead of performing the slow LTO
++ # link again.
++ objects="--whole-archive \
++ vmlinux.o \
++ --no-whole-archive \
++ ${@}"
++ else
++ objects="--whole-archive \
++ ${KBUILD_VMLINUX_OBJS} \
++ --no-whole-archive \
++ --start-group \
++ ${KBUILD_VMLINUX_LIBS} \
++ --end-group \
++ ${@}"
++ fi
+
+ ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} \
+ ${strip_debug#-Wl,} \
+@@ -270,7 +287,6 @@ fi;
+ ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
+
+ #link vmlinux.o
+-info LD vmlinux.o
+ modpost_link vmlinux.o
+ objtool_link vmlinux.o
+
+--
+2.28.0
+
diff --git a/0005-kbuild-lto-fix-module-versioning.patch b/0005-kbuild-lto-fix-module-versioning.patch
new file mode 100644
index 000000000000..1a20ec858c1f
--- /dev/null
+++ b/0005-kbuild-lto-fix-module-versioning.patch
@@ -0,0 +1,219 @@
+From 50f22050930b49f29dfcc607766632c7d8096402 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Fri, 6 Mar 2020 14:19:09 -0800
+Subject: [PATCH 05/24] kbuild: lto: fix module versioning
+
+With CONFIG_MODVERSIONS, version information is linked into each
+compilation unit that exports symbols. With LTO, we cannot use this
+method as all C code is compiled into LLVM bitcode instead. This
+change collects symbol versions into .symversions files and merges
+them in link-vmlinux.sh where they are all linked into vmlinux.o at
+the same time.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ .gitignore | 1 +
+ Makefile | 3 ++-
+ arch/Kconfig | 1 -
+ scripts/Makefile.build | 33 +++++++++++++++++++++++++++++++--
+ scripts/Makefile.modpost | 2 ++
+ scripts/link-vmlinux.sh | 25 ++++++++++++++++++++++++-
+ 6 files changed, 60 insertions(+), 5 deletions(-)
+
+diff --git a/.gitignore b/.gitignore
+index 162bd2b67bdf..06e76dc39ffe 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -41,6 +41,7 @@
+ *.so.dbg
+ *.su
+ *.symtypes
++*.symversions
+ *.tab.[ch]
+ *.tar
+ *.xz
+diff --git a/Makefile b/Makefile
+index 44615ea079e5..b59ce19ef248 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1794,7 +1794,8 @@ clean: $(clean-dirs)
+ -o -name '.tmp_*.o.*' \
+ -o -name '*.c.[012]*.*' \
+ -o -name '*.ll' \
+- -o -name '*.gcno' \) -type f -print | xargs rm -f
++ -o -name '*.gcno' \
++ -o -name '*.*.symversions' \) -type f -print | xargs rm -f
+
+ # Generate tags for editors
+ # ---------------------------------------------------------------------------
+diff --git a/arch/Kconfig b/arch/Kconfig
+index df5a42854a51..d9c74e3b4cf8 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -601,7 +601,6 @@ config LTO_CLANG
+ depends on ARCH_SUPPORTS_LTO_CLANG
+ depends on !FTRACE_MCOUNT_RECORD
+ depends on !KASAN
+- depends on !MODVERSIONS
+ select LTO
+ help
+ This option enables Clang's Link Time Optimization (LTO), which
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index f307e708a1b7..5c0bbb6ddfcf 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -163,6 +163,15 @@ ifdef CONFIG_MODVERSIONS
+ # the actual value of the checksum generated by genksyms
+ # o remove .tmp_<file>.o to <file>.o
+
++ifdef CONFIG_LTO_CLANG
++# Generate .o.symversions files for each .o with exported symbols, and link these
++# to the kernel and/or modules at the end.
++cmd_modversions_c = \
++ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \
++ $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
++ > $@.symversions; \
++ fi;
++else
+ cmd_modversions_c = \
+ if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \
+ $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
+@@ -174,6 +183,7 @@ cmd_modversions_c = \
+ rm -f $(@D)/.tmp_$(@F:.o=.ver); \
+ fi
+ endif
++endif
+
+ ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ ifndef CC_USING_RECORD_MCOUNT
+@@ -389,6 +399,18 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
+ $(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ;
+ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
+
++# combine symversions for later processing
++quiet_cmd_update_lto_symversions = SYMVER $@
++ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y)
++ cmd_update_lto_symversions = \
++ rm -f $@.symversions \
++ $(foreach n, $(filter-out FORCE,$^), \
++ $(if $(wildcard $(n).symversions), \
++ ; cat $(n).symversions >> $@.symversions))
++else
++ cmd_update_lto_symversions = echo >/dev/null
++endif
++
+ #
+ # Rule to compile a set of .o files into one .a file (without symbol table)
+ #
+@@ -396,8 +418,11 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
+ quiet_cmd_ar_builtin = AR $@
+ cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
+
++quiet_cmd_ar_and_symver = AR $@
++ cmd_ar_and_symver = $(cmd_update_lto_symversions); $(cmd_ar_builtin)
++
+ $(obj)/built-in.a: $(real-obj-y) FORCE
+- $(call if_changed,ar_builtin)
++ $(call if_changed,ar_and_symver)
+
+ #
+ # Rule to create modules.order file
+@@ -417,8 +442,11 @@ $(obj)/modules.order: $(obj-m) FORCE
+ #
+ # Rule to compile a set of .o files into one .a file (with symbol table)
+ #
++quiet_cmd_ar_lib = AR $@
++ cmd_ar_lib = $(cmd_update_lto_symversions); $(cmd_ar)
++
+ $(obj)/lib.a: $(lib-y) FORCE
+- $(call if_changed,ar)
++ $(call if_changed,ar_lib)
+
+ # NOTE:
+ # Do not replace $(filter %.o,^) with $(real-prereqs). When a single object
+@@ -427,6 +455,7 @@ $(obj)/lib.a: $(lib-y) FORCE
+ ifdef CONFIG_LTO_CLANG
+ quiet_cmd_link_multi-m = AR [M] $@
+ cmd_link_multi-m = \
++ $(cmd_update_lto_symversions); \
+ rm -f $@; \
+ $(AR) rcsTP$(KBUILD_ARFLAGS) $@ $(filter %.o,$^)
+ else
+diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
+index a70f1f7da6aa..f9718bf4172d 100644
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -110,6 +110,8 @@ prelink-ext = .lto
+ quiet_cmd_cc_lto_link_modules = LTO [M] $@
+ cmd_cc_lto_link_modules = \
+ $(LD) $(ld_flags) -r -o $@ \
++ $(shell [ -s $(@:.lto.o=.o.symversions) ] && \
++ echo -T $(@:.lto.o=.o.symversions)) \
+ --whole-archive $(filter-out FORCE,$^)
+
+ %.lto.o: %.o FORCE
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index 4b9ae7751b63..712769355a5b 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -39,11 +39,28 @@ info()
+ fi
+ }
+
++# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
++# .tmp_symversions.lds
++gen_symversions()
++{
++ info GEN .tmp_symversions.lds
++ rm -f .tmp_symversions.lds
++
++ for a in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
++ for o in $(${AR} t $a 2>/dev/null); do
++ if [ -f ${o}.symversions ]; then
++ cat ${o}.symversions >> .tmp_symversions.lds
++ fi
++ done
++ done
++}
++
+ # Link of vmlinux.o used for section mismatch analysis
+ # ${1} output file
+ modpost_link()
+ {
+ local objects
++ local lds=""
+
+ objects="--whole-archive \
+ ${KBUILD_VMLINUX_OBJS} \
+@@ -53,6 +70,11 @@ modpost_link()
+ --end-group"
+
+ if [ -n "${CONFIG_LTO_CLANG}" ]; then
++ if [ -n "${CONFIG_MODVERSIONS}" ]; then
++ gen_symversions
++ lds="${lds} -T .tmp_symversions.lds"
++ fi
++
+ # This might take a while, so indicate that we're doing
+ # an LTO link
+ info LTO ${1}
+@@ -60,7 +82,7 @@ modpost_link()
+ info LD ${1}
+ fi
+
+- ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
++ ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
+ }
+
+ objtool_link()
+@@ -238,6 +260,7 @@ cleanup()
+ {
+ rm -f .btf.*
+ rm -f .tmp_System.map
++ rm -f .tmp_symversions.lds
+ rm -f .tmp_vmlinux*
+ rm -f System.map
+ rm -f vmlinux
+--
+2.28.0
+
diff --git a/0006-kbuild-lto-fix-recordmcount.patch b/0006-kbuild-lto-fix-recordmcount.patch
new file mode 100644
index 000000000000..1156acd9ad4f
--- /dev/null
+++ b/0006-kbuild-lto-fix-recordmcount.patch
@@ -0,0 +1,238 @@
+From 1bbbfffdb5d0f291c8fc1787a8c9857ecb4b2f93 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Thu, 2 Apr 2020 17:22:36 -0700
+Subject: [PATCH 06/24] kbuild: lto: fix recordmcount
+
+With LTO, LLVM bitcode won't be compiled into native code until
+modpost_link. This change postpones calls to recordmcount until after
+this step.
+
+In order to exclude specific functions from inspection, we add a new
+code section .text..nomcount, which we tell recordmcount to ignore, and
+a __nomcount attribute for moving functions to this section.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ Makefile | 2 +-
+ arch/Kconfig | 2 +-
+ include/asm-generic/vmlinux.lds.h | 1 +
+ include/linux/compiler-clang.h | 4 ++++
+ include/linux/compiler_types.h | 4 ++++
+ kernel/trace/ftrace.c | 1 +
+ scripts/Makefile.build | 9 +++++++++
+ scripts/Makefile.modfinal | 18 ++++++++++++++++--
+ scripts/link-vmlinux.sh | 29 +++++++++++++++++++++++++++++
+ scripts/recordmcount.c | 3 ++-
+ 10 files changed, 68 insertions(+), 5 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index b59ce19ef248..19e2bf26c52c 100644
+--- a/Makefile
++++ b/Makefile
+@@ -862,7 +862,7 @@ KBUILD_AFLAGS += $(CC_FLAGS_USING)
+ ifdef CONFIG_DYNAMIC_FTRACE
+ ifdef CONFIG_HAVE_C_RECORDMCOUNT
+ BUILD_C_RECORDMCOUNT := y
+- export BUILD_C_RECORDMCOUNT
++ export BUILD_C_RECORDMCOUNT RECORDMCOUNT_WARN
+ endif
+ endif
+ endif
+diff --git a/arch/Kconfig b/arch/Kconfig
+index d9c74e3b4cf8..694bfdc2073f 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -599,7 +599,7 @@ config LTO_CLANG
+ depends on $(success,$(NM) --help | head -n 1 | grep -qi llvm)
+ depends on $(success,$(AR) --help | head -n 1 | grep -qi llvm)
+ depends on ARCH_SUPPORTS_LTO_CLANG
+- depends on !FTRACE_MCOUNT_RECORD
++ depends on !FTRACE_MCOUNT_RECORD || HAVE_C_RECORDMCOUNT
+ depends on !KASAN
+ select LTO
+ help
+diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+index 7f62f7eef94c..7c9a686cf633 100644
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -566,6 +566,7 @@
+ *(.text.hot TEXT_MAIN .text.fixup .text.unlikely) \
+ NOINSTR_TEXT \
+ *(.text..refcount) \
++ *(.text..nomcount) \
+ *(.ref.text) \
+ MEM_KEEP(init.text*) \
+ MEM_KEEP(exit.text*) \
+diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
+index 5e55302e3bf6..21423d6f6dc4 100644
+--- a/include/linux/compiler-clang.h
++++ b/include/linux/compiler-clang.h
+@@ -63,3 +63,7 @@
+ #if __has_feature(shadow_call_stack)
+ # define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))
+ #endif
++
++#if defined(CONFIG_LTO_CLANG) && defined(CONFIG_FTRACE_MCOUNT_RECORD)
++#define __nomcount __attribute__((__section__(".text..nomcount")))
++#endif
+diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
+index 01dd58c74d80..23c7cf44aa92 100644
+--- a/include/linux/compiler_types.h
++++ b/include/linux/compiler_types.h
+@@ -231,6 +231,10 @@ struct ftrace_likely_data {
+ # define __noscs
+ #endif
+
++#ifndef __nomcount
++# define __nomcount
++#endif
++
+ #ifndef asm_volatile_goto
+ #define asm_volatile_goto(x...) asm goto(x)
+ #endif
+diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
+index 1903b80db6eb..8e3ddb8123d9 100644
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -6062,6 +6062,7 @@ static int ftrace_cmp_ips(const void *a, const void *b)
+ return 0;
+ }
+
++__nomcount
+ static int ftrace_process_locs(struct module *mod,
+ unsigned long *start,
+ unsigned long *end)
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index 5c0bbb6ddfcf..64e99f4baa5b 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -187,6 +187,9 @@ endif
+
+ ifdef CONFIG_FTRACE_MCOUNT_RECORD
+ ifndef CC_USING_RECORD_MCOUNT
++ifndef CC_USING_PATCHABLE_FUNCTION_ENTRY
++# With LTO, we postpone recordmcount until we compile a native binary
++ifndef CONFIG_LTO_CLANG
+ # compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
+ ifdef BUILD_C_RECORDMCOUNT
+ ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
+@@ -200,6 +203,8 @@ sub_cmd_record_mcount = \
+ if [ $(@) != "scripts/mod/empty.o" ]; then \
+ $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \
+ fi;
++endif # CONFIG_LTO_CLANG
++
+ recordmcount_source := $(srctree)/scripts/recordmcount.c \
+ $(srctree)/scripts/recordmcount.h
+ else
+@@ -209,11 +214,15 @@ sub_cmd_record_mcount = perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+ "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)" \
+ "$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \
+ "$(if $(part-of-module),1,0)" "$(@)";
++
+ recordmcount_source := $(srctree)/scripts/recordmcount.pl
+ endif # BUILD_C_RECORDMCOUNT
++ifndef CONFIG_LTO_CLANG
+ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), \
+ $(sub_cmd_record_mcount))
++endif # CONFIG_LTO_CLANG
+ endif # CC_USING_RECORD_MCOUNT
++endif # CC_USING_PATCHABLE_FUNCTION_ENTRY
+ endif # CONFIG_FTRACE_MCOUNT_RECORD
+
+ ifdef CONFIG_STACK_VALIDATION
+diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
+index 1005b147abd0..d168f0cfe67c 100644
+--- a/scripts/Makefile.modfinal
++++ b/scripts/Makefile.modfinal
+@@ -34,10 +34,24 @@ ifdef CONFIG_LTO_CLANG
+ # With CONFIG_LTO_CLANG, reuse the object file we compiled for modpost to
+ # avoid a second slow LTO link
+ prelink-ext := .lto
+-endif
++
++# ELF processing was skipped earlier because we didn't have native code,
++# so let's now process the prelinked binary before we link the module.
++
++ifdef CONFIG_FTRACE_MCOUNT_RECORD
++ifndef CC_USING_RECORD_MCOUNT
++ifndef CC_USING_PATCHABLE_FUNCTION_ENTRY
++cmd_ld_ko_o += $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) \
++ $(@:.ko=$(prelink-ext).o);
++
++endif # CC_USING_PATCHABLE_FUNCTION_ENTRY
++endif # CC_USING_RECORD_MCOUNT
++endif # CONFIG_FTRACE_MCOUNT_RECORD
++
++endif # CONFIG_LTO_CLANG
+
+ quiet_cmd_ld_ko_o = LD [M] $@
+- cmd_ld_ko_o = \
++ cmd_ld_ko_o += \
+ $(LD) -r $(KBUILD_LDFLAGS) \
+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+ $(addprefix -T , $(KBUILD_LDS_MODULE)) \
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index 712769355a5b..c5715608fe63 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -108,6 +108,29 @@ objtool_link()
+ fi
+ }
+
++# If CONFIG_LTO_CLANG is selected, we postpone running recordmcount until
++# we have compiled LLVM IR to an object file.
++recordmcount()
++{
++ if [ "${CONFIG_LTO_CLANG} ${CONFIG_FTRACE_MCOUNT_RECORD}" != "y y" ]; then
++ return
++ fi
++
++ if [ -n "${CC_USING_RECORD_MCOUNT}" ]; then
++ return
++ fi
++ if [ -n "${CC_USING_PATCHABLE_FUNCTION_ENTRY}" ]; then
++ return
++ fi
++
++ local flags=""
++
++ [ -n "${RECORDMCOUNT_WARN}" ] && flags="-w"
++
++ info MCOUNT $*
++ ${objtree}/scripts/recordmcount ${flags} $*
++}
++
+ # Link of vmlinux
+ # ${1} - output file
+ # ${2}, ${3}, ... - optional extra .o files
+@@ -316,6 +339,12 @@ objtool_link vmlinux.o
+ # modpost vmlinux.o to check for section mismatches
+ ${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1
+
++if [ -n "${CONFIG_LTO_CLANG}" ]; then
++ # If we postponed ELF processing steps due to LTO, process
++ # vmlinux.o instead.
++ recordmcount vmlinux.o
++fi
++
+ info MODINFO modules.builtin.modinfo
+ ${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo
+ info GEN modules.builtin
+diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
+index 7225107a9aaf..9e9f10b4d649 100644
+--- a/scripts/recordmcount.c
++++ b/scripts/recordmcount.c
+@@ -404,7 +404,8 @@ static uint32_t (*w2)(uint16_t);
+ /* Names of the sections that could contain calls to mcount. */
+ static int is_mcounted_section_name(char const *const txtname)
+ {
+- return strncmp(".text", txtname, 5) == 0 ||
++ return (strncmp(".text", txtname, 5) == 0 &&
++ strcmp(".text..nomcount", txtname) != 0) ||
+ strcmp(".init.text", txtname) == 0 ||
+ strcmp(".ref.text", txtname) == 0 ||
+ strcmp(".sched.text", txtname) == 0 ||
+--
+2.28.0
+
diff --git a/0007-kbuild-lto-postpone-objtool.patch b/0007-kbuild-lto-postpone-objtool.patch
new file mode 100644
index 000000000000..2dabca6fbe89
--- /dev/null
+++ b/0007-kbuild-lto-postpone-objtool.patch
@@ -0,0 +1,87 @@
+From 3cce747e84f3e12dc20368a85be694828e8e6eb7 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Mon, 13 Apr 2020 16:10:13 -0700
+Subject: [PATCH 07/24] kbuild: lto: postpone objtool
+
+With LTO, LLVM bitcode won't be compiled into native code until
+modpost_link, or modfinal for modules. This change postpones calls
+to objtool until after these steps.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ scripts/Makefile.build | 2 ++
+ scripts/Makefile.modfinal | 15 +++++++++++++++
+ scripts/link-vmlinux.sh | 9 +++++++++
+ 3 files changed, 26 insertions(+)
+
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index 64e99f4baa5b..82977350f5a6 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -226,6 +226,7 @@ endif # CC_USING_PATCHABLE_FUNCTION_ENTRY
+ endif # CONFIG_FTRACE_MCOUNT_RECORD
+
+ ifdef CONFIG_STACK_VALIDATION
++ifndef CONFIG_LTO_CLANG
+ ifneq ($(SKIP_STACK_VALIDATION),1)
+
+ __objtool_obj := $(objtree)/tools/objtool/objtool
+@@ -258,6 +259,7 @@ objtool_obj = $(if $(patsubst y%,, \
+ $(__objtool_obj))
+
+ endif # SKIP_STACK_VALIDATION
++endif # CONFIG_LTO_CLANG
+ endif # CONFIG_STACK_VALIDATION
+
+ # Rebuild all objects when objtool changes, or is enabled/disabled.
+diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
+index d168f0cfe67c..9f1df2f1fab5 100644
+--- a/scripts/Makefile.modfinal
++++ b/scripts/Makefile.modfinal
+@@ -48,6 +48,21 @@ endif # CC_USING_PATCHABLE_FUNCTION_ENTRY
+ endif # CC_USING_RECORD_MCOUNT
+ endif # CONFIG_FTRACE_MCOUNT_RECORD
+
++ifdef CONFIG_STACK_VALIDATION
++ifneq ($(SKIP_STACK_VALIDATION),1)
++cmd_ld_ko_o += \
++ $(objtree)/tools/objtool/objtool \
++ $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \
++ --module \
++ $(if $(CONFIG_FRAME_POINTER),,--no-fp) \
++ $(if $(CONFIG_GCOV_KERNEL),--no-unreachable,) \
++ $(if $(CONFIG_RETPOLINE),--retpoline,) \
++ $(if $(CONFIG_X86_SMAP),--uaccess,) \
++ $(@:.ko=$(prelink-ext).o);
++
++endif # SKIP_STACK_VALIDATION
++endif # CONFIG_STACK_VALIDATION
++
+ endif # CONFIG_LTO_CLANG
+
+ quiet_cmd_ld_ko_o = LD [M] $@
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index c5715608fe63..7e9de077ee7f 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -89,8 +89,17 @@ objtool_link()
+ {
+ local objtoolopt;
+
++ if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then
++ # Don't perform vmlinux validation unless explicitly requested,
++ # but run objtool on vmlinux.o now that we have an object file.
++ objtoolopt="check"
++ fi
++
+ if [ -n "${CONFIG_VMLINUX_VALIDATION}" ]; then
+ objtoolopt="check --vmlinux"
++ fi
++
++ if [ -n "${objtoolopt}" ]; then
+ if [ -z "${CONFIG_FRAME_POINTER}" ]; then
+ objtoolopt="${objtoolopt} --no-fp"
+ fi
+--
+2.28.0
+
diff --git a/0008-kbuild-lto-limit-inlining.patch b/0008-kbuild-lto-limit-inlining.patch
new file mode 100644
index 000000000000..fc91b82c7380
--- /dev/null
+++ b/0008-kbuild-lto-limit-inlining.patch
@@ -0,0 +1,38 @@
+From ba6bd6d4f05dc173ddcf5ff7365a7964c7769349 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Wed, 4 Dec 2019 15:57:39 -0800
+Subject: [PATCH 08/24] kbuild: lto: limit inlining
+
+This change limits function inlining across translation unit boundaries
+in order to reduce the binary size with LTO. The -import-instr-limit
+flag defines a size limit, as the number of LLVM IR instructions, for
+importing functions from other TUs, defaulting to 100.
+
+Based on testing with arm64 defconfig, we found that a limit of 5 is a
+reasonable compromise between performance and binary size, reducing the
+size of a stripped vmlinux by 11%.
+
+Suggested-by: George Burgess IV <gbiv@google.com>
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ Makefile | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/Makefile b/Makefile
+index 19e2bf26c52c..498d281aa318 100644
+--- a/Makefile
++++ b/Makefile
+@@ -895,6 +895,10 @@ else
+ CC_FLAGS_LTO_CLANG := -flto
+ endif
+ CC_FLAGS_LTO_CLANG += -fvisibility=default
++
++# Limit inlining across translation units to reduce binary size
++LD_FLAGS_LTO_CLANG := -mllvm -import-instr-limit=5
++KBUILD_LDFLAGS += $(LD_FLAGS_LTO_CLANG)
+ endif
+
+ ifdef CONFIG_LTO
+--
+2.28.0
+
diff --git a/0009-kbuild-lto-merge-module-sections.patch b/0009-kbuild-lto-merge-module-sections.patch
new file mode 100644
index 000000000000..6f0272a5d05d
--- /dev/null
+++ b/0009-kbuild-lto-merge-module-sections.patch
@@ -0,0 +1,65 @@
+From b54ed19078d33c7b777335e9ae135aec5c89ccdf Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Tue, 3 Dec 2019 15:56:24 -0800
+Subject: [PATCH 09/24] kbuild: lto: merge module sections
+
+LLD always splits sections with LTO, which increases module sizes. This
+change adds a linker script that merges the split sections in the final
+module.
+
+Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ Makefile | 2 ++
+ scripts/module-lto.lds | 26 ++++++++++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+ create mode 100644 scripts/module-lto.lds
+
+diff --git a/Makefile b/Makefile
+index 498d281aa318..50d9516e1796 100644
+--- a/Makefile
++++ b/Makefile
+@@ -899,6 +899,8 @@ CC_FLAGS_LTO_CLANG += -fvisibility=default
+ # Limit inlining across translation units to reduce binary size
+ LD_FLAGS_LTO_CLANG := -mllvm -import-instr-limit=5
+ KBUILD_LDFLAGS += $(LD_FLAGS_LTO_CLANG)
++
++KBUILD_LDS_MODULE += $(srctree)/scripts/module-lto.lds
+ endif
+
+ ifdef CONFIG_LTO
+diff --git a/scripts/module-lto.lds b/scripts/module-lto.lds
+new file mode 100644
+index 000000000000..cbb11dc3639a
+--- /dev/null
++++ b/scripts/module-lto.lds
+@@ -0,0 +1,26 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * With CONFIG_LTO_CLANG, LLD always enables -fdata-sections and
++ * -ffunction-sections, which increases the size of the final module.
++ * Merge the split sections in the final binary.
++ */
++SECTIONS {
++ __patchable_function_entries : { *(__patchable_function_entries) }
++
++ .bss : {
++ *(.bss .bss.[0-9a-zA-Z_]*)
++ *(.bss..L*)
++ }
++
++ .data : {
++ *(.data .data.[0-9a-zA-Z_]*)
++ *(.data..L*)
++ }
++
++ .rodata : {
++ *(.rodata .rodata.[0-9a-zA-Z_]*)
++ *(.rodata..L*)
++ }
++
++ .text : { *(.text .text.[0-9a-zA-Z_]*) }
++}
+--
+2.28.0
+
diff --git a/0010-kbuild-lto-remove-duplicate-dependencies-from-.mod-f.patch b/0010-kbuild-lto-remove-duplicate-dependencies-from-.mod-f.patch
new file mode 100644
index 000000000000..2ccca6751423
--- /dev/null
+++ b/0010-kbuild-lto-remove-duplicate-dependencies-from-.mod-f.patch
@@ -0,0 +1,38 @@
+From b71272e6ef894b1fab04efa2ba98e32d00829eb0 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Wed, 5 Feb 2020 06:09:07 -0800
+Subject: [PATCH 10/24] kbuild: lto: remove duplicate dependencies from .mod
+ files
+
+With LTO, llvm-nm prints out symbols for each archive member
+separately, which results in a lot of duplicate dependencies in the
+.mod file when CONFIG_TRIM_UNUSED_SYMS is enabled. When a module
+consists of several compilation units, the output can exceed the
+default xargs command size limit and split the dependency list to
+multiple lines, which results in used symbols getting trimmed.
+
+This change removes duplicate dependencies, which will reduce the
+probability of this happening and makes .mod files smaller and
+easier to read.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ scripts/Makefile.build | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index 82977350f5a6..82b465ce3ca0 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -291,7 +291,7 @@ endef
+
+ # List module undefined symbols (or empty line if not enabled)
+ ifdef CONFIG_TRIM_UNUSED_KSYMS
+-cmd_undef_syms = $(NM) $< | sed -n 's/^ *U //p' | xargs echo
++cmd_undef_syms = $(NM) $< | sed -n 's/^ *U //p' | sort -u | xargs echo
+ else
+ cmd_undef_syms = echo
+ endif
+--
+2.28.0
+
diff --git a/0011-init-lto-ensure-initcall-ordering.patch b/0011-init-lto-ensure-initcall-ordering.patch
new file mode 100644
index 000000000000..0d9c6807de34
--- /dev/null
+++ b/0011-init-lto-ensure-initcall-ordering.patch
@@ -0,0 +1,442 @@
+From aab50d6ec2952003f430339dcbfffa407c7349e0 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Fri, 8 Dec 2017 15:49:24 -0800
+Subject: [PATCH 11/24] init: lto: ensure initcall ordering
+
+With LTO, the compiler doesn't necessarily obey the link order for
+initcalls, and initcall variables need globally unique names to avoid
+collisions at link time.
+
+This change exports __KBUILD_MODNAME and adds the initcall_id() macro,
+which uses it together with __COUNTER__ and __LINE__ to help ensure
+these variables have unique names, and moves each variable to its own
+section when LTO is enabled, so the correct order can be specified using
+a linker script.
+
+The generate_initcall_ordering.pl script uses nm to find initcalls from
+the object files passed to the linker, and generates a linker script
+that specifies the intended order. With LTO, the script is called in
+link-vmlinux.sh.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ include/linux/init.h | 52 +++++-
+ scripts/Makefile.lib | 6 +-
+ scripts/generate_initcall_order.pl | 270 +++++++++++++++++++++++++++++
+ scripts/link-vmlinux.sh | 14 ++
+ 4 files changed, 333 insertions(+), 9 deletions(-)
+ create mode 100755 scripts/generate_initcall_order.pl
+
+diff --git a/include/linux/init.h b/include/linux/init.h
+index 212fc9e2f691..af638cd6dd52 100644
+--- a/include/linux/init.h
++++ b/include/linux/init.h
+@@ -184,19 +184,57 @@ extern bool initcall_debug;
+ * as KEEP() in the linker script.
+ */
+
++/* Format: <modname>__<counter>_<line>_<fn> */
++#define __initcall_id(fn) \
++ __PASTE(__KBUILD_MODNAME, \
++ __PASTE(__, \
++ __PASTE(__COUNTER__, \
++ __PASTE(_, \
++ __PASTE(__LINE__, \
++ __PASTE(_, fn))))))
++
++/* Format: __<prefix>__<iid><id> */
++#define __initcall_name(prefix, __iid, id) \
++ __PASTE(__, \
++ __PASTE(prefix, \
++ __PASTE(__, \
++ __PASTE(__iid, id))))
++
++#ifdef CONFIG_LTO_CLANG
++/*
++ * With LTO, the compiler doesn't necessarily obey link order for
++ * initcalls. In order to preserve the correct order, we add each
++ * variable into its own section and generate a linker script (in
++ * scripts/link-vmlinux.sh) to specify the order of the sections.
++ */
++#define __initcall_section(__sec, __iid) \
++ #__sec ".init.." #__iid
++#else
++#define __initcall_section(__sec, __iid) \
++ #__sec ".init"
++#endif
++
+ #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+-#define ___define_initcall(fn, id, __sec) \
++#define ____define_initcall(fn, __name, __sec) \
+ __ADDRESSABLE(fn) \
+- asm(".section \"" #__sec ".init\", \"a\" \n" \
+- "__initcall_" #fn #id ": \n" \
++ asm(".section \"" __sec "\", \"a\" \n" \
++ __stringify(__name) ": \n" \
+ ".long " #fn " - . \n" \
+ ".previous \n");
+ #else
+-#define ___define_initcall(fn, id, __sec) \
+- static initcall_t __initcall_##fn##id __used \
+- __attribute__((__section__(#__sec ".init"))) = fn;
++#define ____define_initcall(fn, __name, __sec) \
++ static initcall_t __name __used \
++ __attribute__((__section__(__sec))) = fn;
+ #endif
+
++#define __unique_initcall(fn, id, __sec, __iid) \
++ ____define_initcall(fn, \
++ __initcall_name(initcall, __iid, id), \
++ __initcall_section(__sec, __iid))
++
++#define ___define_initcall(fn, id, __sec) \
++ __unique_initcall(fn, id, __sec, __initcall_id(fn))
++
+ #define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)
+
+ /*
+@@ -236,7 +274,7 @@ extern bool initcall_debug;
+ #define __exitcall(fn) \
+ static exitcall_t __exitcall_##fn __exit_call = fn
+
+-#define console_initcall(fn) ___define_initcall(fn,, .con_initcall)
++#define console_initcall(fn) ___define_initcall(fn, con, .con_initcall)
+
+ struct obs_kernel_param {
+ const char *str;
+diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
+index 54f7b7eb580b..5d7b0b2cc594 100644
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -106,9 +106,11 @@ target-stem = $(basename $(patsubst $(obj)/%,%,$@))
+ # These flags are needed for modversions and compiling, so we define them here
+ # $(modname_flags) defines KBUILD_MODNAME as the name of the module it will
+ # end up in (or would, if it gets compiled in)
+-name-fix = $(call stringify,$(subst $(comma),_,$(subst -,_,$1)))
++name-fix-token = $(subst $(comma),_,$(subst -,_,$1))
++name-fix = $(call stringify,$(call name-fix-token,$1))
+ basename_flags = -DKBUILD_BASENAME=$(call name-fix,$(basetarget))
+-modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname))
++modname_flags = -DKBUILD_MODNAME=$(call name-fix,$(modname)) \
++ -D__KBUILD_MODNAME=kmod_$(call name-fix-token,$(modname))
+ modfile_flags = -DKBUILD_MODFILE=$(call stringify,$(modfile))
+
+ orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
+diff --git a/scripts/generate_initcall_order.pl b/scripts/generate_initcall_order.pl
+new file mode 100755
+index 000000000000..fe83aec2b51e
+--- /dev/null
++++ b/scripts/generate_initcall_order.pl
+@@ -0,0 +1,270 @@
++#!/usr/bin/env perl
++# SPDX-License-Identifier: GPL-2.0
++#
++# Generates a linker script that specifies the correct initcall order.
++#
++# Copyright (C) 2019 Google LLC
++
++use strict;
++use warnings;
++use IO::Handle;
++use IO::Select;
++use POSIX ":sys_wait_h";
++
++my $nm = $ENV{'NM'} || die "$0: ERROR: NM not set?";
++my $objtree = $ENV{'objtree'} || '.';
++
++## currently active child processes
++my $jobs = {}; # child process pid -> file handle
++## results from child processes
++my $results = {}; # object index -> [ { level, secname }, ... ]
++
++## reads _NPROCESSORS_ONLN to determine the maximum number of processes to
++## start
++sub get_online_processors {
++ open(my $fh, "getconf _NPROCESSORS_ONLN 2>/dev/null |")
++ or die "$0: ERROR: failed to execute getconf: $!";
++ my $procs = <$fh>;
++ close($fh);
++
++ if (!($procs =~ /^\d+$/)) {
++ return 1;
++ }
++
++ return int($procs);
++}
++
++## writes results to the parent process
++## format: <file index> <initcall level> <base initcall section name>
++sub write_results {
++ my ($index, $initcalls) = @_;
++
++ # sort by the counter value to ensure the order of initcalls within
++ # each object file is correct
++ foreach my $counter (sort { $a <=> $b } keys(%{$initcalls})) {
++ my $level = $initcalls->{$counter}->{'level'};
++
++ # section name for the initcall function
++ my $secname = $initcalls->{$counter}->{'module'} . '__' .
++ $counter . '_' .
++ $initcalls->{$counter}->{'line'} . '_' .
++ $initcalls->{$counter}->{'function'};
++
++ print "$index $level $secname\n";
++ }
++}
++
++## reads a result line from a child process and adds it to the $results array
++sub read_results{
++ my ($fh) = @_;
++
++ # each child prints out a full line w/ autoflush and exits after the
++ # last line, so even if buffered I/O blocks here, it shouldn't block
++ # very long
++ my $data = <$fh>;
++
++ if (!defined($data)) {
++ return 0;
++ }
++
++ chomp($data);
++
++ my ($index, $level, $secname) = $data =~
++ /^(\d+)\ ([^\ ]+)\ (.*)$/;
++
++ if (!defined($index) ||
++ !defined($level) ||
++ !defined($secname)) {
++ die "$0: ERROR: child process returned invalid data: $data\n";
++ }
++
++ $index = int($index);
++
++ if (!exists($results->{$index})) {
++ $results->{$index} = [];
++ }
++
++ push (@{$results->{$index}}, {
++ 'level' => $level,
++ 'secname' => $secname
++ });
++
++ return 1;
++}
++
++## finds initcalls from an object file or all object files in an archive, and
++## writes results back to the parent process
++sub find_initcalls {
++ my ($index, $file) = @_;
++
++ die "$0: ERROR: file $file doesn't exist?" if (! -f $file);
++
++ open(my $fh, "\"$nm\" --defined-only \"$file\" 2>/dev/null |")
++ or die "$0: ERROR: failed to execute \"$nm\": $!";
++
++ my $initcalls = {};
++
++ while (<$fh>) {
++ chomp;
++
++ # check for the start of a new object file (if processing an
++ # archive)
++ my ($path)= $_ =~ /^(.+)\:$/;
++
++ if (defined($path)) {
++ write_results($index, $initcalls);
++ $initcalls = {};
++ next;
++ }
++
++ # look for an initcall
++ my ($module, $counter, $line, $symbol) = $_ =~
++ /[a-z]\s+__initcall__(\S*)__(\d+)_(\d+)_(.*)$/;
++
++ if (!defined($module)) {
++ $module = ''
++ }
++
++ if (!defined($counter) ||
++ !defined($line) ||
++ !defined($symbol)) {
++ next;
++ }
++
++ # parse initcall level
++ my ($function, $level) = $symbol =~
++ /^(.*)((early|rootfs|con|[0-9])s?)$/;
++
++ die "$0: ERROR: invalid initcall name $symbol in $file($path)"
++ if (!defined($function) || !defined($level));
++
++ $initcalls->{$counter} = {
++ 'module' => $module,
++ 'line' => $line,
++ 'function' => $function,
++ 'level' => $level,
++ };
++ }
++
++ close($fh);
++ write_results($index, $initcalls);
++}
++
++## waits for any child process to complete, reads the results, and adds them to
++## the $results array for later processing
++sub wait_for_results {
++ my ($select) = @_;
++
++ my $pid = 0;
++ do {
++ # unblock children that may have a full write buffer
++ foreach my $fh ($select->can_read(0)) {
++ read_results($fh);
++ }
++
++ # check for children that have exited, read the remaining data
++ # from them, and clean up
++ $pid = waitpid(-1, WNOHANG);
++ if ($pid > 0) {
++ if (!exists($jobs->{$pid})) {
++ next;
++ }
++
++ my $fh = $jobs->{$pid};
++ $select->remove($fh);
++
++ while (read_results($fh)) {
++ # until eof
++ }
++
++ close($fh);
++ delete($jobs->{$pid});
++ }
++ } while ($pid > 0);
++}
++
++## forks a child to process each file passed in the command line and collects
++## the results
++sub process_files {
++ my $index = 0;
++ my $njobs = get_online_processors();
++ my $select = IO::Select->new();
++
++ while (my $file = shift(@ARGV)) {
++ # fork a child process and read it's stdout
++ my $pid = open(my $fh, '-|');
++
++ if (!defined($pid)) {
++ die "$0: ERROR: failed to fork: $!";
++ } elsif ($pid) {
++ # save the child process pid and the file handle
++ $select->add($fh);
++ $jobs->{$pid} = $fh;
++ } else {
++ # in the child process
++ STDOUT->autoflush(1);
++ find_initcalls($index, "$objtree/$file");
++ exit;
++ }
++
++ $index++;
++
++ # limit the number of children to $njobs
++ if (scalar(keys(%{$jobs})) >= $njobs) {
++ wait_for_results($select);
++ }
++ }
++
++ # wait for the remaining children to complete
++ while (scalar(keys(%{$jobs})) > 0) {
++ wait_for_results($select);
++ }
++}
++
++sub generate_initcall_lds() {
++ process_files();
++
++ my $sections = {}; # level -> [ secname, ...]
++
++ # sort results to retain link order and split to sections per
++ # initcall level
++ foreach my $index (sort { $a <=> $b } keys(%{$results})) {
++ foreach my $result (@{$results->{$index}}) {
++ my $level = $result->{'level'};
++
++ if (!exists($sections->{$level})) {
++ $sections->{$level} = [];
++ }
++
++ push(@{$sections->{$level}}, $result->{'secname'});
++ }
++ }
++
++ die "$0: ERROR: no initcalls?" if (!keys(%{$sections}));
++
++ # print out a linker script that defines the order of initcalls for
++ # each level
++ print "SECTIONS {\n";
++
++ foreach my $level (sort(keys(%{$sections}))) {
++ my $section;
++
++ if ($level eq 'con') {
++ $section = '.con_initcall.init';
++ } else {
++ $section = ".initcall${level}.init";
++ }
++
++ print "\t${section} : {\n";
++
++ foreach my $secname (@{$sections->{$level}}) {
++ print "\t\t*(${section}..${secname}) ;\n";
++ }
++
++ print "\t}\n";
++ }
++
++ print "}\n";
++}
++
++generate_initcall_lds();
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index 7e9de077ee7f..5b95af4b5c4a 100755
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -39,6 +39,16 @@ info()
+ fi
+ }
+
++# Generate a linker script to ensure correct ordering of initcalls.
++gen_initcalls()
++{
++ info GEN .tmp_initcalls.lds
++
++ ${srctree}/scripts/generate_initcall_order.pl \
++ ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \
++ > .tmp_initcalls.lds
++}
++
+ # If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
+ # .tmp_symversions.lds
+ gen_symversions()
+@@ -70,6 +80,9 @@ modpost_link()
+ --end-group"
+
+ if [ -n "${CONFIG_LTO_CLANG}" ]; then
++ gen_initcalls
++ lds="-T .tmp_initcalls.lds"
++
+ if [ -n "${CONFIG_MODVERSIONS}" ]; then
+ gen_symversions
+ lds="${lds} -T .tmp_symversions.lds"
+@@ -292,6 +305,7 @@ cleanup()
+ {
+ rm -f .btf.*
+ rm -f .tmp_System.map
++ rm -f .tmp_initcalls.lds
+ rm -f .tmp_symversions.lds
+ rm -f .tmp_vmlinux*
+ rm -f System.map
+--
+2.28.0
+
diff --git a/0012-init-lto-fix-PREL32-relocations.patch b/0012-init-lto-fix-PREL32-relocations.patch
new file mode 100644
index 000000000000..9fa77b777fbb
--- /dev/null
+++ b/0012-init-lto-fix-PREL32-relocations.patch
@@ -0,0 +1,77 @@
+From bbc874d7b9d64809d9aab8ff9a188c02003971ad Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Sun, 22 Mar 2020 17:01:40 -0700
+Subject: [PATCH 12/24] init: lto: fix PREL32 relocations
+
+With LTO, the compiler can rename static functions to avoid global
+naming collisions. As initcall functions are typically static,
+renaming can break references to them in inline assembly. This
+change adds a global stub with a stable name for each initcall to
+fix the issue when PREL32 relocations are used.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ include/linux/init.h | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/init.h b/include/linux/init.h
+index af638cd6dd52..cea63f7e7705 100644
+--- a/include/linux/init.h
++++ b/include/linux/init.h
+@@ -209,26 +209,49 @@ extern bool initcall_debug;
+ */
+ #define __initcall_section(__sec, __iid) \
+ #__sec ".init.." #__iid
++
++/*
++ * With LTO, the compiler can rename static functions to avoid
++ * global naming collisions. We use a global stub function for
++ * initcalls to create a stable symbol name whose address can be
++ * taken in inline assembly when PREL32 relocations are used.
++ */
++#define __initcall_stub(fn, __iid, id) \
++ __initcall_name(initstub, __iid, id)
++
++#define __define_initcall_stub(__stub, fn) \
++ int __init __stub(void); \
++ int __init __stub(void) \
++ { \
++ return fn(); \
++ } \
++ __ADDRESSABLE(__stub)
+ #else
+ #define __initcall_section(__sec, __iid) \
+ #__sec ".init"
++
++#define __initcall_stub(fn, __iid, id) fn
++
++#define __define_initcall_stub(__stub, fn) \
++ __ADDRESSABLE(fn)
+ #endif
+
+ #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+-#define ____define_initcall(fn, __name, __sec) \
+- __ADDRESSABLE(fn) \
++#define ____define_initcall(fn, __stub, __name, __sec) \
++ __define_initcall_stub(__stub, fn) \
+ asm(".section \"" __sec "\", \"a\" \n" \
+ __stringify(__name) ": \n" \
+- ".long " #fn " - . \n" \
++ ".long " __stringify(__stub) " - . \n" \
+ ".previous \n");
+ #else
+-#define ____define_initcall(fn, __name, __sec) \
++#define ____define_initcall(fn, __unused, __name, __sec) \
+ static initcall_t __name __used \
+ __attribute__((__section__(__sec))) = fn;
+ #endif
+
+ #define __unique_initcall(fn, id, __sec, __iid) \
+ ____define_initcall(fn, \
++ __initcall_stub(fn, __iid, id), \
+ __initcall_name(initcall, __iid, id), \
+ __initcall_section(__sec, __iid))
+
+--
+2.28.0
+
diff --git a/0013-PCI-Fix-PREL32-relocations-for-LTO.patch b/0013-PCI-Fix-PREL32-relocations-for-LTO.patch
new file mode 100644
index 000000000000..f98e7d2cb97b
--- /dev/null
+++ b/0013-PCI-Fix-PREL32-relocations-for-LTO.patch
@@ -0,0 +1,59 @@
+From b8a624d8f629a31cc567f34f64053fab031e70f3 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Thu, 19 Mar 2020 17:09:17 -0700
+Subject: [PATCH 13/24] PCI: Fix PREL32 relocations for LTO
+
+With Clang's Link Time Optimization (LTO), the compiler can rename
+static functions to avoid global naming collisions. As PCI fixup
+functions are typically static, renaming can break references
+to them in inline assembly. This change adds a global stub to
+DECLARE_PCI_FIXUP_SECTION to fix the issue when PREL32 relocations
+are used.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+---
+ include/linux/pci.h | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 34c1c4f45288..fd8ee60b812f 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1909,19 +1909,28 @@ enum pci_fixup_pass {
+ };
+
+ #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+-#define __DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class, \
+- class_shift, hook) \
+- __ADDRESSABLE(hook) \
++#define ___DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class, \
++ class_shift, hook, stub) \
++ void stub(struct pci_dev *dev); \
++ void stub(struct pci_dev *dev) \
++ { \
++ hook(dev); \
++ } \
+ asm(".section " #sec ", \"a\" \n" \
+ ".balign 16 \n" \
+ ".short " #vendor ", " #device " \n" \
+ ".long " #class ", " #class_shift " \n" \
+- ".long " #hook " - . \n" \
++ ".long " #stub " - . \n" \
+ ".previous \n");
++
++#define __DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class, \
++ class_shift, hook, stub) \
++ ___DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class, \
++ class_shift, hook, stub)
+ #define DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class, \
+ class_shift, hook) \
+ __DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class, \
+- class_shift, hook)
++ class_shift, hook, __UNIQUE_ID(hook))
+ #else
+ /* Anonymous variables would be nice... */
+ #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class, \
+--
+2.28.0
+
diff --git a/0014-modpost-lto-strip-.lto-from-module-names.patch b/0014-modpost-lto-strip-.lto-from-module-names.patch
new file mode 100644
index 000000000000..1ff4b6fde3dc
--- /dev/null
+++ b/0014-modpost-lto-strip-.lto-from-module-names.patch
@@ -0,0 +1,116 @@
+From 56f70f11a55f51c191b3bb65821ca2f5fd9e4924 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Fri, 6 Mar 2020 13:52:03 -0800
+Subject: [PATCH 14/24] modpost: lto: strip .lto from module names
+
+With LTO, everything is compiled into LLVM bitcode, so we have to link
+each module into native code before modpost. Kbuild uses the .lto.o
+suffix for these files, which also ends up in module information. This
+change strips the unnecessary .lto suffix from the module name.
+
+Suggested-by: Bill Wendling <morbo@google.com>
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ scripts/mod/modpost.c | 16 +++++++---------
+ scripts/mod/modpost.h | 9 +++++++++
+ scripts/mod/sumversion.c | 6 +++++-
+ 3 files changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index 69341b36f271..5a329df55cc3 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -17,7 +17,6 @@
+ #include <ctype.h>
+ #include <string.h>
+ #include <limits.h>
+-#include <stdbool.h>
+ #include <errno.h>
+ #include "modpost.h"
+ #include "../../include/linux/license.h"
+@@ -80,14 +79,6 @@ modpost_log(enum loglevel loglevel, const char *fmt, ...)
+ exit(1);
+ }
+
+-static inline bool strends(const char *str, const char *postfix)
+-{
+- if (strlen(str) < strlen(postfix))
+- return false;
+-
+- return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+-}
+-
+ void *do_nofail(void *ptr, const char *expr)
+ {
+ if (!ptr)
+@@ -1984,6 +1975,10 @@ static char *remove_dot(char *s)
+ size_t m = strspn(s + n + 1, "0123456789");
+ if (m && (s[n + m] == '.' || s[n + m] == 0))
+ s[n] = 0;
++
++ /* strip trailing .lto */
++ if (strends(s, ".lto"))
++ s[strlen(s) - 4] = '\0';
+ }
+ return s;
+ }
+@@ -2007,6 +2002,9 @@ static void read_symbols(const char *modname)
+ /* strip trailing .o */
+ tmp = NOFAIL(strdup(modname));
+ tmp[strlen(tmp) - 2] = '\0';
++ /* strip trailing .lto */
++ if (strends(tmp, ".lto"))
++ tmp[strlen(tmp) - 4] = '\0';
+ mod = new_module(tmp);
+ free(tmp);
+ }
+diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
+index 3aa052722233..fab30d201f9e 100644
+--- a/scripts/mod/modpost.h
++++ b/scripts/mod/modpost.h
+@@ -2,6 +2,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdarg.h>
++#include <stdbool.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+@@ -180,6 +181,14 @@ static inline unsigned int get_secindex(const struct elf_info *info,
+ return info->symtab_shndx_start[sym - info->symtab_start];
+ }
+
++static inline bool strends(const char *str, const char *postfix)
++{
++ if (strlen(str) < strlen(postfix))
++ return false;
++
++ return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
++}
++
+ /* file2alias.c */
+ extern unsigned int cross_build;
+ void handle_moddevtable(struct module *mod, struct elf_info *info,
+diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
+index d587f40f1117..760e6baa7eda 100644
+--- a/scripts/mod/sumversion.c
++++ b/scripts/mod/sumversion.c
+@@ -391,10 +391,14 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
+ struct md4_ctx md;
+ char *fname;
+ char filelist[PATH_MAX + 1];
++ int postfix_len = 1;
++
++ if (strends(modname, ".lto.o"))
++ postfix_len = 5;
+
+ /* objects for a module are listed in the first line of *.mod file. */
+ snprintf(filelist, sizeof(filelist), "%.*smod",
+- (int)strlen(modname) - 1, modname);
++ (int)strlen(modname) - postfix_len, modname);
+
+ buf = read_text_file(filelist);
+
+--
+2.28.0
+
diff --git a/0015-scripts-mod-disable-LTO-for-empty.c.patch b/0015-scripts-mod-disable-LTO-for-empty.c.patch
new file mode 100644
index 000000000000..2ab30257bce0
--- /dev/null
+++ b/0015-scripts-mod-disable-LTO-for-empty.c.patch
@@ -0,0 +1,28 @@
+From 5a21945e8fd13b08584e5e62b477dae609970c7c Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Mon, 10 Apr 2017 12:32:24 -0700
+Subject: [PATCH 15/24] scripts/mod: disable LTO for empty.c
+
+With CONFIG_LTO_CLANG, clang generates LLVM IR instead of ELF object
+files. As empty.o is used for probing target properties, disable LTO
+for it to produce an object file instead.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ scripts/mod/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
+index 296b6a3878b2..b6e3b40c6eeb 100644
+--- a/scripts/mod/Makefile
++++ b/scripts/mod/Makefile
+@@ -1,5 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ OBJECT_FILES_NON_STANDARD := y
++CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)
+
+ hostprogs := modpost mk_elfconfig
+ always-y := $(hostprogs) empty.o
+--
+2.28.0
+
diff --git a/0016-efi-libstub-disable-LTO.patch b/0016-efi-libstub-disable-LTO.patch
new file mode 100644
index 000000000000..e4e517cfcedd
--- /dev/null
+++ b/0016-efi-libstub-disable-LTO.patch
@@ -0,0 +1,30 @@
+From b34b8b1ffab687116806638c2c8e2bbf0b70d52e Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Mon, 1 May 2017 11:08:05 -0700
+Subject: [PATCH 16/24] efi/libstub: disable LTO
+
+With CONFIG_LTO_CLANG, we produce LLVM bitcode instead of ELF object
+files. Since LTO is not really needed here and the Makefile assumes we
+produce an object file, disable LTO for libstub.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ drivers/firmware/efi/libstub/Makefile | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
+index 75daaf20374e..95e12002cc7c 100644
+--- a/drivers/firmware/efi/libstub/Makefile
++++ b/drivers/firmware/efi/libstub/Makefile
+@@ -35,6 +35,8 @@ KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
+
+ # remove SCS flags from all objects in this directory
+ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_SCS), $(KBUILD_CFLAGS))
++# disable LTO
++KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS))
+
+ GCOV_PROFILE := n
+ # Sanitizer runtimes are unavailable and cannot be linked here.
+--
+2.28.0
+
diff --git a/0017-drivers-misc-lkdtm-disable-LTO-for-rodata.o.patch b/0017-drivers-misc-lkdtm-disable-LTO-for-rodata.o.patch
new file mode 100644
index 000000000000..f6fbfc001587
--- /dev/null
+++ b/0017-drivers-misc-lkdtm-disable-LTO-for-rodata.o.patch
@@ -0,0 +1,29 @@
+From 32d54d9cf192a72bde7eab0358832ecb785a3b80 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Tue, 5 Dec 2017 12:54:13 -0800
+Subject: [PATCH 17/24] drivers/misc/lkdtm: disable LTO for rodata.o
+
+Disable LTO for rodata.o to allow objcopy to be used to
+manipulate sections.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+Acked-by: Kees Cook <keescook@chromium.org>
+---
+ drivers/misc/lkdtm/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile
+index c70b3822013f..dd4c936d4d73 100644
+--- a/drivers/misc/lkdtm/Makefile
++++ b/drivers/misc/lkdtm/Makefile
+@@ -13,6 +13,7 @@ lkdtm-$(CONFIG_LKDTM) += cfi.o
+
+ KASAN_SANITIZE_stackleak.o := n
+ KCOV_INSTRUMENT_rodata.o := n
++CFLAGS_REMOVE_rodata.o += $(CC_FLAGS_LTO)
+
+ OBJCOPYFLAGS :=
+ OBJCOPYFLAGS_rodata_objcopy.o := \
+--
+2.28.0
+
diff --git a/0018-arm64-export-CC_USING_PATCHABLE_FUNCTION_ENTRY.patch b/0018-arm64-export-CC_USING_PATCHABLE_FUNCTION_ENTRY.patch
new file mode 100644
index 000000000000..9e4fda6acf3a
--- /dev/null
+++ b/0018-arm64-export-CC_USING_PATCHABLE_FUNCTION_ENTRY.patch
@@ -0,0 +1,29 @@
+From 1e323ca36f6cf7b3c85a22cf5195a05fe15002b3 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Mon, 6 Apr 2020 14:58:41 -0700
+Subject: [PATCH 18/24] arm64: export CC_USING_PATCHABLE_FUNCTION_ENTRY
+
+Since arm64 does not use -pg in CC_FLAGS_FTRACE with
+DYNAMIC_FTRACE_WITH_REGS, skip running recordmcount by
+exporting CC_USING_PATCHABLE_FUNCTION_ENTRY.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ arch/arm64/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
+index 70f5905954dd..c90cc19fab92 100644
+--- a/arch/arm64/Makefile
++++ b/arch/arm64/Makefile
+@@ -115,6 +115,7 @@ endif
+ ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_REGS),y)
+ KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
+ CC_FLAGS_FTRACE := -fpatchable-function-entry=2
++ export CC_USING_PATCHABLE_FUNCTION_ENTRY := 1
+ endif
+
+ # Default value
+--
+2.28.0
+
diff --git a/0019-arm64-vdso-disable-LTO.patch b/0019-arm64-vdso-disable-LTO.patch
new file mode 100644
index 000000000000..37735ae4d65e
--- /dev/null
+++ b/0019-arm64-vdso-disable-LTO.patch
@@ -0,0 +1,31 @@
+From c317d4f54f587c42f0a4a2e3eafcf7de9d4e88d4 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Tue, 19 Dec 2017 08:55:23 -0800
+Subject: [PATCH 19/24] arm64: vdso: disable LTO
+
+Disable LTO for the vDSO by filtering out CC_FLAGS_LTO, as there's no
+point in using link-time optimization for the small about of C code.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ arch/arm64/kernel/vdso/Makefile | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
+index 45d5cfe46429..aa47070a3ccf 100644
+--- a/arch/arm64/kernel/vdso/Makefile
++++ b/arch/arm64/kernel/vdso/Makefile
+@@ -30,8 +30,8 @@ ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 --hash-style=sysv \
+ ccflags-y := -fno-common -fno-builtin -fno-stack-protector -ffixed-x18
+ ccflags-y += -DDISABLE_BRANCH_PROFILING
+
+-CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) $(GCC_PLUGINS_CFLAGS)
+-KBUILD_CFLAGS += $(DISABLE_LTO)
++CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) $(GCC_PLUGINS_CFLAGS) \
++ $(CC_FLAGS_LTO)
+ KASAN_SANITIZE := n
+ UBSAN_SANITIZE := n
+ OBJECT_FILES_NON_STANDARD := y
+--
+2.28.0
+
diff --git a/0020-arm64-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch b/0020-arm64-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
new file mode 100644
index 000000000000..a54a3e74a74d
--- /dev/null
+++ b/0020-arm64-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
@@ -0,0 +1,28 @@
+From ed4e20fa5e35bcb4a2e2ec0a47a44227349ac007 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Thu, 2 Nov 2017 09:34:42 -0700
+Subject: [PATCH 20/24] arm64: allow LTO_CLANG and THINLTO to be selected
+
+Allow CONFIG_LTO_CLANG and CONFIG_THINLTO to be enabled.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ arch/arm64/Kconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 66dc41fd49f2..c9fb665b62b5 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -72,6 +72,8 @@ config ARM64
+ select ARCH_USE_SYM_ANNOTATIONS
+ select ARCH_SUPPORTS_MEMORY_FAILURE
+ select ARCH_SUPPORTS_SHADOW_CALL_STACK if CC_HAVE_SHADOW_CALL_STACK
++ select ARCH_SUPPORTS_LTO_CLANG
++ select ARCH_SUPPORTS_THINLTO
+ select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 && (GCC_VERSION >= 50000 || CC_IS_CLANG)
+ select ARCH_SUPPORTS_NUMA_BALANCING
+--
+2.28.0
+
diff --git a/0021-g86-vdso-disable-LTO-only-for-vDSO.patch b/0021-g86-vdso-disable-LTO-only-for-vDSO.patch
new file mode 100644
index 000000000000..fa7009ba2782
--- /dev/null
+++ b/0021-g86-vdso-disable-LTO-only-for-vDSO.patch
@@ -0,0 +1,48 @@
+From 69e4a800e255147d8e9fb52eaab8d6b29a33ebcf Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Tue, 16 Apr 2019 14:40:00 -0700
+Subject: [PATCH 21/24] g86, vdso: disable LTO only for vDSO
+
+Remove the undefined DISABLE_LTO flag from the vDSO, and filter out
+CC_FLAGS_LTO flags instead where needed. Note that while we could use
+Clang's LTO for the 64-bit vDSO, it won't add noticeable benefit for
+the small amount of C code.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ arch/x86/entry/vdso/Makefile | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
+index 04e65f0698f6..67f60662830a 100644
+--- a/arch/x86/entry/vdso/Makefile
++++ b/arch/x86/entry/vdso/Makefile
+@@ -9,8 +9,6 @@ ARCH_REL_TYPE_ABS := R_X86_64_JUMP_SLOT|R_X86_64_GLOB_DAT|R_X86_64_RELATIVE|
+ ARCH_REL_TYPE_ABS += R_386_GLOB_DAT|R_386_JMP_SLOT|R_386_RELATIVE
+ include $(srctree)/lib/vdso/Makefile
+
+-KBUILD_CFLAGS += $(DISABLE_LTO)
+-
+ # Sanitizer runtimes are unavailable and cannot be linked here.
+ KASAN_SANITIZE := n
+ UBSAN_SANITIZE := n
+@@ -92,7 +90,7 @@ ifneq ($(RETPOLINE_VDSO_CFLAGS),)
+ endif
+ endif
+
+-$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
++$(vobjs): KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO) $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
+
+ #
+ # vDSO code runs in userspace and -pg doesn't help with profiling anyway.
+@@ -150,6 +148,7 @@ KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 := $(filter-out -mfentry,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 := $(filter-out $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS_32))
++KBUILD_CFLAGS_32 := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 += -m32 -msoft-float -mregparm=0 -fpic
+ KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector)
+ KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls)
+--
+2.28.0
+
diff --git a/0022-x86-ftrace-disable-recordmcount-for-ftrace_make_nop.patch b/0022-x86-ftrace-disable-recordmcount-for-ftrace_make_nop.patch
new file mode 100644
index 000000000000..b6f69b476300
--- /dev/null
+++ b/0022-x86-ftrace-disable-recordmcount-for-ftrace_make_nop.patch
@@ -0,0 +1,27 @@
+From f388fe0b28282f272c8ca441e63f16c438c55bde Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Tue, 5 May 2020 14:58:24 -0700
+Subject: [PATCH 22/24] x86, ftrace: disable recordmcount for ftrace_make_nop
+
+Ignore mcount relocations in ftrace_make_nop.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ arch/x86/kernel/ftrace.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
+index 51504566b3a6..c3b28b81277b 100644
+--- a/arch/x86/kernel/ftrace.c
++++ b/arch/x86/kernel/ftrace.c
+@@ -121,6 +121,7 @@ ftrace_modify_code_direct(unsigned long ip, const char *old_code,
+ return 0;
+ }
+
++__nomcount
+ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
+ {
+ unsigned long ip = rec->ip;
+--
+2.28.0
+
diff --git a/0023-x86-relocs-Ignore-L4_PAGE_OFFSET-relocations.patch b/0023-x86-relocs-Ignore-L4_PAGE_OFFSET-relocations.patch
new file mode 100644
index 000000000000..72bbad0cfcf9
--- /dev/null
+++ b/0023-x86-relocs-Ignore-L4_PAGE_OFFSET-relocations.patch
@@ -0,0 +1,28 @@
+From be6d4b6b69e92700f1a2359de3a02c358e074926 Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Fri, 17 Apr 2020 19:28:45 -0700
+Subject: [PATCH 23/24] x86, relocs: Ignore L4_PAGE_OFFSET relocations
+
+L4_PAGE_OFFSET is a constant value, so don't warn about absolute
+relocations.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ arch/x86/tools/relocs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
+index ce7188cbdae5..8f3bf34840ce 100644
+--- a/arch/x86/tools/relocs.c
++++ b/arch/x86/tools/relocs.c
+@@ -47,6 +47,7 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
+ [S_ABS] =
+ "^(xen_irq_disable_direct_reloc$|"
+ "xen_save_fl_direct_reloc$|"
++ "L4_PAGE_OFFSET|"
+ "VDSO|"
+ "__crc_)",
+
+--
+2.28.0
+
diff --git a/0024-x86-build-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch b/0024-x86-build-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
new file mode 100644
index 000000000000..1196a76b0f7d
--- /dev/null
+++ b/0024-x86-build-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
@@ -0,0 +1,45 @@
+From c4850e7fee85527976519f6d55685706d41cb91b Mon Sep 17 00:00:00 2001
+From: Sami Tolvanen <samitolvanen@google.com>
+Date: Wed, 10 Apr 2019 14:17:20 -0700
+Subject: [PATCH 24/24] x86, build: allow LTO_CLANG and THINLTO to be selected
+
+Allow CONFIG_LTO_CLANG and CONFIG_THINLTO to be enabled.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+---
+ arch/x86/Kconfig | 2 ++
+ arch/x86/Makefile | 5 +++++
+ 2 files changed, 7 insertions(+)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 4a64395bc35d..16f046d5abea 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -92,6 +92,8 @@ config X86
+ select ARCH_SUPPORTS_ACPI
+ select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_NUMA_BALANCING if X86_64
++ select ARCH_SUPPORTS_LTO_CLANG if X86_64
++ select ARCH_SUPPORTS_THINLTO if X86_64
+ select ARCH_USE_BUILTIN_BSWAP
+ select ARCH_USE_QUEUED_RWLOCKS
+ select ARCH_USE_QUEUED_SPINLOCKS
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index 00e378de8bc0..a1abc1e081ad 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -188,6 +188,11 @@ ifdef CONFIG_X86_64
+ KBUILD_LDFLAGS += $(call ld-option, -z max-page-size=0x200000)
+ endif
+
++ifdef CONFIG_LTO_CLANG
++KBUILD_LDFLAGS += -plugin-opt=-code-model=kernel \
++ -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8)
++endif
++
+ # Workaround for a gcc prelease that unfortunately was shipped in a suse release
+ KBUILD_CFLAGS += -Wno-sign-compare
+ #
+--
+2.28.0
+
diff --git a/PKGBUILD b/PKGBUILD
index e7337695e3b8..23b6b795ecb5 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -20,6 +20,7 @@ source=(
"$_srcname::git+https://git.archlinux.org/linux.git#tag=$_srctag"
config # the main kernel config file
sphinx-workaround.patch
+ # ZSTD
0001-lib-prepare-zstd-for-preboot-environment.patch
0002-lib-add-zstd-support-to-decompress.patch
0003-init-add-support-for-zstd-compressed-kernel.patch
@@ -27,10 +28,36 @@ source=(
0005-x86-bump-ZO_z_extra_bytes-margin-for-zstd.patch
0006-x86-Add-support-for-ZSTD-compressed-kernel.patch
0007-.gitignore-add-ZSTD-compressed-files.patch
+ # LTO
+ 0001-bitfield.h-don-t-compile-time-validate-_val-in-FIELD.patch
+ 0002-objtool-use-sh_info-to-find-the-base-for-.rela-secti.patch
+ 0003-objtool-don-t-autodetect-vmlinux.o.patch
+ 0004-kbuild-add-support-for-Clang-LTO.patch
+ 0005-kbuild-lto-fix-module-versioning.patch
+ 0006-kbuild-lto-fix-recordmcount.patch
+ 0007-kbuild-lto-postpone-objtool.patch
+ 0008-kbuild-lto-limit-inlining.patch
+ 0009-kbuild-lto-merge-module-sections.patch
+ 0010-kbuild-lto-remove-duplicate-dependencies-from-.mod-f.patch
+ 0011-init-lto-ensure-initcall-ordering.patch
+ 0012-init-lto-fix-PREL32-relocations.patch
+ 0013-PCI-Fix-PREL32-relocations-for-LTO.patch
+ 0014-modpost-lto-strip-.lto-from-module-names.patch
+ 0015-scripts-mod-disable-LTO-for-empty.c.patch
+ 0016-efi-libstub-disable-LTO.patch
+ 0017-drivers-misc-lkdtm-disable-LTO-for-rodata.o.patch
+ 0018-arm64-export-CC_USING_PATCHABLE_FUNCTION_ENTRY.patch
+ 0019-arm64-vdso-disable-LTO.patch
+ 0020-arm64-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
+ 0021-g86-vdso-disable-LTO-only-for-vDSO.patch
+ 0022-x86-ftrace-disable-recordmcount-for-ftrace_make_nop.patch
+ 0023-x86-relocs-Ignore-L4_PAGE_OFFSET-relocations.patch
+ 0024-x86-build-allow-LTO_CLANG-and-THINLTO-to-be-selected.patch
+ # CPU
enable_additional_cpu_optimizations_for_gcc_v10.1+_kernel_v5.8+.patch
)
sha256sums=('SKIP'
- '7748dbdc1d0ff9efa8358268e82b21b338acfb7ebbd2876753bf23c4e71da44c'
+ '639e5ac559832b05d1b3be611faedab33aa65059eb8cd76879d2b92ecd17d7fa'
'8cb21e0b3411327b627a9dd15b8eb773295a0d2782b1a41b2a8839d1b2f5778c'
'2f0090ec0c9a72e6241bbea05faaef979405119ce8ef669d84dead36c8e2246e'
'5f21c12f002e71ec5b5db96832b415ce291a7e230fa07b328c21760274e72e9d'
@@ -39,6 +66,30 @@ sha256sums=('SKIP'
'2b558cc58e95343bb2e3cfd96c668b671251c543124176b8687baf12cdf999d5'
'84c275eb98fb908b742ffe51faa7feb0312550712b0cd729bf72941a2f633a65'
'f88df9ee297e229792e516ac9fb6f35ddc1aa13c3fdeb9ba15fb4de8b1dcd7c7'
+ '524b329a965f1b983fd4b78e1827854727d4ebb9c21cc9f245bf2ce91c2bed1d'
+ '053582c4fa855a9219f45f864d7a03b3a28cfd04ec798b0cc47080c836669184'
+ '7e155527495f8a009efc6edc43d44c1775de64c750c9c112f6964d599eada3ef'
+ '2ef22d6b576ebf452238ae48658515d5d484b3ab7448b9d62fc1295570bb8f14'
+ '9bbda700ef98d75ce24c43f5bf191f77f51d5587ea06ad5c763d9ac10d39c96e'
+ '5684845b4c0a516fc907a1f24d420760f2cd2a53ab977fb409a6378f9b1f473e'
+ '438c34b332cb3d67e31856f11ed71052974a869f8fd71da637343da7de0c1bf2'
+ 'efaa62f8d18463141958fdeb495b58c03e49f62ef7bca30e5cd261821bff4ca6'
+ 'c44e6e4de658ba682cba3b24f766af5bb70572869c8419c0091767726439bfa1'
+ '75939f2da39a5644e407aaee060ea00fa6b8e06bf5cc361af793affe5a660243'
+ '407e9262ed5cf234172f3048ae79513030589022acba42039ad709f490c6d139'
+ 'e89ceb6f4cda3fa9ae59c3482b27118df18c98d0a74665d0fe07f05017c1144e'
+ 'eacb3b5cd7380a48ae50f38c57153a3f90a6dd890b573bf172c0d0585e4f1ab9'
+ '7854b55ff44f5ec0a94d295075679aaaf1ff3baf9039bd8a7ea73e4e9ae4f8dd'
+ '4668748669f31e3535e02c11f2f4554412d5bd29279ebdbe241f515d7f34aafc'
+ '729f41453d3607c6c055ae1f52e476d09a4b49169897fe136ad37a451c7872bb'
+ 'e3d865689bc4c3ab52b9d0a897278bde415a7cd4892c0e7006ce7998c6e97fe7'
+ '4c2bc4f796ef21d1f5cbc7e4a7600a250c66de329819795f77cad3e52106b2fe'
+ '85bf687909b628e36ea8a2c973cdd3ef2819f57422d5405cf338abce9037ef9a'
+ '0c269cb936eec02fc767f1d4f2ca4436582f5c4f046a3b4c53608d4232a09809'
+ '0feb6c229e75c5a4ed532840bbe3ab1426ae255c0897f7852a93537e7661b461'
+ 'bd3f17cbb1da5293bb54a5bdeaa613098d41fe676ee327ba35867c18732ee80c'
+ '539794c1dc9b8e35a73e2e165040f363d0c7f32bc5da415ae6b27a9ffe57dde2'
+ '3b956c3768e59f2d5fb0546a855138319eff60e077822667befed734c7ac84af'
'5ab29eb64e57df83b395a29a6a4f89030d142feffbfbf73b3afc6d97a2a7fd12')
export KBUILD_BUILD_HOST=archlinux
diff --git a/config b/config
index 28dd8a383697..56da4388f1cc 100644
--- a/config
+++ b/config
@@ -854,6 +854,9 @@ CONFIG_HAVE_STACKPROTECTOR=y
CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
+CONFIG_ARCH_SUPPORTS_THINLTO=y
+CONFIG_LTO_NONE=y
CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y