# CONFIG_LTC2497 is not set
# CONFIG_LTC2632 is not set
# CONFIG_LTE_GDM724X is not set
+# CONFIG_LTO_CP_CLONE is not set
+# CONFIG_LTO_DEBUG is not set
+# CONFIG_LTO_DISABLE is not set
+CONFIG_LTO_MENU=y
# CONFIG_LTPC is not set
# CONFIG_LTR501 is not set
# CONFIG_LUSTRE_FS is not set
--- a/Makefile
+++ b/Makefile
-@@ -430,7 +430,7 @@ KBUILD_AFLAGS_KERNEL :=
+@@ -431,7 +431,7 @@ KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
KBUILD_AFLAGS_MODULE := -DMODULE
KBUILD_CFLAGS_MODULE := -DMODULE
--- a/init/Kconfig
+++ b/init/Kconfig
-@@ -1903,6 +1903,13 @@ config TRIM_UNUSED_KSYMS
+@@ -1971,6 +1971,13 @@ config TRIM_UNUSED_KSYMS
If unsure, or if you need to build out-of-tree modules, say N.
--- a/Makefile
+++ b/Makefile
-@@ -1233,7 +1233,6 @@ all: modules
+@@ -1235,7 +1235,6 @@ all: modules
PHONY += modules
modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
@$(kecho) ' Building modules, stage 2.';
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
-@@ -1262,7 +1261,6 @@ _modinst_:
+@@ -1264,7 +1263,6 @@ _modinst_:
rm -f $(MODLIB)/build ; \
ln -s $(CURDIR) $(MODLIB)/build ; \
fi
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
-@@ -787,11 +792,6 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH
+@@ -788,11 +793,6 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH
KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
endif
.init.data : {
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
-@@ -39,6 +39,7 @@ config MIPS
- select HAVE_CBPF_JIT if (!64BIT && !CPU_MICROMIPS)
- select HAVE_EBPF_JIT if (64BIT && !CPU_MICROMIPS)
+@@ -41,6 +41,7 @@ config MIPS
select HAVE_CC_STACKPROTECTOR
+ select THIN_ARCHIVES if LTO
+ select ARCH_SUPPORTS_LTO
+ select LD_DEAD_CODE_DATA_ELIMINATION
select HAVE_CONTEXT_TRACKING
select HAVE_COPY_THREAD_TLS
__used \
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
-@@ -434,7 +434,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $(
+@@ -440,7 +440,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $(
# Linker scripts preprocessor (.lds.S -> .lds)
# ---------------------------------------------------------------------------
quiet_cmd_cpp_lds_S = LDS $@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
-@@ -1157,6 +1157,10 @@ config SYNC_R4K
+@@ -1159,6 +1159,10 @@ config SYNC_R4K
config MIPS_MACHINE
def_bool n
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Subject: [PATCH] mips: allow the compiler to optimize memset, memcmp, memcpy for better performance and (in some instances) smaller code
-
-lede-commit: 07e59c7bc7f375f792ec9734be42fe4fa391a8bb
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- arch/mips/boot/compressed/Makefile | 3 ++-
- arch/mips/include/asm/string.h | 38 ++++++++++++++++++++++++++++++++++++++
- arch/mips/lib/Makefile | 2 +-
- arch/mips/lib/memcmp.c | 22 ++++++++++++++++++++++
- 4 files changed, 63 insertions(+), 2 deletions(-)
- create mode 100644 arch/mips/lib/memcmp.c
-
---- a/arch/mips/boot/compressed/Makefile
-+++ b/arch/mips/boot/compressed/Makefile
-@@ -23,7 +23,8 @@ KBUILD_CFLAGS := $(filter-out -pg, $(KBU
- KBUILD_CFLAGS := $(filter-out -fstack-protector, $(KBUILD_CFLAGS))
-
- KBUILD_CFLAGS := $(KBUILD_CFLAGS) -D__KERNEL__ \
-- -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull"
-+ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" \
-+ -D__ZBOOT__
-
- KBUILD_AFLAGS := $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
- -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \
---- a/arch/mips/include/asm/string.h
-+++ b/arch/mips/include/asm/string.h
-@@ -140,4 +140,42 @@ extern void *memcpy(void *__to, __const_
- #define __HAVE_ARCH_MEMMOVE
- extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
-
-+#ifndef __ZBOOT__
-+#define memset(__s, __c, len) \
-+({ \
-+ size_t __len = (len); \
-+ void *__ret; \
-+ if (__builtin_constant_p(len) && __len >= 64) \
-+ __ret = memset((__s), (__c), __len); \
-+ else \
-+ __ret = __builtin_memset((__s), (__c), __len); \
-+ __ret; \
-+})
-+
-+#define memcpy(dst, src, len) \
-+({ \
-+ size_t __len = (len); \
-+ void *__ret; \
-+ if (__builtin_constant_p(len) && __len >= 64) \
-+ __ret = memcpy((dst), (src), __len); \
-+ else \
-+ __ret = __builtin_memcpy((dst), (src), __len); \
-+ __ret; \
-+})
-+
-+#define memmove(dst, src, len) \
-+({ \
-+ size_t __len = (len); \
-+ void *__ret; \
-+ if (__builtin_constant_p(len) && __len >= 64) \
-+ __ret = memmove((dst), (src), __len); \
-+ else \
-+ __ret = __builtin_memmove((dst), (src), __len); \
-+ __ret; \
-+})
-+
-+#define __HAVE_ARCH_MEMCMP
-+#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len))
-+#endif
-+
- #endif /* _ASM_STRING_H */
---- a/arch/mips/lib/Makefile
-+++ b/arch/mips/lib/Makefile
-@@ -5,7 +5,7 @@
-
- lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \
- mips-atomic.o strncpy_user.o \
-- strnlen_user.o uncached.o
-+ strnlen_user.o uncached.o memcmp.o
-
- obj-y += iomap.o iomap_copy.o
- obj-$(CONFIG_PCI) += iomap-pci.o
---- /dev/null
-+++ b/arch/mips/lib/memcmp.c
-@@ -0,0 +1,22 @@
-+/*
-+ * copied from linux/lib/string.c
-+ *
-+ * Copyright (C) 1991, 1992 Linus Torvalds
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+
-+#undef memcmp
-+int memcmp(const void *cs, const void *ct, size_t count)
-+{
-+ const unsigned char *su1, *su2;
-+ int res = 0;
-+
-+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
-+ if ((res = *su1 - *su2) != 0)
-+ break;
-+ return res;
-+}
-+EXPORT_SYMBOL(memcmp);
-+
--- /dev/null
+From 009ccccd66b9918f83df4a5c1eb20af6f4b61c60 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sat, 8 Apr 2017 17:35:17 -0700
+Subject: x86/xen: Mark pv stub assembler symbol visible
+
+With LTO any external assembler symbol has to be marked __visible.
+Mark the generated asm PV stubs __visible to prevent a linker error.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/include/asm/paravirt.h | 3 ++-
+ drivers/xen/time.c | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/include/asm/paravirt.h
++++ b/arch/x86/include/asm/paravirt.h
+@@ -746,7 +746,8 @@ static __always_inline bool pv_vcpu_is_p
+ */
+ #define PV_THUNK_NAME(func) "__raw_callee_save_" #func
+ #define PV_CALLEE_SAVE_REGS_THUNK(func) \
+- extern typeof(func) __raw_callee_save_##func; \
++ extern __visible typeof(func) __raw_callee_save_##func; \
++ extern __visible typeof(func) func; \
+ \
+ asm(".pushsection .text;" \
+ ".globl " PV_THUNK_NAME(func) ";" \
+--- a/drivers/xen/time.c
++++ b/drivers/xen/time.c
+@@ -76,7 +76,7 @@ void xen_get_runstate_snapshot(struct vc
+ }
+
+ /* 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;
+ }
--- /dev/null
+From 822a1c048fcd75ccb346283d96b21ee082f7c204 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sat, 8 Apr 2017 17:37:26 -0700
+Subject: afs: Fix const confusion in AFS
+
+A trace point string cannot be const because the underlying special
+section is not marked const. An LTO build complains about the
+section attribute mismatch. Fix it by not marking the trace point
+string in afs const.
+
+Cc: dhowells@redhat.com
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ fs/afs/cmservice.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/afs/cmservice.c
++++ b/fs/afs/cmservice.c
+@@ -31,7 +31,7 @@ static void SRXAFSCB_ProbeUuid(struct wo
+ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *);
+
+ #define CM_NAME(name) \
+- const char afs_SRXCB##name##_name[] __tracepoint_string = \
++ char afs_SRXCB##name##_name[] __tracepoint_string = \
+ "CB." #name
+
+ /*
--- /dev/null
+From e41f29e5c53ea2f44761c76b65f84b8dd5289fd6 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Mon, 10 Feb 2014 07:26:30 +0100
+Subject: x86/timer: Don't inline __const_udelay
+
+__const_udelay is marked inline, and LTO will happily inline it everywhere
+Dropping the inline saves ~44k text in a LTO build.
+
+13999560 1740864 1499136 17239560 1070e08 vmlinux-with-udelay-inline
+13954764 1736768 1499136 17190668 1064f0c vmlinux-wo-udelay-inline
+
+Even without LTO I believe marking it noinline documents it correctly.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/lib/delay.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/lib/delay.c
++++ b/arch/x86/lib/delay.c
+@@ -162,7 +162,7 @@ void __delay(unsigned long loops)
+ }
+ EXPORT_SYMBOL(__delay);
+
+-inline void __const_udelay(unsigned long xloops)
++void __const_udelay(unsigned long xloops)
+ {
+ unsigned long lpj = this_cpu_read(cpu_info.loops_per_jiffy) ? : loops_per_jiffy;
+ int d0;
--- /dev/null
+From 5a3ca87268864f3489fd6e08f0282e1c024ca7b9 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Fri, 10 Aug 2012 03:11:20 +0200
+Subject: locking/spinlocks: Mark spinlocks noinline when inline spinlocks are
+ disabled
+
+Otherwise LTO will inline them anyways and cause a large
+kernel text increase.
+
+Since the explicit intention here is to not inline them marking
+them noinline is good documentation even for the non LTO case.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ kernel/locking/spinlock.c | 56 +++++++++++++++++++++++------------------------
+ 1 file changed, 28 insertions(+), 28 deletions(-)
+
+--- a/kernel/locking/spinlock.c
++++ b/kernel/locking/spinlock.c
+@@ -131,7 +131,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);
+ }
+@@ -139,7 +139,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);
+ }
+@@ -147,7 +147,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);
+ }
+@@ -155,7 +155,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);
+ }
+@@ -163,7 +163,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);
+ }
+@@ -171,7 +171,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);
+ }
+@@ -179,7 +179,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);
+ }
+@@ -187,7 +187,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);
+ }
+@@ -195,7 +195,7 @@ EXPORT_SYMBOL(_raw_spin_unlock_irqrestor
+ #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);
+ }
+@@ -203,7 +203,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);
+ }
+@@ -211,7 +211,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);
+ }
+@@ -219,7 +219,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);
+ }
+@@ -227,7 +227,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);
+ }
+@@ -235,7 +235,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);
+ }
+@@ -243,7 +243,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);
+ }
+@@ -251,7 +251,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);
+ }
+@@ -259,7 +259,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);
+ }
+@@ -267,7 +267,7 @@ EXPORT_SYMBOL(_raw_read_unlock_irqrestor
+ #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);
+ }
+@@ -275,7 +275,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);
+ }
+@@ -283,7 +283,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);
+ }
+@@ -291,7 +291,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);
+ }
+@@ -299,7 +299,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);
+ }
+@@ -307,7 +307,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);
+ }
+@@ -315,7 +315,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);
+ }
+@@ -323,7 +323,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);
+ }
+@@ -331,7 +331,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);
+ }
+@@ -339,7 +339,7 @@ EXPORT_SYMBOL(_raw_write_unlock_irqresto
+ #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);
+ }
+@@ -347,7 +347,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);
+ }
--- /dev/null
+From 261cba7275fb23df12a3a801387e29d496e96ba6 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sun, 23 Apr 2017 21:46:06 -0700
+Subject: x86/kvm: Make steal_time visible
+
+This per cpu variable is accessed from assembler code, so needs
+to be visible.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/kernel/kvm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/kvm.c
++++ b/arch/x86/kernel/kvm.c
+@@ -76,7 +76,7 @@ static int parse_no_kvmclock_vsyscall(ch
+ early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);
+
+ static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
+-static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
++DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64) __visible;
+ static int has_steal_clock = 0;
+
+ /*
--- /dev/null
+From ae09f35b2d5e6a63be25cd7db32317f9e57c67da Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sat, 8 Apr 2017 17:33:48 -0700
+Subject: x86/syscalls: Make x86 syscalls use real prototypes
+
+LTO complains very loudly that the x86 syscalls use their own different
+prototypes. Switch it to use the real prototypes instead. This requires
+adding a few extra prototypes to asm/syscalls.h.
+
+This is a generic cleanup, useful even without LTO.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/entry/syscall_32.c | 13 +++++--------
+ arch/x86/entry/syscall_64.c | 11 +++++------
+ arch/x86/include/asm/syscalls.h | 42 ++++++++++++++++++++++++++++++++++++-----
+ 3 files changed, 47 insertions(+), 19 deletions(-)
+
+--- a/arch/x86/entry/syscall_32.c
++++ b/arch/x86/entry/syscall_32.c
+@@ -6,20 +6,17 @@
+ #include <linux/cache.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/syscall.h>
++#include <linux/syscalls.h>
++#include <asm/syscalls.h>
++#include <asm/sys_ia32.h>
+
+-#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
+-#include <asm/syscalls_32.h>
+-#undef __SYSCALL_I386
+-
+-#define __SYSCALL_I386(nr, sym, qual) [nr] = sym,
+-
+-extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
++#define __SYSCALL_I386(nr, sym, qual) [nr] = (sys_call_ptr_t)sym,
+
+ __visible const sys_call_ptr_t ia32_sys_call_table[__NR_syscall_compat_max+1] = {
+ /*
+ * Smells like a compiler bug -- it doesn't work
+ * when the & below is removed.
+ */
+- [0 ... __NR_syscall_compat_max] = &sys_ni_syscall,
++ [0 ... __NR_syscall_compat_max] = (sys_call_ptr_t)&sys_ni_syscall,
+ #include <asm/syscalls_32.h>
+ };
+--- a/arch/x86/entry/syscall_64.c
++++ b/arch/x86/entry/syscall_64.c
+@@ -4,14 +4,13 @@
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+ #include <linux/cache.h>
++#include <linux/syscalls.h>
++#include <linux/compat.h>
+ #include <asm/asm-offsets.h>
+ #include <asm/syscall.h>
++#include <asm/syscalls.h>
+
+-#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
+-#include <asm/syscalls_64.h>
+-#undef __SYSCALL_64
+-
+-#define __SYSCALL_64(nr, sym, qual) [nr] = sym,
++#define __SYSCALL_64(nr, sym, qual) [nr] = (sys_call_ptr_t)sym,
+
+ extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
+
+@@ -20,6 +19,6 @@ asmlinkage const sys_call_ptr_t sys_call
+ * Smells like a compiler bug -- it doesn't work
+ * when the & below is removed.
+ */
+- [0 ... __NR_syscall_max] = &sys_ni_syscall,
++ [0 ... __NR_syscall_max] = (sys_call_ptr_t)&sys_ni_syscall,
+ #include <asm/syscalls_64.h>
+ };
+--- a/arch/x86/include/asm/syscalls.h
++++ b/arch/x86/include/asm/syscalls.h
+@@ -14,6 +14,7 @@
+ #include <linux/linkage.h>
+ #include <linux/signal.h>
+ #include <linux/types.h>
++#include <linux/compat.h>
+
+ /* Common in X86_32 and X86_64 */
+ /* kernel/ioport.c */
+@@ -30,6 +31,8 @@ asmlinkage long sys_rt_sigreturn(void);
+ asmlinkage long sys_set_thread_area(struct user_desc __user *);
+ asmlinkage long sys_get_thread_area(struct user_desc __user *);
+
++asmlinkage long sys_arch_prctl(int, unsigned long);
++
+ /* X86_32 only */
+ #ifdef CONFIG_X86_32
+
+@@ -43,13 +46,42 @@ asmlinkage long sys_vm86(unsigned long,
+
+ #else /* CONFIG_X86_32 */
+
+-/* X86_64 only */
+-/* kernel/process_64.c */
+-asmlinkage long sys_arch_prctl(int, unsigned long);
+-
+ /* kernel/sys_x86_64.c */
+ asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long,
+ unsigned long, unsigned long, unsigned long);
+
+-#endif /* CONFIG_X86_32 */
++asmlinkage long ptregs_sys_rt_sigreturn(struct pt_regs *regs);
++asmlinkage long ptregs_sys_fork(struct pt_regs *regs);
++asmlinkage long ptregs_sys_vfork(struct pt_regs *regs);
++asmlinkage long ptregs_sys_execve(const char __user *filename,
++ const char __user *const __user *argv,
++ const char __user *const __user *envp);
++asmlinkage long ptregs_sys_iopl(unsigned int);
++asmlinkage long ptregs_sys_execveat(int dfd, const char __user *filename,
++ const char __user *const __user *argv,
++ const char __user *const __user *envp, int flags);
++asmlinkage long ptregs_sys_clone(unsigned long, unsigned long, int __user *,
++ int __user *, unsigned long);
++
++#ifdef CONFIG_COMPAT
++asmlinkage long compat_sys_preadv64v2(unsigned long fd,
++ const struct compat_iovec __user *vec,
++ unsigned long vlen, loff_t pos, int flags);
++asmlinkage long ptregs_compat_sys_execve(unsigned long dfd,
++ const char __user *filename,
++ const compat_uptr_t __user *argv,
++ const compat_uptr_t __user *envp);
++asmlinkage long ptregs_compat_sys_execveat(int dfd, const char __user *filename,
++ const compat_uptr_t __user *argv,
++ const compat_uptr_t __user *envp, int flags);
++asmlinkage long compat_sys_old_getrlimit(unsigned int resource,
++ struct compat_rlimit __user *rlim);
++asmlinkage long stub32_clone(unsigned, unsigned, int __user *,
++ compat_uptr_t __user *, unsigned);
++#endif
++
++asmlinkage long sys32_x32_rt_sigreturn(void);
++
++
++#endif /* !CONFIG_X86_32 */
+ #endif /* _ASM_X86_SYSCALLS_H */
--- /dev/null
+From c973559eaafc89424d4ded966ffed21e2f0d1fc4 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sun, 9 Apr 2017 22:06:47 -0700
+Subject: x86: Make exception handler functions visible
+
+Make the C exception handler functions that are directly called through
+exception tables visible. LTO needs to know they are accessed from assembler.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/mm/extable.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -21,7 +21,7 @@ ex_fixup_handler(const struct exception_
+ return (ex_handler_t)((unsigned long)&x->handler + x->handler);
+ }
+
+-bool ex_handler_default(const struct exception_table_entry *fixup,
++__visible bool ex_handler_default(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+ regs->ip = ex_fixup_addr(fixup);
+@@ -29,7 +29,7 @@ bool ex_handler_default(const struct exc
+ }
+ EXPORT_SYMBOL(ex_handler_default);
+
+-bool ex_handler_fault(const struct exception_table_entry *fixup,
++__visible bool ex_handler_fault(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+ regs->ip = ex_fixup_addr(fixup);
+@@ -42,7 +42,7 @@ EXPORT_SYMBOL_GPL(ex_handler_fault);
+ * Handler for UD0 exception following a failed test against the
+ * result of a refcount inc/dec/add/sub.
+ */
+-bool ex_handler_refcount(const struct exception_table_entry *fixup,
++__visible bool ex_handler_refcount(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+ /* First unconditionally saturate the refcount. */
+@@ -95,6 +95,7 @@ EXPORT_SYMBOL(ex_handler_refcount);
+ * of vulnerability by restoring from the initial state (essentially, zeroing
+ * out all the FPU registers) if we can't restore from the task's FPU state.
+ */
++__visible
+ bool ex_handler_fprestore(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+@@ -108,7 +109,7 @@ bool ex_handler_fprestore(const struct e
+ }
+ EXPORT_SYMBOL_GPL(ex_handler_fprestore);
+
+-bool ex_handler_ext(const struct exception_table_entry *fixup,
++__visible bool ex_handler_ext(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+ /* Special hack for uaccess_err */
+@@ -118,7 +119,7 @@ bool ex_handler_ext(const struct excepti
+ }
+ EXPORT_SYMBOL(ex_handler_ext);
+
+-bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
++__visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+ if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pF)\n",
+@@ -133,7 +134,7 @@ bool ex_handler_rdmsr_unsafe(const struc
+ }
+ EXPORT_SYMBOL(ex_handler_rdmsr_unsafe);
+
+-bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
++__visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+ if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pF)\n",
+@@ -147,7 +148,7 @@ bool ex_handler_wrmsr_unsafe(const struc
+ }
+ EXPORT_SYMBOL(ex_handler_wrmsr_unsafe);
+
+-bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
++__visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+ {
+ if (static_cpu_has(X86_BUG_NULL_SEG))
+@@ -157,7 +158,7 @@ bool ex_handler_clear_fs(const struct ex
+ }
+ EXPORT_SYMBOL(ex_handler_clear_fs);
+
+-bool ex_has_fault_handler(unsigned long ip)
++__visible bool ex_has_fault_handler(unsigned long ip)
+ {
+ const struct exception_table_entry *e;
+ ex_handler_t handler;
--- /dev/null
+From cfad6e9087263269113644ae52c83571047b6026 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sun, 9 Apr 2017 22:10:40 -0700
+Subject: lto: Use C version for SYSCALL_ALIAS
+
+LTO doesn't like the assembler aliasing used for SYSCALL_ALIAS.
+Replace it with C aliasing. Also mark the only user visible.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ include/linux/linkage.h | 6 ++----
+ kernel/time/posix-stubs.c | 2 +-
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+--- a/include/linux/linkage.h
++++ b/include/linux/linkage.h
+@@ -30,10 +30,8 @@
+ #endif
+
+ #ifndef SYSCALL_ALIAS
+-#define SYSCALL_ALIAS(alias, name) asm( \
+- ".globl " VMLINUX_SYMBOL_STR(alias) "\n\t" \
+- ".set " VMLINUX_SYMBOL_STR(alias) "," \
+- VMLINUX_SYMBOL_STR(name))
++#define SYSCALL_ALIAS(a, name) \
++ __visible typeof(a) a __attribute__((alias(__stringify(name))))
+ #endif
+
+ #define __page_aligned_data __section(.data..page_aligned) __aligned(PAGE_SIZE)
+--- a/kernel/time/posix-stubs.c
++++ b/kernel/time/posix-stubs.c
+@@ -19,7 +19,7 @@
+ #include <linux/posix-timers.h>
+ #include <linux/compat.h>
+
+-asmlinkage long sys_ni_posix_timers(void)
++__visible asmlinkage long sys_ni_posix_timers(void)
+ {
+ pr_err_once("process %d (%s) attempted a POSIX timer syscall "
+ "while CONFIG_POSIX_TIMERS is not set\n",
--- /dev/null
+From c7916b76334d9e03aadfc7be71e072d9146ac6bf Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Thu, 23 Nov 2017 16:06:26 -0800
+Subject: Fix read buffer overflow in delta-ipc
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The single caller passes a string to delta_ipc_open, which copies with a
+fixed size larger than the string. So it copies some random data after
+the original string the ro segment.
+
+If the string was at the end of a page it may fault.
+
+Just copy the string with a normal strcpy after clearing the field.
+
+Found by a LTO build (which errors out)
+because the compiler inlines the functions and can resolve
+the string sizes and triggers the compile time checks in memcpy.
+
+In function ‘memcpy’,
+ inlined from ‘delta_ipc_open.constprop’ at linux/drivers/media/platform/sti/delta/delta-ipc.c:178:0,
+ inlined from ‘delta_mjpeg_ipc_open’ at linux/drivers/media/platform/sti/delta/delta-mjpeg-dec.c:227:0,
+ inlined from ‘delta_mjpeg_decode’ at linux/drivers/media/platform/sti/delta/delta-mjpeg-dec.c:403:0:
+/home/andi/lsrc/linux/include/linux/string.h:337:0: error: call to ‘__read_overflow2’ declared with attribute error: detected read beyond size of object passed as 2nd parameter
+ __read_overflow2();
+
+Cc: hugues.fruchet@st.com
+Cc: mchehab@s-opensource.com
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ certs/blacklist_nohashes.c | 2 +-
+ drivers/media/platform/sti/delta/delta-ipc.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/certs/blacklist_nohashes.c
++++ b/certs/blacklist_nohashes.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include "blacklist.h"
+
+-const char __initdata *const blacklist_hashes[] = {
++const char __initconst *const blacklist_hashes[] = {
+ NULL
+ };
+--- 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 *pct
+ 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);
--- /dev/null
+From 495d00fc424ed8bea9a404d4ed63f9efdae8028a Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sat, 11 Apr 2015 22:36:12 -0700
+Subject: trace: Use -mcount-record for dynamic ftrace
+
+gcc 5 supports a new -mcount-record option to generate ftrace
+tables directly. This avoids the need to run record_mcount
+manually.
+
+Use this option when available.
+
+So far doesn't use -mcount-nop, which also exists now.
+
+This is needed to make ftrace work with LTO because the
+normal record-mcount script doesn't run over the link
+time output.
+
+It should also improve build times slightly in the general
+case.
+
+Cc: rostedt@goodmis.org
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ scripts/Makefile.build | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -224,6 +224,11 @@ cmd_modversions_c = \
+ endif
+
+ ifdef CONFIG_FTRACE_MCOUNT_RECORD
++# gcc 5 supports generating the mcount tables directly
++ifneq ($(call cc-option,-mrecord-mcount,y),y)
++KBUILD_CFLAGS += -mrecord-mcount
++else
++# else do it all manually
+ ifdef BUILD_C_RECORDMCOUNT
+ ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
+ RECORDMCOUNT_FLAGS = -w
+@@ -253,6 +258,7 @@ cmd_record_mcount = \
+ $(sub_cmd_record_mcount) \
+ fi;
+ endif # CONFIG_FTRACE_MCOUNT_RECORD
++endif
+
+ ifdef CONFIG_STACK_VALIDATION
+ ifneq ($(SKIP_STACK_VALIDATION),1)
--- /dev/null
+From c026e5a9dc3691450e48321d12414d9310d07f11 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Fri, 24 Nov 2017 15:24:35 -0800
+Subject: ftrace: Mark function tracer test functions noinline/noclone
+
+The ftrace function tracer self tests calls some functions to verify
+the get traced. This relies on them not being inlined. Previously
+this was ensured by putting them into another file, but with LTO
+the compiler can inline across files, which makes the tests fail.
+
+Mark these functions as noinline and noclone.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ kernel/trace/trace_selftest_dynamic.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/kernel/trace/trace_selftest_dynamic.c
++++ b/kernel/trace/trace_selftest_dynamic.c
+@@ -1,13 +1,14 @@
+ // SPDX-License-Identifier: GPL-2.0
++#include <linux/compiler.h>
+ #include "trace.h"
+
+-int DYN_FTRACE_TEST_NAME(void)
++noinline __noclone int DYN_FTRACE_TEST_NAME(void)
+ {
+ /* used to call mcount */
+ return 0;
+ }
+
+-int DYN_FTRACE_TEST_NAME2(void)
++noinline __noclone int DYN_FTRACE_TEST_NAME2(void)
+ {
+ /* used to call mcount */
+ return 0;
--- /dev/null
+From 40a16a348428c1cb831d1b59694e19b7c42500fe Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Mon, 27 Nov 2017 10:24:10 -0800
+Subject: ftrace: Disable LTO for ftrace self tests
+
+Even when the test functions are not inlined something makes the ftrace
+self tests fail with LTO. ftrace manually tests seems to work fine.
+Disable LTO for the self test file, which makes the self tests work
+again.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ kernel/trace/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/trace/Makefile
++++ b/kernel/trace/Makefile
+@@ -8,7 +8,7 @@ KBUILD_CFLAGS = $(subst $(CC_FLAGS_FTRAC
+
+ ifdef CONFIG_FTRACE_SELFTEST
+ # selftest needs instrumentation
+-CFLAGS_trace_selftest_dynamic.o = $(CC_FLAGS_FTRACE)
++CFLAGS_trace_selftest_dynamic.o = $(CC_FLAGS_FTRACE) ${DISABLE_LTO}
+ obj-y += trace_selftest_dynamic.o
+ endif
+ endif
--- /dev/null
+From 63f2d318e202f71bfd1d3603bd11a156ffce67da Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Tue, 11 Apr 2017 01:55:19 -0700
+Subject: lto, fs: Avoid static variable in linux/fs.h
+
+linux/fs.h has a initialized static variable kernel_read_file_str. It doesn't
+make much sense to have a static variable in a frequently included
+header file. With LTO -fno-toplevel-reorder gcc is unable to eliminate
+it, which leads to a lot of unnecessary duplicated copies.
+
+Move the static into the scope of the only inline that uses it,
+this tells the compiler enough to not duplicate it. Right now
+the inline is only called from one place, so that is ok. If it was
+called from more places would need to move it somewhere else
+to avoid unnecessary copies.
+
+With LTO this avoids ~100k unnecessary data segment for a x86 defconfig
+build. Even without LTO it doesn't make any sense.
+
+Cc: viro@zeniv.linux.org.uk
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ include/linux/fs.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2803,12 +2803,12 @@ enum kernel_read_file_id {
+ __kernel_read_file_id(__fid_enumify)
+ };
+
+-static const char * const kernel_read_file_str[] = {
+- __kernel_read_file_id(__fid_stringify)
+-};
+-
+ static inline const char *kernel_read_file_id_str(enum kernel_read_file_id id)
+ {
++ static const char * const kernel_read_file_str[] = {
++ __kernel_read_file_id(__fid_stringify)
++ };
++
+ if ((unsigned)id >= READING_MAX_ID)
+ return kernel_read_file_str[READING_UNKNOWN];
+
--- /dev/null
+From fe50f73a715541c8df06858c9403ed599697f276 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sun, 9 Apr 2017 22:07:45 -0700
+Subject: lto, x86, mm: Disable vmalloc BUILD_BUG_ON for LTO
+
+On 32bit builds this BUILD_BUG_ON often fires with LTO for unknown
+reasons. As far as I can tell it's a false positive. So disable
+it for LTO.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/mm/init_32.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/x86/mm/init_32.c
++++ b/arch/x86/mm/init_32.c
+@@ -829,7 +829,9 @@ void __init mem_init(void)
+ BUILD_BUG_ON(VMALLOC_END > PKMAP_BASE);
+ #endif
+ #define high_memory (-128UL << 20)
++#ifndef CONFIG_LTO
+ BUILD_BUG_ON(VMALLOC_START >= VMALLOC_END);
++#endif
+ #undef high_memory
+ #undef __FIXADDR_TOP
+
--- /dev/null
+From 088ef0f57075de5ea49d6fdafb52c8d678221ea6 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Tue, 31 Mar 2015 03:45:39 -0700
+Subject: lto: Add __noreorder and mark initcalls __noreorder
+
+gcc 5 has a new no_reorder attribute that prevents top level
+reordering only for that symbol.
+
+Kernels don't like any reordering of initcalls between files, as several
+initcalls depend on each other. LTO previously needed to use
+-fno-toplevel-reordering to prevent boot failures.
+
+Add a __noreorder wrapper for the no_reorder attribute and use
+it for initcalls.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ include/linux/compiler-gcc.h | 5 +++++
+ include/linux/compiler_types.h | 3 +++
+ include/linux/init.h | 2 +-
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/include/linux/compiler-gcc.h
++++ b/include/linux/compiler-gcc.h
+@@ -325,6 +325,11 @@
+ #define __no_sanitize_address
+ #endif
+
++#if __GNUC__ >= 5
++/* Avoid reordering a top level statement */
++#define __noreorder __attribute__((no_reorder))
++#endif
++
+ /*
+ * A trick to suppress uninitialized variable warning without generating any
+ * code
+--- a/include/linux/compiler_types.h
++++ b/include/linux/compiler_types.h
+@@ -260,6 +260,9 @@ struct ftrace_likely_data {
+ #define __assume_aligned(a, ...)
+ #endif
+
++#ifndef __noreorder
++#define __noreorder
++#endif
+
+ /* Are two types/vars the same type (ignoring qualifiers)? */
+ #ifndef __same_type
+--- a/include/linux/init.h
++++ b/include/linux/init.h
+@@ -170,7 +170,7 @@ extern bool initcall_debug;
+ */
+
+ #define __define_initcall(fn, id) \
+- static initcall_t __initcall_##fn##id __used \
++ static initcall_t __initcall_##fn##id __used __noreorder \
+ __attribute__((__section__(".initcall" #id ".init"))) = fn;
+
+ /*
--- /dev/null
+From 406f45fe8179447365f1ef478315eb7d0267f287 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Fri, 27 Jun 2014 23:11:22 +0200
+Subject: lto, workaround: Disable LTO for BPF
+
+Disable LTO for the BPF interpreter. This works around a gcc bug in the LTO
+partitioner that partitions the jumptable used the BPF interpreter
+into a different LTO unit. This in term causes assembler
+errors because the jump table contains references to the
+code labels in the original file.
+
+gcc problem tracked in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50676
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ kernel/bpf/Makefile | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/kernel/bpf/Makefile
++++ b/kernel/bpf/Makefile
+@@ -13,3 +13,8 @@ ifeq ($(CONFIG_PERF_EVENTS),y)
+ obj-$(CONFIG_BPF_SYSCALL) += stackmap.o
+ endif
+ obj-$(CONFIG_CGROUP_BPF) += cgroup.o
++
++# various version of gcc have a LTO bug where the &&labels used in the
++# BPF interpreter can cause linker errors when spread incorrectly over
++# partitions. Disable LTO for BPF for now
++CFLAGS_core.o = $(DISABLE_LTO)
--- /dev/null
+From 55a23d7196ba9c6e693696ca2bc74a4a7ba9276f Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Mon, 27 Nov 2017 10:49:45 -0800
+Subject: lto, crypto: Disable LTO for camelia glue
+
+The camelia assembler glue functions don't like LTO
+and cause missing symbols. Just disable LTO for them.
+I tried to add some visibles, but it's good enough
+and this works fine.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/crypto/Makefile | 1 +
+ crypto/Makefile | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/arch/x86/crypto/Makefile
++++ b/arch/x86/crypto/Makefile
+@@ -64,6 +64,7 @@ serpent-sse2-i586-y := serpent-sse2-i586
+
+ aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
+ des3_ede-x86_64-y := des3_ede-asm_64.o des3_ede_glue.o
++CFLAGS_camellia_glue.o += $(DISABLE_LTO)
+ camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o
+ blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
+ twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -101,6 +101,7 @@ obj-$(CONFIG_CRYPTO_AES) += aes_generic.
+ CFLAGS_aes_generic.o := $(call cc-ifversion, -ge, 0701, -Os) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83356
+ obj-$(CONFIG_CRYPTO_AES_TI) += aes_ti.o
+ obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o
++CFLAGS_cast_common.o += $(DISABLE_LTO)
+ obj-$(CONFIG_CRYPTO_CAST_COMMON) += cast_common.o
+ obj-$(CONFIG_CRYPTO_CAST5) += cast5_generic.o
+ obj-$(CONFIG_CRYPTO_CAST6) += cast6_generic.o
--- /dev/null
+From e2e107112d768cca49b3b8816ef6b0d3447739aa Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Mon, 27 Nov 2017 10:51:13 -0800
+Subject: lto, x86: Disable LTO for realmode / vDSO / head64
+
+These files all don't like being compiled with LTO. Disable
+it for them.
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/entry/vdso/Makefile | 3 +--
+ arch/x86/kernel/Makefile | 2 ++
+ arch/x86/realmode/Makefile | 1 +
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/entry/vdso/Makefile
++++ b/arch/x86/entry/vdso/Makefile
+@@ -3,7 +3,6 @@
+ # Building vDSO images for x86.
+ #
+
+-KBUILD_CFLAGS += $(DISABLE_LTO)
+ KASAN_SANITIZE := n
+ UBSAN_SANITIZE := n
+ OBJECT_FILES_NON_STANDARD := y
+@@ -74,7 +73,7 @@ $(obj)/vdso-image-%.c: $(obj)/vdso%.so.d
+ CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
+ $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
+ -fno-omit-frame-pointer -foptimize-sibling-calls \
+- -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
++ -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO $(DISABLE_LTO)
+
+ $(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
+
+--- a/arch/x86/kernel/Makefile
++++ b/arch/x86/kernel/Makefile
+@@ -22,6 +22,8 @@ CFLAGS_REMOVE_early_printk.o = -pg
+ CFLAGS_REMOVE_head64.o = -pg
+ endif
+
++CFLAGS_head64.o += $(DISABLE_LTO)
++
+ KASAN_SANITIZE_head$(BITS).o := n
+ KASAN_SANITIZE_dumpstack.o := n
+ KASAN_SANITIZE_dumpstack_$(BITS).o := n
+--- a/arch/x86/realmode/Makefile
++++ b/arch/x86/realmode/Makefile
+@@ -6,6 +6,7 @@
+ # for more details.
+ #
+ #
++KBUILD_CFLAGS += $(DISABLE_LTO)
+ KASAN_SANITIZE := n
+ OBJECT_FILES_NON_STANDARD := y
+
--- /dev/null
+From c74c8a092107ed905adb217d778fdd0d589348a7 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Mon, 3 Sep 2012 21:18:23 +0200
+Subject: Kbuild, lto: Add Link Time Optimization support
+
+With LTO gcc will do whole program optimizations for
+the whole kernel and each module. This increases compile time,
+and makes incremential builds slower, but can generate faster and
+smaller code and allows the compiler to do some global checking.
+
+gcc can complain now about type mismatches for symbols between
+different files.
+
+The main advantage is that it allows cross file inlining, which
+enables a range of new optimizations. It also allows the compiler
+to throw away unused functions, which typically shrinks the kernel
+somewhat.
+
+It also enables a range of advanced and future optimizations
+in the compiler.
+
+Unlike earlier, this version doesn't require special
+binutils, but relies on THIN_ARCHIVES instead.
+
+This adds the basic Kbuild plumbing for LTO:
+
+- In Kbuild add a new scripts/Makefile.lto that checks
+the tool chain and when the tests pass sets the LTO options
+We enable it only for gcc 5.0+ and reasonable new binutils
+
+- Add a new LDFINAL variable that controls the final link
+for vmlinux or module. In this case we call gcc-ld instead
+of ld, to run the LTO step.
+
+- Kconfigs:
+Since LTO with allyesconfig needs more than 4G of memory (~8G)
+and has the potential to makes people's system swap to death.
+Smaller configs typically work with 4G.
+I used a nested config that ensures that a simple
+allyesconfig disables LTO. It has to be explicitely
+enabled.
+
+- This version runs modpost on the LTO object files.
+This currently breaks MODVERSIONS and causes some warnings
+and requires disabling the module resolution checks.
+MODVERSIONS is excluded with LTO here. Solution would be to
+reorganize the linking step to do a LDFINAL -r link
+on all modules before running modpost
+
+- Since this kernel version links the final kernel two-three
+times for kallsyms all optimization steps are done multiple
+times.
+
+Thanks to HJ Lu, Joe Mario, Honza Hubicka, Richard Guenther,
+Don Zickus, Changlong Xie, Gleb Schukin who helped with this project
+(and probably some more who I forgot, sorry)
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ Documentation/lto-build | 76 ++++++++++++++++++++++++++++++++++++++
+ Makefile | 6 ++-
+ init/Kconfig | 68 ++++++++++++++++++++++++++++++++++
+ scripts/Makefile.lto | 95 ++++++++++++++++++++++++++++++++++++++++++++++++
+ scripts/Makefile.modpost | 7 ++--
+ scripts/gcc-ld | 4 +-
+ scripts/link-vmlinux.sh | 6 +--
+ 7 files changed, 252 insertions(+), 10 deletions(-)
+ create mode 100644 Documentation/lto-build
+ create mode 100644 scripts/Makefile.lto
+
+--- /dev/null
++++ b/Documentation/lto-build
+@@ -0,0 +1,76 @@
++Link time optimization (LTO) for the Linux kernel
++
++This is an experimental feature.
++
++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)
++
++Oops can be somewhat more difficult to read, due to the more aggressive
++inlining (it helps to use scripts/faddr2line)
++
++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.
++
++Configuration:
++- Enable CONFIG_LTO_MENU and then disable CONFIG_LTO_DISABLE.
++This is mainly to not have allyesconfig default to LTO.
++
++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 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.
++
++Q: What's up with .XXXXX numeric post fixes
++A: This is due LTO turning (near) all symbols to static
++Use gcc 4.9, it avoids them in most cases. They are also filtered out
++in kallsyms. There are still some .lto_priv left.
++
++References:
++
++Presentation on Kernel LTO
++(note, performance numbers/details outdated. In particular gcc 4.9 fixed
++most of the build time problems):
++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
+--- a/Makefile
++++ b/Makefile
+@@ -377,6 +377,7 @@ endif
+ # Make variables (CC, etc...)
+ AS = $(CROSS_COMPILE)as
+ LD = $(CROSS_COMPILE)ld
++LDFINAL = $(LD)
+ CC = $(CROSS_COMPILE)gcc
+ CPP = $(CC) -E
+ AR = $(CROSS_COMPILE)ar
+@@ -434,7 +435,7 @@ KBUILD_LDFLAGS_MODULE := -T $(srctree)/s
+ GCC_PLUGINS_CFLAGS :=
+
+ export ARCH SRCARCH SUBARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD
+-export CC CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES
++export CC CPP AR NM STRIP OBJCOPY OBJDUMP HOSTLDFLAGS HOST_LOADLIBES LDFINAL
+ export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
+ export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+
+@@ -841,6 +842,7 @@ KBUILD_ARFLAGS := $(call ar-option,D)
+ include scripts/Makefile.kasan
+ include scripts/Makefile.extrawarn
+ include scripts/Makefile.ubsan
++include scripts/Makefile.lto
+
+ # Add any arch overrides and user supplied CPPFLAGS, AFLAGS and CFLAGS as the
+ # last assignments
+@@ -1014,7 +1016,7 @@ ARCH_POSTLINK := $(wildcard $(srctree)/a
+
+ # Final link of vmlinux with optional arch pass after final link
+ cmd_link-vmlinux = \
+- $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) ; \
++ $(CONFIG_SHELL) $< $(LDFINAL) $(LDFLAGS) $(LDFLAGS_vmlinux) ; \
+ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+
+ vmlinux: scripts/link-vmlinux.sh vmlinux_prereq $(vmlinux-deps) FORCE
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1052,6 +1052,73 @@ config CC_OPTIMIZE_FOR_SIZE
+
+ endchoice
+
++config ARCH_SUPPORTS_LTO
++ bool
++
++config LTO_MENU
++ bool "Enable gcc link time optimization (LTO)"
++ depends on ARCH_SUPPORTS_LTO
++ help
++ With this option gcc will do whole program optimizations for
++ the whole kernel and module. This increases compile time, but can
++ lead to better code. It allows gcc to inline functions between
++ different files and do other optimization. It might also trigger
++ bugs due to more aggressive optimization. It allows gcc to drop unused
++ code. On smaller monolithic kernel configurations
++ it usually leads to smaller kernels, especially when modules
++ are disabled.
++
++ With this option gcc will also do some global checking over
++ different source files. It also disables a number of kernel
++ features.
++
++ This option is recommended for release builds. With LTO
++ the kernel always has to be re-optimized (but not re-parsed)
++ on each build.
++
++ This requires a gcc 5.0 or later compiler, or 6.0 or later
++ if UBSAN is used.
++
++ On larger configurations this may need more than 4GB of RAM.
++ It will likely not work on those with a 32bit compiler.
++
++ When the toolchain support is not available this will (hopefully)
++ be automatically disabled.
++
++ For more information see Documentation/lto-build
++
++config LTO_DISABLE
++ bool "Disable LTO again"
++ depends on LTO_MENU
++ default n
++ help
++ This option is merely here so that allyesconfig or allmodconfig do
++ not enable LTO. If you want to actually use LTO do not enable.
++
++config LTO
++ bool
++ default y
++ depends on LTO_MENU && !LTO_DISABLE
++
++config LTO_DEBUG
++ bool "Enable LTO compile time debugging"
++ depends on LTO
++ help
++ Enable LTO debugging in the compiler. The compiler dumps
++ some log files that make it easier to figure out LTO
++ behavior. The log files also allow to reconstruct
++ the global inlining and a global callgraph.
++ They however add some (single threaded) cost to the
++ compilation. When in doubt do not enable.
++
++config LTO_CP_CLONE
++ bool "Allow aggressive cloning for function specialization"
++ depends on LTO
++ help
++ Allow the compiler to clone and specialize functions for specific
++ arguments when it determines these arguments are very commonly
++ called. Experimential. Will increase text size.
++
+ config SYSCTL
+ bool
+
+@@ -1740,6 +1807,7 @@ config MODULE_FORCE_UNLOAD
+
+ config MODVERSIONS
+ bool "Module versioning support"
++ depends on !LTO
+ help
+ Usually, you have to use modules compiled with your kernel.
+ Saying Y here makes it sometimes possible to use modules
+--- /dev/null
++++ b/scripts/Makefile.lto
+@@ -0,0 +1,95 @@
++#
++# Support for gcc link time optimization
++#
++
++DISABLE_LTO :=
++LTO_CFLAGS :=
++
++export DISABLE_LTO
++export LTO_CFLAGS
++
++ifdef CONFIG_LTO
++ifdef CONFIG_UBSAN
++ifeq ($(call cc-ifversion,-lt,0600,y),y)
++ # work around compiler asserts due to UBSAN
++ $(warning Disabling LTO for gcc 5.x because UBSAN is active)
++ undefine CONFIG_LTO
++endif
++endif
++endif
++
++ifdef CONFIG_LTO
++# 4.7 works mostly, but it sometimes loses symbols on large builds
++# This can be worked around by marking those symbols visible,
++# but that is fairly ugly and the problem is gone with 4.8
++# 4.8 was very slow
++# 4.9 was missing __attribute__((noreorder)) for ordering initcalls,
++# and needed -fno-toplevel-reorder, which can lead to missing symbols
++# so only support 5.0+
++ifeq ($(call cc-ifversion, -ge, 0500,y),y)
++# is the compiler compiled with LTO?
++ifneq ($(call cc-option,${LTO_CFLAGS},n),n)
++# binutils before 2.27 has various problems with plugins
++ifeq ($(call ld-ifversion,-ge,227000000,y),y)
++
++ LTO_CFLAGS := -flto $(DISABLE_TL_REORDER)
++ LTO_FINAL_CFLAGS := -fuse-linker-plugin
++
++# would be needed to support < 5.0
++# LTO_FINAL_CFLAGS += -fno-toplevel-reorder
++
++ LTO_FINAL_CFLAGS += -flto=jobserver
++
++ # don't compile everything twice
++ # requires plugin ar
++ LTO_CFLAGS += -fno-fat-lto-objects
++
++ # Used to disable LTO for specific files (e.g. vdso)
++ DISABLE_LTO := -fno-lto
++
++ # shut up lots of warnings for the compat syscalls
++ LTO_CFLAGS += $(call cc-disable-warning,attribute-alias,)
++
++ LTO_FINAL_CFLAGS += ${LTO_CFLAGS} -fwhole-program
++
++ # most options are passed through implicitely in the LTO
++ # files per function, but not all.
++ # should not pass any that may need to be disabled for
++ # individual files.
++ LTO_FINAL_CFLAGS += $(filter -pg,${KBUILD_CFLAGS})
++ LTO_FINAL_CFLAGS += $(filter -fno-strict-aliasing,${KBUILD_CFLAGS})
++
++ifdef CONFIG_LTO_DEBUG
++ LTO_FINAL_CFLAGS += -fdump-ipa-cgraph -fdump-ipa-inline-details
++ # add for debugging compiler crashes:
++ # LTO_FINAL_CFLAGS += -dH -save-temps
++endif
++ifdef CONFIG_LTO_CP_CLONE
++ LTO_FINAL_CFLAGS += -fipa-cp-clone
++ LTO_CFLAGS += -fipa-cp-clone
++endif
++
++ KBUILD_CFLAGS += ${LTO_CFLAGS}
++
++ LDFINAL := ${CONFIG_SHELL} ${srctree}/scripts/gcc-ld \
++ ${LTO_FINAL_CFLAGS}
++
++ # 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.
++ TMPDIR ?= $(objtree)
++ export TMPDIR
++
++ # use plugin aware tools
++ AR = $(CROSS_COMPILE)gcc-ar
++ NM = $(CROSS_COMPILE)gcc-nm
++else
++ $(warning WARNING old binutils. LTO disabled)
++endif
++else
++ $(warning "WARNING: Compiler/Linker does not support LTO/WHOPR with linker plugin. CONFIG_LTO disabled.")
++endif
++else
++ $(warning "WARNING: GCC $(call cc-version) too old for LTO/WHOPR. CONFIG_LTO disabled")
++endif
++endif
+--- a/scripts/Makefile.modpost
++++ b/scripts/Makefile.modpost
+@@ -79,7 +79,8 @@ modpost = scripts/mod/modpost
+ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
+ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
+ $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
+- $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w)
++ $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
++ $(if $(CONFIG_LTO),-w)
+
+ MODPOST_OPT=$(subst -i,-n,$(filter -i,$(MAKEFLAGS)))
+
+@@ -118,9 +119,9 @@ targets += $(modules:.ko=.mod.o)
+ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
+
+ # Step 6), final link of the modules with optional arch pass after final link
+-quiet_cmd_ld_ko_o = LD [M] $@
++quiet_cmd_ld_ko_o = LDFINAL [M] $@
+ cmd_ld_ko_o = \
+- $(LD) -r $(LDFLAGS) \
++ $(LDFINAL) -r $(LDFLAGS) \
+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+ -o $@ $(filter-out FORCE,$^) ; \
+ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+--- a/scripts/gcc-ld
++++ b/scripts/gcc-ld
+@@ -8,7 +8,7 @@ ARGS="-nostdlib"
+
+ while [ "$1" != "" ] ; do
+ case "$1" in
+- -save-temps|-m32|-m64) N="$1" ;;
++ -save-temps*|-m32|-m64) N="$1" ;;
+ -r) N="$1" ;;
+ -[Wg]*) N="$1" ;;
+ -[olv]|-[Ofd]*|-nostdlib) N="$1" ;;
+@@ -19,7 +19,7 @@ while [ "$1" != "" ] ; do
+ -rpath-link|--sort-section|--section-start|-Tbss|-Tdata|-Ttext|\
+ --version-script|--dynamic-list|--version-exports-symbol|--wrap|-m)
+ A="$1" ; shift ; N="-Wl,$A,$1" ;;
+- -[m]*) N="$1" ;;
++ -[mp]*) N="$1" ;;
+ -*) N="-Wl,$1" ;;
+ *) N="$1" ;;
+ esac
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -84,7 +84,7 @@ modpost_link()
+ ${KBUILD_VMLINUX_LIBS} \
+ --end-group"
+ fi
+- ${LD} ${LDFLAGS} -r -o ${1} ${objects}
++ ${LDFINAL} ${LDFLAGS} -r -o ${1} ${objects}
+ }
+
+ # Link of vmlinux
+@@ -113,7 +113,7 @@ vmlinux_link()
+ ${1}"
+ fi
+
+- ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
++ ${LDFINAL} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
+ -T ${lds} ${objects}
+ else
+ if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
+@@ -315,7 +315,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
+ fi
+ fi
+
+-info LD vmlinux
++info LDFINAL vmlinux
+ vmlinux_link "${kallsymso}" vmlinux
+
+ if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then
--- /dev/null
+From 29d1034ff503504fae938a2c006f82a09ebe8921 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Wed, 22 Nov 2017 19:43:48 -0800
+Subject: x86: Enable Link Time Optimization
+
+LTO is opt-in per architecture because it usually needs some
+fixes.
+
+LTO needs THIN_ARCHIVES because standard binutils doesn't like mixing
+assembler and LTO code with ld -r.
+
+Enable LTO and THIN_ARCHIVES for x86
+
+Signed-off-by: Andi Kleen <ak@linux.intel.com>
+---
+ arch/x86/Kconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -121,6 +121,8 @@ config X86
+ select HAVE_ARCH_VMAP_STACK if X86_64
+ select HAVE_ARCH_WITHIN_STACK_FRAMES
+ select HAVE_CC_STACKPROTECTOR
++ select THIN_ARCHIVES if LTO
++ select ARCH_SUPPORTS_LTO
+ select HAVE_CMPXCHG_DOUBLE
+ select HAVE_CMPXCHG_LOCAL
+ select HAVE_CONTEXT_TRACKING if X86_64
--- /dev/null
+From 7851f54590f0646aaee001e24c9a2917fd0fb3b1 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 11:12:58 +0200
+Subject: Make sys_* functions visible
+
+On mips the sys_clone and sys_fork function are referenced by assembler
+code, if they are not visible the linking with lto activated will fail.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ include/linux/syscalls.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -191,7 +191,7 @@ static inline int is_syscall_trace_event
+
+ #define SYSCALL_DEFINE0(sname) \
+ SYSCALL_METADATA(_##sname, 0); \
+- asmlinkage long sys_##sname(void)
++ __visible asmlinkage long sys_##sname(void)
+
+ #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
+ #define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
+@@ -208,7 +208,7 @@ static inline int is_syscall_trace_event
+
+ #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
+ #define __SYSCALL_DEFINEx(x, name, ...) \
+- asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
++ __visible asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
+ __attribute__((alias(__stringify(SyS##name)))); \
+ static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
+ asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
--- /dev/null
+From 775df9f0770286eca3138e6340654ec231a6b8b6 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 11:15:13 +0200
+Subject: MIPS: Use same definition for tlbmiss_handler_setup_pgd
+
+tlbmiss_handler_setup_pgd is defined as a pointer to a u32 array in
+tlbex.c and as a function pointer in mmu_context.h. This was done
+because tlbex.c fills the memory of u32 with assembler code which
+implements a function, this assembler code depends on the CPU being
+used. Later the code will jump into this function.
+
+This patch uses the same type for both definitions and makes use of the
+pointer to the _start of the function in places where we have to access
+the code of the function.
+
+This fixes the build with LTO.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/mips/mm/tlbex.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/mips/mm/tlbex.c
++++ b/arch/mips/mm/tlbex.c
+@@ -1575,7 +1575,7 @@ extern u32 handle_tlbl[], handle_tlbl_en
+ extern u32 handle_tlbs[], handle_tlbs_end[];
+ extern u32 handle_tlbm[], handle_tlbm_end[];
+ extern u32 tlbmiss_handler_setup_pgd_start[];
+-extern u32 tlbmiss_handler_setup_pgd[];
++extern void tlbmiss_handler_setup_pgd(unsigned long);
+ EXPORT_SYMBOL_GPL(tlbmiss_handler_setup_pgd);
+ extern u32 tlbmiss_handler_setup_pgd_end[];
+
+@@ -1592,7 +1592,7 @@ static void build_setup_pgd(void)
+ #endif
+
+ memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
+- sizeof(tlbmiss_handler_setup_pgd[0]));
++ sizeof(u32));
+ memset(labels, 0, sizeof(labels));
+ memset(relocs, 0, sizeof(relocs));
+ pgd_reg = allocate_kscratch();
+@@ -1650,9 +1650,9 @@ static void build_setup_pgd(void)
+
+ uasm_resolve_relocs(relocs, labels);
+ pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
+- (unsigned int)(p - tlbmiss_handler_setup_pgd));
++ (unsigned int)(p - tlbmiss_handler_setup_pgd_start));
+
+- dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
++ dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd_start,
+ tlbmiss_handler_setup_pgd_size);
+ }
+
--- /dev/null
+From 3c3bf587d2e4139eb0cf03cb202c4bbe8a171dbf Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 11:23:43 +0200
+Subject: MIPS: make __stack_chk_guard visible
+
+When linking some kernel modules with LTO it failed because of undefined
+references to __stack_chk_guard. This fixes the problem by making this
+always visible.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/mips/kernel/process.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/mips/kernel/process.c
++++ b/arch/mips/kernel/process.c
+@@ -182,7 +182,7 @@ int copy_thread_tls(unsigned long clone_
+
+ #ifdef CONFIG_CC_STACKPROTECTOR
+ #include <linux/stackprotector.h>
+-unsigned long __stack_chk_guard __read_mostly;
++unsigned long __stack_chk_guard __read_mostly __visible;
+ EXPORT_SYMBOL(__stack_chk_guard);
+ #endif
+
--- /dev/null
+From 9ba7cd8ea46b36e1e77136b3350de472ad4b68a4 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 11:40:34 +0200
+Subject: MIPS: define __current_thread_info inside of function
+
+__current_thread_info is currently defined in the header file, but when
+we link the kernel with LTO it shows up in all files which include this
+header file and causes conflicts with itself. Move the definition into
+the only function which uses it to prevent these problems.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/mips/include/asm/thread_info.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/include/asm/thread_info.h
++++ b/arch/mips/include/asm/thread_info.h
+@@ -52,11 +52,11 @@ struct thread_info {
+ #define init_thread_info (init_thread_union.thread_info)
+ #define init_stack (init_thread_union.stack)
+
+-/* How to get the thread information struct from C. */
+-register struct thread_info *__current_thread_info __asm__("$28");
+-
+ static inline struct thread_info *current_thread_info(void)
+ {
++ /* How to get the thread information struct from C. */
++ register struct thread_info *__current_thread_info __asm__("$28");
++
+ return __current_thread_info;
+ }
+
--- /dev/null
+From 72d623ce0619cf438d4092b4780607bdd43a80a5 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 11:40:47 +0200
+Subject: MIPS: activate LTO suport for MIPS
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/mips/Kconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -39,6 +39,8 @@ config MIPS
+ select HAVE_CBPF_JIT if (!64BIT && !CPU_MICROMIPS)
+ select HAVE_EBPF_JIT if (64BIT && !CPU_MICROMIPS)
+ select HAVE_CC_STACKPROTECTOR
++ select THIN_ARCHIVES if LTO
++ select ARCH_SUPPORTS_LTO
+ select HAVE_CONTEXT_TRACKING
+ select HAVE_COPY_THREAD_TLS
+ select HAVE_C_RECORDMCOUNT
--- /dev/null
+From c5782b86caa9307778d09afa1dae124346931c32 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 13:43:03 +0200
+Subject: freevxfs: do not inline vxfs_put_page()
+
+This function is declated in a header file and used outside of this file.
+With inline this causes a link error with LTO linking.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ fs/freevxfs/vxfs_subr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/freevxfs/vxfs_subr.c
++++ b/fs/freevxfs/vxfs_subr.c
+@@ -46,7 +46,7 @@ const struct address_space_operations vx
+ .bmap = vxfs_bmap,
+ };
+
+-inline void
++void
+ vxfs_put_page(struct page *pp)
+ {
+ kunmap(pp);
--- /dev/null
+From 04199f8694ac0b4cc0d66e412438ffa41d08cda0 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 13:44:24 +0200
+Subject: MIPS: make __ashrdi3 visilbe
+
+Some modules need this funtion and under MIPS with LTo compiling some modules could not find this.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/mips/lib/ashrdi3.c | 2 +-
+ arch/mips/lib/lshrdi3.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/lib/ashrdi3.c
++++ b/arch/mips/lib/ashrdi3.c
+@@ -3,7 +3,7 @@
+
+ #include "libgcc.h"
+
+-long long notrace __ashrdi3(long long u, word_type b)
++long long notrace __visible __ashrdi3(long long u, word_type b)
+ {
+ DWunion uu, w;
+ word_type bm;
+--- a/arch/mips/lib/lshrdi3.c
++++ b/arch/mips/lib/lshrdi3.c
+@@ -3,7 +3,7 @@
+
+ #include "libgcc.h"
+
+-long long notrace __lshrdi3(long long u, word_type b)
++__visible long long notrace __lshrdi3(long long u, word_type b)
+ {
+ DWunion uu, w;
+ word_type bm;
--- /dev/null
+From e8e2e2d663ff5d7442d060fd870e74bb6807eaf0 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Sun, 20 May 2018 20:22:45 +0200
+Subject: MIPS: remove const from mips_io_port_base
+
+This variable is changed by some platform init code. When LTO is used gcc assumes that the variable never changes and inlines the code.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ arch/mips/include/asm/io.h | 2 +-
+ arch/mips/kernel/setup.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/include/asm/io.h
++++ b/arch/mips/include/asm/io.h
+@@ -60,7 +60,7 @@
+ * instruction, so the lower 16 bits must be zero. Should be true on
+ * on any sane architecture; generic code does not use this assumption.
+ */
+-extern const unsigned long mips_io_port_base;
++extern unsigned long mips_io_port_base;
+
+ /*
+ * Gcc will generate code to load the value of mips_io_port_base after each
+--- a/arch/mips/kernel/setup.c
++++ b/arch/mips/kernel/setup.c
+@@ -75,7 +75,7 @@ static char __initdata builtin_cmdline[C
+ * mips_io_port_base is the begin of the address space to which x86 style
+ * I/O ports are mapped.
+ */
+-const unsigned long mips_io_port_base = -1;
++unsigned long mips_io_port_base = -1;
+ EXPORT_SYMBOL(mips_io_port_base);
+
+ static struct resource code_resource = { .name = "Kernel code", };
--- a/init/Kconfig
+++ b/init/Kconfig
-@@ -1427,6 +1427,15 @@ config EMBEDDED
+@@ -1494,6 +1494,15 @@ config EMBEDDED
an embedded system so certain expert options are available
for configuration.