commit: 7c645b2dad257213648257512db2a21941a4b19f Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Sun Jul 22 15:14:32 2018 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Sun Jul 22 15:14:32 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=7c645b2d
Linux patch 4.9.114 0000_README | 4 + 1113_linux-4.9.114.patch | 3269 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3273 insertions(+) diff --git a/0000_README b/0000_README index 9efde71..c3aaa60 100644 --- a/0000_README +++ b/0000_README @@ -495,6 +495,10 @@ Patch: 1112_linux-4.9.113.patch From: http://www.kernel.org Desc: Linux 4.9.113 +Patch: 1113_linux-4.9.114.patch +From: http://www.kernel.org +Desc: Linux 4.9.114 + 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/1113_linux-4.9.114.patch b/1113_linux-4.9.114.patch new file mode 100644 index 0000000..995ed5f --- /dev/null +++ b/1113_linux-4.9.114.patch @@ -0,0 +1,3269 @@ +diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt +index 52240a63132e..a16f87e4dd10 100644 +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -4023,6 +4023,23 @@ bytes respectively. Such letter suffixes can also be entirely omitted. + spia_pedr= + spia_peddr= + ++ ssbd= [ARM64,HW] ++ Speculative Store Bypass Disable control ++ ++ On CPUs that are vulnerable to the Speculative ++ Store Bypass vulnerability and offer a ++ firmware based mitigation, this parameter ++ indicates how the mitigation should be used: ++ ++ force-on: Unconditionally enable mitigation for ++ for both kernel and userspace ++ force-off: Unconditionally disable mitigation for ++ for both kernel and userspace ++ kernel: Always enable mitigation in the ++ kernel, and offer a prctl interface ++ to allow userspace to register its ++ interest in being mitigated too. ++ + stack_guard_gap= [MM] + override the default stack gap protection. The value + is in page units and it defines how many pages prior +diff --git a/Makefile b/Makefile +index 3884afb2850f..f4cd42c9b940 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 113 ++SUBLEVEL = 114 + EXTRAVERSION = + NAME = Roaring Lionus + +diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h +index f4dab20ac9f3..0833d8a1dbbb 100644 +--- a/arch/arm/include/asm/kvm_host.h ++++ b/arch/arm/include/asm/kvm_host.h +@@ -327,4 +327,16 @@ static inline bool kvm_arm_harden_branch_predictor(void) + return false; + } + ++#define KVM_SSBD_UNKNOWN -1 ++#define KVM_SSBD_FORCE_DISABLE 0 ++#define KVM_SSBD_KERNEL 1 ++#define KVM_SSBD_FORCE_ENABLE 2 ++#define KVM_SSBD_MITIGATED 3 ++ ++static inline int kvm_arm_have_ssbd(void) ++{ ++ /* No way to detect it yet, pretend it is not there. */ ++ return KVM_SSBD_UNKNOWN; ++} ++ + #endif /* __ARM_KVM_HOST_H__ */ +diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h +index 7f66b1b3aca1..e2f05cedaf97 100644 +--- a/arch/arm/include/asm/kvm_mmu.h ++++ b/arch/arm/include/asm/kvm_mmu.h +@@ -28,6 +28,13 @@ + */ + #define kern_hyp_va(kva) (kva) + ++/* Contrary to arm64, there is no need to generate a PC-relative address */ ++#define hyp_symbol_addr(s) \ ++ ({ \ ++ typeof(s) *addr = &(s); \ ++ addr; \ ++ }) ++ + /* + * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation levels. + */ +@@ -249,6 +256,11 @@ static inline int kvm_map_vectors(void) + return 0; + } + ++static inline int hyp_map_aux_data(void) ++{ ++ return 0; ++} ++ + #endif /* !__ASSEMBLY__ */ + + #endif /* __ARM_KVM_MMU_H__ */ +diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c +index ef6595c7d697..20436972537f 100644 +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -51,8 +51,8 @@ + __asm__(".arch_extension virt"); + #endif + ++DEFINE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state); + static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); +-static kvm_cpu_context_t __percpu *kvm_host_cpu_state; + static unsigned long hyp_default_vectors; + + /* Per-CPU variable containing the currently running vcpu. */ +@@ -338,7 +338,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) + } + + vcpu->cpu = cpu; +- vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); ++ vcpu->arch.host_cpu_context = this_cpu_ptr(&kvm_host_cpu_state); + + kvm_arm_set_running_vcpu(vcpu); + } +@@ -1199,19 +1199,8 @@ static inline void hyp_cpu_pm_exit(void) + } + #endif + +-static void teardown_common_resources(void) +-{ +- free_percpu(kvm_host_cpu_state); +-} +- + static int init_common_resources(void) + { +- kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t); +- if (!kvm_host_cpu_state) { +- kvm_err("Cannot allocate host CPU state\n"); +- return -ENOMEM; +- } +- + /* set size of VMID supported by CPU */ + kvm_vmid_bits = kvm_get_vmid_bits(); + kvm_info("%d-bit VMID\n", kvm_vmid_bits); +@@ -1369,7 +1358,7 @@ static int init_hyp_mode(void) + for_each_possible_cpu(cpu) { + kvm_cpu_context_t *cpu_ctxt; + +- cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu); ++ cpu_ctxt = per_cpu_ptr(&kvm_host_cpu_state, cpu); + err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1, PAGE_HYP); + + if (err) { +@@ -1378,6 +1367,12 @@ static int init_hyp_mode(void) + } + } + ++ err = hyp_map_aux_data(); ++ if (err) { ++ kvm_err("Cannot map host auxilary data: %d\n", err); ++ goto out_err; ++ } ++ + kvm_info("Hyp mode initialized successfully\n"); + + return 0; +@@ -1447,7 +1442,6 @@ int kvm_arch_init(void *opaque) + out_hyp: + teardown_hyp_mode(); + out_err: +- teardown_common_resources(); + return err; + } + +diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c +index 8a9c654f4f87..83365bec04b6 100644 +--- a/arch/arm/kvm/psci.c ++++ b/arch/arm/kvm/psci.c +@@ -403,7 +403,7 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu) + int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) + { + u32 func_id = smccc_get_function(vcpu); +- u32 val = PSCI_RET_NOT_SUPPORTED; ++ u32 val = SMCCC_RET_NOT_SUPPORTED; + u32 feature; + + switch (func_id) { +@@ -415,7 +415,21 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) + switch(feature) { + case ARM_SMCCC_ARCH_WORKAROUND_1: + if (kvm_arm_harden_branch_predictor()) +- val = 0; ++ val = SMCCC_RET_SUCCESS; ++ break; ++ case ARM_SMCCC_ARCH_WORKAROUND_2: ++ switch (kvm_arm_have_ssbd()) { ++ case KVM_SSBD_FORCE_DISABLE: ++ case KVM_SSBD_UNKNOWN: ++ break; ++ case KVM_SSBD_KERNEL: ++ val = SMCCC_RET_SUCCESS; ++ break; ++ case KVM_SSBD_FORCE_ENABLE: ++ case KVM_SSBD_MITIGATED: ++ val = SMCCC_RET_NOT_REQUIRED; ++ break; ++ } + break; + } + break; +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index d0df3611d1e2..3e43874568f9 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -776,6 +776,15 @@ config HARDEN_BRANCH_PREDICTOR + + If unsure, say Y. + ++config ARM64_SSBD ++ bool "Speculative Store Bypass Disable" if EXPERT ++ default y ++ help ++ This enables mitigation of the bypassing of previous stores ++ by speculative loads. ++ ++ If unsure, say Y. ++ + menuconfig ARMV8_DEPRECATED + bool "Emulate deprecated/obsolete ARMv8 instructions" + depends on COMPAT +diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h +index 6e1cb8c5af4d..7e842dcae450 100644 +--- a/arch/arm64/include/asm/alternative.h ++++ b/arch/arm64/include/asm/alternative.h +@@ -4,6 +4,8 @@ + #include <asm/cpucaps.h> + #include <asm/insn.h> + ++#define ARM64_CB_PATCH ARM64_NCAPS ++ + #ifndef __ASSEMBLY__ + + #include <linux/init.h> +@@ -11,6 +13,8 @@ + #include <linux/stddef.h> + #include <linux/stringify.h> + ++extern int alternatives_applied; ++ + struct alt_instr { + s32 orig_offset; /* offset to original instruction */ + s32 alt_offset; /* offset to replacement instruction */ +@@ -19,12 +23,19 @@ struct alt_instr { + u8 alt_len; /* size of new instruction(s), <= orig_len */ + }; + ++typedef void (*alternative_cb_t)(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, int nr_inst); ++ + void __init apply_alternatives_all(void); + void apply_alternatives(void *start, size_t length); + +-#define ALTINSTR_ENTRY(feature) \ ++#define ALTINSTR_ENTRY(feature,cb) \ + " .word 661b - .\n" /* label */ \ ++ " .if " __stringify(cb) " == 0\n" \ + " .word 663f - .\n" /* new instruction */ \ ++ " .else\n" \ ++ " .word " __stringify(cb) "- .\n" /* callback */ \ ++ " .endif\n" \ + " .hword " __stringify(feature) "\n" /* feature bit */ \ + " .byte 662b-661b\n" /* source len */ \ + " .byte 664f-663f\n" /* replacement len */ +@@ -42,15 +53,18 @@ void apply_alternatives(void *start, size_t length); + * but most assemblers die if insn1 or insn2 have a .inst. This should + * be fixed in a binutils release posterior to 2.25.51.0.2 (anything + * containing commit 4e4d08cf7399b606 or c1baaddf8861). ++ * ++ * Alternatives with callbacks do not generate replacement instructions. + */ +-#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled) \ ++#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled, cb) \ + ".if "__stringify(cfg_enabled)" == 1\n" \ + "661:\n\t" \ + oldinstr "\n" \ + "662:\n" \ + ".pushsection .altinstructions,\"a\"\n" \ +- ALTINSTR_ENTRY(feature) \ ++ ALTINSTR_ENTRY(feature,cb) \ + ".popsection\n" \ ++ " .if " __stringify(cb) " == 0\n" \ + ".pushsection .altinstr_replacement, \"a\"\n" \ + "663:\n\t" \ + newinstr "\n" \ +@@ -58,11 +72,17 @@ void apply_alternatives(void *start, size_t length); + ".popsection\n\t" \ + ".org . - (664b-663b) + (662b-661b)\n\t" \ + ".org . - (662b-661b) + (664b-663b)\n" \ ++ ".else\n\t" \ ++ "663:\n\t" \ ++ "664:\n\t" \ ++ ".endif\n" \ + ".endif\n" + + #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \ +- __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) ++ __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg), 0) + ++#define ALTERNATIVE_CB(oldinstr, cb) \ ++ __ALTERNATIVE_CFG(oldinstr, "NOT_AN_INSTRUCTION", ARM64_CB_PATCH, 1, cb) + #else + + #include <asm/assembler.h> +@@ -129,6 +149,14 @@ void apply_alternatives(void *start, size_t length); + 661: + .endm + ++.macro alternative_cb cb ++ .set .Lasm_alt_mode, 0 ++ .pushsection .altinstructions, "a" ++ altinstruction_entry 661f, \cb, ARM64_CB_PATCH, 662f-661f, 0 ++ .popsection ++661: ++.endm ++ + /* + * Provide the other half of the alternative code sequence. + */ +@@ -154,6 +182,13 @@ void apply_alternatives(void *start, size_t length); + .org . - (662b-661b) + (664b-663b) + .endm + ++/* ++ * Callback-based alternative epilogue ++ */ ++.macro alternative_cb_end ++662: ++.endm ++ + /* + * Provides a trivial alternative or default sequence consisting solely + * of NOPs. The number of NOPs is chosen automatically to match the +diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h +index bfcfec3590f6..3f85bbcd7e40 100644 +--- a/arch/arm64/include/asm/assembler.h ++++ b/arch/arm64/include/asm/assembler.h +@@ -239,14 +239,33 @@ lr .req x30 // link register + .endm + + /* ++ * @dst: Result of per_cpu(sym, smp_processor_id()) + * @sym: The name of the per-cpu variable +- * @reg: Result of per_cpu(sym, smp_processor_id()) + * @tmp: scratch register + */ +- .macro this_cpu_ptr, sym, reg, tmp +- adr_l \reg, \sym ++ .macro adr_this_cpu, dst, sym, tmp ++ adr_l \dst, \sym ++alternative_if_not ARM64_HAS_VIRT_HOST_EXTN + mrs \tmp, tpidr_el1 +- add \reg, \reg, \tmp ++alternative_else ++ mrs \tmp, tpidr_el2 ++alternative_endif ++ add \dst, \dst, \tmp ++ .endm ++ ++ /* ++ * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id())) ++ * @sym: The name of the per-cpu variable ++ * @tmp: scratch register ++ */ ++ .macro ldr_this_cpu dst, sym, tmp ++ adr_l \dst, \sym ++alternative_if_not ARM64_HAS_VIRT_HOST_EXTN ++ mrs \tmp, tpidr_el1 ++alternative_else ++ mrs \tmp, tpidr_el2 ++alternative_endif ++ ldr \dst, [\dst, \tmp] + .endm + + /* +diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h +index ce67bf6a0886..7010779a1429 100644 +--- a/arch/arm64/include/asm/cpucaps.h ++++ b/arch/arm64/include/asm/cpucaps.h +@@ -36,7 +36,8 @@ + #define ARM64_MISMATCHED_CACHE_LINE_SIZE 15 + #define ARM64_UNMAP_KERNEL_AT_EL0 16 + #define ARM64_HARDEN_BRANCH_PREDICTOR 17 ++#define ARM64_SSBD 18 + +-#define ARM64_NCAPS 18 ++#define ARM64_NCAPS 19 + + #endif /* __ASM_CPUCAPS_H */ +diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h +index 4ea85ebdf4df..15868eca58de 100644 +--- a/arch/arm64/include/asm/cpufeature.h ++++ b/arch/arm64/include/asm/cpufeature.h +@@ -221,6 +221,28 @@ static inline bool system_supports_mixed_endian_el0(void) + return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1)); + } + ++#define ARM64_SSBD_UNKNOWN -1 ++#define ARM64_SSBD_FORCE_DISABLE 0 ++#define ARM64_SSBD_KERNEL 1 ++#define ARM64_SSBD_FORCE_ENABLE 2 ++#define ARM64_SSBD_MITIGATED 3 ++ ++static inline int arm64_get_ssbd_state(void) ++{ ++#ifdef CONFIG_ARM64_SSBD ++ extern int ssbd_state; ++ return ssbd_state; ++#else ++ return ARM64_SSBD_UNKNOWN; ++#endif ++} ++ ++#ifdef CONFIG_ARM64_SSBD ++void arm64_set_ssbd_mitigation(bool state); ++#else ++static inline void arm64_set_ssbd_mitigation(bool state) {} ++#endif ++ + #endif /* __ASSEMBLY__ */ + + #endif +diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h +index ec3553eb9349..8f5cf83b2339 100644 +--- a/arch/arm64/include/asm/kvm_asm.h ++++ b/arch/arm64/include/asm/kvm_asm.h +@@ -33,6 +33,10 @@ + #define KVM_ARM64_DEBUG_DIRTY_SHIFT 0 + #define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT) + ++#define VCPU_WORKAROUND_2_FLAG_SHIFT 0 ++#define VCPU_WORKAROUND_2_FLAG (_AC(1, UL) << VCPU_WORKAROUND_2_FLAG_SHIFT) ++ ++/* Translate a kernel address of @sym into its equivalent linear mapping */ + #define kvm_ksym_ref(sym) \ + ({ \ + void *val = &sym; \ +@@ -65,6 +69,43 @@ extern u32 __kvm_get_mdcr_el2(void); + + extern u32 __init_stage2_translation(void); + ++/* Home-grown __this_cpu_{ptr,read} variants that always work at HYP */ ++#define __hyp_this_cpu_ptr(sym) \ ++ ({ \ ++ void *__ptr = hyp_symbol_addr(sym); \ ++ __ptr += read_sysreg(tpidr_el2); \ ++ (typeof(&sym))__ptr; \ ++ }) ++ ++#define __hyp_this_cpu_read(sym) \ ++ ({ \ ++ *__hyp_this_cpu_ptr(sym); \ ++ }) ++ ++#else /* __ASSEMBLY__ */ ++ ++.macro hyp_adr_this_cpu reg, sym, tmp ++ adr_l \reg, \sym ++ mrs \tmp, tpidr_el2 ++ add \reg, \reg, \tmp ++.endm ++ ++.macro hyp_ldr_this_cpu reg, sym, tmp ++ adr_l \reg, \sym ++ mrs \tmp, tpidr_el2 ++ ldr \reg, [\reg, \tmp] ++.endm ++ ++.macro get_host_ctxt reg, tmp ++ hyp_adr_this_cpu \reg, kvm_host_cpu_state, \tmp ++.endm ++ ++.macro get_vcpu_ptr vcpu, ctxt ++ get_host_ctxt \ctxt, \vcpu ++ ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] ++ kern_hyp_va \vcpu ++.endm ++ + #endif + + #endif /* __ARM_KVM_ASM_H__ */ +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index 2abb4493f4f6..4cdfbd01b2de 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -197,6 +197,8 @@ struct kvm_cpu_context { + u64 sys_regs[NR_SYS_REGS]; + u32 copro[NR_COPRO_REGS]; + }; ++ ++ struct kvm_vcpu *__hyp_running_vcpu; + }; + + typedef struct kvm_cpu_context kvm_cpu_context_t; +@@ -211,6 +213,9 @@ struct kvm_vcpu_arch { + /* Exception Information */ + struct kvm_vcpu_fault_info fault; + ++ /* State of various workarounds, see kvm_asm.h for bit assignment */ ++ u64 workaround_flags; ++ + /* Guest debug state */ + u64 debug_flags; + +@@ -354,10 +359,15 @@ int kvm_perf_teardown(void); + + struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr); + ++void __kvm_set_tpidr_el2(u64 tpidr_el2); ++DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state); ++ + static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, + unsigned long hyp_stack_ptr, + unsigned long vector_ptr) + { ++ u64 tpidr_el2; ++ + /* + * Call initialization code, and switch to the full blown HYP code. + * If the cpucaps haven't been finalized yet, something has gone very +@@ -366,6 +376,16 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, + */ + BUG_ON(!static_branch_likely(&arm64_const_caps_ready)); + __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr); ++ ++ /* ++ * Calculate the raw per-cpu offset without a translation from the ++ * kernel's mapping to the linear mapping, and store it in tpidr_el2 ++ * so that we can use adr_l to access per-cpu variables in EL2. ++ */ ++ tpidr_el2 = (u64)this_cpu_ptr(&kvm_host_cpu_state) ++ - (u64)kvm_ksym_ref(kvm_host_cpu_state); ++ ++ kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2); + } + + void __kvm_hyp_teardown(void); +@@ -405,4 +425,27 @@ static inline bool kvm_arm_harden_branch_predictor(void) + return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); + } + ++#define KVM_SSBD_UNKNOWN -1 ++#define KVM_SSBD_FORCE_DISABLE 0 ++#define KVM_SSBD_KERNEL 1 ++#define KVM_SSBD_FORCE_ENABLE 2 ++#define KVM_SSBD_MITIGATED 3 ++ ++static inline int kvm_arm_have_ssbd(void) ++{ ++ switch (arm64_get_ssbd_state()) { ++ case ARM64_SSBD_FORCE_DISABLE: ++ return KVM_SSBD_FORCE_DISABLE; ++ case ARM64_SSBD_KERNEL: ++ return KVM_SSBD_KERNEL; ++ case ARM64_SSBD_FORCE_ENABLE: ++ return KVM_SSBD_FORCE_ENABLE; ++ case ARM64_SSBD_MITIGATED: ++ return KVM_SSBD_MITIGATED; ++ case ARM64_SSBD_UNKNOWN: ++ default: ++ return KVM_SSBD_UNKNOWN; ++ } ++} ++ + #endif /* __ARM64_KVM_HOST_H__ */ +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index 824c83db9b47..547519abc751 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -130,6 +130,26 @@ static inline unsigned long __kern_hyp_va(unsigned long v) + + #define kern_hyp_va(v) ((typeof(v))(__kern_hyp_va((unsigned long)(v)))) + ++/* ++ * Obtain the PC-relative address of a kernel symbol ++ * s: symbol ++ * ++ * The goal of this macro is to return a symbol's address based on a ++ * PC-relative computation, as opposed to a loading the VA from a ++ * constant pool or something similar. This works well for HYP, as an ++ * absolute VA is guaranteed to be wrong. Only use this if trying to ++ * obtain the address of a symbol (i.e. not something you obtained by ++ * following a pointer). ++ */ ++#define hyp_symbol_addr(s) \ ++ ({ \ ++ typeof(s) *addr; \ ++ asm("adrp %0, %1\n" \ ++ "add %0, %0, :lo12:%1\n" \ ++ : "=r" (addr) : "S" (&s)); \ ++ addr; \ ++ }) ++ + /* + * We currently only support a 40bit IPA. + */ +@@ -367,5 +387,29 @@ static inline int kvm_map_vectors(void) + } + #endif + ++#ifdef CONFIG_ARM64_SSBD ++DECLARE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); ++ ++static inline int hyp_map_aux_data(void) ++{ ++ int cpu, err; ++ ++ for_each_possible_cpu(cpu) { ++ u64 *ptr; ++ ++ ptr = per_cpu_ptr(&arm64_ssbd_callback_required, cpu); ++ err = create_hyp_mappings(ptr, ptr + 1, PAGE_HYP); ++ if (err) ++ return err; ++ } ++ return 0; ++} ++#else ++static inline int hyp_map_aux_data(void) ++{ ++ return 0; ++} ++#endif ++ + #endif /* __ASSEMBLY__ */ + #endif /* __ARM64_KVM_MMU_H__ */ +diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h +index 5394c8405e66..0d551576eb57 100644 +--- a/arch/arm64/include/asm/percpu.h ++++ b/arch/arm64/include/asm/percpu.h +@@ -16,9 +16,14 @@ + #ifndef __ASM_PERCPU_H + #define __ASM_PERCPU_H + ++#include <asm/alternative.h> ++ + static inline void set_my_cpu_offset(unsigned long off) + { +- asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory"); ++ asm volatile(ALTERNATIVE("msr tpidr_el1, %0", ++ "msr tpidr_el2, %0", ++ ARM64_HAS_VIRT_HOST_EXTN) ++ :: "r" (off) : "memory"); + } + + static inline unsigned long __my_cpu_offset(void) +@@ -29,7 +34,10 @@ static inline unsigned long __my_cpu_offset(void) + * We want to allow caching the value, so avoid using volatile and + * instead use a fake stack read to hazard against barrier(). + */ +- asm("mrs %0, tpidr_el1" : "=r" (off) : ++ asm(ALTERNATIVE("mrs %0, tpidr_el1", ++ "mrs %0, tpidr_el2", ++ ARM64_HAS_VIRT_HOST_EXTN) ++ : "=r" (off) : + "Q" (*(const unsigned long *)current_stack_pointer)); + + return off; +diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h +index e9ea5a6bd449..0dd1bc13f942 100644 +--- a/arch/arm64/include/asm/thread_info.h ++++ b/arch/arm64/include/asm/thread_info.h +@@ -122,6 +122,7 @@ static inline struct thread_info *current_thread_info(void) + #define TIF_RESTORE_SIGMASK 20 + #define TIF_SINGLESTEP 21 + #define TIF_32BIT 22 /* 32bit process */ ++#define TIF_SSBD 23 /* Wants SSB mitigation */ + + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile +index 74b8fd860714..6dadaaee796d 100644 +--- a/arch/arm64/kernel/Makefile ++++ b/arch/arm64/kernel/Makefile +@@ -50,6 +50,7 @@ arm64-obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o + arm64-obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o + arm64-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o \ + cpu-reset.o ++arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o + + ifeq ($(CONFIG_KVM),y) + arm64-obj-$(CONFIG_HARDEN_BRANCH_PREDICTOR) += bpi.o +diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c +index 06d650f61da7..091748095140 100644 +--- a/arch/arm64/kernel/alternative.c ++++ b/arch/arm64/kernel/alternative.c +@@ -28,10 +28,12 @@ + #include <asm/sections.h> + #include <linux/stop_machine.h> + +-#define __ALT_PTR(a,f) (u32 *)((void *)&(a)->f + (a)->f) ++#define __ALT_PTR(a,f) ((void *)&(a)->f + (a)->f) + #define ALT_ORIG_PTR(a) __ALT_PTR(a, orig_offset) + #define ALT_REPL_PTR(a) __ALT_PTR(a, alt_offset) + ++int alternatives_applied; ++ + struct alt_region { + struct alt_instr *begin; + struct alt_instr *end; +@@ -105,31 +107,52 @@ static u32 get_alt_insn(struct alt_instr *alt, u32 *insnptr, u32 *altinsnptr) + return insn; + } + ++static void patch_alternative(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, int nr_inst) ++{ ++ __le32 *replptr; ++ int i; ++ ++ replptr = ALT_REPL_PTR(alt); ++ for (i = 0; i < nr_inst; i++) { ++ u32 insn; ++ ++ insn = get_alt_insn(alt, origptr + i, replptr + i); ++ updptr[i] = cpu_to_le32(insn); ++ } ++} ++ + static void __apply_alternatives(void *alt_region) + { + struct alt_instr *alt; + struct alt_region *region = alt_region; +- u32 *origptr, *replptr; ++ __le32 *origptr; ++ alternative_cb_t alt_cb; + + for (alt = region->begin; alt < region->end; alt++) { +- u32 insn; +- int i, nr_inst; ++ int nr_inst; + +- if (!cpus_have_cap(alt->cpufeature)) ++ /* Use ARM64_CB_PATCH as an unconditional patch */ ++ if (alt->cpufeature < ARM64_CB_PATCH && ++ !cpus_have_cap(alt->cpufeature)) + continue; + +- BUG_ON(alt->alt_len != alt->orig_len); ++ if (alt->cpufeature == ARM64_CB_PATCH) ++ BUG_ON(alt->alt_len != 0); ++ else ++ BUG_ON(alt->alt_len != alt->orig_len); + + pr_info_once("patching kernel code\n"); + + origptr = ALT_ORIG_PTR(alt); +- replptr = ALT_REPL_PTR(alt); +- nr_inst = alt->alt_len / sizeof(insn); ++ nr_inst = alt->orig_len / AARCH64_INSN_SIZE; + +- for (i = 0; i < nr_inst; i++) { +- insn = get_alt_insn(alt, origptr + i, replptr + i); +- *(origptr + i) = cpu_to_le32(insn); +- } ++ if (alt->cpufeature < ARM64_CB_PATCH) ++ alt_cb = patch_alternative; ++ else ++ alt_cb = ALT_REPL_PTR(alt); ++ ++ alt_cb(alt, origptr, origptr, nr_inst); + + flush_icache_range((uintptr_t)origptr, + (uintptr_t)(origptr + nr_inst)); +@@ -142,7 +165,6 @@ static void __apply_alternatives(void *alt_region) + */ + static int __apply_alternatives_multi_stop(void *unused) + { +- static int patched = 0; + struct alt_region region = { + .begin = (struct alt_instr *)__alt_instructions, + .end = (struct alt_instr *)__alt_instructions_end, +@@ -150,14 +172,14 @@ static int __apply_alternatives_multi_stop(void *unused) + + /* We always have a CPU 0 at this point (__init) */ + if (smp_processor_id()) { +- while (!READ_ONCE(patched)) ++ while (!READ_ONCE(alternatives_applied)) + cpu_relax(); + isb(); + } else { +- BUG_ON(patched); ++ BUG_ON(alternatives_applied); + __apply_alternatives(®ion); + /* Barriers provided by the cache flushing */ +- WRITE_ONCE(patched, 1); ++ WRITE_ONCE(alternatives_applied, 1); + } + + return 0; +diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c +index 5f4bf3c6f016..bd239b1b7a68 100644 +--- a/arch/arm64/kernel/asm-offsets.c ++++ b/arch/arm64/kernel/asm-offsets.c +@@ -127,11 +127,13 @@ int main(void) + BLANK(); + #ifdef CONFIG_KVM_ARM_HOST + DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); ++ DEFINE(VCPU_WORKAROUND_FLAGS, offsetof(struct kvm_vcpu, arch.workaround_flags)); + DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs)); + DEFINE(CPU_USER_PT_REGS, offsetof(struct kvm_regs, regs)); + DEFINE(CPU_FP_REGS, offsetof(struct kvm_regs, fp_regs)); + DEFINE(VCPU_FPEXC32_EL2, offsetof(struct kvm_vcpu, arch.ctxt.sys_regs[FPEXC32_EL2])); + DEFINE(VCPU_HOST_CONTEXT, offsetof(struct kvm_vcpu, arch.host_cpu_context)); ++ DEFINE(HOST_CONTEXT_VCPU, offsetof(struct kvm_cpu_context, __hyp_running_vcpu)); + #endif + #ifdef CONFIG_CPU_PM + DEFINE(CPU_SUSPEND_SZ, sizeof(struct cpu_suspend_ctx)); +diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c +index 2de62aa91303..1db97ad7b58b 100644 +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -187,6 +187,178 @@ static int enable_smccc_arch_workaround_1(void *data) + } + #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ + ++#ifdef CONFIG_ARM64_SSBD ++DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); ++ ++int ssbd_state __read_mostly = ARM64_SSBD_KERNEL; ++ ++static const struct ssbd_options { ++ const char *str; ++ int state; ++} ssbd_options[] = { ++ { "force-on", ARM64_SSBD_FORCE_ENABLE, }, ++ { "force-off", ARM64_SSBD_FORCE_DISABLE, }, ++ { "kernel", ARM64_SSBD_KERNEL, }, ++}; ++ ++static int __init ssbd_cfg(char *buf) ++{ ++ int i; ++ ++ if (!buf || !buf[0]) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(ssbd_options); i++) { ++ int len = strlen(ssbd_options[i].str); ++ ++ if (strncmp(buf, ssbd_options[i].str, len)) ++ continue; ++ ++ ssbd_state = ssbd_options[i].state; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++early_param("ssbd", ssbd_cfg); ++ ++void __init arm64_update_smccc_conduit(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, ++ int nr_inst) ++{ ++ u32 insn; ++ ++ BUG_ON(nr_inst != 1); ++ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ insn = aarch64_insn_get_hvc_value(); ++ break; ++ case PSCI_CONDUIT_SMC: ++ insn = aarch64_insn_get_smc_value(); ++ break; ++ default: ++ return; ++ } ++ ++ *updptr = cpu_to_le32(insn); ++} ++ ++void __init arm64_enable_wa2_handling(struct alt_instr *alt, ++ __le32 *origptr, __le32 *updptr, ++ int nr_inst) ++{ ++ BUG_ON(nr_inst != 1); ++ /* ++ * Only allow mitigation on EL1 entry/exit and guest ++ * ARCH_WORKAROUND_2 handling if the SSBD state allows it to ++ * be flipped. ++ */ ++ if (arm64_get_ssbd_state() == ARM64_SSBD_KERNEL) ++ *updptr = cpu_to_le32(aarch64_insn_gen_nop()); ++} ++ ++void arm64_set_ssbd_mitigation(bool state) ++{ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); ++ break; ++ ++ case PSCI_CONDUIT_SMC: ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); ++ break; ++ ++ default: ++ WARN_ON_ONCE(1); ++ break; ++ } ++} ++ ++static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry, ++ int scope) ++{ ++ struct arm_smccc_res res; ++ bool required = true; ++ s32 val; ++ ++ WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); ++ ++ if (psci_ops.smccc_version == SMCCC_VERSION_1_0) { ++ ssbd_state = ARM64_SSBD_UNKNOWN; ++ return false; ++ } ++ ++ switch (psci_ops.conduit) { ++ case PSCI_CONDUIT_HVC: ++ arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_2, &res); ++ break; ++ ++ case PSCI_CONDUIT_SMC: ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ++ ARM_SMCCC_ARCH_WORKAROUND_2, &res); ++ break; ++ ++ default: ++ ssbd_state = ARM64_SSBD_UNKNOWN; ++ return false; ++ } ++ ++ val = (s32)res.a0; ++ ++ switch (val) { ++ case SMCCC_RET_NOT_SUPPORTED: ++ ssbd_state = ARM64_SSBD_UNKNOWN; ++ return false; ++ ++ case SMCCC_RET_NOT_REQUIRED: ++ pr_info_once("%s mitigation not required\n", entry->desc); ++ ssbd_state = ARM64_SSBD_MITIGATED; ++ return false; ++ ++ case SMCCC_RET_SUCCESS: ++ required = true; ++ break; ++ ++ case 1: /* Mitigation not required on this CPU */ ++ required = false; ++ break; ++ ++ default: ++ WARN_ON(1); ++ return false; ++ } ++ ++ switch (ssbd_state) { ++ case ARM64_SSBD_FORCE_DISABLE: ++ pr_info_once("%s disabled from command-line\n", entry->desc); ++ arm64_set_ssbd_mitigation(false); ++ required = false; ++ break; ++ ++ case ARM64_SSBD_KERNEL: ++ if (required) { ++ __this_cpu_write(arm64_ssbd_callback_required, 1); ++ arm64_set_ssbd_mitigation(true); ++ } ++ break; ++ ++ case ARM64_SSBD_FORCE_ENABLE: ++ pr_info_once("%s forced from command-line\n", entry->desc); ++ arm64_set_ssbd_mitigation(true); ++ required = true; ++ break; ++ ++ default: ++ WARN_ON(1); ++ break; ++ } ++ ++ return required; ++} ++#endif /* CONFIG_ARM64_SSBD */ ++ + #define MIDR_RANGE(model, min, max) \ + .def_scope = SCOPE_LOCAL_CPU, \ + .matches = is_affected_midr_range, \ +@@ -309,6 +481,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { + MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), + .enable = enable_smccc_arch_workaround_1, + }, ++#endif ++#ifdef CONFIG_ARM64_SSBD ++ { ++ .desc = "Speculative Store Bypass Disable", ++ .def_scope = SCOPE_LOCAL_CPU, ++ .capability = ARM64_SSBD, ++ .matches = has_ssbd_mitigation, ++ }, + #endif + { + } +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index 625c2b240ffb..ab15747a49d4 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -829,6 +829,22 @@ static int __init parse_kpti(char *str) + early_param("kpti", parse_kpti); + #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ + ++static int cpu_copy_el2regs(void *__unused) ++{ ++ /* ++ * Copy register values that aren't redirected by hardware. ++ * ++ * Before code patching, we only set tpidr_el1, all CPUs need to copy ++ * this value to tpidr_el2 before we patch the code. Once we've done ++ * that, freshly-onlined CPUs will set tpidr_el2, so we don't need to ++ * do anything here. ++ */ ++ if (!alternatives_applied) ++ write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); ++ ++ return 0; ++} ++ + static const struct arm64_cpu_capabilities arm64_features[] = { + { + .desc = "GIC system register CPU interface", +@@ -895,6 +911,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { + .capability = ARM64_HAS_VIRT_HOST_EXTN, + .def_scope = SCOPE_SYSTEM, + .matches = runs_at_el2, ++ .enable = cpu_copy_el2regs, + }, + { + .desc = "32-bit EL0 Support", +diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S +index b79e302d2a3e..ca978d7d98eb 100644 +--- a/arch/arm64/kernel/entry.S ++++ b/arch/arm64/kernel/entry.S +@@ -18,6 +18,7 @@ + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + ++#include <linux/arm-smccc.h> + #include <linux/init.h> + #include <linux/linkage.h> + +@@ -95,6 +96,25 @@ alternative_else_nop_endif + add \dst, \dst, #(\sym - .entry.tramp.text) + .endm + ++ // This macro corrupts x0-x3. It is the caller's duty ++ // to save/restore them if required. ++ .macro apply_ssbd, state, targ, tmp1, tmp2 ++#ifdef CONFIG_ARM64_SSBD ++alternative_cb arm64_enable_wa2_handling ++ b \targ ++alternative_cb_end ++ ldr_this_cpu \tmp2, arm64_ssbd_callback_required, \tmp1 ++ cbz \tmp2, \targ ++ ldr \tmp2, [tsk, #TI_FLAGS] ++ tbnz \tmp2, #TIF_SSBD, \targ ++ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 ++ mov w1, #\state ++alternative_cb arm64_update_smccc_conduit ++ nop // Patched to SMC/HVC #0 ++alternative_cb_end ++#endif ++ .endm ++ + .macro kernel_entry, el, regsize = 64 + .if \regsize == 32 + mov w0, w0 // zero upper 32 bits of x0 +@@ -122,6 +142,14 @@ alternative_else_nop_endif + ldr x19, [tsk, #TI_FLAGS] // since we can unmask debug + disable_step_tsk x19, x20 // exceptions when scheduling. + ++ apply_ssbd 1, 1f, x22, x23 ++ ++#ifdef CONFIG_ARM64_SSBD ++ ldp x0, x1, [sp, #16 * 0] ++ ldp x2, x3, [sp, #16 * 1] ++#endif ++1: ++ + mov x29, xzr // fp pointed to user-space + .else + add x21, sp, #S_FRAME_SIZE +@@ -190,6 +218,8 @@ alternative_if ARM64_WORKAROUND_845719 + alternative_else_nop_endif + #endif + 3: ++ apply_ssbd 0, 5f, x0, x1 ++5: + .endif + msr elr_el1, x21 // set up the return data + msr spsr_el1, x22 +@@ -243,7 +273,7 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 + cmp x25, tsk + b.ne 9998f + +- this_cpu_ptr irq_stack, x25, x26 ++ adr_this_cpu x25, irq_stack, x26 + mov x26, #IRQ_STACK_START_SP + add x26, x25, x26 + +diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c +index d55a7b09959b..f6e71c73cceb 100644 +--- a/arch/arm64/kernel/hibernate.c ++++ b/arch/arm64/kernel/hibernate.c +@@ -308,6 +308,17 @@ int swsusp_arch_suspend(void) + + sleep_cpu = -EINVAL; + __cpu_suspend_exit(); ++ ++ /* ++ * Just in case the boot kernel did turn the SSBD ++ * mitigation off behind our back, let's set the state ++ * to what we expect it to be. ++ */ ++ switch (arm64_get_ssbd_state()) { ++ case ARM64_SSBD_FORCE_ENABLE: ++ case ARM64_SSBD_KERNEL: ++ arm64_set_ssbd_mitigation(true); ++ } + } + + local_dbg_restore(flags); +diff --git a/arch/arm64/kernel/ssbd.c b/arch/arm64/kernel/ssbd.c +new file mode 100644 +index 000000000000..0560738c1d5c +--- /dev/null ++++ b/arch/arm64/kernel/ssbd.c +@@ -0,0 +1,108 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2018 ARM Ltd, All Rights Reserved. ++ */ ++ ++#include <linux/errno.h> ++#include <linux/prctl.h> ++#include <linux/sched.h> ++#include <linux/thread_info.h> ++ ++#include <asm/cpufeature.h> ++ ++/* ++ * prctl interface for SSBD ++ */ ++static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) ++{ ++ int state = arm64_get_ssbd_state(); ++ ++ /* Unsupported */ ++ if (state == ARM64_SSBD_UNKNOWN) ++ return -EINVAL; ++ ++ /* Treat the unaffected/mitigated state separately */ ++ if (state == ARM64_SSBD_MITIGATED) { ++ switch (ctrl) { ++ case PR_SPEC_ENABLE: ++ return -EPERM; ++ case PR_SPEC_DISABLE: ++ case PR_SPEC_FORCE_DISABLE: ++ return 0; ++ } ++ } ++ ++ /* ++ * Things are a bit backward here: the arm64 internal API ++ * *enables the mitigation* when the userspace API *disables ++ * speculation*. So much fun. ++ */ ++ switch (ctrl) { ++ case PR_SPEC_ENABLE: ++ /* If speculation is force disabled, enable is not allowed */ ++ if (state == ARM64_SSBD_FORCE_ENABLE || ++ task_spec_ssb_force_disable(task)) ++ return -EPERM; ++ task_clear_spec_ssb_disable(task); ++ clear_tsk_thread_flag(task, TIF_SSBD); ++ break; ++ case PR_SPEC_DISABLE: ++ if (state == ARM64_SSBD_FORCE_DISABLE) ++ return -EPERM; ++ task_set_spec_ssb_disable(task); ++ set_tsk_thread_flag(task, TIF_SSBD); ++ break; ++ case PR_SPEC_FORCE_DISABLE: ++ if (state == ARM64_SSBD_FORCE_DISABLE) ++ return -EPERM; ++ task_set_spec_ssb_disable(task); ++ task_set_spec_ssb_force_disable(task); ++ set_tsk_thread_flag(task, TIF_SSBD); ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ return 0; ++} ++ ++int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, ++ unsigned long ctrl) ++{ ++ switch (which) { ++ case PR_SPEC_STORE_BYPASS: ++ return ssbd_prctl_set(task, ctrl); ++ default: ++ return -ENODEV; ++ } ++} ++ ++static int ssbd_prctl_get(struct task_struct *task) ++{ ++ switch (arm64_get_ssbd_state()) { ++ case ARM64_SSBD_UNKNOWN: ++ return -EINVAL; ++ case ARM64_SSBD_FORCE_ENABLE: ++ return PR_SPEC_DISABLE; ++ case ARM64_SSBD_KERNEL: ++ if (task_spec_ssb_force_disable(task)) ++ return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; ++ if (task_spec_ssb_disable(task)) ++ return PR_SPEC_PRCTL | PR_SPEC_DISABLE; ++ return PR_SPEC_PRCTL | PR_SPEC_ENABLE; ++ case ARM64_SSBD_FORCE_DISABLE: ++ return PR_SPEC_ENABLE; ++ default: ++ return PR_SPEC_NOT_AFFECTED; ++ } ++} ++ ++int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) ++{ ++ switch (which) { ++ case PR_SPEC_STORE_BYPASS: ++ return ssbd_prctl_get(task); ++ default: ++ return -ENODEV; ++ } ++} +diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c +index bb0cd787a9d3..1dbf6099e2a5 100644 +--- a/arch/arm64/kernel/suspend.c ++++ b/arch/arm64/kernel/suspend.c +@@ -67,6 +67,14 @@ void notrace __cpu_suspend_exit(void) + */ + if (hw_breakpoint_restore) + hw_breakpoint_restore(cpu); ++ ++ /* ++ * On resume, firmware implementing dynamic mitigation will ++ * have turned the mitigation on. If the user has forcefully ++ * disabled it, make sure their wishes are obeyed. ++ */ ++ if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) ++ arm64_set_ssbd_mitigation(false); + } + + /* +diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S +index 4bbff904169d..db5efaf2a985 100644 +--- a/arch/arm64/kvm/hyp-init.S ++++ b/arch/arm64/kvm/hyp-init.S +@@ -118,6 +118,10 @@ CPU_BE( orr x4, x4, #SCTLR_ELx_EE) + kern_hyp_va x2 + msr vbar_el2, x2 + ++ /* copy tpidr_el1 into tpidr_el2 for use by HYP */ ++ mrs x1, tpidr_el1 ++ msr tpidr_el2, x1 ++ + /* Hello, World! */ + eret + ENDPROC(__kvm_hyp_init) +diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S +index 12ee62d6d410..a360ac6e89e9 100644 +--- a/arch/arm64/kvm/hyp/entry.S ++++ b/arch/arm64/kvm/hyp/entry.S +@@ -62,9 +62,6 @@ ENTRY(__guest_enter) + // Store the host regs + save_callee_saved_regs x1 + +- // Store the host_ctxt for use at exit time +- str x1, [sp, #-16]! +- + add x18, x0, #VCPU_CONTEXT + + // Restore guest regs x0-x17 +@@ -118,8 +115,7 @@ ENTRY(__guest_exit) + // Store the guest regs x19-x29, lr + save_callee_saved_regs x1 + +- // Restore the host_ctxt from the stack +- ldr x2, [sp], #16 ++ get_host_ctxt x2, x3 + + // Now restore the host regs + restore_callee_saved_regs x2 +@@ -159,6 +155,10 @@ abort_guest_exit_end: + ENDPROC(__guest_exit) + + ENTRY(__fpsimd_guest_restore) ++ // x0: esr ++ // x1: vcpu ++ // x2-x29,lr: vcpu regs ++ // vcpu x0-x1 on the stack + stp x2, x3, [sp, #-16]! + stp x4, lr, [sp, #-16]! + +@@ -173,7 +173,7 @@ alternative_else + alternative_endif + isb + +- mrs x3, tpidr_el2 ++ mov x3, x1 + + ldr x0, [x3, #VCPU_HOST_CONTEXT] + kern_hyp_va x0 +diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S +index 4e9d50c3e658..bf4988f9dae8 100644 +--- a/arch/arm64/kvm/hyp/hyp-entry.S ++++ b/arch/arm64/kvm/hyp/hyp-entry.S +@@ -72,13 +72,8 @@ ENDPROC(__kvm_hyp_teardown) + el1_sync: // Guest trapped into EL2 + stp x0, x1, [sp, #-16]! + +-alternative_if_not ARM64_HAS_VIRT_HOST_EXTN +- mrs x1, esr_el2 +-alternative_else +- mrs x1, esr_el1 +-alternative_endif +- lsr x0, x1, #ESR_ELx_EC_SHIFT +- ++ mrs x0, esr_el2 ++ lsr x0, x0, #ESR_ELx_EC_SHIFT + cmp x0, #ESR_ELx_EC_HVC64 + ccmp x0, #ESR_ELx_EC_HVC32, #4, ne + b.ne el1_trap +@@ -112,33 +107,73 @@ el1_hvc_guest: + */ + ldr x1, [sp] // Guest's x0 + eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 ++ cbz w1, wa_epilogue ++ ++ /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ ++ eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \ ++ ARM_SMCCC_ARCH_WORKAROUND_2) + cbnz w1, el1_trap +- mov x0, x1 ++ ++#ifdef CONFIG_ARM64_SSBD ++alternative_cb arm64_enable_wa2_handling ++ b wa2_end ++alternative_cb_end ++ get_vcpu_ptr x2, x0 ++ ldr x0, [x2, #VCPU_WORKAROUND_FLAGS] ++ ++ // Sanitize the argument and update the guest flags ++ ldr x1, [sp, #8] // Guest's x1 ++ clz w1, w1 // Murphy's device: ++ lsr w1, w1, #5 // w1 = !!w1 without using ++ eor w1, w1, #1 // the flags... ++ bfi x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1 ++ str x0, [x2, #VCPU_WORKAROUND_FLAGS] ++ ++ /* Check that we actually need to perform the call */ ++ hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2 ++ cbz x0, wa2_end ++ ++ mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 ++ smc #0 ++ ++ /* Don't leak data from the SMC call */ ++ mov x3, xzr ++wa2_end: ++ mov x2, xzr ++ mov x1, xzr ++#endif ++ ++wa_epilogue: ++ mov x0, xzr + add sp, sp, #16 + eret + + el1_trap: ++ get_vcpu_ptr x1, x0 ++ ++ mrs x0, esr_el2 ++ lsr x0, x0, #ESR_ELx_EC_SHIFT + /* + * x0: ESR_EC ++ * x1: vcpu pointer + */ + + /* Guest accessed VFP/SIMD registers, save host, restore Guest */ + cmp x0, #ESR_ELx_EC_FP_ASIMD + b.eq __fpsimd_guest_restore + +- mrs x1, tpidr_el2 + mov x0, #ARM_EXCEPTION_TRAP + b __guest_exit + + el1_irq: + stp x0, x1, [sp, #-16]! +- mrs x1, tpidr_el2 ++ get_vcpu_ptr x1, x0 + mov x0, #ARM_EXCEPTION_IRQ + b __guest_exit + + el1_error: + stp x0, x1, [sp, #-16]! +- mrs x1, tpidr_el2 ++ get_vcpu_ptr x1, x0 + mov x0, #ARM_EXCEPTION_EL1_SERROR + b __guest_exit + +@@ -173,6 +208,11 @@ ENTRY(__hyp_do_panic) + eret + ENDPROC(__hyp_do_panic) + ++ENTRY(__hyp_panic) ++ get_host_ctxt x0, x1 ++ b hyp_panic ++ENDPROC(__hyp_panic) ++ + .macro invalid_vector label, target = __hyp_panic + .align 2 + \label: +diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c +index c49d09387192..12f9d1ecdf4c 100644 +--- a/arch/arm64/kvm/hyp/switch.c ++++ b/arch/arm64/kvm/hyp/switch.c +@@ -15,6 +15,7 @@ + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + ++#include <linux/arm-smccc.h> + #include <linux/types.h> + #include <linux/jump_label.h> + #include <uapi/linux/psci.h> +@@ -267,6 +268,39 @@ static void __hyp_text __skip_instr(struct kvm_vcpu *vcpu) + write_sysreg_el2(*vcpu_pc(vcpu), elr); + } + ++static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu) ++{ ++ if (!cpus_have_cap(ARM64_SSBD)) ++ return false; ++ ++ return !(vcpu->arch.workaround_flags & VCPU_WORKAROUND_2_FLAG); ++} ++ ++static void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu *vcpu) ++{ ++#ifdef CONFIG_ARM64_SSBD ++ /* ++ * The host runs with the workaround always present. If the ++ * guest wants it disabled, so be it... ++ */ ++ if (__needs_ssbd_off(vcpu) && ++ __hyp_this_cpu_read(arm64_ssbd_callback_required)) ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 0, NULL); ++#endif ++} ++ ++static void __hyp_text __set_host_arch_workaround_state(struct kvm_vcpu *vcpu) ++{ ++#ifdef CONFIG_ARM64_SSBD ++ /* ++ * If the guest has disabled the workaround, bring it back on. ++ */ ++ if (__needs_ssbd_off(vcpu) && ++ __hyp_this_cpu_read(arm64_ssbd_callback_required)) ++ arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 1, NULL); ++#endif ++} ++ + int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + { + struct kvm_cpu_context *host_ctxt; +@@ -275,9 +309,9 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + u64 exit_code; + + vcpu = kern_hyp_va(vcpu); +- write_sysreg(vcpu, tpidr_el2); + + host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); ++ host_ctxt->__hyp_running_vcpu = vcpu; + guest_ctxt = &vcpu->arch.ctxt; + + __sysreg_save_host_state(host_ctxt); +@@ -297,6 +331,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + __sysreg_restore_guest_state(guest_ctxt); + __debug_restore_state(vcpu, kern_hyp_va(vcpu->arch.debug_ptr), guest_ctxt); + ++ __set_guest_arch_workaround_state(vcpu); ++ + /* Jump in the fire! */ + again: + exit_code = __guest_enter(vcpu, host_ctxt); +@@ -339,6 +375,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + } + } + ++ __set_host_arch_workaround_state(vcpu); ++ + fp_enabled = __fpsimd_enabled(); + + __sysreg_save_guest_state(guest_ctxt); +@@ -364,7 +402,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) + + static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n"; + +-static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par) ++static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par, ++ struct kvm_vcpu *vcpu) + { + unsigned long str_va; + +@@ -378,35 +417,32 @@ static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par) + __hyp_do_panic(str_va, + spsr, elr, + read_sysreg(esr_el2), read_sysreg_el2(far), +- read_sysreg(hpfar_el2), par, +- (void *)read_sysreg(tpidr_el2)); ++ read_sysreg(hpfar_el2), par, vcpu); + } + +-static void __hyp_text __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par) ++static void __hyp_text __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par, ++ struct kvm_vcpu *vcpu) + { + panic(__hyp_panic_string, + spsr, elr, + read_sysreg_el2(esr), read_sysreg_el2(far), +- read_sysreg(hpfar_el2), par, +- (void *)read_sysreg(tpidr_el2)); ++ read_sysreg(hpfar_el2), par, vcpu); + } + + static hyp_alternate_select(__hyp_call_panic, + __hyp_call_panic_nvhe, __hyp_call_panic_vhe, + ARM64_HAS_VIRT_HOST_EXTN); + +-void __hyp_text __noreturn __hyp_panic(void) ++void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt) + { ++ struct kvm_vcpu *vcpu = NULL; ++ + u64 spsr = read_sysreg_el2(spsr); + u64 elr = read_sysreg_el2(elr); + u64 par = read_sysreg(par_el1); + + if (read_sysreg(vttbr_el2)) { +- struct kvm_vcpu *vcpu; +- struct kvm_cpu_context *host_ctxt; +- +- vcpu = (struct kvm_vcpu *)read_sysreg(tpidr_el2); +- host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); ++ vcpu = host_ctxt->__hyp_running_vcpu; + __timer_save_state(vcpu); + __deactivate_traps(vcpu); + __deactivate_vm(vcpu); +@@ -414,7 +450,7 @@ void __hyp_text __noreturn __hyp_panic(void) + } + + /* Call panic for real */ +- __hyp_call_panic()(spsr, elr, par); ++ __hyp_call_panic()(spsr, elr, par, vcpu); + + unreachable(); + } +diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c +index 934137647837..e19d89cabf2a 100644 +--- a/arch/arm64/kvm/hyp/sysreg-sr.c ++++ b/arch/arm64/kvm/hyp/sysreg-sr.c +@@ -27,8 +27,8 @@ static void __hyp_text __sysreg_do_nothing(struct kvm_cpu_context *ctxt) { } + /* + * Non-VHE: Both host and guest must save everything. + * +- * VHE: Host must save tpidr*_el[01], actlr_el1, mdscr_el1, sp0, pc, +- * pstate, and guest must save everything. ++ * VHE: Host must save tpidr*_el0, actlr_el1, mdscr_el1, sp_el0, ++ * and guest must save everything. + */ + + static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) +@@ -36,11 +36,8 @@ static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) + ctxt->sys_regs[ACTLR_EL1] = read_sysreg(actlr_el1); + ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0); + ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0); +- ctxt->sys_regs[TPIDR_EL1] = read_sysreg(tpidr_el1); + ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1); + ctxt->gp_regs.regs.sp = read_sysreg(sp_el0); +- ctxt->gp_regs.regs.pc = read_sysreg_el2(elr); +- ctxt->gp_regs.regs.pstate = read_sysreg_el2(spsr); + } + + static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt) +@@ -62,10 +59,13 @@ static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt) + ctxt->sys_regs[AMAIR_EL1] = read_sysreg_el1(amair); + ctxt->sys_regs[CNTKCTL_EL1] = read_sysreg_el1(cntkctl); + ctxt->sys_regs[PAR_EL1] = read_sysreg(par_el1); ++ ctxt->sys_regs[TPIDR_EL1] = read_sysreg(tpidr_el1); + + ctxt->gp_regs.sp_el1 = read_sysreg(sp_el1); + ctxt->gp_regs.elr_el1 = read_sysreg_el1(elr); + ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(spsr); ++ ctxt->gp_regs.regs.pc = read_sysreg_el2(elr); ++ ctxt->gp_regs.regs.pstate = read_sysreg_el2(spsr); + } + + static hyp_alternate_select(__sysreg_call_save_host_state, +@@ -89,11 +89,8 @@ static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctx + write_sysreg(ctxt->sys_regs[ACTLR_EL1], actlr_el1); + write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0); + write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0); +- write_sysreg(ctxt->sys_regs[TPIDR_EL1], tpidr_el1); + write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1); + write_sysreg(ctxt->gp_regs.regs.sp, sp_el0); +- write_sysreg_el2(ctxt->gp_regs.regs.pc, elr); +- write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr); + } + + static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt) +@@ -115,10 +112,13 @@ static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt) + write_sysreg_el1(ctxt->sys_regs[AMAIR_EL1], amair); + write_sysreg_el1(ctxt->sys_regs[CNTKCTL_EL1], cntkctl); + write_sysreg(ctxt->sys_regs[PAR_EL1], par_el1); ++ write_sysreg(ctxt->sys_regs[TPIDR_EL1], tpidr_el1); + + write_sysreg(ctxt->gp_regs.sp_el1, sp_el1); + write_sysreg_el1(ctxt->gp_regs.elr_el1, elr); + write_sysreg_el1(ctxt->gp_regs.spsr[KVM_SPSR_EL1],spsr); ++ write_sysreg_el2(ctxt->gp_regs.regs.pc, elr); ++ write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr); + } + + static hyp_alternate_select(__sysreg_call_restore_host_state, +@@ -183,3 +183,8 @@ void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) + if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY) + write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2); + } ++ ++void __hyp_text __kvm_set_tpidr_el2(u64 tpidr_el2) ++{ ++ asm("msr tpidr_el2, %0": : "r" (tpidr_el2)); ++} +diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c +index 5bc460884639..29a27a09f21f 100644 +--- a/arch/arm64/kvm/reset.c ++++ b/arch/arm64/kvm/reset.c +@@ -135,6 +135,10 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) + /* Reset PMU */ + kvm_pmu_vcpu_reset(vcpu); + ++ /* Default workaround setup is enabled (if supported) */ ++ if (kvm_arm_have_ssbd() == KVM_SSBD_KERNEL) ++ vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG; ++ + /* Reset timer */ + return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq); + } +diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c +index cb1e9c184b5a..513a63b9b991 100644 +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -26,6 +26,7 @@ + #include <linux/kallsyms.h> + #include <linux/random.h> + #include <linux/prctl.h> ++#include <linux/nmi.h> + + #include <asm/asm.h> + #include <asm/bootinfo.h> +@@ -633,28 +634,42 @@ unsigned long arch_align_stack(unsigned long sp) + return sp & ALMASK; + } + +-static void arch_dump_stack(void *info) +-{ +- struct pt_regs *regs; ++static DEFINE_PER_CPU(struct call_single_data, backtrace_csd); ++static struct cpumask backtrace_csd_busy; + +- regs = get_irq_regs(); +- +- if (regs) +- show_regs(regs); +- else +- dump_stack(); ++static void handle_backtrace(void *info) ++{ ++ nmi_cpu_backtrace(get_irq_regs()); ++ cpumask_clear_cpu(smp_processor_id(), &backtrace_csd_busy); + } + +-void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self) ++static void raise_backtrace(cpumask_t *mask) + { +- long this_cpu = get_cpu(); ++ struct call_single_data *csd; ++ int cpu; + +- if (cpumask_test_cpu(this_cpu, mask) && !exclude_self) +- dump_stack(); ++ for_each_cpu(cpu, mask) { ++ /* ++ * If we previously sent an IPI to the target CPU & it hasn't ++ * cleared its bit in the busy cpumask then it didn't handle ++ * our previous IPI & it's not safe for us to reuse the ++ * call_single_data_t. ++ */ ++ if (cpumask_test_and_set_cpu(cpu, &backtrace_csd_busy)) { ++ pr_warn("Unable to send backtrace IPI to CPU%u - perhaps it hung?\n", ++ cpu); ++ continue; ++ } + +- smp_call_function_many(mask, arch_dump_stack, NULL, 1); ++ csd = &per_cpu(backtrace_csd, cpu); ++ csd->func = handle_backtrace; ++ smp_call_function_single_async(cpu, csd); ++ } ++} + +- put_cpu(); ++void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self) ++{ ++ nmi_trigger_cpumask_backtrace(mask, exclude_self, raise_backtrace); + } + + int mips_get_process_fp_mode(struct task_struct *task) +diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h +index 8d8c24f3a963..742712b4bdc3 100644 +--- a/arch/x86/include/asm/asm.h ++++ b/arch/x86/include/asm/asm.h +@@ -45,6 +45,65 @@ + #define _ASM_SI __ASM_REG(si) + #define _ASM_DI __ASM_REG(di) + ++#ifndef __x86_64__ ++/* 32 bit */ ++ ++#define _ASM_ARG1 _ASM_AX ++#define _ASM_ARG2 _ASM_DX ++#define _ASM_ARG3 _ASM_CX ++ ++#define _ASM_ARG1L eax ++#define _ASM_ARG2L edx ++#define _ASM_ARG3L ecx ++ ++#define _ASM_ARG1W ax ++#define _ASM_ARG2W dx ++#define _ASM_ARG3W cx ++ ++#define _ASM_ARG1B al ++#define _ASM_ARG2B dl ++#define _ASM_ARG3B cl ++ ++#else ++/* 64 bit */ ++ ++#define _ASM_ARG1 _ASM_DI ++#define _ASM_ARG2 _ASM_SI ++#define _ASM_ARG3 _ASM_DX ++#define _ASM_ARG4 _ASM_CX ++#define _ASM_ARG5 r8 ++#define _ASM_ARG6 r9 ++ ++#define _ASM_ARG1Q rdi ++#define _ASM_ARG2Q rsi ++#define _ASM_ARG3Q rdx ++#define _ASM_ARG4Q rcx ++#define _ASM_ARG5Q r8 ++#define _ASM_ARG6Q r9 ++ ++#define _ASM_ARG1L edi ++#define _ASM_ARG2L esi ++#define _ASM_ARG3L edx ++#define _ASM_ARG4L ecx ++#define _ASM_ARG5L r8d ++#define _ASM_ARG6L r9d ++ ++#define _ASM_ARG1W di ++#define _ASM_ARG2W si ++#define _ASM_ARG3W dx ++#define _ASM_ARG4W cx ++#define _ASM_ARG5W r8w ++#define _ASM_ARG6W r9w ++ ++#define _ASM_ARG1B dil ++#define _ASM_ARG2B sil ++#define _ASM_ARG3B dl ++#define _ASM_ARG4B cl ++#define _ASM_ARG5B r8b ++#define _ASM_ARG6B r9b ++ ++#endif ++ + /* + * Macros to generate condition code outputs from inline assembly, + * The output operand must be type "bool". +diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h +index ac7692dcfa2e..8a8a6c66be9a 100644 +--- a/arch/x86/include/asm/irqflags.h ++++ b/arch/x86/include/asm/irqflags.h +@@ -12,7 +12,7 @@ + * Interrupt control: + */ + +-static inline unsigned long native_save_fl(void) ++extern inline unsigned long native_save_fl(void) + { + unsigned long flags; + +diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile +index 4c9c61517613..a9ba968621cb 100644 +--- a/arch/x86/kernel/Makefile ++++ b/arch/x86/kernel/Makefile +@@ -56,6 +56,7 @@ obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o + obj-y += tsc.o tsc_msr.o io_delay.o rtc.o + obj-y += pci-iommu_table.o + obj-y += resource.o ++obj-y += irqflags.o + + obj-y += process.o + obj-y += fpu/ +diff --git a/arch/x86/kernel/irqflags.S b/arch/x86/kernel/irqflags.S +new file mode 100644 +index 000000000000..ddeeaac8adda +--- /dev/null ++++ b/arch/x86/kernel/irqflags.S +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#include <asm/asm.h> ++#include <asm/export.h> ++#include <linux/linkage.h> ++ ++/* ++ * unsigned long native_save_fl(void) ++ */ ++ENTRY(native_save_fl) ++ pushf ++ pop %_ASM_AX ++ ret ++ENDPROC(native_save_fl) ++EXPORT_SYMBOL(native_save_fl) ++ ++/* ++ * void native_restore_fl(unsigned long flags) ++ * %eax/%rdi: flags ++ */ ++ENTRY(native_restore_fl) ++ push %_ASM_ARG1 ++ popf ++ ret ++ENDPROC(native_restore_fl) ++EXPORT_SYMBOL(native_restore_fl) +diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c +index d0fac641e717..a0b88f148990 100644 +--- a/drivers/atm/zatm.c ++++ b/drivers/atm/zatm.c +@@ -1483,6 +1483,8 @@ static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) + return -EFAULT; + if (pool < 0 || pool > ZATM_LAST_POOL) + return -EINVAL; ++ pool = array_index_nospec(pool, ++ ZATM_LAST_POOL + 1); + if (copy_from_user(&info, + &((struct zatm_pool_req __user *) arg)->info, + sizeof(info))) return -EFAULT; +diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c +index dae1e39139e9..c7524bbbaf98 100644 +--- a/drivers/crypto/amcc/crypto4xx_core.c ++++ b/drivers/crypto/amcc/crypto4xx_core.c +@@ -208,7 +208,7 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev) + dev->pdr_pa); + return -ENOMEM; + } +- memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); ++ memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); + dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device, + 256 * PPC4XX_NUM_PD, + &dev->shadow_sa_pool_pa, +@@ -241,13 +241,15 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev) + + static void crypto4xx_destroy_pdr(struct crypto4xx_device *dev) + { +- if (dev->pdr != NULL) ++ if (dev->pdr) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_pd) * PPC4XX_NUM_PD, + dev->pdr, dev->pdr_pa); ++ + if (dev->shadow_sa_pool) + dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD, + dev->shadow_sa_pool, dev->shadow_sa_pool_pa); ++ + if (dev->shadow_sr_pool) + dma_free_coherent(dev->core_dev->device, + sizeof(struct sa_state_record) * PPC4XX_NUM_PD, +@@ -417,12 +419,12 @@ static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev) + + static void crypto4xx_destroy_sdr(struct crypto4xx_device *dev) + { +- if (dev->sdr != NULL) ++ if (dev->sdr) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_sd) * PPC4XX_NUM_SD, + dev->sdr, dev->sdr_pa); + +- if (dev->scatter_buffer_va != NULL) ++ if (dev->scatter_buffer_va) + dma_free_coherent(dev->core_dev->device, + dev->scatter_buffer_size * PPC4XX_NUM_SD, + dev->scatter_buffer_va, +@@ -1034,12 +1036,10 @@ int crypto4xx_register_alg(struct crypto4xx_device *sec_dev, + break; + } + +- if (rc) { +- list_del(&alg->entry); ++ if (rc) + kfree(alg); +- } else { ++ else + list_add_tail(&alg->entry, &sec_dev->alg_list); +- } + } + + return 0; +@@ -1193,7 +1193,7 @@ static int crypto4xx_probe(struct platform_device *ofdev) + + rc = crypto4xx_build_gdr(core_dev->dev); + if (rc) +- goto err_build_gdr; ++ goto err_build_pdr; + + rc = crypto4xx_build_sdr(core_dev->dev); + if (rc) +@@ -1236,12 +1236,11 @@ static int crypto4xx_probe(struct platform_device *ofdev) + err_request_irq: + irq_dispose_mapping(core_dev->irq); + tasklet_kill(&core_dev->tasklet); +- crypto4xx_destroy_sdr(core_dev->dev); + err_build_sdr: ++ crypto4xx_destroy_sdr(core_dev->dev); + crypto4xx_destroy_gdr(core_dev->dev); +-err_build_gdr: +- crypto4xx_destroy_pdr(core_dev->dev); + err_build_pdr: ++ crypto4xx_destroy_pdr(core_dev->dev); + kfree(core_dev->dev); + err_alloc_dev: + kfree(core_dev); +diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c +index 9cf7fcd28034..16a7df2a0246 100644 +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -172,7 +172,8 @@ static ssize_t m25p80_read(struct spi_nor *nor, loff_t from, size_t len, + + t[1].rx_buf = buf; + t[1].rx_nbits = m25p80_rx_nbits(nor); +- t[1].len = min(len, spi_max_transfer_size(spi)); ++ t[1].len = min3(len, spi_max_transfer_size(spi), ++ spi_max_message_size(spi) - t[0].len); + spi_message_add_tail(&t[1], &m); + + ret = spi_sync(spi, &m); +diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c +index 08d91efceed0..c4078401b7de 100644 +--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c ++++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c +@@ -1063,7 +1063,8 @@ static int bcm_enet_open(struct net_device *dev) + val = enet_readl(priv, ENET_CTL_REG); + val |= ENET_CTL_ENABLE_MASK; + enet_writel(priv, val, ENET_CTL_REG); +- enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); ++ if (priv->dma_has_sram) ++ enet_dma_writel(priv, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); + enet_dmac_writel(priv, priv->dma_chan_en_mask, + ENETDMAC_CHANCFG, priv->rx_chan); + +@@ -1790,7 +1791,9 @@ static int bcm_enet_probe(struct platform_device *pdev) + ret = PTR_ERR(priv->mac_clk); + goto out; + } +- clk_prepare_enable(priv->mac_clk); ++ ret = clk_prepare_enable(priv->mac_clk); ++ if (ret) ++ goto out_put_clk_mac; + + /* initialize default and fetch platform data */ + priv->rx_ring_size = BCMENET_DEF_RX_DESC; +@@ -1822,9 +1825,11 @@ static int bcm_enet_probe(struct platform_device *pdev) + if (IS_ERR(priv->phy_clk)) { + ret = PTR_ERR(priv->phy_clk); + priv->phy_clk = NULL; +- goto out_put_clk_mac; ++ goto out_disable_clk_mac; + } +- clk_prepare_enable(priv->phy_clk); ++ ret = clk_prepare_enable(priv->phy_clk); ++ if (ret) ++ goto out_put_clk_phy; + } + + /* do minimal hardware init to be able to probe mii bus */ +@@ -1915,13 +1920,16 @@ static int bcm_enet_probe(struct platform_device *pdev) + out_uninit_hw: + /* turn off mdc clock */ + enet_writel(priv, 0, ENET_MIISC_REG); +- if (priv->phy_clk) { ++ if (priv->phy_clk) + clk_disable_unprepare(priv->phy_clk); ++ ++out_put_clk_phy: ++ if (priv->phy_clk) + clk_put(priv->phy_clk); +- } + +-out_put_clk_mac: ++out_disable_clk_mac: + clk_disable_unprepare(priv->mac_clk); ++out_put_clk_mac: + clk_put(priv->mac_clk); + out: + free_netdev(dev); +@@ -2766,7 +2774,9 @@ static int bcm_enetsw_probe(struct platform_device *pdev) + ret = PTR_ERR(priv->mac_clk); + goto out_unmap; + } +- clk_enable(priv->mac_clk); ++ ret = clk_prepare_enable(priv->mac_clk); ++ if (ret) ++ goto out_put_clk; + + priv->rx_chan = 0; + priv->tx_chan = 1; +@@ -2787,7 +2797,7 @@ static int bcm_enetsw_probe(struct platform_device *pdev) + + ret = register_netdev(dev); + if (ret) +- goto out_put_clk; ++ goto out_disable_clk; + + netif_carrier_off(dev); + platform_set_drvdata(pdev, dev); +@@ -2796,6 +2806,9 @@ static int bcm_enetsw_probe(struct platform_device *pdev) + + return 0; + ++out_disable_clk: ++ clk_disable_unprepare(priv->mac_clk); ++ + out_put_clk: + clk_put(priv->mac_clk); + +@@ -2827,6 +2840,9 @@ static int bcm_enetsw_remove(struct platform_device *pdev) + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + ++ clk_disable_unprepare(priv->mac_clk); ++ clk_put(priv->mac_clk); ++ + free_netdev(dev); + return 0; + } +diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +index 43da891fab97..dc0efbd91c32 100644 +--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +@@ -50,6 +50,7 @@ + #include <linux/stringify.h> + #include <linux/sched.h> + #include <linux/slab.h> ++#include <linux/nospec.h> + #include <asm/uaccess.h> + + #include "common.h" +@@ -2259,6 +2260,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) + + if (t.qset_idx >= nqsets) + return -EINVAL; ++ t.qset_idx = array_index_nospec(t.qset_idx, nqsets); + + q = &adapter->params.sge.qset[q1 + t.qset_idx]; + t.rspq_size = q->rspq_size; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index 6631fb0782d7..9680c8805178 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -784,6 +784,7 @@ static void cmd_work_handler(struct work_struct *work) + struct semaphore *sem; + unsigned long flags; + int alloc_ret; ++ int cmd_mode; + + sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; + down(sem); +@@ -830,6 +831,7 @@ static void cmd_work_handler(struct work_struct *work) + set_signature(ent, !cmd->checksum_disabled); + dump_command(dev, ent, 1); + ent->ts1 = ktime_get_ns(); ++ cmd_mode = cmd->mode; + + if (ent->callback) + schedule_delayed_work(&ent->cb_timeout_work, cb_timeout); +@@ -854,7 +856,7 @@ static void cmd_work_handler(struct work_struct *work) + iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell); + mmiowb(); + /* if not in polling don't use ent after this point */ +- if (cmd->mode == CMD_MODE_POLLING) { ++ if (cmd_mode == CMD_MODE_POLLING) { + poll_timeout(ent); + /* make sure we read the descriptor after ownership is SW */ + rmb(); +@@ -1256,7 +1258,7 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf, + { + struct mlx5_core_dev *dev = filp->private_data; + struct mlx5_cmd_debug *dbg = &dev->cmd.dbg; +- char outlen_str[8]; ++ char outlen_str[8] = {0}; + int outlen; + void *ptr; + int err; +@@ -1271,8 +1273,6 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf, + if (copy_from_user(outlen_str, buf, count)) + return -EFAULT; + +- outlen_str[7] = 0; +- + err = sscanf(outlen_str, "%d", &outlen); + if (err < 0) + return err; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index 34e7184e23c9..43d7c8378fb4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -575,7 +575,7 @@ EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc); + static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, + int inlen) + { +- u32 out[MLX5_ST_SZ_DW(qtct_reg)]; ++ u32 out[MLX5_ST_SZ_DW(qetc_reg)]; + + if (!MLX5_CAP_GEN(mdev, ets)) + return -ENOTSUPP; +@@ -587,7 +587,7 @@ static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in, + static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out, + int outlen) + { +- u32 in[MLX5_ST_SZ_DW(qtct_reg)]; ++ u32 in[MLX5_ST_SZ_DW(qetc_reg)]; + + if (!MLX5_CAP_GEN(mdev, ets)) + return -ENOTSUPP; +diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +index 9d59cb85c012..7b6824e560d2 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +@@ -677,9 +677,9 @@ qed_dcbx_get_local_lldp_params(struct qed_hwfn *p_hwfn, + p_local = &p_hwfn->p_dcbx_info->lldp_local[LLDP_NEAREST_BRIDGE]; + + memcpy(params->lldp_local.local_chassis_id, p_local->local_chassis_id, +- ARRAY_SIZE(p_local->local_chassis_id)); ++ sizeof(p_local->local_chassis_id)); + memcpy(params->lldp_local.local_port_id, p_local->local_port_id, +- ARRAY_SIZE(p_local->local_port_id)); ++ sizeof(p_local->local_port_id)); + } + + static void +@@ -692,9 +692,9 @@ qed_dcbx_get_remote_lldp_params(struct qed_hwfn *p_hwfn, + p_remote = &p_hwfn->p_dcbx_info->lldp_remote[LLDP_NEAREST_BRIDGE]; + + memcpy(params->lldp_remote.peer_chassis_id, p_remote->peer_chassis_id, +- ARRAY_SIZE(p_remote->peer_chassis_id)); ++ sizeof(p_remote->peer_chassis_id)); + memcpy(params->lldp_remote.peer_port_id, p_remote->peer_port_id, +- ARRAY_SIZE(p_remote->peer_port_id)); ++ sizeof(p_remote->peer_port_id)); + } + + static int +diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c +index 0b949c6d83fc..f36bd0bd37da 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_main.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_main.c +@@ -23,6 +23,7 @@ + #include <linux/vmalloc.h> + #include <linux/qed/qed_if.h> + #include <linux/qed/qed_ll2_if.h> ++#include <linux/crash_dump.h> + + #include "qed.h" + #include "qed_sriov.h" +@@ -701,6 +702,14 @@ static int qed_slowpath_setup_int(struct qed_dev *cdev, + /* We want a minimum of one slowpath and one fastpath vector per hwfn */ + cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; + ++ if (is_kdump_kernel()) { ++ DP_INFO(cdev, ++ "Kdump kernel: Limit the max number of requested MSI-X vectors to %hd\n", ++ cdev->int_params.in.min_msix_cnt); ++ cdev->int_params.in.num_vectors = ++ cdev->int_params.in.min_msix_cnt; ++ } ++ + rc = qed_set_int_mode(cdev, false); + if (rc) { + DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); +diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c +index d6ad0fbd054e..920321bf4bb6 100644 +--- a/drivers/net/ethernet/sun/sungem.c ++++ b/drivers/net/ethernet/sun/sungem.c +@@ -59,8 +59,7 @@ + #include <linux/sungem_phy.h> + #include "sungem.h" + +-/* Stripping FCS is causing problems, disabled for now */ +-#undef STRIP_FCS ++#define STRIP_FCS + + #define DEFAULT_MSG (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ +@@ -434,7 +433,7 @@ static int gem_rxmac_reset(struct gem *gp) + writel(desc_dma & 0xffffffff, gp->regs + RXDMA_DBLOW); + writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK); + val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) | +- ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128); ++ (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128); + writel(val, gp->regs + RXDMA_CFG); + if (readl(gp->regs + GREG_BIFCFG) & GREG_BIFCFG_M66EN) + writel(((5 & RXDMA_BLANK_IPKTS) | +@@ -759,7 +758,6 @@ static int gem_rx(struct gem *gp, int work_to_do) + struct net_device *dev = gp->dev; + int entry, drops, work_done = 0; + u32 done; +- __sum16 csum; + + if (netif_msg_rx_status(gp)) + printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n", +@@ -854,9 +852,13 @@ static int gem_rx(struct gem *gp, int work_to_do) + skb = copy_skb; + } + +- csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff); +- skb->csum = csum_unfold(csum); +- skb->ip_summed = CHECKSUM_COMPLETE; ++ if (likely(dev->features & NETIF_F_RXCSUM)) { ++ __sum16 csum; ++ ++ csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff); ++ skb->csum = csum_unfold(csum); ++ skb->ip_summed = CHECKSUM_COMPLETE; ++ } + skb->protocol = eth_type_trans(skb, gp->dev); + + napi_gro_receive(&gp->napi, skb); +@@ -1754,7 +1756,7 @@ static void gem_init_dma(struct gem *gp) + writel(0, gp->regs + TXDMA_KICK); + + val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) | +- ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128); ++ (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128); + writel(val, gp->regs + RXDMA_CFG); + + writel(desc_dma >> 32, gp->regs + RXDMA_DBHI); +@@ -2972,8 +2974,8 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + pci_set_drvdata(pdev, dev); + + /* We can do scatter/gather and HW checksum */ +- dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM; +- dev->features |= dev->hw_features | NETIF_F_RXCSUM; ++ dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; ++ dev->features = dev->hw_features; + if (pci_using_dac) + dev->features |= NETIF_F_HIGHDMA; + +diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c +index dfbc4ef6d507..24eb5755604f 100644 +--- a/drivers/net/ipvlan/ipvlan_main.c ++++ b/drivers/net/ipvlan/ipvlan_main.c +@@ -525,7 +525,8 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, + ipvlan->dev = dev; + ipvlan->port = port; + ipvlan->sfeatures = IPVLAN_FEATURES; +- ipvlan_adjust_mtu(ipvlan, phy_dev); ++ if (!tb[IFLA_MTU]) ++ ipvlan_adjust_mtu(ipvlan, phy_dev); + INIT_LIST_HEAD(&ipvlan->addrs); + + /* TODO Probably put random address here to be presented to the +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index f5a96678494b..5e0626c80b81 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -2964,6 +2964,7 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) + pkt_cnt = 0; + count = 0; + length = 0; ++ spin_lock_irqsave(&tqp->lock, flags); + for (skb = tqp->next; pkt_cnt < tqp->qlen; skb = skb->next) { + if (skb_is_gso(skb)) { + if (pkt_cnt) { +@@ -2972,7 +2973,8 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) + } + count = 1; + length = skb->len - TX_OVERHEAD; +- skb2 = skb_dequeue(tqp); ++ __skb_unlink(skb, tqp); ++ spin_unlock_irqrestore(&tqp->lock, flags); + goto gso_skb; + } + +@@ -2981,6 +2983,7 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) + skb_totallen = skb->len + roundup(skb_totallen, sizeof(u32)); + pkt_cnt++; + } ++ spin_unlock_irqrestore(&tqp->lock, flags); + + /* copy to a single skb */ + skb = alloc_skb(skb_totallen, GFP_ATOMIC); +diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c +index 85bc0ca61389..6d654d65f8a0 100644 +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -946,6 +946,7 @@ static const struct usb_device_id products[] = { + {QMI_FIXED_INTF(0x413c, 0x81b3, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ + {QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */ + {QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */ ++ {QMI_FIXED_INTF(0x413c, 0x81d7, 1)}, /* Dell Wireless 5821e */ + {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ + {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */ + {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index d3d89b05f66e..5988674818ed 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -3327,7 +3327,8 @@ static int rtl8152_close(struct net_device *netdev) + #ifdef CONFIG_PM_SLEEP + unregister_pm_notifier(&tp->pm_notifier); + #endif +- napi_disable(&tp->napi); ++ if (!test_bit(RTL8152_UNPLUG, &tp->flags)) ++ napi_disable(&tp->napi); + clear_bit(WORK_ENABLE, &tp->flags); + usb_kill_urb(tp->intr_urb); + cancel_delayed_work_sync(&tp->schedule); +diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c +index 4da4e458142c..9526643312d9 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/core.c ++++ b/drivers/net/wireless/realtek/rtlwifi/core.c +@@ -131,7 +131,6 @@ static void rtl_fw_do_work(const struct firmware *firmware, void *context, + firmware->size); + rtlpriv->rtlhal.wowlan_fwsize = firmware->size; + } +- rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); + } + +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index 487586e2d8b9..353c93bc459b 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -1052,7 +1052,8 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) + if (ubufs) + vhost_net_ubuf_put_wait_and_free(ubufs); + err_ubufs: +- sockfd_put(sock); ++ if (sock) ++ sockfd_put(sock); + err_vq: + mutex_unlock(&vq->mutex); + err: +diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c +index f2961b13e8c5..c26d046adaaa 100644 +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -134,6 +134,19 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, + return err; + } + ++static int ocfs2_lock_get_block(struct inode *inode, sector_t iblock, ++ struct buffer_head *bh_result, int create) ++{ ++ int ret = 0; ++ struct ocfs2_inode_info *oi = OCFS2_I(inode); ++ ++ down_read(&oi->ip_alloc_sem); ++ ret = ocfs2_get_block(inode, iblock, bh_result, create); ++ up_read(&oi->ip_alloc_sem); ++ ++ return ret; ++} ++ + int ocfs2_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) + { +@@ -2120,7 +2133,7 @@ static void ocfs2_dio_free_write_ctx(struct inode *inode, + * called like this: dio->get_blocks(dio->inode, fs_startblk, + * fs_count, map_bh, dio->rw == WRITE); + */ +-static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock, ++static int ocfs2_dio_wr_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) + { + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); +@@ -2146,12 +2159,9 @@ static int ocfs2_dio_get_block(struct inode *inode, sector_t iblock, + * while file size will be changed. + */ + if (pos + total_len <= i_size_read(inode)) { +- down_read(&oi->ip_alloc_sem); +- /* This is the fast path for re-write. */ +- ret = ocfs2_get_block(inode, iblock, bh_result, create); +- +- up_read(&oi->ip_alloc_sem); + ++ /* This is the fast path for re-write. */ ++ ret = ocfs2_lock_get_block(inode, iblock, bh_result, create); + if (buffer_mapped(bh_result) && + !buffer_new(bh_result) && + ret == 0) +@@ -2416,9 +2426,9 @@ static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) + return 0; + + if (iov_iter_rw(iter) == READ) +- get_block = ocfs2_get_block; ++ get_block = ocfs2_lock_get_block; + else +- get_block = ocfs2_dio_get_block; ++ get_block = ocfs2_dio_wr_get_block; + + return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, + iter, get_block, +diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c +index b17d180bdc16..c204ac9b49e5 100644 +--- a/fs/ocfs2/cluster/nodemanager.c ++++ b/fs/ocfs2/cluster/nodemanager.c +@@ -40,6 +40,9 @@ char *o2nm_fence_method_desc[O2NM_FENCE_METHODS] = { + "panic", /* O2NM_FENCE_PANIC */ + }; + ++static inline void o2nm_lock_subsystem(void); ++static inline void o2nm_unlock_subsystem(void); ++ + struct o2nm_node *o2nm_get_node_by_num(u8 node_num) + { + struct o2nm_node *node = NULL; +@@ -181,7 +184,10 @@ static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node) + { + /* through the first node_set .parent + * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */ +- return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ if (node->nd_item.ci_parent) ++ return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent); ++ else ++ return NULL; + } + + enum { +@@ -194,7 +200,7 @@ static ssize_t o2nm_node_num_store(struct config_item *item, const char *page, + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + int ret = 0; +@@ -214,6 +220,13 @@ static ssize_t o2nm_node_num_store(struct config_item *item, const char *page, + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + write_lock(&cluster->cl_nodes_lock); + if (cluster->cl_nodes[tmp]) + ret = -EEXIST; +@@ -226,6 +239,8 @@ static ssize_t o2nm_node_num_store(struct config_item *item, const char *page, + set_bit(tmp, cluster->cl_nodes_bitmap); + } + write_unlock(&cluster->cl_nodes_lock); ++ o2nm_unlock_subsystem(); ++ + if (ret) + return ret; + +@@ -269,7 +284,7 @@ static ssize_t o2nm_node_ipv4_address_store(struct config_item *item, + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + int ret, i; + struct rb_node **p, *parent; + unsigned int octets[4]; +@@ -286,6 +301,13 @@ static ssize_t o2nm_node_ipv4_address_store(struct config_item *item, + be32_add_cpu(&ipv4_addr, octets[i] << (i * 8)); + } + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ o2nm_unlock_subsystem(); ++ return -EINVAL; ++ } ++ + ret = 0; + write_lock(&cluster->cl_nodes_lock); + if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent)) +@@ -298,6 +320,8 @@ static ssize_t o2nm_node_ipv4_address_store(struct config_item *item, + rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree); + } + write_unlock(&cluster->cl_nodes_lock); ++ o2nm_unlock_subsystem(); ++ + if (ret) + return ret; + +@@ -315,7 +339,7 @@ static ssize_t o2nm_node_local_store(struct config_item *item, const char *page, + size_t count) + { + struct o2nm_node *node = to_o2nm_node(item); +- struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node); ++ struct o2nm_cluster *cluster; + unsigned long tmp; + char *p = (char *)page; + ssize_t ret; +@@ -333,17 +357,26 @@ static ssize_t o2nm_node_local_store(struct config_item *item, const char *page, + !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes)) + return -EINVAL; /* XXX */ + ++ o2nm_lock_subsystem(); ++ cluster = to_o2nm_cluster_from_node(node); ++ if (!cluster) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + /* the only failure case is trying to set a new local node + * when a different one is already set */ + if (tmp && tmp == cluster->cl_has_local && +- cluster->cl_local_node != node->nd_num) +- return -EBUSY; ++ cluster->cl_local_node != node->nd_num) { ++ ret = -EBUSY; ++ goto out; ++ } + + /* bring up the rx thread if we're setting the new local node. */ + if (tmp && !cluster->cl_has_local) { + ret = o2net_start_listening(node); + if (ret) +- return ret; ++ goto out; + } + + if (!tmp && cluster->cl_has_local && +@@ -358,7 +391,11 @@ static ssize_t o2nm_node_local_store(struct config_item *item, const char *page, + cluster->cl_local_node = node->nd_num; + } + +- return count; ++ ret = count; ++ ++out: ++ o2nm_unlock_subsystem(); ++ return ret; + } + + CONFIGFS_ATTR(o2nm_node_, num); +@@ -738,6 +775,16 @@ static struct o2nm_cluster_group o2nm_cluster_group = { + }, + }; + ++static inline void o2nm_lock_subsystem(void) ++{ ++ mutex_lock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ ++static inline void o2nm_unlock_subsystem(void) ++{ ++ mutex_unlock(&o2nm_cluster_group.cs_subsys.su_mutex); ++} ++ + int o2nm_depend_item(struct config_item *item) + { + return configfs_depend_item(&o2nm_cluster_group.cs_subsys, item); +diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c +index 4f3f928076f3..92470e5973f8 100644 +--- a/fs/reiserfs/prints.c ++++ b/fs/reiserfs/prints.c +@@ -76,83 +76,99 @@ static char *le_type(struct reiserfs_key *key) + } + + /* %k */ +-static void sprintf_le_key(char *buf, struct reiserfs_key *key) ++static int scnprintf_le_key(char *buf, size_t size, struct reiserfs_key *key) + { + if (key) +- sprintf(buf, "[%d %d %s %s]", le32_to_cpu(key->k_dir_id), +- le32_to_cpu(key->k_objectid), le_offset(key), +- le_type(key)); ++ return scnprintf(buf, size, "[%d %d %s %s]", ++ le32_to_cpu(key->k_dir_id), ++ le32_to_cpu(key->k_objectid), le_offset(key), ++ le_type(key)); + else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + } + + /* %K */ +-static void sprintf_cpu_key(char *buf, struct cpu_key *key) ++static int scnprintf_cpu_key(char *buf, size_t size, struct cpu_key *key) + { + if (key) +- sprintf(buf, "[%d %d %s %s]", key->on_disk_key.k_dir_id, +- key->on_disk_key.k_objectid, reiserfs_cpu_offset(key), +- cpu_type(key)); ++ return scnprintf(buf, size, "[%d %d %s %s]", ++ key->on_disk_key.k_dir_id, ++ key->on_disk_key.k_objectid, ++ reiserfs_cpu_offset(key), cpu_type(key)); + else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + } + +-static void sprintf_de_head(char *buf, struct reiserfs_de_head *deh) ++static int scnprintf_de_head(char *buf, size_t size, ++ struct reiserfs_de_head *deh) + { + if (deh) +- sprintf(buf, +- "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", +- deh_offset(deh), deh_dir_id(deh), deh_objectid(deh), +- deh_location(deh), deh_state(deh)); ++ return scnprintf(buf, size, ++ "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", ++ deh_offset(deh), deh_dir_id(deh), ++ deh_objectid(deh), deh_location(deh), ++ deh_state(deh)); + else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + + } + +-static void sprintf_item_head(char *buf, struct item_head *ih) ++static int scnprintf_item_head(char *buf, size_t size, struct item_head *ih) + { + if (ih) { +- strcpy(buf, +- (ih_version(ih) == KEY_FORMAT_3_6) ? "*3.6* " : "*3.5*"); +- sprintf_le_key(buf + strlen(buf), &(ih->ih_key)); +- sprintf(buf + strlen(buf), ", item_len %d, item_location %d, " +- "free_space(entry_count) %d", +- ih_item_len(ih), ih_location(ih), ih_free_space(ih)); ++ char *p = buf; ++ char * const end = buf + size; ++ ++ p += scnprintf(p, end - p, "%s", ++ (ih_version(ih) == KEY_FORMAT_3_6) ? ++ "*3.6* " : "*3.5*"); ++ ++ p += scnprintf_le_key(p, end - p, &ih->ih_key); ++ ++ p += scnprintf(p, end - p, ++ ", item_len %d, item_location %d, free_space(entry_count) %d", ++ ih_item_len(ih), ih_location(ih), ++ ih_free_space(ih)); ++ return p - buf; + } else +- sprintf(buf, "[NULL]"); ++ return scnprintf(buf, size, "[NULL]"); + } + +-static void sprintf_direntry(char *buf, struct reiserfs_dir_entry *de) ++static int scnprintf_direntry(char *buf, size_t size, ++ struct reiserfs_dir_entry *de) + { + char name[20]; + + memcpy(name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen); + name[de->de_namelen > 19 ? 19 : de->de_namelen] = 0; +- sprintf(buf, "\"%s\"==>[%d %d]", name, de->de_dir_id, de->de_objectid); ++ return scnprintf(buf, size, "\"%s\"==>[%d %d]", ++ name, de->de_dir_id, de->de_objectid); + } + +-static void sprintf_block_head(char *buf, struct buffer_head *bh) ++static int scnprintf_block_head(char *buf, size_t size, struct buffer_head *bh) + { +- sprintf(buf, "level=%d, nr_items=%d, free_space=%d rdkey ", +- B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh)); ++ return scnprintf(buf, size, ++ "level=%d, nr_items=%d, free_space=%d rdkey ", ++ B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh)); + } + +-static void sprintf_buffer_head(char *buf, struct buffer_head *bh) ++static int scnprintf_buffer_head(char *buf, size_t size, struct buffer_head *bh) + { +- sprintf(buf, +- "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)", +- bh->b_bdev, bh->b_size, +- (unsigned long long)bh->b_blocknr, atomic_read(&(bh->b_count)), +- bh->b_state, bh->b_page, +- buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE", +- buffer_dirty(bh) ? "DIRTY" : "CLEAN", +- buffer_locked(bh) ? "LOCKED" : "UNLOCKED"); ++ return scnprintf(buf, size, ++ "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)", ++ bh->b_bdev, bh->b_size, ++ (unsigned long long)bh->b_blocknr, ++ atomic_read(&(bh->b_count)), ++ bh->b_state, bh->b_page, ++ buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE", ++ buffer_dirty(bh) ? "DIRTY" : "CLEAN", ++ buffer_locked(bh) ? "LOCKED" : "UNLOCKED"); + } + +-static void sprintf_disk_child(char *buf, struct disk_child *dc) ++static int scnprintf_disk_child(char *buf, size_t size, struct disk_child *dc) + { +- sprintf(buf, "[dc_number=%d, dc_size=%u]", dc_block_number(dc), +- dc_size(dc)); ++ return scnprintf(buf, size, "[dc_number=%d, dc_size=%u]", ++ dc_block_number(dc), dc_size(dc)); + } + + static char *is_there_reiserfs_struct(char *fmt, int *what) +@@ -189,55 +205,60 @@ static void prepare_error_buf(const char *fmt, va_list args) + char *fmt1 = fmt_buf; + char *k; + char *p = error_buf; ++ char * const end = &error_buf[sizeof(error_buf)]; + int what; + + spin_lock(&error_lock); + +- strcpy(fmt1, fmt); ++ if (WARN_ON(strscpy(fmt_buf, fmt, sizeof(fmt_buf)) < 0)) { ++ strscpy(error_buf, "format string too long", end - error_buf); ++ goto out_unlock; ++ } + + while ((k = is_there_reiserfs_struct(fmt1, &what)) != NULL) { + *k = 0; + +- p += vsprintf(p, fmt1, args); ++ p += vscnprintf(p, end - p, fmt1, args); + + switch (what) { + case 'k': +- sprintf_le_key(p, va_arg(args, struct reiserfs_key *)); ++ p += scnprintf_le_key(p, end - p, ++ va_arg(args, struct reiserfs_key *)); + break; + case 'K': +- sprintf_cpu_key(p, va_arg(args, struct cpu_key *)); ++ p += scnprintf_cpu_key(p, end - p, ++ va_arg(args, struct cpu_key *)); + break; + case 'h': +- sprintf_item_head(p, va_arg(args, struct item_head *)); ++ p += scnprintf_item_head(p, end - p, ++ va_arg(args, struct item_head *)); + break; + case 't': +- sprintf_direntry(p, +- va_arg(args, +- struct reiserfs_dir_entry *)); ++ p += scnprintf_direntry(p, end - p, ++ va_arg(args, struct reiserfs_dir_entry *)); + break; + case 'y': +- sprintf_disk_child(p, +- va_arg(args, struct disk_child *)); ++ p += scnprintf_disk_child(p, end - p, ++ va_arg(args, struct disk_child *)); + break; + case 'z': +- sprintf_block_head(p, +- va_arg(args, struct buffer_head *)); ++ p += scnprintf_block_head(p, end - p, ++ va_arg(args, struct buffer_head *)); + break; + case 'b': +- sprintf_buffer_head(p, +- va_arg(args, struct buffer_head *)); ++ p += scnprintf_buffer_head(p, end - p, ++ va_arg(args, struct buffer_head *)); + break; + case 'a': +- sprintf_de_head(p, +- va_arg(args, +- struct reiserfs_de_head *)); ++ p += scnprintf_de_head(p, end - p, ++ va_arg(args, struct reiserfs_de_head *)); + break; + } + +- p += strlen(p); + fmt1 = k + 2; + } +- vsprintf(p, fmt1, args); ++ p += vscnprintf(p, end - p, fmt1, args); ++out_unlock: + spin_unlock(&error_lock); + + } +diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h +index a031897fca76..ca1d2cc2cdfa 100644 +--- a/include/linux/arm-smccc.h ++++ b/include/linux/arm-smccc.h +@@ -80,6 +80,11 @@ + ARM_SMCCC_SMC_32, \ + 0, 0x8000) + ++#define ARM_SMCCC_ARCH_WORKAROUND_2 \ ++ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ++ ARM_SMCCC_SMC_32, \ ++ 0, 0x7fff) ++ + #ifndef __ASSEMBLY__ + + #include <linux/linkage.h> +@@ -291,5 +296,10 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, + */ + #define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) + ++/* Return codes defined in ARM DEN 0070A */ ++#define SMCCC_RET_SUCCESS 0 ++#define SMCCC_RET_NOT_SUPPORTED -1 ++#define SMCCC_RET_NOT_REQUIRED -2 ++ + #endif /*__ASSEMBLY__*/ + #endif /*__LINUX_ARM_SMCCC_H*/ +diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h +index ad793c69cc46..8e82e3373eaf 100644 +--- a/include/linux/compiler-gcc.h ++++ b/include/linux/compiler-gcc.h +@@ -64,22 +64,41 @@ + #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) + #endif + ++/* ++ * Feature detection for gnu_inline (gnu89 extern inline semantics). Either ++ * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics, ++ * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not ++ * defined so the gnu89 semantics are the default. ++ */ ++#ifdef __GNUC_STDC_INLINE__ ++# define __gnu_inline __attribute__((gnu_inline)) ++#else ++# define __gnu_inline ++#endif ++ + /* + * Force always-inline if the user requests it so via the .config, +- * or if gcc is too old: ++ * or if gcc is too old. ++ * GCC does not warn about unused static inline functions for ++ * -Wunused-function. This turns out to avoid the need for complex #ifdef ++ * directives. Suppress the warning in clang as well by using "unused" ++ * function attribute, which is redundant but not harmful for gcc. ++ * Prefer gnu_inline, so that extern inline functions do not emit an ++ * externally visible function. This makes extern inline behave as per gnu89 ++ * semantics rather than c99. This prevents multiple symbol definition errors ++ * of extern inline functions at link time. ++ * A lot of inline functions can cause havoc with function tracing. + */ + #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \ + !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4) +-#define inline inline __attribute__((always_inline)) notrace +-#define __inline__ __inline__ __attribute__((always_inline)) notrace +-#define __inline __inline __attribute__((always_inline)) notrace ++#define inline \ ++ inline __attribute__((always_inline, unused)) notrace __gnu_inline + #else +-/* A lot of inline functions can cause havoc with function tracing */ +-#define inline inline notrace +-#define __inline__ __inline__ notrace +-#define __inline __inline notrace ++#define inline inline __attribute__((unused)) notrace __gnu_inline + #endif + ++#define __inline__ inline ++#define __inline inline + #define __always_inline inline __attribute__((always_inline)) + #define noinline __attribute__((noinline)) + +diff --git a/include/linux/string.h b/include/linux/string.h +index 0c88c0a1a72b..60042e5e88ff 100644 +--- a/include/linux/string.h ++++ b/include/linux/string.h +@@ -27,7 +27,7 @@ extern char * strncpy(char *,const char *, __kernel_size_t); + size_t strlcpy(char *, const char *, size_t); + #endif + #ifndef __HAVE_ARCH_STRSCPY +-ssize_t __must_check strscpy(char *, const char *, size_t); ++ssize_t strscpy(char *, const char *, size_t); + #endif + #ifndef __HAVE_ARCH_STRCAT + extern char * strcat(char *, const char *); +diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c +index cb6fbb525ba6..18c1f07e4f3b 100644 +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -406,6 +406,12 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par, + watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0); + if (IS_ERR(watcher)) + return PTR_ERR(watcher); ++ ++ if (watcher->family != NFPROTO_BRIDGE) { ++ module_put(watcher->me); ++ return -ENOENT; ++ } ++ + w->u.watcher = watcher; + + par->target = watcher; +@@ -727,6 +733,13 @@ ebt_check_entry(struct ebt_entry *e, struct net *net, + goto cleanup_watchers; + } + ++ /* Reject UNSPEC, xtables verdicts/return values are incompatible */ ++ if (target->family != NFPROTO_BRIDGE) { ++ module_put(target->me); ++ ret = -ENOENT; ++ goto cleanup_watchers; ++ } ++ + t->u.target = target; + if (t->u.target == &ebt_standard_target) { + if (gap < sizeof(struct ebt_standard_target)) { +diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c +index 119c04317d48..03fcf3ee1534 100644 +--- a/net/dccp/ccids/ccid3.c ++++ b/net/dccp/ccids/ccid3.c +@@ -599,7 +599,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, + { + struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); + struct dccp_sock *dp = dccp_sk(sk); +- ktime_t now = ktime_get_real(); ++ ktime_t now = ktime_get(); + s64 delta = 0; + + switch (fbtype) { +@@ -624,15 +624,14 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, + case CCID3_FBACK_PERIODIC: + delta = ktime_us_delta(now, hc->rx_tstamp_last_feedback); + if (delta <= 0) +- DCCP_BUG("delta (%ld) <= 0", (long)delta); +- else +- hc->rx_x_recv = scaled_div32(hc->rx_bytes_recv, delta); ++ delta = 1; ++ hc->rx_x_recv = scaled_div32(hc->rx_bytes_recv, delta); + break; + default: + return; + } + +- ccid3_pr_debug("Interval %ldusec, X_recv=%u, 1/p=%u\n", (long)delta, ++ ccid3_pr_debug("Interval %lldusec, X_recv=%u, 1/p=%u\n", delta, + hc->rx_x_recv, hc->rx_pinv); + + hc->rx_tstamp_last_feedback = now; +@@ -679,7 +678,8 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) + static u32 ccid3_first_li(struct sock *sk) + { + struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); +- u32 x_recv, p, delta; ++ u32 x_recv, p; ++ s64 delta; + u64 fval; + + if (hc->rx_rtt == 0) { +@@ -687,7 +687,9 @@ static u32 ccid3_first_li(struct sock *sk) + hc->rx_rtt = DCCP_FALLBACK_RTT; + } + +- delta = ktime_to_us(net_timedelta(hc->rx_tstamp_last_feedback)); ++ delta = ktime_us_delta(ktime_get(), hc->rx_tstamp_last_feedback); ++ if (delta <= 0) ++ delta = 1; + x_recv = scaled_div32(hc->rx_bytes_recv, delta); + if (x_recv == 0) { /* would also trigger divide-by-zero */ + DCCP_WARN("X_recv==0\n"); +diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c +index f0252768ecf4..5f5d9eafccf5 100644 +--- a/net/dns_resolver/dns_key.c ++++ b/net/dns_resolver/dns_key.c +@@ -87,35 +87,39 @@ dns_resolver_preparse(struct key_preparsed_payload *prep) + opt++; + kdebug("options: '%s'", opt); + do { ++ int opt_len, opt_nlen; + const char *eq; +- int opt_len, opt_nlen, opt_vlen, tmp; ++ char optval[128]; + + next_opt = memchr(opt, '#', end - opt) ?: end; + opt_len = next_opt - opt; +- if (opt_len <= 0 || opt_len > 128) { ++ if (opt_len <= 0 || opt_len > sizeof(optval)) { + pr_warn_ratelimited("Invalid option length (%d) for dns_resolver key\n", + opt_len); + return -EINVAL; + } + +- eq = memchr(opt, '=', opt_len) ?: end; +- opt_nlen = eq - opt; +- eq++; +- opt_vlen = next_opt - eq; /* will be -1 if no value */ ++ eq = memchr(opt, '=', opt_len); ++ if (eq) { ++ opt_nlen = eq - opt; ++ eq++; ++ memcpy(optval, eq, next_opt - eq); ++ optval[next_opt - eq] = '\0'; ++ } else { ++ opt_nlen = opt_len; ++ optval[0] = '\0'; ++ } + +- tmp = opt_vlen >= 0 ? opt_vlen : 0; +- kdebug("option '%*.*s' val '%*.*s'", +- opt_nlen, opt_nlen, opt, tmp, tmp, eq); ++ kdebug("option '%*.*s' val '%s'", ++ opt_nlen, opt_nlen, opt, optval); + + /* see if it's an error number representing a DNS error + * that's to be recorded as the result in this key */ + if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 && + memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) { + kdebug("dns error number option"); +- if (opt_vlen <= 0) +- goto bad_option_value; + +- ret = kstrtoul(eq, 10, &derrno); ++ ret = kstrtoul(optval, 10, &derrno); + if (ret < 0) + goto bad_option_value; + +diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c +index 566cfc50f7cf..51a0039cb318 100644 +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -212,8 +212,9 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, + { + struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; + struct tcp_fastopen_context *ctxt; +- int ret; + u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ ++ __le32 key[4]; ++ int ret, i; + + tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL); + if (!tbl.data) +@@ -222,11 +223,14 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, + rcu_read_lock(); + ctxt = rcu_dereference(tcp_fastopen_ctx); + if (ctxt) +- memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); ++ memcpy(key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); + else +- memset(user_key, 0, sizeof(user_key)); ++ memset(key, 0, sizeof(key)); + rcu_read_unlock(); + ++ for (i = 0; i < ARRAY_SIZE(key); i++) ++ user_key[i] = le32_to_cpu(key[i]); ++ + snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x", + user_key[0], user_key[1], user_key[2], user_key[3]); + ret = proc_dostring(&tbl, write, buffer, lenp, ppos); +@@ -242,12 +246,16 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write, + * first invocation of tcp_fastopen_cookie_gen + */ + tcp_fastopen_init_key_once(false); +- tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH); ++ ++ for (i = 0; i < ARRAY_SIZE(user_key); i++) ++ key[i] = cpu_to_le32(user_key[i]); ++ ++ tcp_fastopen_reset_cipher(key, TCP_FASTOPEN_KEY_LENGTH); + } + + bad_key: + pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n", +- user_key[0], user_key[1], user_key[2], user_key[3], ++ user_key[0], user_key[1], user_key[2], user_key[3], + (char *)tbl.data, ret); + kfree(tbl.data); + return ret; +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 8999e25fd0e1..be453aa8fce8 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3236,6 +3236,15 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, + + if (tcp_is_reno(tp)) { + tcp_remove_reno_sacks(sk, pkts_acked); ++ ++ /* If any of the cumulatively ACKed segments was ++ * retransmitted, non-SACK case cannot confirm that ++ * progress was due to original transmission due to ++ * lack of TCPCB_SACKED_ACKED bits even if some of ++ * the packets may have been never retransmitted. ++ */ ++ if (flag & FLAG_RETRANS_DATA_ACKED) ++ flag &= ~FLAG_ORIG_SACK_ACKED; + } else { + int delta; + +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index 64ec23388450..722a9db8c6a7 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -618,6 +618,8 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) + fq->q.meat == fq->q.len && + nf_ct_frag6_reasm(fq, skb, dev)) + ret = 0; ++ else ++ skb_dst_drop(skb); + + out_unlock: + spin_unlock_bh(&fq->q.lock); +diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c +index 3f266115294f..04759a0c3273 100644 +--- a/net/nfc/llcp_commands.c ++++ b/net/nfc/llcp_commands.c +@@ -753,11 +753,14 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, + pr_debug("Fragment %zd bytes remaining %zd", + frag_len, remaining_len); + +- pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, ++ pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, 0, + frag_len + LLCP_HEADER_SIZE, &err); + if (pdu == NULL) { +- pr_err("Could not allocate PDU\n"); +- continue; ++ pr_err("Could not allocate PDU (error=%d)\n", err); ++ len -= remaining_len; ++ if (len == 0) ++ len = err; ++ break; + } + + pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 2c4a47f29f36..ea601f7ca2f8 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2265,6 +2265,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + if (po->stats.stats1.tp_drops) + status |= TP_STATUS_LOSING; + } ++ ++ if (do_vnet && ++ __packet_rcv_vnet(skb, h.raw + macoff - ++ sizeof(struct virtio_net_hdr))) ++ goto drop_n_account; ++ + po->stats.stats1.tp_packets++; + if (copy_skb) { + status |= TP_STATUS_COPY; +@@ -2272,14 +2278,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + } + spin_unlock(&sk->sk_receive_queue.lock); + +- if (do_vnet) { +- if (__packet_rcv_vnet(skb, h.raw + macoff - +- sizeof(struct virtio_net_hdr))) { +- spin_lock(&sk->sk_receive_queue.lock); +- goto drop_n_account; +- } +- } +- + skb_copy_bits(skb, 0, h.raw + macoff, snaplen); + + if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp))) +diff --git a/net/rds/loop.c b/net/rds/loop.c +index f2bf78de5688..dac6218a460e 100644 +--- a/net/rds/loop.c ++++ b/net/rds/loop.c +@@ -193,4 +193,5 @@ struct rds_transport rds_loop_transport = { + .inc_copy_to_user = rds_message_inc_copy_to_user, + .inc_free = rds_loop_inc_free, + .t_name = "loopback", ++ .t_type = RDS_TRANS_LOOP, + }; +diff --git a/net/rds/rds.h b/net/rds/rds.h +index 30a51fec0f63..edfc3397aa24 100644 +--- a/net/rds/rds.h ++++ b/net/rds/rds.h +@@ -440,6 +440,11 @@ struct rds_notifier { + int n_status; + }; + ++/* Available as part of RDS core, so doesn't need to participate ++ * in get_preferred transport etc ++ */ ++#define RDS_TRANS_LOOP 3 ++ + /** + * struct rds_transport - transport specific behavioural hooks + * +diff --git a/net/rds/recv.c b/net/rds/recv.c +index cbfabdf3ff48..f16ee1b13b8d 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -94,6 +94,11 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk, + return; + + rs->rs_rcv_bytes += delta; ++ ++ /* loop transport doesn't send/recv congestion updates */ ++ if (rs->rs_transport->t_type == RDS_TRANS_LOOP) ++ return; ++ + now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs); + + rdsdebug("rs %p (%pI4:%u) recv bytes %d buf %d " +diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c +index c98a61e980ba..9c4c2bb547d7 100644 +--- a/net/sched/sch_blackhole.c ++++ b/net/sched/sch_blackhole.c +@@ -21,7 +21,7 @@ static int blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch, + struct sk_buff **to_free) + { + qdisc_drop(skb, sch, to_free); +- return NET_XMIT_SUCCESS; ++ return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + } + + static struct sk_buff *blackhole_dequeue(struct Qdisc *sch) +diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c +index 95021246ee26..3d6dbdf850aa 100644 +--- a/virt/kvm/arm/hyp/vgic-v2-sr.c ++++ b/virt/kvm/arm/hyp/vgic-v2-sr.c +@@ -203,7 +203,7 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu) + return -1; + + rd = kvm_vcpu_dabt_get_rd(vcpu); +- addr = kern_hyp_va((kern_hyp_va(&kvm_vgic_global_state))->vcpu_base_va); ++ addr = kern_hyp_va(hyp_symbol_addr(kvm_vgic_global_state)->vcpu_base_va); + addr += fault_ipa - vgic->vgic_cpu_base; + + if (kvm_vcpu_dabt_iswrite(vcpu)) {
