From patchwork Fri Jun 16 10:31:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 13282599 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 EDF9DEB64D8 for ; Fri, 16 Jun 2023 10:32:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:Cc :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=wWI3tlI8W2z3weG3evou9ftT8XoJGkVWunaz0VXZEyM=; b=IljoRgPXH5OWVy mPJC22rxotrk1EkR7wizkPiOUdhxms9up6DTo6ZzKiOuKzvT8Sbq6xlStVh1CV8FgWiOX5XBD7DIx G4C2BniP1oMXu55KuK3iWPqcFIPjoBxAnxDVDllzTXl3BVIYiP5jlxiOBJFKzwvalSvxj+y/XwjJ5 wVkEu8R3NBumBvGkym0aa7yzHF9VSPCgQ/xeU5SWKGdF4ZV7QyXLwo/boFwHdCHq8c4ywOllq4UxU S/xXQqipkNYQa5N6Eyjtrjyj5SghnMXrbpchSpVZw8VCLT5HrIt3j0/pQzBDvBIKY+QkKYwAuTw7q 3Fi8LwnEy6txm98pHdIg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qA6kR-0004Oc-03; Fri, 16 Jun 2023 10:32:07 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qA6kO-0004MK-1C for linux-arm-kernel@lists.infradead.org; Fri, 16 Jun 2023 10:32:06 +0000 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 6627E1FB; Fri, 16 Jun 2023 03:32:40 -0700 (PDT) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B75773F5A1; Fri, 16 Jun 2023 03:31:55 -0700 (PDT) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org, Catalin Marinas Cc: mark.rutland@arm.com, will@kernel.org Subject: [PATCH] arm64: alternatives: make clean_dcache_range_nopatch() noinstr-safe Date: Fri, 16 Jun 2023 11:31:50 +0100 Message-Id: <20230616103150.1238132-1-mark.rutland@arm.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230616_033204_474167_07E62967 X-CRM114-Status: GOOD ( 16.58 ) 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 When patching kernel alternatives, we need to be careful not to execute kernel code which is itself subject to patching. In general, if code is executed after the instructions in memory have been patched but prior to the cache maintenance and barriers completing, it could lead to UNPREDICTABLE results. As our regular cache maintenance routines are patched with alternatives, we have a clean_dcache_range_nopatch() function which is *intended* to avoid patchable code and therefore supposed to be safe in the middle of patching alternatives. Unfortunately, it's not marked as 'noinstr', and so can be instrumented with patchable code. Additionally, it calls read_sanitised_ftr_reg() (which may be instrumented with patchable code) to find the sanitized value of CTR_EL0.DminLine, and is therefore not safe to call during patching. Luckily, since commit: 675b0563d6b26aa9 ("arm64: cpufeature: expose arm64_ftr_reg struct for CTR_EL0") ... we can read the sanitised CTR_EL0 value directly, and avoid the call to read_sanitised_ftr_reg(). This patch marks clean_dcache_range_nopatch() as noinstr, and has it read the sanitized CTR_EL0 value directly, avoiding the issues above. As a bonus, this is also an optimization. As read_sanitised_ftr_reg() performs a binary search to find the CTR_EL0 value, reading the value directly avoids this binary search per applied alternative, avoiding some unnecessary work. Signed-off-by: Mark Rutland Cc: Catalin Marinas Cc: Will Deacon --- arch/arm64/kernel/alternative.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) Hi Catalin, This is part of a larger noinstr-safety cleanup that I'm trying to handle for the alternatives and insn patching code. The rest of that isn't ready yet, and I don't want to force that through this late (since e.g. it requires some major rework to the aarch64_insn_*() code), but as this patch is simple and also an optimization, I'd like to get it out of the way now if you're happy to pick it up. Mark. diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c index 53d13b2e5f59e..8ff6610af4966 100644 --- a/arch/arm64/kernel/alternative.c +++ b/arch/arm64/kernel/alternative.c @@ -121,11 +121,11 @@ static noinstr void patch_alternative(struct alt_instr *alt, * accidentally call into the cache.S code, which is patched by us at * runtime. */ -static void clean_dcache_range_nopatch(u64 start, u64 end) +static noinstr void clean_dcache_range_nopatch(u64 start, u64 end) { u64 cur, d_size, ctr_el0; - ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0); + ctr_el0 = arm64_ftr_reg_ctrel0.sys_val; d_size = 4 << cpuid_feature_extract_unsigned_field(ctr_el0, CTR_EL0_DminLine_SHIFT); cur = start & ~(d_size - 1);