From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id A72C81580EB for ; Thu, 22 May 2025 13:40:18 +0000 (UTC) Received: from lists.gentoo.org (bobolink.gentoo.org [140.211.166.189]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: relay-lists.gentoo.org@gentoo.org) by smtp.gentoo.org (Postfix) with ESMTPSA id 9ACEA3430C6 for ; Thu, 22 May 2025 13:40:18 +0000 (UTC) Received: from bobolink.gentoo.org (localhost [127.0.0.1]) by bobolink.gentoo.org (Postfix) with ESMTP id 6F9791103DE; Thu, 22 May 2025 13:40:17 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [140.211.166.183]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bobolink.gentoo.org (Postfix) with ESMTPS id 630081103DE for ; Thu, 22 May 2025 13:40:17 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id A4FBA3430BD for ; Thu, 22 May 2025 13:40:16 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 0CF021968 for ; Thu, 22 May 2025 13:40:15 +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: <1747921200.c579c98ecd05dd166b78e1503aa5ee23e379b1fd.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:5.15 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1183_linux-5.15.184.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: c579c98ecd05dd166b78e1503aa5ee23e379b1fd X-VCS-Branch: 5.15 Date: Thu, 22 May 2025 13:40:15 +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-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: eed4ca05-3280-4844-80cf-e7b79cdceaea X-Archives-Hash: 090b569324449265da319afc1c834d02 commit: c579c98ecd05dd166b78e1503aa5ee23e379b1fd Author: Mike Pagano gentoo org> AuthorDate: Thu May 22 13:40:00 2025 +0000 Commit: Mike Pagano gentoo org> CommitDate: Thu May 22 13:40:00 2025 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=c579c98e Linux patch 5.15.184 Signed-off-by: Mike Pagano gentoo.org> 0000_README | 4 + 1183_linux-5.15.184.patch | 2835 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2839 insertions(+) diff --git a/0000_README b/0000_README index f44e48d0..aec14aab 100644 --- a/0000_README +++ b/0000_README @@ -775,6 +775,10 @@ Patch: 1182_linux-5.15.183.patch From: https://www.kernel.org Desc: Linux 5.15.183 +Patch: 1183_linux-5.15.184.patch +From: https://www.kernel.org +Desc: Linux 5.15.184 + 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/1183_linux-5.15.184.patch b/1183_linux-5.15.184.patch new file mode 100644 index 00000000..58f68c5f --- /dev/null +++ b/1183_linux-5.15.184.patch @@ -0,0 +1,2835 @@ +diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu +index 23e0537f6e0c79..1d657a6b1b53bd 100644 +--- a/Documentation/ABI/testing/sysfs-devices-system-cpu ++++ b/Documentation/ABI/testing/sysfs-devices-system-cpu +@@ -512,6 +512,7 @@ Description: information about CPUs heterogeneity. + + What: /sys/devices/system/cpu/vulnerabilities + /sys/devices/system/cpu/vulnerabilities/gather_data_sampling ++ /sys/devices/system/cpu/vulnerabilities/indirect_target_selection + /sys/devices/system/cpu/vulnerabilities/itlb_multihit + /sys/devices/system/cpu/vulnerabilities/l1tf + /sys/devices/system/cpu/vulnerabilities/mds +diff --git a/Documentation/admin-guide/hw-vuln/index.rst b/Documentation/admin-guide/hw-vuln/index.rst +index 3e4a14e38b49e8..dc69ba0b05e474 100644 +--- a/Documentation/admin-guide/hw-vuln/index.rst ++++ b/Documentation/admin-guide/hw-vuln/index.rst +@@ -22,3 +22,4 @@ are configurable at compile, boot or run time. + gather_data_sampling.rst + srso + reg-file-data-sampling ++ indirect-target-selection +diff --git a/Documentation/admin-guide/hw-vuln/indirect-target-selection.rst b/Documentation/admin-guide/hw-vuln/indirect-target-selection.rst +new file mode 100644 +index 00000000000000..4788e14ebce09a +--- /dev/null ++++ b/Documentation/admin-guide/hw-vuln/indirect-target-selection.rst +@@ -0,0 +1,156 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++Indirect Target Selection (ITS) ++=============================== ++ ++ITS is a vulnerability in some Intel CPUs that support Enhanced IBRS and were ++released before Alder Lake. ITS may allow an attacker to control the prediction ++of indirect branches and RETs located in the lower half of a cacheline. ++ ++ITS is assigned CVE-2024-28956 with a CVSS score of 4.7 (Medium). ++ ++Scope of Impact ++--------------- ++- **eIBRS Guest/Host Isolation**: Indirect branches in KVM/kernel may still be ++ predicted with unintended target corresponding to a branch in the guest. ++ ++- **Intra-Mode BTI**: In-kernel training such as through cBPF or other native ++ gadgets. ++ ++- **Indirect Branch Prediction Barrier (IBPB)**: After an IBPB, indirect ++ branches may still be predicted with targets corresponding to direct branches ++ executed prior to the IBPB. This is fixed by the IPU 2025.1 microcode, which ++ should be available via distro updates. Alternatively microcode can be ++ obtained from Intel's github repository [#f1]_. ++ ++Affected CPUs ++------------- ++Below is the list of ITS affected CPUs [#f2]_ [#f3]_: ++ ++ ======================== ============ ==================== =============== ++ Common name Family_Model eIBRS Intra-mode BTI ++ Guest/Host Isolation ++ ======================== ============ ==================== =============== ++ SKYLAKE_X (step >= 6) 06_55H Affected Affected ++ ICELAKE_X 06_6AH Not affected Affected ++ ICELAKE_D 06_6CH Not affected Affected ++ ICELAKE_L 06_7EH Not affected Affected ++ TIGERLAKE_L 06_8CH Not affected Affected ++ TIGERLAKE 06_8DH Not affected Affected ++ KABYLAKE_L (step >= 12) 06_8EH Affected Affected ++ KABYLAKE (step >= 13) 06_9EH Affected Affected ++ COMETLAKE 06_A5H Affected Affected ++ COMETLAKE_L 06_A6H Affected Affected ++ ROCKETLAKE 06_A7H Not affected Affected ++ ======================== ============ ==================== =============== ++ ++- All affected CPUs enumerate Enhanced IBRS feature. ++- IBPB isolation is affected on all ITS affected CPUs, and need a microcode ++ update for mitigation. ++- None of the affected CPUs enumerate BHI_CTRL which was introduced in Golden ++ Cove (Alder Lake and Sapphire Rapids). This can help guests to determine the ++ host's affected status. ++- Intel Atom CPUs are not affected by ITS. ++ ++Mitigation ++---------- ++As only the indirect branches and RETs that have their last byte of instruction ++in the lower half of the cacheline are vulnerable to ITS, the basic idea behind ++the mitigation is to not allow indirect branches in the lower half. ++ ++This is achieved by relying on existing retpoline support in the kernel, and in ++compilers. ITS-vulnerable retpoline sites are runtime patched to point to newly ++added ITS-safe thunks. These safe thunks consists of indirect branch in the ++second half of the cacheline. Not all retpoline sites are patched to thunks, if ++a retpoline site is evaluated to be ITS-safe, it is replaced with an inline ++indirect branch. ++ ++Dynamic thunks ++~~~~~~~~~~~~~~ ++From a dynamically allocated pool of safe-thunks, each vulnerable site is ++replaced with a new thunk, such that they get a unique address. This could ++improve the branch prediction accuracy. Also, it is a defense-in-depth measure ++against aliasing. ++ ++Note, for simplicity, indirect branches in eBPF programs are always replaced ++with a jump to a static thunk in __x86_indirect_its_thunk_array. If required, ++in future this can be changed to use dynamic thunks. ++ ++All vulnerable RETs are replaced with a static thunk, they do not use dynamic ++thunks. This is because RETs get their prediction from RSB mostly that does not ++depend on source address. RETs that underflow RSB may benefit from dynamic ++thunks. But, RETs significantly outnumber indirect branches, and any benefit ++from a unique source address could be outweighed by the increased icache ++footprint and iTLB pressure. ++ ++Retpoline ++~~~~~~~~~ ++Retpoline sequence also mitigates ITS-unsafe indirect branches. For this ++reason, when retpoline is enabled, ITS mitigation only relocates the RETs to ++safe thunks. Unless user requested the RSB-stuffing mitigation. ++ ++Mitigation in guests ++^^^^^^^^^^^^^^^^^^^^ ++All guests deploy ITS mitigation by default, irrespective of eIBRS enumeration ++and Family/Model of the guest. This is because eIBRS feature could be hidden ++from a guest. One exception to this is when a guest enumerates BHI_DIS_S, which ++indicates that the guest is running on an unaffected host. ++ ++To prevent guests from unnecessarily deploying the mitigation on unaffected ++platforms, Intel has defined ITS_NO bit(62) in MSR IA32_ARCH_CAPABILITIES. When ++a guest sees this bit set, it should not enumerate the ITS bug. Note, this bit ++is not set by any hardware, but is **intended for VMMs to synthesize** it for ++guests as per the host's affected status. ++ ++Mitigation options ++^^^^^^^^^^^^^^^^^^ ++The ITS mitigation can be controlled using the "indirect_target_selection" ++kernel parameter. The available options are: ++ ++ ======== =================================================================== ++ on (default) Deploy the "Aligned branch/return thunks" mitigation. ++ If spectre_v2 mitigation enables retpoline, aligned-thunks are only ++ deployed for the affected RET instructions. Retpoline mitigates ++ indirect branches. ++ ++ off Disable ITS mitigation. ++ ++ vmexit Equivalent to "=on" if the CPU is affected by guest/host isolation ++ part of ITS. Otherwise, mitigation is not deployed. This option is ++ useful when host userspace is not in the threat model, and only ++ attacks from guest to host are considered. ++ ++ force Force the ITS bug and deploy the default mitigation. ++ ======== =================================================================== ++ ++Sysfs reporting ++--------------- ++ ++The sysfs file showing ITS mitigation status is: ++ ++ /sys/devices/system/cpu/vulnerabilities/indirect_target_selection ++ ++Note, microcode mitigation status is not reported in this file. ++ ++The possible values in this file are: ++ ++.. list-table:: ++ ++ * - Not affected ++ - The processor is not vulnerable. ++ * - Vulnerable ++ - System is vulnerable and no mitigation has been applied. ++ * - Vulnerable, KVM: Not affected ++ - System is vulnerable to intra-mode BTI, but not affected by eIBRS ++ guest/host isolation. ++ * - Mitigation: Aligned branch/return thunks ++ - The mitigation is enabled, affected indirect branches and RETs are ++ relocated to safe thunks. ++ ++References ++---------- ++.. [#f1] Microcode repository - https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files ++ ++.. [#f2] Affected Processors list - https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html ++ ++.. [#f3] Affected Processors list (machine readable) - https://github.com/intel/Intel-affected-processor-list +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index ede522c60ac4f1..4bc5d8c97d097b 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -1926,6 +1926,20 @@ + different crypto accelerators. This option can be used + to achieve best performance for particular HW. + ++ indirect_target_selection= [X86,Intel] Mitigation control for Indirect ++ Target Selection(ITS) bug in Intel CPUs. Updated ++ microcode is also required for a fix in IBPB. ++ ++ on: Enable mitigation (default). ++ off: Disable mitigation. ++ force: Force the ITS bug and deploy default ++ mitigation. ++ vmexit: Only deploy mitigation if CPU is affected by ++ guest/host isolation part of ITS. ++ ++ For details see: ++ Documentation/admin-guide/hw-vuln/indirect-target-selection.rst ++ + init= [KNL] + Format: + Run specified binary instead of /sbin/init as init +@@ -3073,6 +3087,7 @@ + improves system performance, but it may also + expose users to several CPU vulnerabilities. + Equivalent to: gather_data_sampling=off [X86] ++ indirect_target_selection=off [X86] + kpti=0 [ARM64] + kvm.nx_huge_pages=off [X86] + l1tf=off [X86] +diff --git a/Makefile b/Makefile +index 09de195b86f268..0840259608be33 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 15 +-SUBLEVEL = 183 ++SUBLEVEL = 184 + EXTRAVERSION = + NAME = Trick or Treat + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index de6a66ad3fa624..026a5714f78f39 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -2517,6 +2517,17 @@ config MITIGATION_SPECTRE_BHI + indirect branches. + See + ++config MITIGATION_ITS ++ bool "Enable Indirect Target Selection mitigation" ++ depends on CPU_SUP_INTEL && X86_64 ++ depends on RETPOLINE && RETHUNK ++ default y ++ help ++ Enable Indirect Target Selection (ITS) mitigation. ITS is a bug in ++ BPU on some Intel CPUs that may allow Spectre V2 style attacks. If ++ disabled, mitigation cannot be enabled via cmdline. ++ See ++ + endif + + config ARCH_HAS_ADD_PAGES +diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S +index f656c6e0e45882..ed74778c8ebd7f 100644 +--- a/arch/x86/entry/entry_64.S ++++ b/arch/x86/entry/entry_64.S +@@ -1530,7 +1530,9 @@ SYM_CODE_END(rewind_stack_and_make_dead) + * ORC to unwind properly. + * + * The alignment is for performance and not for safety, and may be safely +- * refactored in the future if needed. ++ * refactored in the future if needed. The .skips are for safety, to ensure ++ * that all RETs are in the second half of a cacheline to mitigate Indirect ++ * Target Selection, rather than taking the slowpath via its_return_thunk. + */ + SYM_FUNC_START(clear_bhb_loop) + push %rbp +@@ -1540,10 +1542,22 @@ SYM_FUNC_START(clear_bhb_loop) + call 1f + jmp 5f + .align 64, 0xcc ++ /* ++ * Shift instructions so that the RET is in the upper half of the ++ * cacheline and don't take the slowpath to its_return_thunk. ++ */ ++ .skip 32 - (.Lret1 - 1f), 0xcc + ANNOTATE_INTRA_FUNCTION_CALL + 1: call 2f +- RET ++.Lret1: RET + .align 64, 0xcc ++ /* ++ * As above shift instructions for RET at .Lret2 as well. ++ * ++ * This should be ideally be: .skip 32 - (.Lret2 - 2f), 0xcc ++ * but some Clang versions (e.g. 18) don't like this. ++ */ ++ .skip 32 - 18, 0xcc + 2: movl $5, %eax + 3: jmp 4f + nop +@@ -1551,7 +1565,7 @@ SYM_FUNC_START(clear_bhb_loop) + jnz 3b + sub $1, %ecx + jnz 1b +- RET ++.Lret2: RET + 5: lfence + pop %rbp + RET +diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h +index a364971967c40e..1797f80c10de4e 100644 +--- a/arch/x86/include/asm/alternative.h ++++ b/arch/x86/include/asm/alternative.h +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + + #define ALTINSTR_FLAG_INV (1 << 15) + #define ALT_NOT(feat) ((feat) | ALTINSTR_FLAG_INV) +@@ -80,6 +81,37 @@ extern void apply_returns(s32 *start, s32 *end); + + struct module; + ++#ifdef CONFIG_MITIGATION_ITS ++extern void its_init_mod(struct module *mod); ++extern void its_fini_mod(struct module *mod); ++extern void its_free_mod(struct module *mod); ++extern u8 *its_static_thunk(int reg); ++#else /* CONFIG_MITIGATION_ITS */ ++static inline void its_init_mod(struct module *mod) { } ++static inline void its_fini_mod(struct module *mod) { } ++static inline void its_free_mod(struct module *mod) { } ++static inline u8 *its_static_thunk(int reg) ++{ ++ WARN_ONCE(1, "ITS not compiled in"); ++ ++ return NULL; ++} ++#endif ++ ++#ifdef CONFIG_RETHUNK ++extern bool cpu_wants_rethunk(void); ++extern bool cpu_wants_rethunk_at(void *addr); ++#else ++static __always_inline bool cpu_wants_rethunk(void) ++{ ++ return false; ++} ++static __always_inline bool cpu_wants_rethunk_at(void *addr) ++{ ++ return false; ++} ++#endif ++ + #ifdef CONFIG_SMP + extern void alternatives_smp_module_add(struct module *mod, char *name, + void *locks, void *locks_end, +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +index 4faa47cc1a5c3c..e2bf1cba02cdde 100644 +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -433,6 +433,7 @@ + #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ + #define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */ + #define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */ ++#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32 + 5) /* "" Use thunk for indirect branches in lower half of cacheline */ + + /* + * BUG word(s) +@@ -483,4 +484,6 @@ + #define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */ + #define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */ + #define X86_BUG_IBPB_NO_RET X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */ ++#define X86_BUG_ITS X86_BUG(1*32 + 5) /* CPU is affected by Indirect Target Selection */ ++#define X86_BUG_ITS_NATIVE_ONLY X86_BUG(1*32 + 6) /* CPU is affected by ITS, VMX is not affected */ + #endif /* _ASM_X86_CPUFEATURES_H */ +diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h +index 03b12c19458892..241b688cc9b858 100644 +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -183,6 +183,14 @@ + * VERW clears CPU Register + * File. + */ ++#define ARCH_CAP_ITS_NO BIT_ULL(62) /* ++ * Not susceptible to ++ * Indirect Target Selection. ++ * This bit is not set by ++ * HW, but is synthesized by ++ * VMMs for guests to know ++ * their affected status. ++ */ + + #define MSR_IA32_FLUSH_CMD 0x0000010b + #define L1D_FLUSH BIT(0) /* +diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h +index bdf22582a8c013..17156b61fcc32d 100644 +--- a/arch/x86/include/asm/nospec-branch.h ++++ b/arch/x86/include/asm/nospec-branch.h +@@ -118,6 +118,18 @@ + #endif + .endm + ++/* ++ * Emits a conditional CS prefix that is compatible with ++ * -mindirect-branch-cs-prefix. ++ */ ++.macro __CS_PREFIX reg:req ++ .irp rs,r8,r9,r10,r11,r12,r13,r14,r15 ++ .ifc \reg,\rs ++ .byte 0x2e ++ .endif ++ .endr ++.endm ++ + /* + * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple + * indirect jmp/call which may be susceptible to the Spectre variant 2 +@@ -125,19 +137,18 @@ + */ + .macro JMP_NOSPEC reg:req + #ifdef CONFIG_RETPOLINE +- ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), \ +- __stringify(jmp __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ +- __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *%\reg), X86_FEATURE_RETPOLINE_LFENCE ++ __CS_PREFIX \reg ++ jmp __x86_indirect_thunk_\reg + #else + jmp *%\reg ++ int3 + #endif + .endm + + .macro CALL_NOSPEC reg:req + #ifdef CONFIG_RETPOLINE +- ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *%\reg), \ +- __stringify(call __x86_indirect_thunk_\reg), X86_FEATURE_RETPOLINE, \ +- __stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *%\reg), X86_FEATURE_RETPOLINE_LFENCE ++ __CS_PREFIX \reg ++ call __x86_indirect_thunk_\reg + #else + call *%\reg + #endif +@@ -239,6 +250,12 @@ extern void __x86_return_thunk(void); + static inline void __x86_return_thunk(void) {} + #endif + ++#ifdef CONFIG_MITIGATION_ITS ++extern void its_return_thunk(void); ++#else ++static inline void its_return_thunk(void) {} ++#endif ++ + extern void retbleed_return_thunk(void); + extern void srso_return_thunk(void); + extern void srso_alias_return_thunk(void); +@@ -260,6 +277,11 @@ extern void (*x86_return_thunk)(void); + + typedef u8 retpoline_thunk_t[RETPOLINE_THUNK_SIZE]; + ++#define ITS_THUNK_SIZE 64 ++typedef u8 its_thunk_t[ITS_THUNK_SIZE]; ++ ++extern its_thunk_t __x86_indirect_its_thunk_array[]; ++ + #define GEN(reg) \ + extern retpoline_thunk_t __x86_indirect_thunk_ ## reg; + #include +@@ -269,20 +291,23 @@ extern retpoline_thunk_t __x86_indirect_thunk_array[]; + + #ifdef CONFIG_X86_64 + ++/* ++ * Emits a conditional CS prefix that is compatible with ++ * -mindirect-branch-cs-prefix. ++ */ ++#define __CS_PREFIX(reg) \ ++ ".irp rs,r8,r9,r10,r11,r12,r13,r14,r15\n" \ ++ ".ifc \\rs," reg "\n" \ ++ ".byte 0x2e\n" \ ++ ".endif\n" \ ++ ".endr\n" ++ + /* + * Inline asm uses the %V modifier which is only in newer GCC + * which is ensured when CONFIG_RETPOLINE is defined. + */ +-# define CALL_NOSPEC \ +- ALTERNATIVE_2( \ +- ANNOTATE_RETPOLINE_SAFE \ +- "call *%[thunk_target]\n", \ +- "call __x86_indirect_thunk_%V[thunk_target]\n", \ +- X86_FEATURE_RETPOLINE, \ +- "lfence;\n" \ +- ANNOTATE_RETPOLINE_SAFE \ +- "call *%[thunk_target]\n", \ +- X86_FEATURE_RETPOLINE_LFENCE) ++#define CALL_NOSPEC __CS_PREFIX("%V[thunk_target]") \ ++ "call __x86_indirect_thunk_%V[thunk_target]\n" + + # define THUNK_TARGET(addr) [thunk_target] "r" (addr) + +diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c +index 5614e6d219b756..43ec73da66d8b8 100644 +--- a/arch/x86/kernel/alternative.c ++++ b/arch/x86/kernel/alternative.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -30,6 +31,7 @@ + #include + #include + #include ++#include + + int __read_mostly alternatives_patched; + +@@ -395,6 +397,216 @@ static int emit_indirect(int op, int reg, u8 *bytes) + return i; + } + ++#ifdef CONFIG_MITIGATION_ITS ++ ++#ifdef CONFIG_MODULES ++static struct module *its_mod; ++static void *its_page; ++static unsigned int its_offset; ++ ++/* Initialize a thunk with the "jmp *reg; int3" instructions. */ ++static void *its_init_thunk(void *thunk, int reg) ++{ ++ u8 *bytes = thunk; ++ int i = 0; ++ ++ if (reg >= 8) { ++ bytes[i++] = 0x41; /* REX.B prefix */ ++ reg -= 8; ++ } ++ bytes[i++] = 0xff; ++ bytes[i++] = 0xe0 + reg; /* jmp *reg */ ++ bytes[i++] = 0xcc; ++ ++ return thunk; ++} ++ ++void its_init_mod(struct module *mod) ++{ ++ if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) ++ return; ++ ++ mutex_lock(&text_mutex); ++ its_mod = mod; ++ its_page = NULL; ++} ++ ++void its_fini_mod(struct module *mod) ++{ ++ int i; ++ ++ if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) ++ return; ++ ++ WARN_ON_ONCE(its_mod != mod); ++ ++ its_mod = NULL; ++ its_page = NULL; ++ mutex_unlock(&text_mutex); ++ ++ for (i = 0; i < mod->its_num_pages; i++) { ++ void *page = mod->its_page_array[i]; ++ set_memory_ro((unsigned long)page, 1); ++ set_memory_x((unsigned long)page, 1); ++ } ++} ++ ++void its_free_mod(struct module *mod) ++{ ++ int i; ++ ++ if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) ++ return; ++ ++ for (i = 0; i < mod->its_num_pages; i++) { ++ void *page = mod->its_page_array[i]; ++ module_memfree(page); ++ } ++ kfree(mod->its_page_array); ++} ++ ++static void *its_alloc(void) ++{ ++ void *page = module_alloc(PAGE_SIZE); ++ ++ if (!page) ++ return NULL; ++ ++ if (its_mod) { ++ void *tmp = krealloc(its_mod->its_page_array, ++ (its_mod->its_num_pages+1) * sizeof(void *), ++ GFP_KERNEL); ++ if (!tmp) { ++ module_memfree(page); ++ return NULL; ++ } ++ ++ its_mod->its_page_array = tmp; ++ its_mod->its_page_array[its_mod->its_num_pages++] = page; ++ } ++ ++ return page; ++} ++ ++static void *its_allocate_thunk(int reg) ++{ ++ int size = 3 + (reg / 8); ++ void *thunk; ++ ++ if (!its_page || (its_offset + size - 1) >= PAGE_SIZE) { ++ its_page = its_alloc(); ++ if (!its_page) { ++ pr_err("ITS page allocation failed\n"); ++ return NULL; ++ } ++ memset(its_page, INT3_INSN_OPCODE, PAGE_SIZE); ++ its_offset = 32; ++ } ++ ++ /* ++ * If the indirect branch instruction will be in the lower half ++ * of a cacheline, then update the offset to reach the upper half. ++ */ ++ if ((its_offset + size - 1) % 64 < 32) ++ its_offset = ((its_offset - 1) | 0x3F) + 33; ++ ++ thunk = its_page + its_offset; ++ its_offset += size; ++ ++ set_memory_rw((unsigned long)its_page, 1); ++ thunk = its_init_thunk(thunk, reg); ++ set_memory_ro((unsigned long)its_page, 1); ++ set_memory_x((unsigned long)its_page, 1); ++ ++ return thunk; ++} ++#else /* CONFIG_MODULES */ ++ ++static void *its_allocate_thunk(int reg) ++{ ++ return NULL; ++} ++ ++#endif /* CONFIG_MODULES */ ++ ++static int __emit_trampoline(void *addr, struct insn *insn, u8 *bytes, ++ void *call_dest, void *jmp_dest) ++{ ++ u8 op = insn->opcode.bytes[0]; ++ int i = 0; ++ ++ /* ++ * Clang does 'weird' Jcc __x86_indirect_thunk_r11 conditional ++ * tail-calls. Deal with them. ++ */ ++ if (is_jcc32(insn)) { ++ bytes[i++] = op; ++ op = insn->opcode.bytes[1]; ++ goto clang_jcc; ++ } ++ ++ if (insn->length == 6) ++ bytes[i++] = 0x2e; /* CS-prefix */ ++ ++ switch (op) { ++ case CALL_INSN_OPCODE: ++ __text_gen_insn(bytes+i, op, addr+i, ++ call_dest, ++ CALL_INSN_SIZE); ++ i += CALL_INSN_SIZE; ++ break; ++ ++ case JMP32_INSN_OPCODE: ++clang_jcc: ++ __text_gen_insn(bytes+i, op, addr+i, ++ jmp_dest, ++ JMP32_INSN_SIZE); ++ i += JMP32_INSN_SIZE; ++ break; ++ ++ default: ++ WARN(1, "%pS %px %*ph\n", addr, addr, 6, addr); ++ return -1; ++ } ++ ++ WARN_ON_ONCE(i != insn->length); ++ ++ return i; ++} ++ ++static int emit_its_trampoline(void *addr, struct insn *insn, int reg, u8 *bytes) ++{ ++ u8 *thunk = __x86_indirect_its_thunk_array[reg]; ++ u8 *tmp = its_allocate_thunk(reg); ++ ++ if (tmp) ++ thunk = tmp; ++ ++ return __emit_trampoline(addr, insn, bytes, thunk, thunk); ++} ++ ++/* Check if an indirect branch is at ITS-unsafe address */ ++static bool cpu_wants_indirect_its_thunk_at(unsigned long addr, int reg) ++{ ++ if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) ++ return false; ++ ++ /* Indirect branch opcode is 2 or 3 bytes depending on reg */ ++ addr += 1 + reg / 8; ++ ++ /* Lower-half of the cacheline? */ ++ return !(addr & 0x20); ++} ++ ++u8 *its_static_thunk(int reg) ++{ ++ u8 *thunk = __x86_indirect_its_thunk_array[reg]; ++ ++ return thunk; ++} ++ ++#endif ++ + /* + * Rewrite the compiler generated retpoline thunk calls. + * +@@ -466,6 +678,15 @@ static int patch_retpoline(void *addr, struct insn *insn, u8 *bytes) + bytes[i++] = 0xe8; /* LFENCE */ + } + ++#ifdef CONFIG_MITIGATION_ITS ++ /* ++ * Check if the address of last byte of emitted-indirect is in ++ * lower-half of the cacheline. Such branches need ITS mitigation. ++ */ ++ if (cpu_wants_indirect_its_thunk_at((unsigned long)addr + i, reg)) ++ return emit_its_trampoline(addr, insn, reg, bytes); ++#endif ++ + ret = emit_indirect(op, reg, bytes + i); + if (ret < 0) + return ret; +@@ -528,6 +749,21 @@ void __init_or_module noinline apply_retpolines(s32 *start, s32 *end) + + #ifdef CONFIG_RETHUNK + ++bool cpu_wants_rethunk(void) ++{ ++ return cpu_feature_enabled(X86_FEATURE_RETHUNK); ++} ++ ++bool cpu_wants_rethunk_at(void *addr) ++{ ++ if (!cpu_feature_enabled(X86_FEATURE_RETHUNK)) ++ return false; ++ if (x86_return_thunk != its_return_thunk) ++ return true; ++ ++ return !((unsigned long)addr & 0x20); ++} ++ + /* + * Rewrite the compiler generated return thunk tail-calls. + * +@@ -543,13 +779,12 @@ static int patch_return(void *addr, struct insn *insn, u8 *bytes) + { + int i = 0; + +- if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) { +- if (x86_return_thunk == __x86_return_thunk) +- return -1; +- ++ /* Patch the custom return thunks... */ ++ if (cpu_wants_rethunk_at(addr)) { + i = JMP32_INSN_SIZE; + __text_gen_insn(bytes, JMP32_INSN_OPCODE, addr, x86_return_thunk, i); + } else { ++ /* ... or patch them out if not needed. */ + bytes[i++] = RET_INSN_OPCODE; + } + +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index c10d93d2773b4b..63af3d73d19e5d 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -48,6 +48,7 @@ static void __init srbds_select_mitigation(void); + static void __init l1d_flush_select_mitigation(void); + static void __init gds_select_mitigation(void); + static void __init srso_select_mitigation(void); ++static void __init its_select_mitigation(void); + + /* The base value of the SPEC_CTRL MSR without task-specific bits set */ + u64 x86_spec_ctrl_base; +@@ -66,6 +67,14 @@ static DEFINE_MUTEX(spec_ctrl_mutex); + + void (*x86_return_thunk)(void) __ro_after_init = &__x86_return_thunk; + ++static void __init set_return_thunk(void *thunk) ++{ ++ if (x86_return_thunk != __x86_return_thunk) ++ pr_warn("x86/bugs: return thunk changed\n"); ++ ++ x86_return_thunk = thunk; ++} ++ + /* Update SPEC_CTRL MSR and its cached copy unconditionally */ + static void update_spec_ctrl(u64 val) + { +@@ -174,6 +183,7 @@ void __init cpu_select_mitigations(void) + */ + srso_select_mitigation(); + gds_select_mitigation(); ++ its_select_mitigation(); + } + + /* +@@ -1081,7 +1091,7 @@ static void __init retbleed_select_mitigation(void) + setup_force_cpu_cap(X86_FEATURE_UNRET); + + if (IS_ENABLED(CONFIG_RETHUNK)) +- x86_return_thunk = retbleed_return_thunk; ++ set_return_thunk(retbleed_return_thunk); + + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && + boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) +@@ -1142,6 +1152,116 @@ static void __init retbleed_select_mitigation(void) + pr_info("%s\n", retbleed_strings[retbleed_mitigation]); + } + ++#undef pr_fmt ++#define pr_fmt(fmt) "ITS: " fmt ++ ++enum its_mitigation_cmd { ++ ITS_CMD_OFF, ++ ITS_CMD_ON, ++ ITS_CMD_VMEXIT, ++}; ++ ++enum its_mitigation { ++ ITS_MITIGATION_OFF, ++ ITS_MITIGATION_VMEXIT_ONLY, ++ ITS_MITIGATION_ALIGNED_THUNKS, ++}; ++ ++static const char * const its_strings[] = { ++ [ITS_MITIGATION_OFF] = "Vulnerable", ++ [ITS_MITIGATION_VMEXIT_ONLY] = "Mitigation: Vulnerable, KVM: Not affected", ++ [ITS_MITIGATION_ALIGNED_THUNKS] = "Mitigation: Aligned branch/return thunks", ++}; ++ ++static enum its_mitigation its_mitigation __ro_after_init = ITS_MITIGATION_ALIGNED_THUNKS; ++ ++static enum its_mitigation_cmd its_cmd __ro_after_init = ++ IS_ENABLED(CONFIG_MITIGATION_ITS) ? ITS_CMD_ON : ITS_CMD_OFF; ++ ++static int __init its_parse_cmdline(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ if (!IS_ENABLED(CONFIG_MITIGATION_ITS)) { ++ pr_err("Mitigation disabled at compile time, ignoring option (%s)", str); ++ return 0; ++ } ++ ++ if (!strcmp(str, "off")) { ++ its_cmd = ITS_CMD_OFF; ++ } else if (!strcmp(str, "on")) { ++ its_cmd = ITS_CMD_ON; ++ } else if (!strcmp(str, "force")) { ++ its_cmd = ITS_CMD_ON; ++ setup_force_cpu_bug(X86_BUG_ITS); ++ } else if (!strcmp(str, "vmexit")) { ++ its_cmd = ITS_CMD_VMEXIT; ++ } else { ++ pr_err("Ignoring unknown indirect_target_selection option (%s).", str); ++ } ++ ++ return 0; ++} ++early_param("indirect_target_selection", its_parse_cmdline); ++ ++static void __init its_select_mitigation(void) ++{ ++ enum its_mitigation_cmd cmd = its_cmd; ++ ++ if (!boot_cpu_has_bug(X86_BUG_ITS) || cpu_mitigations_off()) { ++ its_mitigation = ITS_MITIGATION_OFF; ++ return; ++ } ++ ++ /* Exit early to avoid irrelevant warnings */ ++ if (cmd == ITS_CMD_OFF) { ++ its_mitigation = ITS_MITIGATION_OFF; ++ goto out; ++ } ++ if (spectre_v2_enabled == SPECTRE_V2_NONE) { ++ pr_err("WARNING: Spectre-v2 mitigation is off, disabling ITS\n"); ++ its_mitigation = ITS_MITIGATION_OFF; ++ goto out; ++ } ++ if (!IS_ENABLED(CONFIG_RETPOLINE) || !IS_ENABLED(CONFIG_RETHUNK)) { ++ pr_err("WARNING: ITS mitigation depends on retpoline and rethunk support\n"); ++ its_mitigation = ITS_MITIGATION_OFF; ++ goto out; ++ } ++ if (IS_ENABLED(CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B)) { ++ pr_err("WARNING: ITS mitigation is not compatible with CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B\n"); ++ its_mitigation = ITS_MITIGATION_OFF; ++ goto out; ++ } ++ if (boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) { ++ pr_err("WARNING: ITS mitigation is not compatible with lfence mitigation\n"); ++ its_mitigation = ITS_MITIGATION_OFF; ++ goto out; ++ } ++ ++ switch (cmd) { ++ case ITS_CMD_OFF: ++ its_mitigation = ITS_MITIGATION_OFF; ++ break; ++ case ITS_CMD_VMEXIT: ++ if (boot_cpu_has_bug(X86_BUG_ITS_NATIVE_ONLY)) { ++ its_mitigation = ITS_MITIGATION_VMEXIT_ONLY; ++ goto out; ++ } ++ fallthrough; ++ case ITS_CMD_ON: ++ its_mitigation = ITS_MITIGATION_ALIGNED_THUNKS; ++ if (!boot_cpu_has(X86_FEATURE_RETPOLINE)) ++ setup_force_cpu_cap(X86_FEATURE_INDIRECT_THUNK_ITS); ++ setup_force_cpu_cap(X86_FEATURE_RETHUNK); ++ set_return_thunk(its_return_thunk); ++ break; ++ } ++out: ++ pr_info("%s\n", its_strings[its_mitigation]); ++} ++ + #undef pr_fmt + #define pr_fmt(fmt) "Spectre V2 : " fmt + +@@ -2592,10 +2712,10 @@ static void __init srso_select_mitigation(void) + + if (boot_cpu_data.x86 == 0x19) { + setup_force_cpu_cap(X86_FEATURE_SRSO_ALIAS); +- x86_return_thunk = srso_alias_return_thunk; ++ set_return_thunk(srso_alias_return_thunk); + } else { + setup_force_cpu_cap(X86_FEATURE_SRSO); +- x86_return_thunk = srso_return_thunk; ++ set_return_thunk(srso_return_thunk); + } + srso_mitigation = SRSO_MITIGATION_SAFE_RET; + } else { +@@ -2775,6 +2895,11 @@ static ssize_t rfds_show_state(char *buf) + return sysfs_emit(buf, "%s\n", rfds_strings[rfds_mitigation]); + } + ++static ssize_t its_show_state(char *buf) ++{ ++ return sysfs_emit(buf, "%s\n", its_strings[its_mitigation]); ++} ++ + static char *stibp_state(void) + { + if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) && +@@ -2959,6 +3084,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr + case X86_BUG_RFDS: + return rfds_show_state(buf); + ++ case X86_BUG_ITS: ++ return its_show_state(buf); ++ + default: + break; + } +@@ -3038,4 +3166,9 @@ ssize_t cpu_show_reg_file_data_sampling(struct device *dev, struct device_attrib + { + return cpu_show_common(dev, attr, buf, X86_BUG_RFDS); + } ++ ++ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ return cpu_show_common(dev, attr, buf, X86_BUG_ITS); ++} + #endif +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 1ebd67c95d869a..dc15568e14d935 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1141,6 +1141,10 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { + #define GDS BIT(6) + /* CPU is affected by Register File Data Sampling */ + #define RFDS BIT(7) ++/* CPU is affected by Indirect Target Selection */ ++#define ITS BIT(8) ++/* CPU is affected by Indirect Target Selection, but guest-host isolation is not affected */ ++#define ITS_NATIVE_ONLY BIT(9) + + static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { + VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS), +@@ -1152,22 +1156,25 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { + VULNBL_INTEL_STEPPINGS(BROADWELL_G, X86_STEPPING_ANY, SRBDS), + VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO), + VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS), +- VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED | GDS), ++ VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPINGS(0x0, 0x5), MMIO | RETBLEED | GDS), ++ VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | ITS), + VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS), + VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS), +- VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS), +- VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS), ++ VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPINGS(0x0, 0xb), MMIO | RETBLEED | GDS | SRBDS), ++ VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS | ITS), ++ VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPINGS(0x0, 0xc), MMIO | RETBLEED | GDS | SRBDS), ++ VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | SRBDS | ITS), + VULNBL_INTEL_STEPPINGS(CANNONLAKE_L, X86_STEPPING_ANY, RETBLEED), +- VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), +- VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO | GDS), +- VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO | GDS), +- VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), +- VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED), +- VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), +- VULNBL_INTEL_STEPPINGS(TIGERLAKE_L, X86_STEPPING_ANY, GDS), +- VULNBL_INTEL_STEPPINGS(TIGERLAKE, X86_STEPPING_ANY, GDS), ++ VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS | ITS_NATIVE_ONLY), ++ VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO | GDS | ITS | ITS_NATIVE_ONLY), ++ VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO | GDS | ITS | ITS_NATIVE_ONLY), ++ VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS), ++ VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED | ITS), ++ VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS), ++ VULNBL_INTEL_STEPPINGS(TIGERLAKE_L, X86_STEPPING_ANY, GDS | ITS | ITS_NATIVE_ONLY), ++ VULNBL_INTEL_STEPPINGS(TIGERLAKE, X86_STEPPING_ANY, GDS | ITS | ITS_NATIVE_ONLY), + VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), +- VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS), ++ VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS | ITS | ITS_NATIVE_ONLY), + VULNBL_INTEL_STEPPINGS(ALDERLAKE, X86_STEPPING_ANY, RFDS), + VULNBL_INTEL_STEPPINGS(ALDERLAKE_L, X86_STEPPING_ANY, RFDS), + VULNBL_INTEL_STEPPINGS(RAPTORLAKE, X86_STEPPING_ANY, RFDS), +@@ -1231,6 +1238,32 @@ static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr) + return cpu_matches(cpu_vuln_blacklist, RFDS); + } + ++static bool __init vulnerable_to_its(u64 x86_arch_cap_msr) ++{ ++ /* The "immunity" bit trumps everything else: */ ++ if (x86_arch_cap_msr & ARCH_CAP_ITS_NO) ++ return false; ++ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) ++ return false; ++ ++ /* None of the affected CPUs have BHI_CTRL */ ++ if (boot_cpu_has(X86_FEATURE_BHI_CTRL)) ++ return false; ++ ++ /* ++ * If a VMM did not expose ITS_NO, assume that a guest could ++ * be running on a vulnerable hardware or may migrate to such ++ * hardware. ++ */ ++ if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) ++ return true; ++ ++ if (cpu_matches(cpu_vuln_blacklist, ITS)) ++ return true; ++ ++ return false; ++} ++ + static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + { + u64 x86_arch_cap_msr = x86_read_arch_cap_msr(); +@@ -1358,6 +1391,12 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + if (cpu_has(c, X86_FEATURE_AMD_IBPB) && !cpu_has(c, X86_FEATURE_AMD_IBPB_RET)) + setup_force_cpu_bug(X86_BUG_IBPB_NO_RET); + ++ if (vulnerable_to_its(x86_arch_cap_msr)) { ++ setup_force_cpu_bug(X86_BUG_ITS); ++ if (cpu_matches(cpu_vuln_blacklist, ITS_NATIVE_ONLY)) ++ setup_force_cpu_bug(X86_BUG_ITS_NATIVE_ONLY); ++ } ++ + if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) + return; + +diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c +index 85c09843df1b9e..fee8c63e15d474 100644 +--- a/arch/x86/kernel/ftrace.c ++++ b/arch/x86/kernel/ftrace.c +@@ -367,7 +367,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) + goto fail; + + ip = trampoline + size; +- if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) ++ if (cpu_wants_rethunk_at(ip)) + __text_gen_insn(ip, JMP32_INSN_OPCODE, ip, x86_return_thunk, JMP32_INSN_SIZE); + else + memcpy(ip, retq, sizeof(retq)); +@@ -422,8 +422,6 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) + /* ALLOC_TRAMP flags lets us know we created it */ + ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP; + +- set_vm_flush_reset_perms(trampoline); +- + if (likely(system_state != SYSTEM_BOOTING)) + set_memory_ro((unsigned long)trampoline, npages); + set_memory_x((unsigned long)trampoline, npages); +diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c +index 99dd504307fdc4..2a0563780ebb2b 100644 +--- a/arch/x86/kernel/kprobes/core.c ++++ b/arch/x86/kernel/kprobes/core.c +@@ -403,7 +403,6 @@ void *alloc_insn_page(void) + if (!page) + return NULL; + +- set_vm_flush_reset_perms(page); + /* + * First make the page read-only, and only then make it executable to + * prevent it from being W+X in between. +diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c +index 06b53ea940bf60..f0f2bbf73f205e 100644 +--- a/arch/x86/kernel/module.c ++++ b/arch/x86/kernel/module.c +@@ -74,10 +74,10 @@ void *module_alloc(unsigned long size) + return NULL; + + p = __vmalloc_node_range(size, MODULE_ALIGN, +- MODULES_VADDR + get_module_load_offset(), +- MODULES_END, gfp_mask, +- PAGE_KERNEL, VM_DEFER_KMEMLEAK, NUMA_NO_NODE, +- __builtin_return_address(0)); ++ MODULES_VADDR + get_module_load_offset(), ++ MODULES_END, gfp_mask, PAGE_KERNEL, ++ VM_FLUSH_RESET_PERMS | VM_DEFER_KMEMLEAK, ++ NUMA_NO_NODE, __builtin_return_address(0)); + if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { + vfree(p); + return NULL; +@@ -283,10 +283,16 @@ int module_finalize(const Elf_Ehdr *hdr, + void *pseg = (void *)para->sh_addr; + apply_paravirt(pseg, pseg + para->sh_size); + } ++ ++ its_init_mod(me); ++ + if (retpolines) { + void *rseg = (void *)retpolines->sh_addr; + apply_retpolines(rseg, rseg + retpolines->sh_size); + } ++ ++ its_fini_mod(me); ++ + if (returns) { + void *rseg = (void *)returns->sh_addr; + apply_returns(rseg, rseg + returns->sh_size); +@@ -317,4 +323,5 @@ int module_finalize(const Elf_Ehdr *hdr, + void module_arch_cleanup(struct module *mod) + { + alternatives_smp_module_del(mod); ++ its_free_mod(mod); + } +diff --git a/arch/x86/kernel/static_call.c b/arch/x86/kernel/static_call.c +index a5dd11c92d055c..74eb1d6c7bb0d0 100644 +--- a/arch/x86/kernel/static_call.c ++++ b/arch/x86/kernel/static_call.c +@@ -81,7 +81,7 @@ static void __ref __static_call_transform(void *insn, enum insn_type type, + break; + + case RET: +- if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) ++ if (cpu_wants_rethunk_at(insn)) + code = text_gen_insn(JMP32_INSN_OPCODE, insn, x86_return_thunk); + else + code = &retinsn; +diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S +index 351c604de263ac..c570da8be03077 100644 +--- a/arch/x86/kernel/vmlinux.lds.S ++++ b/arch/x86/kernel/vmlinux.lds.S +@@ -532,6 +532,16 @@ INIT_PER_CPU(irq_stack_backing_store); + "SRSO function pair won't alias"); + #endif + ++#if defined(CONFIG_MITIGATION_ITS) && !defined(CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B) ++. = ASSERT(__x86_indirect_its_thunk_rax & 0x20, "__x86_indirect_thunk_rax not in second half of cacheline"); ++. = ASSERT(((__x86_indirect_its_thunk_rcx - __x86_indirect_its_thunk_rax) % 64) == 0, "Indirect thunks are not cacheline apart"); ++. = ASSERT(__x86_indirect_its_thunk_array == __x86_indirect_its_thunk_rax, "Gap in ITS thunk array"); ++#endif ++ ++#if defined(CONFIG_MITIGATION_ITS) && !defined(CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B) ++. = ASSERT(its_return_thunk & 0x20, "its_return_thunk not in second half of cacheline"); ++#endif ++ + #endif /* CONFIG_X86_64 */ + + #ifdef CONFIG_KEXEC_CORE +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index bf03f3ff896e36..b5bf68c2d2fc8f 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -1499,7 +1499,7 @@ static unsigned int num_msr_based_features; + ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \ + ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \ + ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO | \ +- ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO) ++ ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO | ARCH_CAP_ITS_NO) + + static u64 kvm_get_arch_capabilities(void) + { +@@ -1538,6 +1538,8 @@ static u64 kvm_get_arch_capabilities(void) + data |= ARCH_CAP_MDS_NO; + if (!boot_cpu_has_bug(X86_BUG_RFDS)) + data |= ARCH_CAP_RFDS_NO; ++ if (!boot_cpu_has_bug(X86_BUG_ITS)) ++ data |= ARCH_CAP_ITS_NO; + + if (!boot_cpu_has(X86_FEATURE_RTM)) { + /* +diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S +index 019096b66eff35..ae0151c6caba57 100644 +--- a/arch/x86/lib/retpoline.S ++++ b/arch/x86/lib/retpoline.S +@@ -254,6 +254,45 @@ SYM_FUNC_START(entry_untrain_ret) + SYM_FUNC_END(entry_untrain_ret) + __EXPORT_THUNK(entry_untrain_ret) + ++#ifdef CONFIG_MITIGATION_ITS ++ ++.macro ITS_THUNK reg ++ ++SYM_INNER_LABEL(__x86_indirect_its_thunk_\reg, SYM_L_GLOBAL) ++ UNWIND_HINT_EMPTY ++ ANNOTATE_NOENDBR ++ ANNOTATE_RETPOLINE_SAFE ++ jmp *%\reg ++ int3 ++ .align 32, 0xcc /* fill to the end of the line */ ++ .skip 32, 0xcc /* skip to the next upper half */ ++.endm ++ ++/* ITS mitigation requires thunks be aligned to upper half of cacheline */ ++.align 64, 0xcc ++.skip 32, 0xcc ++SYM_CODE_START(__x86_indirect_its_thunk_array) ++ ++#define GEN(reg) ITS_THUNK reg ++#include ++#undef GEN ++ ++ .align 64, 0xcc ++SYM_CODE_END(__x86_indirect_its_thunk_array) ++ ++.align 64, 0xcc ++.skip 32, 0xcc ++SYM_CODE_START(its_return_thunk) ++ UNWIND_HINT_FUNC ++ ANNOTATE_NOENDBR ++ ANNOTATE_UNRET_SAFE ++ ret ++ int3 ++SYM_CODE_END(its_return_thunk) ++EXPORT_SYMBOL(its_return_thunk) ++ ++#endif /* CONFIG_MITIGATION_ITS */ ++ + SYM_CODE_START(__x86_return_thunk) + UNWIND_HINT_FUNC + ANNOTATE_NOENDBR +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index f62ebeee8b14ef..37a005df0b9520 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -446,7 +446,11 @@ static void emit_indirect_jump(u8 **pprog, int reg, u8 *ip) + u8 *prog = *pprog; + + #ifdef CONFIG_RETPOLINE +- if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) { ++ if (IS_ENABLED(CONFIG_MITIGATION_ITS) && ++ cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) { ++ OPTIMIZER_HIDE_VAR(reg); ++ emit_jump(&prog, its_static_thunk(reg), ip); ++ } else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE_LFENCE)) { + EMIT_LFENCE(); + EMIT2(0xFF, 0xE0 + reg); + } else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) { +@@ -462,7 +466,7 @@ static void emit_return(u8 **pprog, u8 *ip) + { + u8 *prog = *pprog; + +- if (cpu_feature_enabled(X86_FEATURE_RETHUNK)) { ++ if (cpu_wants_rethunk()) { + emit_jump(&prog, x86_return_thunk, ip); + } else { + EMIT1(0xC3); /* ret */ +diff --git a/block/fops.c b/block/fops.c +index 4c8948979921a6..72da501542f148 100644 +--- a/block/fops.c ++++ b/block/fops.c +@@ -259,7 +259,6 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, + blk_finish_plug(&plug); + return -EAGAIN; + } +- bio->bi_opf |= REQ_NOWAIT; + } + + if (is_read) { +@@ -270,6 +269,10 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, + bio->bi_opf = dio_bio_write_op(iocb); + task_io_account_write(bio->bi_iter.bi_size); + } ++ ++ if (iocb->ki_flags & IOCB_NOWAIT) ++ bio->bi_opf |= REQ_NOWAIT; ++ + dio->size += bio->bi_iter.bi_size; + pos += bio->bi_iter.bi_size; + +diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c +index 9fa339639d0c06..0b56fd962b28e7 100644 +--- a/drivers/acpi/pptt.c ++++ b/drivers/acpi/pptt.c +@@ -219,16 +219,18 @@ static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr, + sizeof(struct acpi_table_pptt)); + proc_sz = sizeof(struct acpi_pptt_processor); + +- while ((unsigned long)entry + proc_sz < table_end) { ++ /* ignore subtable types that are smaller than a processor node */ ++ while ((unsigned long)entry + proc_sz <= table_end) { + cpu_node = (struct acpi_pptt_processor *)entry; ++ + if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && + cpu_node->parent == node_entry) + return 0; + if (entry->length == 0) + return 0; ++ + entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, + entry->length); +- + } + return 1; + } +@@ -261,15 +263,18 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he + proc_sz = sizeof(struct acpi_pptt_processor); + + /* find the processor structure associated with this cpuid */ +- while ((unsigned long)entry + proc_sz < table_end) { ++ while ((unsigned long)entry + proc_sz <= table_end) { + cpu_node = (struct acpi_pptt_processor *)entry; + + if (entry->length == 0) { + pr_warn("Invalid zero length subtable\n"); + break; + } ++ /* entry->length may not equal proc_sz, revalidate the processor structure length */ + if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && + acpi_cpu_id == cpu_node->acpi_processor_id && ++ (unsigned long)entry + entry->length <= table_end && ++ entry->length == proc_sz + cpu_node->number_of_priv_resources * sizeof(u32) && + acpi_pptt_leaf_node(table_hdr, cpu_node)) { + return (struct acpi_pptt_processor *)entry; + } +diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c +index 93222cf3915769..df196e0730972c 100644 +--- a/drivers/base/cpu.c ++++ b/drivers/base/cpu.c +@@ -595,6 +595,12 @@ ssize_t __weak cpu_show_reg_file_data_sampling(struct device *dev, + return sysfs_emit(buf, "Not affected\n"); + } + ++ssize_t __weak cpu_show_indirect_target_selection(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sysfs_emit(buf, "Not affected\n"); ++} ++ + static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); + static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); + static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL); +@@ -609,6 +615,7 @@ static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL); + static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL); + static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL); + static DEVICE_ATTR(reg_file_data_sampling, 0444, cpu_show_reg_file_data_sampling, NULL); ++static DEVICE_ATTR(indirect_target_selection, 0444, cpu_show_indirect_target_selection, NULL); + + static struct attribute *cpu_root_vulnerabilities_attrs[] = { + &dev_attr_meltdown.attr, +@@ -625,6 +632,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = { + &dev_attr_gather_data_sampling.attr, + &dev_attr_spec_rstack_overflow.attr, + &dev_attr_reg_file_data_sampling.attr, ++ &dev_attr_indirect_target_selection.attr, + NULL + }; + +diff --git a/drivers/clocksource/i8253.c b/drivers/clocksource/i8253.c +index 39f7c2d736d169..9a91ce66e16eb9 100644 +--- a/drivers/clocksource/i8253.c ++++ b/drivers/clocksource/i8253.c +@@ -103,7 +103,9 @@ int __init clocksource_i8253_init(void) + #ifdef CONFIG_CLKEVT_I8253 + void clockevent_i8253_disable(void) + { +- raw_spin_lock(&i8253_lock); ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&i8253_lock, flags); + + /* + * Writing the MODE register should stop the counter, according to +@@ -133,7 +135,7 @@ void clockevent_i8253_disable(void) + + outb_p(0x30, PIT_MODE); + +- raw_spin_unlock(&i8253_lock); ++ raw_spin_unlock_irqrestore(&i8253_lock, flags); + } + + static int pit_shutdown(struct clock_event_device *evt) +diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c +index 0d8d01673010c2..f696246f57fdb3 100644 +--- a/drivers/dma/dmatest.c ++++ b/drivers/dma/dmatest.c +@@ -828,9 +828,9 @@ static int dmatest_func(void *data) + } else { + dma_async_issue_pending(chan); + +- wait_event_timeout(thread->done_wait, +- done->done, +- msecs_to_jiffies(params->timeout)); ++ wait_event_freezable_timeout(thread->done_wait, ++ done->done, ++ msecs_to_jiffies(params->timeout)); + + status = dma_async_is_tx_complete(chan, cookie, NULL, + NULL); +diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c +index e0e0c7f286b67e..f2d27c6ec1ce88 100644 +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -289,6 +289,7 @@ static int idxd_setup_engines(struct idxd_device *idxd) + rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id); + if (rc < 0) { + put_device(conf_dev); ++ kfree(engine); + goto err; + } + +@@ -302,7 +303,10 @@ static int idxd_setup_engines(struct idxd_device *idxd) + engine = idxd->engines[i]; + conf_dev = engine_confdev(engine); + put_device(conf_dev); ++ kfree(engine); + } ++ kfree(idxd->engines); ++ + return rc; + } + +@@ -336,6 +340,7 @@ static int idxd_setup_groups(struct idxd_device *idxd) + rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id); + if (rc < 0) { + put_device(conf_dev); ++ kfree(group); + goto err; + } + +@@ -355,7 +360,10 @@ static int idxd_setup_groups(struct idxd_device *idxd) + while (--i >= 0) { + group = idxd->groups[i]; + put_device(group_confdev(group)); ++ kfree(group); + } ++ kfree(idxd->groups); ++ + return rc; + } + +diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c +index 9db45c4eaaf246..1ca552a324778b 100644 +--- a/drivers/dma/ti/k3-udma.c ++++ b/drivers/dma/ti/k3-udma.c +@@ -1082,8 +1082,11 @@ static void udma_check_tx_completion(struct work_struct *work) + u32 residue_diff; + ktime_t time_diff; + unsigned long delay; ++ unsigned long flags; + + while (1) { ++ spin_lock_irqsave(&uc->vc.lock, flags); ++ + if (uc->desc) { + /* Get previous residue and time stamp */ + residue_diff = uc->tx_drain.residue; +@@ -1118,6 +1121,8 @@ static void udma_check_tx_completion(struct work_struct *work) + break; + } + ++ spin_unlock_irqrestore(&uc->vc.lock, flags); ++ + usleep_range(ktime_to_us(delay), + ktime_to_us(delay) + 10); + continue; +@@ -1134,6 +1139,8 @@ static void udma_check_tx_completion(struct work_struct *work) + + break; + } ++ ++ spin_unlock_irqrestore(&uc->vc.lock, flags); + } + + static irqreturn_t udma_ring_irq_handler(int irq, void *data) +@@ -4203,7 +4210,6 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) + { + struct udma_dev *ud = ofdma->of_dma_data; +- dma_cap_mask_t mask = ud->ddev.cap_mask; + struct udma_filter_param filter_param; + struct dma_chan *chan; + +@@ -4235,7 +4241,7 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec, + } + } + +- chan = __dma_request_channel(&mask, udma_dma_filter_fn, &filter_param, ++ chan = __dma_request_channel(&ud->ddev.cap_mask, udma_dma_filter_fn, &filter_param, + ofdma->of_node); + if (!chan) { + dev_err(ud->dev, "get channel fail in %s.\n", __func__); +diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c +index c922faab4a52b6..e240fac8b6b377 100644 +--- a/drivers/iio/adc/ad7768-1.c ++++ b/drivers/iio/adc/ad7768-1.c +@@ -169,7 +169,7 @@ struct ad7768_state { + union { + struct { + __be32 chan; +- s64 timestamp; ++ aligned_s64 timestamp; + } scan; + __be32 d32; + u8 d8[2]; +diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c +index d51314505115e2..43991fe2e35bf4 100644 +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -108,7 +108,7 @@ static irqreturn_t sps30_trigger_handler(int irq, void *p) + int ret; + struct { + s32 data[4]; /* PM1, PM2P5, PM4, PM10 */ +- s64 ts; ++ aligned_s64 ts; + } scan; + + mutex_lock(&state->lock); +diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c +index 4eedaa0244b398..f22f8e950baef4 100644 +--- a/drivers/infiniband/sw/rxe/rxe_cq.c ++++ b/drivers/infiniband/sw/rxe/rxe_cq.c +@@ -71,11 +71,8 @@ int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe, + + err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, + cq->queue->buf, cq->queue->buf_size, &cq->queue->ip); +- if (err) { +- vfree(cq->queue->buf); +- kfree(cq->queue); ++ if (err) + return err; +- } + + if (uresp) + cq->is_user = 1; +diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c +index 888f10d93b9ab9..ec1c0ad591184f 100644 +--- a/drivers/net/dsa/sja1105/sja1105_main.c ++++ b/drivers/net/dsa/sja1105/sja1105_main.c +@@ -1969,6 +1969,7 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port, + switch (state) { + case BR_STATE_DISABLED: + case BR_STATE_BLOCKING: ++ case BR_STATE_LISTENING: + /* From UM10944 description of DRPDTAG (why put this there?): + * "Management traffic flows to the port regardless of the state + * of the INGRESS flag". So BPDUs are still be allowed to pass. +@@ -1978,11 +1979,6 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port, + mac[port].egress = false; + mac[port].dyn_learn = false; + break; +- case BR_STATE_LISTENING: +- mac[port].ingress = true; +- mac[port].egress = false; +- mac[port].dyn_learn = false; +- break; + case BR_STATE_LEARNING: + mac[port].ingress = true; + mac[port].egress = false; +diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c +index 275baaaea0e12a..667af80a739b97 100644 +--- a/drivers/net/ethernet/cadence/macb_main.c ++++ b/drivers/net/ethernet/cadence/macb_main.c +@@ -986,22 +986,15 @@ static void macb_update_stats(struct macb *bp) + + static int macb_halt_tx(struct macb *bp) + { +- unsigned long halt_time, timeout; +- u32 status; ++ u32 status; + + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT)); + +- timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT); +- do { +- halt_time = jiffies; +- status = macb_readl(bp, TSR); +- if (!(status & MACB_BIT(TGO))) +- return 0; +- +- udelay(250); +- } while (time_before(halt_time, timeout)); +- +- return -ETIMEDOUT; ++ /* Poll TSR until TGO is cleared or timeout. */ ++ return read_poll_timeout_atomic(macb_readl, status, ++ !(status & MACB_BIT(TGO)), ++ 250, MACB_HALT_TIMEOUT, false, ++ bp, TSR); + } + + static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb) +diff --git a/drivers/net/ethernet/intel/ice/ice_arfs.c b/drivers/net/ethernet/intel/ice/ice_arfs.c +index 9cebae92364ebb..760783f0efe18c 100644 +--- a/drivers/net/ethernet/intel/ice/ice_arfs.c ++++ b/drivers/net/ethernet/intel/ice/ice_arfs.c +@@ -577,7 +577,7 @@ void ice_free_cpu_rx_rmap(struct ice_vsi *vsi) + { + struct net_device *netdev; + +- if (!vsi || vsi->type != ICE_VSI_PF || !vsi->arfs_fltr_list) ++ if (!vsi || vsi->type != ICE_VSI_PF) + return; + + netdev = vsi->netdev; +@@ -599,7 +599,7 @@ int ice_set_cpu_rx_rmap(struct ice_vsi *vsi) + int base_idx, i; + + if (!vsi || vsi->type != ICE_VSI_PF) +- return -EINVAL; ++ return 0; + + pf = vsi->back; + netdev = vsi->netdev; +@@ -636,7 +636,6 @@ void ice_remove_arfs(struct ice_pf *pf) + if (!pf_vsi) + return; + +- ice_free_cpu_rx_rmap(pf_vsi); + ice_clear_arfs(pf_vsi); + } + +@@ -653,9 +652,5 @@ void ice_rebuild_arfs(struct ice_pf *pf) + return; + + ice_remove_arfs(pf); +- if (ice_set_cpu_rx_rmap(pf_vsi)) { +- dev_err(ice_pf_to_dev(pf), "Failed to rebuild aRFS\n"); +- return; +- } + ice_init_arfs(pf_vsi); + } +diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c +index 8a00864ead7c49..71d062b969cd7d 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -2645,6 +2645,8 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) + return; + + vsi->irqs_ready = false; ++ ice_free_cpu_rx_rmap(vsi); ++ + ice_for_each_q_vector(vsi, i) { + u16 vector = i + base; + int irq_num; +@@ -2658,7 +2660,8 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) + continue; + + /* clear the affinity notifier in the IRQ descriptor */ +- irq_set_affinity_notifier(irq_num, NULL); ++ if (!IS_ENABLED(CONFIG_RFS_ACCEL)) ++ irq_set_affinity_notifier(irq_num, NULL); + + /* clear the affinity_mask in the IRQ descriptor */ + irq_set_affinity_hint(irq_num, NULL); +diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c +index 735f8cef6bfa45..91840ea92b0dfe 100644 +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -2393,6 +2393,13 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) + irq_set_affinity_hint(irq_num, &q_vector->affinity_mask); + } + ++ err = ice_set_cpu_rx_rmap(vsi); ++ if (err) { ++ netdev_err(vsi->netdev, "Failed to setup CPU RMAP on VSI %u: %pe\n", ++ vsi->vsi_num, ERR_PTR(err)); ++ goto free_q_irqs; ++ } ++ + vsi->irqs_ready = true; + return 0; + +@@ -3380,22 +3387,12 @@ static int ice_setup_pf_sw(struct ice_pf *pf) + */ + ice_napi_add(vsi); + +- status = ice_set_cpu_rx_rmap(vsi); +- if (status) { +- dev_err(ice_pf_to_dev(pf), "Failed to set CPU Rx map VSI %d error %d\n", +- vsi->vsi_num, status); +- status = -EINVAL; +- goto unroll_napi_add; +- } + status = ice_init_mac_fltr(pf); + if (status) +- goto free_cpu_rx_map; ++ goto unroll_napi_add; + + return status; + +-free_cpu_rx_map: +- ice_free_cpu_rx_rmap(vsi); +- + unroll_napi_add: + if (vsi) { + ice_napi_del(vsi); +@@ -4886,7 +4883,6 @@ static int __maybe_unused ice_suspend(struct device *dev) + continue; + ice_vsi_free_q_vectors(pf->vsi[v]); + } +- ice_free_cpu_rx_rmap(ice_get_main_vsi(pf)); + ice_clear_interrupt_scheme(pf); + + pci_save_state(pdev); +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +index d7c93c409a7765..3bc2f83176d036 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +@@ -1485,8 +1485,11 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_o + } + + cmd_op = (cmd.rsp.arg[0] & 0xff); +- if (cmd.rsp.arg[0] >> 25 == 2) +- return 2; ++ if (cmd.rsp.arg[0] >> 25 == 2) { ++ ret = 2; ++ goto out; ++ } ++ + if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) + set_bit(QLC_BC_VF_STATE, &vf->state); + else +diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c +index f225a34e218619..e0d6d7ee66defd 100644 +--- a/drivers/net/wireless/mediatek/mt76/dma.c ++++ b/drivers/net/wireless/mediatek/mt76/dma.c +@@ -684,6 +684,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) + int i; + + mt76_worker_disable(&dev->tx_worker); ++ napi_disable(&dev->tx_napi); + netif_napi_del(&dev->tx_napi); + + for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) { +diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +index 7e61c6b278a742..670514d44fe3fc 100644 +--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c ++++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c +@@ -453,8 +453,11 @@ static int rcar_gen3_phy_usb2_init(struct phy *p) + val = readl(usb2_base + USB2_INT_ENABLE); + val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; + writel(val, usb2_base + USB2_INT_ENABLE); +- writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); +- writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); ++ ++ if (!rcar_gen3_is_any_rphy_initialized(channel)) { ++ writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET); ++ writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET); ++ } + + /* Initialize otg part */ + if (channel->is_otg_channel) { +diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c +index be31b1e25b3806..17a119e8cf7ed0 100644 +--- a/drivers/phy/tegra/xusb.c ++++ b/drivers/phy/tegra/xusb.c +@@ -542,16 +542,16 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port, + + err = dev_set_name(&port->dev, "%s-%u", name, index); + if (err < 0) +- goto unregister; ++ goto put_device; + + err = device_add(&port->dev); + if (err < 0) +- goto unregister; ++ goto put_device; + + return 0; + +-unregister: +- device_unregister(&port->dev); ++put_device: ++ put_device(&port->dev); + return err; + } + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index a34d0f53ad16f2..d9933d37181296 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -3052,7 +3052,8 @@ static int asus_wmi_add(struct platform_device *pdev) + goto fail_leds; + + asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); +- if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) ++ if ((result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) == ++ (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) + asus->driver->wlan_ctrl_by_user = 1; + + if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) { +diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c +index 4d4f77a186a98a..89fccb9da1b8ee 100644 +--- a/drivers/spi/spi-loopback-test.c ++++ b/drivers/spi/spi-loopback-test.c +@@ -383,7 +383,7 @@ MODULE_LICENSE("GPL"); + static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) + { + /* limit the hex_dump */ +- if (len < 1024) { ++ if (len <= 1024) { + print_hex_dump(KERN_INFO, pre, + DUMP_PREFIX_OFFSET, 16, 1, + ptr, len, 0); +diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c +index 8f0c6da27dd1b1..97a912f0c4eed4 100644 +--- a/drivers/usb/typec/altmodes/displayport.c ++++ b/drivers/usb/typec/altmodes/displayport.c +@@ -521,22 +521,26 @@ static ssize_t pin_assignment_show(struct device *dev, + } + static DEVICE_ATTR_RW(pin_assignment); + +-static struct attribute *dp_altmode_attrs[] = { ++static struct attribute *displayport_attrs[] = { + &dev_attr_configuration.attr, + &dev_attr_pin_assignment.attr, + NULL + }; + +-static const struct attribute_group dp_altmode_group = { ++static const struct attribute_group displayport_group = { + .name = "displayport", +- .attrs = dp_altmode_attrs, ++ .attrs = displayport_attrs, ++}; ++ ++static const struct attribute_group *displayport_groups[] = { ++ &displayport_group, ++ NULL, + }; + + int dp_altmode_probe(struct typec_altmode *alt) + { + const struct typec_altmode *port = typec_altmode_get_partner(alt); + struct dp_altmode *dp; +- int ret; + + /* FIXME: Port can only be DFP_U. */ + +@@ -547,10 +551,6 @@ int dp_altmode_probe(struct typec_altmode *alt) + DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo))) + return -ENODEV; + +- ret = sysfs_create_group(&alt->dev.kobj, &dp_altmode_group); +- if (ret) +- return ret; +- + dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL); + if (!dp) + return -ENOMEM; +@@ -576,7 +576,6 @@ void dp_altmode_remove(struct typec_altmode *alt) + { + struct dp_altmode *dp = typec_altmode_get_drvdata(alt); + +- sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group); + cancel_work_sync(&dp->work); + } + EXPORT_SYMBOL_GPL(dp_altmode_remove); +@@ -594,6 +593,7 @@ static struct typec_altmode_driver dp_altmode_driver = { + .driver = { + .name = "typec_displayport", + .owner = THIS_MODULE, ++ .dev_groups = displayport_groups, + }, + }; + module_typec_altmode_driver(dp_altmode_driver); +diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c +index 8c19081c325542..e3b5fa3b5f955d 100644 +--- a/drivers/usb/typec/ucsi/displayport.c ++++ b/drivers/usb/typec/ucsi/displayport.c +@@ -54,7 +54,8 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo) + u8 cur = 0; + int ret; + +- mutex_lock(&dp->con->lock); ++ if (!ucsi_con_mutex_lock(dp->con)) ++ return -ENOTCONN; + + if (!dp->override && dp->initialized) { + const struct typec_altmode *p = typec_altmode_get_partner(alt); +@@ -100,7 +101,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo) + schedule_work(&dp->work); + ret = 0; + err_unlock: +- mutex_unlock(&dp->con->lock); ++ ucsi_con_mutex_unlock(dp->con); + + return ret; + } +@@ -112,7 +113,8 @@ static int ucsi_displayport_exit(struct typec_altmode *alt) + u64 command; + int ret = 0; + +- mutex_lock(&dp->con->lock); ++ if (!ucsi_con_mutex_lock(dp->con)) ++ return -ENOTCONN; + + if (!dp->override) { + const struct typec_altmode *p = typec_altmode_get_partner(alt); +@@ -144,7 +146,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt) + schedule_work(&dp->work); + + out_unlock: +- mutex_unlock(&dp->con->lock); ++ ucsi_con_mutex_unlock(dp->con); + + return ret; + } +@@ -202,20 +204,21 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt, + int cmd = PD_VDO_CMD(header); + int svdm_version; + +- mutex_lock(&dp->con->lock); ++ if (!ucsi_con_mutex_lock(dp->con)) ++ return -ENOTCONN; + + if (!dp->override && dp->initialized) { + const struct typec_altmode *p = typec_altmode_get_partner(alt); + + dev_warn(&p->dev, + "firmware doesn't support alternate mode overriding\n"); +- mutex_unlock(&dp->con->lock); ++ ucsi_con_mutex_unlock(dp->con); + return -EOPNOTSUPP; + } + + svdm_version = typec_altmode_get_svdm_version(alt); + if (svdm_version < 0) { +- mutex_unlock(&dp->con->lock); ++ ucsi_con_mutex_unlock(dp->con); + return svdm_version; + } + +@@ -259,7 +262,7 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt, + break; + } + +- mutex_unlock(&dp->con->lock); ++ ucsi_con_mutex_unlock(dp->con); + + return 0; + } +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index 979af06f22d837..e42e146d5bed93 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1351,6 +1351,40 @@ void ucsi_set_drvdata(struct ucsi *ucsi, void *data) + } + EXPORT_SYMBOL_GPL(ucsi_set_drvdata); + ++/** ++ * ucsi_con_mutex_lock - Acquire the connector mutex ++ * @con: The connector interface to lock ++ * ++ * Returns true on success, false if the connector is disconnected ++ */ ++bool ucsi_con_mutex_lock(struct ucsi_connector *con) ++{ ++ bool mutex_locked = false; ++ bool connected = true; ++ ++ while (connected && !mutex_locked) { ++ mutex_locked = mutex_trylock(&con->lock) != 0; ++ connected = con->status.flags & UCSI_CONSTAT_CONNECTED; ++ if (connected && !mutex_locked) ++ msleep(20); ++ } ++ ++ connected = connected && con->partner; ++ if (!connected && mutex_locked) ++ mutex_unlock(&con->lock); ++ ++ return connected; ++} ++ ++/** ++ * ucsi_con_mutex_unlock - Release the connector mutex ++ * @con: The connector interface to unlock ++ */ ++void ucsi_con_mutex_unlock(struct ucsi_connector *con) ++{ ++ mutex_unlock(&con->lock); ++} ++ + /** + * ucsi_create - Allocate UCSI instance + * @dev: Device interface to the PPM (Platform Policy Manager) +diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h +index 656a53ccd89178..87b1a54d68e8bd 100644 +--- a/drivers/usb/typec/ucsi/ucsi.h ++++ b/drivers/usb/typec/ucsi/ucsi.h +@@ -15,6 +15,7 @@ + + struct ucsi; + struct ucsi_altmode; ++struct ucsi_connector; + + /* UCSI offsets (Bytes) */ + #define UCSI_VERSION 0 +@@ -62,6 +63,8 @@ int ucsi_register(struct ucsi *ucsi); + void ucsi_unregister(struct ucsi *ucsi); + void *ucsi_get_drvdata(struct ucsi *ucsi); + void ucsi_set_drvdata(struct ucsi *ucsi, void *data); ++bool ucsi_con_mutex_lock(struct ucsi_connector *con); ++void ucsi_con_mutex_unlock(struct ucsi_connector *con); + + void ucsi_connector_change(struct ucsi *ucsi, u8 num); + +diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c +index fb6211efb5d871..dffdb5eb506b7b 100644 +--- a/drivers/usb/typec/ucsi/ucsi_ccg.c ++++ b/drivers/usb/typec/ucsi/ucsi_ccg.c +@@ -573,6 +573,10 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, + uc->has_multiple_dp) { + con_index = (uc->last_cmd_sent >> 16) & + UCSI_CMD_CONNECTOR_MASK; ++ if (con_index == 0) { ++ ret = -EINVAL; ++ goto err_put; ++ } + con = &uc->ucsi->connector[con_index - 1]; + ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val); + } +@@ -587,6 +591,7 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset, + + err_clear_bit: + clear_bit(DEV_CMD_PENDING, &uc->flags); ++err_put: + pm_runtime_put_sync(uc->dev); + mutex_unlock(&uc->lock); + +diff --git a/fs/btrfs/discard.c b/fs/btrfs/discard.c +index bd9dde374e5d81..7b2f77a8aa982d 100644 +--- a/fs/btrfs/discard.c ++++ b/fs/btrfs/discard.c +@@ -78,8 +78,6 @@ static void __add_to_discard_list(struct btrfs_discard_ctl *discard_ctl, + struct btrfs_block_group *block_group) + { + lockdep_assert_held(&discard_ctl->lock); +- if (!btrfs_run_discard_work(discard_ctl)) +- return; + + if (list_empty(&block_group->discard_list) || + block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED) { +@@ -102,6 +100,9 @@ static void add_to_discard_list(struct btrfs_discard_ctl *discard_ctl, + if (!btrfs_is_block_group_data_only(block_group)) + return; + ++ if (!btrfs_run_discard_work(discard_ctl)) ++ return; ++ + spin_lock(&discard_ctl->lock); + __add_to_discard_list(discard_ctl, block_group); + spin_unlock(&discard_ctl->lock); +@@ -233,6 +234,18 @@ static struct btrfs_block_group *peek_discard_list( + block_group->used != 0) { + if (btrfs_is_block_group_data_only(block_group)) { + __add_to_discard_list(discard_ctl, block_group); ++ /* ++ * The block group must have been moved to other ++ * discard list even if discard was disabled in ++ * the meantime or a transaction abort happened, ++ * otherwise we can end up in an infinite loop, ++ * always jumping into the 'again' label and ++ * keep getting this block group over and over ++ * in case there are no other block groups in ++ * the discard lists. ++ */ ++ ASSERT(block_group->discard_index != ++ BTRFS_DISCARD_INDEX_UNUSED); + } else { + list_del_init(&block_group->discard_list); + btrfs_put_block_group(block_group); +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 551faae77bc313..8959506a0aa775 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -176,6 +176,14 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, + ei = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_extent_item); + num_refs = btrfs_extent_refs(leaf, ei); ++ if (unlikely(num_refs == 0)) { ++ ret = -EUCLEAN; ++ btrfs_err(fs_info, ++ "unexpected zero reference count for extent item (%llu %u %llu)", ++ key.objectid, key.type, key.offset); ++ btrfs_abort_transaction(trans, ret); ++ goto out_free; ++ } + extent_flags = btrfs_extent_flags(leaf, ei); + } else { + ret = -EINVAL; +@@ -187,8 +195,6 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, + + goto out_free; + } +- +- BUG_ON(num_refs == 0); + } else { + num_refs = 0; + extent_flags = 0; +@@ -218,10 +224,19 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, + goto search_again; + } + spin_lock(&head->lock); +- if (head->extent_op && head->extent_op->update_flags) ++ if (head->extent_op && head->extent_op->update_flags) { + extent_flags |= head->extent_op->flags_to_set; +- else +- BUG_ON(num_refs == 0); ++ } else if (unlikely(num_refs == 0)) { ++ spin_unlock(&head->lock); ++ mutex_unlock(&head->mutex); ++ spin_unlock(&delayed_refs->lock); ++ ret = -EUCLEAN; ++ btrfs_err(fs_info, ++ "unexpected zero reference count for extent %llu (%s)", ++ bytenr, metadata ? "metadata" : "data"); ++ btrfs_abort_transaction(trans, ret); ++ goto out_free; ++ } + + num_refs += head->ref_mod; + spin_unlock(&head->lock); +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 346fc46d019bf7..a1946d62911c9f 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2624,7 +2624,6 @@ int btrfs_repair_one_sector(struct inode *inode, + const int icsum = bio_offset >> fs_info->sectorsize_bits; + struct bio *repair_bio; + struct btrfs_io_bio *repair_io_bio; +- blk_status_t status; + + btrfs_debug(fs_info, + "repair read error: read error at %llu", start); +@@ -2664,13 +2663,13 @@ int btrfs_repair_one_sector(struct inode *inode, + "repair read error: submitting new read to mirror %d", + failrec->this_mirror); + +- status = submit_bio_hook(inode, repair_bio, failrec->this_mirror, +- failrec->bio_flags); +- if (status) { +- free_io_failure(failure_tree, tree, failrec); +- bio_put(repair_bio); +- } +- return blk_status_to_errno(status); ++ /* ++ * At this point we have a bio, so any errors from submit_bio_hook() ++ * will be handled by the endio on the repair_bio, so we can't return an ++ * error here. ++ */ ++ submit_bio_hook(inode, repair_bio, failrec->this_mirror, failrec->bio_flags); ++ return BLK_STS_OK; + } + + static void end_page_read(struct page *page, bool uptodate, u64 start, u32 len) +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 4a0691aeb7c1db..e4b3f25bb8e48b 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -6835,10 +6835,18 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, + struct nfs4_unlockdata *p; + struct nfs4_state *state = lsp->ls_state; + struct inode *inode = state->inode; ++ struct nfs_lock_context *l_ctx; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) + return NULL; ++ l_ctx = nfs_get_lock_context(ctx); ++ if (!IS_ERR(l_ctx)) { ++ p->l_ctx = l_ctx; ++ } else { ++ kfree(p); ++ return NULL; ++ } + p->arg.fh = NFS_FH(inode); + p->arg.fl = &p->fl; + p->arg.seqid = seqid; +@@ -6846,7 +6854,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, + p->lsp = lsp; + /* Ensure we don't close file until we're done freeing locks! */ + p->ctx = get_nfs_open_context(ctx); +- p->l_ctx = nfs_get_lock_context(ctx); + locks_init_lock(&p->fl); + locks_copy_lock(&p->fl, fl); + p->server = NFS_SERVER(inode); +diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c +index 4016cc5316230e..83935bb1719ad9 100644 +--- a/fs/nfs/pnfs.c ++++ b/fs/nfs/pnfs.c +@@ -729,6 +729,14 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo, + return remaining; + } + ++static void pnfs_reset_return_info(struct pnfs_layout_hdr *lo) ++{ ++ struct pnfs_layout_segment *lseg; ++ ++ list_for_each_entry(lseg, &lo->plh_return_segs, pls_list) ++ pnfs_set_plh_return_info(lo, lseg->pls_range.iomode, 0); ++} ++ + static void + pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo, + struct list_head *free_me, +@@ -1177,6 +1185,7 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo, + pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq); + pnfs_free_returned_lsegs(lo, &freeme, range, seq); + pnfs_set_layout_stateid(lo, stateid, NULL, true); ++ pnfs_reset_return_info(lo); + } else + pnfs_mark_layout_stateid_invalid(lo, &freeme); + out_unlock: +diff --git a/include/linux/cpu.h b/include/linux/cpu.h +index e1e6a045c38b77..87b5a176e84897 100644 +--- a/include/linux/cpu.h ++++ b/include/linux/cpu.h +@@ -76,6 +76,8 @@ extern ssize_t cpu_show_gds(struct device *dev, + struct device_attribute *attr, char *buf); + extern ssize_t cpu_show_reg_file_data_sampling(struct device *dev, + struct device_attribute *attr, char *buf); ++extern ssize_t cpu_show_indirect_target_selection(struct device *dev, ++ struct device_attribute *attr, char *buf); + + extern __printf(4, 5) + struct device *cpu_device_create(struct device *parent, void *drvdata, +diff --git a/include/linux/module.h b/include/linux/module.h +index fb9762e16f2858..8e629b03ed1e41 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -528,6 +528,11 @@ struct module { + atomic_t refcnt; + #endif + ++#ifdef CONFIG_MITIGATION_ITS ++ int its_num_pages; ++ void **its_page_array; ++#endif ++ + #ifdef CONFIG_CONSTRUCTORS + /* Constructor functions. */ + ctor_fn_t *ctors; +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index 9ee225cff61129..605d4c0a63e9a7 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -1088,7 +1088,7 @@ static inline bool nft_chain_is_bound(struct nft_chain *chain) + + int nft_chain_add(struct nft_table *table, struct nft_chain *chain); + void nft_chain_del(struct nft_chain *chain); +-void nf_tables_chain_destroy(struct nft_ctx *ctx); ++void nf_tables_chain_destroy(struct nft_chain *chain); + + struct nft_stats { + u64 bytes; +diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h +index 0919dfd3a67a68..55127305478dfd 100644 +--- a/include/net/sch_generic.h ++++ b/include/net/sch_generic.h +@@ -1035,6 +1035,21 @@ static inline struct sk_buff *__qdisc_dequeue_head(struct qdisc_skb_head *qh) + return skb; + } + ++static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool direct) ++{ ++ struct sk_buff *skb; ++ ++ skb = __skb_dequeue(&sch->gso_skb); ++ if (skb) { ++ sch->q.qlen--; ++ return skb; ++ } ++ if (direct) ++ return __qdisc_dequeue_head(&sch->q); ++ else ++ return sch->dequeue(sch); ++} ++ + static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) + { + struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); +diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c +index d4f71372332349..6d0e9f869ad688 100644 +--- a/kernel/trace/trace_dynevent.c ++++ b/kernel/trace/trace_dynevent.c +@@ -16,7 +16,7 @@ + #include "trace_output.h" /* for trace_event_sem */ + #include "trace_dynevent.h" + +-static DEFINE_MUTEX(dyn_event_ops_mutex); ++DEFINE_MUTEX(dyn_event_ops_mutex); + static LIST_HEAD(dyn_event_ops_list); + + bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call) +@@ -125,6 +125,20 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type + return ret; + } + ++/* ++ * Locked version of event creation. The event creation must be protected by ++ * dyn_event_ops_mutex because of protecting trace_probe_log. ++ */ ++int dyn_event_create(const char *raw_command, struct dyn_event_operations *type) ++{ ++ int ret; ++ ++ mutex_lock(&dyn_event_ops_mutex); ++ ret = type->create(raw_command); ++ mutex_unlock(&dyn_event_ops_mutex); ++ return ret; ++} ++ + static int create_dyn_event(const char *raw_command) + { + struct dyn_event_operations *ops; +diff --git a/kernel/trace/trace_dynevent.h b/kernel/trace/trace_dynevent.h +index 936477a111d3e7..beee3f8d754444 100644 +--- a/kernel/trace/trace_dynevent.h ++++ b/kernel/trace/trace_dynevent.h +@@ -100,6 +100,7 @@ void *dyn_event_seq_next(struct seq_file *m, void *v, loff_t *pos); + void dyn_event_seq_stop(struct seq_file *m, void *v); + int dyn_events_release_all(struct dyn_event_operations *type); + int dyn_event_release(const char *raw_command, struct dyn_event_operations *type); ++int dyn_event_create(const char *raw_command, struct dyn_event_operations *type); + + /* + * for_each_dyn_event - iterate over the dyn_event list +diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c +index 106f9813841a15..d56e208f5cb8f9 100644 +--- a/kernel/trace/trace_events_trigger.c ++++ b/kernel/trace/trace_events_trigger.c +@@ -1244,7 +1244,7 @@ stacktrace_trigger(struct event_trigger_data *data, + struct trace_event_file *file = data->private_data; + + if (file) +- __trace_stack(file->tr, tracing_gen_ctx(), STACK_SKIP); ++ __trace_stack(file->tr, tracing_gen_ctx_dec(), STACK_SKIP); + else + trace_dump_stack(STACK_SKIP); + } +diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c +index 1f0e63f5d1f983..18b8580971f6bd 100644 +--- a/kernel/trace/trace_functions.c ++++ b/kernel/trace/trace_functions.c +@@ -568,11 +568,7 @@ ftrace_traceoff(unsigned long ip, unsigned long parent_ip, + + static __always_inline void trace_stack(struct trace_array *tr) + { +- unsigned int trace_ctx; +- +- trace_ctx = tracing_gen_ctx(); +- +- __trace_stack(tr, trace_ctx, FTRACE_STACK_SKIP); ++ __trace_stack(tr, tracing_gen_ctx_dec(), FTRACE_STACK_SKIP); + } + + static void +diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c +index 3a1c54c9918b44..e062f4efec8d0a 100644 +--- a/kernel/trace/trace_kprobe.c ++++ b/kernel/trace/trace_kprobe.c +@@ -971,7 +971,7 @@ static int create_or_delete_trace_kprobe(const char *raw_command) + if (raw_command[0] == '-') + return dyn_event_release(raw_command, &trace_kprobe_ops); + +- ret = trace_kprobe_create(raw_command); ++ ret = dyn_event_create(raw_command, &trace_kprobe_ops); + return ret == -ECANCELED ? -EINVAL : ret; + } + +diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c +index d2a1b7f0306855..38fa6cc118dafa 100644 +--- a/kernel/trace/trace_probe.c ++++ b/kernel/trace/trace_probe.c +@@ -143,9 +143,12 @@ static const struct fetch_type *find_fetch_type(const char *type) + } + + static struct trace_probe_log trace_probe_log; ++extern struct mutex dyn_event_ops_mutex; + + void trace_probe_log_init(const char *subsystem, int argc, const char **argv) + { ++ lockdep_assert_held(&dyn_event_ops_mutex); ++ + trace_probe_log.subsystem = subsystem; + trace_probe_log.argc = argc; + trace_probe_log.argv = argv; +@@ -154,11 +157,15 @@ void trace_probe_log_init(const char *subsystem, int argc, const char **argv) + + void trace_probe_log_clear(void) + { ++ lockdep_assert_held(&dyn_event_ops_mutex); ++ + memset(&trace_probe_log, 0, sizeof(trace_probe_log)); + } + + void trace_probe_log_set_index(int index) + { ++ lockdep_assert_held(&dyn_event_ops_mutex); ++ + trace_probe_log.index = index; + } + +@@ -167,6 +174,8 @@ void __trace_probe_log_err(int offset, int err_type) + char *command, *p; + int i, len = 0, pos = 0; + ++ lockdep_assert_held(&dyn_event_ops_mutex); ++ + if (!trace_probe_log.argv) + return; + +diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c +index 720b46b34ab941..322d56661d04ad 100644 +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -729,7 +729,7 @@ static int create_or_delete_trace_uprobe(const char *raw_command) + if (raw_command[0] == '-') + return dyn_event_release(raw_command, &trace_uprobe_ops); + +- ret = trace_uprobe_create(raw_command); ++ ret = dyn_event_create(raw_command, &trace_uprobe_ops); + return ret == -ECANCELED ? -EINVAL : ret; + } + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 07fdd5f18f3c9b..a1f60f275814cd 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1981,9 +1981,9 @@ static void nf_tables_chain_free_chain_rules(struct nft_chain *chain) + kvfree(chain->rules_next); + } + +-void nf_tables_chain_destroy(struct nft_ctx *ctx) ++void nf_tables_chain_destroy(struct nft_chain *chain) + { +- struct nft_chain *chain = ctx->chain; ++ const struct nft_table *table = chain->table; + struct nft_hook *hook, *next; + + if (WARN_ON(chain->use > 0)) +@@ -1995,7 +1995,7 @@ void nf_tables_chain_destroy(struct nft_ctx *ctx) + if (nft_is_base_chain(chain)) { + struct nft_base_chain *basechain = nft_base_chain(chain); + +- if (nft_base_chain_netdev(ctx->family, basechain->ops.hooknum)) { ++ if (nft_base_chain_netdev(table->family, basechain->ops.hooknum)) { + list_for_each_entry_safe(hook, next, + &basechain->hook_list, list) { + list_del_rcu(&hook->list); +@@ -2445,7 +2445,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, + err_use: + nf_tables_unregister_hook(net, table, chain); + err_destroy_chain: +- nf_tables_chain_destroy(ctx); ++ nf_tables_chain_destroy(chain); + + return err; + } +@@ -3440,8 +3440,11 @@ void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule) + kfree(rule); + } + ++/* can only be used if rule is no longer visible to dumps */ + static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule) + { ++ lockdep_commit_lock_is_held(ctx->net); ++ + nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE); + nf_tables_rule_destroy(ctx, rule); + } +@@ -5177,6 +5180,8 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set, + struct nft_set_binding *binding, + enum nft_trans_phase phase) + { ++ lockdep_commit_lock_is_held(ctx->net); ++ + switch (phase) { + case NFT_TRANS_PREPARE_ERROR: + nft_set_trans_unbind(ctx, set); +@@ -8809,7 +8814,7 @@ static void nft_commit_release(struct nft_trans *trans) + kfree(nft_trans_chain_name(trans)); + break; + case NFT_MSG_DELCHAIN: +- nf_tables_chain_destroy(&trans->ctx); ++ nf_tables_chain_destroy(nft_trans_chain(trans)); + break; + case NFT_MSG_DELRULE: + nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); +@@ -9721,7 +9726,7 @@ static void nf_tables_abort_release(struct nft_trans *trans) + nf_tables_table_destroy(&trans->ctx); + break; + case NFT_MSG_NEWCHAIN: +- nf_tables_chain_destroy(&trans->ctx); ++ nf_tables_chain_destroy(nft_trans_chain(trans)); + break; + case NFT_MSG_NEWRULE: + nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); +@@ -10428,23 +10433,43 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, + } + EXPORT_SYMBOL_GPL(nft_data_dump); + +-int __nft_release_basechain(struct nft_ctx *ctx) ++static void __nft_release_basechain_now(struct nft_ctx *ctx) + { + struct nft_rule *rule, *nr; + +- if (WARN_ON(!nft_is_base_chain(ctx->chain))) +- return 0; +- +- nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); + list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { + list_del(&rule->list); +- nft_use_dec(&ctx->chain->use); + nf_tables_rule_release(ctx, rule); + } ++ nf_tables_chain_destroy(ctx->chain); ++} ++ ++int __nft_release_basechain(struct nft_ctx *ctx) ++{ ++ struct nft_rule *rule; ++ ++ if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain))) ++ return 0; ++ ++ nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); ++ list_for_each_entry(rule, &ctx->chain->rules, list) ++ nft_use_dec(&ctx->chain->use); ++ + nft_chain_del(ctx->chain); + nft_use_dec(&ctx->table->use); +- nf_tables_chain_destroy(ctx); + ++ if (!maybe_get_net(ctx->net)) { ++ __nft_release_basechain_now(ctx); ++ return 0; ++ } ++ ++ /* wait for ruleset dumps to complete. Owning chain is no longer in ++ * lists, so new dumps can't find any of these rules anymore. ++ */ ++ synchronize_rcu(); ++ ++ __nft_release_basechain_now(ctx); ++ put_net(ctx->net); + return 0; + } + EXPORT_SYMBOL_GPL(__nft_release_basechain); +@@ -10519,10 +10544,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table) + nft_obj_destroy(&ctx, obj); + } + list_for_each_entry_safe(chain, nc, &table->chains, list) { +- ctx.chain = chain; + nft_chain_del(chain); + nft_use_dec(&table->use); +- nf_tables_chain_destroy(&ctx); ++ nf_tables_chain_destroy(chain); + } + nf_tables_table_destroy(&ctx); + } +diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c +index d154fe67ca8a63..a889cf1d863ef3 100644 +--- a/net/netfilter/nft_immediate.c ++++ b/net/netfilter/nft_immediate.c +@@ -221,7 +221,7 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx, + list_del(&rule->list); + nf_tables_rule_destroy(&chain_ctx, rule); + } +- nf_tables_chain_destroy(&chain_ctx); ++ nf_tables_chain_destroy(chain); + break; + default: + break; +diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c +index 30169b3adbbb06..d99c7386e24e6b 100644 +--- a/net/sched/sch_codel.c ++++ b/net/sched/sch_codel.c +@@ -174,7 +174,7 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt, + + qlen = sch->q.qlen; + while (sch->q.qlen > sch->limit) { +- struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); ++ struct sk_buff *skb = qdisc_dequeue_internal(sch, true); + + dropped += qdisc_pkt_len(skb); + qdisc_qstats_backlog_dec(sch, skb); +diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c +index 5a1274199fe336..65b12b39e2ec5d 100644 +--- a/net/sched/sch_fq.c ++++ b/net/sched/sch_fq.c +@@ -904,7 +904,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + } + while (sch->q.qlen > sch->limit) { +- struct sk_buff *skb = fq_dequeue(sch); ++ struct sk_buff *skb = qdisc_dequeue_internal(sch, false); + + if (!skb) + break; +diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c +index efda894bbb78b2..f954969ea8fece 100644 +--- a/net/sched/sch_fq_codel.c ++++ b/net/sched/sch_fq_codel.c +@@ -429,7 +429,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, + + while (sch->q.qlen > sch->limit || + q->memory_usage > q->memory_limit) { +- struct sk_buff *skb = fq_codel_dequeue(sch); ++ struct sk_buff *skb = qdisc_dequeue_internal(sch, false); + + q->cstats.drop_len += qdisc_pkt_len(skb); + rtnl_kfree_skbs(skb, skb); +diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c +index 1fb68c973f4510..30259c87564511 100644 +--- a/net/sched/sch_fq_pie.c ++++ b/net/sched/sch_fq_pie.c +@@ -360,7 +360,7 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt, + + /* Drop excess packets if new limit is lower */ + while (sch->q.qlen > sch->limit) { +- struct sk_buff *skb = fq_pie_qdisc_dequeue(sch); ++ struct sk_buff *skb = qdisc_dequeue_internal(sch, false); + + len_dropped += qdisc_pkt_len(skb); + num_dropped += 1; +diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c +index 420ede8753229f..433bddcbc0c724 100644 +--- a/net/sched/sch_hhf.c ++++ b/net/sched/sch_hhf.c +@@ -563,7 +563,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt, + qlen = sch->q.qlen; + prev_backlog = sch->qstats.backlog; + while (sch->q.qlen > sch->limit) { +- struct sk_buff *skb = hhf_dequeue(sch); ++ struct sk_buff *skb = qdisc_dequeue_internal(sch, false); + + rtnl_kfree_skbs(skb, skb); + } +diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c +index 5a457ff61acd87..67ce65af52b5cd 100644 +--- a/net/sched/sch_pie.c ++++ b/net/sched/sch_pie.c +@@ -193,7 +193,7 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt, + /* Drop excess packets if new limit is lower */ + qlen = sch->q.qlen; + while (sch->q.qlen > sch->limit) { +- struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); ++ struct sk_buff *skb = qdisc_dequeue_internal(sch, true); + + dropped += qdisc_pkt_len(skb); + qdisc_qstats_backlog_dec(sch, skb); +diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c +index 916dc2e81e428f..f3d09998c24dea 100644 +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -518,6 +518,8 @@ static int proc_sctp_do_auth(struct ctl_table *ctl, int write, + return ret; + } + ++static DEFINE_MUTEX(sctp_sysctl_mutex); ++ + static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, + void *buffer, size_t *lenp, loff_t *ppos) + { +@@ -542,6 +544,7 @@ static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, + if (new_value > max || new_value < min) + return -EINVAL; + ++ mutex_lock(&sctp_sysctl_mutex); + net->sctp.udp_port = new_value; + sctp_udp_sock_stop(net); + if (new_value) { +@@ -554,6 +557,7 @@ static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, + lock_sock(sk); + sctp_sk(sk)->udp_port = htons(net->sctp.udp_port); + release_sock(sk); ++ mutex_unlock(&sctp_sysctl_mutex); + } + + return ret; +diff --git a/samples/ftrace/sample-trace-array.c b/samples/ftrace/sample-trace-array.c +index 6aba02a31c96c5..77685a7eb7678e 100644 +--- a/samples/ftrace/sample-trace-array.c ++++ b/samples/ftrace/sample-trace-array.c +@@ -112,7 +112,7 @@ static int __init sample_trace_array_init(void) + /* + * If context specific per-cpu buffers havent already been allocated. + */ +- trace_printk_init_buffers(); ++ trace_array_init_printk(tr); + + simple_tsk = kthread_run(simple_thread, NULL, "sample-instance"); + if (IS_ERR(simple_tsk)) { +diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c +index 4a7e20bb11bcae..802c5ed4a5ba4b 100644 +--- a/sound/pci/es1968.c ++++ b/sound/pci/es1968.c +@@ -1569,7 +1569,7 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) + struct snd_pcm_runtime *runtime = substream->runtime; + struct es1968 *chip = snd_pcm_substream_chip(substream); + struct esschan *es; +- int apu1, apu2; ++ int err, apu1, apu2; + + apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE); + if (apu1 < 0) +@@ -1613,7 +1613,9 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream) + runtime->hw = snd_es1968_capture; + runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = + calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */ +- snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); ++ err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); ++ if (err < 0) ++ return err; + + spin_lock_irq(&chip->substream_lock); + list_add(&es->list, &chip->substream_list); +diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig +index b75fbb3236a7b9..f5fa09d740b4c9 100644 +--- a/sound/sh/Kconfig ++++ b/sound/sh/Kconfig +@@ -14,7 +14,7 @@ if SND_SUPERH + + config SND_AICA + tristate "Dreamcast Yamaha AICA sound" +- depends on SH_DREAMCAST ++ depends on SH_DREAMCAST && SH_DMA_API + select SND_PCM + select G2_DMA + help +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 10430c76475b5f..488fcdbb6a2d4b 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1837,6 +1837,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */ + QUIRK_FLAG_GET_SAMPLE_RATE), ++ DEVICE_FLG(0x0c45, 0x636b, /* Microdia JP001 USB Camera */ ++ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x0d8c, 0x0014, /* USB Audio Device */ + QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ +@@ -1845,6 +1847,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + QUIRK_FLAG_FIXED_RATE), + DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), ++ DEVICE_FLG(0x1101, 0x0003, /* Audioengine D1 */ ++ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ +diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c +index 7c260060a1a6b8..00ebd9d508ffdf 100644 +--- a/tools/testing/selftests/vm/compaction_test.c ++++ b/tools/testing/selftests/vm/compaction_test.c +@@ -89,6 +89,8 @@ int check_compaction(unsigned long mem_free, unsigned long hugepage_size) + int compaction_index = 0; + char initial_nr_hugepages[20] = {0}; + char nr_hugepages[20] = {0}; ++ char target_nr_hugepages[24] = {0}; ++ int slen; + + /* We want to test with 80% of available memory. Else, OOM killer comes + in to play */ +@@ -118,11 +120,18 @@ int check_compaction(unsigned long mem_free, unsigned long hugepage_size) + + lseek(fd, 0, SEEK_SET); + +- /* Request a large number of huge pages. The Kernel will allocate +- as much as it can */ +- if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) { +- ksft_test_result_fail("Failed to write 100000 to /proc/sys/vm/nr_hugepages: %s\n", +- strerror(errno)); ++ /* ++ * Request huge pages for about half of the free memory. The Kernel ++ * will allocate as much as it can, and we expect it will get at least 1/3 ++ */ ++ nr_hugepages_ul = mem_free / hugepage_size / 2; ++ snprintf(target_nr_hugepages, sizeof(target_nr_hugepages), ++ "%lu", nr_hugepages_ul); ++ ++ slen = strlen(target_nr_hugepages); ++ if (write(fd, target_nr_hugepages, slen) != slen) { ++ ksft_test_result_fail("Failed to write %lu to /proc/sys/vm/nr_hugepages: %s\n", ++ nr_hugepages_ul, strerror(errno)); + goto close_fd; + } +