From patchwork Wed Jul 31 13:36:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Deacon X-Patchwork-Id: 13748817 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D40A2C3DA7F for ; Wed, 31 Jul 2024 13:36:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=r78zw5SIvw7IdMBhtWffZBpLw9Capyvrayl953nGBjE=; b=FzN3frinziIwMCJDJ+lABjILmo GIBvlCDbsWW6uCVyOM+avYVUDCBYGqJW1bevvcWWbZUzejA/G90aJzxAVezSG2MEIERRN9CkP+hCj 5JAUDxG5RzayHkeI66+kshaGJ9yY996Lfs19EkXHp+P5UWKr3oVobzXnRLupgBsCr6VoX/XUVacgC XAS42Yo8cNTuHu6E5Q2tOEVvpV449UkKZcCwfxOUsEd15XRFZTFDpcyVa4QXZLk5Ox72M5SQR6Vev Nmc3iHkieWWSHYRvMo5qk4B+fwz/NYvGKuZgwE2PMKtRRn5XZKERJdgyruf0Enev1S4TJYrP2EmY5 ZfYb+g/w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZ9VP-00000001K8T-38O5; Wed, 31 Jul 2024 13:36:39 +0000 Received: from sin.source.kernel.org ([2604:1380:40e1:4800::1]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sZ9Uw-00000001K5M-1NYb for linux-arm-kernel@lists.infradead.org; Wed, 31 Jul 2024 13:36:11 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id C12A9CE169C; Wed, 31 Jul 2024 13:36:07 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C92A8C116B1; Wed, 31 Jul 2024 13:36:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1722432967; bh=Zf4/x12q1InHJDqlICcsMZdtd9Uvd7cajor3rfznYxU=; h=From:To:Cc:Subject:Date:From; b=QN/D4gjMVtn0R3pgmjv+o/qFMCwJXZO95DdV1exX0ut72zTYMhnJI4xu+5f3OQmC2 1zIN+s1fSFb32Hew0+MnB+Z5O4X8x4hP4ePDiChxjVQv2Dw27BJ//WHH8mTydC6iIP WgbRnNtHahnpCsyjM31fMlydmYd/svJnNxZd5TKPjWMI8cYYfzP5l8rUp7/T8CO2bn abxMRjGnIMvTnqhS4ySnK4xh1+pXjfebL6kIPSV88bCQoSl0i+44nADSe7GhCqRx1g 5plsb+xL03P+bq4LeBjX462AN6U/KIqDE6+ypSbDpAinNJj+koYSzTPn+UlnYNJP0e 1jgcxAUJR4NSQ== From: Will Deacon To: linux-arm-kernel@lists.infradead.org Cc: Will Deacon , Catalin Marinas , Alexander Potapenko , Mark Rutland , Marc Zyngier Subject: [RFC PATCH] arm64: jump_label: Ensure patched jump_labels are visible to all CPUs Date: Wed, 31 Jul 2024 14:36:01 +0100 Message-Id: <20240731133601.3073-1-will@kernel.org> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240731_063610_737718_7DD51FBC X-CRM114-Status: GOOD ( 19.51 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Although the Arm architecture permits concurrent modification and execution of NOP and branch instructions, it still requires some synchronisation to ensure that other CPUs consistently execute the newly written instruction: > When the modified instructions are observable, each PE that is > executing the modified instructions must execute an ISB or perform a > context synchronizing event to ensure execution of the modified > instructions Prior to commit f6cc0c501649 ("arm64: Avoid calling stop_machine() when patching jump labels"), the arm64 jump_label patching machinery performed synchronisation using stop_machine() after each modification, however this was problematic when flipping static keys from atomic contexts (namely, the arm_arch_timer CPU hotplug startup notifier) and so we switched to the _nosync() patching routines to avoid "scheduling while atomic" BUG()s during boot. In hindsight, the analysis of the issue in f6cc0c501649 isn't quite right: it cites the use of IPIs in the default patching routines as the cause of the lockup, whereas stop_machine() does not rely on IPIs and the I-cache invalidation is performed using __flush_icache_range(), which elides the call to kick_all_cpus_sync(). In fact, the blocking wait for other CPUs is what triggers the BUG() and the problem remains even after f6cc0c501649, for example because we could block on the jump_label_mutex. Eventually, the arm_arch_timer driver was fixed to avoid the static key entirely in commit a862fc2254bd ("clocksource/arm_arch_timer: Remove use of workaround static key"). This all leaves the jump_label patching code in a funny situation on arm64 as we do not synchronise with other CPUs to reduce the likelihood of a bug which no longer exists. Consequently, toggling a static key on one CPU cannot be assumed to take effect on other CPUs, leading to potential issues, for example with missing preempt notifiers. Rather than revert f6cc0c501649 and go back to stop_machine() for each patch site, implement arch_jump_label_transform_apply() and kick all the other CPUs with an IPI at the end of patching. Cc: Catalin Marinas Cc: Alexander Potapenko Cc: Mark Rutland Cc: Marc Zyngier Fixes: f6cc0c501649 ("arm64: Avoid calling stop_machine() when patching jump labels") Signed-off-by: Will Deacon Reviewed-by: Catalin Marinas Reviewed-by: Marc Zyngier --- arch/arm64/include/asm/jump_label.h | 1 + arch/arm64/kernel/jump_label.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h index 4e753908b801..a0a5bbae7229 100644 --- a/arch/arm64/include/asm/jump_label.h +++ b/arch/arm64/include/asm/jump_label.h @@ -13,6 +13,7 @@ #include #include +#define HAVE_JUMP_LABEL_BATCH #define JUMP_LABEL_NOP_SIZE AARCH64_INSN_SIZE #define JUMP_TABLE_ENTRY(key, label) \ diff --git a/arch/arm64/kernel/jump_label.c b/arch/arm64/kernel/jump_label.c index faf88ec9c48e..f63ea915d6ad 100644 --- a/arch/arm64/kernel/jump_label.c +++ b/arch/arm64/kernel/jump_label.c @@ -7,11 +7,12 @@ */ #include #include +#include #include #include -void arch_jump_label_transform(struct jump_entry *entry, - enum jump_label_type type) +bool arch_jump_label_transform_queue(struct jump_entry *entry, + enum jump_label_type type) { void *addr = (void *)jump_entry_code(entry); u32 insn; @@ -25,4 +26,10 @@ void arch_jump_label_transform(struct jump_entry *entry, } aarch64_insn_patch_text_nosync(addr, insn); + return true; +} + +void arch_jump_label_transform_apply(void) +{ + kick_all_cpus_sync(); }