From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id D6B78138334 for ; Wed, 6 Jun 2018 18:04:15 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 96B6EE09EC; Wed, 6 Jun 2018 18:04:14 +0000 (UTC) Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id EB4C3E09EC for ; Wed, 6 Jun 2018 18:04:13 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id D3B64335C92 for ; Wed, 6 Jun 2018 18:04:11 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 196AD2C3 for ; Wed, 6 Jun 2018 18:04:10 +0000 (UTC) From: "Mike Pagano" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Pagano" Message-ID: <1528308243.cdf8ca221eb77267c919d87bc783e83c7ed6a1eb.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:4.9 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1106_linux-4.9.107.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: cdf8ca221eb77267c919d87bc783e83c7ed6a1eb X-VCS-Branch: 4.9 Date: Wed, 6 Jun 2018 18:04:10 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 7246f3a1-36dc-438d-8a50-9f9f426cc504 X-Archives-Hash: 9b3594981ac620c380566cbe24f518de commit: cdf8ca221eb77267c919d87bc783e83c7ed6a1eb Author: Mike Pagano gentoo org> AuthorDate: Wed Jun 6 18:04:03 2018 +0000 Commit: Mike Pagano gentoo org> CommitDate: Wed Jun 6 18:04:03 2018 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=cdf8ca22 Linux patch 4.9.107 0000_README | 4 + 1106_linux-4.9.107.patch | 3059 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 3063 insertions(+) diff --git a/0000_README b/0000_README index d5b0351..5798d3a 100644 --- a/0000_README +++ b/0000_README @@ -467,6 +467,10 @@ Patch: 1105_linux-4.9.106.patch From: http://www.kernel.org Desc: Linux 4.9.106 +Patch: 1106_linux-4.9.107.patch +From: http://www.kernel.org +Desc: Linux 4.9.107 + 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/1106_linux-4.9.107.patch b/1106_linux-4.9.107.patch new file mode 100644 index 0000000..50f9eb8 --- /dev/null +++ b/1106_linux-4.9.107.patch @@ -0,0 +1,3059 @@ +diff --git a/Makefile b/Makefile +index 48d87e3a36c1..ac30e448e0a5 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 106 ++SUBLEVEL = 107 + EXTRAVERSION = + NAME = Roaring Lionus + +diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h +index 7457ce082b5f..d32a0160c89f 100644 +--- a/arch/arm64/include/asm/atomic_lse.h ++++ b/arch/arm64/include/asm/atomic_lse.h +@@ -117,7 +117,7 @@ static inline void atomic_and(int i, atomic_t *v) + /* LSE atomics */ + " mvn %w[i], %w[i]\n" + " stclr %w[i], %[v]") +- : [i] "+r" (w0), [v] "+Q" (v->counter) ++ : [i] "+&r" (w0), [v] "+Q" (v->counter) + : "r" (x1) + : __LL_SC_CLOBBERS); + } +@@ -135,7 +135,7 @@ static inline int atomic_fetch_and##name(int i, atomic_t *v) \ + /* LSE atomics */ \ + " mvn %w[i], %w[i]\n" \ + " ldclr" #mb " %w[i], %w[i], %[v]") \ +- : [i] "+r" (w0), [v] "+Q" (v->counter) \ ++ : [i] "+&r" (w0), [v] "+Q" (v->counter) \ + : "r" (x1) \ + : __LL_SC_CLOBBERS, ##cl); \ + \ +@@ -161,7 +161,7 @@ static inline void atomic_sub(int i, atomic_t *v) + /* LSE atomics */ + " neg %w[i], %w[i]\n" + " stadd %w[i], %[v]") +- : [i] "+r" (w0), [v] "+Q" (v->counter) ++ : [i] "+&r" (w0), [v] "+Q" (v->counter) + : "r" (x1) + : __LL_SC_CLOBBERS); + } +@@ -180,7 +180,7 @@ static inline int atomic_sub_return##name(int i, atomic_t *v) \ + " neg %w[i], %w[i]\n" \ + " ldadd" #mb " %w[i], w30, %[v]\n" \ + " add %w[i], %w[i], w30") \ +- : [i] "+r" (w0), [v] "+Q" (v->counter) \ ++ : [i] "+&r" (w0), [v] "+Q" (v->counter) \ + : "r" (x1) \ + : __LL_SC_CLOBBERS , ##cl); \ + \ +@@ -207,7 +207,7 @@ static inline int atomic_fetch_sub##name(int i, atomic_t *v) \ + /* LSE atomics */ \ + " neg %w[i], %w[i]\n" \ + " ldadd" #mb " %w[i], %w[i], %[v]") \ +- : [i] "+r" (w0), [v] "+Q" (v->counter) \ ++ : [i] "+&r" (w0), [v] "+Q" (v->counter) \ + : "r" (x1) \ + : __LL_SC_CLOBBERS, ##cl); \ + \ +@@ -314,7 +314,7 @@ static inline void atomic64_and(long i, atomic64_t *v) + /* LSE atomics */ + " mvn %[i], %[i]\n" + " stclr %[i], %[v]") +- : [i] "+r" (x0), [v] "+Q" (v->counter) ++ : [i] "+&r" (x0), [v] "+Q" (v->counter) + : "r" (x1) + : __LL_SC_CLOBBERS); + } +@@ -332,7 +332,7 @@ static inline long atomic64_fetch_and##name(long i, atomic64_t *v) \ + /* LSE atomics */ \ + " mvn %[i], %[i]\n" \ + " ldclr" #mb " %[i], %[i], %[v]") \ +- : [i] "+r" (x0), [v] "+Q" (v->counter) \ ++ : [i] "+&r" (x0), [v] "+Q" (v->counter) \ + : "r" (x1) \ + : __LL_SC_CLOBBERS, ##cl); \ + \ +@@ -358,7 +358,7 @@ static inline void atomic64_sub(long i, atomic64_t *v) + /* LSE atomics */ + " neg %[i], %[i]\n" + " stadd %[i], %[v]") +- : [i] "+r" (x0), [v] "+Q" (v->counter) ++ : [i] "+&r" (x0), [v] "+Q" (v->counter) + : "r" (x1) + : __LL_SC_CLOBBERS); + } +@@ -377,7 +377,7 @@ static inline long atomic64_sub_return##name(long i, atomic64_t *v) \ + " neg %[i], %[i]\n" \ + " ldadd" #mb " %[i], x30, %[v]\n" \ + " add %[i], %[i], x30") \ +- : [i] "+r" (x0), [v] "+Q" (v->counter) \ ++ : [i] "+&r" (x0), [v] "+Q" (v->counter) \ + : "r" (x1) \ + : __LL_SC_CLOBBERS, ##cl); \ + \ +@@ -404,7 +404,7 @@ static inline long atomic64_fetch_sub##name(long i, atomic64_t *v) \ + /* LSE atomics */ \ + " neg %[i], %[i]\n" \ + " ldadd" #mb " %[i], %[i], %[v]") \ +- : [i] "+r" (x0), [v] "+Q" (v->counter) \ ++ : [i] "+&r" (x0), [v] "+Q" (v->counter) \ + : "r" (x1) \ + : __LL_SC_CLOBBERS, ##cl); \ + \ +@@ -516,7 +516,7 @@ static inline long __cmpxchg_double##name(unsigned long old1, \ + " eor %[old1], %[old1], %[oldval1]\n" \ + " eor %[old2], %[old2], %[oldval2]\n" \ + " orr %[old1], %[old1], %[old2]") \ +- : [old1] "+r" (x0), [old2] "+r" (x1), \ ++ : [old1] "+&r" (x0), [old2] "+&r" (x1), \ + [v] "+Q" (*(unsigned long *)ptr) \ + : [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \ + [oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \ +diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h +index 0bc0b1de90c4..4ea85ebdf4df 100644 +--- a/arch/arm64/include/asm/cpufeature.h ++++ b/arch/arm64/include/asm/cpufeature.h +@@ -9,8 +9,6 @@ + #ifndef __ASM_CPUFEATURE_H + #define __ASM_CPUFEATURE_H + +-#include +- + #include + #include + #include +@@ -27,6 +25,8 @@ + + #ifndef __ASSEMBLY__ + ++#include ++#include + #include + + /* CPU feature register tracking */ +@@ -96,6 +96,7 @@ struct arm64_cpu_capabilities { + + extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); + extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS]; ++extern struct static_key_false arm64_const_caps_ready; + + bool this_cpu_has_cap(unsigned int cap); + +@@ -104,14 +105,27 @@ static inline bool cpu_have_feature(unsigned int num) + return elf_hwcap & (1UL << num); + } + ++/* System capability check for constant caps */ ++static inline bool __cpus_have_const_cap(int num) ++{ ++ if (num >= ARM64_NCAPS) ++ return false; ++ return static_branch_unlikely(&cpu_hwcap_keys[num]); ++} ++ + static inline bool cpus_have_cap(unsigned int num) + { + if (num >= ARM64_NCAPS) + return false; +- if (__builtin_constant_p(num)) +- return static_branch_unlikely(&cpu_hwcap_keys[num]); ++ return test_bit(num, cpu_hwcaps); ++} ++ ++static inline bool cpus_have_const_cap(int num) ++{ ++ if (static_branch_likely(&arm64_const_caps_ready)) ++ return __cpus_have_const_cap(num); + else +- return test_bit(num, cpu_hwcaps); ++ return cpus_have_cap(num); + } + + static inline void cpus_set_cap(unsigned int num) +@@ -121,7 +135,6 @@ static inline void cpus_set_cap(unsigned int num) + num, ARM64_NCAPS); + } else { + __set_bit(num, cpu_hwcaps); +- static_branch_enable(&cpu_hwcap_keys[num]); + } + } + +@@ -200,7 +213,7 @@ static inline bool cpu_supports_mixed_endian_el0(void) + + static inline bool system_supports_32bit_el0(void) + { +- return cpus_have_cap(ARM64_HAS_32BIT_EL0); ++ return cpus_have_const_cap(ARM64_HAS_32BIT_EL0); + } + + static inline bool system_supports_mixed_endian_el0(void) +diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h +index 0a33ea304e63..2abb4493f4f6 100644 +--- a/arch/arm64/include/asm/kvm_host.h ++++ b/arch/arm64/include/asm/kvm_host.h +@@ -24,6 +24,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -358,9 +359,12 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, + unsigned long vector_ptr) + { + /* +- * Call initialization code, and switch to the full blown +- * HYP code. ++ * Call initialization code, and switch to the full blown HYP code. ++ * If the cpucaps haven't been finalized yet, something has gone very ++ * wrong, and hyp will crash and burn when it uses any ++ * cpus_have_const_cap() wrapper. + */ ++ BUG_ON(!static_branch_likely(&arm64_const_caps_ready)); + __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr); + } + +@@ -398,7 +402,7 @@ static inline void __cpu_init_stage2(void) + + static inline bool kvm_arm_harden_branch_predictor(void) + { +- return cpus_have_cap(ARM64_HARDEN_BRANCH_PREDICTOR); ++ return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); + } + + #endif /* __ARM64_KVM_HOST_H__ */ +diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h +index eac73a640ea7..824c83db9b47 100644 +--- a/arch/arm64/include/asm/kvm_mmu.h ++++ b/arch/arm64/include/asm/kvm_mmu.h +@@ -341,7 +341,7 @@ static inline void *kvm_get_hyp_vector(void) + vect = __bp_harden_hyp_vecs_start + + data->hyp_vectors_slot * SZ_2K; + +- if (!cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN)) ++ if (!cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) + vect = lm_alias(vect); + } + +diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h +index d51158a61892..6ac34c75f4e1 100644 +--- a/arch/arm64/include/asm/mmu.h ++++ b/arch/arm64/include/asm/mmu.h +@@ -37,7 +37,7 @@ typedef struct { + static inline bool arm64_kernel_unmapped_at_el0(void) + { + return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) && +- cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0); ++ cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0); + } + + typedef void (*bp_hardening_cb_t)(void); +diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c +index a0ee01202503..7959d2c92010 100644 +--- a/arch/arm64/kernel/cpufeature.c ++++ b/arch/arm64/kernel/cpufeature.c +@@ -47,6 +47,7 @@ unsigned int compat_elf_hwcap2 __read_mostly; + #endif + + DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); ++EXPORT_SYMBOL(cpu_hwcaps); + + DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, ARM64_NCAPS); + EXPORT_SYMBOL(cpu_hwcap_keys); +@@ -762,7 +763,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, + * ThunderX leads to apparent I-cache corruption of kernel text, which + * ends as well as you might imagine. Don't even try. + */ +- if (cpus_have_cap(ARM64_WORKAROUND_CAVIUM_27456)) { ++ if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_27456)) { + str = "ARM64_WORKAROUND_CAVIUM_27456"; + __kpti_forced = -1; + } +@@ -1051,8 +1052,16 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps, + */ + void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) + { +- for (; caps->matches; caps++) +- if (caps->enable && cpus_have_cap(caps->capability)) ++ for (; caps->matches; caps++) { ++ unsigned int num = caps->capability; ++ ++ if (!cpus_have_cap(num)) ++ continue; ++ ++ /* Ensure cpus_have_const_cap(num) works */ ++ static_branch_enable(&cpu_hwcap_keys[num]); ++ ++ if (caps->enable) { + /* + * Use stop_machine() as it schedules the work allowing + * us to modify PSTATE, instead of on_each_cpu() which +@@ -1060,6 +1069,8 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps) + * we return. + */ + stop_machine(caps->enable, (void *)caps, cpu_online_mask); ++ } ++ } + } + + /* +@@ -1163,6 +1174,14 @@ static void __init setup_feature_capabilities(void) + enable_cpu_capabilities(arm64_features); + } + ++DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready); ++EXPORT_SYMBOL(arm64_const_caps_ready); ++ ++static void __init mark_const_caps_ready(void) ++{ ++ static_branch_enable(&arm64_const_caps_ready); ++} ++ + extern const struct arm64_cpu_capabilities arm64_errata[]; + + bool this_cpu_has_cap(unsigned int cap) +@@ -1179,6 +1198,7 @@ void __init setup_cpu_features(void) + /* Set the CPU feature capabilies */ + setup_feature_capabilities(); + enable_errata_workarounds(); ++ mark_const_caps_ready(); + setup_elf_hwcaps(arm64_elf_hwcaps); + + if (system_supports_32bit_el0()) +@@ -1203,5 +1223,5 @@ void __init setup_cpu_features(void) + static bool __maybe_unused + cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused) + { +- return (cpus_have_cap(ARM64_HAS_PAN) && !cpus_have_cap(ARM64_HAS_UAO)); ++ return (cpus_have_const_cap(ARM64_HAS_PAN) && !cpus_have_const_cap(ARM64_HAS_UAO)); + } +diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c +index 0972ce58316d..e917d119490c 100644 +--- a/arch/arm64/kernel/process.c ++++ b/arch/arm64/kernel/process.c +@@ -291,7 +291,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, + memset(childregs, 0, sizeof(struct pt_regs)); + childregs->pstate = PSR_MODE_EL1h; + if (IS_ENABLED(CONFIG_ARM64_UAO) && +- cpus_have_cap(ARM64_HAS_UAO)) ++ cpus_have_const_cap(ARM64_HAS_UAO)) + childregs->pstate |= PSR_UAO_BIT; + p->thread.cpu_context.x19 = stack_start; + p->thread.cpu_context.x20 = stk_sz; +diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c +index 6e716a5f1173..ebb575c4231b 100644 +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -699,6 +699,10 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value) + if (value & ~known_bits) + return -EOPNOTSUPP; + ++ /* Setting FRE without FR is not supported. */ ++ if ((value & (PR_FP_MODE_FR | PR_FP_MODE_FRE)) == PR_FP_MODE_FRE) ++ return -EOPNOTSUPP; ++ + /* Avoid inadvertently triggering emulation */ + if ((value & PR_FP_MODE_FR) && raw_cpu_has_fpu && + !(raw_current_cpu_data.fpu_id & MIPS_FPIR_F64)) +diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c +index 8f7bf74d1c0b..4f64913b4b4c 100644 +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -838,7 +838,7 @@ long arch_ptrace(struct task_struct *child, long request, + break; + } + #endif +- tmp = get_fpr32(&fregs[addr - FPR_BASE], 0); ++ tmp = get_fpr64(&fregs[addr - FPR_BASE], 0); + break; + case PC: + tmp = regs->cp0_epc; +diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c +index bc9afbabbe14..b1e945738138 100644 +--- a/arch/mips/kernel/ptrace32.c ++++ b/arch/mips/kernel/ptrace32.c +@@ -107,7 +107,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + addr & 1); + break; + } +- tmp = get_fpr32(&fregs[addr - FPR_BASE], 0); ++ tmp = get_fpr64(&fregs[addr - FPR_BASE], 0); + break; + case PC: + tmp = regs->cp0_epc; +diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h +index 903e76a9f158..e2200100828d 100644 +--- a/arch/powerpc/include/asm/exception-64s.h ++++ b/arch/powerpc/include/asm/exception-64s.h +@@ -51,6 +51,27 @@ + #define EX_PPR 88 /* SMT thread status register (priority) */ + #define EX_CTR 96 + ++#define STF_ENTRY_BARRIER_SLOT \ ++ STF_ENTRY_BARRIER_FIXUP_SECTION; \ ++ nop; \ ++ nop; \ ++ nop ++ ++#define STF_EXIT_BARRIER_SLOT \ ++ STF_EXIT_BARRIER_FIXUP_SECTION; \ ++ nop; \ ++ nop; \ ++ nop; \ ++ nop; \ ++ nop; \ ++ nop ++ ++/* ++ * r10 must be free to use, r13 must be paca ++ */ ++#define INTERRUPT_TO_KERNEL \ ++ STF_ENTRY_BARRIER_SLOT ++ + /* + * Macros for annotating the expected destination of (h)rfid + * +@@ -67,16 +88,19 @@ + rfid + + #define RFI_TO_USER \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + rfid; \ + b rfi_flush_fallback + + #define RFI_TO_USER_OR_KERNEL \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + rfid; \ + b rfi_flush_fallback + + #define RFI_TO_GUEST \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + rfid; \ + b rfi_flush_fallback +@@ -85,21 +109,25 @@ + hrfid + + #define HRFI_TO_USER \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback + + #define HRFI_TO_USER_OR_KERNEL \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback + + #define HRFI_TO_GUEST \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback + + #define HRFI_TO_UNKNOWN \ ++ STF_EXIT_BARRIER_SLOT; \ + RFI_FLUSH_SLOT; \ + hrfid; \ + b hrfi_flush_fallback +@@ -225,6 +253,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) + #define __EXCEPTION_PROLOG_1(area, extra, vec) \ + OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \ + OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \ ++ INTERRUPT_TO_KERNEL; \ + SAVE_CTR(r10, area); \ + mfcr r9; \ + extra(vec); \ +diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h +index 7b332342071c..0bf8202feca6 100644 +--- a/arch/powerpc/include/asm/feature-fixups.h ++++ b/arch/powerpc/include/asm/feature-fixups.h +@@ -189,6 +189,22 @@ void apply_feature_fixups(void); + void setup_feature_keys(void); + #endif + ++#define STF_ENTRY_BARRIER_FIXUP_SECTION \ ++953: \ ++ .pushsection __stf_entry_barrier_fixup,"a"; \ ++ .align 2; \ ++954: \ ++ FTR_ENTRY_OFFSET 953b-954b; \ ++ .popsection; ++ ++#define STF_EXIT_BARRIER_FIXUP_SECTION \ ++955: \ ++ .pushsection __stf_exit_barrier_fixup,"a"; \ ++ .align 2; \ ++956: \ ++ FTR_ENTRY_OFFSET 955b-956b; \ ++ .popsection; ++ + #define RFI_FLUSH_FIXUP_SECTION \ + 951: \ + .pushsection __rfi_flush_fixup,"a"; \ +@@ -200,6 +216,9 @@ void setup_feature_keys(void); + + #ifndef __ASSEMBLY__ + ++extern long stf_barrier_fallback; ++extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; ++extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; + extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; + + #endif +diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h +index dc0996b9d75d..9d978102bf0d 100644 +--- a/arch/powerpc/include/asm/hvcall.h ++++ b/arch/powerpc/include/asm/hvcall.h +@@ -313,6 +313,9 @@ + #define H_CPU_CHAR_L1D_FLUSH_ORI30 (1ull << 61) // IBM bit 2 + #define H_CPU_CHAR_L1D_FLUSH_TRIG2 (1ull << 60) // IBM bit 3 + #define H_CPU_CHAR_L1D_THREAD_PRIV (1ull << 59) // IBM bit 4 ++#define H_CPU_CHAR_BRANCH_HINTS_HONORED (1ull << 58) // IBM bit 5 ++#define H_CPU_CHAR_THREAD_RECONFIG_CTRL (1ull << 57) // IBM bit 6 ++#define H_CPU_CHAR_COUNT_CACHE_DISABLED (1ull << 56) // IBM bit 7 + + #define H_CPU_BEHAV_FAVOUR_SECURITY (1ull << 63) // IBM bit 0 + #define H_CPU_BEHAV_L1D_FLUSH_PR (1ull << 62) // IBM bit 1 +diff --git a/arch/powerpc/include/asm/security_features.h b/arch/powerpc/include/asm/security_features.h +new file mode 100644 +index 000000000000..44989b22383c +--- /dev/null ++++ b/arch/powerpc/include/asm/security_features.h +@@ -0,0 +1,85 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Security related feature bit definitions. ++ * ++ * Copyright 2018, Michael Ellerman, IBM Corporation. ++ */ ++ ++#ifndef _ASM_POWERPC_SECURITY_FEATURES_H ++#define _ASM_POWERPC_SECURITY_FEATURES_H ++ ++ ++extern unsigned long powerpc_security_features; ++extern bool rfi_flush; ++ ++/* These are bit flags */ ++enum stf_barrier_type { ++ STF_BARRIER_NONE = 0x1, ++ STF_BARRIER_FALLBACK = 0x2, ++ STF_BARRIER_EIEIO = 0x4, ++ STF_BARRIER_SYNC_ORI = 0x8, ++}; ++ ++void setup_stf_barrier(void); ++void do_stf_barrier_fixups(enum stf_barrier_type types); ++ ++static inline void security_ftr_set(unsigned long feature) ++{ ++ powerpc_security_features |= feature; ++} ++ ++static inline void security_ftr_clear(unsigned long feature) ++{ ++ powerpc_security_features &= ~feature; ++} ++ ++static inline bool security_ftr_enabled(unsigned long feature) ++{ ++ return !!(powerpc_security_features & feature); ++} ++ ++ ++// Features indicating support for Spectre/Meltdown mitigations ++ ++// The L1-D cache can be flushed with ori r30,r30,0 ++#define SEC_FTR_L1D_FLUSH_ORI30 0x0000000000000001ull ++ ++// The L1-D cache can be flushed with mtspr 882,r0 (aka SPRN_TRIG2) ++#define SEC_FTR_L1D_FLUSH_TRIG2 0x0000000000000002ull ++ ++// ori r31,r31,0 acts as a speculation barrier ++#define SEC_FTR_SPEC_BAR_ORI31 0x0000000000000004ull ++ ++// Speculation past bctr is disabled ++#define SEC_FTR_BCCTRL_SERIALISED 0x0000000000000008ull ++ ++// Entries in L1-D are private to a SMT thread ++#define SEC_FTR_L1D_THREAD_PRIV 0x0000000000000010ull ++ ++// Indirect branch prediction cache disabled ++#define SEC_FTR_COUNT_CACHE_DISABLED 0x0000000000000020ull ++ ++ ++// Features indicating need for Spectre/Meltdown mitigations ++ ++// The L1-D cache should be flushed on MSR[HV] 1->0 transition (hypervisor to guest) ++#define SEC_FTR_L1D_FLUSH_HV 0x0000000000000040ull ++ ++// The L1-D cache should be flushed on MSR[PR] 0->1 transition (kernel to userspace) ++#define SEC_FTR_L1D_FLUSH_PR 0x0000000000000080ull ++ ++// A speculation barrier should be used for bounds checks (Spectre variant 1) ++#define SEC_FTR_BNDS_CHK_SPEC_BAR 0x0000000000000100ull ++ ++// Firmware configuration indicates user favours security over performance ++#define SEC_FTR_FAVOUR_SECURITY 0x0000000000000200ull ++ ++ ++// Features enabled by default ++#define SEC_FTR_DEFAULT \ ++ (SEC_FTR_L1D_FLUSH_HV | \ ++ SEC_FTR_L1D_FLUSH_PR | \ ++ SEC_FTR_BNDS_CHK_SPEC_BAR | \ ++ SEC_FTR_FAVOUR_SECURITY) ++ ++#endif /* _ASM_POWERPC_SECURITY_FEATURES_H */ +diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h +index 6825a67cc3db..3f160cd20107 100644 +--- a/arch/powerpc/include/asm/setup.h ++++ b/arch/powerpc/include/asm/setup.h +@@ -48,7 +48,7 @@ enum l1d_flush_type { + L1D_FLUSH_MTTRIG = 0x8, + }; + +-void __init setup_rfi_flush(enum l1d_flush_type, bool enable); ++void setup_rfi_flush(enum l1d_flush_type, bool enable); + void do_rfi_flush_fixups(enum l1d_flush_type types); + + #endif /* !__ASSEMBLY__ */ +diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile +index adb52d101133..13885786282b 100644 +--- a/arch/powerpc/kernel/Makefile ++++ b/arch/powerpc/kernel/Makefile +@@ -44,7 +44,7 @@ obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ + obj-$(CONFIG_VDSO32) += vdso32/ + obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o + obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o +-obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o ++obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o security.o + obj-$(CONFIG_PPC_BOOK3S_64) += mce.o mce_power.o + obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o + obj-$(CONFIG_PPC64) += vdso64/ +diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S +index 9e05c8828ee2..ff45d007d195 100644 +--- a/arch/powerpc/kernel/cpu_setup_power.S ++++ b/arch/powerpc/kernel/cpu_setup_power.S +@@ -28,6 +28,7 @@ _GLOBAL(__setup_cpu_power7) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + bl __init_LPCR + bl __init_tlb_power7 +@@ -41,6 +42,7 @@ _GLOBAL(__restore_cpu_power7) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + bl __init_LPCR + bl __init_tlb_power7 +@@ -57,6 +59,7 @@ _GLOBAL(__setup_cpu_power8) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + ori r3, r3, LPCR_PECEDH + bl __init_LPCR +@@ -78,6 +81,7 @@ _GLOBAL(__restore_cpu_power8) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + ori r3, r3, LPCR_PECEDH + bl __init_LPCR +@@ -98,6 +102,7 @@ _GLOBAL(__setup_cpu_power9) + li r0,0 + mtspr SPRN_LPID,r0 + mtspr SPRN_PID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE) + or r3, r3, r4 +@@ -121,6 +126,7 @@ _GLOBAL(__restore_cpu_power9) + li r0,0 + mtspr SPRN_LPID,r0 + mtspr SPRN_PID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE) + or r3, r3, r4 +diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S +index 94b5dfb087e9..d50cc9b38b80 100644 +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -846,7 +846,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) + #endif + + +-EXC_REAL_MASKABLE(decrementer, 0x900, 0x980) ++EXC_REAL_OOL_MASKABLE(decrementer, 0x900, 0x980) + EXC_VIRT_MASKABLE(decrementer, 0x4900, 0x4980, 0x900) + TRAMP_KVM(PACA_EXGEN, 0x900) + EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt) +@@ -884,6 +884,7 @@ BEGIN_FTR_SECTION \ + END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ + mr r9,r13 ; \ + GET_PACA(r13) ; \ ++ INTERRUPT_TO_KERNEL ; \ + mfspr r11,SPRN_SRR0 ; \ + 0: + +@@ -1353,6 +1354,19 @@ masked_##_H##interrupt: \ + ##_H##RFI_TO_KERNEL; \ + b . + ++TRAMP_REAL_BEGIN(stf_barrier_fallback) ++ std r9,PACA_EXRFI+EX_R9(r13) ++ std r10,PACA_EXRFI+EX_R10(r13) ++ sync ++ ld r9,PACA_EXRFI+EX_R9(r13) ++ ld r10,PACA_EXRFI+EX_R10(r13) ++ ori 31,31,0 ++ .rept 14 ++ b 1f ++1: ++ .endr ++ blr ++ + /* + * Real mode exceptions actually use this too, but alternate + * instruction code patches (which end up in the common .text area) +diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c +new file mode 100644 +index 000000000000..2277df84ef6e +--- /dev/null ++++ b/arch/powerpc/kernel/security.c +@@ -0,0 +1,237 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++// ++// Security related flags and so on. ++// ++// Copyright 2018, Michael Ellerman, IBM Corporation. ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++ ++unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; ++ ++ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ bool thread_priv; ++ ++ thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV); ++ ++ if (rfi_flush || thread_priv) { ++ struct seq_buf s; ++ seq_buf_init(&s, buf, PAGE_SIZE - 1); ++ ++ seq_buf_printf(&s, "Mitigation: "); ++ ++ if (rfi_flush) ++ seq_buf_printf(&s, "RFI Flush"); ++ ++ if (rfi_flush && thread_priv) ++ seq_buf_printf(&s, ", "); ++ ++ if (thread_priv) ++ seq_buf_printf(&s, "L1D private per thread"); ++ ++ seq_buf_printf(&s, "\n"); ++ ++ return s.len; ++ } ++ ++ if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && ++ !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)) ++ return sprintf(buf, "Not affected\n"); ++ ++ return sprintf(buf, "Vulnerable\n"); ++} ++ ++ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) ++ return sprintf(buf, "Not affected\n"); ++ ++ return sprintf(buf, "Vulnerable\n"); ++} ++ ++ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ bool bcs, ccd, ori; ++ struct seq_buf s; ++ ++ seq_buf_init(&s, buf, PAGE_SIZE - 1); ++ ++ bcs = security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED); ++ ccd = security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED); ++ ori = security_ftr_enabled(SEC_FTR_SPEC_BAR_ORI31); ++ ++ if (bcs || ccd) { ++ seq_buf_printf(&s, "Mitigation: "); ++ ++ if (bcs) ++ seq_buf_printf(&s, "Indirect branch serialisation (kernel only)"); ++ ++ if (bcs && ccd) ++ seq_buf_printf(&s, ", "); ++ ++ if (ccd) ++ seq_buf_printf(&s, "Indirect branch cache disabled"); ++ } else ++ seq_buf_printf(&s, "Vulnerable"); ++ ++ if (ori) ++ seq_buf_printf(&s, ", ori31 speculation barrier enabled"); ++ ++ seq_buf_printf(&s, "\n"); ++ ++ return s.len; ++} ++ ++/* ++ * Store-forwarding barrier support. ++ */ ++ ++static enum stf_barrier_type stf_enabled_flush_types; ++static bool no_stf_barrier; ++bool stf_barrier; ++ ++static int __init handle_no_stf_barrier(char *p) ++{ ++ pr_info("stf-barrier: disabled on command line."); ++ no_stf_barrier = true; ++ return 0; ++} ++ ++early_param("no_stf_barrier", handle_no_stf_barrier); ++ ++/* This is the generic flag used by other architectures */ ++static int __init handle_ssbd(char *p) ++{ ++ if (!p || strncmp(p, "auto", 5) == 0 || strncmp(p, "on", 2) == 0 ) { ++ /* Until firmware tells us, we have the barrier with auto */ ++ return 0; ++ } else if (strncmp(p, "off", 3) == 0) { ++ handle_no_stf_barrier(NULL); ++ return 0; ++ } else ++ return 1; ++ ++ return 0; ++} ++early_param("spec_store_bypass_disable", handle_ssbd); ++ ++/* This is the generic flag used by other architectures */ ++static int __init handle_no_ssbd(char *p) ++{ ++ handle_no_stf_barrier(NULL); ++ return 0; ++} ++early_param("nospec_store_bypass_disable", handle_no_ssbd); ++ ++static void stf_barrier_enable(bool enable) ++{ ++ if (enable) ++ do_stf_barrier_fixups(stf_enabled_flush_types); ++ else ++ do_stf_barrier_fixups(STF_BARRIER_NONE); ++ ++ stf_barrier = enable; ++} ++ ++void setup_stf_barrier(void) ++{ ++ enum stf_barrier_type type; ++ bool enable, hv; ++ ++ hv = cpu_has_feature(CPU_FTR_HVMODE); ++ ++ /* Default to fallback in case fw-features are not available */ ++ if (cpu_has_feature(CPU_FTR_ARCH_300)) ++ type = STF_BARRIER_EIEIO; ++ else if (cpu_has_feature(CPU_FTR_ARCH_207S)) ++ type = STF_BARRIER_SYNC_ORI; ++ else if (cpu_has_feature(CPU_FTR_ARCH_206)) ++ type = STF_BARRIER_FALLBACK; ++ else ++ type = STF_BARRIER_NONE; ++ ++ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && ++ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || ++ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && hv)); ++ ++ if (type == STF_BARRIER_FALLBACK) { ++ pr_info("stf-barrier: fallback barrier available\n"); ++ } else if (type == STF_BARRIER_SYNC_ORI) { ++ pr_info("stf-barrier: hwsync barrier available\n"); ++ } else if (type == STF_BARRIER_EIEIO) { ++ pr_info("stf-barrier: eieio barrier available\n"); ++ } ++ ++ stf_enabled_flush_types = type; ++ ++ if (!no_stf_barrier) ++ stf_barrier_enable(enable); ++} ++ ++ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ if (stf_barrier && stf_enabled_flush_types != STF_BARRIER_NONE) { ++ const char *type; ++ switch (stf_enabled_flush_types) { ++ case STF_BARRIER_EIEIO: ++ type = "eieio"; ++ break; ++ case STF_BARRIER_SYNC_ORI: ++ type = "hwsync"; ++ break; ++ case STF_BARRIER_FALLBACK: ++ type = "fallback"; ++ break; ++ default: ++ type = "unknown"; ++ } ++ return sprintf(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type); ++ } ++ ++ if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && ++ !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)) ++ return sprintf(buf, "Not affected\n"); ++ ++ return sprintf(buf, "Vulnerable\n"); ++} ++ ++#ifdef CONFIG_DEBUG_FS ++static int stf_barrier_set(void *data, u64 val) ++{ ++ bool enable; ++ ++ if (val == 1) ++ enable = true; ++ else if (val == 0) ++ enable = false; ++ else ++ return -EINVAL; ++ ++ /* Only do anything if we're changing state */ ++ if (enable != stf_barrier) ++ stf_barrier_enable(enable); ++ ++ return 0; ++} ++ ++static int stf_barrier_get(void *data, u64 *val) ++{ ++ *val = stf_barrier ? 1 : 0; ++ return 0; ++} ++ ++DEFINE_SIMPLE_ATTRIBUTE(fops_stf_barrier, stf_barrier_get, stf_barrier_set, "%llu\n"); ++ ++static __init int stf_barrier_debugfs_init(void) ++{ ++ debugfs_create_file("stf_barrier", 0600, powerpc_debugfs_root, NULL, &fops_stf_barrier); ++ return 0; ++} ++device_initcall(stf_barrier_debugfs_init); ++#endif /* CONFIG_DEBUG_FS */ +diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c +index 5243501d95ef..fdba10695208 100644 +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -679,6 +679,7 @@ static int __init disable_hardlockup_detector(void) + return 0; + } + early_initcall(disable_hardlockup_detector); ++#endif /* CONFIG_HARDLOCKUP_DETECTOR */ + + #ifdef CONFIG_PPC_BOOK3S_64 + static enum l1d_flush_type enabled_flush_types; +@@ -716,9 +717,6 @@ static void do_nothing(void *unused) + + void rfi_flush_enable(bool enable) + { +- if (rfi_flush == enable) +- return; +- + if (enable) { + do_rfi_flush_fixups(enabled_flush_types); + on_each_cpu(do_nothing, NULL, 1); +@@ -728,11 +726,15 @@ void rfi_flush_enable(bool enable) + rfi_flush = enable; + } + +-static void init_fallback_flush(void) ++static void __ref init_fallback_flush(void) + { + u64 l1d_size, limit; + int cpu; + ++ /* Only allocate the fallback flush area once (at boot time). */ ++ if (l1d_flush_fallback_area) ++ return; ++ + l1d_size = ppc64_caches.dsize; + limit = min(safe_stack_limit(), ppc64_rma_size); + +@@ -750,18 +752,18 @@ static void init_fallback_flush(void) + } + } + +-void __init setup_rfi_flush(enum l1d_flush_type types, bool enable) ++void setup_rfi_flush(enum l1d_flush_type types, bool enable) + { + if (types & L1D_FLUSH_FALLBACK) { +- pr_info("rfi-flush: Using fallback displacement flush\n"); ++ pr_info("rfi-flush: fallback displacement flush available\n"); + init_fallback_flush(); + } + + if (types & L1D_FLUSH_ORI) +- pr_info("rfi-flush: Using ori type flush\n"); ++ pr_info("rfi-flush: ori type flush available\n"); + + if (types & L1D_FLUSH_MTTRIG) +- pr_info("rfi-flush: Using mttrig type flush\n"); ++ pr_info("rfi-flush: mttrig type flush available\n"); + + enabled_flush_types = types; + +@@ -772,13 +774,19 @@ void __init setup_rfi_flush(enum l1d_flush_type types, bool enable) + #ifdef CONFIG_DEBUG_FS + static int rfi_flush_set(void *data, u64 val) + { ++ bool enable; ++ + if (val == 1) +- rfi_flush_enable(true); ++ enable = true; + else if (val == 0) +- rfi_flush_enable(false); ++ enable = false; + else + return -EINVAL; + ++ /* Only do anything if we're changing state */ ++ if (enable != rfi_flush) ++ rfi_flush_enable(enable); ++ + return 0; + } + +@@ -797,13 +805,4 @@ static __init int rfi_flush_debugfs_init(void) + } + device_initcall(rfi_flush_debugfs_init); + #endif +- +-ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) +-{ +- if (rfi_flush) +- return sprintf(buf, "Mitigation: RFI Flush\n"); +- +- return sprintf(buf, "Vulnerable\n"); +-} + #endif /* CONFIG_PPC_BOOK3S_64 */ +-#endif +diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S +index b61fb7902018..c16fddbb6ab8 100644 +--- a/arch/powerpc/kernel/vmlinux.lds.S ++++ b/arch/powerpc/kernel/vmlinux.lds.S +@@ -133,6 +133,20 @@ SECTIONS + RODATA + + #ifdef CONFIG_PPC64 ++ . = ALIGN(8); ++ __stf_entry_barrier_fixup : AT(ADDR(__stf_entry_barrier_fixup) - LOAD_OFFSET) { ++ __start___stf_entry_barrier_fixup = .; ++ *(__stf_entry_barrier_fixup) ++ __stop___stf_entry_barrier_fixup = .; ++ } ++ ++ . = ALIGN(8); ++ __stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) { ++ __start___stf_exit_barrier_fixup = .; ++ *(__stf_exit_barrier_fixup) ++ __stop___stf_exit_barrier_fixup = .; ++ } ++ + . = ALIGN(8); + __rfi_flush_fixup : AT(ADDR(__rfi_flush_fixup) - LOAD_OFFSET) { + __start___rfi_flush_fixup = .; +diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c +index 46c8338a61bc..cf1398e3c2e0 100644 +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -117,6 +118,120 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) + } + + #ifdef CONFIG_PPC_BOOK3S_64 ++void do_stf_entry_barrier_fixups(enum stf_barrier_type types) ++{ ++ unsigned int instrs[3], *dest; ++ long *start, *end; ++ int i; ++ ++ start = PTRRELOC(&__start___stf_entry_barrier_fixup), ++ end = PTRRELOC(&__stop___stf_entry_barrier_fixup); ++ ++ instrs[0] = 0x60000000; /* nop */ ++ instrs[1] = 0x60000000; /* nop */ ++ instrs[2] = 0x60000000; /* nop */ ++ ++ i = 0; ++ if (types & STF_BARRIER_FALLBACK) { ++ instrs[i++] = 0x7d4802a6; /* mflr r10 */ ++ instrs[i++] = 0x60000000; /* branch patched below */ ++ instrs[i++] = 0x7d4803a6; /* mtlr r10 */ ++ } else if (types & STF_BARRIER_EIEIO) { ++ instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */ ++ } else if (types & STF_BARRIER_SYNC_ORI) { ++ instrs[i++] = 0x7c0004ac; /* hwsync */ ++ instrs[i++] = 0xe94d0000; /* ld r10,0(r13) */ ++ instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ ++ } ++ ++ for (i = 0; start < end; start++, i++) { ++ dest = (void *)start + *start; ++ ++ pr_devel("patching dest %lx\n", (unsigned long)dest); ++ ++ patch_instruction(dest, instrs[0]); ++ ++ if (types & STF_BARRIER_FALLBACK) ++ patch_branch(dest + 1, (unsigned long)&stf_barrier_fallback, ++ BRANCH_SET_LINK); ++ else ++ patch_instruction(dest + 1, instrs[1]); ++ ++ patch_instruction(dest + 2, instrs[2]); ++ } ++ ++ printk(KERN_DEBUG "stf-barrier: patched %d entry locations (%s barrier)\n", i, ++ (types == STF_BARRIER_NONE) ? "no" : ++ (types == STF_BARRIER_FALLBACK) ? "fallback" : ++ (types == STF_BARRIER_EIEIO) ? "eieio" : ++ (types == (STF_BARRIER_SYNC_ORI)) ? "hwsync" ++ : "unknown"); ++} ++ ++void do_stf_exit_barrier_fixups(enum stf_barrier_type types) ++{ ++ unsigned int instrs[6], *dest; ++ long *start, *end; ++ int i; ++ ++ start = PTRRELOC(&__start___stf_exit_barrier_fixup), ++ end = PTRRELOC(&__stop___stf_exit_barrier_fixup); ++ ++ instrs[0] = 0x60000000; /* nop */ ++ instrs[1] = 0x60000000; /* nop */ ++ instrs[2] = 0x60000000; /* nop */ ++ instrs[3] = 0x60000000; /* nop */ ++ instrs[4] = 0x60000000; /* nop */ ++ instrs[5] = 0x60000000; /* nop */ ++ ++ i = 0; ++ if (types & STF_BARRIER_FALLBACK || types & STF_BARRIER_SYNC_ORI) { ++ if (cpu_has_feature(CPU_FTR_HVMODE)) { ++ instrs[i++] = 0x7db14ba6; /* mtspr 0x131, r13 (HSPRG1) */ ++ instrs[i++] = 0x7db04aa6; /* mfspr r13, 0x130 (HSPRG0) */ ++ } else { ++ instrs[i++] = 0x7db243a6; /* mtsprg 2,r13 */ ++ instrs[i++] = 0x7db142a6; /* mfsprg r13,1 */ ++ } ++ instrs[i++] = 0x7c0004ac; /* hwsync */ ++ instrs[i++] = 0xe9ad0000; /* ld r13,0(r13) */ ++ instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ ++ if (cpu_has_feature(CPU_FTR_HVMODE)) { ++ instrs[i++] = 0x7db14aa6; /* mfspr r13, 0x131 (HSPRG1) */ ++ } else { ++ instrs[i++] = 0x7db242a6; /* mfsprg r13,2 */ ++ } ++ } else if (types & STF_BARRIER_EIEIO) { ++ instrs[i++] = 0x7e0006ac; /* eieio + bit 6 hint */ ++ } ++ ++ for (i = 0; start < end; start++, i++) { ++ dest = (void *)start + *start; ++ ++ pr_devel("patching dest %lx\n", (unsigned long)dest); ++ ++ patch_instruction(dest, instrs[0]); ++ patch_instruction(dest + 1, instrs[1]); ++ patch_instruction(dest + 2, instrs[2]); ++ patch_instruction(dest + 3, instrs[3]); ++ patch_instruction(dest + 4, instrs[4]); ++ patch_instruction(dest + 5, instrs[5]); ++ } ++ printk(KERN_DEBUG "stf-barrier: patched %d exit locations (%s barrier)\n", i, ++ (types == STF_BARRIER_NONE) ? "no" : ++ (types == STF_BARRIER_FALLBACK) ? "fallback" : ++ (types == STF_BARRIER_EIEIO) ? "eieio" : ++ (types == (STF_BARRIER_SYNC_ORI)) ? "hwsync" ++ : "unknown"); ++} ++ ++ ++void do_stf_barrier_fixups(enum stf_barrier_type types) ++{ ++ do_stf_entry_barrier_fixups(types); ++ do_stf_exit_barrier_fixups(types); ++} ++ + void do_rfi_flush_fixups(enum l1d_flush_type types) + { + unsigned int instrs[3], *dest; +@@ -153,7 +268,14 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) + patch_instruction(dest + 2, instrs[2]); + } + +- printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i); ++ printk(KERN_DEBUG "rfi-flush: patched %d locations (%s flush)\n", i, ++ (types == L1D_FLUSH_NONE) ? "no" : ++ (types == L1D_FLUSH_FALLBACK) ? "fallback displacement" : ++ (types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG) ++ ? "ori+mttrig type" ++ : "ori type" : ++ (types & L1D_FLUSH_MTTRIG) ? "mttrig type" ++ : "unknown"); + } + #endif /* CONFIG_PPC_BOOK3S_64 */ + +diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c +index 6f8b4c19373a..17203abf38e8 100644 +--- a/arch/powerpc/platforms/powernv/setup.c ++++ b/arch/powerpc/platforms/powernv/setup.c +@@ -37,53 +37,92 @@ + #include + #include + #include ++#include + + #include "powernv.h" + ++ ++static bool fw_feature_is(const char *state, const char *name, ++ struct device_node *fw_features) ++{ ++ struct device_node *np; ++ bool rc = false; ++ ++ np = of_get_child_by_name(fw_features, name); ++ if (np) { ++ rc = of_property_read_bool(np, state); ++ of_node_put(np); ++ } ++ ++ return rc; ++} ++ ++static void init_fw_feat_flags(struct device_node *np) ++{ ++ if (fw_feature_is("enabled", "inst-spec-barrier-ori31,31,0", np)) ++ security_ftr_set(SEC_FTR_SPEC_BAR_ORI31); ++ ++ if (fw_feature_is("enabled", "fw-bcctrl-serialized", np)) ++ security_ftr_set(SEC_FTR_BCCTRL_SERIALISED); ++ ++ if (fw_feature_is("enabled", "inst-l1d-flush-ori30,30,0", np)) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30); ++ ++ if (fw_feature_is("enabled", "inst-l1d-flush-trig2", np)) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_TRIG2); ++ ++ if (fw_feature_is("enabled", "fw-l1d-thread-split", np)) ++ security_ftr_set(SEC_FTR_L1D_THREAD_PRIV); ++ ++ if (fw_feature_is("enabled", "fw-count-cache-disabled", np)) ++ security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); ++ ++ /* ++ * The features below are enabled by default, so we instead look to see ++ * if firmware has *disabled* them, and clear them if so. ++ */ ++ if (fw_feature_is("disabled", "speculation-policy-favor-security", np)) ++ security_ftr_clear(SEC_FTR_FAVOUR_SECURITY); ++ ++ if (fw_feature_is("disabled", "needs-l1d-flush-msr-pr-0-to-1", np)) ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); ++ ++ if (fw_feature_is("disabled", "needs-l1d-flush-msr-hv-1-to-0", np)) ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_HV); ++ ++ if (fw_feature_is("disabled", "needs-spec-barrier-for-bound-checks", np)) ++ security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); ++} ++ + static void pnv_setup_rfi_flush(void) + { + struct device_node *np, *fw_features; + enum l1d_flush_type type; +- int enable; ++ bool enable; + + /* Default to fallback in case fw-features are not available */ + type = L1D_FLUSH_FALLBACK; +- enable = 1; + + np = of_find_node_by_name(NULL, "ibm,opal"); + fw_features = of_get_child_by_name(np, "fw-features"); + of_node_put(np); + + if (fw_features) { +- np = of_get_child_by_name(fw_features, "inst-l1d-flush-trig2"); +- if (np && of_property_read_bool(np, "enabled")) +- type = L1D_FLUSH_MTTRIG; ++ init_fw_feat_flags(fw_features); ++ of_node_put(fw_features); + +- of_node_put(np); ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_TRIG2)) ++ type = L1D_FLUSH_MTTRIG; + +- np = of_get_child_by_name(fw_features, "inst-l1d-flush-ori30,30,0"); +- if (np && of_property_read_bool(np, "enabled")) ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_ORI30)) + type = L1D_FLUSH_ORI; +- +- of_node_put(np); +- +- /* Enable unless firmware says NOT to */ +- enable = 2; +- np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-hv-1-to-0"); +- if (np && of_property_read_bool(np, "disabled")) +- enable--; +- +- of_node_put(np); +- +- np = of_get_child_by_name(fw_features, "needs-l1d-flush-msr-pr-0-to-1"); +- if (np && of_property_read_bool(np, "disabled")) +- enable--; +- +- of_node_put(np); +- of_node_put(fw_features); + } + +- setup_rfi_flush(type, enable > 0); ++ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ ++ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || \ ++ security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); ++ ++ setup_rfi_flush(type, enable); + } + + static void __init pnv_setup_arch(void) +@@ -91,6 +130,7 @@ static void __init pnv_setup_arch(void) + set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT); + + pnv_setup_rfi_flush(); ++ setup_stf_barrier(); + + /* Initialize SMP */ + pnv_smp_init(); +diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c +index 6a5e7467445c..3784a7abfcc8 100644 +--- a/arch/powerpc/platforms/pseries/mobility.c ++++ b/arch/powerpc/platforms/pseries/mobility.c +@@ -314,6 +314,9 @@ void post_mobility_fixup(void) + printk(KERN_ERR "Post-mobility device tree update " + "failed: %d\n", rc); + ++ /* Possibly switch to a new RFI flush type */ ++ pseries_setup_rfi_flush(); ++ + return; + } + +diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h +index b1be7b713fe6..62ff57cf6c24 100644 +--- a/arch/powerpc/platforms/pseries/pseries.h ++++ b/arch/powerpc/platforms/pseries/pseries.h +@@ -79,4 +79,6 @@ extern struct pci_controller_ops pseries_pci_controller_ops; + + unsigned long pseries_memory_block_size(void); + ++void pseries_setup_rfi_flush(void); ++ + #endif /* _PSERIES_PSERIES_H */ +diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c +index 1845fc611912..91ade7755823 100644 +--- a/arch/powerpc/platforms/pseries/setup.c ++++ b/arch/powerpc/platforms/pseries/setup.c +@@ -66,6 +66,7 @@ + #include + #include + #include ++#include + + #include "pseries.h" + +@@ -450,35 +451,78 @@ static void __init find_and_init_phbs(void) + of_pci_check_probe_only(); + } + +-static void pseries_setup_rfi_flush(void) ++static void init_cpu_char_feature_flags(struct h_cpu_char_result *result) ++{ ++ /* ++ * The features below are disabled by default, so we instead look to see ++ * if firmware has *enabled* them, and set them if so. ++ */ ++ if (result->character & H_CPU_CHAR_SPEC_BAR_ORI31) ++ security_ftr_set(SEC_FTR_SPEC_BAR_ORI31); ++ ++ if (result->character & H_CPU_CHAR_BCCTRL_SERIALISED) ++ security_ftr_set(SEC_FTR_BCCTRL_SERIALISED); ++ ++ if (result->character & H_CPU_CHAR_L1D_FLUSH_ORI30) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_ORI30); ++ ++ if (result->character & H_CPU_CHAR_L1D_FLUSH_TRIG2) ++ security_ftr_set(SEC_FTR_L1D_FLUSH_TRIG2); ++ ++ if (result->character & H_CPU_CHAR_L1D_THREAD_PRIV) ++ security_ftr_set(SEC_FTR_L1D_THREAD_PRIV); ++ ++ if (result->character & H_CPU_CHAR_COUNT_CACHE_DISABLED) ++ security_ftr_set(SEC_FTR_COUNT_CACHE_DISABLED); ++ ++ /* ++ * The features below are enabled by default, so we instead look to see ++ * if firmware has *disabled* them, and clear them if so. ++ */ ++ if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY)) ++ security_ftr_clear(SEC_FTR_FAVOUR_SECURITY); ++ ++ if (!(result->behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_PR); ++ ++ if (!(result->behaviour & H_CPU_BEHAV_BNDS_CHK_SPEC_BAR)) ++ security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR); ++} ++ ++void pseries_setup_rfi_flush(void) + { + struct h_cpu_char_result result; + enum l1d_flush_type types; + bool enable; + long rc; + +- /* Enable by default */ +- enable = true; ++ /* ++ * Set features to the defaults assumed by init_cpu_char_feature_flags() ++ * so it can set/clear again any features that might have changed after ++ * migration, and in case the hypercall fails and it is not even called. ++ */ ++ powerpc_security_features = SEC_FTR_DEFAULT; + + rc = plpar_get_cpu_characteristics(&result); +- if (rc == H_SUCCESS) { +- types = L1D_FLUSH_NONE; ++ if (rc == H_SUCCESS) ++ init_cpu_char_feature_flags(&result); + +- if (result.character & H_CPU_CHAR_L1D_FLUSH_TRIG2) +- types |= L1D_FLUSH_MTTRIG; +- if (result.character & H_CPU_CHAR_L1D_FLUSH_ORI30) +- types |= L1D_FLUSH_ORI; ++ /* ++ * We're the guest so this doesn't apply to us, clear it to simplify ++ * handling of it elsewhere. ++ */ ++ security_ftr_clear(SEC_FTR_L1D_FLUSH_HV); + +- /* Use fallback if nothing set in hcall */ +- if (types == L1D_FLUSH_NONE) +- types = L1D_FLUSH_FALLBACK; ++ types = L1D_FLUSH_FALLBACK; + +- if (!(result.behaviour & H_CPU_BEHAV_L1D_FLUSH_PR)) +- enable = false; +- } else { +- /* Default to fallback if case hcall is not available */ +- types = L1D_FLUSH_FALLBACK; +- } ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_TRIG2)) ++ types |= L1D_FLUSH_MTTRIG; ++ ++ if (security_ftr_enabled(SEC_FTR_L1D_FLUSH_ORI30)) ++ types |= L1D_FLUSH_ORI; ++ ++ enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ ++ security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); + + setup_rfi_flush(types, enable); + } +@@ -501,6 +545,7 @@ static void __init pSeries_setup_arch(void) + fwnmi_init(); + + pseries_setup_rfi_flush(); ++ setup_stf_barrier(); + + /* By default, only probe PCI (can be overridden by rtas_pci) */ + pci_add_flags(PCI_PROBE_ONLY); +diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c +index f87a55d77094..9b3f2e212b37 100644 +--- a/arch/sparc/kernel/ds.c ++++ b/arch/sparc/kernel/ds.c +@@ -908,7 +908,7 @@ static int register_services(struct ds_info *dp) + pbuf.req.handle = cp->handle; + pbuf.req.major = 1; + pbuf.req.minor = 0; +- strcpy(pbuf.req.svc_id, cp->service_id); ++ strcpy(pbuf.id_buf, cp->service_id); + + err = __ds_send(lp, &pbuf, msg_len); + if (err > 0) +diff --git a/arch/sparc/lib/multi3.S b/arch/sparc/lib/multi3.S +index d6b6c97fe3c7..703127aaf4a5 100644 +--- a/arch/sparc/lib/multi3.S ++++ b/arch/sparc/lib/multi3.S +@@ -5,26 +5,26 @@ + .align 4 + ENTRY(__multi3) /* %o0 = u, %o1 = v */ + mov %o1, %g1 +- srl %o3, 0, %g4 +- mulx %g4, %g1, %o1 ++ srl %o3, 0, %o4 ++ mulx %o4, %g1, %o1 + srlx %g1, 0x20, %g3 +- mulx %g3, %g4, %g5 +- sllx %g5, 0x20, %o5 +- srl %g1, 0, %g4 ++ mulx %g3, %o4, %g7 ++ sllx %g7, 0x20, %o5 ++ srl %g1, 0, %o4 + sub %o1, %o5, %o5 + srlx %o5, 0x20, %o5 +- addcc %g5, %o5, %g5 ++ addcc %g7, %o5, %g7 + srlx %o3, 0x20, %o5 +- mulx %g4, %o5, %g4 ++ mulx %o4, %o5, %o4 + mulx %g3, %o5, %o5 + sethi %hi(0x80000000), %g3 +- addcc %g5, %g4, %g5 +- srlx %g5, 0x20, %g5 ++ addcc %g7, %o4, %g7 ++ srlx %g7, 0x20, %g7 + add %g3, %g3, %g3 + movcc %xcc, %g0, %g3 +- addcc %o5, %g5, %o5 +- sllx %g4, 0x20, %g4 +- add %o1, %g4, %o1 ++ addcc %o5, %g7, %o5 ++ sllx %o4, 0x20, %o4 ++ add %o1, %o4, %o1 + add %o5, %g3, %g2 + mulx %g1, %o2, %g1 + add %g1, %g2, %g1 +diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c +index e3a3f5a64884..2986a13b9786 100644 +--- a/arch/x86/xen/enlighten.c ++++ b/arch/x86/xen/enlighten.c +@@ -472,6 +472,12 @@ static void __init xen_init_cpuid_mask(void) + cpuid_leaf1_ecx_set_mask = (1 << (X86_FEATURE_MWAIT % 32)); + } + ++static void __init xen_init_capabilities(void) ++{ ++ if (xen_pv_domain()) ++ setup_force_cpu_cap(X86_FEATURE_XENPV); ++} ++ + static void xen_set_debugreg(int reg, unsigned long val) + { + HYPERVISOR_set_debugreg(reg, val); +@@ -1634,6 +1640,7 @@ asmlinkage __visible void __init xen_start_kernel(void) + + xen_init_irq_ops(); + xen_init_cpuid_mask(); ++ xen_init_capabilities(); + + #ifdef CONFIG_X86_LOCAL_APIC + /* +@@ -1978,12 +1985,6 @@ bool xen_hvm_need_lapic(void) + } + EXPORT_SYMBOL_GPL(xen_hvm_need_lapic); + +-static void xen_set_cpu_features(struct cpuinfo_x86 *c) +-{ +- if (xen_pv_domain()) +- set_cpu_cap(c, X86_FEATURE_XENPV); +-} +- + static void xen_pin_vcpu(int cpu) + { + static bool disable_pinning; +@@ -2030,7 +2031,6 @@ const struct hypervisor_x86 x86_hyper_xen = { + .init_platform = xen_hvm_guest_init, + #endif + .x2apic_available = xen_x2apic_para_available, +- .set_cpu_features = xen_set_cpu_features, + .pin_vcpu = xen_pin_vcpu, + }; + EXPORT_SYMBOL(x86_hyper_xen); +diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c +index 6b54e02da10c..e48140e76043 100644 +--- a/drivers/dma-buf/dma-buf.c ++++ b/drivers/dma-buf/dma-buf.c +@@ -551,7 +551,7 @@ EXPORT_SYMBOL_GPL(dma_buf_detach); + struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, + enum dma_data_direction direction) + { +- struct sg_table *sg_table = ERR_PTR(-EINVAL); ++ struct sg_table *sg_table; + + might_sleep(); + +diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c +index 3e6fe82c6d64..4d49fa0911c6 100644 +--- a/drivers/gpu/drm/drm_dp_helper.c ++++ b/drivers/gpu/drm/drm_dp_helper.c +@@ -1065,6 +1065,7 @@ int drm_dp_psr_setup_time(const u8 psr_cap[EDP_PSR_RECEIVER_CAP_SIZE]) + static const u16 psr_setup_time_us[] = { + PSR_SETUP_TIME(330), + PSR_SETUP_TIME(275), ++ PSR_SETUP_TIME(220), + PSR_SETUP_TIME(165), + PSR_SETUP_TIME(110), + PSR_SETUP_TIME(55), +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index 3517c0ed984a..479d64184da5 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -864,6 +864,14 @@ static const struct dmi_system_id intel_no_lvds[] = { + DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"), + }, + }, ++ { ++ .callback = intel_no_lvds_dmi_callback, ++ .ident = "Radiant P845", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P845"), ++ }, ++ }, + + { } /* terminating entry */ + }; +diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c +index 877a0ed76abf..c38645106783 100644 +--- a/drivers/hwtracing/stm/core.c ++++ b/drivers/hwtracing/stm/core.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include "stm.h" + + #include +@@ -682,7 +683,7 @@ static void stm_device_release(struct device *dev) + { + struct stm_device *stm = to_stm_device(dev); + +- kfree(stm); ++ vfree(stm); + } + + int stm_register_device(struct device *parent, struct stm_data *stm_data, +@@ -699,7 +700,7 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data, + return -EINVAL; + + nmasters = stm_data->sw_end - stm_data->sw_start + 1; +- stm = kzalloc(sizeof(*stm) + nmasters * sizeof(void *), GFP_KERNEL); ++ stm = vzalloc(sizeof(*stm) + nmasters * sizeof(void *)); + if (!stm) + return -ENOMEM; + +@@ -752,7 +753,7 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data, + /* matches device_initialize() above */ + put_device(&stm->dev); + err_free: +- kfree(stm); ++ vfree(stm); + + return err; + } +diff --git a/drivers/iio/buffer/kfifo_buf.c b/drivers/iio/buffer/kfifo_buf.c +index c5b999f0c519..7ef9b13262a8 100644 +--- a/drivers/iio/buffer/kfifo_buf.c ++++ b/drivers/iio/buffer/kfifo_buf.c +@@ -24,6 +24,13 @@ static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, + if ((length == 0) || (bytes_per_datum == 0)) + return -EINVAL; + ++ /* ++ * Make sure we don't overflow an unsigned int after kfifo rounds up to ++ * the next power of 2. ++ */ ++ if (roundup_pow_of_two(length) > UINT_MAX / bytes_per_datum) ++ return -EINVAL; ++ + return __kfifo_alloc((struct __kfifo *)&buf->kf, length, + bytes_per_datum, GFP_KERNEL); + } +diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c +index ae04826e82fc..a32dd851e712 100644 +--- a/drivers/infiniband/core/cache.c ++++ b/drivers/infiniband/core/cache.c +@@ -437,7 +437,7 @@ static int __ib_cache_gid_get(struct ib_device *ib_dev, u8 port, int index, + return -EINVAL; + + if (table->data_vec[index].props & GID_TABLE_ENTRY_INVALID) +- return -EAGAIN; ++ return -EINVAL; + + memcpy(gid, &table->data_vec[index].gid, sizeof(*gid)); + if (attr) { +diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c +index e23b2495d52e..05b8695a6369 100644 +--- a/drivers/input/mouse/elan_i2c_smbus.c ++++ b/drivers/input/mouse/elan_i2c_smbus.c +@@ -130,7 +130,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client *client, + bool max_baseline, u8 *value) + { + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + error = i2c_smbus_read_block_data(client, + max_baseline ? +@@ -149,7 +149,7 @@ static int elan_smbus_get_version(struct i2c_client *client, + bool iap, u8 *version) + { + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + error = i2c_smbus_read_block_data(client, + iap ? ETP_SMBUS_IAP_VERSION_CMD : +@@ -169,7 +169,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client, + u8 *ic_type, u8 *version) + { + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + error = i2c_smbus_read_block_data(client, + ETP_SMBUS_SM_VERSION_CMD, val); +@@ -186,7 +186,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client, + static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id) + { + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + error = i2c_smbus_read_block_data(client, + ETP_SMBUS_UNIQUEID_CMD, val); +@@ -203,7 +203,7 @@ static int elan_smbus_get_checksum(struct i2c_client *client, + bool iap, u16 *csum) + { + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + error = i2c_smbus_read_block_data(client, + iap ? ETP_SMBUS_FW_CHECKSUM_CMD : +@@ -224,7 +224,7 @@ static int elan_smbus_get_max(struct i2c_client *client, + { + int ret; + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val); + if (ret != 3) { +@@ -244,7 +244,7 @@ static int elan_smbus_get_resolution(struct i2c_client *client, + { + int ret; + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val); + if (ret != 3) { +@@ -265,7 +265,7 @@ static int elan_smbus_get_num_traces(struct i2c_client *client, + { + int ret; + int error; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val); + if (ret != 3) { +@@ -292,7 +292,7 @@ static int elan_smbus_iap_get_mode(struct i2c_client *client, + { + int error; + u16 constant; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val); + if (error < 0) { +@@ -343,7 +343,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client *client) + int len; + int error; + enum tp_mode mode; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06}; + u16 password; + +@@ -417,7 +417,7 @@ static int elan_smbus_write_fw_block(struct i2c_client *client, + struct device *dev = &client->dev; + int error; + u16 result; +- u8 val[3]; ++ u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; + + /* + * Due to the limitation of smbus protocol limiting +diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c +index 0b1d5bdd0862..f7b8681aed3f 100644 +--- a/drivers/irqchip/irq-gic-v3.c ++++ b/drivers/irqchip/irq-gic-v3.c +@@ -120,11 +120,10 @@ static void gic_redist_wait_for_rwp(void) + } + + #ifdef CONFIG_ARM64 +-static DEFINE_STATIC_KEY_FALSE(is_cavium_thunderx); + + static u64 __maybe_unused gic_read_iar(void) + { +- if (static_branch_unlikely(&is_cavium_thunderx)) ++ if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_23154)) + return gic_read_iar_cavium_thunderx(); + else + return gic_read_iar_common(); +@@ -908,14 +907,6 @@ static const struct irq_domain_ops partition_domain_ops = { + .select = gic_irq_domain_select, + }; + +-static void gicv3_enable_quirks(void) +-{ +-#ifdef CONFIG_ARM64 +- if (cpus_have_cap(ARM64_WORKAROUND_CAVIUM_23154)) +- static_branch_enable(&is_cavium_thunderx); +-#endif +-} +- + static int __init gic_init_bases(void __iomem *dist_base, + struct redist_region *rdist_regs, + u32 nr_redist_regions, +@@ -938,8 +929,6 @@ static int __init gic_init_bases(void __iomem *dist_base, + gic_data.nr_redist_regions = nr_redist_regions; + gic_data.redist_stride = redist_stride; + +- gicv3_enable_quirks(); +- + /* + * Find out how many interrupts are supported. + * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI) +diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c +index bcbb80ff86a7..1a92cd719e19 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c +@@ -142,16 +142,17 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv, + struct mlx4_en_rx_alloc *frags, + int i) + { +- const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; +- u32 next_frag_end = frags[i].page_offset + 2 * frag_info->frag_stride; +- +- +- if (next_frag_end > frags[i].page_size) +- dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size, +- frag_info->dma_dir); ++ if (frags[i].page) { ++ const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i]; ++ u32 next_frag_end = frags[i].page_offset + ++ 2 * frag_info->frag_stride; + +- if (frags[i].page) ++ if (next_frag_end > frags[i].page_size) { ++ dma_unmap_page(priv->ddev, frags[i].dma, ++ frags[i].page_size, frag_info->dma_dir); ++ } + put_page(frags[i].page); ++ } + } + + static int mlx4_en_init_allocator(struct mlx4_en_priv *priv, +@@ -586,21 +587,28 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv, + int length) + { + struct skb_frag_struct *skb_frags_rx = skb_shinfo(skb)->frags; +- struct mlx4_en_frag_info *frag_info; + int nr; + dma_addr_t dma; + + /* Collect used fragments while replacing them in the HW descriptors */ + for (nr = 0; nr < priv->num_frags; nr++) { +- frag_info = &priv->frag_info[nr]; ++ struct mlx4_en_frag_info *frag_info = &priv->frag_info[nr]; ++ u32 next_frag_end = frags[nr].page_offset + ++ 2 * frag_info->frag_stride; ++ + if (length <= frag_info->frag_prefix_size) + break; + if (unlikely(!frags[nr].page)) + goto fail; + + dma = be64_to_cpu(rx_desc->data[nr].addr); +- dma_sync_single_for_cpu(priv->ddev, dma, frag_info->frag_size, +- DMA_FROM_DEVICE); ++ if (next_frag_end > frags[nr].page_size) ++ dma_unmap_page(priv->ddev, frags[nr].dma, ++ frags[nr].page_size, frag_info->dma_dir); ++ else ++ dma_sync_single_for_cpu(priv->ddev, dma, ++ frag_info->frag_size, ++ DMA_FROM_DEVICE); + + /* Save page reference in skb */ + __skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page); +diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c +index ec2ea56f7933..fdbd35954d15 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c +@@ -304,9 +304,6 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, + writeVal = 0x00000000; + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeVal = writeVal - 0x06060606; +- else if (rtlpriv->dm.dynamic_txhighpower_lvl == +- TXHIGHPWRLEVEL_BT2) +- writeVal = writeVal; + *(p_outwriteval + rf) = writeVal; + } + } +diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c +index 056845bdf67b..bedce3453dd3 100644 +--- a/drivers/pinctrl/qcom/pinctrl-msm.c ++++ b/drivers/pinctrl/qcom/pinctrl-msm.c +@@ -790,7 +790,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) + return -EINVAL; + + chip = &pctrl->chip; +- chip->base = -1; ++ chip->base = 0; + chip->ngpio = ngpio; + chip->label = dev_name(pctrl->dev); + chip->parent = pctrl->dev; +diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c +index f9a245465fd0..6a25bfd4541e 100644 +--- a/drivers/platform/chrome/cros_ec_lpc.c ++++ b/drivers/platform/chrome/cros_ec_lpc.c +@@ -49,7 +49,6 @@ static int ec_response_timed_out(void) + static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec, + struct cros_ec_command *msg) + { +- struct ec_host_request *request; + struct ec_host_response response; + u8 sum = 0; + int i; +@@ -62,8 +61,6 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec, + for (i = 0; i < ret; i++) + outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i); + +- request = (struct ec_host_request *)ec->dout; +- + /* Here we go */ + outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); + +diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c +index e3cd3ece4412..c3d1891d2d3f 100644 +--- a/drivers/scsi/scsi_transport_srp.c ++++ b/drivers/scsi/scsi_transport_srp.c +@@ -52,6 +52,8 @@ struct srp_internal { + struct transport_container rport_attr_cont; + }; + ++static int scsi_is_srp_rport(const struct device *dev); ++ + #define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t) + + #define dev_to_rport(d) container_of(d, struct srp_rport, dev) +@@ -61,9 +63,24 @@ static inline struct Scsi_Host *rport_to_shost(struct srp_rport *r) + return dev_to_shost(r->dev.parent); + } + ++static int find_child_rport(struct device *dev, void *data) ++{ ++ struct device **child = data; ++ ++ if (scsi_is_srp_rport(dev)) { ++ WARN_ON_ONCE(*child); ++ *child = dev; ++ } ++ return 0; ++} ++ + static inline struct srp_rport *shost_to_rport(struct Scsi_Host *shost) + { +- return transport_class_to_srp_rport(&shost->shost_gendev); ++ struct device *child = NULL; ++ ++ WARN_ON_ONCE(device_for_each_child(&shost->shost_gendev, &child, ++ find_child_rport) < 0); ++ return child ? dev_to_rport(child) : NULL; + } + + /** +@@ -637,7 +654,8 @@ static enum blk_eh_timer_return srp_timed_out(struct scsi_cmnd *scmd) + struct srp_rport *rport = shost_to_rport(shost); + + pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev)); +- return rport->fast_io_fail_tmo < 0 && rport->dev_loss_tmo < 0 && ++ return rport && rport->fast_io_fail_tmo < 0 && ++ rport->dev_loss_tmo < 0 && + i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ? + BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; + } +diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h +index 845b874e2977..5bb2316f60bf 100644 +--- a/drivers/scsi/ufs/ufs.h ++++ b/drivers/scsi/ufs/ufs.h +@@ -145,7 +145,7 @@ enum attr_idn { + /* Descriptor idn for Query requests */ + enum desc_idn { + QUERY_DESC_IDN_DEVICE = 0x0, +- QUERY_DESC_IDN_CONFIGURAION = 0x1, ++ QUERY_DESC_IDN_CONFIGURATION = 0x1, + QUERY_DESC_IDN_UNIT = 0x2, + QUERY_DESC_IDN_RFU_0 = 0x3, + QUERY_DESC_IDN_INTERCONNECT = 0x4, +@@ -161,19 +161,13 @@ enum desc_header_offset { + QUERY_DESC_DESC_TYPE_OFFSET = 0x01, + }; + +-enum ufs_desc_max_size { +- QUERY_DESC_DEVICE_MAX_SIZE = 0x1F, +- QUERY_DESC_CONFIGURAION_MAX_SIZE = 0x90, +- QUERY_DESC_UNIT_MAX_SIZE = 0x23, +- QUERY_DESC_INTERCONNECT_MAX_SIZE = 0x06, +- /* +- * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes +- * of descriptor header. +- */ +- QUERY_DESC_STRING_MAX_SIZE = 0xFE, +- QUERY_DESC_GEOMETRY_MAX_SIZE = 0x44, +- QUERY_DESC_POWER_MAX_SIZE = 0x62, +- QUERY_DESC_RFU_MAX_SIZE = 0x00, ++enum ufs_desc_def_size { ++ QUERY_DESC_DEVICE_DEF_SIZE = 0x40, ++ QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90, ++ QUERY_DESC_UNIT_DEF_SIZE = 0x23, ++ QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06, ++ QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44, ++ QUERY_DESC_POWER_DEF_SIZE = 0x62, + }; + + /* Unit descriptor parameters offsets in bytes*/ +@@ -522,4 +516,16 @@ struct ufs_dev_info { + bool is_lu_power_on_wp; + }; + ++#define MAX_MODEL_LEN 16 ++/** ++ * ufs_dev_desc - ufs device details from the device descriptor ++ * ++ * @wmanufacturerid: card details ++ * @model: card model ++ */ ++struct ufs_dev_desc { ++ u16 wmanufacturerid; ++ char model[MAX_MODEL_LEN + 1]; ++}; ++ + #endif /* End of Header */ +diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h +index 08b799d4efcc..71f73d1d1ad1 100644 +--- a/drivers/scsi/ufs/ufs_quirks.h ++++ b/drivers/scsi/ufs/ufs_quirks.h +@@ -21,41 +21,28 @@ + #define UFS_ANY_VENDOR 0xFFFF + #define UFS_ANY_MODEL "ANY_MODEL" + +-#define MAX_MODEL_LEN 16 +- + #define UFS_VENDOR_TOSHIBA 0x198 + #define UFS_VENDOR_SAMSUNG 0x1CE + #define UFS_VENDOR_SKHYNIX 0x1AD + +-/** +- * ufs_device_info - ufs device details +- * @wmanufacturerid: card details +- * @model: card model +- */ +-struct ufs_device_info { +- u16 wmanufacturerid; +- char model[MAX_MODEL_LEN + 1]; +-}; +- + /** + * ufs_dev_fix - ufs device quirk info + * @card: ufs card details + * @quirk: device quirk + */ + struct ufs_dev_fix { +- struct ufs_device_info card; ++ struct ufs_dev_desc card; + unsigned int quirk; + }; + + #define END_FIX { { 0 }, 0 } + + /* add specific device quirk */ +-#define UFS_FIX(_vendor, _model, _quirk) \ +- { \ +- .card.wmanufacturerid = (_vendor),\ +- .card.model = (_model), \ +- .quirk = (_quirk), \ +- } ++#define UFS_FIX(_vendor, _model, _quirk) { \ ++ .card.wmanufacturerid = (_vendor),\ ++ .card.model = (_model), \ ++ .quirk = (_quirk), \ ++} + + /* + * If UFS device is having issue in processing LCC (Line Control +@@ -144,7 +131,4 @@ struct ufs_dev_fix { + */ + #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME (1 << 8) + +-struct ufs_hba; +-void ufs_advertise_fixup_device(struct ufs_hba *hba); +- + #endif /* UFS_QUIRKS_H_ */ +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index 98a7111dd53f..86a3110c6d75 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -98,19 +98,6 @@ + _ret; \ + }) + +-static u32 ufs_query_desc_max_size[] = { +- QUERY_DESC_DEVICE_MAX_SIZE, +- QUERY_DESC_CONFIGURAION_MAX_SIZE, +- QUERY_DESC_UNIT_MAX_SIZE, +- QUERY_DESC_RFU_MAX_SIZE, +- QUERY_DESC_INTERCONNECT_MAX_SIZE, +- QUERY_DESC_STRING_MAX_SIZE, +- QUERY_DESC_RFU_MAX_SIZE, +- QUERY_DESC_GEOMETRY_MAX_SIZE, +- QUERY_DESC_POWER_MAX_SIZE, +- QUERY_DESC_RFU_MAX_SIZE, +-}; +- + enum { + UFSHCD_MAX_CHANNEL = 0, + UFSHCD_MAX_ID = 1, +@@ -1961,7 +1948,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, + goto out; + } + +- if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { ++ if (*buf_len < QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { + dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", + __func__, *buf_len); + err = -EINVAL; +@@ -2040,6 +2027,92 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, + } + EXPORT_SYMBOL(ufshcd_query_descriptor_retry); + ++/** ++ * ufshcd_read_desc_length - read the specified descriptor length from header ++ * @hba: Pointer to adapter instance ++ * @desc_id: descriptor idn value ++ * @desc_index: descriptor index ++ * @desc_length: pointer to variable to read the length of descriptor ++ * ++ * Return 0 in case of success, non-zero otherwise ++ */ ++static int ufshcd_read_desc_length(struct ufs_hba *hba, ++ enum desc_idn desc_id, ++ int desc_index, ++ int *desc_length) ++{ ++ int ret; ++ u8 header[QUERY_DESC_HDR_SIZE]; ++ int header_len = QUERY_DESC_HDR_SIZE; ++ ++ if (desc_id >= QUERY_DESC_IDN_MAX) ++ return -EINVAL; ++ ++ ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, ++ desc_id, desc_index, 0, header, ++ &header_len); ++ ++ if (ret) { ++ dev_err(hba->dev, "%s: Failed to get descriptor header id %d", ++ __func__, desc_id); ++ return ret; ++ } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) { ++ dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch", ++ __func__, header[QUERY_DESC_DESC_TYPE_OFFSET], ++ desc_id); ++ ret = -EINVAL; ++ } ++ ++ *desc_length = header[QUERY_DESC_LENGTH_OFFSET]; ++ return ret; ++ ++} ++ ++/** ++ * ufshcd_map_desc_id_to_length - map descriptor IDN to its length ++ * @hba: Pointer to adapter instance ++ * @desc_id: descriptor idn value ++ * @desc_len: mapped desc length (out) ++ * ++ * Return 0 in case of success, non-zero otherwise ++ */ ++int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, ++ enum desc_idn desc_id, int *desc_len) ++{ ++ switch (desc_id) { ++ case QUERY_DESC_IDN_DEVICE: ++ *desc_len = hba->desc_size.dev_desc; ++ break; ++ case QUERY_DESC_IDN_POWER: ++ *desc_len = hba->desc_size.pwr_desc; ++ break; ++ case QUERY_DESC_IDN_GEOMETRY: ++ *desc_len = hba->desc_size.geom_desc; ++ break; ++ case QUERY_DESC_IDN_CONFIGURATION: ++ *desc_len = hba->desc_size.conf_desc; ++ break; ++ case QUERY_DESC_IDN_UNIT: ++ *desc_len = hba->desc_size.unit_desc; ++ break; ++ case QUERY_DESC_IDN_INTERCONNECT: ++ *desc_len = hba->desc_size.interc_desc; ++ break; ++ case QUERY_DESC_IDN_STRING: ++ *desc_len = QUERY_DESC_MAX_SIZE; ++ break; ++ case QUERY_DESC_IDN_RFU_0: ++ case QUERY_DESC_IDN_RFU_1: ++ *desc_len = 0; ++ break; ++ default: ++ *desc_len = 0; ++ return -EINVAL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(ufshcd_map_desc_id_to_length); ++ + /** + * ufshcd_read_desc_param - read the specified descriptor parameter + * @hba: Pointer to adapter instance +@@ -2054,50 +2127,64 @@ EXPORT_SYMBOL(ufshcd_query_descriptor_retry); + static int ufshcd_read_desc_param(struct ufs_hba *hba, + enum desc_idn desc_id, + int desc_index, +- u32 param_offset, ++ u8 param_offset, + u8 *param_read_buf, +- u32 param_size) ++ u8 param_size) + { + int ret; + u8 *desc_buf; +- u32 buff_len; ++ int buff_len; + bool is_kmalloc = true; + +- /* safety checks */ +- if (desc_id >= QUERY_DESC_IDN_MAX) ++ /* Safety check */ ++ if (desc_id >= QUERY_DESC_IDN_MAX || !param_size) + return -EINVAL; + +- buff_len = ufs_query_desc_max_size[desc_id]; +- if ((param_offset + param_size) > buff_len) +- return -EINVAL; ++ /* Get the max length of descriptor from structure filled up at probe ++ * time. ++ */ ++ ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len); + +- if (!param_offset && (param_size == buff_len)) { +- /* memory space already available to hold full descriptor */ +- desc_buf = param_read_buf; +- is_kmalloc = false; +- } else { +- /* allocate memory to hold full descriptor */ ++ /* Sanity checks */ ++ if (ret || !buff_len) { ++ dev_err(hba->dev, "%s: Failed to get full descriptor length", ++ __func__); ++ return ret; ++ } ++ ++ /* Check whether we need temp memory */ ++ if (param_offset != 0 || param_size < buff_len) { + desc_buf = kmalloc(buff_len, GFP_KERNEL); + if (!desc_buf) + return -ENOMEM; ++ } else { ++ desc_buf = param_read_buf; ++ is_kmalloc = false; + } + ++ /* Request for full descriptor */ + ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, +- desc_id, desc_index, 0, desc_buf, +- &buff_len); +- +- if (ret || (buff_len < ufs_query_desc_max_size[desc_id]) || +- (desc_buf[QUERY_DESC_LENGTH_OFFSET] != +- ufs_query_desc_max_size[desc_id]) +- || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) { +- dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d param_offset %d buff_len %d ret %d", +- __func__, desc_id, param_offset, buff_len, ret); +- if (!ret) +- ret = -EINVAL; ++ desc_id, desc_index, 0, ++ desc_buf, &buff_len); ++ ++ if (ret) { ++ dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d", ++ __func__, desc_id, desc_index, param_offset, ret); ++ goto out; ++ } + ++ /* Sanity check */ ++ if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) { ++ dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header", ++ __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]); ++ ret = -EINVAL; + goto out; + } + ++ /* Check wherher we will not copy more data, than available */ ++ if (is_kmalloc && param_size > buff_len) ++ param_size = buff_len; ++ + if (is_kmalloc) + memcpy(param_read_buf, &desc_buf[param_offset], param_size); + out: +@@ -4789,8 +4876,8 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba, + static void ufshcd_init_icc_levels(struct ufs_hba *hba) + { + int ret; +- int buff_len = QUERY_DESC_POWER_MAX_SIZE; +- u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE]; ++ int buff_len = hba->desc_size.pwr_desc; ++ u8 desc_buf[hba->desc_size.pwr_desc]; + + ret = ufshcd_read_power_desc(hba, desc_buf, buff_len); + if (ret) { +@@ -4883,16 +4970,15 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) + return ret; + } + +-static int ufs_get_device_info(struct ufs_hba *hba, +- struct ufs_device_info *card_data) ++static int ufs_get_device_desc(struct ufs_hba *hba, ++ struct ufs_dev_desc *dev_desc) + { + int err; + u8 model_index; +- u8 str_desc_buf[QUERY_DESC_STRING_MAX_SIZE + 1] = {0}; +- u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE]; ++ u8 str_desc_buf[QUERY_DESC_MAX_SIZE + 1] = {0}; ++ u8 desc_buf[hba->desc_size.dev_desc]; + +- err = ufshcd_read_device_desc(hba, desc_buf, +- QUERY_DESC_DEVICE_MAX_SIZE); ++ err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc); + if (err) { + dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n", + __func__, err); +@@ -4903,50 +4989,40 @@ static int ufs_get_device_info(struct ufs_hba *hba, + * getting vendor (manufacturerID) and Bank Index in big endian + * format + */ +- card_data->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 | ++ dev_desc->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 | + desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]; + + model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; + + err = ufshcd_read_string_desc(hba, model_index, str_desc_buf, +- QUERY_DESC_STRING_MAX_SIZE, ASCII_STD); ++ QUERY_DESC_MAX_SIZE, ASCII_STD); + if (err) { + dev_err(hba->dev, "%s: Failed reading Product Name. err = %d\n", + __func__, err); + goto out; + } + +- str_desc_buf[QUERY_DESC_STRING_MAX_SIZE] = '\0'; +- strlcpy(card_data->model, (str_desc_buf + QUERY_DESC_HDR_SIZE), ++ str_desc_buf[QUERY_DESC_MAX_SIZE] = '\0'; ++ strlcpy(dev_desc->model, (str_desc_buf + QUERY_DESC_HDR_SIZE), + min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET], + MAX_MODEL_LEN)); + + /* Null terminate the model string */ +- card_data->model[MAX_MODEL_LEN] = '\0'; ++ dev_desc->model[MAX_MODEL_LEN] = '\0'; + + out: + return err; + } + +-void ufs_advertise_fixup_device(struct ufs_hba *hba) ++static void ufs_fixup_device_setup(struct ufs_hba *hba, ++ struct ufs_dev_desc *dev_desc) + { +- int err; + struct ufs_dev_fix *f; +- struct ufs_device_info card_data; +- +- card_data.wmanufacturerid = 0; +- +- err = ufs_get_device_info(hba, &card_data); +- if (err) { +- dev_err(hba->dev, "%s: Failed getting device info. err = %d\n", +- __func__, err); +- return; +- } + + for (f = ufs_fixups; f->quirk; f++) { +- if (((f->card.wmanufacturerid == card_data.wmanufacturerid) || +- (f->card.wmanufacturerid == UFS_ANY_VENDOR)) && +- (STR_PRFX_EQUAL(f->card.model, card_data.model) || ++ if ((f->card.wmanufacturerid == dev_desc->wmanufacturerid || ++ f->card.wmanufacturerid == UFS_ANY_VENDOR) && ++ (STR_PRFX_EQUAL(f->card.model, dev_desc->model) || + !strcmp(f->card.model, UFS_ANY_MODEL))) + hba->dev_quirks |= f->quirk; + } +@@ -5116,6 +5192,51 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) + ufshcd_vops_apply_dev_quirks(hba); + } + ++static void ufshcd_init_desc_sizes(struct ufs_hba *hba) ++{ ++ int err; ++ ++ err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_DEVICE, 0, ++ &hba->desc_size.dev_desc); ++ if (err) ++ hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; ++ ++ err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_POWER, 0, ++ &hba->desc_size.pwr_desc); ++ if (err) ++ hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; ++ ++ err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_INTERCONNECT, 0, ++ &hba->desc_size.interc_desc); ++ if (err) ++ hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; ++ ++ err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_CONFIGURATION, 0, ++ &hba->desc_size.conf_desc); ++ if (err) ++ hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; ++ ++ err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_UNIT, 0, ++ &hba->desc_size.unit_desc); ++ if (err) ++ hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; ++ ++ err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_GEOMETRY, 0, ++ &hba->desc_size.geom_desc); ++ if (err) ++ hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; ++} ++ ++static void ufshcd_def_desc_sizes(struct ufs_hba *hba) ++{ ++ hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE; ++ hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE; ++ hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE; ++ hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE; ++ hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE; ++ hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE; ++} ++ + /** + * ufshcd_probe_hba - probe hba to detect device and initialize + * @hba: per-adapter instance +@@ -5124,6 +5245,7 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba) + */ + static int ufshcd_probe_hba(struct ufs_hba *hba) + { ++ struct ufs_dev_desc card = {0}; + int ret; + + ret = ufshcd_link_startup(hba); +@@ -5147,7 +5269,17 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) + if (ret) + goto out; + +- ufs_advertise_fixup_device(hba); ++ /* Init check for device descriptor sizes */ ++ ufshcd_init_desc_sizes(hba); ++ ++ ret = ufs_get_device_desc(hba, &card); ++ if (ret) { ++ dev_err(hba->dev, "%s: Failed getting device info. err = %d\n", ++ __func__, ret); ++ goto out; ++ } ++ ++ ufs_fixup_device_setup(hba, &card); + ufshcd_tune_unipro_params(hba); + + ret = ufshcd_set_vccq_rail_unused(hba, +@@ -5173,6 +5305,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) + + /* set the state as operational after switching to desired gear */ + hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; ++ + /* + * If we are in error handling context or in power management callbacks + * context, no need to scan the host +@@ -6549,6 +6682,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) + hba->mmio_base = mmio_base; + hba->irq = irq; + ++ /* Set descriptor lengths to specification defaults */ ++ ufshcd_def_desc_sizes(hba); ++ + err = ufshcd_hba_init(hba); + if (err) + goto out_error; +diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h +index f2170d5058a8..6dbd2e176333 100644 +--- a/drivers/scsi/ufs/ufshcd.h ++++ b/drivers/scsi/ufs/ufshcd.h +@@ -205,6 +205,15 @@ struct ufs_dev_cmd { + struct ufs_query query; + }; + ++struct ufs_desc_size { ++ int dev_desc; ++ int pwr_desc; ++ int geom_desc; ++ int interc_desc; ++ int unit_desc; ++ int conf_desc; ++}; ++ + /** + * struct ufs_clk_info - UFS clock related info + * @list: list headed by hba->clk_list_head +@@ -388,6 +397,7 @@ struct ufs_init_prefetch { + * @clk_list_head: UFS host controller clocks list node head + * @pwr_info: holds current power mode + * @max_pwr_info: keeps the device max valid pwm ++ * @desc_size: descriptor sizes reported by device + * @urgent_bkops_lvl: keeps track of urgent bkops level for device + * @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for + * device is known or not. +@@ -563,6 +573,8 @@ struct ufs_hba { + + enum bkops_status urgent_bkops_lvl; + bool is_urgent_bkops_lvl_checked; ++ ++ struct ufs_desc_size desc_size; + }; + + /* Returns true if clocks can be gated. Otherwise false */ +@@ -736,6 +748,10 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, + enum flag_idn idn, bool *flag_res); + int ufshcd_hold(struct ufs_hba *hba, bool async); + void ufshcd_release(struct ufs_hba *hba); ++ ++int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, ++ int *desc_length); ++ + u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba); + + /* Wrapper functions for safely calling variant operations */ +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index b42d7f1c9089..6b1863293fe1 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -2320,12 +2320,67 @@ static int __init pl011_console_setup(struct console *co, char *options) + return uart_set_options(&uap->port, co, baud, parity, bits, flow); + } + ++/** ++ * pl011_console_match - non-standard console matching ++ * @co: registering console ++ * @name: name from console command line ++ * @idx: index from console command line ++ * @options: ptr to option string from console command line ++ * ++ * Only attempts to match console command lines of the form: ++ * console=pl011,mmio|mmio32,[,] ++ * console=pl011,0x[,] ++ * This form is used to register an initial earlycon boot console and ++ * replace it with the amba_console at pl011 driver init. ++ * ++ * Performs console setup for a match (as required by interface) ++ * If no are specified, then assume the h/w is already setup. ++ * ++ * Returns 0 if console matches; otherwise non-zero to use default matching ++ */ ++static int __init pl011_console_match(struct console *co, char *name, int idx, ++ char *options) ++{ ++ unsigned char iotype; ++ resource_size_t addr; ++ int i; ++ ++ if (strcmp(name, "pl011") != 0) ++ return -ENODEV; ++ ++ if (uart_parse_earlycon(options, &iotype, &addr, &options)) ++ return -ENODEV; ++ ++ if (iotype != UPIO_MEM && iotype != UPIO_MEM32) ++ return -ENODEV; ++ ++ /* try to match the port specified on the command line */ ++ for (i = 0; i < ARRAY_SIZE(amba_ports); i++) { ++ struct uart_port *port; ++ ++ if (!amba_ports[i]) ++ continue; ++ ++ port = &amba_ports[i]->port; ++ ++ if (port->mapbase != addr) ++ continue; ++ ++ co->index = i; ++ port->cons = co; ++ return pl011_console_setup(co, options); ++ } ++ ++ return -ENODEV; ++} ++ + static struct uart_driver amba_reg; + static struct console amba_console = { + .name = "ttyAMA", + .write = pl011_console_write, + .device = uart_console_device, + .setup = pl011_console_setup, ++ .match = pl011_console_match, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &amba_reg, +diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c +index d98531823998..46b4dea7a0ec 100644 +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -33,7 +33,7 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *); + static void cp210x_close(struct usb_serial_port *); + static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *); + static void cp210x_get_termios_port(struct usb_serial_port *port, +- unsigned int *cflagp, unsigned int *baudp); ++ tcflag_t *cflagp, unsigned int *baudp); + static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *, + struct ktermios *); + static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, +@@ -728,7 +728,7 @@ static void cp210x_get_termios(struct tty_struct *tty, + &tty->termios.c_cflag, &baud); + tty_encode_baud_rate(tty, baud, baud); + } else { +- unsigned int cflag; ++ tcflag_t cflag; + cflag = 0; + cp210x_get_termios_port(port, &cflag, &baud); + } +@@ -739,10 +739,10 @@ static void cp210x_get_termios(struct tty_struct *tty, + * This is the heart of cp210x_get_termios which always uses a &usb_serial_port. + */ + static void cp210x_get_termios_port(struct usb_serial_port *port, +- unsigned int *cflagp, unsigned int *baudp) ++ tcflag_t *cflagp, unsigned int *baudp) + { + struct device *dev = &port->dev; +- unsigned int cflag; ++ tcflag_t cflag; + struct cp210x_flow_ctl flow_ctl; + u32 baud; + u16 bits; +diff --git a/fs/aio.c b/fs/aio.c +index 42d8c09311d1..b1170a7affe2 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -636,9 +636,8 @@ static void free_ioctx_users(struct percpu_ref *ref) + while (!list_empty(&ctx->active_reqs)) { + req = list_first_entry(&ctx->active_reqs, + struct aio_kiocb, ki_list); +- +- list_del_init(&req->ki_list); + kiocb_cancel(req); ++ list_del_init(&req->ki_list); + } + + spin_unlock_irq(&ctx->ctx_lock); +diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c +index c3702cda010a..e567551402a6 100644 +--- a/fs/xfs/libxfs/xfs_alloc.c ++++ b/fs/xfs/libxfs/xfs_alloc.c +@@ -2034,6 +2034,93 @@ xfs_alloc_space_available( + return true; + } + ++/* ++ * Check the agfl fields of the agf for inconsistency or corruption. The purpose ++ * is to detect an agfl header padding mismatch between current and early v5 ++ * kernels. This problem manifests as a 1-slot size difference between the ++ * on-disk flcount and the active [first, last] range of a wrapped agfl. This ++ * may also catch variants of agfl count corruption unrelated to padding. Either ++ * way, we'll reset the agfl and warn the user. ++ * ++ * Return true if a reset is required before the agfl can be used, false ++ * otherwise. ++ */ ++static bool ++xfs_agfl_needs_reset( ++ struct xfs_mount *mp, ++ struct xfs_agf *agf) ++{ ++ uint32_t f = be32_to_cpu(agf->agf_flfirst); ++ uint32_t l = be32_to_cpu(agf->agf_fllast); ++ uint32_t c = be32_to_cpu(agf->agf_flcount); ++ int agfl_size = XFS_AGFL_SIZE(mp); ++ int active; ++ ++ /* no agfl header on v4 supers */ ++ if (!xfs_sb_version_hascrc(&mp->m_sb)) ++ return false; ++ ++ /* ++ * The agf read verifier catches severe corruption of these fields. ++ * Repeat some sanity checks to cover a packed -> unpacked mismatch if ++ * the verifier allows it. ++ */ ++ if (f >= agfl_size || l >= agfl_size) ++ return true; ++ if (c > agfl_size) ++ return true; ++ ++ /* ++ * Check consistency between the on-disk count and the active range. An ++ * agfl padding mismatch manifests as an inconsistent flcount. ++ */ ++ if (c && l >= f) ++ active = l - f + 1; ++ else if (c) ++ active = agfl_size - f + l + 1; ++ else ++ active = 0; ++ ++ return active != c; ++} ++ ++/* ++ * Reset the agfl to an empty state. Ignore/drop any existing blocks since the ++ * agfl content cannot be trusted. Warn the user that a repair is required to ++ * recover leaked blocks. ++ * ++ * The purpose of this mechanism is to handle filesystems affected by the agfl ++ * header padding mismatch problem. A reset keeps the filesystem online with a ++ * relatively minor free space accounting inconsistency rather than suffer the ++ * inevitable crash from use of an invalid agfl block. ++ */ ++static void ++xfs_agfl_reset( ++ struct xfs_trans *tp, ++ struct xfs_buf *agbp, ++ struct xfs_perag *pag) ++{ ++ struct xfs_mount *mp = tp->t_mountp; ++ struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); ++ ++ ASSERT(pag->pagf_agflreset); ++ trace_xfs_agfl_reset(mp, agf, 0, _RET_IP_); ++ ++ xfs_warn(mp, ++ "WARNING: Reset corrupted AGFL on AG %u. %d blocks leaked. " ++ "Please unmount and run xfs_repair.", ++ pag->pag_agno, pag->pagf_flcount); ++ ++ agf->agf_flfirst = 0; ++ agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); ++ agf->agf_flcount = 0; ++ xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLLAST | ++ XFS_AGF_FLCOUNT); ++ ++ pag->pagf_flcount = 0; ++ pag->pagf_agflreset = false; ++} ++ + /* + * Decide whether to use this allocation group for this allocation. + * If so, fix up the btree freelist's size. +@@ -2095,6 +2182,10 @@ xfs_alloc_fix_freelist( + } + } + ++ /* reset a padding mismatched agfl before final free space check */ ++ if (pag->pagf_agflreset) ++ xfs_agfl_reset(tp, agbp, pag); ++ + /* If there isn't enough total space or single-extent, reject it. */ + need = xfs_alloc_min_freelist(mp, pag); + if (!xfs_alloc_space_available(args, need, flags)) +@@ -2251,6 +2342,7 @@ xfs_alloc_get_freelist( + agf->agf_flfirst = 0; + + pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); ++ ASSERT(!pag->pagf_agflreset); + be32_add_cpu(&agf->agf_flcount, -1); + xfs_trans_agflist_delta(tp, -1); + pag->pagf_flcount--; +@@ -2362,6 +2454,7 @@ xfs_alloc_put_freelist( + agf->agf_fllast = 0; + + pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno)); ++ ASSERT(!pag->pagf_agflreset); + be32_add_cpu(&agf->agf_flcount, 1); + xfs_trans_agflist_delta(tp, 1); + pag->pagf_flcount++; +@@ -2568,6 +2661,7 @@ xfs_alloc_read_agf( + pag->pagb_count = 0; + pag->pagb_tree = RB_ROOT; + pag->pagf_init = 1; ++ pag->pagf_agflreset = xfs_agfl_needs_reset(mp, agf); + } + #ifdef DEBUG + else if (!XFS_FORCED_SHUTDOWN(mp)) { +diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h +index 5415f9031ef8..7cb099e1c84c 100644 +--- a/fs/xfs/xfs_mount.h ++++ b/fs/xfs/xfs_mount.h +@@ -368,6 +368,7 @@ typedef struct xfs_perag { + char pagi_inodeok; /* The agi is ok for inodes */ + __uint8_t pagf_levels[XFS_BTNUM_AGF]; + /* # of levels in bno & cnt btree */ ++ bool pagf_agflreset; /* agfl requires reset before use */ + __uint32_t pagf_flcount; /* count of blocks in freelist */ + xfs_extlen_t pagf_freeblks; /* total free blocks */ + xfs_extlen_t pagf_longest; /* longest free space */ +diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h +index bdf69e1c7410..42a7c0da898f 100644 +--- a/fs/xfs/xfs_trace.h ++++ b/fs/xfs/xfs_trace.h +@@ -1516,7 +1516,7 @@ TRACE_EVENT(xfs_trans_commit_lsn, + __entry->lsn) + ); + +-TRACE_EVENT(xfs_agf, ++DECLARE_EVENT_CLASS(xfs_agf_class, + TP_PROTO(struct xfs_mount *mp, struct xfs_agf *agf, int flags, + unsigned long caller_ip), + TP_ARGS(mp, agf, flags, caller_ip), +@@ -1572,6 +1572,13 @@ TRACE_EVENT(xfs_agf, + __entry->longest, + (void *)__entry->caller_ip) + ); ++#define DEFINE_AGF_EVENT(name) \ ++DEFINE_EVENT(xfs_agf_class, name, \ ++ TP_PROTO(struct xfs_mount *mp, struct xfs_agf *agf, int flags, \ ++ unsigned long caller_ip), \ ++ TP_ARGS(mp, agf, flags, caller_ip)) ++DEFINE_AGF_EVENT(xfs_agf); ++DEFINE_AGF_EVENT(xfs_agfl_reset); + + TRACE_EVENT(xfs_free_extent, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index f50b717ce644..d0c3615f9050 100644 +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -337,7 +337,7 @@ struct tcp_sock { + + /* Receiver queue space */ + struct { +- int space; ++ u32 space; + u32 seq; + u32 time; + } rcvq_space; +diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h +index 7290eacc8cee..b902f106f69a 100644 +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2379,7 +2379,7 @@ enum nl80211_attrs { + #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS + #define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + +-#define NL80211_WIPHY_NAME_MAXLEN 128 ++#define NL80211_WIPHY_NAME_MAXLEN 64 + + #define NL80211_MAX_SUPP_RATES 32 + #define NL80211_MAX_SUPP_HT_RATES 77 +diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c +index 6721a1e89f39..88f398af57fa 100644 +--- a/kernel/trace/trace_events_trigger.c ++++ b/kernel/trace/trace_events_trigger.c +@@ -481,9 +481,10 @@ clear_event_triggers(struct trace_array *tr) + struct trace_event_file *file; + + list_for_each_entry(file, &tr->events, list) { +- struct event_trigger_data *data; +- list_for_each_entry_rcu(data, &file->triggers, list) { ++ struct event_trigger_data *data, *n; ++ list_for_each_entry_safe(data, n, &file->triggers, list) { + trace_event_trigger_enable_disable(file, 0); ++ list_del_rcu(&data->list); + if (data->ops->free) + data->ops->free(data->ops, data); + } +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 2d4b6478237b..f03ca5ab86b1 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -1393,7 +1393,7 @@ int __isolate_lru_page(struct page *page, isolate_mode_t mode) + return ret; + + mapping = page_mapping(page); +- migrate_dirty = mapping && mapping->a_ops->migratepage; ++ migrate_dirty = !mapping || mapping->a_ops->migratepage; + unlock_page(page); + if (!migrate_dirty) + return ret; +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 52b0a84be765..94a55b83e48c 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -581,8 +581,8 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk, + void tcp_rcv_space_adjust(struct sock *sk) + { + struct tcp_sock *tp = tcp_sk(sk); ++ u32 copied; + int time; +- int copied; + + time = tcp_time_stamp - tp->rcvq_space.time; + if (time < (tp->rcv_rtt_est.rtt >> 3) || tp->rcv_rtt_est.rtt == 0) +@@ -604,12 +604,13 @@ void tcp_rcv_space_adjust(struct sock *sk) + + if (sysctl_tcp_moderate_rcvbuf && + !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) { +- int rcvwin, rcvmem, rcvbuf; ++ int rcvmem, rcvbuf; ++ u64 rcvwin; + + /* minimal window to cope with packet losses, assuming + * steady state. Add some cushion because of small variations. + */ +- rcvwin = (copied << 1) + 16 * tp->advmss; ++ rcvwin = ((u64)copied << 1) + 16 * tp->advmss; + + /* If rate increased by 25%, + * assume slow start, rcvwin = 3 * copied +@@ -629,7 +630,8 @@ void tcp_rcv_space_adjust(struct sock *sk) + while (tcp_win_from_space(rcvmem) < tp->advmss) + rcvmem += 128; + +- rcvbuf = min(rcvwin / tp->advmss * rcvmem, sysctl_tcp_rmem[2]); ++ do_div(rcvwin, tp->advmss); ++ rcvbuf = min_t(u64, rcvwin * rcvmem, sysctl_tcp_rmem[2]); + if (rcvbuf > sk->sk_rcvbuf) { + sk->sk_rcvbuf = rcvbuf; + +diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c +index 7bf8b005a178..1e6f23f77f15 100644 +--- a/security/integrity/ima/ima_appraise.c ++++ b/security/integrity/ima/ima_appraise.c +@@ -389,14 +389,10 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + result = ima_protect_xattr(dentry, xattr_name, xattr_value, + xattr_value_len); + if (result == 1) { +- bool digsig; +- + if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST)) + return -EINVAL; +- digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG); +- if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE)) +- return -EPERM; +- ima_reset_appraise_flags(d_backing_inode(dentry), digsig); ++ ima_reset_appraise_flags(d_backing_inode(dentry), ++ (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0); + result = 0; + } + return result; +diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c +index d656b7c98394..bfc4ffa1fa1a 100644 +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -1435,7 +1435,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, + scontext_len, &context, def_sid); + if (rc == -EINVAL && force) { + context.str = str; +- context.len = scontext_len; ++ context.len = strlen(str) + 1; + str = NULL; + } else if (rc) + goto out_unlock; +diff --git a/sound/soc/intel/common/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c +index a086c35f91bb..79a9fdf94d38 100644 +--- a/sound/soc/intel/common/sst-firmware.c ++++ b/sound/soc/intel/common/sst-firmware.c +@@ -274,7 +274,6 @@ int sst_dma_new(struct sst_dsp *sst) + struct sst_pdata *sst_pdata = sst->pdata; + struct sst_dma *dma; + struct resource mem; +- const char *dma_dev_name; + int ret = 0; + + if (sst->pdata->resindex_dma_base == -1) +@@ -285,7 +284,6 @@ int sst_dma_new(struct sst_dsp *sst) + * is attached to the ADSP IP. */ + switch (sst->pdata->dma_engine) { + case SST_DMA_TYPE_DW: +- dma_dev_name = "dw_dmac"; + break; + default: + dev_err(sst->dev, "error: invalid DMA engine %d\n",