From patchwork Fri Dec 10 18:41:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 12670685 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5CDD5C43217 for ; Fri, 10 Dec 2021 18:45:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233120AbhLJSsh (ORCPT ); Fri, 10 Dec 2021 13:48:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245562AbhLJSse (ORCPT ); Fri, 10 Dec 2021 13:48:34 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [IPv6:2604:1380:40e1:4800::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57F4CC061B38 for ; Fri, 10 Dec 2021 10:44:59 -0800 (PST) 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 sin.source.kernel.org (Postfix) with ESMTPS id A3D49CE2C90 for ; Fri, 10 Dec 2021 18:44:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 589FDC341CB; Fri, 10 Dec 2021 18:44:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1639161895; bh=jLrKauMo97jhxOy35VKRzK15Vz0tTJowtBEC7D/upGc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F2B9KUeOUjztaYL9fNQ0Uf9+lwmhOp3MC1hDCCWHToTERxRbILq+WTDIeIDfCVvnz CsLAEb6Bvnd91MjtjocOqEdx+bjjqaPfXaObH8CW3NTC5ZAWZW3coumncM0lBP5yOi P4w5/twX3EP1E9RoIqH5Iw1gaZd1jV4aUHIaklNogcLpVWj9jftp0t9lsxq2JRG4Nv 0dbxt623P+mTqMtaw0pXMovcyUPvh2awHd/NRvnwOBy1YsALul9fPEm+nKelB/DesP QCX+YLgVtKsA6qLHBWOYU+YlwkOOS3sxChnKEAVzZBfbU+FNutJvdl9hUZaNzvF1nJ bCAgmDbSdvy5w== From: Mark Brown To: Catalin Marinas , Will Deacon , Shuah Khan , Shuah Khan Cc: Alan Hayward , Luis Machado , Salil Akerkar , Basant Kumar Dwivedi , Szabolcs Nagy , linux-arm-kernel@lists.infradead.org, linux-kselftest@vger.kernel.org, Mark Brown Subject: [PATCH v7 27/37] arm64/sme: Save and restore streaming mode over EFI runtime calls Date: Fri, 10 Dec 2021 18:41:23 +0000 Message-Id: <20211210184133.320748-28-broonie@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211210184133.320748-1-broonie@kernel.org> References: <20211210184133.320748-1-broonie@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3623; h=from:subject; bh=jLrKauMo97jhxOy35VKRzK15Vz0tTJowtBEC7D/upGc=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBhs59T75M88oFp3XXYCMLvzif+Fo9rFzcyfxpqLgB8 f5GkBE2JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCYbOfUwAKCRAk1otyXVSH0FwQB/ sFsOBrna4IMO0mnHkGKhYz07vLkBSrM8omRT3WQpCMpNUBOBzElsO8kBL/xItu/WrIzen2G7YyzqKV kFcSYopuIclUuccLyE/QqZQonb7gvwJ/kh9JzK6BEaJUzu+1wUV8NGsZ/Kc1IN72yeHpYImavqzpJW nGnPDza6syB+nDVBzgL6KeOySlMbunCxh8C6SPKTlyMZiKs8FqEUmGBMrpeLls/jmeepp6L/Yjlqsc 9TAsfXSrm/FZRe8XoODq4HhB+tGqkiM0+YVl05RqaJvUnT7IApZ2UQEUjGlkv8QgM8qtNx17twy1hX I1/vSF0VSpkDn7gX5vlZgLUzd/R0Bz X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org When saving and restoring the floating point state over an EFI runtime call ensure that we handle streaming mode, only handling FFR if we are not in streaming mode and ensuring that we are in normal mode over the call into runtime services. We currently assume that ZA will not be modified by runtime services, the specification is not yet finalised so this may need updating if that changes. Signed-off-by: Mark Brown --- arch/arm64/kernel/fpsimd.c | 47 +++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index bb174c1b8ae0..7ad55fa54d03 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1061,21 +1061,25 @@ int vec_verify_vq_map(enum vec_type type) static void __init sve_efi_setup(void) { - struct vl_info *info = &vl_info[ARM64_VEC_SVE]; + int max_vl = 0; + int i; if (!IS_ENABLED(CONFIG_EFI)) return; + for (i = 0; i < ARRAY_SIZE(vl_info); i++) + max_vl = max(vl_info[i].max_vl, max_vl); + /* * alloc_percpu() warns and prints a backtrace if this goes wrong. * This is evidence of a crippled system and we are returning void, * so no attempt is made to handle this situation here. */ - if (!sve_vl_valid(info->max_vl)) + if (!sve_vl_valid(max_vl)) goto fail; efi_sve_state = __alloc_percpu( - SVE_SIG_REGS_SIZE(sve_vq_from_vl(info->max_vl)), SVE_VQ_BYTES); + SVE_SIG_REGS_SIZE(sve_vq_from_vl(max_vl)), SVE_VQ_BYTES); if (!efi_sve_state) goto fail; @@ -1857,6 +1861,7 @@ EXPORT_SYMBOL(kernel_neon_end); static DEFINE_PER_CPU(struct user_fpsimd_state, efi_fpsimd_state); static DEFINE_PER_CPU(bool, efi_fpsimd_state_used); static DEFINE_PER_CPU(bool, efi_sve_state_used); +static DEFINE_PER_CPU(bool, efi_sm_state); /* * EFI runtime services support functions @@ -1891,12 +1896,28 @@ void __efi_fpsimd_begin(void) */ if (system_supports_sve() && likely(efi_sve_state)) { char *sve_state = this_cpu_ptr(efi_sve_state); + bool ffr = true; + u64 svcr; __this_cpu_write(efi_sve_state_used, true); + /* If we are in streaming mode don't touch FFR */ + if (system_supports_sme()) { + svcr = read_sysreg_s(SYS_SVCR_EL0); + + ffr = svcr & SYS_SVCR_EL0_SM_MASK; + + __this_cpu_write(efi_sm_state, ffr); + } + sve_save_state(sve_state + sve_ffr_offset(sve_max_vl()), &this_cpu_ptr(&efi_fpsimd_state)->fpsr, - true); + ffr); + + if (system_supports_sme()) + sysreg_clear_set_s(SYS_SVCR_EL0, + SYS_SVCR_EL0_SM_MASK, 0); + } else { fpsimd_save_state(this_cpu_ptr(&efi_fpsimd_state)); } @@ -1919,11 +1940,25 @@ void __efi_fpsimd_end(void) if (system_supports_sve() && likely(__this_cpu_read(efi_sve_state_used))) { char const *sve_state = this_cpu_ptr(efi_sve_state); + bool ffr = true; + + /* + * Restore streaming mode; EFI calls are + * normal function calls so should not return in + * streaming mode. + */ + if (system_supports_sme()) { + if (__this_cpu_read(efi_sm_state)) { + sysreg_clear_set_s(SYS_SVCR_EL0, + 0, + SYS_SVCR_EL0_SM_MASK); + ffr = false; + } + } - sve_set_vq(sve_vq_from_vl(sve_get_vl()) - 1); sve_load_state(sve_state + sve_ffr_offset(sve_max_vl()), &this_cpu_ptr(&efi_fpsimd_state)->fpsr, - true); + ffr); __this_cpu_write(efi_sve_state_used, false); } else {