Received: by 2002:a05:7412:3210:b0:e2:908c:2ebd with SMTP id eu16csp251553rdb; Thu, 31 Aug 2023 08:26:13 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEdylBJ7/Eo79zl8/tw92SkKs4xNaIa6C1xyezPUMwLzlSKlMzYUgw2Oy5QGoFU38qGLzPI X-Received: by 2002:a05:651c:228:b0:2bc:b61d:44c9 with SMTP id z8-20020a05651c022800b002bcb61d44c9mr4267328ljn.53.1693495572772; Thu, 31 Aug 2023 08:26:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693495572; cv=none; d=google.com; s=arc-20160816; b=FMz5JQnXXdJ46miZRB+bKmPhW71jy1rcsXyzo0eGGHMmqcffutsiC5KnxvpCVxvDcs 7fFcJ+8KFEQ0NFMBFVC2oDyoLHiGFlc/SdrGk4J6GHvNG4tBbcmFc0EUm8ixKTBynFg9 W2d1Kf/oAPLNCiM8bmWSsXZNfnDlocm2y0KG6iBynxVaMXm519d48VVEE+wxtUOuzknf p5GGl1Ql0SYaM8AN369H7HE+PA3Xt+A/v36iBXFIA+ISM3SaWMudUFLtsRZwvpO0gF8g vh3vE1oMb6eXiMR948GNI+oqa3/pJkSxqt+EyPqgsGwn3EJN6Iww+QwFZ265rhMIqaGt EG8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date; bh=i/CdqjDSKPhIjO0MwCTr8NAQCMgrJFswXA2BHAlN0TA=; fh=x0/2qkX0lGfPpoDCb/M/7sbTH5vD38l/RXrCEwshX34=; b=TPSECPKGFZM5zV7DOYaxGN6yDozjHx7VClhWGQlUMr69xpitBjz8wpQQO7UpNLrpAp F+OmbS6O2qQr9dIhVE87bVOuOBMiOinhpoQIn8xJOOrgP2IcOYxocxE6ZA0MD545OrBI +6BUzh/Y36n+Gw6lOsZRW6HaofAFOcm9C4YjhdPZ9b1F5HgJxp1OmliZjMUO0SyzQSAk hJAiFzjcD0zrAQmPUQmHxFm6zURO3Exs237ruh1/qAcPs7JboRBWwWyv4RA5STs0Iy3g 3IGQFzurjKJbD4i8GH/z14Ooz4ymsVpXVeBEvldqJDxXX8u3QTrSvG/r2uFkYWbj4Gjt JhFg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x16-20020a170906135000b0099cc71ae649si1139113ejb.114.2023.08.31.08.25.30; Thu, 31 Aug 2023 08:26:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235240AbjHaNIH (ORCPT + 99 others); Thu, 31 Aug 2023 09:08:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50404 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232184AbjHaNIG (ORCPT ); Thu, 31 Aug 2023 09:08:06 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8A689BC for ; Thu, 31 Aug 2023 06:08:03 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C4518C15; Thu, 31 Aug 2023 06:08:42 -0700 (PDT) Received: from FVFF77S0Q05N.cambridge.arm.com (FVFF77S0Q05N.cambridge.arm.com [10.1.36.128]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 610753F738; Thu, 31 Aug 2023 06:08:02 -0700 (PDT) Date: Thu, 31 Aug 2023 14:07:23 +0100 From: Mark Rutland To: Sumit Garg Cc: linux-kernel@vger.kernel.org, dianders@chromium.org, keescook@chromium.org, swboyd@chromium.org Subject: Re: [PATCH] lkdtm/bugs: add test for panic() with stuck secondary CPUs Message-ID: References: <20230831101026.3122590-1-mark.rutland@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Aug 31, 2023 at 06:15:29PM +0530, Sumit Garg wrote: > Hi Mark, > > Thanks for putting up a test case for this. > > On Thu, 31 Aug 2023 at 15:40, Mark Rutland wrote: > > > > Upon a panic() the kernel will use either smp_send_stop() or > > crash_smp_send_stop() to attempt to stop secondary CPUs via an IPI, > > which may or may not be an NMI. Generally it's preferable that this is an > > NMI so that CPUs can be stopped in as many situations as possible, but > > it's not always possible to provide an NMI, and there are cases where > > CPUs may be unable to handle the NMI regardless. > > > > This patch adds a test for panic() where all other CPUs are stuck with > > interrupts disabled, which can be used to check whether the kernel > > gracefully handles CPUs failing to respond to a stop, and whe NMIs stops > > s/whe/when/ > > > work. > > > > For example, on arm64 *without* an NMI, this results in: > > > > | # echo PANIC_STOP_IRQOFF > /sys/kernel/debug/provoke-crash/DIRECT > > | lkdtm: Performing direct entry PANIC_STOP_IRQOFF > > | Kernel panic - not syncing: panic stop irqoff test > > | CPU: 2 PID: 24 Comm: migration/2 Not tainted 6.5.0-rc3-00077-ge6c782389895-dirty #4 > > | Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015 > > | Stopper: multi_cpu_stop+0x0/0x1a0 <- stop_machine_cpuslocked+0x158/0x1a4 > > | Call trace: > > | dump_backtrace+0x94/0xec > > | show_stack+0x18/0x24 > > | dump_stack_lvl+0x74/0xc0 > > | dump_stack+0x18/0x24 > > | panic+0x358/0x3e8 > > | lkdtm_PANIC+0x0/0x18 > > | multi_cpu_stop+0x9c/0x1a0 > > | cpu_stopper_thread+0x84/0x118 > > | smpboot_thread_fn+0x224/0x248 > > | kthread+0x114/0x118 > > | ret_from_fork+0x10/0x20 > > | SMP: stopping secondary CPUs > > | SMP: failed to stop secondary CPUs 0-3 > > | Kernel Offset: 0x401cf3490000 from 0xffff800080000000 > > | PHYS_OFFSET: 0x40000000 > > | CPU features: 0x00000000,68c167a1,cce6773f > > | Memory Limit: none > > | ---[ end Kernel panic - not syncing: panic stop irqoff test ]--- > > > > On arm64 *with* an NMI, this results in: > > I suppose a more interesting test scenario to show difference among > NMI stop IPI and regular stop IPI would be: > > - First put any CPU into hard lockup state via: > $ echo HARDLOCKUP > /sys/kernel/debug/provoke-crash/DIRECT > > - And then provoke following from other CPU: > $ echo PANIC_STOP_IRQOFF > /sys/kernel/debug/provoke-crash/DIRECT I don't follow. IIUC that's only going to test whether a HW watchdog can fire and reset the system? The PANIC_STOP_IRQOFF test has each CPU run panic_stop_irqoff_fn() with IRQs disabled, and if one CPU is stuck in the HARDLOCKUP test, we'll never get all CPUs into panic_stop_irqoff_fn(), and so all CPUs will be stuck with IRQs disabled, spinning. The PANIC_STOP_IRQOFF test itself tests the different between an NMI stop IPI and regular stop IPI, as the results in the commit message shows. Look for the line above that says: | SMP: failed to stop secondary CPUs 0-3 ... which is *not* present in the NMI case (though we don't have an explicit "stoppped all CPUs" message). > > > > | # echo PANIC_STOP_IRQOFF > /sys/kernel/debug/provoke-crash/DIRECT > > | lkdtm: Performing direct entry PANIC_STOP_IRQOFF > > | Kernel panic - not syncing: panic stop irqoff test > > | CPU: 1 PID: 19 Comm: migration/1 Not tainted 6.5.0-rc3-00077-ge6c782389895-dirty #4 > > | Hardware name: QEMU QEMU Virtual Machine, BIOS 0.0.0 02/06/2015 > > | Stopper: multi_cpu_stop+0x0/0x1a0 <- stop_machine_cpuslocked+0x158/0x1a4 > > | Call trace: > > | dump_backtrace+0x94/0xec > > | show_stack+0x18/0x24 > > | dump_stack_lvl+0x74/0xc0 > > | dump_stack+0x18/0x24 > > | panic+0x358/0x3e8 > > | lkdtm_PANIC+0x0/0x18 > > | multi_cpu_stop+0x9c/0x1a0 > > | cpu_stopper_thread+0x84/0x118 > > | smpboot_thread_fn+0x224/0x248 > > | kthread+0x114/0x118 > > | ret_from_fork+0x10/0x20 > > | SMP: stopping secondary CPUs > > | Kernel Offset: 0x55a9c0bc0000 from 0xffff800080000000 > > | PHYS_OFFSET: 0x40000000 > > | CPU features: 0x00000000,68c167a1,fce6773f > > | Memory Limit: none > > | ---[ end Kernel panic - not syncing: panic stop irqoff test ]--- > > > > Signed-off-by: Mark Rutland > > Cc: Douglas Anderson > > Cc: Kees Cook > > Cc: Stephen Boyd > Cc: Sumit Garg > > --- > > drivers/misc/lkdtm/bugs.c | 29 ++++++++++++++++++++++++++++- > > 1 file changed, 28 insertions(+), 1 deletion(-) > > > > I've tested this with the arm64 NMI IPI patches: > > > > https://lore.kernel.org/linux-arm-kernel/20230830191314.1618136-1-dianders@chromium.org/ > > > > Specifically, with the patch that uses an NMI for IPI_CPU_STOP and > > IPI_CPU_CRASH_STOP: > > > > https://lore.kernel.org/linux-arm-kernel/20230830121115.v12.5.Ifadbfd45b22c52edcb499034dd4783d096343260@changeid/ > > > > Mark. > > > > diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c > > index 3c95600ab2f71..368da8b83cd1c 100644 > > --- a/drivers/misc/lkdtm/bugs.c > > +++ b/drivers/misc/lkdtm/bugs.c > > @@ -6,12 +6,14 @@ > > * test source files. > > */ > > #include "lkdtm.h" > > +#include > > #include > > #include > > #include > > #include > > -#include > > #include > > +#include > > +#include > > > > #if IS_ENABLED(CONFIG_X86_32) && !IS_ENABLED(CONFIG_UML) > > #include > > @@ -73,6 +75,30 @@ static void lkdtm_PANIC(void) > > panic("dumptest"); > > } > > > > +static int panic_stop_irqoff_fn(void *arg) > > +{ > > + atomic_t *v = arg; > > + > > + /* > > + * Trigger the panic after all other CPUs have entered this function, > > + * so that they are guaranteed to have IRQs disabled. > > + */ > > + if (atomic_inc_return(v) == num_online_cpus()) > > + panic("panic stop irqoff test"); > > + > > + for (;;) > > + cpu_relax(); > > +} > > + > > +static void lkdtm_PANIC_STOP_IRQOFF(void) > > +{ > > + atomic_t v = ATOMIC_INIT(0); > > + > > + cpus_read_lock(); > > + stop_machine(panic_stop_irqoff_fn, &v, cpu_online_mask); > > + cpus_read_unlock(); > > stop_machine() does internally use cpus_read_{lock/unlock}(), is there > any need to have them here as well? For some reason I thought that stop_machine() copied the mask prior to calling cpus_read_lock(), and hance it was necessary to avoid the online mask changing, but from taking a look just now that's not the case. I'll drop the cpus_read_lock() .. cpus_read_unlock() here. Thanks, Mark.