From 4a8723855a11337ad1f5937f34f6432e3add4a4f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 May 2019 15:12:27 +0200 Subject: [PATCH] 5.0-stable patches added patches: arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch btrfs-honor-path-skip_locking-in-backref-code.patch --- ...round-for-cortex-a76-erratum-1463225.patch | 226 ++++++++++++++++++ ...or-path-skip_locking-in-backref-code.patch | 156 ++++++++++++ queue-5.0/series | 2 + 3 files changed, 384 insertions(+) create mode 100644 queue-5.0/arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch create mode 100644 queue-5.0/btrfs-honor-path-skip_locking-in-backref-code.patch diff --git a/queue-5.0/arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch b/queue-5.0/arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch new file mode 100644 index 00000000000..08fba626ad4 --- /dev/null +++ b/queue-5.0/arm64-errata-add-workaround-for-cortex-a76-erratum-1463225.patch @@ -0,0 +1,226 @@ +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/kernel/cpu_errata.c | 24 +++++++++++++++++++++ + arch/arm64/kernel/syscall.c | 31 +++++++++++++++++++++++++++ + arch/arm64/mm/fault.c | 37 +++++++++++++++++++++++++++++++-- + 6 files changed, 111 insertions(+), 3 deletions(-) + +--- a/Documentation/arm64/silicon-errata.txt ++++ b/Documentation/arm64/silicon-errata.txt +@@ -61,6 +61,7 @@ stable kernels. + | ARM | Cortex-A76 | #1188873 | ARM64_ERRATUM_1188873 | + | ARM | Cortex-A76 | #1165522 | ARM64_ERRATUM_1165522 | + | ARM | Cortex-A76 | #1286807 | ARM64_ERRATUM_1286807 | ++| 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 +@@ -518,6 +518,24 @@ config ARM64_ERRATUM_1286807 + + 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 +@@ -60,7 +60,8 @@ + #define ARM64_HAS_ADDRESS_AUTH_IMP_DEF 39 + #define ARM64_HAS_GENERIC_AUTH_ARCH 40 + #define ARM64_HAS_GENERIC_AUTH_IMP_DEF 41 ++#define ARM64_WORKAROUND_1463225 42 + +-#define ARM64_NCAPS 42 ++#define ARM64_NCAPS 43 + + #endif /* __ASM_CPUCAPS_H */ +--- a/arch/arm64/kernel/cpu_errata.c ++++ b/arch/arm64/kernel/cpu_errata.c +@@ -464,6 +464,22 @@ out_printmsg: + } + #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 ++ + static void __maybe_unused + cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused) + { +@@ -739,6 +755,14 @@ const struct arm64_cpu_capabilities arm6 + ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 2, 0), + }, + #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 +@@ -824,14 +824,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 = esr_to_debug_fault_info(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-5.0/btrfs-honor-path-skip_locking-in-backref-code.patch b/queue-5.0/btrfs-honor-path-skip_locking-in-backref-code.patch new file mode 100644 index 00000000000..007b6c3389c --- /dev/null +++ b/queue-5.0/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 ] +[ solve conflicts and backport to linux-5.0.y ] +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 +@@ -712,7 +712,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; +@@ -737,12 +737,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(); +@@ -1227,7 +1229,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; + +@@ -1288,11 +1290,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-5.0/series b/queue-5.0/series index b2f4daad8c9..70144493bf6 100644 --- a/queue-5.0/series +++ b/queue-5.0/series @@ -24,3 +24,5 @@ fbdev-fix-divide-error-in-fb_var_to_videomode.patch cifs-fix-credits-leak-for-smb1-oplock-breaks.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 -- 2.47.2