Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp3365286pxb; Mon, 17 Jan 2022 18:42:16 -0800 (PST) X-Google-Smtp-Source: ABdhPJy4WHKESKRj7LRDgtirajz8rloxocK3OCx2p6CrUMXqXVByLH3jL6EoRzV3Z7855kM/0ZNK X-Received: by 2002:a17:90b:4f88:: with SMTP id qe8mr7902372pjb.164.1642473736160; Mon, 17 Jan 2022 18:42:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642473736; cv=none; d=google.com; s=arc-20160816; b=CTak/z6fe01ZHdLbRyaHY8QcL8FCjSEMVsqTcRAXqIFTOgRLU+h5EkMTyRpRmimEXz 2j9L6wt7ywx35rGZy0FQmufIulDtx9g2lp5zbO4pJsGH8x7/Z45rIUN/CW78c7kOdo8C gzibKU4vjGvgrcovwtKZGQ2gikNNoMyQdnVhB4VJTs2ecaQAuLN+GZqDOb5je+Dsckpz 1732litQXJr9DvtmYHySmpAIjzawGMIdISkD1EGXxo4utGAaLMu6KccDJwsAEFrRfN+b Uo+WoPpLjFoXLyjplGKAUY16TQnaKAiSKqTGF97xqpAhuKI5vh5hSXED/MhOFB+Vi0XT ZwmQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=7juGHYjYC8OPdg5QNlhkQZ2yv/SRsVa0+nXdUh+1NSI=; b=giKrFu2Qccon07cJpLAns53UxLyzrvoIkU0xpf6EkOtIGaIzhhczT6kb2W2++gDzEu SMdeRyuy5qJtFxAkIHJyjB9WQt6yw2FbiYcVtCi1fLhLKb7rdsN8LzYW6N9NwXybVBBZ lUy2LIYPace3CN1GmUeFbK8nvLYBs0rp+p72CQCHLt62i6g0kAP8pPXT4n/CL+Uu9LVm KcNth6Y22V/Bvwr028AKJ0fEyef4Uz/Si6wTNcJJddTt8QI1SugcxGMm/Kz/hpdJzKi2 o7f24dOK5I8BAX8rByCForc+vBTU3hNVTc8MWKODk3nyadgAl2uIW+snLzxIQfOZCw6v uomA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=DAyLwaUV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id s2si15744768pgv.333.2022.01.17.18.42.03; Mon, 17 Jan 2022 18:42:16 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=DAyLwaUV; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241237AbiAQQ7T (ORCPT + 99 others); Mon, 17 Jan 2022 11:59:19 -0500 Received: from ams.source.kernel.org ([145.40.68.75]:47270 "EHLO ams.source.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237822AbiAQQ7O (ORCPT ); Mon, 17 Jan 2022 11:59:14 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id EB6E1B81131; Mon, 17 Jan 2022 16:59:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8BDEEC36AE7; Mon, 17 Jan 2022 16:59:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1642438751; bh=tg8iEjvzYlmjjMbrWjc40apMLT5XKRdF0J/xCoow65U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DAyLwaUVmJYaJR2GMGKsK3+GKol98s1haTOP34ur+MEFIuV+dHUwS00meAy/wer4D 3hXOaWuiWXrxGXIs+0f9UiAooRbD8dLnRKnfsk28DG4bRYyaOMRiIINzfD4Hu1cFWF ya4+FmsyTSKJGvbzJTR5fH7+4VUOVKBG6YQ2nCdsH4rVKT6c+H86bRiVl0ZNx9ndmv sQwUp4Ki9WgcvjFArp7l7Ne0kZKJFKLFUFPk6iD79ijchB7AOGVRV35YM6P7rzfCRz PSG+0FfDboPh8bOa6mxk1YR8WNJYjnNU64ojLw/SxvgPr4OGjIbZqNH4XcoiJkNwaK k5xEHMBKdFzcQ== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Nicholas Piggin , Laurent Dufour , Michael Ellerman , Sasha Levin , pmladek@suse.com, john.ogness@linutronix.de, clg@kaod.org, sudeep.holla@arm.com, linuxppc-dev@lists.ozlabs.org Subject: [PATCH AUTOSEL 5.16 07/52] powerpc/watchdog: Fix missed watchdog reset due to memory ordering race Date: Mon, 17 Jan 2022 11:58:08 -0500 Message-Id: <20220117165853.1470420-7-sashal@kernel.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220117165853.1470420-1-sashal@kernel.org> References: <20220117165853.1470420-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Nicholas Piggin [ Upstream commit 5dad4ba68a2483fc80d70b9dc90bbe16e1f27263 ] It is possible for all CPUs to miss the pending cpumask becoming clear, and then nobody resetting it, which will cause the lockup detector to stop working. It will eventually expire, but watchdog_smp_panic will avoid doing anything if the pending mask is clear and it will never be reset. Order the cpumask clear vs the subsequent test to close this race. Add an extra check for an empty pending mask when the watchdog fires and finds its bit still clear, to try to catch any other possible races or bugs here and keep the watchdog working. The extra test in arch_touch_nmi_watchdog is required to prevent the new warning from firing off. Signed-off-by: Nicholas Piggin Reviewed-by: Laurent Dufour Debugged-by: Laurent Dufour Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20211110025056.2084347-2-npiggin@gmail.com Signed-off-by: Sasha Levin --- arch/powerpc/kernel/watchdog.c | 41 +++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c index 3fa6d240bade2..ad94a2c6b7337 100644 --- a/arch/powerpc/kernel/watchdog.c +++ b/arch/powerpc/kernel/watchdog.c @@ -135,6 +135,10 @@ static void set_cpumask_stuck(const struct cpumask *cpumask, u64 tb) { cpumask_or(&wd_smp_cpus_stuck, &wd_smp_cpus_stuck, cpumask); cpumask_andnot(&wd_smp_cpus_pending, &wd_smp_cpus_pending, cpumask); + /* + * See wd_smp_clear_cpu_pending() + */ + smp_mb(); if (cpumask_empty(&wd_smp_cpus_pending)) { wd_smp_last_reset_tb = tb; cpumask_andnot(&wd_smp_cpus_pending, @@ -221,13 +225,44 @@ static void wd_smp_clear_cpu_pending(int cpu, u64 tb) cpumask_clear_cpu(cpu, &wd_smp_cpus_stuck); wd_smp_unlock(&flags); + } else { + /* + * The last CPU to clear pending should have reset the + * watchdog so we generally should not find it empty + * here if our CPU was clear. However it could happen + * due to a rare race with another CPU taking the + * last CPU out of the mask concurrently. + * + * We can't add a warning for it. But just in case + * there is a problem with the watchdog that is causing + * the mask to not be reset, try to kick it along here. + */ + if (unlikely(cpumask_empty(&wd_smp_cpus_pending))) + goto none_pending; } return; } + cpumask_clear_cpu(cpu, &wd_smp_cpus_pending); + + /* + * Order the store to clear pending with the load(s) to check all + * words in the pending mask to check they are all empty. This orders + * with the same barrier on another CPU. This prevents two CPUs + * clearing the last 2 pending bits, but neither seeing the other's + * store when checking if the mask is empty, and missing an empty + * mask, which ends with a false positive. + */ + smp_mb(); if (cpumask_empty(&wd_smp_cpus_pending)) { unsigned long flags; +none_pending: + /* + * Double check under lock because more than one CPU could see + * a clear mask with the lockless check after clearing their + * pending bits. + */ wd_smp_lock(&flags); if (cpumask_empty(&wd_smp_cpus_pending)) { wd_smp_last_reset_tb = tb; @@ -318,8 +353,12 @@ void arch_touch_nmi_watchdog(void) { unsigned long ticks = tb_ticks_per_usec * wd_timer_period_ms * 1000; int cpu = smp_processor_id(); - u64 tb = get_tb(); + u64 tb; + if (!cpumask_test_cpu(cpu, &watchdog_cpumask)) + return; + + tb = get_tb(); if (tb - per_cpu(wd_timer_tb, cpu) >= ticks) { per_cpu(wd_timer_tb, cpu) = tb; wd_smp_clear_cpu_pending(cpu, tb); -- 2.34.1