Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ptr1337/0a472b1ba36973584928873bcfe97928 to your computer and use it in GitHub Desktop.
Save ptr1337/0a472b1ba36973584928873bcfe97928 to your computer and use it in GitHub Desktop.
From 841d090cab781709c26974af8309ac309ec32875 Mon Sep 17 00:00:00 2001
From: mssx86 <mss@tutanota.de>
Date: Thu, 13 May 2021 21:43:18 +0300
Subject: [PATCH] andikleen lto-5.12-3 3fb2a4dd for 5.12.3.
---
Documentation/bpf/btf.rst | 4 ++
Documentation/kbuild/lto-build.rst | 70 ++++++++++++++++++++
Kbuild | 3 +
Makefile | 9 ++-
arch/Kconfig | 53 +++++++++++++++
arch/x86/Kconfig | 5 +-
arch/x86/boot/compressed/string.c | 4 +-
arch/x86/entry/vdso/Makefile | 2 +
arch/x86/include/asm/preempt.h | 4 +-
arch/x86/kernel/alternative.c | 6 +-
arch/x86/kernel/cpu/resctrl/monitor.c | 2 +-
arch/x86/kernel/module.c | 7 +-
arch/x86/lib/memcpy_32.c | 6 +-
arch/x86/lib/msr-smp.c | 4 +-
arch/x86/purgatory/Makefile | 1 +
arch/x86/realmode/Makefile | 1 +
drivers/gpu/drm/amd/amdkfd/kfd_iommu.c | 4 +-
drivers/gpu/drm/i915/i915_drv.h | 6 +-
drivers/media/pci/cobalt/cobalt-i2c.c | 2 +-
drivers/media/pci/cx18/cx18-i2c.c | 2 +-
drivers/media/platform/sti/delta/delta-ipc.c | 4 +-
drivers/xen/time.c | 2 +-
fs/open.c | 2 +-
include/crypto/internal/poly1305.h | 2 +-
include/linux/btf_ids.h | 28 ++++----
include/linux/compiler_attributes.h | 16 +++++
include/linux/compiler_types.h | 10 +++
include/linux/export.h | 6 +-
include/linux/init.h | 2 +-
include/linux/linkage.h | 16 ++---
include/linux/static_call.h | 21 +++---
include/linux/tracepoint.h | 4 +-
init/Kconfig | 6 ++
kernel/Makefile | 2 +-
kernel/bpf/btf.c | 1 +
kernel/bpf/core.c | 2 +-
kernel/bpf/map_iter.c | 1 +
kernel/bpf/prog_iter.c | 1 +
kernel/bpf/task_iter.c | 1 +
kernel/livepatch/Kconfig | 1 +
kernel/locking/spinlock.c | 56 ++++++++--------
kernel/sched/core.c | 18 +++--
kernel/softirq.c | 2 +-
kernel/static_call.c | 14 ++--
kernel/time/posix-stubs.c | 2 +-
lib/Kconfig.debug | 1 +
net/core/filter.c | 2 +
net/ipv6/route.c | 1 +
net/netlink/af_netlink.c | 1 +
scripts/Makefile.build | 23 ++++---
scripts/Makefile.lib | 2 +-
scripts/Makefile.lto | 40 +++++++++++
scripts/Makefile.modfinal | 10 +--
scripts/Makefile.modpost | 6 +-
scripts/bloat-o-meter | 2 +-
scripts/gcc-ld | 18 +++--
scripts/gen_autoksyms.sh | 4 +-
scripts/link-vmlinux.sh | 49 +++++++-------
scripts/mksysmap | 3 +-
scripts/mod/Makefile | 3 +
scripts/mod/modpost.c | 22 +++++-
tools/objtool/arch/x86/decode.c | 7 +-
tools/objtool/check.c | 34 +++++++---
tools/objtool/include/objtool/check.h | 4 +-
tools/objtool/orc_gen.c | 19 ++++--
65 files changed, 482 insertions(+), 184 deletions(-)
create mode 100644 Documentation/kbuild/lto-build.rst
create mode 100644 scripts/Makefile.lto
diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
index 44dc789de..ee59e827d 100644
--- a/Documentation/bpf/btf.rst
+++ b/Documentation/bpf/btf.rst
@@ -706,6 +706,9 @@ with following syntax::
BTF_ID_LIST(list)
BTF_ID(type1, name1)
BTF_ID(type2, name2)
+ BTF_ID_LIST_END
+
+The unsorted list must be terminated with ``BTF_ID_LIST_END``.
resulting in following layout in .BTF_ids section::
@@ -723,6 +726,7 @@ want to define unused entry in BTF_ID_LIST, like::
BTF_ID(struct, sk_buff)
BTF_ID_UNUSED
BTF_ID(struct, task_struct)
+ BTF_ID_LIST_END
The ``BTF_SET_START/END`` macros pair defines sorted list of BTF ID values
and their count, with following syntax::
diff --git a/Documentation/kbuild/lto-build.rst b/Documentation/kbuild/lto-build.rst
new file mode 100644
index 000000000..e8a0f149e
--- /dev/null
+++ b/Documentation/kbuild/lto-build.rst
@@ -0,0 +1,70 @@
+=====================================================
+gcc link time optimization (LTO) for the Linux kernel
+=====================================================
+
+Link Time Optimization allows the compiler to optimize the complete program
+instead of just each file.
+
+The compiler can inline functions between files and do various other global
+optimizations, like specializing functions for common parameters,
+determing when global variables are clobbered, making functions pure/const,
+propagating constants globally, removing unneeded data and others.
+
+It will also drop unused functions which can make the kernel
+image smaller in some circumstances, in particular for small kernel
+configurations.
+
+For small monolithic kernels it can throw away unused code very effectively
+(especially when modules are disabled) and usually shrinks
+the code size.
+
+Build time and memory consumption at build time will increase, depending
+on the size of the largest binary. Modular kernels are less affected.
+With LTO incremental builds are less incremental, as always the whole
+binary needs to be re-optimized (but not re-parsed)
+
+Oopses can be somewhat more difficult to read, due to the more aggressive
+inlining: it helps to use scripts/faddr2line.
+
+It is currently incompatible with live patching.
+
+Normal "reasonable" builds work with less than 4GB of RAM, but very large
+configurations like allyesconfig typically need more memory. The actual
+memory needed depends on the available memory (gcc sizes its garbage
+collector pools based on that or on the ulimit -m limits) and
+the compiler version.
+
+Requirements:
+-------------
+- Enough memory: 4GB for a standard build, more for allyesconfig
+The peak memory usage happens single threaded (when lto-wpa merges types),
+so dialing back -j options will not help much.
+
+A 32bit hosted compiler is unlikely to work due to the memory requirements.
+You can however build a kernel targeted at 32bit on a 64bit host.
+
+FAQs:
+-----
+Q: I get a section type attribute conflict
+A: Usually because of someone doing
+const __initdata (should be const __initconst) or const __read_mostly
+(should be just const). Check both symbols reported by gcc.
+
+References:
+-----------
+
+Presentation on Kernel LTO
+(note, performance numbers/details totally outdated.)
+http://halobates.de/kernel-lto.pdf
+
+Generic gcc LTO:
+http://www.ucw.cz/~hubicka/slides/labs2013.pdf
+http://www.hipeac.net/system/files/barcelona.pdf
+
+Somewhat outdated too:
+http://gcc.gnu.org/projects/lto/lto.pdf
+http://gcc.gnu.org/projects/lto/whopr.pdf
+
+Happy Link-Time-Optimizing!
+
+Andi Kleen
diff --git a/Kbuild b/Kbuild
index fa441b98c..69c86a38e 100644
--- a/Kbuild
+++ b/Kbuild
@@ -10,6 +10,8 @@ bounds-file := include/generated/bounds.h
always-y := $(bounds-file)
targets := kernel/bounds.s
+kernel/bounds.s: KBUILD_CFLAGS += $(DISABLE_LTO_GCC)
+
$(bounds-file): kernel/bounds.s FORCE
$(call filechk,offsets,__LINUX_BOUNDS_H__)
@@ -32,6 +34,7 @@ always-y += $(offsets-file)
targets += arch/$(SRCARCH)/kernel/asm-offsets.s
arch/$(SRCARCH)/kernel/asm-offsets.s: $(timeconst-file) $(bounds-file)
+arch/$(SRCARCH)/kernel/asm-offsets.s: KBUILD_CFLAGS += $(DISABLE_LTO_GCC)
$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s FORCE
$(call filechk,offsets,__ASM_OFFSETS_H__)
diff --git a/Makefile b/Makefile
index 53a4b1cb7..961b66a77 100644
--- a/Makefile
+++ b/Makefile
@@ -437,6 +437,7 @@ STRIP = llvm-strip
else
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
+LDFINAL = $(LD)
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
OBJCOPY = $(CROSS_COMPILE)objcopy
@@ -509,7 +510,7 @@ CLANG_FLAGS :=
export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
-export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD
+export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ ZSTD LDFINAL
export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
@@ -977,6 +978,7 @@ include-$(CONFIG_KASAN) += scripts/Makefile.kasan
include-$(CONFIG_KCSAN) += scripts/Makefile.kcsan
include-$(CONFIG_UBSAN) += scripts/Makefile.ubsan
include-$(CONFIG_KCOV) += scripts/Makefile.kcov
+include-$(CONFIG_LTO_GCC) += scripts/Makefile.lto
include-$(CONFIG_GCC_PLUGINS) += scripts/Makefile.gcc-plugins
include $(addprefix $(srctree)/, $(include-y))
@@ -1191,8 +1193,9 @@ $(autoksyms_h):
ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
# Final link of vmlinux with optional arch pass after final link
-cmd_link-vmlinux = \
- $(CONFIG_SHELL) $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)"; \
+cmd_link-vmlinux = \
+ $(CONFIG_SHELL) $< "$(LD)" "$(LDFINAL)" "$(KBUILD_LDFLAGS)" \
+ "$(LDFLAGS_vmlinux)" ; \
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE
diff --git a/arch/Kconfig b/arch/Kconfig
index ecfd3520b..23702ce4a 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -643,6 +643,21 @@ config HAS_LTO_CLANG
The compiler and Kconfig options support building with Clang's
LTO.
+config ARCH_SUPPORTS_GCC_LTO
+ bool
+
+# Some ar versions leak file descriptors when using the LTO
+# plugin and cause strange errors when ulimit -n is too low.
+# Pick an arbitrary threshold, which should be enough for most
+# kernel configs. This was a regression that is only
+# in some transient binutils version, so either older or
+# new enough is ok.
+# This might not be the exact range with this bug.
+config BAD_AR
+ depends on LD_VERSION = 23000
+ depends on $(shell,ulimit -n) < 4000
+ def_bool y
+
choice
prompt "Link Time Optimization (LTO)"
default LTO_NONE
@@ -690,8 +705,46 @@ config LTO_CLANG_THIN
https://clang.llvm.org/docs/ThinLTO.html
If unsure, say Y.
+
+config LTO_GCC
+ bool "gcc LTO"
+ depends on ARCH_SUPPORTS_GCC_LTO && CC_IS_GCC
+ depends on GCC_VERSION >= 90000
+ depends on LD_VERSION >= 22700
+ depends on !BAD_AR
+ select LTO
+ select CC_NEEDS_FRE_WA if GCC_VERSION < 100300
+ help
+ Enable whole program (link time) optimizations (LTO) for the the
+ whole kernel and each module. This usually increases compile time,
+ especially for incremential builds, but tends to generate better code
+ as well as some global checks.
+
+ It allows the compiler to inline functions between different files
+ and do other global optimization, like propagating constants between
+ functions, determine side effects of functions, avoid unnecessary
+ register saving around functions, or optimize unused function arguments.
+ It also allows the compiler to drop unused functions.
+
+ With this option the compiler will also do some global checking over
+ different source files.
+
+ This requires a gcc 9 or later compiler and binutils >= 2.27.
+
+ On larger non modular configurations this may need more than 4GB of
+ RAM for the link phase, as well as a 64bit host compiler.
+
+ For more information see Documentation/kbuild/lto-build.rst
endchoice
+config LTO_CP_CLONE
+ bool "Allow aggressive cloning for function specialization"
+ depends on LTO_GCC
+ help
+ Allow the compiler to clone and specialize functions for specific
+ arguments when it determines these arguments are commonly
+ called. Experimential. Will increase text size.
+
config HAVE_ARCH_WITHIN_STACK_FRAMES
bool
help
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 268b7d5c9..703de5619 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -156,7 +156,9 @@ config X86
select HAVE_ARCH_MMAP_RND_BITS if MMU
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if MMU && COMPAT
select HAVE_ARCH_COMPAT_MMAP_BASES if MMU && COMPAT
- select HAVE_ARCH_PREL32_RELOCATIONS
+ # LTO can move assembler to different files, so all
+ # the init functions would need to be global for this to work
+ select HAVE_ARCH_PREL32_RELOCATIONS if !LTO_GCC
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
select HAVE_ARCH_STACKLEAK
@@ -242,6 +244,7 @@ config X86
select PCI_DOMAINS if PCI
select PCI_LOCKLESS_CONFIG if PCI
select PERF_EVENTS
+ select ARCH_SUPPORTS_GCC_LTO
select RTC_LIB
select RTC_MC146818_LIB
select SPARSE_IRQ
diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c
index 81fc1eaa3..05aa7a05e 100644
--- a/arch/x86/boot/compressed/string.c
+++ b/arch/x86/boot/compressed/string.c
@@ -50,7 +50,7 @@ void *memset(void *s, int c, size_t n)
return s;
}
-void *memmove(void *dest, const void *src, size_t n)
+__visible __used void *memmove(void *dest, const void *src, size_t n)
{
unsigned char *d = dest;
const unsigned char *s = src;
@@ -65,7 +65,7 @@ void *memmove(void *dest, const void *src, size_t n)
}
/* Detect and warn about potential overlaps, but handle them with memmove. */
-void *memcpy(void *dest, const void *src, size_t n)
+__visible __used void *memcpy(void *dest, const void *src, size_t n)
{
if (dest > src && dest - src < n) {
warn("Avoiding potentially unsafe overlapping memcpy()!");
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index 05c4abc2f..35dad9437 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -3,6 +3,8 @@
# Building vDSO images for x86.
#
+KBUILD_CFLAGS += $(DISABLE_LTO_GCC)
+
# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
# the inclusion of generic Makefile.
ARCH_REL_TYPE_ABS := R_X86_64_JUMP_SLOT|R_X86_64_GLOB_DAT|R_X86_64_RELATIVE|
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
index f8cb8af4d..903ad9011 100644
--- a/arch/x86/include/asm/preempt.h
+++ b/arch/x86/include/asm/preempt.h
@@ -106,12 +106,12 @@ static __always_inline bool should_resched(int preempt_offset)
#ifdef CONFIG_PREEMPTION
extern asmlinkage void preempt_schedule(void);
-extern asmlinkage void preempt_schedule_thunk(void);
+extern __visible asmlinkage void preempt_schedule_thunk(void);
#define __preempt_schedule_func preempt_schedule_thunk
extern asmlinkage void preempt_schedule_notrace(void);
-extern asmlinkage void preempt_schedule_notrace_thunk(void);
+extern __visible asmlinkage void preempt_schedule_notrace_thunk(void);
#define __preempt_schedule_notrace_func preempt_schedule_notrace_thunk
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 8d778e467..e1c52f7d4 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -634,11 +634,12 @@ extern struct paravirt_patch_site __start_parainstructions[],
* convention such that we can 'call' it from assembly.
*/
-extern void int3_magic(unsigned int *ptr); /* defined in asm */
+extern __visible void int3_magic(unsigned int *ptr); /* defined in asm */
asm (
" .pushsection .init.text, \"ax\", @progbits\n"
" .type int3_magic, @function\n"
+" .globl int3_magic\n"
"int3_magic:\n"
" movl $1, (%" _ASM_ARG1 ")\n"
" ret\n"
@@ -646,7 +647,7 @@ asm (
" .popsection\n"
);
-extern __initdata unsigned long int3_selftest_ip; /* defined in asm below */
+extern __initdata __visible unsigned long int3_selftest_ip; /* defined in asm below */
static int __init
int3_exception_notify(struct notifier_block *self, unsigned long val, void *data)
@@ -687,6 +688,7 @@ static void __init int3_selftest(void)
asm volatile ("1: int3; nop; nop; nop; nop\n\t"
".pushsection .init.data,\"aw\"\n\t"
".align " __ASM_SEL(4, 8) "\n\t"
+ ".globl int3_selftest_ip\n\t"
".type int3_selftest_ip, @object\n\t"
".size int3_selftest_ip, " __ASM_SEL(4, 8) "\n\t"
"int3_selftest_ip:\n\t"
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 7ac31210e..4327792a2 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -84,7 +84,7 @@ unsigned int resctrl_cqm_threshold;
static const struct mbm_correction_factor_table {
u32 rmidthreshold;
u64 cf;
-} mbm_cf_table[] __initdata = {
+} mbm_cf_table[] __initconst = {
{7, CF(1.000000)},
{15, CF(1.000000)},
{15, CF(0.969650)},
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index 5e9a34b5b..ff61a45fc 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -218,6 +218,11 @@ overflow:
return -ENOEXEC;
}
+static void *copy_write(void *dest, const void *src, size_t len)
+{
+ return memcpy(dest, src, len);
+}
+
int apply_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
@@ -226,7 +231,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
{
int ret;
bool early = me->state == MODULE_STATE_UNFORMED;
- void *(*write)(void *, const void *, size_t) = memcpy;
+ void *(*write)(void *, const void *, size_t) = copy_write;
if (!early) {
write = text_poke;
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
index e565d1c90..3435cd754 100644
--- a/arch/x86/lib/memcpy_32.c
+++ b/arch/x86/lib/memcpy_32.c
@@ -5,7 +5,7 @@
#undef memcpy
#undef memset
-__visible void *memcpy(void *to, const void *from, size_t n)
+__used __visible void *memcpy(void *to, const void *from, size_t n)
{
#if defined(CONFIG_X86_USE_3DNOW) && !defined(CONFIG_FORTIFY_SOURCE)
return __memcpy3d(to, from, n);
@@ -15,13 +15,13 @@ __visible void *memcpy(void *to, const void *from, size_t n)
}
EXPORT_SYMBOL(memcpy);
-__visible void *memset(void *s, int c, size_t count)
+__used __visible void *memset(void *s, int c, size_t count)
{
return __memset(s, c, count);
}
EXPORT_SYMBOL(memset);
-__visible void *memmove(void *dest, const void *src, size_t n)
+__used __visible void *memmove(void *dest, const void *src, size_t n)
{
int d0,d1,d2,d3,d4,d5;
char *ret = dest;
diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c
index 75a0915b0..40bbe56bd 100644
--- a/arch/x86/lib/msr-smp.c
+++ b/arch/x86/lib/msr-smp.c
@@ -252,7 +252,7 @@ static void __wrmsr_safe_regs_on_cpu(void *info)
rv->err = wrmsr_safe_regs(rv->regs);
}
-int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
{
int err;
struct msr_regs_info rv;
@@ -265,7 +265,7 @@ int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
}
EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
-int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
{
int err;
struct msr_regs_info rv;
diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
index 95ea17a9d..e3b04a62d 100644
--- a/arch/x86/purgatory/Makefile
+++ b/arch/x86/purgatory/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
OBJECT_FILES_NON_STANDARD := y
+KBUILD_CFLAGS += $(DISABLE_LTO_GCC)
purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
diff --git a/arch/x86/realmode/Makefile b/arch/x86/realmode/Makefile
index 6b1f3a4ee..af8945f4b 100644
--- a/arch/x86/realmode/Makefile
+++ b/arch/x86/realmode/Makefile
@@ -10,6 +10,7 @@
# Sanitizer runtimes are unavailable and cannot be linked here.
KASAN_SANITIZE := n
KCSAN_SANITIZE := n
+#KBUILD_CFLAGS += $(DISABLE_LTO)
OBJECT_FILES_NON_STANDARD := y
subdir- := rm
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
index 66bbca61e..e846844c8 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
@@ -330,8 +330,8 @@ int kfd_iommu_resume(struct kfd_dev *kfd)
}
extern bool amd_iommu_pc_supported(void);
-extern u8 amd_iommu_pc_get_max_banks(u16 devid);
-extern u8 amd_iommu_pc_get_max_counters(u16 devid);
+extern u8 amd_iommu_pc_get_max_banks(unsigned devid);
+extern u8 amd_iommu_pc_get_max_counters(unsigned devid);
/** kfd_iommu_add_perf_counters - Add IOMMU performance counters to topology
*/
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cb62ddba2..c80add5f6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1095,11 +1095,11 @@ struct drm_i915_private {
* in 0.5us units for WM1+.
*/
/* primary */
- u16 pri_latency[5];
+ u16 pri_latency[8];
/* sprite */
- u16 spr_latency[5];
+ u16 spr_latency[8];
/* cursor */
- u16 cur_latency[5];
+ u16 cur_latency[8];
/*
* Raw watermark memory latency values
* for SKL for all 8 levels
diff --git a/drivers/media/pci/cobalt/cobalt-i2c.c b/drivers/media/pci/cobalt/cobalt-i2c.c
index 10c9ee33f..ab8b7e31e 100644
--- a/drivers/media/pci/cobalt/cobalt-i2c.c
+++ b/drivers/media/pci/cobalt/cobalt-i2c.c
@@ -302,7 +302,7 @@ static const struct i2c_algorithm cobalt_algo = {
};
/* init + register i2c algo-bit adapter */
-int cobalt_i2c_init(struct cobalt *cobalt)
+__no_fre int cobalt_i2c_init(struct cobalt *cobalt)
{
int i, err;
int status;
diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c
index a83435245..ae775ab0b 100644
--- a/drivers/media/pci/cx18/cx18-i2c.c
+++ b/drivers/media/pci/cx18/cx18-i2c.c
@@ -214,7 +214,7 @@ static const struct i2c_algo_bit_data cx18_i2c_algo_template = {
};
/* init + register i2c adapter */
-int init_cx18_i2c(struct cx18 *cx)
+__no_fre int init_cx18_i2c(struct cx18 *cx)
{
int i, err;
CX18_DEBUG_I2C("i2c init\n");
diff --git a/drivers/media/platform/sti/delta/delta-ipc.c b/drivers/media/platform/sti/delta/delta-ipc.c
index 186d88f02..371429d81 100644
--- a/drivers/media/platform/sti/delta/delta-ipc.c
+++ b/drivers/media/platform/sti/delta/delta-ipc.c
@@ -175,8 +175,8 @@ int delta_ipc_open(struct delta_ctx *pctx, const char *name,
msg.ipc_buf_size = ipc_buf_size;
msg.ipc_buf_paddr = ctx->ipc_buf->paddr;
- memcpy(msg.name, name, sizeof(msg.name));
- msg.name[sizeof(msg.name) - 1] = 0;
+ memset(msg.name, 0, sizeof(msg.name));
+ strcpy(msg.name, name);
msg.param_size = param->size;
memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size);
diff --git a/drivers/xen/time.c b/drivers/xen/time.c
index 108edbcbc..fc7dd451b 100644
--- a/drivers/xen/time.c
+++ b/drivers/xen/time.c
@@ -144,7 +144,7 @@ void xen_get_runstate_snapshot(struct vcpu_runstate_info *res)
}
/* return true when a vcpu could run but has no real cpu to run on */
-bool xen_vcpu_stolen(int vcpu)
+__visible bool xen_vcpu_stolen(int vcpu)
{
return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable;
}
diff --git a/fs/open.c b/fs/open.c
index e53af13b5..f15eec2d4 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -66,7 +66,7 @@ int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
return ret;
}
-long vfs_truncate(const struct path *path, loff_t length)
+__visible long vfs_truncate(const struct path *path, loff_t length)
{
struct user_namespace *mnt_userns;
struct inode *inode;
diff --git a/include/crypto/internal/poly1305.h b/include/crypto/internal/poly1305.h
index 064e52ca5..90ee36411 100644
--- a/include/crypto/internal/poly1305.h
+++ b/include/crypto/internal/poly1305.h
@@ -18,7 +18,7 @@
* only the ε-almost-∆-universal hash function (not the full MAC) is computed.
*/
-void poly1305_core_setkey(struct poly1305_core_key *key, const u8 *raw_key);
+void poly1305_core_setkey(struct poly1305_core_key *key, const u8 raw_key[16]);
static inline void poly1305_core_init(struct poly1305_state *state)
{
*state = (struct poly1305_state){};
diff --git a/include/linux/btf_ids.h b/include/linux/btf_ids.h
index 57890b357..7986c4284 100644
--- a/include/linux/btf_ids.h
+++ b/include/linux/btf_ids.h
@@ -25,14 +25,13 @@ struct btf_id_set {
#define BTF_IDS_SECTION ".BTF_ids"
#define ____BTF_ID(symbol) \
-asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
-".local " #symbol " ; \n" \
+".globl " #symbol " ; \n" \
".type " #symbol ", STT_OBJECT; \n" \
".size " #symbol ", 4; \n" \
#symbol ": \n" \
".zero 4 \n" \
-".popsection; \n");
+".popsection; \n"
#define __BTF_ID(symbol) \
____BTF_ID(symbol)
@@ -47,6 +46,8 @@ asm( \
#define BTF_ID(prefix, name) \
__BTF_ID(__ID(__BTF_ID__##prefix##__##name##__))
+#define BTF_ID_LIST_END );
+
/*
* The BTF_ID_LIST macro defines pure (unsorted) list
* of BTF IDs, with following layout:
@@ -67,11 +68,11 @@ asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
"." #scope " " #name "; \n" \
#name ":; \n" \
-".popsection; \n");
+".popsection; \n"
#define BTF_ID_LIST(name) \
-__BTF_ID_LIST(name, local) \
-extern u32 name[];
+extern u32 name[]; \
+__BTF_ID_LIST(name, globl) \
#define BTF_ID_LIST_GLOBAL(name) \
__BTF_ID_LIST(name, globl)
@@ -80,8 +81,9 @@ __BTF_ID_LIST(name, globl)
* a single entry.
*/
#define BTF_ID_LIST_SINGLE(name, prefix, typename) \
- BTF_ID_LIST(name) \
- BTF_ID(prefix, typename)
+ BTF_ID_LIST(name) \
+ BTF_ID(prefix, typename) \
+ BTF_ID_LIST_END
/*
* The BTF_ID_UNUSED macro defines 4 zero bytes.
@@ -95,10 +97,9 @@ __BTF_ID_LIST(name, globl)
*/
#define BTF_ID_UNUSED \
-asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
".zero 4 \n" \
-".popsection; \n");
+".popsection; \n"
/*
* The BTF_SET_START/END macros pair defines sorted list of
@@ -119,15 +120,14 @@ asm( \
*
*/
#define __BTF_SET_START(name, scope) \
-asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
"." #scope " __BTF_ID__set__" #name "; \n" \
"__BTF_ID__set__" #name ":; \n" \
".zero 4 \n" \
-".popsection; \n");
+".popsection; \n"
#define BTF_SET_START(name) \
-__BTF_ID_LIST(name, local) \
+__BTF_ID_LIST(name, globl) \
__BTF_SET_START(name, local)
#define BTF_SET_START_GLOBAL(name) \
@@ -135,7 +135,6 @@ __BTF_ID_LIST(name, globl) \
__BTF_SET_START(name, globl)
#define BTF_SET_END(name) \
-asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
".size __BTF_ID__set__" #name ", .-" #name " \n" \
".popsection; \n"); \
@@ -148,6 +147,7 @@ extern struct btf_id_set name;
#define BTF_ID_UNUSED
#define BTF_ID_LIST_GLOBAL(name) u32 name[1];
#define BTF_ID_LIST_SINGLE(name, prefix, typename) static u32 name[1];
+#define BTF_ID_LIST_END
#define BTF_SET_START(name) static struct btf_id_set name = { 0 };
#define BTF_SET_START_GLOBAL(name) static struct btf_id_set name = { 0 };
#define BTF_SET_END(name)
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index c043b8d2b..48a004dea 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -34,6 +34,7 @@
# define __GCC4_has_attribute___no_caller_saved_registers__ 0
# define __GCC4_has_attribute___noclone__ 1
# define __GCC4_has_attribute___nonstring__ 0
+# define __GCC4_has_attribute___no_reorder__ 0
# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)
# define __GCC4_has_attribute___no_sanitize_undefined__ (__GNUC_MINOR__ >= 9)
# define __GCC4_has_attribute___fallthrough__ 0
@@ -214,7 +215,12 @@
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
* clang: https://clang.llvm.org/docs/AttributeReference.html#flatten
*/
+#ifndef CONFIG_LTO_GCC
# define __flatten __attribute__((flatten))
+#else
+/* Causes very large memory use with gcc 10 in LTO mode */
+# define __flatten
+#endif
/*
* Note the missing underscores.
@@ -290,4 +296,14 @@
*/
#define __weak __attribute__((__weak__))
+/*
+ * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
+ */
+
+#if __has_attribute(__no_reorder__)
+#define __noreorder __attribute__((no_reorder))
+#else
+#define __noreorder
+#endif
+
#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index e5dd5a4ae..bac3c526f 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -252,6 +252,16 @@ struct ftrace_likely_data {
#define asm_inline asm
#endif
+/*
+ * Work around compiler crash in some gcc versions by disabling
+ * FRE pass for a function.
+ */
+#ifdef CONFIG_CC_NEEDS_FRE_WA
+#define __no_fre __attribute__((optimize("-fno-tree-fre")))
+#else
+#define __no_fre
+#endif
+
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
diff --git a/include/linux/export.h b/include/linux/export.h
index 6271a5d9c..2ebd8c84d 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -96,12 +96,14 @@ struct kernel_symbol {
*/
#define ___EXPORT_SYMBOL(sym, sec, ns) \
extern typeof(sym) sym; \
- extern const char __kstrtab_##sym[]; \
- extern const char __kstrtabns_##sym[]; \
+ extern const char __visible __kstrtab_##sym[]; \
+ extern const char __visible __kstrtabns_##sym[]; \
__CRC_SYMBOL(sym, sec); \
asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \
+ " .globl __kstrtab_" #sym " \n" \
"__kstrtab_" #sym ": \n" \
" .asciz \"" #sym "\" \n" \
+ " .globl __kstrtabns_" #sym " \n" \
"__kstrtabns_" #sym ": \n" \
" .asciz \"" ns "\" \n" \
" .previous \n"); \
diff --git a/include/linux/init.h b/include/linux/init.h
index 31f54de58..4223047df 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -245,7 +245,7 @@ extern bool initcall_debug;
".previous \n");
#else
#define ____define_initcall(fn, __unused, __name, __sec) \
- static initcall_t __name __used \
+ static initcall_t __name __used __noreorder \
__attribute__((__section__(__sec))) = fn;
#endif
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index dbf8506de..645e5a73b 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -23,17 +23,17 @@
#endif
#ifndef cond_syscall
-#define cond_syscall(x) asm( \
- ".weak " __stringify(x) "\n\t" \
- ".set " __stringify(x) "," \
- __stringify(sys_ni_syscall))
+#define cond_syscall(x) \
+ extern long x(void) __attribute__((alias("sys_ni_syscall"), weak));
#endif
#ifndef SYSCALL_ALIAS
-#define SYSCALL_ALIAS(alias, name) asm( \
- ".globl " __stringify(alias) "\n\t" \
- ".set " __stringify(alias) "," \
- __stringify(name))
+#define SYSCALL_ALIAS(a, name) \
+ long a(void) __attribute__((alias(__stringify(name))))
+#define SYSCALL_ALIAS_PROTO(a, name) \
+ typeof(a) a __attribute__((alias(__stringify(name))))
+#else
+#define SYSCALL_ALIAS_PROTO(a, name) SYSCALL_ALIAS(a, name)
#endif
#define __page_aligned_data __section(".data..page_aligned") __aligned(PAGE_SIZE)
diff --git a/include/linux/static_call.h b/include/linux/static_call.h
index 85ecc789f..e75aef659 100644
--- a/include/linux/static_call.h
+++ b/include/linux/static_call.h
@@ -100,6 +100,8 @@
#ifdef CONFIG_HAVE_STATIC_CALL
#include <asm/static_call.h>
+extern long __static_call_return0(void);
+
/*
* Either @site or @tramp can be NULL.
*/
@@ -148,11 +150,9 @@ extern void __static_call_update(struct static_call_key *key, void *tramp, void
extern int static_call_mod_init(struct module *mod);
extern int static_call_text_reserved(void *start, void *end);
-extern long __static_call_return0(void);
-
#define __DEFINE_STATIC_CALL(name, _func, _func_init) \
DECLARE_STATIC_CALL(name, _func); \
- struct static_call_key STATIC_CALL_KEY(name) = { \
+ __visible struct static_call_key STATIC_CALL_KEY(name) = { \
.func = _func_init, \
.type = 1, \
}; \
@@ -160,7 +160,7 @@ extern long __static_call_return0(void);
#define DEFINE_STATIC_CALL_NULL(name, _func) \
DECLARE_STATIC_CALL(name, _func); \
- struct static_call_key STATIC_CALL_KEY(name) = { \
+ __visible struct static_call_key STATIC_CALL_KEY(name) = { \
.func = NULL, \
.type = 1, \
}; \
@@ -193,14 +193,14 @@ struct static_call_key {
#define __DEFINE_STATIC_CALL(name, _func, _func_init) \
DECLARE_STATIC_CALL(name, _func); \
- struct static_call_key STATIC_CALL_KEY(name) = { \
+ __visible struct static_call_key STATIC_CALL_KEY(name) = { \
.func = _func_init, \
}; \
ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func_init)
#define DEFINE_STATIC_CALL_NULL(name, _func) \
DECLARE_STATIC_CALL(name, _func); \
- struct static_call_key STATIC_CALL_KEY(name) = { \
+ __visible struct static_call_key STATIC_CALL_KEY(name) = { \
.func = NULL, \
}; \
ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name)
@@ -221,11 +221,6 @@ static inline int static_call_text_reserved(void *start, void *end)
return 0;
}
-static inline long __static_call_return0(void)
-{
- return 0;
-}
-
#define EXPORT_STATIC_CALL(name) \
EXPORT_SYMBOL(STATIC_CALL_KEY(name)); \
EXPORT_SYMBOL(STATIC_CALL_TRAMP(name))
@@ -254,13 +249,13 @@ static inline long __static_call_return0(void)
#define __DEFINE_STATIC_CALL(name, _func, _func_init) \
DECLARE_STATIC_CALL(name, _func); \
- struct static_call_key STATIC_CALL_KEY(name) = { \
+ __visible struct static_call_key STATIC_CALL_KEY(name) = { \
.func = _func_init, \
}
#define DEFINE_STATIC_CALL_NULL(name, _func) \
DECLARE_STATIC_CALL(name, _func); \
- struct static_call_key STATIC_CALL_KEY(name) = { \
+ __visible struct static_call_key STATIC_CALL_KEY(name) = { \
.func = NULL, \
}
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 9cfb099da..00ca51b38 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -229,7 +229,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
* poking RCU a bit.
*/
#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
- extern int __traceiter_##name(data_proto); \
+ extern int __visible __traceiter_##name(data_proto); \
DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \
extern struct tracepoint __tracepoint_##name; \
static inline void trace_##name(proto) \
@@ -296,7 +296,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
.unregfunc = _unreg, \
.funcs = NULL }; \
__TRACEPOINT_ENTRY(_name); \
- int __traceiter_##_name(void *__data, proto) \
+ __visible int __traceiter_##_name(void *__data, proto) \
{ \
struct tracepoint_func *it_func_ptr; \
void *it_func; \
diff --git a/init/Kconfig b/init/Kconfig
index 5f5c776ef..696212271 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1339,6 +1339,12 @@ config HAVE_LD_DEAD_CODE_DATA_ELIMINATION
sections (e.g., '.text.init'). Typically '.' in section names
is used to distinguish them from label names / C identifiers.
+config CC_NEEDS_FRE_WA
+ bool
+ help
+ Disable FRE compiler pass in some functions to work around
+ gcc segfault.
+
config LD_DEAD_CODE_DATA_ELIMINATION
bool "Dead code and data elimination (EXPERIMENTAL)"
depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
diff --git a/kernel/Makefile b/kernel/Makefile
index 605ec3e70..4071dbad2 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -110,7 +110,7 @@ obj-$(CONFIG_CPU_PM) += cpu_pm.o
obj-$(CONFIG_BPF) += bpf/
obj-$(CONFIG_KCSAN) += kcsan/
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
-obj-$(CONFIG_HAVE_STATIC_CALL_INLINE) += static_call.o
+obj-$(CONFIG_HAVE_STATIC_CALL) += static_call.o
obj-$(CONFIG_PERF_EVENTS) += events/
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index b1a76fe04..4e79f6989 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -4407,6 +4407,7 @@ static int btf_translate_to_vmlinux(struct bpf_verifier_log *log,
BTF_ID_LIST(bpf_ctx_convert_btf_id)
BTF_ID(struct, bpf_ctx_convert)
+BTF_ID_LIST_END
struct btf *btf_parse_vmlinux(void)
{
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 75244ecb2..1b89e0ece 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1373,7 +1373,7 @@ u64 __weak bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr)
*
* Decode and execute eBPF instructions.
*/
-static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)
+static u64 __noreorder ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)
{
#define BPF_INSN_2_LBL(x, y) [BPF_##x | BPF_##y] = &&x##_##y
#define BPF_INSN_3_LBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = &&x##_##y##_##z
diff --git a/kernel/bpf/map_iter.c b/kernel/bpf/map_iter.c
index 6a9542af4..548180dc4 100644
--- a/kernel/bpf/map_iter.c
+++ b/kernel/bpf/map_iter.c
@@ -80,6 +80,7 @@ static const struct seq_operations bpf_map_seq_ops = {
BTF_ID_LIST(btf_bpf_map_id)
BTF_ID(struct, bpf_map)
+BTF_ID_LIST_END
static const struct bpf_iter_seq_info bpf_map_seq_info = {
.seq_ops = &bpf_map_seq_ops,
diff --git a/kernel/bpf/prog_iter.c b/kernel/bpf/prog_iter.c
index 53a73c841..f9ea2dc32 100644
--- a/kernel/bpf/prog_iter.c
+++ b/kernel/bpf/prog_iter.c
@@ -80,6 +80,7 @@ static const struct seq_operations bpf_prog_seq_ops = {
BTF_ID_LIST(btf_bpf_prog_id)
BTF_ID(struct, bpf_prog)
+BTF_ID_LIST_END
static const struct bpf_iter_seq_info bpf_prog_seq_info = {
.seq_ops = &bpf_prog_seq_ops,
diff --git a/kernel/bpf/task_iter.c b/kernel/bpf/task_iter.c
index b68cb5d6d..99cc112d6 100644
--- a/kernel/bpf/task_iter.c
+++ b/kernel/bpf/task_iter.c
@@ -528,6 +528,7 @@ BTF_ID_LIST(btf_task_file_ids)
BTF_ID(struct, task_struct)
BTF_ID(struct, file)
BTF_ID(struct, vm_area_struct)
+BTF_ID_LIST_END
static const struct bpf_iter_seq_info task_seq_info = {
.seq_ops = &task_seq_ops,
diff --git a/kernel/livepatch/Kconfig b/kernel/livepatch/Kconfig
index 53d51ed61..8c004f211 100644
--- a/kernel/livepatch/Kconfig
+++ b/kernel/livepatch/Kconfig
@@ -12,6 +12,7 @@ config LIVEPATCH
depends on KALLSYMS_ALL
depends on HAVE_LIVEPATCH
depends on !TRIM_UNUSED_KSYMS
+ depends on !LTO_GCC # not supported in gcc 10
help
Say Y here if you want to support kernel live patching.
This option has no runtime impact until a kernel "patch"
diff --git a/kernel/locking/spinlock.c b/kernel/locking/spinlock.c
index 0ff08380f..f2b65270e 100644
--- a/kernel/locking/spinlock.c
+++ b/kernel/locking/spinlock.c
@@ -130,7 +130,7 @@ BUILD_LOCK_OPS(write, rwlock);
#endif
#ifndef CONFIG_INLINE_SPIN_TRYLOCK
-int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock)
+noinline int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock)
{
return __raw_spin_trylock(lock);
}
@@ -138,7 +138,7 @@ EXPORT_SYMBOL(_raw_spin_trylock);
#endif
#ifndef CONFIG_INLINE_SPIN_TRYLOCK_BH
-int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock)
+noinline int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock)
{
return __raw_spin_trylock_bh(lock);
}
@@ -146,7 +146,7 @@ EXPORT_SYMBOL(_raw_spin_trylock_bh);
#endif
#ifndef CONFIG_INLINE_SPIN_LOCK
-void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
+noinline void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
{
__raw_spin_lock(lock);
}
@@ -154,7 +154,7 @@ EXPORT_SYMBOL(_raw_spin_lock);
#endif
#ifndef CONFIG_INLINE_SPIN_LOCK_IRQSAVE
-unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock)
+noinline unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
return __raw_spin_lock_irqsave(lock);
}
@@ -162,7 +162,7 @@ EXPORT_SYMBOL(_raw_spin_lock_irqsave);
#endif
#ifndef CONFIG_INLINE_SPIN_LOCK_IRQ
-void __lockfunc _raw_spin_lock_irq(raw_spinlock_t *lock)
+noinline void __lockfunc _raw_spin_lock_irq(raw_spinlock_t *lock)
{
__raw_spin_lock_irq(lock);
}
@@ -170,7 +170,7 @@ EXPORT_SYMBOL(_raw_spin_lock_irq);
#endif
#ifndef CONFIG_INLINE_SPIN_LOCK_BH
-void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock)
+noinline void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock)
{
__raw_spin_lock_bh(lock);
}
@@ -178,7 +178,7 @@ EXPORT_SYMBOL(_raw_spin_lock_bh);
#endif
#ifdef CONFIG_UNINLINE_SPIN_UNLOCK
-void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock)
+noinline void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock)
{
__raw_spin_unlock(lock);
}
@@ -186,7 +186,7 @@ EXPORT_SYMBOL(_raw_spin_unlock);
#endif
#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE
-void __lockfunc _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags)
+noinline void __lockfunc _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags)
{
__raw_spin_unlock_irqrestore(lock, flags);
}
@@ -194,7 +194,7 @@ EXPORT_SYMBOL(_raw_spin_unlock_irqrestore);
#endif
#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQ
-void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock)
+noinline void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock)
{
__raw_spin_unlock_irq(lock);
}
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(_raw_spin_unlock_irq);
#endif
#ifndef CONFIG_INLINE_SPIN_UNLOCK_BH
-void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock)
+noinline void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock)
{
__raw_spin_unlock_bh(lock);
}
@@ -210,7 +210,7 @@ EXPORT_SYMBOL(_raw_spin_unlock_bh);
#endif
#ifndef CONFIG_INLINE_READ_TRYLOCK
-int __lockfunc _raw_read_trylock(rwlock_t *lock)
+noinline int __lockfunc _raw_read_trylock(rwlock_t *lock)
{
return __raw_read_trylock(lock);
}
@@ -218,7 +218,7 @@ EXPORT_SYMBOL(_raw_read_trylock);
#endif
#ifndef CONFIG_INLINE_READ_LOCK
-void __lockfunc _raw_read_lock(rwlock_t *lock)
+noinline void __lockfunc _raw_read_lock(rwlock_t *lock)
{
__raw_read_lock(lock);
}
@@ -226,7 +226,7 @@ EXPORT_SYMBOL(_raw_read_lock);
#endif
#ifndef CONFIG_INLINE_READ_LOCK_IRQSAVE
-unsigned long __lockfunc _raw_read_lock_irqsave(rwlock_t *lock)
+noinline unsigned long __lockfunc _raw_read_lock_irqsave(rwlock_t *lock)
{
return __raw_read_lock_irqsave(lock);
}
@@ -234,7 +234,7 @@ EXPORT_SYMBOL(_raw_read_lock_irqsave);
#endif
#ifndef CONFIG_INLINE_READ_LOCK_IRQ
-void __lockfunc _raw_read_lock_irq(rwlock_t *lock)
+noinline void __lockfunc _raw_read_lock_irq(rwlock_t *lock)
{
__raw_read_lock_irq(lock);
}
@@ -242,7 +242,7 @@ EXPORT_SYMBOL(_raw_read_lock_irq);
#endif
#ifndef CONFIG_INLINE_READ_LOCK_BH
-void __lockfunc _raw_read_lock_bh(rwlock_t *lock)
+noinline void __lockfunc _raw_read_lock_bh(rwlock_t *lock)
{
__raw_read_lock_bh(lock);
}
@@ -250,7 +250,7 @@ EXPORT_SYMBOL(_raw_read_lock_bh);
#endif
#ifndef CONFIG_INLINE_READ_UNLOCK
-void __lockfunc _raw_read_unlock(rwlock_t *lock)
+noinline void __lockfunc _raw_read_unlock(rwlock_t *lock)
{
__raw_read_unlock(lock);
}
@@ -258,7 +258,7 @@ EXPORT_SYMBOL(_raw_read_unlock);
#endif
#ifndef CONFIG_INLINE_READ_UNLOCK_IRQRESTORE
-void __lockfunc _raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+noinline void __lockfunc _raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
{
__raw_read_unlock_irqrestore(lock, flags);
}
@@ -266,7 +266,7 @@ EXPORT_SYMBOL(_raw_read_unlock_irqrestore);
#endif
#ifndef CONFIG_INLINE_READ_UNLOCK_IRQ
-void __lockfunc _raw_read_unlock_irq(rwlock_t *lock)
+noinline void __lockfunc _raw_read_unlock_irq(rwlock_t *lock)
{
__raw_read_unlock_irq(lock);
}
@@ -274,7 +274,7 @@ EXPORT_SYMBOL(_raw_read_unlock_irq);
#endif
#ifndef CONFIG_INLINE_READ_UNLOCK_BH
-void __lockfunc _raw_read_unlock_bh(rwlock_t *lock)
+noinline void __lockfunc _raw_read_unlock_bh(rwlock_t *lock)
{
__raw_read_unlock_bh(lock);
}
@@ -282,7 +282,7 @@ EXPORT_SYMBOL(_raw_read_unlock_bh);
#endif
#ifndef CONFIG_INLINE_WRITE_TRYLOCK
-int __lockfunc _raw_write_trylock(rwlock_t *lock)
+noinline int __lockfunc _raw_write_trylock(rwlock_t *lock)
{
return __raw_write_trylock(lock);
}
@@ -290,7 +290,7 @@ EXPORT_SYMBOL(_raw_write_trylock);
#endif
#ifndef CONFIG_INLINE_WRITE_LOCK
-void __lockfunc _raw_write_lock(rwlock_t *lock)
+noinline void __lockfunc _raw_write_lock(rwlock_t *lock)
{
__raw_write_lock(lock);
}
@@ -298,7 +298,7 @@ EXPORT_SYMBOL(_raw_write_lock);
#endif
#ifndef CONFIG_INLINE_WRITE_LOCK_IRQSAVE
-unsigned long __lockfunc _raw_write_lock_irqsave(rwlock_t *lock)
+noinline unsigned long __lockfunc _raw_write_lock_irqsave(rwlock_t *lock)
{
return __raw_write_lock_irqsave(lock);
}
@@ -306,7 +306,7 @@ EXPORT_SYMBOL(_raw_write_lock_irqsave);
#endif
#ifndef CONFIG_INLINE_WRITE_LOCK_IRQ
-void __lockfunc _raw_write_lock_irq(rwlock_t *lock)
+noinline void __lockfunc _raw_write_lock_irq(rwlock_t *lock)
{
__raw_write_lock_irq(lock);
}
@@ -314,7 +314,7 @@ EXPORT_SYMBOL(_raw_write_lock_irq);
#endif
#ifndef CONFIG_INLINE_WRITE_LOCK_BH
-void __lockfunc _raw_write_lock_bh(rwlock_t *lock)
+noinline void __lockfunc _raw_write_lock_bh(rwlock_t *lock)
{
__raw_write_lock_bh(lock);
}
@@ -322,7 +322,7 @@ EXPORT_SYMBOL(_raw_write_lock_bh);
#endif
#ifndef CONFIG_INLINE_WRITE_UNLOCK
-void __lockfunc _raw_write_unlock(rwlock_t *lock)
+noinline void __lockfunc _raw_write_unlock(rwlock_t *lock)
{
__raw_write_unlock(lock);
}
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(_raw_write_unlock);
#endif
#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE
-void __lockfunc _raw_write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+noinline void __lockfunc _raw_write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
{
__raw_write_unlock_irqrestore(lock, flags);
}
@@ -338,7 +338,7 @@ EXPORT_SYMBOL(_raw_write_unlock_irqrestore);
#endif
#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQ
-void __lockfunc _raw_write_unlock_irq(rwlock_t *lock)
+noinline void __lockfunc _raw_write_unlock_irq(rwlock_t *lock)
{
__raw_write_unlock_irq(lock);
}
@@ -346,7 +346,7 @@ EXPORT_SYMBOL(_raw_write_unlock_irq);
#endif
#ifndef CONFIG_INLINE_WRITE_UNLOCK_BH
-void __lockfunc _raw_write_unlock_bh(rwlock_t *lock)
+noinline void __lockfunc _raw_write_unlock_bh(rwlock_t *lock)
{
__raw_write_unlock_bh(lock);
}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 98191218d..272a654f5 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8086,12 +8086,20 @@ void __init sched_init(void)
unsigned long ptr = 0;
int i;
- /* Make sure the linker didn't screw up */
- BUG_ON(&idle_sched_class + 1 != &fair_sched_class ||
- &fair_sched_class + 1 != &rt_sched_class ||
- &rt_sched_class + 1 != &dl_sched_class);
+ /*
+ * Make sure the linker didn't screw up.
+ * We have to use RELOC_HIDE to prevent gcc from optimizing
+ * them to true because they're technically undefined in ISO-C.
+ */
+ BUG_ON(RELOC_HIDE(&idle_sched_class, 0) + 1 !=
+ RELOC_HIDE(&fair_sched_class, 0));
+ BUG_ON(RELOC_HIDE(&fair_sched_class, 0) + 1 !=
+ RELOC_HIDE(&rt_sched_class, 0));
+ BUG_ON(RELOC_HIDE(&rt_sched_class, 0) + 1 !=
+ RELOC_HIDE(&dl_sched_class, 0));
#ifdef CONFIG_SMP
- BUG_ON(&dl_sched_class + 1 != &stop_sched_class);
+ BUG_ON(RELOC_HIDE(&dl_sched_class, 0) + 1 !=
+ RELOC_HIDE(&stop_sched_class, 0));
#endif
wait_bit_init();
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 9908ec4a9..462c8f6b8 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -429,7 +429,7 @@ static inline void __irq_exit_rcu(void)
*
* Also processes softirqs if needed and possible.
*/
-void irq_exit_rcu(void)
+__visible void irq_exit_rcu(void)
{
__irq_exit_rcu();
/* must be last! */
diff --git a/kernel/static_call.c b/kernel/static_call.c
index 2c5950b0b..f22836e22 100644
--- a/kernel/static_call.c
+++ b/kernel/static_call.c
@@ -10,6 +10,8 @@
#include <linux/processor.h>
#include <asm/sections.h>
+#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
+
extern struct static_call_site __start_static_call_sites[],
__stop_static_call_sites[];
extern struct static_call_tramp_key __start_static_call_tramp_key[],
@@ -496,14 +498,18 @@ int __init static_call_init(void)
}
early_initcall(static_call_init);
-long __static_call_return0(void)
+#endif /* HAVE_STATIC_CALL_INLINE */
+
+__visible long __static_call_return0(void)
{
return 0;
}
#ifdef CONFIG_STATIC_CALL_SELFTEST
-static int func_a(int x)
+int __visible sc_func_a(int x); /* Avoid warning */
+
+int __visible sc_func_a(int x)
{
return x+1;
}
@@ -513,7 +519,7 @@ static int func_b(int x)
return x+2;
}
-DEFINE_STATIC_CALL(sc_selftest, func_a);
+DEFINE_STATIC_CALL(sc_selftest, sc_func_a);
static struct static_call_data {
int (*func)(int);
@@ -522,7 +528,7 @@ static struct static_call_data {
} static_call_data [] __initdata = {
{ NULL, 2, 3 },
{ func_b, 2, 4 },
- { func_a, 2, 3 }
+ { sc_func_a, 2, 3 }
};
static int __init test_static_call_init(void)
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index fcb3b21d8..24fafe778 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -31,7 +31,7 @@ asmlinkage long sys_ni_posix_timers(void)
}
#ifndef SYS_NI
-#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
+#define SYS_NI(name) SYSCALL_ALIAS_PROTO(sys_##name, sys_ni_posix_timers)
#endif
#ifndef COMPAT_SYS_NI
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 417c3d3e5..bfc9959f4 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -244,6 +244,7 @@ config DEBUG_INFO_COMPRESSED
config DEBUG_INFO_SPLIT
bool "Produce split debuginfo in .dwo files"
depends on $(cc-option,-gsplit-dwarf)
+ depends on !LTO_GCC
help
Generate debug info into separate .dwo files. This significantly
reduces the build directory size for builds with DEBUG_INFO,
diff --git a/net/core/filter.c b/net/core/filter.c
index 9323d34d3..46f78b3c6 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -10479,6 +10479,7 @@ BTF_ID_LIST_GLOBAL(btf_sock_ids)
#define BTF_SOCK_TYPE(name, type) BTF_ID(struct, type)
BTF_SOCK_TYPE_xxx
#undef BTF_SOCK_TYPE
+BTF_ID_LIST_END
#else
u32 btf_sock_ids[MAX_BTF_SOCK_TYPE];
#endif
@@ -10601,6 +10602,7 @@ BPF_CALL_1(bpf_sock_from_file, struct file *, file)
BTF_ID_LIST(bpf_sock_from_file_btf_ids)
BTF_ID(struct, socket)
BTF_ID(struct, file)
+BTF_ID_LIST_END
const struct bpf_func_proto bpf_sock_from_file_proto = {
.func = bpf_sock_from_file,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 373d48073..6db42e5b1 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -6471,6 +6471,7 @@ DEFINE_BPF_ITER_FUNC(ipv6_route, struct bpf_iter_meta *meta, struct fib6_info *r
BTF_ID_LIST(btf_fib6_info_id)
BTF_ID(struct, fib6_info)
+BTF_ID_LIST_END
static const struct bpf_iter_seq_info ipv6_route_seq_info = {
.seq_ops = &ipv6_route_seq_ops,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 3a62f97ac..3abcf2d12 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2838,6 +2838,7 @@ static const struct rhashtable_params netlink_rhashtable_params = {
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
BTF_ID_LIST(btf_netlink_sock_id)
BTF_ID(struct, netlink_sock)
+BTF_ID_LIST_END
static const struct bpf_iter_seq_info netlink_seq_info = {
.seq_ops = &netlink_seq_ops,
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 1b6094a13..59de68083 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -165,11 +165,11 @@ ifdef CONFIG_MODVERSIONS
# the actual value of the checksum generated by genksyms
# o remove .tmp_<file>.o to <file>.o
-ifdef CONFIG_LTO_CLANG
+ifdef CONFIG_LTO
# 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 \
+ if $(NM) $@ 2>/dev/null | grep -q __kstrtab; then \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $@.symversions; \
fi;
@@ -179,7 +179,7 @@ cmd_modversions_c = \
$(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
- $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
+ $(LDFINAL) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
-T $(@D)/.tmp_$(@F:.o=.ver); \
mv -f $(@D)/.tmp_$(@F) $@; \
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
@@ -217,7 +217,7 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),
endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
ifdef CONFIG_STACK_VALIDATION
-ifndef CONFIG_LTO_CLANG
+ifndef CONFIG_LTO
ifneq ($(SKIP_STACK_VALIDATION),1)
__objtool_obj := $(objtree)/tools/objtool/objtool
@@ -233,7 +233,7 @@ objtool_obj = $(if $(patsubst y%,, \
$(__objtool_obj))
endif # SKIP_STACK_VALIDATION
-endif # CONFIG_LTO_CLANG
+endif # CONFIG_LTO
endif # CONFIG_STACK_VALIDATION
# Rebuild all objects when objtool changes, or is enabled/disabled.
@@ -280,7 +280,8 @@ $(obj)/%.mod: $(obj)/%.o FORCE
$(call if_changed,mod)
quiet_cmd_cc_lst_c = MKLST $@
- cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
+ cmd_cc_lst_c = $(if $(CONFIG_LTO),$(warning Listing in LTO mode does not match final binary)) \
+ $(CC) $(c_flags) -g -c -o $*.o $< && \
$(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \
System.map $(OBJDUMP) > $@
@@ -341,7 +342,7 @@ cmd_modversions_S = \
$(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
> $(@D)/.tmp_$(@F:.o=.ver); \
\
- $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \
+ $(LDFINAL) $(KBUILD_LDFLAGS) -r $(KBUILD_MOD_LDFLAGS) -o $(@D)/.tmp_$(@F) $@ \
-T $(@D)/.tmp_$(@F:.o=.ver); \
mv -f $(@D)/.tmp_$(@F) $@; \
rm -f $(@D)/.tmp_$(@F:.o=.ver); \
@@ -382,7 +383,7 @@ $(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)
+ifeq ($(CONFIG_LTO) $(CONFIG_MODVERSIONS),y y)
cmd_update_lto_symversions = \
rm -f $@.symversions \
$(foreach n, $(filter-out FORCE,$^), \
@@ -433,15 +434,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
+ifdef CONFIG_LTO
quiet_cmd_link_multi-m = AR [M] $@
cmd_link_multi-m = \
$(cmd_update_lto_symversions); \
rm -f $@; \
$(AR) cDPrsT $@ $(filter %.o,$^)
else
-quiet_cmd_link_multi-m = LD [M] $@
- cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^)
+quiet_cmd_link_multi-m = LDFINAL [M] $@
+ cmd_link_multi-m = $(LDFINAL) $(ld_flags) -r -o $@ $(filter %.o,$^)
endif
$(multi-used-m): FORCE
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 8cd67b1b6..d5d5e5643 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -188,7 +188,7 @@ quiet_modtag = $(if $(part-of-module),[M], )
modkern_cflags = \
$(if $(part-of-module), \
- $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
+ $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
$(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL) $(modfile_flags))
modkern_aflags = $(if $(part-of-module), \
diff --git a/scripts/Makefile.lto b/scripts/Makefile.lto
new file mode 100644
index 000000000..df97be2d9
--- /dev/null
+++ b/scripts/Makefile.lto
@@ -0,0 +1,40 @@
+#
+# Support for gcc link time optimization
+#
+
+DISABLE_LTO_GCC :=
+export DISABLE_LTO_GCC
+
+ifdef CONFIG_LTO_GCC
+ CC_FLAGS_LTO_GCC := -flto
+ DISABLE_LTO_GCC := -fno-lto
+
+ KBUILD_CFLAGS += ${CC_FLAGS_LTO_GCC}
+
+ lto-flags-y := -flto -flinker-output=nolto-rel -flto=jobserver
+ lto-flags-y += -fwhole-program
+
+ lto-flags-$(CONFIG_LTO_CP_CLONE) += -fipa-cp-clone
+
+ # allow extra flags from command line
+ lto-flags-y += ${LTO_EXTRA_CFLAGS}
+
+ # For LTO we need to use gcc to do the linking, not ld
+ # directly. Use a wrapper to convert the ld command line
+ # to gcc
+ LDFINAL := ${CONFIG_SHELL} ${srctree}/scripts/gcc-ld \
+ ${lto-flags-y}
+
+ # LTO gcc creates a lot of files in TMPDIR, and with /tmp as tmpfs
+ # it's easy to drive the machine OOM. Use the object directory
+ # instead for temporaries.
+ # This has the drawback that there might be some junk more visible
+ # after interrupted compilations, but you would have that junk
+ # there anyways in /tmp.
+ TMPDIR ?= $(objtree)
+ export TMPDIR
+
+ # use plugin aware tools
+ AR = $(CROSS_COMPILE)gcc-ar
+ NM = $(CROSS_COMPILE)gcc-nm
+endif # CONFIG_LTO_GCC
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 735e11e90..4033e8803 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -30,8 +30,8 @@ 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
+ifdef CONFIG_LTO
+# With CONFIG_LTO, reuse the object file we compiled for modpost to
# avoid a second slow LTO link
prelink-ext := .lto
@@ -47,11 +47,11 @@ cmd_ld_ko_o += \
endif # SKIP_STACK_VALIDATION
endif # CONFIG_STACK_VALIDATION
-endif # CONFIG_LTO_CLANG
+endif # CONFIG_LTO
-quiet_cmd_ld_ko_o = LD [M] $@
+quiet_cmd_ld_ko_o = LDFINAL [M] $@
cmd_ld_ko_o += \
- $(LD) -r $(KBUILD_LDFLAGS) \
+ $(LDFINAL) -r $(KBUILD_LDFLAGS) \
$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
-T scripts/module.lds -o $@ $(filter %.o, $^); \
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 066beffca..54ec57859 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -105,14 +105,14 @@ $(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
+ifdef CONFIG_LTO
+# With CONFIG_LTO, .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 $@ \
+ $(LDFINAL) $(ld_flags) -r -o $@ \
$(shell [ -s $(@:.lto.o=.o.symversions) ] && \
echo -T $(@:.lto.o=.o.symversions)) \
--whole-archive $^
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index dcd8d8750..ec5ece4ee 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -37,7 +37,7 @@ def getsizes(file, format):
if name.startswith("__addressable_"): continue
if name == "linux_banner": continue
# statics and some other optimizations adds random .NUMBER
- name = re_NUMBER.sub('', name)
+ name = re_NUMBER.sub('', name).replace(".lto_priv", "")
sym[name] = sym.get(name, 0) + int(size, 16)
return sym
diff --git a/scripts/gcc-ld b/scripts/gcc-ld
index 997b818c3..13e85ece8 100755
--- a/scripts/gcc-ld
+++ b/scripts/gcc-ld
@@ -6,18 +6,26 @@
ARGS="-nostdlib"
+for j in "$@" ; do
+ if [ "$j" = -v ] ; then
+ exec `$CC -print-prog-name=ld` -v
+ fi
+done
+
while [ "$1" != "" ] ; do
case "$1" in
- -save-temps|-m32|-m64) N="$1" ;;
+ -save-temps*|-m32|-m64) N="$1" ;;
-r) N="$1" ;;
+ -flinker-output*) N="$1" ;;
-[Wg]*) N="$1" ;;
-[olv]|-[Ofd]*|-nostdlib) N="$1" ;;
- --end-group|--start-group)
+ --end-group|--start-group|--whole-archive|--no-whole-archive|\
+--no-undefined|--hash-style*|--build-id*|--eh-frame-hdr|-Bsymbolic)
N="-Wl,$1" ;;
-[RTFGhIezcbyYu]*|\
--script|--defsym|-init|-Map|--oformat|-rpath|\
--rpath-link|--sort-section|--section-start|-Tbss|-Tdata|-Ttext|\
---version-script|--dynamic-list|--version-exports-symbol|--wrap|-m)
+-rpath-link|--sort-section|--section-start|-Tbss|-Tdata|-Ttext|-soname|\
+--version-script|--dynamic-list|--version-exports-symbol|--wrap|-m|-z)
A="$1" ; shift ; N="-Wl,$A,$1" ;;
-[m]*) N="$1" ;;
-*) N="-Wl,$1" ;;
@@ -27,4 +35,6 @@ while [ "$1" != "" ] ; do
shift
done
+[ -n "$V" ] && echo >&2 $CC $ARGS
+
exec $CC $ARGS
diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh
index da320151e..ece61af2c 100755
--- a/scripts/gen_autoksyms.sh
+++ b/scripts/gen_autoksyms.sh
@@ -26,10 +26,10 @@ if [ -n "$CONFIG_MODVERSIONS" ]; then
needed_symbols="$needed_symbols module_layout"
fi
-# With CONFIG_LTO_CLANG, LLVM bitcode has not yet been compiled into a binary
+# With CONFIG_LTO, LLVM bitcode has not yet been compiled into a binary
# when the .mod files are generated, which means they don't yet contain
# references to certain symbols that will be present in the final binaries.
-if [ -n "$CONFIG_LTO_CLANG" ]; then
+if [ -n "$CONFIG_LTO" ]; then
# intrinsic functions
needed_symbols="$needed_symbols memcpy memmove memset"
# ftrace
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 3b261b0f7..27aac42bd 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -31,8 +31,9 @@
set -e
LD="$1"
-KBUILD_LDFLAGS="$2"
-LDFLAGS_vmlinux="$3"
+LDFINAL="$2"
+KBUILD_LDFLAGS="$3"
+LDFLAGS_vmlinux="$4"
# Nice output in kbuild format
# Will be supressed by "make -s"
@@ -54,7 +55,7 @@ gen_initcalls()
> .tmp_initcalls.lds
}
-# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
+# If CONFIG_LTO is selected, collect generated symbol versions into
# .tmp_symversions.lds
gen_symversions()
{
@@ -82,9 +83,12 @@ modpost_link()
${KBUILD_VMLINUX_LIBS} \
--end-group"
- if [ -n "${CONFIG_LTO_CLANG}" ]; then
- gen_initcalls
- lds="-T .tmp_initcalls.lds"
+ if [ -n "${CONFIG_LTO}" ]; then
+ lds=""
+ if [ -n "${CONFIG_LTO_CLANG}" ] ; then
+ gen_initcalls
+ lds="-T .tmp_initcalls.lds"
+ fi
if [ -n "${CONFIG_MODVERSIONS}" ]; then
gen_symversions
@@ -98,7 +102,7 @@ modpost_link()
info LD ${1}
fi
- ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
+ ${LDFINAL} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
}
objtool_link()
@@ -106,7 +110,7 @@ objtool_link()
local objtoolcmd;
local objtoolopt;
- if [ "${CONFIG_LTO_CLANG} ${CONFIG_STACK_VALIDATION}" = "y y" ]; then
+ if [ "${CONFIG_LTO} ${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.
if [ -n "${CONFIG_UNWINDER_ORC}" ]; then
@@ -132,7 +136,7 @@ objtool_link()
if [ -z "${CONFIG_FRAME_POINTER}" ]; then
objtoolopt="${objtoolopt} --no-fp"
fi
- if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO_CLANG}" ]; then
+ if [ -n "${CONFIG_GCOV_KERNEL}" ] || [ -n "${CONFIG_LTO}" ]; then
objtoolopt="${objtoolopt} --no-unreachable"
fi
if [ -n "${CONFIG_RETPOLINE}" ]; then
@@ -162,12 +166,12 @@ vmlinux_link()
shift
# The kallsyms linking does not need debug symbols included.
- if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ] ; then
+ if [ "$output" != "${output#.tmp_vmlinux.kallsyms}" ]; then
strip_debug=-Wl,--strip-debug
fi
if [ "${SRCARCH}" != "um" ]; then
- if [ -n "${CONFIG_LTO_CLANG}" ]; then
+ if [ -n "${CONFIG_LTO}" ]; then
# Use vmlinux.o instead of performing the slow LTO
# link again.
objects="--whole-archive \
@@ -228,7 +232,14 @@ gen_btf()
vmlinux_link ${1}
info "BTF" ${2}
- LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${1}
+
+ BTF_ARGS=""
+ if [ -n "${CONFIG_LTO_GCC}" ]; then
+ # gcc LTO generates some dwarf symbols that pahole
+ # doesn't like. Skip those instead of aborting.
+ BTF_ARGS=--btf_encode_force
+ fi
+ LLVM_OBJCOPY=${OBJCOPY} ${PAHOLE} -J ${BTF_ARGS} ${1}
# Create ${2} which contains just .BTF section but no symbols. Add
# SHF_ALLOC because .BTF will be part of the vmlinux image. --strip-all
@@ -306,20 +317,6 @@ cleanup()
rm -f vmlinux.o
}
-on_exit()
-{
- if [ $? -ne 0 ]; then
- cleanup
- fi
-}
-trap on_exit EXIT
-
-on_signals()
-{
- exit 1
-}
-trap on_signals HUP INT QUIT TERM
-
# Use "make V=1" to debug this script
case "${KBUILD_VERBOSE}" in
*1*)
diff --git a/scripts/mksysmap b/scripts/mksysmap
index 9aa23d158..8b525c484 100755
--- a/scripts/mksysmap
+++ b/scripts/mksysmap
@@ -34,6 +34,7 @@
# U - undefined global symbols
# N - debugging symbols
# w - local weak symbols
+# W - weak symbols if they contain .c.
# readprofile starts reading symbols when _stext is found, and
# continue until it finds a symbol which is not either of 'T', 't',
@@ -41,4 +42,4 @@
# so we just ignore them to let readprofile continue to work.
# (At least sparc64 has __crc_ in the middle).
-$NM -n $1 | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)\|\( \.L\)' > $2
+$NM -n $1 | grep -v '\( [aNUw] \)\|\(__crc_\)\|\( \$[adt]\)\|\( \.L\)\|\(W .*\.c\.\)' > $2
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index c9e38ad93..aa3465d6b 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
OBJECT_FILES_NON_STANDARD := y
CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)
+CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO_GCC)
hostprogs-always-y += modpost mk_elfconfig
always-y += empty.o
@@ -9,6 +10,8 @@ modpost-objs := modpost.o file2alias.o sumversion.o
devicetable-offsets-file := devicetable-offsets.h
+$(obj)/devicetable-offsets.s: KBUILD_CFLAGS += $(DISABLE_LTO_GCC)
+
$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s FORCE
$(call filechk,offsets,__DEVICETABLE_OFFSETS_H__)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 24725e50c..3ba0e6970 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1559,6 +1559,20 @@ static void report_sec_mismatch(const char *modname,
fprintf(stderr, "\n");
}
+/* For checks remove .lto_priv.0 which is added randomly by gcc LTO */
+
+static char *cleansym(const char *sym)
+{
+ char *nsym = strdup(sym);
+ char *p;
+ if (!nsym)
+ exit(ENOMEM);
+ p = strstr(nsym, ".lto_priv.0");
+ if (p && p[11] == 0)
+ *p = 0;
+ return nsym;
+}
+
static void default_mismatch_handler(const char *modname, struct elf_info *elf,
const struct sectioncheck* const mismatch,
Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
@@ -1568,6 +1582,7 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
Elf_Sym *from;
const char *tosym;
const char *fromsym;
+ char *fromsym_clean, *tosym_clean;
from = find_elf_symbol2(elf, r->r_offset, fromsec);
fromsym = sym_name(elf, from);
@@ -1579,14 +1594,19 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
to = find_elf_symbol(elf, r->r_addend, sym);
tosym = sym_name(elf, to);
+ fromsym_clean = cleansym(fromsym);
+ tosym_clean = cleansym(tosym);
+
/* check whitelist - we may ignore it */
if (secref_whitelist(mismatch,
- fromsec, fromsym, tosec, tosym)) {
+ fromsec, fromsym_clean, tosec, tosym_clean)) {
report_sec_mismatch(modname, mismatch,
fromsec, r->r_offset, fromsym,
is_function(from), tosec, tosym,
is_function(to));
}
+ free(fromsym_clean);
+ free(tosym_clean);
}
static int is_executable_section(struct elf_info* elf, unsigned int section_index)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 549813cff..bcc92ca70 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -613,7 +613,12 @@ const char *arch_nop_insn(int len)
int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg)
{
- struct cfi_reg *cfa = &insn->cfi.cfa;
+ struct cfi_reg *cfa;
+
+ if (sp_reg == ORC_REG_UNDEFINED && !insn->cfip)
+ return 0;
+
+ cfa = &insn_get_cfi(insn)->cfa;
switch (sp_reg) {
case ORC_REG_UNDEFINED:
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 5e5388a38..cf292aafd 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -253,6 +253,20 @@ static void init_insn_state(struct insn_state *state, struct section *sec)
state->noinstr = sec->noinstr;
}
+struct cfi_state *insn_get_cfi(struct instruction *insn)
+{
+ if (!insn->cfip) {
+ struct cfi_state *cfi = calloc(sizeof(struct cfi_state), 1);
+ if (!cfi) {
+ WARN("calloc failed");
+ exit(1);
+ }
+ init_cfi_state(cfi);
+ insn->cfip = cfi;
+ }
+ return insn->cfip;
+}
+
/*
* Call the arch-specific instruction decoder for all the instructions and add
* them to the global instruction list.
@@ -289,7 +303,6 @@ static int decode_instructions(struct objtool_file *file)
memset(insn, 0, sizeof(*insn));
INIT_LIST_HEAD(&insn->alts);
INIT_LIST_HEAD(&insn->stack_ops);
- init_cfi_state(&insn->cfi);
insn->sec = sec;
insn->offset = offset;
@@ -1138,7 +1151,6 @@ static int handle_group_alt(struct objtool_file *file,
memset(nop, 0, sizeof(*nop));
INIT_LIST_HEAD(&nop->alts);
INIT_LIST_HEAD(&nop->stack_ops);
- init_cfi_state(&nop->cfi);
nop->sec = special_alt->new_sec;
nop->offset = special_alt->new_off + special_alt->new_len;
@@ -1557,7 +1569,7 @@ static int read_unwind_hints(struct objtool_file *file)
insn->hint = true;
if (hint->type == UNWIND_HINT_TYPE_FUNC) {
- set_func_state(&insn->cfi);
+ set_func_state(insn_get_cfi(insn));
continue;
}
@@ -1567,9 +1579,9 @@ static int read_unwind_hints(struct objtool_file *file)
return -1;
}
- insn->cfi.cfa.offset = bswap_if_needed(hint->sp_offset);
- insn->cfi.type = hint->type;
- insn->cfi.end = hint->end;
+ insn_get_cfi(insn)->cfa.offset = bswap_if_needed(hint->sp_offset);
+ insn_get_cfi(insn)->type = hint->type;
+ insn_get_cfi(insn)->end = hint->end;
}
return 0;
@@ -2421,9 +2433,9 @@ static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn
group_off = insn->offset - insn->alt_group->first_insn->offset;
if (!alt_cfi[group_off]) {
- alt_cfi[group_off] = &insn->cfi;
+ alt_cfi[group_off] = insn_get_cfi(insn);
} else {
- if (memcmp(alt_cfi[group_off], &insn->cfi, sizeof(struct cfi_state))) {
+ if (memcmp(alt_cfi[group_off], insn_get_cfi(insn), sizeof(struct cfi_state))) {
WARN_FUNC("stack layout conflict in alternatives",
insn->sec, insn->offset);
return -1;
@@ -2472,7 +2484,7 @@ static int handle_insn_ops(struct instruction *insn, struct insn_state *state)
static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2)
{
- struct cfi_state *cfi1 = &insn->cfi;
+ struct cfi_state *cfi1 = insn_get_cfi(insn);
int i;
if (memcmp(&cfi1->cfa, &cfi2->cfa, sizeof(cfi1->cfa))) {
@@ -2694,9 +2706,9 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
state.instr += insn->instr;
if (insn->hint)
- state.cfi = insn->cfi;
+ state.cfi = *insn_get_cfi(insn);
else
- insn->cfi = state.cfi;
+ *insn_get_cfi(insn) = state.cfi;
insn->visited |= visited;
diff --git a/tools/objtool/include/objtool/check.h b/tools/objtool/include/objtool/check.h
index f5be79810..01b4a65c6 100644
--- a/tools/objtool/include/objtool/check.h
+++ b/tools/objtool/include/objtool/check.h
@@ -59,9 +59,11 @@ struct instruction {
struct list_head alts;
struct symbol *func;
struct list_head stack_ops;
- struct cfi_state cfi;
+ struct cfi_state *cfip;
};
+extern struct cfi_state *insn_get_cfi(struct instruction *);
+
static inline bool is_static_jump(struct instruction *insn)
{
return insn->type == INSN_JUMP_CONDITIONAL ||
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index 738aa5021..46f89481e 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -13,13 +13,19 @@
#include <objtool/warn.h>
#include <objtool/endianness.h>
-static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi)
+static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi,
+ struct instruction *insn)
{
- struct instruction *insn = container_of(cfi, struct instruction, cfi);
struct cfi_reg *bp = &cfi->regs[CFI_BP];
memset(orc, 0, sizeof(*orc));
+ if (!cfi) {
+ orc->end = 0;
+ orc->sp_reg = ORC_REG_UNDEFINED;
+ return 0;
+ }
+
orc->end = cfi->end;
if (cfi->cfa.base == CFI_UNDEFINED) {
@@ -179,7 +185,7 @@ int orc_create(struct objtool_file *file)
int i;
if (!alt_group) {
- if (init_orc_entry(&orc, &insn->cfi))
+ if (init_orc_entry(&orc, insn->cfip, insn))
return -1;
if (!memcmp(&prev_orc, &orc, sizeof(orc)))
continue;
@@ -203,7 +209,8 @@ int orc_create(struct objtool_file *file)
struct cfi_state *cfi = alt_group->cfi[i];
if (!cfi)
continue;
- if (init_orc_entry(&orc, cfi))
+ /* errors are reported on the original insn */
+ if (init_orc_entry(&orc, cfi, insn))
return -1;
if (!memcmp(&prev_orc, &orc, sizeof(orc)))
continue;
@@ -231,8 +238,8 @@ int orc_create(struct objtool_file *file)
/* Create .orc_unwind, .orc_unwind_ip and .rela.orc_unwind_ip sections: */
sec = find_section_by_name(file->elf, ".orc_unwind");
if (sec) {
- WARN("file already has .orc_unwind section, skipping");
- return -1;
+ /* Don't regenerate if it already exists */
+ return 0;
}
orc_sec = elf_create_section(file->elf, ".orc_unwind", 0,
sizeof(struct orc_entry), nr);
--
2.31.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment