From: Greg Kroah-Hartman Date: Tue, 28 May 2019 13:07:33 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v5.1.6~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ebabf46e646170c231eb8d564d77d44e4630fa46;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch btrfs-honor-path-skip_locking-in-backref-code.patch --- diff --git a/queue-4.19/arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch b/queue-4.19/arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch new file mode 100644 index 00000000000..4584e2abe6e --- /dev/null +++ b/queue-4.19/arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch @@ -0,0 +1,245 @@ +From 969f5ea627570e91c9d54403287ee3ed657f58fe Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Mon, 29 Apr 2019 13:03:57 +0100 +Subject: arm64: errata: Add workaround for Cortex-A76 erratum #1463225 + +From: Will Deacon + +commit 969f5ea627570e91c9d54403287ee3ed657f58fe upstream. + +Revisions of the Cortex-A76 CPU prior to r4p0 are affected by an erratum +that can prevent interrupts from being taken when single-stepping. + +This patch implements a software workaround to prevent userspace from +effectively being able to disable interrupts. + +Cc: +Cc: Marc Zyngier +Cc: Catalin Marinas +Signed-off-by: Will Deacon +Signed-off-by: Greg Kroah-Hartman + + +--- + Documentation/arm64/silicon-errata.txt | 1 + arch/arm64/Kconfig | 18 ++++++++++++++++ + arch/arm64/include/asm/cpucaps.h | 3 +- + arch/arm64/include/asm/cputype.h | 2 + + arch/arm64/kernel/cpu_errata.c | 24 +++++++++++++++++++++ + arch/arm64/kernel/syscall.c | 31 +++++++++++++++++++++++++++ + arch/arm64/mm/fault.c | 37 +++++++++++++++++++++++++++++++-- + 7 files changed, 113 insertions(+), 3 deletions(-) + +--- a/Documentation/arm64/silicon-errata.txt ++++ b/Documentation/arm64/silicon-errata.txt +@@ -58,6 +58,7 @@ stable kernels. + | ARM | Cortex-A72 | #853709 | N/A | + | ARM | Cortex-A73 | #858921 | ARM64_ERRATUM_858921 | + | ARM | Cortex-A55 | #1024718 | ARM64_ERRATUM_1024718 | ++| ARM | Cortex-A76 | #1463225 | ARM64_ERRATUM_1463225 | + | ARM | MMU-500 | #841119,#826419 | N/A | + | | | | | + | Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 | +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -479,6 +479,24 @@ config ARM64_ERRATUM_1024718 + + If unsure, say Y. + ++config ARM64_ERRATUM_1463225 ++ bool "Cortex-A76: Software Step might prevent interrupt recognition" ++ default y ++ help ++ This option adds a workaround for Arm Cortex-A76 erratum 1463225. ++ ++ On the affected Cortex-A76 cores (r0p0 to r3p1), software stepping ++ of a system call instruction (SVC) can prevent recognition of ++ subsequent interrupts when software stepping is disabled in the ++ exception handler of the system call and either kernel debugging ++ is enabled or VHE is in use. ++ ++ Work around the erratum by triggering a dummy step exception ++ when handling a system call from a task that is being stepped ++ in a VHE configuration of the kernel. ++ ++ If unsure, say Y. ++ + config CAVIUM_ERRATUM_22375 + bool "Cavium erratum 22375, 24313" + default y +--- a/arch/arm64/include/asm/cpucaps.h ++++ b/arch/arm64/include/asm/cpucaps.h +@@ -51,7 +51,8 @@ + #define ARM64_SSBD 30 + #define ARM64_MISMATCHED_CACHE_TYPE 31 + #define ARM64_HAS_STAGE2_FWB 32 ++#define ARM64_WORKAROUND_1463225 33 + +-#define ARM64_NCAPS 33 ++#define ARM64_NCAPS 34 + + #endif /* __ASM_CPUCAPS_H */ +--- a/arch/arm64/include/asm/cputype.h ++++ b/arch/arm64/include/asm/cputype.h +@@ -86,6 +86,7 @@ + #define ARM_CPU_PART_CORTEX_A75 0xD0A + #define ARM_CPU_PART_CORTEX_A35 0xD04 + #define ARM_CPU_PART_CORTEX_A55 0xD05 ++#define ARM_CPU_PART_CORTEX_A76 0xD0B + + #define APM_CPU_PART_POTENZA 0x000 + +@@ -110,6 +111,7 @@ + #define MIDR_CORTEX_A75 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75) + #define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35) + #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55) ++#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) + #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) + #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) + #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -411,6 +411,22 @@ static bool has_ssbd_mitigation(const st + } + #endif /* CONFIG_ARM64_SSBD */ + ++#ifdef CONFIG_ARM64_ERRATUM_1463225 ++DEFINE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa); ++ ++static bool ++has_cortex_a76_erratum_1463225(const struct arm64_cpu_capabilities *entry, ++ int scope) ++{ ++ u32 midr = read_cpuid_id(); ++ /* Cortex-A76 r0p0 - r3p1 */ ++ struct midr_range range = MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 1); ++ ++ WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); ++ return is_midr_in_range(midr, &range) && is_kernel_in_hyp_mode(); ++} ++#endif ++ + #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \ + .matches = is_affected_midr_range, \ + .midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max) +@@ -680,6 +696,14 @@ const struct arm64_cpu_capabilities arm6 + .matches = has_ssbd_mitigation, + }, + #endif ++#ifdef CONFIG_ARM64_ERRATUM_1463225 ++ { ++ .desc = "ARM erratum 1463225", ++ .capability = ARM64_WORKAROUND_1463225, ++ .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, ++ .matches = has_cortex_a76_erratum_1463225, ++ }, ++#endif + { + } + }; +--- a/arch/arm64/kernel/syscall.c ++++ b/arch/arm64/kernel/syscall.c +@@ -8,6 +8,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -60,6 +61,35 @@ static inline bool has_syscall_work(unsi + int syscall_trace_enter(struct pt_regs *regs); + void syscall_trace_exit(struct pt_regs *regs); + ++#ifdef CONFIG_ARM64_ERRATUM_1463225 ++DECLARE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa); ++ ++static void cortex_a76_erratum_1463225_svc_handler(void) ++{ ++ u32 reg, val; ++ ++ if (!unlikely(test_thread_flag(TIF_SINGLESTEP))) ++ return; ++ ++ if (!unlikely(this_cpu_has_cap(ARM64_WORKAROUND_1463225))) ++ return; ++ ++ __this_cpu_write(__in_cortex_a76_erratum_1463225_wa, 1); ++ reg = read_sysreg(mdscr_el1); ++ val = reg | DBG_MDSCR_SS | DBG_MDSCR_KDE; ++ write_sysreg(val, mdscr_el1); ++ asm volatile("msr daifclr, #8"); ++ isb(); ++ ++ /* We will have taken a single-step exception by this point */ ++ ++ write_sysreg(reg, mdscr_el1); ++ __this_cpu_write(__in_cortex_a76_erratum_1463225_wa, 0); ++} ++#else ++static void cortex_a76_erratum_1463225_svc_handler(void) { } ++#endif /* CONFIG_ARM64_ERRATUM_1463225 */ ++ + static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, + const syscall_fn_t syscall_table[]) + { +@@ -68,6 +98,7 @@ static void el0_svc_common(struct pt_reg + regs->orig_x0 = regs->regs[0]; + regs->syscallno = scno; + ++ cortex_a76_erratum_1463225_svc_handler(); + local_daif_restore(DAIF_PROCCTX); + user_exit(); + +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -827,14 +827,47 @@ void __init hook_debug_fault_code(int nr + debug_fault_info[nr].name = name; + } + ++#ifdef CONFIG_ARM64_ERRATUM_1463225 ++DECLARE_PER_CPU(int, __in_cortex_a76_erratum_1463225_wa); ++ ++static int __exception ++cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs) ++{ ++ if (user_mode(regs)) ++ return 0; ++ ++ if (!__this_cpu_read(__in_cortex_a76_erratum_1463225_wa)) ++ return 0; ++ ++ /* ++ * We've taken a dummy step exception from the kernel to ensure ++ * that interrupts are re-enabled on the syscall path. Return back ++ * to cortex_a76_erratum_1463225_svc_handler() with debug exceptions ++ * masked so that we can safely restore the mdscr and get on with ++ * handling the syscall. ++ */ ++ regs->pstate |= PSR_D_BIT; ++ return 1; ++} ++#else ++static int __exception ++cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs) ++{ ++ return 0; ++} ++#endif /* CONFIG_ARM64_ERRATUM_1463225 */ ++ + asmlinkage int __exception do_debug_exception(unsigned long addr_if_watchpoint, +- unsigned int esr, +- struct pt_regs *regs) ++ unsigned int esr, ++ struct pt_regs *regs) + { + const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr); + unsigned long pc = instruction_pointer(regs); + int rv; + ++ if (cortex_a76_erratum_1463225_debug_handler(regs)) ++ return 0; ++ + /* + * Tell lockdep we disabled irqs in entry.S. Do nothing if they were + * already disabled to preserve the last enabled/disabled addresses. diff --git a/queue-4.19/btrfs-honor-path-skip_locking-in-backref-code.patch b/queue-4.19/btrfs-honor-path-skip_locking-in-backref-code.patch new file mode 100644 index 00000000000..a76d81a9cae --- /dev/null +++ b/queue-4.19/btrfs-honor-path-skip_locking-in-backref-code.patch @@ -0,0 +1,156 @@ +From 38e3eebff643db725633657d1d87a3be019d1018 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Wed, 16 Jan 2019 11:00:57 -0500 +Subject: btrfs: honor path->skip_locking in backref code + +From: Josef Bacik + +commit 38e3eebff643db725633657d1d87a3be019d1018 upstream. + +Qgroups will do the old roots lookup at delayed ref time, which could be +while walking down the extent root while running a delayed ref. This +should be fine, except we specifically lock eb's in the backref walking +code irrespective of path->skip_locking, which deadlocks the system. +Fix up the backref code to honor path->skip_locking, nobody will be +modifying the commit_root when we're searching so it's completely safe +to do. + +This happens since fb235dc06fac ("btrfs: qgroup: Move half of the qgroup +accounting time out of commit trans"), kernel may lockup with quota +enabled. + +There is one backref trace triggered by snapshot dropping along with +write operation in the source subvolume. The example can be reliably +reproduced: + + btrfs-cleaner D 0 4062 2 0x80000000 + Call Trace: + schedule+0x32/0x90 + btrfs_tree_read_lock+0x93/0x130 [btrfs] + find_parent_nodes+0x29b/0x1170 [btrfs] + btrfs_find_all_roots_safe+0xa8/0x120 [btrfs] + btrfs_find_all_roots+0x57/0x70 [btrfs] + btrfs_qgroup_trace_extent_post+0x37/0x70 [btrfs] + btrfs_qgroup_trace_leaf_items+0x10b/0x140 [btrfs] + btrfs_qgroup_trace_subtree+0xc8/0xe0 [btrfs] + do_walk_down+0x541/0x5e3 [btrfs] + walk_down_tree+0xab/0xe7 [btrfs] + btrfs_drop_snapshot+0x356/0x71a [btrfs] + btrfs_clean_one_deleted_snapshot+0xb8/0xf0 [btrfs] + cleaner_kthread+0x12b/0x160 [btrfs] + kthread+0x112/0x130 + ret_from_fork+0x27/0x50 + +When dropping snapshots with qgroup enabled, we will trigger backref +walk. + +However such backref walk at that timing is pretty dangerous, as if one +of the parent nodes get WRITE locked by other thread, we could cause a +dead lock. + +For example: + + FS 260 FS 261 (Dropped) + node A node B + / \ / \ + node C node D node E + / \ / \ / \ + leaf F|leaf G|leaf H|leaf I|leaf J|leaf K + +The lock sequence would be: + + Thread A (cleaner) | Thread B (other writer) +----------------------------------------------------------------------- +write_lock(B) | +write_lock(D) | +^^^ called by walk_down_tree() | + | write_lock(A) + | write_lock(D) << Stall +read_lock(H) << for backref walk | +read_lock(D) << lock owner is | + the same thread A | + so read lock is OK | +read_lock(A) << Stall | + +So thread A hold write lock D, and needs read lock A to unlock. +While thread B holds write lock A, while needs lock D to unlock. + +This will cause a deadlock. + +This is not only limited to snapshot dropping case. As the backref +walk, even only happens on commit trees, is breaking the normal top-down +locking order, makes it deadlock prone. + +Fixes: fb235dc06fac ("btrfs: qgroup: Move half of the qgroup accounting time out of commit trans") +CC: stable@vger.kernel.org # 4.14+ +Reported-and-tested-by: David Sterba +Reported-by: Filipe Manana +Reviewed-by: Qu Wenruo +Signed-off-by: Josef Bacik +Reviewed-by: Filipe Manana +[ rebase to latest branch and fix lock assert bug in btrfs/007 ] +[ backport to linux-4.19.y branch, solve minor conflicts ] +Signed-off-by: Qu Wenruo +[ copy logs and deadlock analysis from Qu's patch ] +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/backref.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/fs/btrfs/backref.c ++++ b/fs/btrfs/backref.c +@@ -710,7 +710,7 @@ out: + * read tree blocks and add keys where required. + */ + static int add_missing_keys(struct btrfs_fs_info *fs_info, +- struct preftrees *preftrees) ++ struct preftrees *preftrees, bool lock) + { + struct prelim_ref *ref; + struct extent_buffer *eb; +@@ -735,12 +735,14 @@ static int add_missing_keys(struct btrfs + free_extent_buffer(eb); + return -EIO; + } +- btrfs_tree_read_lock(eb); ++ if (lock) ++ btrfs_tree_read_lock(eb); + if (btrfs_header_level(eb) == 0) + btrfs_item_key_to_cpu(eb, &ref->key_for_search, 0); + else + btrfs_node_key_to_cpu(eb, &ref->key_for_search, 0); +- btrfs_tree_read_unlock(eb); ++ if (lock) ++ btrfs_tree_read_unlock(eb); + free_extent_buffer(eb); + prelim_ref_insert(fs_info, &preftrees->indirect, ref, NULL); + cond_resched(); +@@ -1225,7 +1227,7 @@ again: + + btrfs_release_path(path); + +- ret = add_missing_keys(fs_info, &preftrees); ++ ret = add_missing_keys(fs_info, &preftrees, path->skip_locking == 0); + if (ret) + goto out; + +@@ -1286,11 +1288,14 @@ again: + ret = -EIO; + goto out; + } +- btrfs_tree_read_lock(eb); +- btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); ++ if (!path->skip_locking) { ++ btrfs_tree_read_lock(eb); ++ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); ++ } + ret = find_extent_in_eb(eb, bytenr, + *extent_item_pos, &eie, ignore_offset); +- btrfs_tree_read_unlock_blocking(eb); ++ if (!path->skip_locking) ++ btrfs_tree_read_unlock_blocking(eb); + free_extent_buffer(eb); + if (ret < 0) + goto out; diff --git a/queue-4.19/series b/queue-4.19/series index 8ddb91089ea..7e7a9bea5e3 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -27,3 +27,5 @@ nfsv4.1-fix-incorrect-return-value-in-copy_file_range.patch bpf-add-bpf_jit_limit-knob-to-restrict-unpriv-allocations.patch brcmfmac-assure-ssid-length-from-firmware-is-limited.patch brcmfmac-add-subtype-check-for-event-handling-in-data-path.patch +arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch +btrfs-honor-path-skip_locking-in-backref-code.patch