From patchwork Wed Mar 6 23:14:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 13584758 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 CAC50C54E41 for ; Wed, 6 Mar 2024 23:15:58 +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:Cc:To:In-Reply-To:References:Message-Id :MIME-Version:Subject:Date:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=NPZUGIhfrkYxw4CvF4cAxvPo1SLbGdn4UDCx/4t9/nU=; b=m3DAtu+tbVugGH MdkMFVUOE3uBnSHzXeiaxYlTEzjHfT7u4ncDmBir0GyhWyIBgUUwVhWXxNyOjDyNiEmgN742q3u6x dPvK68kOt12GNvBU7nuTmUnt8J6BLI1vRvkDqQbVmX39VPfcLJ4HVg5cayKk2iHVWUjj3Sp1rjqGq +HGZPFDRhWpsGlgTcRbGj0LRToFRmLfoV2zJh72nIKwnvNEx8+ofqlJdhFbFcDeD/zF/oEska4iWD uff5brjYuIhjlvMIBBCuVp0xsXOlXjv1r4m45A8iKx8oLfCw/Qp0mm92/KwXC1K4Ch8J//rKrL+Vp 2pcpHs3qLzOxPbKM2sQw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1ri0UB-00000002C0i-01LJ; Wed, 06 Mar 2024 23:15:43 +0000 Received: from dfw.source.kernel.org ([2604:1380:4641:c500::1]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1ri0U5-00000002Bvt-02pW for linux-arm-kernel@lists.infradead.org; Wed, 06 Mar 2024 23:15:38 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 8896061B7F; Wed, 6 Mar 2024 23:15:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A371C43399; Wed, 6 Mar 2024 23:15:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1709766936; bh=+pr8+N8Az9rPBwlL16ghSk5vvthU1BeA1Gwu1lfKkCg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kHwP+rVmCsepQqLkEQyk4lUXm6ReCdE17//+25LSDaEkK3ka2riwBi5IttqzI3rzP tN+4fDtKLUNfHEH+81na8+B7wpjyPzjbR1yROilWyulYU5LZSh3qbPJTGd75aOy4C1 RDYg+NhFCPdz5WiD69Ujyosh3R0C//8JNakw/W2O11XN2NbpwLgPL7J5qKEOXC5s0+ NV7sJuV9hHrPSL/rBTV+Lb762smnsbkd38geirLXsRAZveQxSuRZwgVntCxZVPtwlS RZODYAvDa5nKyXliGx3q4o3EKk0t7jxYFo+ZifZx/EE42l1YVspXveLRYaZyEicEc5 7Xne5ZIihjK7w== From: Mark Brown Date: Wed, 06 Mar 2024 23:14:49 +0000 Subject: [PATCH v5 4/9] arm64/signal: Add FPMR signal handling MIME-Version: 1.0 Message-Id: <20240306-arm64-2023-dpisa-v5-4-c568edc8ed7f@kernel.org> References: <20240306-arm64-2023-dpisa-v5-0-c568edc8ed7f@kernel.org> In-Reply-To: <20240306-arm64-2023-dpisa-v5-0-c568edc8ed7f@kernel.org> To: Catalin Marinas , Will Deacon , Marc Zyngier , Oliver Upton , James Morse , Suzuki K Poulose , Jonathan Corbet , Shuah Khan Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Dave Martin , kvmarm@lists.linux.dev, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.13-dev-a684c X-Developer-Signature: v=1; a=openpgp-sha256; l=4176; i=broonie@kernel.org; h=from:subject:message-id; bh=+pr8+N8Az9rPBwlL16ghSk5vvthU1BeA1Gwu1lfKkCg=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBl6PkENg896N6GZy2rJbMrdI8pLee2Tmix6yiToeY1 nRt+q7qJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCZej5BAAKCRAk1otyXVSH0P1uB/ 9guHvWD79Y64i8lVUZafBNMPxSE/fv6mcqmNulwsbEgsNczP1kK4GAuiMaq+sWed9R3PMgitQsy90A xDU+8WRC4GU+iT2sJS8ypDIMNOwOZiIkVUhMotSomOAREHFNCoFnCME4jS3AV+pAqj07R1c11Z8NgX 9qN14PhgqW5EUmCO4AwQ7le0zyLyHIJjePCyu38u4g+wQ6tsVL/1qVPxninpAWJtRZk2dCGFpGt4SU fk+gxE0wMK0+J1+27pIFan9zcuJKai6f6Y7KGB+jlEobZoKK1Q1Hu5yVt9YX7FkLLZ241OEifeJQQn YoigNtyytavHJAa6NFGqreycsqIMfg X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240306_151537_192081_EDD9016D X-CRM114-Status: GOOD ( 16.52 ) 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 Expose FPMR in the signal context on systems where it is supported. The kernel validates the exact size of the FPSIMD registers so we can't readily add it to fpsimd_context without disruption. Signed-off-by: Mark Brown --- arch/arm64/include/uapi/asm/sigcontext.h | 8 +++++ arch/arm64/kernel/signal.c | 59 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h index f23c1dc3f002..8a45b7a411e0 100644 --- a/arch/arm64/include/uapi/asm/sigcontext.h +++ b/arch/arm64/include/uapi/asm/sigcontext.h @@ -152,6 +152,14 @@ struct tpidr2_context { __u64 tpidr2; }; +/* FPMR context */ +#define FPMR_MAGIC 0x46504d52 + +struct fpmr_context { + struct _aarch64_ctx head; + __u64 fpmr; +}; + #define ZA_MAGIC 0x54366345 struct za_context { diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 0e8beb3349ea..460823baa603 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -60,6 +60,7 @@ struct rt_sigframe_user_layout { unsigned long tpidr2_offset; unsigned long za_offset; unsigned long zt_offset; + unsigned long fpmr_offset; unsigned long extra_offset; unsigned long end_offset; }; @@ -182,6 +183,8 @@ struct user_ctxs { u32 za_size; struct zt_context __user *zt; u32 zt_size; + struct fpmr_context __user *fpmr; + u32 fpmr_size; }; static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) @@ -227,6 +230,33 @@ static int restore_fpsimd_context(struct user_ctxs *user) return err ? -EFAULT : 0; } +static int preserve_fpmr_context(struct fpmr_context __user *ctx) +{ + int err = 0; + + current->thread.uw.fpmr = read_sysreg_s(SYS_FPMR); + + __put_user_error(FPMR_MAGIC, &ctx->head.magic, err); + __put_user_error(sizeof(*ctx), &ctx->head.size, err); + __put_user_error(current->thread.uw.fpmr, &ctx->fpmr, err); + + return err; +} + +static int restore_fpmr_context(struct user_ctxs *user) +{ + u64 fpmr; + int err = 0; + + if (user->fpmr_size != sizeof(*user->fpmr)) + return -EINVAL; + + __get_user_error(fpmr, &user->fpmr->fpmr, err); + if (!err) + write_sysreg_s(fpmr, SYS_FPMR); + + return err; +} #ifdef CONFIG_ARM64_SVE @@ -590,6 +620,7 @@ static int parse_user_sigframe(struct user_ctxs *user, user->tpidr2 = NULL; user->za = NULL; user->zt = NULL; + user->fpmr = NULL; if (!IS_ALIGNED((unsigned long)base, 16)) goto invalid; @@ -684,6 +715,17 @@ static int parse_user_sigframe(struct user_ctxs *user, user->zt_size = size; break; + case FPMR_MAGIC: + if (!system_supports_fpmr()) + goto invalid; + + if (user->fpmr) + goto invalid; + + user->fpmr = (struct fpmr_context __user *)head; + user->fpmr_size = size; + break; + case EXTRA_MAGIC: if (have_extra_context) goto invalid; @@ -806,6 +848,9 @@ static int restore_sigframe(struct pt_regs *regs, if (err == 0 && system_supports_tpidr2() && user.tpidr2) err = restore_tpidr2_context(&user); + if (err == 0 && system_supports_fpmr() && user.fpmr) + err = restore_fpmr_context(&user); + if (err == 0 && system_supports_sme() && user.za) err = restore_za_context(&user); @@ -928,6 +973,13 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, } } + if (system_supports_fpmr()) { + err = sigframe_alloc(user, &user->fpmr_offset, + sizeof(struct fpmr_context)); + if (err) + return err; + } + return sigframe_alloc_end(user); } @@ -983,6 +1035,13 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user, err |= preserve_tpidr2_context(tpidr2_ctx); } + /* FPMR if supported */ + if (system_supports_fpmr() && err == 0) { + struct fpmr_context __user *fpmr_ctx = + apply_user_offset(user, user->fpmr_offset); + err |= preserve_fpmr_context(fpmr_ctx); + } + /* ZA state if present */ if (system_supports_sme() && err == 0 && user->za_offset) { struct za_context __user *za_ctx =