commit: 68ed016b1baa8e1e440b12efbfda34987f0d6ab4 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Fri Nov 23 12:44:55 2018 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Fri Nov 23 12:44:55 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=68ed016b
proj/linux-patches: Linux patch 4.9.139 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> 0000_README | 4 + 1138_linux-4.9.139.patch | 2371 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2375 insertions(+) diff --git a/0000_README b/0000_README index 75308be..56d5a98 100644 --- a/0000_README +++ b/0000_README @@ -595,6 +595,10 @@ Patch: 1137_linux-4.9.138.patch From: http://www.kernel.org Desc: Linux 4.9.138 +Patch: 1138_linux-4.9.139.patch +From: http://www.kernel.org +Desc: Linux 4.9.139 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1138_linux-4.9.139.patch b/1138_linux-4.9.139.patch new file mode 100644 index 0000000..befed26 --- /dev/null +++ b/1138_linux-4.9.139.patch @@ -0,0 +1,2371 @@ +diff --git a/.gitignore b/.gitignore +index c2ed4ecb0acd..0c39aa20b6ba 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -33,6 +33,7 @@ + *.lzo + *.patch + *.gcno ++*.ll + modules.builtin + Module.symvers + *.dwo +diff --git a/Kbuild b/Kbuild +index 3d0ae152af7c..94c752762bc2 100644 +--- a/Kbuild ++++ b/Kbuild +@@ -7,31 +7,6 @@ + # 4) Check for missing system calls + # 5) Generate constants.py (may need bounds.h) + +-# Default sed regexp - multiline due to syntax constraints +-define sed-y +- "/^->/{s:->#\(.*\):/* \1 */:; \ +- s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ +- s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ +- s:->::; p;}" +-endef +- +-# Use filechk to avoid rebuilds when a header changes, but the resulting file +-# does not +-define filechk_offsets +- (set -e; \ +- echo "#ifndef $2"; \ +- echo "#define $2"; \ +- echo "/*"; \ +- echo " * DO NOT MODIFY."; \ +- echo " *"; \ +- echo " * This file was generated by Kbuild"; \ +- echo " */"; \ +- echo ""; \ +- sed -ne $(sed-y); \ +- echo ""; \ +- echo "#endif" ) +-endef +- + ##### + # 1) Generate bounds.h + +diff --git a/Makefile b/Makefile +index ccf2602f664d..a6959d96316d 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 138 ++SUBLEVEL = 139 + EXTRAVERSION = + NAME = Roaring Lionus + +@@ -303,7 +303,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + + HOSTCC = gcc + HOSTCXX = g++ +-HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89 ++HOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -std=gnu89 + HOSTCXXFLAGS = -O2 + + ifeq ($(shell $(HOSTCC) -v 2>&1 | grep -c "clang version"), 1) +@@ -394,7 +394,7 @@ LINUXINCLUDE += $(filter-out $(LINUXINCLUDE),$(USERINCLUDE)) + + KBUILD_AFLAGS := -D__ASSEMBLY__ + KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ +- -fno-strict-aliasing -fno-common \ ++ -fno-strict-aliasing -fno-common -fshort-wchar \ + -Werror-implicit-function-declaration \ + -Wno-format-security \ + -std=gnu89 +@@ -644,7 +644,8 @@ KBUILD_CFLAGS += $(call cc-option,-fdata-sections,) + endif + + ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +-KBUILD_CFLAGS += -Os $(call cc-disable-warning,maybe-uninitialized,) ++KBUILD_CFLAGS += $(call cc-option,-Oz,-Os) ++KBUILD_CFLAGS += $(call cc-disable-warning,maybe-uninitialized,) + else + ifdef CONFIG_PROFILE_ALL_BRANCHES + KBUILD_CFLAGS += -O2 $(call cc-disable-warning,maybe-uninitialized,) +@@ -704,11 +705,20 @@ endif + KBUILD_CFLAGS += $(stackp-flag) + + ifeq ($(cc-name),clang) ++ifneq ($(CROSS_COMPILE),) ++CLANG_TARGET := -target $(notdir $(CROSS_COMPILE:%-=%)) ++GCC_TOOLCHAIN := $(realpath $(dir $(shell which $(LD)))/..) ++endif ++ifneq ($(GCC_TOOLCHAIN),) ++CLANG_GCC_TC := -gcc-toolchain $(GCC_TOOLCHAIN) ++endif ++KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) ++KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) + KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) +-KBUILD_CPPFLAGS += $(call cc-option,-Wno-unknown-warning-option,) + KBUILD_CFLAGS += $(call cc-disable-warning, unused-variable) + KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) + KBUILD_CFLAGS += $(call cc-disable-warning, gnu) ++KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) + # Quiet clang warning: comparison of unsigned expression < 0 is always false + KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare) + # CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the +@@ -716,6 +726,8 @@ KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare) + # See modpost pattern 2 + KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,) + KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior) ++KBUILD_CFLAGS += $(call cc-option, -no-integrated-as) ++KBUILD_AFLAGS += $(call cc-option, -no-integrated-as) + else + + # These warnings generated too much noise in a regular build. +@@ -1379,6 +1391,8 @@ help: + @echo ' (default: $$(INSTALL_MOD_PATH)/lib/firmware)' + @echo ' dir/ - Build all files in dir and below' + @echo ' dir/file.[ois] - Build specified target only' ++ @echo ' dir/file.ll - Build the LLVM assembly file' ++ @echo ' (requires compiler support for LLVM assembly generation)' + @echo ' dir/file.lst - Build specified mixed source/assembly target only' + @echo ' (requires a recent binutils and recent build (System.map))' + @echo ' dir/file.ko - Build module including final link' +@@ -1563,6 +1577,7 @@ clean: $(clean-dirs) + -o -name '*.symtypes' -o -name 'modules.order' \ + -o -name modules.builtin -o -name '.tmp_*.o.*' \ + -o -name '*.c.[012]*.*' \ ++ -o -name '*.ll' \ + -o -name '*.gcno' \) -type f -print | xargs rm -f + + # Generate tags for editors +@@ -1666,6 +1681,8 @@ endif + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + %.symtypes: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) ++%.ll: %.c prepare scripts FORCE ++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + + # Modules + /: prepare scripts FORCE +diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h +index 3aed4492c9a7..e616f61f859d 100644 +--- a/arch/arm/include/asm/assembler.h ++++ b/arch/arm/include/asm/assembler.h +@@ -445,11 +445,23 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) + .size \name , . - \name + .endm + ++ .macro csdb ++#ifdef CONFIG_THUMB2_KERNEL ++ .inst.w 0xf3af8014 ++#else ++ .inst 0xe320f014 ++#endif ++ .endm ++ + .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req + #ifndef CONFIG_CPU_USE_DOMAINS + adds \tmp, \addr, #\size - 1 + sbcccs \tmp, \tmp, \limit + bcs \bad ++#ifdef CONFIG_CPU_SPECTRE ++ movcs \addr, #0 ++ csdb ++#endif + #endif + .endm + +diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h +index f5d698182d50..513e03d138ea 100644 +--- a/arch/arm/include/asm/barrier.h ++++ b/arch/arm/include/asm/barrier.h +@@ -16,6 +16,12 @@ + #define isb(option) __asm__ __volatile__ ("isb " #option : : : "memory") + #define dsb(option) __asm__ __volatile__ ("dsb " #option : : : "memory") + #define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory") ++#ifdef CONFIG_THUMB2_KERNEL ++#define CSDB ".inst.w 0xf3af8014" ++#else ++#define CSDB ".inst 0xe320f014" ++#endif ++#define csdb() __asm__ __volatile__(CSDB : : : "memory") + #elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6 + #define isb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \ + : : "r" (0) : "memory") +@@ -36,6 +42,13 @@ + #define dmb(x) __asm__ __volatile__ ("" : : : "memory") + #endif + ++#ifndef CSDB ++#define CSDB ++#endif ++#ifndef csdb ++#define csdb() ++#endif ++ + #ifdef CONFIG_ARM_HEAVY_MB + extern void (*soc_mb)(void); + extern void arm_heavy_mb(void); +@@ -62,6 +75,25 @@ extern void arm_heavy_mb(void); + #define __smp_rmb() __smp_mb() + #define __smp_wmb() dmb(ishst) + ++#ifdef CONFIG_CPU_SPECTRE ++static inline unsigned long array_index_mask_nospec(unsigned long idx, ++ unsigned long sz) ++{ ++ unsigned long mask; ++ ++ asm volatile( ++ "cmp %1, %2\n" ++ " sbc %0, %1, %1\n" ++ CSDB ++ : "=r" (mask) ++ : "r" (idx), "Ir" (sz) ++ : "cc"); ++ ++ return mask; ++} ++#define array_index_mask_nospec array_index_mask_nospec ++#endif ++ + #include <asm-generic/barrier.h> + + #endif /* !__ASSEMBLY__ */ +diff --git a/arch/arm/include/asm/bugs.h b/arch/arm/include/asm/bugs.h +index a97f1ea708d1..73a99c72a930 100644 +--- a/arch/arm/include/asm/bugs.h ++++ b/arch/arm/include/asm/bugs.h +@@ -10,12 +10,14 @@ + #ifndef __ASM_BUGS_H + #define __ASM_BUGS_H + +-#ifdef CONFIG_MMU + extern void check_writebuffer_bugs(void); + +-#define check_bugs() check_writebuffer_bugs() ++#ifdef CONFIG_MMU ++extern void check_bugs(void); ++extern void check_other_bugs(void); + #else + #define check_bugs() do { } while (0) ++#define check_other_bugs() do { } while (0) + #endif + + #endif +diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h +index dbdbce1b3a72..b74b174ac9fc 100644 +--- a/arch/arm/include/asm/cp15.h ++++ b/arch/arm/include/asm/cp15.h +@@ -64,6 +64,9 @@ + #define __write_sysreg(v, r, w, c, t) asm volatile(w " " c : : "r" ((t)(v))) + #define write_sysreg(v, ...) __write_sysreg(v, __VA_ARGS__) + ++#define BPIALL __ACCESS_CP15(c7, 0, c5, 6) ++#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) ++ + extern unsigned long cr_alignment; /* defined in entry-armv.S */ + + static inline unsigned long get_cr(void) +diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h +index b62eaeb147aa..c55db1e22f0c 100644 +--- a/arch/arm/include/asm/cputype.h ++++ b/arch/arm/include/asm/cputype.h +@@ -76,8 +76,16 @@ + #define ARM_CPU_PART_CORTEX_A12 0x4100c0d0 + #define ARM_CPU_PART_CORTEX_A17 0x4100c0e0 + #define ARM_CPU_PART_CORTEX_A15 0x4100c0f0 ++#define ARM_CPU_PART_CORTEX_A53 0x4100d030 ++#define ARM_CPU_PART_CORTEX_A57 0x4100d070 ++#define ARM_CPU_PART_CORTEX_A72 0x4100d080 ++#define ARM_CPU_PART_CORTEX_A73 0x4100d090 ++#define ARM_CPU_PART_CORTEX_A75 0x4100d0a0 + #define ARM_CPU_PART_MASK 0xff00fff0 + ++/* Broadcom cores */ ++#define ARM_CPU_PART_BRAHMA_B15 0x420000f0 ++ + /* DEC implemented cores */ + #define ARM_CPU_PART_SA1100 0x4400a110 + +diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h +index 8ef05381984b..24f3ec7c9fbe 100644 +--- a/arch/arm/include/asm/kvm_asm.h ++++ b/arch/arm/include/asm/kvm_asm.h +@@ -61,8 +61,6 @@ struct kvm_vcpu; + extern char __kvm_hyp_init[]; + extern char __kvm_hyp_init_end[]; + +-extern char __kvm_hyp_vector[]; +- + extern void __kvm_flush_vm_context(void); + extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa); + extern void __kvm_tlb_flush_vmid(struct kvm *kvm); +diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h +index 0833d8a1dbbb..2fda7e905754 100644 +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -21,6 +21,7 @@ + + #include <linux/types.h> + #include <linux/kvm_types.h> ++#include <asm/cputype.h> + #include <asm/kvm.h> + #include <asm/kvm_asm.h> + #include <asm/kvm_mmio.h> +@@ -323,8 +324,17 @@ static inline int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu, + + static inline bool kvm_arm_harden_branch_predictor(void) + { +- /* No way to detect it yet, pretend it is not there. */ +- return false; ++ switch(read_cpuid_part()) { ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ case ARM_CPU_PART_BRAHMA_B15: ++ case ARM_CPU_PART_CORTEX_A12: ++ case ARM_CPU_PART_CORTEX_A15: ++ case ARM_CPU_PART_CORTEX_A17: ++ return true; ++#endif ++ default: ++ return false; ++ } + } + + #define KVM_SSBD_UNKNOWN -1 +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index e2f05cedaf97..d26395754b56 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -248,7 +248,28 @@ static inline int kvm_read_guest_lock(struct kvm *kvm, + + static inline void *kvm_get_hyp_vector(void) + { +- return kvm_ksym_ref(__kvm_hyp_vector); ++ switch(read_cpuid_part()) { ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ case ARM_CPU_PART_CORTEX_A12: ++ case ARM_CPU_PART_CORTEX_A17: ++ { ++ extern char __kvm_hyp_vector_bp_inv[]; ++ return kvm_ksym_ref(__kvm_hyp_vector_bp_inv); ++ } ++ ++ case ARM_CPU_PART_BRAHMA_B15: ++ case ARM_CPU_PART_CORTEX_A15: ++ { ++ extern char __kvm_hyp_vector_ic_inv[]; ++ return kvm_ksym_ref(__kvm_hyp_vector_ic_inv); ++ } ++#endif ++ default: ++ { ++ extern char __kvm_hyp_vector[]; ++ return kvm_ksym_ref(__kvm_hyp_vector); ++ } ++ } + } + + static inline int kvm_map_vectors(void) +diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h +index 8877ad5ffe10..f379f5f849a9 100644 +--- a/arch/arm/include/asm/proc-fns.h ++++ b/arch/arm/include/asm/proc-fns.h +@@ -36,6 +36,10 @@ extern struct processor { + * Set up any processor specifics + */ + void (*_proc_init)(void); ++ /* ++ * Check for processor bugs ++ */ ++ void (*check_bugs)(void); + /* + * Disable any processor specifics + */ +diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h +index a3d61ad984af..1fed41440af9 100644 +--- a/arch/arm/include/asm/system_misc.h ++++ b/arch/arm/include/asm/system_misc.h +@@ -7,6 +7,7 @@ + #include <linux/linkage.h> + #include <linux/irqflags.h> + #include <linux/reboot.h> ++#include <linux/percpu.h> + + extern void cpu_init(void); + +@@ -14,6 +15,20 @@ void soft_restart(unsigned long); + extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); + extern void (*arm_pm_idle)(void); + ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++typedef void (*harden_branch_predictor_fn_t)(void); ++DECLARE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn); ++static inline void harden_branch_predictor(void) ++{ ++ harden_branch_predictor_fn_t fn = per_cpu(harden_branch_predictor_fn, ++ smp_processor_id()); ++ if (fn) ++ fn(); ++} ++#else ++#define harden_branch_predictor() do { } while (0) ++#endif ++ + #define UDBG_UNDEFINED (1 << 0) + #define UDBG_SYSCALL (1 << 1) + #define UDBG_BADABORT (1 << 2) +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index 776757d1604a..57d2ad9c75ca 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -126,8 +126,8 @@ struct user_vfp_exc; + + extern int vfp_preserve_user_clear_hwstate(struct user_vfp __user *, + struct user_vfp_exc __user *); +-extern int vfp_restore_user_hwstate(struct user_vfp __user *, +- struct user_vfp_exc __user *); ++extern int vfp_restore_user_hwstate(struct user_vfp *, ++ struct user_vfp_exc *); + #endif + + /* +diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h +index b7e0125c0bbf..7b17460127fd 100644 +--- a/arch/arm/include/asm/uaccess.h ++++ b/arch/arm/include/asm/uaccess.h +@@ -114,6 +114,13 @@ static inline void set_fs(mm_segment_t fs) + : "cc"); \ + flag; }) + ++/* ++ * This is a type: either unsigned long, if the argument fits into ++ * that type, or otherwise unsigned long long. ++ */ ++#define __inttype(x) \ ++ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) ++ + /* + * Single-value transfer routines. They automatically use the right + * size if we just have the right pointer type. Note that the functions +@@ -183,7 +190,7 @@ extern int __get_user_64t_4(void *); + ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ + register const typeof(*(p)) __user *__p asm("r0") = (p);\ +- register typeof(x) __r2 asm("r2"); \ ++ register __inttype(x) __r2 asm("r2"); \ + register unsigned long __l asm("r1") = __limit; \ + register int __e asm("r0"); \ + unsigned int __ua_flags = uaccess_save_and_enable(); \ +@@ -273,6 +280,16 @@ static inline void set_fs(mm_segment_t fs) + #define user_addr_max() \ + (segment_eq(get_fs(), KERNEL_DS) ? ~0UL : get_fs()) + ++#ifdef CONFIG_CPU_SPECTRE ++/* ++ * When mitigating Spectre variant 1, it is not worth fixing the non- ++ * verifying accessors, because we need to add verification of the ++ * address space there. Force these to use the standard get_user() ++ * version instead. ++ */ ++#define __get_user(x, ptr) get_user(x, ptr) ++#else ++ + /* + * The "__xxx" versions of the user access functions do not verify the + * address space - it must have been done previously with a separate +@@ -289,12 +306,6 @@ static inline void set_fs(mm_segment_t fs) + __gu_err; \ + }) + +-#define __get_user_error(x, ptr, err) \ +-({ \ +- __get_user_err((x), (ptr), err); \ +- (void) 0; \ +-}) +- + #define __get_user_err(x, ptr, err) \ + do { \ + unsigned long __gu_addr = (unsigned long)(ptr); \ +@@ -354,6 +365,7 @@ do { \ + + #define __get_user_asm_word(x, addr, err) \ + __get_user_asm(x, addr, err, ldr) ++#endif + + + #define __put_user_switch(x, ptr, __err, __fn) \ +diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile +index ad325a8c7e1e..adb9add28b6f 100644 +--- a/arch/arm/kernel/Makefile ++++ b/arch/arm/kernel/Makefile +@@ -30,6 +30,7 @@ else + obj-y += entry-armv.o + endif + ++obj-$(CONFIG_MMU) += bugs.o + obj-$(CONFIG_CPU_IDLE) += cpuidle.o + obj-$(CONFIG_ISA_DMA_API) += dma.o + obj-$(CONFIG_FIQ) += fiq.o fiqasm.o +diff --git a/arch/arm/kernel/bugs.c b/arch/arm/kernel/bugs.c +new file mode 100644 +index 000000000000..7be511310191 +--- /dev/null ++++ b/arch/arm/kernel/bugs.c +@@ -0,0 +1,18 @@ ++// SPDX-Identifier: GPL-2.0 ++#include <linux/init.h> ++#include <asm/bugs.h> ++#include <asm/proc-fns.h> ++ ++void check_other_bugs(void) ++{ ++#ifdef MULTI_CPU ++ if (processor.check_bugs) ++ processor.check_bugs(); ++#endif ++} ++ ++void __init check_bugs(void) ++{ ++ check_writebuffer_bugs(); ++ check_other_bugs(); ++} +diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S +index 10c3283d6c19..56be67ecf0fa 100644 +--- a/arch/arm/kernel/entry-common.S ++++ b/arch/arm/kernel/entry-common.S +@@ -223,9 +223,7 @@ local_restart: + tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? + bne __sys_trace + +- cmp scno, #NR_syscalls @ check upper syscall limit +- badr lr, ret_fast_syscall @ return address +- ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine ++ invoke_syscall tbl, scno, r10, ret_fast_syscall + + add r1, sp, #S_OFF + 2: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) +@@ -258,14 +256,8 @@ __sys_trace: + mov r1, scno + add r0, sp, #S_OFF + bl syscall_trace_enter +- +- badr lr, __sys_trace_return @ return address +- mov scno, r0 @ syscall number (possibly new) +- add r1, sp, #S_R0 + S_OFF @ pointer to regs +- cmp scno, #NR_syscalls @ check upper syscall limit +- ldmccia r1, {r0 - r6} @ have to reload r0 - r6 +- stmccia sp, {r4, r5} @ and update the stack args +- ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine ++ mov scno, r0 ++ invoke_syscall tbl, scno, r10, __sys_trace_return, reload=1 + cmp scno, #-1 @ skip the syscall? + bne 2b + add sp, sp, #S_OFF @ restore stack +@@ -317,6 +309,10 @@ sys_syscall: + bic scno, r0, #__NR_OABI_SYSCALL_BASE + cmp scno, #__NR_syscall - __NR_SYSCALL_BASE + cmpne scno, #NR_syscalls @ check range ++#ifdef CONFIG_CPU_SPECTRE ++ movhs scno, #0 ++ csdb ++#endif + stmloia sp, {r5, r6} @ shuffle args + movlo r0, r1 + movlo r1, r2 +diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S +index e056c9a9aa9d..fa7c6e5c17e7 100644 +--- a/arch/arm/kernel/entry-header.S ++++ b/arch/arm/kernel/entry-header.S +@@ -377,6 +377,31 @@ + #endif + .endm + ++ .macro invoke_syscall, table, nr, tmp, ret, reload=0 ++#ifdef CONFIG_CPU_SPECTRE ++ mov \tmp, \nr ++ cmp \tmp, #NR_syscalls @ check upper syscall limit ++ movcs \tmp, #0 ++ csdb ++ badr lr, \ret @ return address ++ .if \reload ++ add r1, sp, #S_R0 + S_OFF @ pointer to regs ++ ldmccia r1, {r0 - r6} @ reload r0-r6 ++ stmccia sp, {r4, r5} @ update stack arguments ++ .endif ++ ldrcc pc, [\table, \tmp, lsl #2] @ call sys_* routine ++#else ++ cmp \nr, #NR_syscalls @ check upper syscall limit ++ badr lr, \ret @ return address ++ .if \reload ++ add r1, sp, #S_R0 + S_OFF @ pointer to regs ++ ldmccia r1, {r0 - r6} @ reload r0-r6 ++ stmccia sp, {r4, r5} @ update stack arguments ++ .endif ++ ldrcc pc, [\table, \nr, lsl #2] @ call sys_* routine ++#endif ++ .endm ++ + /* + * These are the registers used in the syscall handler, and allow us to + * have in theory up to 7 arguments to a function - r0 to r6. +diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c +index 7b8f2141427b..6bee5c9b1133 100644 +--- a/arch/arm/kernel/signal.c ++++ b/arch/arm/kernel/signal.c +@@ -107,21 +107,20 @@ static int preserve_vfp_context(struct vfp_sigframe __user *frame) + return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc); + } + +-static int restore_vfp_context(struct vfp_sigframe __user *frame) ++static int restore_vfp_context(struct vfp_sigframe __user *auxp) + { +- unsigned long magic; +- unsigned long size; +- int err = 0; ++ struct vfp_sigframe frame; ++ int err; + +- __get_user_error(magic, &frame->magic, err); +- __get_user_error(size, &frame->size, err); ++ err = __copy_from_user(&frame, (char __user *) auxp, sizeof(frame)); + + if (err) +- return -EFAULT; +- if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) ++ return err; ++ ++ if (frame.magic != VFP_MAGIC || frame.size != VFP_STORAGE_SIZE) + return -EINVAL; + +- return vfp_restore_user_hwstate(&frame->ufp, &frame->ufp_exc); ++ return vfp_restore_user_hwstate(&frame.ufp, &frame.ufp_exc); + } + + #endif +@@ -141,6 +140,7 @@ struct rt_sigframe { + + static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) + { ++ struct sigcontext context; + struct aux_sigframe __user *aux; + sigset_t set; + int err; +@@ -149,23 +149,26 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) + if (err == 0) + set_current_blocked(&set); + +- __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); +- __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); +- __get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err); +- __get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err); +- __get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err); +- __get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err); +- __get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err); +- __get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err); +- __get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err); +- __get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err); +- __get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err); +- __get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err); +- __get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err); +- __get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err); +- __get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err); +- __get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err); +- __get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err); ++ err |= __copy_from_user(&context, &sf->uc.uc_mcontext, sizeof(context)); ++ if (err == 0) { ++ regs->ARM_r0 = context.arm_r0; ++ regs->ARM_r1 = context.arm_r1; ++ regs->ARM_r2 = context.arm_r2; ++ regs->ARM_r3 = context.arm_r3; ++ regs->ARM_r4 = context.arm_r4; ++ regs->ARM_r5 = context.arm_r5; ++ regs->ARM_r6 = context.arm_r6; ++ regs->ARM_r7 = context.arm_r7; ++ regs->ARM_r8 = context.arm_r8; ++ regs->ARM_r9 = context.arm_r9; ++ regs->ARM_r10 = context.arm_r10; ++ regs->ARM_fp = context.arm_fp; ++ regs->ARM_ip = context.arm_ip; ++ regs->ARM_sp = context.arm_sp; ++ regs->ARM_lr = context.arm_lr; ++ regs->ARM_pc = context.arm_pc; ++ regs->ARM_cpsr = context.arm_cpsr; ++ } + + err |= !valid_user_regs(regs); + +diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c +index 7dd14e8395e6..d2ce37da87d8 100644 +--- a/arch/arm/kernel/smp.c ++++ b/arch/arm/kernel/smp.c +@@ -29,6 +29,7 @@ + #include <linux/irq_work.h> + + #include <linux/atomic.h> ++#include <asm/bugs.h> + #include <asm/smp.h> + #include <asm/cacheflush.h> + #include <asm/cpu.h> +@@ -400,6 +401,9 @@ asmlinkage void secondary_start_kernel(void) + * before we continue - which happens after __cpu_up returns. + */ + set_cpu_online(cpu, true); ++ ++ check_other_bugs(); ++ + complete(&cpu_running); + + local_irq_enable(); +diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c +index 9a2f882a0a2d..134f0d432610 100644 +--- a/arch/arm/kernel/suspend.c ++++ b/arch/arm/kernel/suspend.c +@@ -1,6 +1,7 @@ + #include <linux/init.h> + #include <linux/slab.h> + ++#include <asm/bugs.h> + #include <asm/cacheflush.h> + #include <asm/idmap.h> + #include <asm/pgalloc.h> +@@ -34,6 +35,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) + cpu_switch_mm(mm->pgd, mm); + local_flush_bp_all(); + local_flush_tlb_all(); ++ check_other_bugs(); + } + + return ret; +diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c +index 5f221acd21ae..640748e27035 100644 +--- a/arch/arm/kernel/sys_oabi-compat.c ++++ b/arch/arm/kernel/sys_oabi-compat.c +@@ -328,9 +328,11 @@ asmlinkage long sys_oabi_semtimedop(int semid, + return -ENOMEM; + err = 0; + for (i = 0; i < nsops; i++) { +- __get_user_error(sops[i].sem_num, &tsops->sem_num, err); +- __get_user_error(sops[i].sem_op, &tsops->sem_op, err); +- __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err); ++ struct oabi_sembuf osb; ++ err |= __copy_from_user(&osb, tsops, sizeof(osb)); ++ sops[i].sem_num = osb.sem_num; ++ sops[i].sem_op = osb.sem_op; ++ sops[i].sem_flg = osb.sem_flg; + tsops++; + } + if (timeout) { +diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S +index 96beb53934c9..64d4a39f4b4b 100644 +--- a/arch/arm/kvm/hyp/hyp-entry.S ++++ b/arch/arm/kvm/hyp/hyp-entry.S +@@ -16,6 +16,7 @@ + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + ++#include <linux/arm-smccc.h> + #include <linux/linkage.h> + #include <asm/kvm_arm.h> + #include <asm/kvm_asm.h> +@@ -71,6 +72,90 @@ __kvm_hyp_vector: + W(b) hyp_irq + W(b) hyp_fiq + ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ .align 5 ++__kvm_hyp_vector_ic_inv: ++ .global __kvm_hyp_vector_ic_inv ++ ++ /* ++ * We encode the exception entry in the bottom 3 bits of ++ * SP, and we have to guarantee to be 8 bytes aligned. ++ */ ++ W(add) sp, sp, #1 /* Reset 7 */ ++ W(add) sp, sp, #1 /* Undef 6 */ ++ W(add) sp, sp, #1 /* Syscall 5 */ ++ W(add) sp, sp, #1 /* Prefetch abort 4 */ ++ W(add) sp, sp, #1 /* Data abort 3 */ ++ W(add) sp, sp, #1 /* HVC 2 */ ++ W(add) sp, sp, #1 /* IRQ 1 */ ++ W(nop) /* FIQ 0 */ ++ ++ mcr p15, 0, r0, c7, c5, 0 /* ICIALLU */ ++ isb ++ ++ b decode_vectors ++ ++ .align 5 ++__kvm_hyp_vector_bp_inv: ++ .global __kvm_hyp_vector_bp_inv ++ ++ /* ++ * We encode the exception entry in the bottom 3 bits of ++ * SP, and we have to guarantee to be 8 bytes aligned. ++ */ ++ W(add) sp, sp, #1 /* Reset 7 */ ++ W(add) sp, sp, #1 /* Undef 6 */ ++ W(add) sp, sp, #1 /* Syscall 5 */ ++ W(add) sp, sp, #1 /* Prefetch abort 4 */ ++ W(add) sp, sp, #1 /* Data abort 3 */ ++ W(add) sp, sp, #1 /* HVC 2 */ ++ W(add) sp, sp, #1 /* IRQ 1 */ ++ W(nop) /* FIQ 0 */ ++ ++ mcr p15, 0, r0, c7, c5, 6 /* BPIALL */ ++ isb ++ ++decode_vectors: ++ ++#ifdef CONFIG_THUMB2_KERNEL ++ /* ++ * Yet another silly hack: Use VPIDR as a temp register. ++ * Thumb2 is really a pain, as SP cannot be used with most ++ * of the bitwise instructions. The vect_br macro ensures ++ * things gets cleaned-up. ++ */ ++ mcr p15, 4, r0, c0, c0, 0 /* VPIDR */ ++ mov r0, sp ++ and r0, r0, #7 ++ sub sp, sp, r0 ++ push {r1, r2} ++ mov r1, r0 ++ mrc p15, 4, r0, c0, c0, 0 /* VPIDR */ ++ mrc p15, 0, r2, c0, c0, 0 /* MIDR */ ++ mcr p15, 4, r2, c0, c0, 0 /* VPIDR */ ++#endif ++ ++.macro vect_br val, targ ++ARM( eor sp, sp, #\val ) ++ARM( tst sp, #7 ) ++ARM( eorne sp, sp, #\val ) ++ ++THUMB( cmp r1, #\val ) ++THUMB( popeq {r1, r2} ) ++ ++ beq \targ ++.endm ++ ++ vect_br 0, hyp_fiq ++ vect_br 1, hyp_irq ++ vect_br 2, hyp_hvc ++ vect_br 3, hyp_dabt ++ vect_br 4, hyp_pabt ++ vect_br 5, hyp_svc ++ vect_br 6, hyp_undef ++ vect_br 7, hyp_reset ++#endif ++ + .macro invalid_vector label, cause + .align + \label: mov r0, #\cause +@@ -118,7 +203,7 @@ hyp_hvc: + lsr r2, r2, #16 + and r2, r2, #0xff + cmp r2, #0 +- bne guest_trap @ Guest called HVC ++ bne guest_hvc_trap @ Guest called HVC + + /* + * Getting here means host called HVC, we shift parameters and branch +@@ -131,7 +216,14 @@ hyp_hvc: + mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR + beq 1f + +- push {lr} ++ /* ++ * Pushing r2 here is just a way of keeping the stack aligned to ++ * 8 bytes on any path that can trigger a HYP exception. Here, ++ * we may well be about to jump into the guest, and the guest ++ * exit would otherwise be badly decoded by our fancy ++ * "decode-exception-without-a-branch" code... ++ */ ++ push {r2, lr} + + mov lr, r0 + mov r0, r1 +@@ -141,9 +233,23 @@ hyp_hvc: + THUMB( orr lr, #1) + blx lr @ Call the HYP function + +- pop {lr} ++ pop {r2, lr} + 1: eret + ++guest_hvc_trap: ++ movw r2, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1 ++ movt r2, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1 ++ ldr r0, [sp] @ Guest's r0 ++ teq r0, r2 ++ bne guest_trap ++ add sp, sp, #12 ++ @ Returns: ++ @ r0 = 0 ++ @ r1 = HSR value (perfectly predictable) ++ @ r2 = ARM_SMCCC_ARCH_WORKAROUND_1 ++ mov r0, #0 ++ eret ++ + guest_trap: + load_vcpu r0 @ Load VCPU pointer to r0 + +diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S +index 7a4b06049001..a826df3d3814 100644 +--- a/arch/arm/lib/copy_from_user.S ++++ b/arch/arm/lib/copy_from_user.S +@@ -90,6 +90,15 @@ + .text + + ENTRY(arm_copy_from_user) ++#ifdef CONFIG_CPU_SPECTRE ++ get_thread_info r3 ++ ldr r3, [r3, #TI_ADDR_LIMIT] ++ adds ip, r1, r2 @ ip=addr+size ++ sub r3, r3, #1 @ addr_limit - 1 ++ cmpcc ip, r3 @ if (addr+size > addr_limit - 1) ++ movcs r1, #0 @ addr = NULL ++ csdb ++#endif + + #include "copy_template.S" + +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index c1799dd1d0d9..7f3760fa9c15 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -396,6 +396,7 @@ config CPU_V7 + select CPU_CP15_MPU if !MMU + select CPU_HAS_ASID if MMU + select CPU_PABRT_V7 ++ select CPU_SPECTRE if MMU + select CPU_TLB_V7 if MMU + + # ARMv7M +@@ -800,6 +801,28 @@ config CPU_BPREDICT_DISABLE + help + Say Y here to disable branch prediction. If unsure, say N. + ++config CPU_SPECTRE ++ bool ++ ++config HARDEN_BRANCH_PREDICTOR ++ bool "Harden the branch predictor against aliasing attacks" if EXPERT ++ depends on CPU_SPECTRE ++ default y ++ help ++ Speculation attacks against some high-performance processors rely ++ on being able to manipulate the branch predictor for a victim ++ context by executing aliasing branches in the attacker context. ++ Such attacks can be partially mitigated against by clearing ++ internal branch predictor state and limiting the prediction ++ logic in some situations. ++ ++ This config option will take CPU-specific actions to harden ++ the branch predictor against aliasing attacks and may rely on ++ specific instruction sequences or control bits being set by ++ the system firmware. ++ ++ If unsure, say Y. ++ + config TLS_REG_EMUL + bool + select NEED_KUSER_HELPERS +diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile +index e8698241ece9..92d47c8cbbc3 100644 +--- a/arch/arm/mm/Makefile ++++ b/arch/arm/mm/Makefile +@@ -94,7 +94,7 @@ obj-$(CONFIG_CPU_MOHAWK) += proc-mohawk.o + obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o + obj-$(CONFIG_CPU_V6) += proc-v6.o + obj-$(CONFIG_CPU_V6K) += proc-v6.o +-obj-$(CONFIG_CPU_V7) += proc-v7.o ++obj-$(CONFIG_CPU_V7) += proc-v7.o proc-v7-bugs.o + obj-$(CONFIG_CPU_V7M) += proc-v7m.o + + AFLAGS_proc-v6.o :=-Wa,-march=armv6 +diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c +index f7861dc83182..5ca207ada852 100644 +--- a/arch/arm/mm/fault.c ++++ b/arch/arm/mm/fault.c +@@ -163,6 +163,9 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr, + { + struct siginfo si; + ++ if (addr > TASK_SIZE) ++ harden_branch_predictor(); ++ + #ifdef CONFIG_DEBUG_USER + if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) || + ((user_debug & UDBG_BUS) && (sig == SIGBUS))) { +diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S +index 0d40c285bd86..7d9176c4a21d 100644 +--- a/arch/arm/mm/proc-macros.S ++++ b/arch/arm/mm/proc-macros.S +@@ -274,13 +274,14 @@ + mcr p15, 0, ip, c7, c10, 4 @ data write barrier + .endm + +-.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0 ++.macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0, bugs=0 + .type \name\()_processor_functions, #object + .align 2 + ENTRY(\name\()_processor_functions) + .word \dabort + .word \pabort + .word cpu_\name\()_proc_init ++ .word \bugs + .word cpu_\name\()_proc_fin + .word cpu_\name\()_reset + .word cpu_\name\()_do_idle +diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S +index c6141a5435c3..f8d45ad2a515 100644 +--- a/arch/arm/mm/proc-v7-2level.S ++++ b/arch/arm/mm/proc-v7-2level.S +@@ -41,11 +41,6 @@ + * even on Cortex-A8 revisions not affected by 430973. + * If IBE is not set, the flush BTAC/BTB won't do anything. + */ +-ENTRY(cpu_ca8_switch_mm) +-#ifdef CONFIG_MMU +- mov r2, #0 +- mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB +-#endif + ENTRY(cpu_v7_switch_mm) + #ifdef CONFIG_MMU + mmid r1, r1 @ get mm->context.id +@@ -66,7 +61,6 @@ ENTRY(cpu_v7_switch_mm) + #endif + bx lr + ENDPROC(cpu_v7_switch_mm) +-ENDPROC(cpu_ca8_switch_mm) + + /* + * cpu_v7_set_pte_ext(ptep, pte) +diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c +new file mode 100644 +index 000000000000..5544b82a2e7a +--- /dev/null ++++ b/arch/arm/mm/proc-v7-bugs.c +@@ -0,0 +1,174 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include <linux/arm-smccc.h> ++#include <linux/kernel.h> ++#include <linux/psci.h> ++#include <linux/smp.h> ++ ++#include <asm/cp15.h> ++#include <asm/cputype.h> ++#include <asm/proc-fns.h> ++#include <asm/system_misc.h> ++ ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++DEFINE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn); ++ ++extern void cpu_v7_iciallu_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); ++extern void cpu_v7_bpiall_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); ++extern void cpu_v7_smc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); ++extern void cpu_v7_hvc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm); ++ ++static void harden_branch_predictor_bpiall(void) ++{ ++ write_sysreg(0, BPIALL); ++} ++ ++static void harden_branch_predictor_iciallu(void) ++{ ++ write_sysreg(0, ICIALLU); ++} ++ ++static void __maybe_unused call_smc_arch_workaround_1(void) ++{ ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); ++} ++ ++static void __maybe_unused call_hvc_arch_workaround_1(void) ++{ ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); ++} ++ ++static void cpu_v7_spectre_init(void) ++{ ++ const char *spectre_v2_method = NULL; ++ int cpu = smp_processor_id(); ++ ++ if (per_cpu(harden_branch_predictor_fn, cpu)) ++ return; ++ ++ switch (read_cpuid_part()) { ++ case ARM_CPU_PART_CORTEX_A8: ++ case ARM_CPU_PART_CORTEX_A9: ++ case ARM_CPU_PART_CORTEX_A12: ++ case ARM_CPU_PART_CORTEX_A17: ++ case ARM_CPU_PART_CORTEX_A73: ++ case ARM_CPU_PART_CORTEX_A75: ++ if (processor.switch_mm != cpu_v7_bpiall_switch_mm) ++ goto bl_error; ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ harden_branch_predictor_bpiall; ++ spectre_v2_method = "BPIALL"; ++ break; ++ ++ case ARM_CPU_PART_CORTEX_A15: ++ case ARM_CPU_PART_BRAHMA_B15: ++ if (processor.switch_mm != cpu_v7_iciallu_switch_mm) ++ goto bl_error; ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ harden_branch_predictor_iciallu; ++ spectre_v2_method = "ICIALLU"; ++ break; ++ ++#ifdef CONFIG_ARM_PSCI ++ default: ++ /* Other ARM CPUs require no workaround */ ++ if (read_cpuid_implementor() == ARM_CPU_IMP_ARM) ++ break; ++ /* fallthrough */ ++ /* Cortex A57/A72 require firmware workaround */ ++ case ARM_CPU_PART_CORTEX_A57: ++ case ARM_CPU_PART_CORTEX_A72: { ++ struct arm_smccc_res res; ++ ++ if (psci_ops.smccc_version == SMCCC_VERSION_1_0) ++ break; ++ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_1, &res); ++ if ((int)res.a0 != 0) ++ break; ++ if (processor.switch_mm != cpu_v7_hvc_switch_mm && cpu) ++ goto bl_error; ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ call_hvc_arch_workaround_1; ++ processor.switch_mm = cpu_v7_hvc_switch_mm; ++ spectre_v2_method = "hypervisor"; ++ break; ++ ++ case PSCI_CONDUIT_SMC: ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_1, &res); ++ if ((int)res.a0 != 0) ++ break; ++ if (processor.switch_mm != cpu_v7_smc_switch_mm && cpu) ++ goto bl_error; ++ per_cpu(harden_branch_predictor_fn, cpu) = ++ call_smc_arch_workaround_1; ++ processor.switch_mm = cpu_v7_smc_switch_mm; ++ spectre_v2_method = "firmware"; ++ break; ++ ++ default: ++ break; ++ } ++ } ++#endif ++ } ++ ++ if (spectre_v2_method) ++ pr_info("CPU%u: Spectre v2: using %s workaround\n", ++ smp_processor_id(), spectre_v2_method); ++ return; ++ ++bl_error: ++ pr_err("CPU%u: Spectre v2: incorrect context switching function, system vulnerable\n", ++ cpu); ++} ++#else ++static void cpu_v7_spectre_init(void) ++{ ++} ++#endif ++ ++static __maybe_unused bool cpu_v7_check_auxcr_set(bool *warned, ++ u32 mask, const char *msg) ++{ ++ u32 aux_cr; ++ ++ asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (aux_cr)); ++ ++ if ((aux_cr & mask) != mask) { ++ if (!*warned) ++ pr_err("CPU%u: %s", smp_processor_id(), msg); ++ *warned = true; ++ return false; ++ } ++ return true; ++} ++ ++static DEFINE_PER_CPU(bool, spectre_warned); ++ ++static bool check_spectre_auxcr(bool *warned, u32 bit) ++{ ++ return IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR) && ++ cpu_v7_check_auxcr_set(warned, bit, ++ "Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable\n"); ++} ++ ++void cpu_v7_ca8_ibe(void) ++{ ++ if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(6))) ++ cpu_v7_spectre_init(); ++} ++ ++void cpu_v7_ca15_ibe(void) ++{ ++ if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(0))) ++ cpu_v7_spectre_init(); ++} ++ ++void cpu_v7_bugs_init(void) ++{ ++ cpu_v7_spectre_init(); ++} +diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S +index d00d52c9de3e..850c22bca19c 100644 +--- a/arch/arm/mm/proc-v7.S ++++ b/arch/arm/mm/proc-v7.S +@@ -9,6 +9,7 @@ + * + * This is the "shell" of the ARMv7 processor support. + */ ++#include <linux/arm-smccc.h> + #include <linux/init.h> + #include <linux/linkage.h> + #include <asm/assembler.h> +@@ -88,6 +89,37 @@ ENTRY(cpu_v7_dcache_clean_area) + ret lr + ENDPROC(cpu_v7_dcache_clean_area) + ++#ifdef CONFIG_ARM_PSCI ++ .arch_extension sec ++ENTRY(cpu_v7_smc_switch_mm) ++ stmfd sp!, {r0 - r3} ++ movw r0, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1 ++ movt r0, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1 ++ smc #0 ++ ldmfd sp!, {r0 - r3} ++ b cpu_v7_switch_mm ++ENDPROC(cpu_v7_smc_switch_mm) ++ .arch_extension virt ++ENTRY(cpu_v7_hvc_switch_mm) ++ stmfd sp!, {r0 - r3} ++ movw r0, #:lower16:ARM_SMCCC_ARCH_WORKAROUND_1 ++ movt r0, #:upper16:ARM_SMCCC_ARCH_WORKAROUND_1 ++ hvc #0 ++ ldmfd sp!, {r0 - r3} ++ b cpu_v7_switch_mm ++ENDPROC(cpu_v7_hvc_switch_mm) ++#endif ++ENTRY(cpu_v7_iciallu_switch_mm) ++ mov r3, #0 ++ mcr p15, 0, r3, c7, c5, 0 @ ICIALLU ++ b cpu_v7_switch_mm ++ENDPROC(cpu_v7_iciallu_switch_mm) ++ENTRY(cpu_v7_bpiall_switch_mm) ++ mov r3, #0 ++ mcr p15, 0, r3, c7, c5, 6 @ flush BTAC/BTB ++ b cpu_v7_switch_mm ++ENDPROC(cpu_v7_bpiall_switch_mm) ++ + string cpu_v7_name, "ARMv7 Processor" + .align + +@@ -153,31 +185,6 @@ ENTRY(cpu_v7_do_resume) + ENDPROC(cpu_v7_do_resume) + #endif + +-/* +- * Cortex-A8 +- */ +- globl_equ cpu_ca8_proc_init, cpu_v7_proc_init +- globl_equ cpu_ca8_proc_fin, cpu_v7_proc_fin +- globl_equ cpu_ca8_reset, cpu_v7_reset +- globl_equ cpu_ca8_do_idle, cpu_v7_do_idle +- globl_equ cpu_ca8_dcache_clean_area, cpu_v7_dcache_clean_area +- globl_equ cpu_ca8_set_pte_ext, cpu_v7_set_pte_ext +- globl_equ cpu_ca8_suspend_size, cpu_v7_suspend_size +-#ifdef CONFIG_ARM_CPU_SUSPEND +- globl_equ cpu_ca8_do_suspend, cpu_v7_do_suspend +- globl_equ cpu_ca8_do_resume, cpu_v7_do_resume +-#endif +- +-/* +- * Cortex-A9 processor functions +- */ +- globl_equ cpu_ca9mp_proc_init, cpu_v7_proc_init +- globl_equ cpu_ca9mp_proc_fin, cpu_v7_proc_fin +- globl_equ cpu_ca9mp_reset, cpu_v7_reset +- globl_equ cpu_ca9mp_do_idle, cpu_v7_do_idle +- globl_equ cpu_ca9mp_dcache_clean_area, cpu_v7_dcache_clean_area +- globl_equ cpu_ca9mp_switch_mm, cpu_v7_switch_mm +- globl_equ cpu_ca9mp_set_pte_ext, cpu_v7_set_pte_ext + .globl cpu_ca9mp_suspend_size + .equ cpu_ca9mp_suspend_size, cpu_v7_suspend_size + 4 * 2 + #ifdef CONFIG_ARM_CPU_SUSPEND +@@ -541,12 +548,79 @@ __v7_setup_stack: + + __INITDATA + ++ .weak cpu_v7_bugs_init ++ + @ define struct processor (see <asm/proc-fns.h> and proc-macros.S) +- define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 ++ define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init ++ ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ @ generic v7 bpiall on context switch ++ globl_equ cpu_v7_bpiall_proc_init, cpu_v7_proc_init ++ globl_equ cpu_v7_bpiall_proc_fin, cpu_v7_proc_fin ++ globl_equ cpu_v7_bpiall_reset, cpu_v7_reset ++ globl_equ cpu_v7_bpiall_do_idle, cpu_v7_do_idle ++ globl_equ cpu_v7_bpiall_dcache_clean_area, cpu_v7_dcache_clean_area ++ globl_equ cpu_v7_bpiall_set_pte_ext, cpu_v7_set_pte_ext ++ globl_equ cpu_v7_bpiall_suspend_size, cpu_v7_suspend_size ++#ifdef CONFIG_ARM_CPU_SUSPEND ++ globl_equ cpu_v7_bpiall_do_suspend, cpu_v7_do_suspend ++ globl_equ cpu_v7_bpiall_do_resume, cpu_v7_do_resume ++#endif ++ define_processor_functions v7_bpiall, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init ++ ++#define HARDENED_BPIALL_PROCESSOR_FUNCTIONS v7_bpiall_processor_functions ++#else ++#define HARDENED_BPIALL_PROCESSOR_FUNCTIONS v7_processor_functions ++#endif ++ + #ifndef CONFIG_ARM_LPAE +- define_processor_functions ca8, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 +- define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 ++ @ Cortex-A8 - always needs bpiall switch_mm implementation ++ globl_equ cpu_ca8_proc_init, cpu_v7_proc_init ++ globl_equ cpu_ca8_proc_fin, cpu_v7_proc_fin ++ globl_equ cpu_ca8_reset, cpu_v7_reset ++ globl_equ cpu_ca8_do_idle, cpu_v7_do_idle ++ globl_equ cpu_ca8_dcache_clean_area, cpu_v7_dcache_clean_area ++ globl_equ cpu_ca8_set_pte_ext, cpu_v7_set_pte_ext ++ globl_equ cpu_ca8_switch_mm, cpu_v7_bpiall_switch_mm ++ globl_equ cpu_ca8_suspend_size, cpu_v7_suspend_size ++#ifdef CONFIG_ARM_CPU_SUSPEND ++ globl_equ cpu_ca8_do_suspend, cpu_v7_do_suspend ++ globl_equ cpu_ca8_do_resume, cpu_v7_do_resume + #endif ++ define_processor_functions ca8, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_ca8_ibe ++ ++ @ Cortex-A9 - needs more registers preserved across suspend/resume ++ @ and bpiall switch_mm for hardening ++ globl_equ cpu_ca9mp_proc_init, cpu_v7_proc_init ++ globl_equ cpu_ca9mp_proc_fin, cpu_v7_proc_fin ++ globl_equ cpu_ca9mp_reset, cpu_v7_reset ++ globl_equ cpu_ca9mp_do_idle, cpu_v7_do_idle ++ globl_equ cpu_ca9mp_dcache_clean_area, cpu_v7_dcache_clean_area ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ globl_equ cpu_ca9mp_switch_mm, cpu_v7_bpiall_switch_mm ++#else ++ globl_equ cpu_ca9mp_switch_mm, cpu_v7_switch_mm ++#endif ++ globl_equ cpu_ca9mp_set_pte_ext, cpu_v7_set_pte_ext ++ define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_bugs_init ++#endif ++ ++ @ Cortex-A15 - needs iciallu switch_mm for hardening ++ globl_equ cpu_ca15_proc_init, cpu_v7_proc_init ++ globl_equ cpu_ca15_proc_fin, cpu_v7_proc_fin ++ globl_equ cpu_ca15_reset, cpu_v7_reset ++ globl_equ cpu_ca15_do_idle, cpu_v7_do_idle ++ globl_equ cpu_ca15_dcache_clean_area, cpu_v7_dcache_clean_area ++#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR ++ globl_equ cpu_ca15_switch_mm, cpu_v7_iciallu_switch_mm ++#else ++ globl_equ cpu_ca15_switch_mm, cpu_v7_switch_mm ++#endif ++ globl_equ cpu_ca15_set_pte_ext, cpu_v7_set_pte_ext ++ globl_equ cpu_ca15_suspend_size, cpu_v7_suspend_size ++ globl_equ cpu_ca15_do_suspend, cpu_v7_do_suspend ++ globl_equ cpu_ca15_do_resume, cpu_v7_do_resume ++ define_processor_functions ca15, dabort=v7_early_abort, pabort=v7_pabort, suspend=1, bugs=cpu_v7_ca15_ibe + #ifdef CONFIG_CPU_PJ4B + define_processor_functions pj4b, dabort=v7_early_abort, pabort=v7_pabort, suspend=1 + #endif +@@ -653,7 +727,7 @@ __v7_ca7mp_proc_info: + __v7_ca12mp_proc_info: + .long 0x410fc0d0 + .long 0xff0ffff0 +- __v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup ++ __v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup, proc_fns = HARDENED_BPIALL_PROCESSOR_FUNCTIONS + .size __v7_ca12mp_proc_info, . - __v7_ca12mp_proc_info + + /* +@@ -663,7 +737,7 @@ __v7_ca12mp_proc_info: + __v7_ca15mp_proc_info: + .long 0x410fc0f0 + .long 0xff0ffff0 +- __v7_proc __v7_ca15mp_proc_info, __v7_ca15mp_setup ++ __v7_proc __v7_ca15mp_proc_info, __v7_ca15mp_setup, proc_fns = ca15_processor_functions + .size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info + + /* +@@ -673,7 +747,7 @@ __v7_ca15mp_proc_info: + __v7_b15mp_proc_info: + .long 0x420f00f0 + .long 0xff0ffff0 +- __v7_proc __v7_b15mp_proc_info, __v7_b15mp_setup ++ __v7_proc __v7_b15mp_proc_info, __v7_b15mp_setup, proc_fns = ca15_processor_functions + .size __v7_b15mp_proc_info, . - __v7_b15mp_proc_info + + /* +@@ -683,9 +757,25 @@ __v7_b15mp_proc_info: + __v7_ca17mp_proc_info: + .long 0x410fc0e0 + .long 0xff0ffff0 +- __v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup ++ __v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup, proc_fns = HARDENED_BPIALL_PROCESSOR_FUNCTIONS + .size __v7_ca17mp_proc_info, . - __v7_ca17mp_proc_info + ++ /* ARM Ltd. Cortex A73 processor */ ++ .type __v7_ca73_proc_info, #object ++__v7_ca73_proc_info: ++ .long 0x410fd090 ++ .long 0xff0ffff0 ++ __v7_proc __v7_ca73_proc_info, __v7_setup, proc_fns = HARDENED_BPIALL_PROCESSOR_FUNCTIONS ++ .size __v7_ca73_proc_info, . - __v7_ca73_proc_info ++ ++ /* ARM Ltd. Cortex A75 processor */ ++ .type __v7_ca75_proc_info, #object ++__v7_ca75_proc_info: ++ .long 0x410fd0a0 ++ .long 0xff0ffff0 ++ __v7_proc __v7_ca75_proc_info, __v7_setup, proc_fns = HARDENED_BPIALL_PROCESSOR_FUNCTIONS ++ .size __v7_ca75_proc_info, . - __v7_ca75_proc_info ++ + /* + * Qualcomm Inc. Krait processors. + */ +diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c +index 5629d7580973..8e5e97989fda 100644 +--- a/arch/arm/vfp/vfpmodule.c ++++ b/arch/arm/vfp/vfpmodule.c +@@ -597,13 +597,11 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp, + } + + /* Sanitise and restore the current VFP state from the provided structures. */ +-int vfp_restore_user_hwstate(struct user_vfp __user *ufp, +- struct user_vfp_exc __user *ufp_exc) ++int vfp_restore_user_hwstate(struct user_vfp *ufp, struct user_vfp_exc *ufp_exc) + { + struct thread_info *thread = current_thread_info(); + struct vfp_hard_struct *hwstate = &thread->vfpstate.hard; + unsigned long fpexc; +- int err = 0; + + /* Disable VFP to avoid corrupting the new thread state. */ + vfp_flush_hwstate(thread); +@@ -612,17 +610,16 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, + * Copy the floating point registers. There can be unused + * registers see asm/hwcap.h for details. + */ +- err |= __copy_from_user(&hwstate->fpregs, &ufp->fpregs, +- sizeof(hwstate->fpregs)); ++ memcpy(&hwstate->fpregs, &ufp->fpregs, sizeof(hwstate->fpregs)); + /* + * Copy the status and control register. + */ +- __get_user_error(hwstate->fpscr, &ufp->fpscr, err); ++ hwstate->fpscr = ufp->fpscr; + + /* + * Sanitise and restore the exception registers. + */ +- __get_user_error(fpexc, &ufp_exc->fpexc, err); ++ fpexc = ufp_exc->fpexc; + + /* Ensure the VFP is enabled. */ + fpexc |= FPEXC_EN; +@@ -631,10 +628,10 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, + fpexc &= ~(FPEXC_EX | FPEXC_FP2V); + hwstate->fpexc = fpexc; + +- __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err); +- __get_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err); ++ hwstate->fpinst = ufp_exc->fpinst; ++ hwstate->fpinst2 = ufp_exc->fpinst2; + +- return err ? -EFAULT : 0; ++ return 0; + } + + /* +diff --git a/arch/arm64/crypto/sha1-ce-core.S b/arch/arm64/crypto/sha1-ce-core.S +index c98e7e849f06..8550408735a0 100644 +--- a/arch/arm64/crypto/sha1-ce-core.S ++++ b/arch/arm64/crypto/sha1-ce-core.S +@@ -82,7 +82,8 @@ ENTRY(sha1_ce_transform) + ldr dgb, [x0, #16] + + /* load sha1_ce_state::finalize */ +- ldr w4, [x0, #:lo12:sha1_ce_offsetof_finalize] ++ ldr_l w4, sha1_ce_offsetof_finalize, x4 ++ ldr w4, [x0, x4] + + /* load input */ + 0: ld1 {v8.4s-v11.4s}, [x1], #64 +@@ -132,7 +133,8 @@ CPU_LE( rev32 v11.16b, v11.16b ) + * the padding is handled by the C code in that case. + */ + cbz x4, 3f +- ldr x4, [x0, #:lo12:sha1_ce_offsetof_count] ++ ldr_l w4, sha1_ce_offsetof_count, x4 ++ ldr x4, [x0, x4] + movi v9.2d, #0 + mov x8, #0x80000000 + movi v10.2d, #0 +diff --git a/arch/arm64/crypto/sha1-ce-glue.c b/arch/arm64/crypto/sha1-ce-glue.c +index aefda9868627..ea319c055f5d 100644 +--- a/arch/arm64/crypto/sha1-ce-glue.c ++++ b/arch/arm64/crypto/sha1-ce-glue.c +@@ -17,9 +17,6 @@ + #include <linux/crypto.h> + #include <linux/module.h> + +-#define ASM_EXPORT(sym, val) \ +- asm(".globl " #sym "; .set " #sym ", %0" :: "I"(val)); +- + MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); + MODULE_AUTHOR("Ard Biesheuvel <ard.biesheu...@linaro.org>"); + MODULE_LICENSE("GPL v2"); +@@ -32,6 +29,9 @@ struct sha1_ce_state { + asmlinkage void sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src, + int blocks); + ++const u32 sha1_ce_offsetof_count = offsetof(struct sha1_ce_state, sst.count); ++const u32 sha1_ce_offsetof_finalize = offsetof(struct sha1_ce_state, finalize); ++ + static int sha1_ce_update(struct shash_desc *desc, const u8 *data, + unsigned int len) + { +@@ -52,11 +52,6 @@ static int sha1_ce_finup(struct shash_desc *desc, const u8 *data, + struct sha1_ce_state *sctx = shash_desc_ctx(desc); + bool finalize = !sctx->sst.count && !(len % SHA1_BLOCK_SIZE); + +- ASM_EXPORT(sha1_ce_offsetof_count, +- offsetof(struct sha1_ce_state, sst.count)); +- ASM_EXPORT(sha1_ce_offsetof_finalize, +- offsetof(struct sha1_ce_state, finalize)); +- + /* + * Allow the asm code to perform the finalization if there is no + * partial data and the input is a round multiple of the block size. +diff --git a/arch/arm64/crypto/sha2-ce-core.S b/arch/arm64/crypto/sha2-ce-core.S +index 01cfee066837..679c6c002f4f 100644 +--- a/arch/arm64/crypto/sha2-ce-core.S ++++ b/arch/arm64/crypto/sha2-ce-core.S +@@ -88,7 +88,8 @@ ENTRY(sha2_ce_transform) + ld1 {dgav.4s, dgbv.4s}, [x0] + + /* load sha256_ce_state::finalize */ +- ldr w4, [x0, #:lo12:sha256_ce_offsetof_finalize] ++ ldr_l w4, sha256_ce_offsetof_finalize, x4 ++ ldr w4, [x0, x4] + + /* load input */ + 0: ld1 {v16.4s-v19.4s}, [x1], #64 +@@ -136,7 +137,8 @@ CPU_LE( rev32 v19.16b, v19.16b ) + * the padding is handled by the C code in that case. + */ + cbz x4, 3f +- ldr x4, [x0, #:lo12:sha256_ce_offsetof_count] ++ ldr_l w4, sha256_ce_offsetof_count, x4 ++ ldr x4, [x0, x4] + movi v17.2d, #0 + mov x8, #0x80000000 + movi v18.2d, #0 +diff --git a/arch/arm64/crypto/sha2-ce-glue.c b/arch/arm64/crypto/sha2-ce-glue.c +index 7cd587564a41..0ed9486f75dd 100644 +--- a/arch/arm64/crypto/sha2-ce-glue.c ++++ b/arch/arm64/crypto/sha2-ce-glue.c +@@ -17,9 +17,6 @@ + #include <linux/crypto.h> + #include <linux/module.h> + +-#define ASM_EXPORT(sym, val) \ +- asm(".globl " #sym "; .set " #sym ", %0" :: "I"(val)); +- + MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions"); + MODULE_AUTHOR("Ard Biesheuvel <ard.biesheu...@linaro.org>"); + MODULE_LICENSE("GPL v2"); +@@ -32,6 +29,11 @@ struct sha256_ce_state { + asmlinkage void sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src, + int blocks); + ++const u32 sha256_ce_offsetof_count = offsetof(struct sha256_ce_state, ++ sst.count); ++const u32 sha256_ce_offsetof_finalize = offsetof(struct sha256_ce_state, ++ finalize); ++ + static int sha256_ce_update(struct shash_desc *desc, const u8 *data, + unsigned int len) + { +@@ -52,11 +54,6 @@ static int sha256_ce_finup(struct shash_desc *desc, const u8 *data, + struct sha256_ce_state *sctx = shash_desc_ctx(desc); + bool finalize = !sctx->sst.count && !(len % SHA256_BLOCK_SIZE); + +- ASM_EXPORT(sha256_ce_offsetof_count, +- offsetof(struct sha256_ce_state, sst.count)); +- ASM_EXPORT(sha256_ce_offsetof_finalize, +- offsetof(struct sha256_ce_state, finalize)); +- + /* + * Allow the asm code to perform the finalization if there is no + * partial data and the input is a round multiple of the block size. +diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h +index a9e54aad15ef..65615820155e 100644 +--- a/arch/arm64/include/asm/efi.h ++++ b/arch/arm64/include/asm/efi.h +@@ -54,6 +54,9 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); + #define alloc_screen_info(x...) &screen_info + #define free_screen_info(x...) + ++/* redeclare as 'hidden' so the compiler will generate relative references */ ++extern struct screen_info screen_info __attribute__((__visibility__("hidden"))); ++ + static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) + { + } +diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h +index 1d047d6c421b..f5cd96c60eb9 100644 +--- a/arch/arm64/include/asm/uaccess.h ++++ b/arch/arm64/include/asm/uaccess.h +@@ -198,7 +198,7 @@ do { \ + (err), ARM64_HAS_UAO); \ + break; \ + case 8: \ +- __get_user_asm("ldr", "ldtr", "%", __gu_val, (ptr), \ ++ __get_user_asm("ldr", "ldtr", "%x", __gu_val, (ptr), \ + (err), ARM64_HAS_UAO); \ + break; \ + default: \ +@@ -272,7 +272,7 @@ do { \ + (err), ARM64_HAS_UAO); \ + break; \ + case 8: \ +- __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \ ++ __put_user_asm("str", "sttr", "%x", __pu_val, (ptr), \ + (err), ARM64_HAS_UAO); \ + break; \ + default: \ +diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile +index 3686d6abafde..9edda5466020 100644 +--- a/arch/ia64/kernel/Makefile ++++ b/arch/ia64/kernel/Makefile +@@ -50,32 +50,10 @@ CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31 + # The gate DSO image is built using a special linker script. + include $(src)/Makefile.gate + +-# Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config +-define sed-y +- "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}" +-endef +-quiet_cmd_nr_irqs = GEN $@ +-define cmd_nr_irqs +- (set -e; \ +- echo "#ifndef __ASM_NR_IRQS_H__"; \ +- echo "#define __ASM_NR_IRQS_H__"; \ +- echo "/*"; \ +- echo " * DO NOT MODIFY."; \ +- echo " *"; \ +- echo " * This file was generated by Kbuild"; \ +- echo " *"; \ +- echo " */"; \ +- echo ""; \ +- sed -ne $(sed-y) $<; \ +- echo ""; \ +- echo "#endif" ) > $@ +-endef +- + # We use internal kbuild rules to avoid the "is up to date" message from make + arch/$(SRCARCH)/kernel/nr-irqs.s: arch/$(SRCARCH)/kernel/nr-irqs.c + $(Q)mkdir -p $(dir $@) + $(call if_changed_dep,cc_s_c) + +-include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s +- $(Q)mkdir -p $(dir $@) +- $(call cmd,nr_irqs) ++include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s FORCE ++ $(call filechk,offsets,__ASM_NR_IRQS_H__) +diff --git a/arch/x86/Makefile b/arch/x86/Makefile +index f408babdf746..b5226a009973 100644 +--- a/arch/x86/Makefile ++++ b/arch/x86/Makefile +@@ -11,6 +11,16 @@ else + KBUILD_DEFCONFIG := $(ARCH)_defconfig + endif + ++# For gcc stack alignment is specified with -mpreferred-stack-boundary, ++# clang has the option -mstack-alignment for that purpose. ++ifneq ($(call cc-option, -mpreferred-stack-boundary=4),) ++ cc_stack_align4 := -mpreferred-stack-boundary=2 ++ cc_stack_align8 := -mpreferred-stack-boundary=3 ++else ifneq ($(call cc-option, -mstack-alignment=16),) ++ cc_stack_align4 := -mstack-alignment=4 ++ cc_stack_align8 := -mstack-alignment=8 ++endif ++ + # How to compile the 16-bit code. Note we always compile for -march=i386; + # that way we can complain to the user if the CPU is insufficient. + # +@@ -24,10 +34,11 @@ REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -D__KERNEL__ \ + -DDISABLE_BRANCH_PROFILING \ + -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ + -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ +- -mno-mmx -mno-sse \ +- $(call cc-option, -ffreestanding) \ +- $(call cc-option, -fno-stack-protector) \ +- $(call cc-option, -mpreferred-stack-boundary=2) ++ -mno-mmx -mno-sse ++ ++REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding) ++REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector) ++REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4)) + export REALMODE_CFLAGS + + # BITS is used as extension for files which are available in a 32 bit +@@ -64,8 +75,10 @@ ifeq ($(CONFIG_X86_32),y) + # with nonstandard options + KBUILD_CFLAGS += -fno-pic + +- # prevent gcc from keeping the stack 16 byte aligned +- KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) ++ # Align the stack to the register width instead of using the default ++ # alignment of 16 bytes. This reduces stack usage and the number of ++ # alignment instructions. ++ KBUILD_CFLAGS += $(call cc-option,$(cc_stack_align4)) + + # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use + # a lot more stack due to the lack of sharing of stacklots: +@@ -88,17 +101,23 @@ else + KBUILD_CFLAGS += -m64 + + # Align jump targets to 1 byte, not the default 16 bytes: +- KBUILD_CFLAGS += -falign-jumps=1 ++ KBUILD_CFLAGS += $(call cc-option,-falign-jumps=1) + + # Pack loops tightly as well: +- KBUILD_CFLAGS += -falign-loops=1 ++ KBUILD_CFLAGS += $(call cc-option,-falign-loops=1) + + # Don't autogenerate traditional x87 instructions + KBUILD_CFLAGS += $(call cc-option,-mno-80387) + KBUILD_CFLAGS += $(call cc-option,-mno-fp-ret-in-387) + +- # Use -mpreferred-stack-boundary=3 if supported. +- KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3) ++ # By default gcc and clang use a stack alignment of 16 bytes for x86. ++ # However the standard kernel entry on x86-64 leaves the stack on an ++ # 8-byte boundary. If the compiler isn't informed about the actual ++ # alignment it will generate extra alignment instructions for the ++ # default alignment which keep the stack *mis*aligned. ++ # Furthermore an alignment to the register width reduces stack usage ++ # and the number of alignment instructions. ++ KBUILD_CFLAGS += $(call cc-option,$(cc_stack_align8)) + + # Use -mskip-rax-setup if supported. + KBUILD_CFLAGS += $(call cc-option,-mskip-rax-setup) +diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c +index 9e240fcba784..08dfce02362c 100644 +--- a/arch/x86/boot/string.c ++++ b/arch/x86/boot/string.c +@@ -16,6 +16,15 @@ + #include "ctype.h" + #include "string.h" + ++/* ++ * Undef these macros so that the functions that we provide ++ * here will have the correct names regardless of how string.h ++ * may have chosen to #define them. ++ */ ++#undef memcpy ++#undef memset ++#undef memcmp ++ + int memcmp(const void *s1, const void *s2, size_t len) + { + bool diff; +diff --git a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S +index a916c4a61165..5f6a5af9c489 100644 +--- a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S ++++ b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S +@@ -65,7 +65,6 @@ + #include <linux/linkage.h> + #include <asm/inst.h> + +-#define CONCAT(a,b) a##b + #define VMOVDQ vmovdqu + + #define xdata0 %xmm0 +@@ -92,8 +91,6 @@ + #define num_bytes %r8 + + #define tmp %r10 +-#define DDQ(i) CONCAT(ddq_add_,i) +-#define XMM(i) CONCAT(%xmm, i) + #define DDQ_DATA 0 + #define XDATA 1 + #define KEY_128 1 +@@ -131,12 +128,12 @@ ddq_add_8: + /* generate a unique variable for ddq_add_x */ + + .macro setddq n +- var_ddq_add = DDQ(\n) ++ var_ddq_add = ddq_add_\n + .endm + + /* generate a unique variable for xmm register */ + .macro setxdata n +- var_xdata = XMM(\n) ++ var_xdata = %xmm\n + .endm + + /* club the numeric 'id' to the symbol 'name' */ +diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile +index 5e23e2d305e7..2cd9496eb696 100644 +--- a/drivers/firmware/efi/libstub/Makefile ++++ b/drivers/firmware/efi/libstub/Makefile +@@ -10,8 +10,8 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ + -fPIC -fno-strict-aliasing -mno-red-zone \ + -mno-mmx -mno-sse + +-cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) +-cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) -g0 \ ++cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) -fpie ++cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \ + -fno-builtin -fpic -mno-single-pic-base + + cflags-$(CONFIG_EFI_ARMSTUB) += -I$(srctree)/scripts/dtc/libfdt +@@ -60,7 +60,7 @@ CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) + extra-$(CONFIG_EFI_ARMSTUB) := $(lib-y) + lib-$(CONFIG_EFI_ARMSTUB) := $(patsubst %.o,%.stub.o,$(lib-y)) + +-STUBCOPY_FLAGS-y := -R .debug* -R *ksymtab* -R *kcrctab* ++STUBCOPY_RM-y := -R *ksymtab* -R *kcrctab* + STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \ + --prefix-symbols=__efistub_ + STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS +@@ -68,17 +68,25 @@ STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS + $(obj)/%.stub.o: $(obj)/%.o FORCE + $(call if_changed,stubcopy) + ++# ++# Strip debug sections and some other sections that may legally contain ++# absolute relocations, so that we can inspect the remaining sections for ++# such relocations. If none are found, regenerate the output object, but ++# this time, use objcopy and leave all sections in place. ++# + quiet_cmd_stubcopy = STUBCPY $@ +- cmd_stubcopy = if $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; then \ +- $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y) \ +- && (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ +- rm -f $@; /bin/false); else /bin/false; fi ++ cmd_stubcopy = if $(STRIP) --strip-debug $(STUBCOPY_RM-y) -o $@ $<; \ ++ then if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); \ ++ then (echo >&2 "$@: absolute symbol references not allowed in the EFI stub"; \ ++ rm -f $@; /bin/false); \ ++ else $(OBJCOPY) $(STUBCOPY_FLAGS-y) $< $@; fi \ ++ else /bin/false; fi + + # + # ARM discards the .data section because it disallows r/w data in the + # decompressor. So move our .data to .data.efistub, which is preserved + # explicitly by the decompressor linker script. + # +-STUBCOPY_FLAGS-$(CONFIG_ARM) += --rename-section .data=.data.efistub \ +- -R ___ksymtab+sort -R ___kcrctab+sort ++STUBCOPY_FLAGS-$(CONFIG_ARM) += --rename-section .data=.data.efistub ++STUBCOPY_RM-$(CONFIG_ARM) += -R ___ksymtab+sort -R ___kcrctab+sort + STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS +diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c +index eae693eb3e91..959d9b8d4845 100644 +--- a/drivers/firmware/efi/libstub/arm64-stub.c ++++ b/drivers/firmware/efi/libstub/arm64-stub.c +@@ -9,9 +9,17 @@ + * published by the Free Software Foundation. + * + */ ++ ++/* ++ * To prevent the compiler from emitting GOT-indirected (and thus absolute) ++ * references to the section markers, override their visibility as 'hidden' ++ */ ++#pragma GCC visibility push(hidden) ++#include <asm/sections.h> ++#pragma GCC visibility pop ++ + #include <linux/efi.h> + #include <asm/efi.h> +-#include <asm/sections.h> + #include <asm/sysreg.h> + + #include "efistub.h" +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 6250989c83d8..c069a04a6e7e 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -12389,6 +12389,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e + { + struct tg3 *tp = netdev_priv(dev); + int i, irq_sync = 0, err = 0; ++ bool reset_phy = false; + + if ((ering->rx_pending > tp->rx_std_ring_mask) || + (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) || +@@ -12420,7 +12421,13 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e + + if (netif_running(dev)) { + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); +- err = tg3_restart_hw(tp, false); ++ /* Reset PHY to avoid PHY lock up */ ++ if (tg3_asic_rev(tp) == ASIC_REV_5717 || ++ tg3_asic_rev(tp) == ASIC_REV_5719 || ++ tg3_asic_rev(tp) == ASIC_REV_5720) ++ reset_phy = true; ++ ++ err = tg3_restart_hw(tp, reset_phy); + if (!err) + tg3_netif_start(tp); + } +@@ -12454,6 +12461,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam + { + struct tg3 *tp = netdev_priv(dev); + int err = 0; ++ bool reset_phy = false; + + if (tp->link_config.autoneg == AUTONEG_ENABLE) + tg3_warn_mgmt_link_flap(tp); +@@ -12544,7 +12552,13 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam + + if (netif_running(dev)) { + tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); +- err = tg3_restart_hw(tp, false); ++ /* Reset PHY to avoid PHY lock up */ ++ if (tg3_asic_rev(tp) == ASIC_REV_5717 || ++ tg3_asic_rev(tp) == ASIC_REV_5719 || ++ tg3_asic_rev(tp) == ASIC_REV_5720) ++ reset_phy = true; ++ ++ err = tg3_restart_hw(tp, reset_phy); + if (!err) + tg3_netif_start(tp); + } +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index a167116ceeee..e29f4c0767eb 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -1590,6 +1590,8 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message) + return ret; + } + ++ cancel_delayed_work_sync(&pdata->carrier_check); ++ + if (pdata->suspend_flags) { + netdev_warn(dev->net, "error during last resume\n"); + pdata->suspend_flags = 0; +@@ -1832,6 +1834,11 @@ done: + */ + if (ret && PMSG_IS_AUTO(message)) + usbnet_resume(intf); ++ ++ if (ret) ++ schedule_delayed_work(&pdata->carrier_check, ++ CARRIER_CHECK_DELAY); ++ + return ret; + } + +diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile +index 8feab810aed9..7f188b8d0c67 100644 +--- a/drivers/xen/Makefile ++++ b/drivers/xen/Makefile +@@ -7,9 +7,6 @@ obj-y += xenbus/ + nostackp := $(call cc-option, -fno-stack-protector) + CFLAGS_features.o := $(nostackp) + +-CFLAGS_efi.o += -fshort-wchar +-LDFLAGS += $(call ld-option, --no-wchar-size-warning) +- + dom0-$(CONFIG_ARM64) += arm-device.o + dom0-$(CONFIG_PCI) += pci.o + dom0-$(CONFIG_USB_SUPPORT) += dbgp.o +diff --git a/include/linux/kbuild.h b/include/linux/kbuild.h +index 22a72198c14b..4e80f3a9ad58 100644 +--- a/include/linux/kbuild.h ++++ b/include/linux/kbuild.h +@@ -2,14 +2,14 @@ + #define __LINUX_KBUILD_H + + #define DEFINE(sym, val) \ +- asm volatile("\n->" #sym " %0 " #val : : "i" (val)) ++ asm volatile("\n.ascii \"->" #sym " %0 " #val "\"" : : "i" (val)) + +-#define BLANK() asm volatile("\n->" : : ) ++#define BLANK() asm volatile("\n.ascii \"->\"" : : ) + + #define OFFSET(sym, str, mem) \ + DEFINE(sym, offsetof(struct str, mem)) + + #define COMMENT(x) \ +- asm volatile("\n->#" x) ++ asm volatile("\n.ascii \"->#" x "\"") + + #endif +diff --git a/include/linux/module.h b/include/linux/module.h +index d2224a09b4b5..fd9e121c7b3f 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -127,13 +127,13 @@ extern void cleanup_module(void); + + /* Each module must use one module_init(). */ + #define module_init(initfn) \ +- static inline initcall_t __inittest(void) \ ++ static inline initcall_t __maybe_unused __inittest(void) \ + { return initfn; } \ + int init_module(void) __attribute__((alias(#initfn))); + + /* This is only required if you want to be unloadable. */ + #define module_exit(exitfn) \ +- static inline exitcall_t __exittest(void) \ ++ static inline exitcall_t __maybe_unused __exittest(void) \ + { return exitfn; } \ + void cleanup_module(void) __attribute__((alias(#exitfn))); + +diff --git a/net/core/dev.c b/net/core/dev.c +index 15e3bb94156b..071c589f7994 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4756,6 +4756,10 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) + skb->vlan_tci = 0; + skb->dev = napi->dev; + skb->skb_iif = 0; ++ ++ /* eth_type_trans() assumes pkt_type is PACKET_HOST */ ++ skb->pkt_type = PACKET_HOST; ++ + skb->encapsulation = 0; + skb_shinfo(skb)->gso_type = 0; + skb->truesize = SKB_TRUESIZE(skb_end_offset(skb)); +diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index 862d63ec56e4..ab7c50026cae 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -538,8 +538,8 @@ ip_proto_again: + break; + } + +- if (dissector_uses_key(flow_dissector, +- FLOW_DISSECTOR_KEY_PORTS)) { ++ if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_PORTS) && ++ !(key_control->flags & FLOW_DIS_IS_FRAGMENT)) { + key_ports = skb_flow_dissector_target(flow_dissector, + FLOW_DISSECTOR_KEY_PORTS, + target_container); +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index 8323d33c0ce2..5a8c26c9872d 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -180,21 +180,22 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, + } + + static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, +- void *arg) ++ void *arg, ++ struct inet_frag_queue **prev) + { + struct inet_frags *f = nf->f; + struct inet_frag_queue *q; +- int err; + + q = inet_frag_alloc(nf, f, arg); +- if (!q) ++ if (!q) { ++ *prev = ERR_PTR(-ENOMEM); + return NULL; +- ++ } + mod_timer(&q->timer, jiffies + nf->timeout); + +- err = rhashtable_insert_fast(&nf->rhashtable, &q->node, +- f->rhash_params); +- if (err < 0) { ++ *prev = rhashtable_lookup_get_insert_key(&nf->rhashtable, &q->key, ++ &q->node, f->rhash_params); ++ if (*prev) { + q->flags |= INET_FRAG_COMPLETE; + inet_frag_kill(q); + inet_frag_destroy(q); +@@ -207,17 +208,18 @@ EXPORT_SYMBOL(inet_frag_create); + /* TODO : call from rcu_read_lock() and no longer use refcount_inc_not_zero() */ + struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key) + { +- struct inet_frag_queue *fq; ++ struct inet_frag_queue *fq = NULL, *prev; + + rcu_read_lock(); +- fq = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params); +- if (fq) { ++ prev = rhashtable_lookup(&nf->rhashtable, key, nf->f->rhash_params); ++ if (!prev) ++ fq = inet_frag_create(nf, key, &prev); ++ if (prev && !IS_ERR(prev)) { ++ fq = prev; + if (!atomic_inc_not_zero(&fq->refcnt)) + fq = NULL; +- rcu_read_unlock(); +- return fq; + } + rcu_read_unlock(); +- return inet_frag_create(nf, key); ++ return fq; + } + EXPORT_SYMBOL(inet_frag_find); +diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c +index 0fd1976ab63b..2220a1b396af 100644 +--- a/net/ipv4/ip_tunnel_core.c ++++ b/net/ipv4/ip_tunnel_core.c +@@ -80,7 +80,7 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, + + iph->version = 4; + iph->ihl = sizeof(struct iphdr) >> 2; +- iph->frag_off = df; ++ iph->frag_off = ip_mtu_locked(&rt->dst) ? 0 : df; + iph->protocol = proto; + iph->tos = tos; + iph->daddr = dst; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 4cc12eeca7ab..0db120d2a4fe 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1439,10 +1439,13 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu); + + void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) + { ++ int oif = sk->sk_bound_dev_if; + struct dst_entry *dst; + +- ip6_update_pmtu(skb, sock_net(sk), mtu, +- sk->sk_bound_dev_if, sk->sk_mark); ++ if (!oif && skb->dev) ++ oif = l3mdev_master_ifindex(skb->dev); ++ ++ ip6_update_pmtu(skb, sock_net(sk), mtu, oif, sk->sk_mark); + + dst = __sk_dst_get(sk); + if (!dst || !dst->obsolete || +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 9827ba4b9f74..93e60068800b 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -3732,32 +3732,16 @@ static int sctp_setsockopt_pr_supported(struct sock *sk, + unsigned int optlen) + { + struct sctp_assoc_value params; +- struct sctp_association *asoc; +- int retval = -EINVAL; + + if (optlen != sizeof(params)) +- goto out; +- +- if (copy_from_user(¶ms, optval, optlen)) { +- retval = -EFAULT; +- goto out; +- } +- +- asoc = sctp_id2assoc(sk, params.assoc_id); +- if (asoc) { +- asoc->prsctp_enable = !!params.assoc_value; +- } else if (!params.assoc_id) { +- struct sctp_sock *sp = sctp_sk(sk); ++ return -EINVAL; + +- sp->ep->prsctp_enable = !!params.assoc_value; +- } else { +- goto out; +- } ++ if (copy_from_user(¶ms, optval, optlen)) ++ return -EFAULT; + +- retval = 0; ++ sctp_sk(sk)->ep->prsctp_enable = !!params.assoc_value; + +-out: +- return retval; ++ return 0; + } + + static int sctp_setsockopt_default_prinfo(struct sock *sk, +diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include +index 8f8965608ee3..123840d827e8 100644 +--- a/scripts/Kbuild.include ++++ b/scripts/Kbuild.include +@@ -109,6 +109,11 @@ as-option = $(call try-run,\ + as-instr = $(call try-run,\ + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3)) + ++# __cc-option ++# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586) ++__cc-option = $(call try-run,\ ++ $(1) -Werror $(2) $(3) -c -x c /dev/null -o "$$TMP",$(3),$(4)) ++ + # Do not attempt to build with gcc plugins during cc-option tests. + # (And this uses delayed resolution so the flags will be up to date.) + CC_OPTION_CFLAGS = $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) +@@ -116,13 +121,18 @@ CC_OPTION_CFLAGS = $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) + # cc-option + # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) + +-cc-option = $(call try-run,\ +- $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) ++cc-option = $(call __cc-option, $(CC),\ ++ $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS),$(1),$(2)) ++ ++# hostcc-option ++# Usage: cflags-y += $(call hostcc-option,-march=winchip-c6,-march=i586) ++hostcc-option = $(call __cc-option, $(HOSTCC),\ ++ $(HOSTCFLAGS) $(HOST_EXTRACFLAGS),$(1),$(2)) + + # cc-option-yn + # Usage: flag := $(call cc-option-yn,-march=winchip-c6) + cc-option-yn = $(call try-run,\ +- $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) ++ $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) + + # cc-option-align + # Prefix align with either -falign or -malign +@@ -132,7 +142,7 @@ cc-option-align = $(subst -functions=0,,\ + # cc-disable-warning + # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) + cc-disable-warning = $(call try-run,\ +- $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) ++ $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) + + # cc-name + # Expands to either gcc or clang +diff --git a/scripts/Makefile.build b/scripts/Makefile.build +index abfd4f4b66dd..6228a83156ea 100644 +--- a/scripts/Makefile.build ++++ b/scripts/Makefile.build +@@ -176,6 +176,14 @@ cmd_cc_symtypes_c = \ + $(obj)/%.symtypes : $(src)/%.c FORCE + $(call cmd,cc_symtypes_c) + ++# LLVM assembly ++# Generate .ll files from .c ++quiet_cmd_cc_ll_c = CC $(quiet_modtag) $@ ++ cmd_cc_ll_c = $(CC) $(c_flags) -emit-llvm -S -o $@ $< ++ ++$(obj)/%.ll: $(src)/%.c FORCE ++ $(call if_changed_dep,cc_ll_c) ++ + # C (.c) files + # The C file is compiled and updated dependency information is generated. + # (See cmd_cc_o_c + relevant part of rule_cc_o_c) +diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn +index 7c321a603b07..fb3522fd8702 100644 +--- a/scripts/Makefile.extrawarn ++++ b/scripts/Makefile.extrawarn +@@ -64,7 +64,6 @@ ifeq ($(cc-name),clang) + KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides) + KBUILD_CFLAGS += $(call cc-disable-warning, unused-value) + KBUILD_CFLAGS += $(call cc-disable-warning, format) +-KBUILD_CFLAGS += $(call cc-disable-warning, unknown-warning-option) + KBUILD_CFLAGS += $(call cc-disable-warning, sign-compare) + KBUILD_CFLAGS += $(call cc-disable-warning, format-zero-length) + KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized) +diff --git a/scripts/Makefile.host b/scripts/Makefile.host +index 45b5b1aaedbd..9cfd5c84d76f 100644 +--- a/scripts/Makefile.host ++++ b/scripts/Makefile.host +@@ -20,12 +20,6 @@ + # Will compile qconf as a C++ program, and menu as a C program. + # They are linked as C++ code to the executable qconf + +-# hostcc-option +-# Usage: cflags-y += $(call hostcc-option,-march=winchip-c6,-march=i586) +- +-hostcc-option = $(call try-run,\ +- $(HOSTCC) $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) +- + __hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) + host-cshlib := $(sort $(hostlibs-y) $(hostlibs-m)) + host-cxxshlib := $(sort $(hostcxxlibs-y) $(hostcxxlibs-m)) +diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib +index c954040c3cf2..4e02d51dfc62 100644 +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -408,3 +408,34 @@ quiet_cmd_xzmisc = XZMISC $@ + cmd_xzmisc = (cat $(filter-out FORCE,$^) | \ + xz --check=crc32 --lzma2=dict=1MiB) > $@ || \ + (rm -f $@ ; false) ++ ++# ASM offsets ++# --------------------------------------------------------------------------- ++ ++# Default sed regexp - multiline due to syntax constraints ++# ++# Use [:space:] because LLVM's integrated assembler inserts <tab> around ++# the .ascii directive whereas GCC keeps the <space> as-is. ++define sed-offsets ++ 's:^[[:space:]]*\.ascii[[:space:]]*"\(.*\)".*:\1:; \ ++ /^->/{s:->#\(.*\):/* \1 */:; \ ++ s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ ++ s:->::; p;}' ++endef ++ ++# Use filechk to avoid rebuilds when a header changes, but the resulting file ++# does not ++define filechk_offsets ++ (set -e; \ ++ echo "#ifndef $2"; \ ++ echo "#define $2"; \ ++ echo "/*"; \ ++ echo " * DO NOT MODIFY."; \ ++ echo " *"; \ ++ echo " * This file was generated by Kbuild"; \ ++ echo " */"; \ ++ echo ""; \ ++ sed -ne $(sed-offsets); \ ++ echo ""; \ ++ echo "#endif" ) ++endef +diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile +index 19d9bcadc0cc..b497d9764dcf 100644 +--- a/scripts/mod/Makefile ++++ b/scripts/mod/Makefile +@@ -7,32 +7,8 @@ modpost-objs := modpost.o file2alias.o sumversion.o + + devicetable-offsets-file := devicetable-offsets.h + +-define sed-y +- "/^->/{s:->#\(.*\):/* \1 */:; \ +- s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \ +- s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ +- s:->::; p;}" +-endef +- +-quiet_cmd_offsets = GEN $@ +-define cmd_offsets +- (set -e; \ +- echo "#ifndef __DEVICETABLE_OFFSETS_H__"; \ +- echo "#define __DEVICETABLE_OFFSETS_H__"; \ +- echo "/*"; \ +- echo " * DO NOT MODIFY."; \ +- echo " *"; \ +- echo " * This file was generated by Kbuild"; \ +- echo " *"; \ +- echo " */"; \ +- echo ""; \ +- sed -ne $(sed-y) $<; \ +- echo ""; \ +- echo "#endif" ) > $@ +-endef +- +-$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s +- $(call if_changed,offsets) ++$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s FORCE ++ $(call filechk,offsets,__DEVICETABLE_OFFSETS_H__) + + targets += $(devicetable-offsets-file) devicetable-offsets.s +