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(&region);
+               /* 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)) {

Reply via email to