From nobody Sat Oct 4 00:26:52 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A08E31D5CC9; Fri, 22 Aug 2025 01:54:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827672; cv=none; b=ft/zB6rcdBTqMOP1xmHDCe6YbGCmv7FAn3XSdCuPmRNWNG+a5Y6sT7KkB6603FUuyhOjoR0E1WRpp9GHCtUHk0+sOPH6gCDbzbmCTZtFdlqAaYNBE1Ngi48GT4lHwuWUpWGy96cy5hvPB8mzZMqMto7uXplDeaJjwN/DChfILSs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827672; c=relaxed/simple; bh=G6Ht9INfK364jYp0ofZOIq49bsCw7bcFjAmT7TRHKx8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WIcF8ld1dgChHB3DpTgxSvUjc8hdENbEJxITJUX/N2M2OTyxYu3J76CTAK+DCOg9kziYm8aiI99StLkqcd+I/2uIJmjUaBADj/BilneyDQehtsCZCH3NR+hyDJQ6hBx2YFTLcYV8dSUdRN4N7jp7rIJa5Ut+xcGkmksGSg+342k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DM0M271g; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DM0M271g" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3971BC116B1; Fri, 22 Aug 2025 01:54:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827671; bh=G6Ht9INfK364jYp0ofZOIq49bsCw7bcFjAmT7TRHKx8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DM0M271g5lQPwotvwbxFy0I9y5Z+lweO6zmFZ2UMsOPxBOBfO/wvIcnPwF7Jvm5Om cgOs1GZQuDSjmo7qT4i3KLJ4/xWJjDZCa7TsascPFOvdzndZUfBJha8ezQqaTcb8EF 1jDPlNoF+lbfB/qLl9aG2p0CF+hcQ25MBtAZtp1pSn3tYGyNf/BkDwHamRQwQNCjbB /ZC4+uPLzDN6YqkX60p6SMzmvYX0zncJtvEwetn4Y60gdJUJJeq2T2W3DtU/soGWrM EjA6ZvGxnMFE4s4huyW9gpE9j9tG4VAP4pQX5EaD4U/dftCJjMbdFNVRGdzgmEBGDW f5UCNCFgiGggA== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:30 +0100 Subject: [PATCH v7 01/29] arm64/sysreg: Update SMIDR_EL1 to DDI0601 2025-06 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-1-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=933; i=broonie@kernel.org; h=from:subject:message-id; bh=G6Ht9INfK364jYp0ofZOIq49bsCw7bcFjAmT7TRHKx8=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop825gBpk0joPx8ZrHWCZPK5OkpZBjPVq+c7zj Kis9wVS0myJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNuQAKCRAk1otyXVSH 0KlSB/0Y9abY+riGwYWOySjPbCGGTymnhIrc7+c9wMa2G6eLR/t4z92bKXn7x4Eq5vcnkWyZPzA y0IG/CFXetslgbuLUYKUEcwfJxVLJOLlIuwUN5nYf5AYZKNwPGARQthDiEEqFkFctEaed0JCn6f yw9mpvyPjnCPFsFS4hhGSldHvGOJNTfUfa16PIo+nxDcC6FjyCKx9Hb6HkIXpcVXtTkVfI/Ddeg /w/uyo1fcAQAaFnMrevZh98pynztRoQ+F4bYJYZZtQHcTxdJL5GS3J++UQNPz087tDXv9oSFyby 24efFVecbhL51mr+nsH1WR3RYHO7RWnQlVvdDRPnS+JcB4fh X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Update the definiton of SMIDR_EL1 in the sysreg definition to reflect the information in DD0601 2025-06. This includes somewhat more generic ways of describing the sharing of SMCUs, more information on supported priorities and provides additional resolution for describing affinity groups. Signed-off-by: Mark Brown --- arch/arm64/tools/sysreg | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg index 696ab1f32a67..9a1adb234ff0 100644 --- a/arch/arm64/tools/sysreg +++ b/arch/arm64/tools/sysreg @@ -3659,11 +3659,15 @@ Field 3:0 BS EndSysreg =20 Sysreg SMIDR_EL1 3 1 0 0 6 -Res0 63:32 +Res0 63:60 +Field 59:56 NSMC +Field 55:52 HIP +Field 51:32 AFFINITY2 Field 31:24 IMPLEMENTER Field 23:16 REVISION Field 15 SMPS -Res0 14:12 +Field 14:13 SH +Res0 12 Field 11:0 AFFINITY EndSysreg =20 --=20 2.39.5 From nobody Sat Oct 4 00:26:52 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B373E1E1DE5; Fri, 22 Aug 2025 01:54:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827675; cv=none; b=Hg1OKy9V3ZI2J9/WOB939kam7hFZeIBALe9Fztm4rQLU7LlS+6LGjPYIip364OtSMe59C3Lx+TwRxDpPwHlqShbfv0UpW2CHPk54kt7+UArtJAP34KVtZ5+NZkqrb9GcVEjW3n/czNKWwjA6uwNyL5xwc6zPTfv0Fva/NDrSnq4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827675; c=relaxed/simple; bh=84pzZs2B5XlM7NI3iiTFhdL+enlb8CJyDRVL7RoB/Dw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JqB6UAzz+k8WrFEpCmD0vbc2zCIb3u7p90xITpYGm5lZptBRFyCR1Oyfzeeao8ecKFJiXV2rCIOag8TEOVzNybeTVbFz4luvgX0c28tUxrsWsH3h/fLXrXCAEfEVmgkFr/w77uN5NQF8/9VZuYXoTJ8/Is6nGB8FEFLxnzyNDYQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EVqD8t7x; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EVqD8t7x" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EBB7EC4CEED; Fri, 22 Aug 2025 01:54:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827675; bh=84pzZs2B5XlM7NI3iiTFhdL+enlb8CJyDRVL7RoB/Dw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EVqD8t7xUqtp+46PXh0747M9FpBzIXex5HnaoyoCyvoGW1nCrRzMHSpowAyDIAksA v2iCcvstKET6KQURX2onEQ32tGtzmjYaaa4kIIj9NBDzCGY5L2qpW6HmuIkiTexZRX wD6j9LDhw6+ypi4AYQ1JFlGI2D5enOvyg/HYWqzuSECDh7rA/EVt9Tzvr1mbWwxVSG DeCDy5+ConK46ehEYZzNypSYShI4x3CviLlkF4RbzWupOMHO8RV9YK7JXJlncDatrK V/NaZkYAAN9riBBlnAMRK1AsWrPke7AT//aLXXz8vUu9XspaNvCMh8T2+wgOabrrh4 l/yryscN0oR8g== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:31 +0100 Subject: [PATCH v7 02/29] arm64/fpsimd: Update FA64 and ZT0 enables when loading SME state Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-2-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=5757; i=broonie@kernel.org; h=from:subject:message-id; bh=84pzZs2B5XlM7NI3iiTFhdL+enlb8CJyDRVL7RoB/Dw=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop826WMYDD5lbJtIlfiiBnzScUFkt/aw+Wi65i yiJxBv3f1qJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNugAKCRAk1otyXVSH 0PeuB/478qzgOWc2cTrGODeWlk0OSICdhP4p8N5DHuAfi60Wd8pnDvddo/Ci9kqHsEpTw8PzJ+4 bn/ko0DANG0Bbjps+kGhHpYNm7HFuYBqkzSXJMCCTTMh3QDBIhoO/bJrLHFnYOTz8bldRtOvZQD Oafc+VzavKENi4Wt1wNj53BJ+EWtV1tVo3HCfTvLciQcCeUWxXH50ZLSXe3JNt+O9KAvFYg/H+x Lej6g5scW08yqTIhNP3qcanrh6yGpSaw0qMi1sc4Yn1G+CI1xdpo0AQkdMBa1H4s//J8XYasWel AlU3+3annWHqAfFDhNqzSLXb2rCi9GkXdouozkS6fjYqb1ll X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Currently we enable EL0 and EL1 access to FA64 and ZT0 at boot and leave them enabled throughout the runtime of the system. When we add KVM support we will need to make this configuration dynamic, these features may be disabled for some KVM guests. Since the host kernel saves the floating point state for non-protected guests and we wish to avoid KVM having to reload the floating point state needlessly on guest reentry let's move the configuration of these enables to the floating point state reload. We provide a helper which does the configuration as part of a read/modify/write operation along with the configuration of the task VL, then update the floating point state load and SME access trap to use it. We also remove the setting of the enable bits from the CPU feature identification and resume paths. There will be a small overhead from setting the enables one at a time but this should be negligable in the context of the state load or access trap. In order to avoid compiler warnings due to unused variables in !CONFIG_ARM64_SME cases we avoid storing the vector length in temporary variables. Signed-off-by: Mark Brown --- arch/arm64/include/asm/fpsimd.h | 14 ++++++++++++ arch/arm64/kernel/cpufeature.c | 2 -- arch/arm64/kernel/fpsimd.c | 47 +++++++++++--------------------------= ---- 3 files changed, 26 insertions(+), 37 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index b8cf0ea43cc0..b4359f942621 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -428,6 +428,18 @@ static inline size_t sme_state_size(struct task_struct= const *task) return __sme_state_size(task_get_sme_vl(task)); } =20 +#define sme_cond_update_smcr(vl, fa64, zt0, reg) \ + do { \ + u64 __old =3D read_sysreg_s((reg)); \ + u64 __new =3D vl; \ + if (fa64) \ + __new |=3D SMCR_ELx_FA64; \ + if (zt0) \ + __new |=3D SMCR_ELx_EZT0; \ + if (__old !=3D __new) \ + write_sysreg_s(__new, (reg)); \ + } while (0) + #else =20 static inline void sme_user_disable(void) { BUILD_BUG(); } @@ -456,6 +468,8 @@ static inline size_t sme_state_size(struct task_struct = const *task) return 0; } =20 +#define sme_cond_update_smcr(val, fa64, zt0, reg) do { } while (0) + #endif /* ! CONFIG_ARM64_SME */ =20 /* For use by EFI runtime services calls only */ diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9ad065f15f1d..85d091d3b279 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -2961,7 +2961,6 @@ static const struct arm64_cpu_capabilities arm64_feat= ures[] =3D { .type =3D ARM64_CPUCAP_SYSTEM_FEATURE, .capability =3D ARM64_SME_FA64, .matches =3D has_cpuid_feature, - .cpu_enable =3D cpu_enable_fa64, ARM64_CPUID_FIELDS(ID_AA64SMFR0_EL1, FA64, IMP) }, { @@ -2969,7 +2968,6 @@ static const struct arm64_cpu_capabilities arm64_feat= ures[] =3D { .type =3D ARM64_CPUCAP_SYSTEM_FEATURE, .capability =3D ARM64_SME2, .matches =3D has_cpuid_feature, - .cpu_enable =3D cpu_enable_sme2, ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, SME, SME2) }, #endif /* CONFIG_ARM64_SME */ diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index c37f02d7194e..653c0dec6b18 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -392,11 +392,15 @@ static void task_fpsimd_load(void) =20 /* Restore SME, override SVE register configuration if needed */ if (system_supports_sme()) { - unsigned long sme_vl =3D task_get_sme_vl(current); - - /* Ensure VL is set up for restoring data */ + /* + * Ensure VL is set up for restoring data. KVM might + * disable subfeatures so we reset them each time. + */ if (test_thread_flag(TIF_SME)) - sme_set_vq(sve_vq_from_vl(sme_vl) - 1); + sme_cond_update_smcr(sve_vq_from_vl(task_get_sme_vl(current)) - 1, + system_supports_fa64(), + system_supports_sme2(), + SYS_SMCR_EL1); =20 write_sysreg_s(current->thread.svcr, SYS_SVCR); =20 @@ -1237,26 +1241,6 @@ void cpu_enable_sme(const struct arm64_cpu_capabilit= ies *__always_unused p) isb(); } =20 -void cpu_enable_sme2(const struct arm64_cpu_capabilities *__always_unused = p) -{ - /* This must be enabled after SME */ - BUILD_BUG_ON(ARM64_SME2 <=3D ARM64_SME); - - /* Allow use of ZT0 */ - write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_EZT0_MASK, - SYS_SMCR_EL1); -} - -void cpu_enable_fa64(const struct arm64_cpu_capabilities *__always_unused = p) -{ - /* This must be enabled after SME */ - BUILD_BUG_ON(ARM64_SME_FA64 <=3D ARM64_SME); - - /* Allow use of FA64 */ - write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_FA64_MASK, - SYS_SMCR_EL1); -} - void __init sme_setup(void) { struct vl_info *info =3D &vl_info[ARM64_VEC_SME]; @@ -1300,17 +1284,9 @@ void __init sme_setup(void) =20 void sme_suspend_exit(void) { - u64 smcr =3D 0; - if (!system_supports_sme()) return; =20 - if (system_supports_fa64()) - smcr |=3D SMCR_ELx_FA64; - if (system_supports_sme2()) - smcr |=3D SMCR_ELx_EZT0; - - write_sysreg_s(smcr, SYS_SMCR_EL1); write_sysreg_s(0, SYS_SMPRI_EL1); } =20 @@ -1425,9 +1401,10 @@ void do_sme_acc(unsigned long esr, struct pt_regs *r= egs) WARN_ON(1); =20 if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { - unsigned long vq_minus_one =3D - sve_vq_from_vl(task_get_sme_vl(current)) - 1; - sme_set_vq(vq_minus_one); + sme_cond_update_smcr(sve_vq_from_vl(task_get_sme_vl(current)) - 1, + system_supports_fa64(), + system_supports_sme2(), + SYS_SMCR_EL1); =20 fpsimd_bind_task_to_cpu(); } else { --=20 2.39.5 From nobody Sat Oct 4 00:26:52 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 740B21F130B; Fri, 22 Aug 2025 01:54:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827679; cv=none; b=CcKZQP7bpIcIZUkH0setYW84UDoDBtkz/Eg4A4Gik7MxVkKnkc5MIWtuNDv8klT0SV78atYDHFqCrK3LaO8EzyXVLSkeF+HEBM+RxRj98MrKcQ3AmsB1GzL2vj8bUBfdBIVEpjZpCiJ1CZHVRiSLkHSCyN1p2xSA7QuHjHNJ7N8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827679; c=relaxed/simple; bh=tDa3Sk8XxTm+Aaxc1UJdjATH+x+7vPOsHdbcIxBkYo8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mijFuU4uqF0hu7Yx9s3R5uRYjZj969dJ7nydd0WTca8r+KhHGGlEhZpw5SoaBxcMGXA3wUiUY6RwZcohiCI0tZAvH6q2VBoJSsWtxjvax7hjNlRb6A1IOzlU+dWQTC7+NDVk0CR1NzcpVOVXFwE/57mThhzd8WkNaFjPRqa8SJM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KhdNZOK3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KhdNZOK3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B01EEC4CEEB; Fri, 22 Aug 2025 01:54:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827679; bh=tDa3Sk8XxTm+Aaxc1UJdjATH+x+7vPOsHdbcIxBkYo8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=KhdNZOK3Uhz33z8IDngblDep6ZUpFArS9oStZOm7E3tYAoLl6aeTGPam+B445S3hy tPoKtFiXSpLr7Fb2p52alFhxzAv7EcWiKevWFZwrffoLyG2Kbxqiiko6Ora9dYqzx4 bOxpsds/IMZMxt9Py5FTPW3+kEfs8/33md1HVc9o2EvmCxj9zIU6EJMfPNARjnBoA3 prJhWKPr5xMy+yFgXqMBhbRvaBgmxOMJ5kNa/wc06nJDTCas4enoOHZbt8JTujeIZ+ DsyXmmetMvLVFdhAvcUKF5z9b/7tmzzLmODxQ8K4jgoK2mJYIv8ag2TngKXfBMyKRF n1Hno2J20WMZA== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:32 +0100 Subject: [PATCH v7 03/29] arm64/fpsimd: Decide to save ZT0 and streaming mode FFR at bind time Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-3-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=3253; i=broonie@kernel.org; h=from:subject:message-id; bh=tDa3Sk8XxTm+Aaxc1UJdjATH+x+7vPOsHdbcIxBkYo8=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop826uYzP1snjmHZRz+3YLBp0E5d8f9TMSaQAg 8u5eVFkI4mJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNugAKCRAk1otyXVSH 0FVwB/979F6kMUmZv//EVqk7RDD4dIMflrPiqEZyizKmQcURwPvXz+p/vJbnczOOyz+eojs7LsM pTJQpMklqRd14HHq5gIB9ZpyOEbPIxcCPv4f+y53ANuYnATetiGTRb26QMOx8hKHUAF3xx6+TV3 LwLv0dYliTKf8sXL2TbC0/75573W2f0QSf1wvtGIeHaaZ+AOVgjRQetJHxlClGM0Wu2Hm3t1M1s jytSBHpOhBlTHFOjshBrZGKyclmPQ8o2THGrAyraB6HsiLmQnuwqApWc19u7Eeanv0S5ttY/9Tg hIQ8PTRA8KyKjl9dvEZDGe2+P550azR+yEMoNf5XPDucnYRf X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Some parts of the SME state are optional, enabled by additional features on top of the base FEAT_SME and controlled with enable bits in SMCR_ELx. We unconditionally enable these for the host but for KVM we will allow the feature set exposed to guests to be restricted by the VMM. These are the FFR register (FEAT_SME_FA64) and ZT0 (FEAT_SME2). We defer saving of guest floating point state for non-protected guests to the host kernel. We also want to avoid having to reconfigure the guest floating point state if nothing used the floating point state while running the host. If the guest was running with the optional features disabled then traps will be enabled for them so the host kernel will need to skip accessing that state when saving state for the guest. Support this by moving the decision about saving this state to the point where we bind floating point state to the CPU, adding a new variable to the cpu_fp_state which uses the enable bits in SMCR_ELx to flag which features are enabled. Signed-off-by: Mark Brown --- arch/arm64/include/asm/fpsimd.h | 1 + arch/arm64/kernel/fpsimd.c | 10 ++++++++-- arch/arm64/kvm/fpsimd.c | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index b4359f942621..0ecdd7dcf623 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -87,6 +87,7 @@ struct cpu_fp_state { void *sme_state; u64 *svcr; u64 *fpmr; + u64 sme_features; unsigned int sve_vl; unsigned int sme_vl; enum fp_type *fp_type; diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 653c0dec6b18..77f9dfaffe8b 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -477,12 +477,12 @@ static void fpsimd_save_user_state(void) =20 if (*svcr & SVCR_ZA_MASK) sme_save_state(last->sme_state, - system_supports_sme2()); + last->sme_features & SMCR_ELx_EZT0); =20 /* If we are in streaming mode override regular SVE. */ if (*svcr & SVCR_SM_MASK) { save_sve_regs =3D true; - save_ffr =3D system_supports_fa64(); + save_ffr =3D last->sme_features & SMCR_ELx_FA64; vl =3D last->sme_vl; } } @@ -1655,6 +1655,12 @@ static void fpsimd_bind_task_to_cpu(void) last->to_save =3D FP_STATE_CURRENT; current->thread.fpsimd_cpu =3D smp_processor_id(); =20 + last->sme_features =3D 0; + if (system_supports_fa64()) + last->sme_features |=3D SMCR_ELx_FA64; + if (system_supports_sme2()) + last->sme_features |=3D SMCR_ELx_EZT0; + /* * Toggle SVE and SME trapping for userspace if needed, these * are serialsied by ret_to_user(). diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 15e17aca1dec..9158353d8be3 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -80,6 +80,7 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) fp_state.svcr =3D __ctxt_sys_reg(&vcpu->arch.ctxt, SVCR); fp_state.fpmr =3D __ctxt_sys_reg(&vcpu->arch.ctxt, FPMR); fp_state.fp_type =3D &vcpu->arch.fp_type; + fp_state.sme_features =3D 0; =20 if (vcpu_has_sve(vcpu)) fp_state.to_save =3D FP_STATE_SVE; --=20 2.39.5 From nobody Sat Oct 4 00:26:52 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C6081F130B; Fri, 22 Aug 2025 01:54:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827683; cv=none; b=bR8DLaR4rrlHpU+OG6lPajpKh+XEgBYD5aTQqbkotlqyPH7JWLvKAQxsTPqCBF1ISyU2zplEdBerIlwDB4UvcBX9rFzNCpCpoG+h8CtuyS4qzo1isahLmno8flTXyxCnN5kKjN3yCekNqm4qH0dUpSDmI7hNP8Ci17CJAkN7AKo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827683; c=relaxed/simple; bh=Rg1wsJ3gpmGTtJKL2YMiJAj+B1RPC9bu8N2e6PnFCu0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ClQUKtyUgHd0H+XDgTOnC3nHRHAOwK98imXEvroXv5iwH26RJvsBciJy4oH3DaHJ0XpXvR1RVlu0DMWASh/yYKIjwfmKlH/64ljpUxvdTApys6NnlnlAUKE7Go+bIwtCIc8Qcr+O4wwNg7eoeh/eXxkrkxCsWctLl9cuzOWTI/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Wwz3Hn43; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Wwz3Hn43" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 72170C116B1; Fri, 22 Aug 2025 01:54:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827682; bh=Rg1wsJ3gpmGTtJKL2YMiJAj+B1RPC9bu8N2e6PnFCu0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Wwz3Hn43I4TquZgTqBapPavDvDPrSDY0GbGUdVMxjTCGrDRz43aE0Z4t/z/qmOtm9 WY69Em/82JCGfEbij5ZJxRkXaDKWLiXbJosNB2gXSpr+kJ74g8HHct0rWW6phMsWSa o54Gs/nxoXHEYsdYsusgI9fJV0BEJhYPOBQyQrCe6Y3K88MyiOzKVJzQRwO2zQUPSS EFhyiBMQKFQ3B+kgWfEmfKS/mh7hhzOjOEa2S/hlFYUqN29YgdNdbw+zpknd1lv4hb iiHeLWQ1a+Qd5Jn4GC03qnejFMSR5GrfjaFXapoe92K8+38XYXDNkbANzhcjv2b+Xh rX1GA7tVDcUNQ== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:33 +0100 Subject: [PATCH v7 04/29] arm64/fpsimd: Check enable bit for FA64 when saving EFI state Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-4-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=1451; i=broonie@kernel.org; h=from:subject:message-id; bh=Rg1wsJ3gpmGTtJKL2YMiJAj+B1RPC9bu8N2e6PnFCu0=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop827+eIQAcHDPaqxZNzgiRFdwTfBj3rLnDk4q YKB0Ewgl6+JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNuwAKCRAk1otyXVSH 0E5fB/4vQ1VVoOwzKnTblIqSntVYv6to2xDnjsx05+jvOatP0D5l8W/MkuG25NE4GJzFiT7NIFy nhlID/y9VrgB4Ab4RZKT/jDKiSgqKUHYAkbssTQM9jiHDqlo3rOKk6k41lmV8r7L6Iq06Y+rE+v EeaEhzIXNKO9YknisQP9nCmr+eILqG2s0CwFvWh7Iml8CzxSkR3H5UhEYNO6pAs3c0lL3kg+eta FwKHivsn3UaWPKWo5yWNrAnS2v1rlmWv+g3r4ADjjaGZJlystQfEoy4PW67W8P7NofucKPk77ph WGNe/wQtOF3OLWTqR75LP550N18yIAT1b8cRZhozoNlgFYpm X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Currently when deciding if we need to save FFR when in streaming mode prior to EFI calls we check if FA64 is supported by the system. Since KVM guest support will mean that FA64 might be enabled and disabled at runtime switch to checking if traps for FA64 are enabled in SMCR_EL1 instead. Signed-off-by: Mark Brown --- arch/arm64/kernel/fpsimd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 77f9dfaffe8b..de2897d6208c 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1908,6 +1908,11 @@ static bool efi_sm_state; * either doing something wrong or you need to propose some refactoring. */ =20 +static bool fa64_enabled(void) +{ + return read_sysreg_s(SYS_SMCR_EL1) & SMCR_ELx_FA64; +} + /* * __efi_fpsimd_begin(): prepare FPSIMD for making an EFI runtime services= call */ @@ -1940,7 +1945,7 @@ void __efi_fpsimd_begin(void) * Unless we have FA64 FFR does not * exist in streaming mode. */ - if (!system_supports_fa64()) + if (!fa64_enabled()) ffr =3D !(svcr & SVCR_SM_MASK); } =20 @@ -1988,7 +1993,7 @@ void __efi_fpsimd_end(void) * Unless we have FA64 FFR does not * exist in streaming mode. */ - if (!system_supports_fa64()) + if (!fa64_enabled()) ffr =3D false; } } --=20 2.39.5 From nobody Sat Oct 4 00:26:52 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3EEE1BD01D; Fri, 22 Aug 2025 01:54:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827686; cv=none; b=YTyfEYPLienIXKuZ1ZsE7R4kXvdfai18Z492S/ruDsTsSJgO+RHhbFSBmRBf2QvNCnDjdFMYdfQCJ+c9oXFeUucBMXc2hChVHALmsQ7zKi0MryVK/SRt2uQTbFUzWJKW+IghvgaMHVOZszvxOIfwf42ZNm5DXcpfda2IBVg83gk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827686; c=relaxed/simple; bh=d5H7XLcR4Rtj+Rj6OZQAl1e1bSehEWOuVd1drKJeL5c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CauNeRg5LzMUopxoMGH+zXgjXMH0FgSi4EJxrBi7PRSIGyVaWGg4z0ZFh/JAGXii27vuHAx5hTuClAkMJdOHTPT4BiVhMNMk5XYClDZPVhgPmHpMK16UEjYGxi0ZWC3W7ACWx2Ntde7yBZ/8fL09i9afwMR/sAkJK4y1p3oL/to= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tibW+k5S; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="tibW+k5S" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3040EC4CEED; Fri, 22 Aug 2025 01:54:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827686; bh=d5H7XLcR4Rtj+Rj6OZQAl1e1bSehEWOuVd1drKJeL5c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tibW+k5SwC+EQm8WETK8o5ITo8euhu5ASLP6FreYV63JafnswXALSlNjA5fe0BBUF utSEukgiYNWb9rkXIO1sltM19IZux+zjdKo0ghJcqZy0BsXULblGupdC9rsILKQea0 2hZfYIXE/paPuG6XPOM2M0JIoK4FfC365vCZICUQXTx6pf+6npuiMla1120UivYIVd NemCtEqTe6FSaaDKfTJaI1d0A0ki2CHwZOsLUgNo+qKCmB554CAH0lar8dKJuLNxjd e0YazioxY9CAmiA4qZvtRpX9RW3W2s/DHxZyT4dQNgmwFYnNZEhpy7MQO789AGnIXy nywxNayD6D5iA== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:34 +0100 Subject: [PATCH v7 05/29] arm64/fpsimd: Determine maximum virtualisable SME vector length Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-5-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=2177; i=broonie@kernel.org; h=from:subject:message-id; bh=d5H7XLcR4Rtj+Rj6OZQAl1e1bSehEWOuVd1drKJeL5c=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop8280CPUlyvzjydHYRql5QRxrmhiav3FGPaDs n+EnHbXasCJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNvAAKCRAk1otyXVSH 0KRVB/wPGSAtQ4s7ogb6sHyi03Q7frhO+eVSnrjqlh6UjiulblrEjYQ7wSeyZTfca1wam4DKPI0 95VzhCW05qMVQMxAgL+SQwE9ACbEw5rW4lirttju1CI9uhSLeXZo0FA0BIthS1Q6mIa3Jqd6Np2 FN/aBsF3co7dWb2CoSuHOGxiBnVPnkbRgTtECO3aqeIuqHpQPUV2tFQ1bdw40kFH3qxfgoQD/1/ 6a+WWCldm9UV/yNVifW+6Oz2or7emXDQRckHyCcI7TPwl20PoJ5RaZr6b6Za4BQ/1XUSR5nCvHw U3UjS069dgR6Prii3dKV1mKfBMZzLPZmAFu3Z1D/Cp5AZcqa X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB As with SVE we can only virtualise SME vector lengths that are supported by all CPUs in the system, implement similar checks to those for SVE. Since unlike SVE there are no specific vector lengths that are architecturally required the handling is subtly different, we report a system where this happens with a maximum vector length of -1. Signed-off-by: Mark Brown --- arch/arm64/kernel/fpsimd.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index de2897d6208c..fbc586813f6a 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1244,7 +1244,8 @@ void cpu_enable_sme(const struct arm64_cpu_capabiliti= es *__always_unused p) void __init sme_setup(void) { struct vl_info *info =3D &vl_info[ARM64_VEC_SME]; - int min_bit, max_bit; + DECLARE_BITMAP(tmp_map, SVE_VQ_MAX); + int min_bit, max_bit, b; =20 if (!system_supports_sme()) return; @@ -1274,12 +1275,32 @@ void __init sme_setup(void) */ set_sme_default_vl(find_supported_vector_length(ARM64_VEC_SME, 32)); =20 + bitmap_andnot(tmp_map, info->vq_partial_map, info->vq_map, + SVE_VQ_MAX); + + b =3D find_last_bit(tmp_map, SVE_VQ_MAX); + if (b >=3D SVE_VQ_MAX) + /* All VLs virtualisable */ + info->max_virtualisable_vl =3D SVE_VQ_MAX; + else if (b =3D=3D SVE_VQ_MAX - 1) + /* No virtualisable VLs */ + info->max_virtualisable_vl =3D -1; + else + info->max_virtualisable_vl =3D sve_vl_from_vq(__bit_to_vq(b + 1)); + + if (info->max_virtualisable_vl > info->max_vl) + info->max_virtualisable_vl =3D info->max_vl; + pr_info("SME: minimum available vector length %u bytes per vector\n", info->min_vl); pr_info("SME: maximum available vector length %u bytes per vector\n", info->max_vl); pr_info("SME: default vector length %u bytes per vector\n", get_sme_default_vl()); + + /* KVM decides whether to support mismatched systems. Just warn here: */ + if (info->max_virtualisable_vl < info->max_vl) + pr_warn("SME: unvirtualisable vector lengths present\n"); } =20 void sme_suspend_exit(void) --=20 2.39.5 From nobody Sat Oct 4 00:26:52 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C28E1DA60F; Fri, 22 Aug 2025 01:54:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827690; cv=none; b=nhW4bHLRK+v5GtwAzF9HbEp+o0jlaPLVj1nc39X0mvt5XiPxa8qH9CfNKWCDIx7p3dn2JvY+OoOM9gxutikox0SbmoSDjWfnqJ4ackkr7Q2QIERIp3P91iqqHpcI7vvYVefARHugdIjrkqYAg/dfmn3cElmDd44kFAlymEh850s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827690; c=relaxed/simple; bh=dbI2jtQQauIA3bdjDRznGzLHLedqf9IfSzISWZL55Y8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KIm5H7HuF5ORB4rVMxY51Z1bZHwMBG6PY2J7Y8veW/mDcPDMzkf24GMvvtGRYIvtB1sY3WkHnzP8RvZLz/nGfhDVgLgYC2NqLqjBKfqiGdYotTE41eEobn+19QmsBxM0HdtcfJYya2dwYSUu3T5LeJVtARKZ1WVCgSokrPPctCE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hjW7ydp/; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hjW7ydp/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E16CCC113D0; Fri, 22 Aug 2025 01:54:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827690; bh=dbI2jtQQauIA3bdjDRznGzLHLedqf9IfSzISWZL55Y8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=hjW7ydp/ascrbwXrcytmv5A9A1QEEN67C+Y5WX5OBY3/PYu9k8RL7QbbRZ3A9cF87 zvHTJdrUz+BxWe3Oo3pKkXRjOlbISZf0JhWVrDdcLIPgv0t9O8QJG8MglnenJ1r4L4 Yif+4ocwkGzHJ9n55EdJsFiBKMbmjJn280S0X3Ku4458uAsp3oN+dRXdN+imOr4yQs CbIkHI7jrNc0cuB1br7jKSQPZrpWyjB2UZlMbFiH3nuJbbRr/7yG4sHhgZN1S2aUy9 1eETb+eeKfs7gFAO5W260jW5v1hCuQOH5HTm3Mx15CUoonxniSs1EyqwYt/R06LSwk CastnJw58rfbQ== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:35 +0100 Subject: [PATCH v7 06/29] KVM: arm64: Introduce non-UNDEF FGT control Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-6-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=2799; i=broonie@kernel.org; h=from:subject:message-id; bh=dbI2jtQQauIA3bdjDRznGzLHLedqf9IfSzISWZL55Y8=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop829zOsFUMjKA1Q+FQQwAiqq9AB2vWjQjAPE2 u9JV2QclT6JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNvQAKCRAk1otyXVSH 0CJDB/9j0rvgLnZvq7G9tLdHgMeGcVymfgbIkxBZuMivsNHRGROfGH4orSwWGmYihtCtFbjPm+j uAgEjOrR03z3Zp+lXbyNnG7zSDiMMS0yRZ4Xxje+HUVTN23JD59V1OIx6W30F4FhIU2La5UhiY6 vGPLnuBCDShNugj/oJR4HqR0EzyxuQS0jUqH/R/Csn4SajUTfdw2JVT5E0E6KX+09Wbw07f8tsV /Wq1P3h3y5MUScUQ6iD+huxr8aPoHUtSIjn12pOMtCErdSm9pHnjmQDI2AjPL3Q+f/Wv2IiaIJv olwGfxzvFeQrkbaK/+kKYtb3j7j8UeKtQZm9j85taCkAp3FN X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB We have support for determining a set of fine grained traps to enable for the guest which is tied to the support for injecting UNDEFs for undefined features. This means that we can't use the mechanism for system registers which should be present but need emulation, such as SMPRI_EL1 which should be accessible when SME is present but if SME priority support is absent SMPRI_EL1.Priority should be RAZ. Add an additional set of fine grained traps fgt, mirroring the existing fgu array. We use the same format where we always set the bit for the trap in the array as for FGU. This makes it clear what is being explicitly managed and keeps the code consistent. We do not convert the handling of ARM_WORKAROUND_AMPERE_ACO3_CPU_38 to this mechanism since this only enables a write trap and when implementing the existing UNDEF that we would share the read and write trap enablement (this being the overwhelmingly common case). Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 6 ++++++ arch/arm64/kvm/hyp/include/hyp/switch.h | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 2f2394cce24e..b501c2880ba2 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -302,6 +302,12 @@ struct kvm_arch { */ u64 fgu[__NR_FGT_GROUP_IDS__]; =20 + /* + * Additional FGTs to enable for the guests, eg. for emulated + * registers, + */ + u64 fgt[__NR_FGT_GROUP_IDS__]; + /* * Stage 2 paging state for VMs with nested S2 using a virtual * VMID. diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/i= nclude/hyp/switch.h index 84ec4e100fbb..d5620e02787f 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -283,9 +283,9 @@ static inline void __deactivate_cptr_traps(struct kvm_v= cpu *vcpu) id; \ }) =20 -#define compute_undef_clr_set(vcpu, kvm, reg, clr, set) \ +#define compute_trap_clr_set(vcpu, kvm, trap, reg, clr, set) \ do { \ - u64 hfg =3D kvm->arch.fgu[reg_to_fgt_group_id(reg)]; \ + u64 hfg =3D kvm->arch.trap[reg_to_fgt_group_id(reg)]; \ struct fgt_masks *m =3D reg_to_fgt_masks(reg); \ set |=3D hfg & m->mask; \ clr |=3D hfg & m->nmask; \ @@ -301,7 +301,8 @@ static inline void __deactivate_cptr_traps(struct kvm_v= cpu *vcpu) if (is_nested_ctxt(vcpu)) \ compute_clr_set(vcpu, reg, c, s); \ \ - compute_undef_clr_set(vcpu, kvm, reg, c, s); \ + compute_trap_clr_set(vcpu, kvm, fgu, reg, c, s); \ + compute_trap_clr_set(vcpu, kvm, fgt, reg, c, s); \ \ val =3D m->nmask; \ val |=3D s; \ --=20 2.39.5 From nobody Sat Oct 4 00:26:52 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D2AF1DA60F; Fri, 22 Aug 2025 01:54:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827694; cv=none; b=FP/CIv9UfSohSSP2/BsYb0JtaHffvY6vfOX6NYI3VAgQU2oltVD0mzkmeRWSsCt2YWniK4b/RqFvIzUzyPkvdYzi/OUMAkRfWuiVB3lmzk6ikSoF3JwVi6CPsuV9bbQ97e2iI3zhDokeNrX3lZ/ifkNhydVUhW9w049MNtBMGjk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827694; c=relaxed/simple; bh=LDt1xNEXDV4dCIkz7nCmkUUILCzxDoXGLDJ0dFTAhvY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Lh6uZvl43PFxyTkBuP9Zeja/IEoDtizHRRKN+1ao581w5yZeIcak9J+TJJHqLHWqOibsnpfqaJuFCrNfaX3SkFQemSrjYYfY5Mh3AVN2G5a47qle+QJGB7RcOBZth1cZ6HpJoH9sgzQH0lEF5GXFtQGDSo3c4//0Dfs0rqCjAls= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rQ1QAK+e; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rQ1QAK+e" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A3E43C4CEED; Fri, 22 Aug 2025 01:54:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827694; bh=LDt1xNEXDV4dCIkz7nCmkUUILCzxDoXGLDJ0dFTAhvY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rQ1QAK+ejMF2UsJTYMuGaQ+IUgv6wAQRUG1tk9AKVHc5EzOuBwatDMV2fTFBvZn5i 87J0trOaDm015XUoetk1CWfbiu72sypzgCtoDDeLo2MplMOpClXboXPx6n2LAwQtlI urSrhJtfcvsQNLTXMWNHZlSdzZn6nPjNjCh8wiSrdzNVuZmFKpDz2gWbssytXP0xQj hdnvytjfOnWU3HcUfPGND+WYEGAsoZY9VUQyhlP5r9Uwm2klEWv/HyQ1KXx1U6urkO 5xfvPPiAcsEbwTvMO0C7wpnFfhQ+O9tGhCETceauxB6SJXbA+ztvKYRHrFoqC6JPof Bf1ng3cyhJTxg== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:36 +0100 Subject: [PATCH v7 07/29] KVM: arm64: Pay attention to FFR parameter in SVE save and load Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-7-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=1028; i=broonie@kernel.org; h=from:subject:message-id; bh=LDt1xNEXDV4dCIkz7nCmkUUILCzxDoXGLDJ0dFTAhvY=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop829BfoReXLtofNQ/kSrhSNQrNRdpaxmFkV/T Frm4XVS2POJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNvQAKCRAk1otyXVSH 0IjhB/sF1Ys0WLO7A1A82RVjg1EGqd6NKiYg5AvJPYIvoPas6kpQsDCY2maqTagJ+xiueDoTxRm HJ+ZMnY0BudQLN8nXcOQRjKKhn59JQHrd+pJp2OPk6mjp7ev5SCENSoVRunepqOEGx1Yid805UO +ikcucvpnAOHOhDQofC22vWssdqMANC0G2iE1fVRSVJy9f/Svs+TlZknaG1Psh6GoqBv65WFtAj 8ZyObioXb69XxEJXUIGvn4HL40otAYtrv+4XDSkIS9qOt8NgMXM2iIzVSGDgNaMDRUyoplONbqH xY//UrwfZs8HibaGIExxej3MEd3vb49SGNGl3BJ+12BEj139 X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB The hypervisor copies of the SVE save and load functions are prototyped with third arguments specifying FFR should be accessed but the assembly functions overwrite whatever is supplied to unconditionally access FFR. Remove this and use the supplied parameter. This has no effect currently since FFR is always present for SVE but will be important for SME. Signed-off-by: Mark Brown --- arch/arm64/kvm/hyp/fpsimd.S | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/kvm/hyp/fpsimd.S b/arch/arm64/kvm/hyp/fpsimd.S index e950875e31ce..6e16cbfc5df2 100644 --- a/arch/arm64/kvm/hyp/fpsimd.S +++ b/arch/arm64/kvm/hyp/fpsimd.S @@ -21,13 +21,11 @@ SYM_FUNC_START(__fpsimd_restore_state) SYM_FUNC_END(__fpsimd_restore_state) =20 SYM_FUNC_START(__sve_restore_state) - mov x2, #1 sve_load 0, x1, x2, 3 ret SYM_FUNC_END(__sve_restore_state) =20 SYM_FUNC_START(__sve_save_state) - mov x2, #1 sve_save 0, x1, x2, 3 ret SYM_FUNC_END(__sve_save_state) --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 47C561DE8AD; Fri, 22 Aug 2025 01:54:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827699; cv=none; b=kAwjjvUG6VGOoiBAK7WCeV/+WMbiYRWhx3Qi74uIf+KGJXfy9O3PYduhPw3Ed8ljwztIRdlwjFcrlpsYphNzTMWCz94KvNu9EvSHfUAg1S26wGuG2qI2Ydm8948C2z6J8nlnSVXlbxPjsWsdy4hZHqmVTZOL8lup1g+jos55/II= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827699; c=relaxed/simple; bh=Sp+TAelZmX24aLyaDocHISqg813AdGCzZMNr5P6CYI4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=odprla4mUMuObn4cGYvANoIaiJ2BDn1jiqF4rHPhmWov7dYJlJICfb7KxFCweKNEDGhRKQhatDO9nmM2ghPMPbsGnxz+cM29XLlO63VnopYjWlI0ZIjvbcT+fiyXKRryt2aT3/dD3z6Kx+c5EzV14Dq9jDn1coiVUoRgMnv2bZU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HfYf91E2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HfYf91E2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 61F32C4CEEB; Fri, 22 Aug 2025 01:54:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827697; bh=Sp+TAelZmX24aLyaDocHISqg813AdGCzZMNr5P6CYI4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=HfYf91E2maGA3GZ8dIacAgPOtLnD5vsLR0VAXS7RANNRgZyUI4K32k7JgrGDzG4aG +gIH/aHm5qG+fmz/mUrULpM1rocjGLAbixmApGDjkejv6AWIe5dbaU5wOrPbplUTog t062FY05TU+E7fjwKxJoSSkAnV+izGSzBF+WVYOYiX/3haQStAp5sD3BP6L8tQTvKC We+Mknfof6x/P1NAD9u+dvzNcY6h4qHx7mcT8QNkXVpUgenVTEaV4cLMT2qMlPRWsG 2higbfMFDqA8pftTeePNuAhpPYlHoGKbm7y2IHhBQ8GeH8VZMg9smD4miIYE0UHaIH TTYRZBtqBZD0A== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:37 +0100 Subject: [PATCH v7 08/29] KVM: arm64: Pull ctxt_has_ helpers to start of sysreg-sr.h Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-8-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=3907; i=broonie@kernel.org; h=from:subject:message-id; bh=Sp+TAelZmX24aLyaDocHISqg813AdGCzZMNr5P6CYI4=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop82+8E+qQ2biWvK54LmYXwac54UiR74PjxM5c wdjpRzgNQ2JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNvgAKCRAk1otyXVSH 0OD7B/4mpUxOxRZaFS6g5BXtGs46mMGQgGp7fPIF5ZZ4/z1eMQW8mNdsTffRGiEGK7X9A4Y2gOl Htt4punjrKq5/54ovofB9Vfs4Bcv/IxX3EtBImJmI/SGnKtg/iECBTpisV8B7jfFQw644aw9Rlo k1Qctanl6Ck0zDZsFBzeOY3/3moQo6OcZEuTfJfLTdyhXQ+Jv5Ci8dpZphF8eXJ0CuutC/tNmBS xGiZsYIaMlIDLQG027Gw9lRJ4noRA5JI4DEbiZ6wX+bRNEKKCHOpqUoIKlbZQG1Zf+iPVATd5fK LDSA23Je2Ravfi5Bs6iZMES4+My1IkwN9oSFP5GGNnWZ3w+c X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Rather than add earlier prototypes of specific ctxt_has_ helpers let's just pull all their definitions to the top of sysreg-sr.h so they're all available to all the individual save/restore functions. Signed-off-by: Mark Brown --- arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 84 +++++++++++++++-----------= ---- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hy= p/include/hyp/sysreg-sr.h index a17cbe7582de..5624fd705ae3 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -16,8 +16,6 @@ #include #include =20 -static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt); - static inline struct kvm_vcpu *ctxt_to_vcpu(struct kvm_cpu_context *ctxt) { struct kvm_vcpu *vcpu =3D ctxt->__hyp_running_vcpu; @@ -28,47 +26,6 @@ static inline struct kvm_vcpu *ctxt_to_vcpu(struct kvm_c= pu_context *ctxt) return vcpu; } =20 -static inline bool ctxt_is_guest(struct kvm_cpu_context *ctxt) -{ - return host_data_ptr(host_ctxt) !=3D ctxt; -} - -static inline u64 *ctxt_mdscr_el1(struct kvm_cpu_context *ctxt) -{ - struct kvm_vcpu *vcpu =3D ctxt_to_vcpu(ctxt); - - if (ctxt_is_guest(ctxt) && kvm_host_owns_debug_regs(vcpu)) - return &vcpu->arch.external_mdscr_el1; - - return &ctxt_sys_reg(ctxt, MDSCR_EL1); -} - -static inline u64 ctxt_midr_el1(struct kvm_cpu_context *ctxt) -{ - struct kvm *kvm =3D kern_hyp_va(ctxt_to_vcpu(ctxt)->kvm); - - if (!(ctxt_is_guest(ctxt) && - test_bit(KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS, &kvm->arch.flags))) - return read_cpuid_id(); - - return kvm_read_vm_id_reg(kvm, SYS_MIDR_EL1); -} - -static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt) -{ - *ctxt_mdscr_el1(ctxt) =3D read_sysreg(mdscr_el1); - - // POR_EL0 can affect uaccess, so must be saved/restored early. - if (ctxt_has_s1poe(ctxt)) - ctxt_sys_reg(ctxt, POR_EL0) =3D read_sysreg_s(SYS_POR_EL0); -} - -static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt) -{ - ctxt_sys_reg(ctxt, TPIDR_EL0) =3D read_sysreg(tpidr_el0); - ctxt_sys_reg(ctxt, TPIDRRO_EL0) =3D read_sysreg(tpidrro_el0); -} - static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) { struct kvm_vcpu *vcpu =3D ctxt_to_vcpu(ctxt); @@ -131,6 +88,47 @@ static inline bool ctxt_has_sctlr2(struct kvm_cpu_conte= xt *ctxt) return kvm_has_sctlr2(kern_hyp_va(vcpu->kvm)); } =20 +static inline bool ctxt_is_guest(struct kvm_cpu_context *ctxt) +{ + return host_data_ptr(host_ctxt) !=3D ctxt; +} + +static inline u64 *ctxt_mdscr_el1(struct kvm_cpu_context *ctxt) +{ + struct kvm_vcpu *vcpu =3D ctxt_to_vcpu(ctxt); + + if (ctxt_is_guest(ctxt) && kvm_host_owns_debug_regs(vcpu)) + return &vcpu->arch.external_mdscr_el1; + + return &ctxt_sys_reg(ctxt, MDSCR_EL1); +} + +static inline u64 ctxt_midr_el1(struct kvm_cpu_context *ctxt) +{ + struct kvm *kvm =3D kern_hyp_va(ctxt_to_vcpu(ctxt)->kvm); + + if (!(ctxt_is_guest(ctxt) && + test_bit(KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS, &kvm->arch.flags))) + return read_cpuid_id(); + + return kvm_read_vm_id_reg(kvm, SYS_MIDR_EL1); +} + +static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt) +{ + *ctxt_mdscr_el1(ctxt) =3D read_sysreg(mdscr_el1); + + // POR_EL0 can affect uaccess, so must be saved/restored early. + if (ctxt_has_s1poe(ctxt)) + ctxt_sys_reg(ctxt, POR_EL0) =3D read_sysreg_s(SYS_POR_EL0); +} + +static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt) +{ + ctxt_sys_reg(ctxt, TPIDR_EL0) =3D read_sysreg(tpidr_el0); + ctxt_sys_reg(ctxt, TPIDRRO_EL0) =3D read_sysreg(tpidrro_el0); +} + static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, SCTLR_EL1) =3D read_sysreg_el1(SYS_SCTLR); --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC1A0243968; Fri, 22 Aug 2025 01:55:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827702; cv=none; b=EVli4qKhiWcAzfhBenNrGBesch8KuF0PoRcQhW4yP8nzDtrruZZUCRUGXevuPd0tfKBQGJJ59uDHOJgkCP1FyOHpLqh3rULO8QCPEZZOJZ2sIFVnxn9s5PcCzIMXLHzWU4qrw2jlmCyTbuVnTwIL15YnNLDCuB6dHfv0hQH1/Sk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827702; c=relaxed/simple; bh=ZG4fxyvl+fJjEtNXLvLt23cYfT+WmIeEoPP0DgaTqa0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jlDI+umel7xdYkF5XuK0RFxczIp9nAGEwbXtIxvMs4Lieuj700Hjk9lxldDSq+il/ope8euGXodCuf34GDGkhbvYvcq0a9/kUVgw/Xy5ELDa9kzLj+nDjOkP73RlenCEYIttjYvupPxxAvr5jHLIBE0mZmzDwuKhFy7XCGo7rU0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vNMmW3u6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vNMmW3u6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1F6CDC4CEED; Fri, 22 Aug 2025 01:54:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827701; bh=ZG4fxyvl+fJjEtNXLvLt23cYfT+WmIeEoPP0DgaTqa0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=vNMmW3u68moScB4YLlHhhuTjSmZjS4ocgb7RysoWRgCf1f3gwRsm/hs3XgAuVh1e2 dFfrN+voWD87cQaiH5iFd9NPKNKEadAa2FlyTvv/7fxENKXA0PdeAp8vhS45fdsfAk 7SCc7g3fTA3cJmGxzxgJGS1P21ggtFdKlc+RUlQwGUxazcU5h8LxYLKxxQa9jH1K1P 9aUMACzZWzQoOcoClWme0LrSA6NgJvNGRBKdgCXR4MEWTramcSGy0hef9n+mslK0vO 1Y9c6G42e5BCTLhD3/Hq9BBMs0LIqV7QQqnbFyGPF0P7hUb9EYUZUAcJDAgPGzwDSh qZfVFXd3/4xgw== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:38 +0100 Subject: [PATCH v7 09/29] KVM: arm64: Move SVE state access macros after feature test macros Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-9-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=2722; i=broonie@kernel.org; h=from:subject:message-id; bh=ZG4fxyvl+fJjEtNXLvLt23cYfT+WmIeEoPP0DgaTqa0=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop82/fOTWED/bf1kLN5UWctuDyjzq8csRed7k5 +r4evadPJ6JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNvwAKCRAk1otyXVSH 0AfOB/9DdJ/PeLOWQm7WyyBFCHgGWBEblTef76PTQMYaiCkSW+D5SFJT2zM0i06lCkitUT1Un59 xbikMemKg2qqGvMhFX/ye0e3fe1Srdo/j9yw6e5Csivx9paiJjLoqz5/tQYMH2jt2/u5IswsufR gam7pRQmfWvpFQ0sCbQ+gpV8HuVdufOKu6j5HHHMOUtp/awFg5CWPTkF4zpYudFPfcy96v2bqVu QvlefIb+337j+qeZw1hY/ar0o89ldTU3aXwhUsCXEFnyyqJFcUm8e8+HfLsAXAjzrCkkHt7Rcu3 skFv8UtNnMnr1DusSM4CcHSHJjOKvbVCj/sZ+Gg5Whrxtciq X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB In preparation for SME support move the macros used to access SVE state after the feature test macros, we will need to test for SME subfeatures to determine the size of the SME state. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 50 +++++++++++++++++++----------------= ---- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index b501c2880ba2..8f48c2a488f7 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1045,31 +1045,6 @@ struct kvm_vcpu_arch { #define NESTED_SERROR_PENDING __vcpu_single_flag(sflags, BIT(8)) =20 =20 -/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ -#define vcpu_sve_pffr(vcpu) (kern_hyp_va((vcpu)->arch.sve_state) + \ - sve_ffr_offset((vcpu)->arch.sve_max_vl)) - -#define vcpu_sve_max_vq(vcpu) sve_vq_from_vl((vcpu)->arch.sve_max_vl) - -#define vcpu_sve_zcr_elx(vcpu) \ - (unlikely(is_hyp_ctxt(vcpu)) ? ZCR_EL2 : ZCR_EL1) - -#define sve_state_size_from_vl(sve_max_vl) ({ \ - size_t __size_ret; \ - unsigned int __vq; \ - \ - if (WARN_ON(!sve_vl_valid(sve_max_vl))) { \ - __size_ret =3D 0; \ - } else { \ - __vq =3D sve_vq_from_vl(sve_max_vl); \ - __size_ret =3D SVE_SIG_REGS_SIZE(__vq); \ - } \ - \ - __size_ret; \ -}) - -#define vcpu_sve_state_size(vcpu) sve_state_size_from_vl((vcpu)->arch.sve_= max_vl) - #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \ KVM_GUESTDBG_USE_SW_BP | \ KVM_GUESTDBG_USE_HW | \ @@ -1105,6 +1080,31 @@ struct kvm_vcpu_arch { =20 #define vcpu_gp_regs(v) (&(v)->arch.ctxt.regs) =20 +/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ +#define vcpu_sve_pffr(vcpu) (kern_hyp_va((vcpu)->arch.sve_state) + \ + sve_ffr_offset((vcpu)->arch.sve_max_vl)) + +#define vcpu_sve_max_vq(vcpu) sve_vq_from_vl((vcpu)->arch.sve_max_vl) + +#define vcpu_sve_zcr_elx(vcpu) \ + (unlikely(is_hyp_ctxt(vcpu)) ? ZCR_EL2 : ZCR_EL1) + +#define sve_state_size_from_vl(sve_max_vl) ({ \ + size_t __size_ret; \ + unsigned int __vq; \ + \ + if (WARN_ON(!sve_vl_valid(sve_max_vl))) { \ + __size_ret =3D 0; \ + } else { \ + __vq =3D sve_vq_from_vl(sve_max_vl); \ + __size_ret =3D SVE_SIG_REGS_SIZE(__vq); \ + } \ + \ + __size_ret; \ +}) + +#define vcpu_sve_state_size(vcpu) sve_state_size_from_vl((vcpu)->arch.sve_= max_vl) + /* * Only use __vcpu_sys_reg/ctxt_sys_reg if you know you want the * memory backed version of a register, and not the one most recently --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46C0D243968; Fri, 22 Aug 2025 01:55:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827705; cv=none; b=aFUCwzLH+nPC+uHa3BkxFDWA885IMT9v1+9KgBDtRFr9CrqVqUUXCUbvXahtJexb6eew3edWzXRnu0B5Ty1neULIPCjMkuhte9cWmmi+cJk/bdOOicfLXvMkyO54oeZhGs8GiYnz0Vp64yNBAt+6muz4pMpbSs3672BTzbtJMFQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827705; c=relaxed/simple; bh=8axVTKd1b6ikITueHwT3N1OlRgy3HWVT9HvnlpgFOig=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AN/UQlIzBenduJEpVKGJ2kFM8hNk5zABLePnES/5sv6EfCFZXYH2njFf/TALk+/UP3csWzcnmfQTODHtF134mkIqw6KpabWs5osIcgJ9T4co9DqdzXsrLNQC5Yhn6y6OZCwRYiJyyjTc/XqY/I/OoiZ0wT2mAN0Q30k4T/dFdFQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cVRzBFtN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cVRzBFtN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1C74C4CEEB; Fri, 22 Aug 2025 01:55:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827705; bh=8axVTKd1b6ikITueHwT3N1OlRgy3HWVT9HvnlpgFOig=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cVRzBFtNfZtKHMbH1kFwUNYEkFtK3sWmzpCkwUXavdCH8w6CqVFTzXnB1XAciAHKi hxAdIGPCeqMaXUolOECq/WnrCpPY9gcRtlx14lI7tAtZ5/wz8fFo9WBRrQcTLddYYm f9Ts3xWFPtEr5Y4a6T+C58cBFzSA/hYfuDiGByYiTohKsdTfwTY3CLVMsvFvygA3hm tlPMgJHmWcuu81ppvwvIXaN+xPg7mkZT22b/iVu5KmX6KXRQyC9bbBprzEHnMzOKFL na+iseeWX85VNtnQRmW9yxupRMniqvs0fj4AtSmDKop1v7NrHKvvXjN1Nu9XA8e+ga znefzEWP9Ib8A== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:39 +0100 Subject: [PATCH v7 10/29] KVM: arm64: Rename SVE finalization constants to be more general Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-10-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=7220; i=broonie@kernel.org; h=from:subject:message-id; bh=8axVTKd1b6ikITueHwT3N1OlRgy3HWVT9HvnlpgFOig=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83AJO0OzincENy0qWeaLvGbxvOYJ6wSSXwb3 xsJi/j2faKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNwAAKCRAk1otyXVSH 0OHvB/9mLghKYcWpzI+mdVz6pXmWpG7NtW8FvtX8lILx5HOhHFGjM7E7twcW4tqxPlsydap/NEQ 0zES7O2++LoEDSiLMeY6R49LuXY/w4QmiAh5g/FVave5iyupE6XvnkuCiNWesY+w4WqHzfkCFVy 9HhwXXZOjoxGLZb8tktVqXxVwOXOHd8owPE4Ov+VClG4CqgsBdBPVob5RHwWVgGZksdZUz3b7yn TQqLddg/jwxLcfEjkA2ZFWZK1Eaye4VCUlRvJXpvKXQRaYp9C0F9LE/siRN3jsuCrdpvrQYoe1x zqwus8RNpb98/vvT/XbmhIRyd+pFHvwQd4nHmjhKtJQWKczT X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Due to the overlap between SVE and SME vector length configuration created by streaming mode SVE we will finalize both at once. Rename the existing finalization to use _VEC (vector) for the naming to avoid confusion. Since this includes the userspace API we create an alias KVM_ARM_VCPU_VEC for the existing KVM_ARM_VCPU_SVE capability, existing code which does not enable SME will be unaffected and any SME only code will not need to use SVE constants. No functional change. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 8 +++++--- arch/arm64/include/uapi/asm/kvm.h | 6 ++++++ arch/arm64/kvm/guest.c | 10 +++++----- arch/arm64/kvm/hyp/nvhe/pkvm.c | 2 +- arch/arm64/kvm/reset.c | 20 ++++++++++---------- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 8f48c2a488f7..88d184aac789 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -985,8 +985,8 @@ struct kvm_vcpu_arch { =20 /* KVM_ARM_VCPU_INIT completed */ #define VCPU_INITIALIZED __vcpu_single_flag(cflags, BIT(0)) -/* SVE config completed */ -#define VCPU_SVE_FINALIZED __vcpu_single_flag(cflags, BIT(1)) +/* Vector config completed */ +#define VCPU_VEC_FINALIZED __vcpu_single_flag(cflags, BIT(1)) /* pKVM VCPU setup completed */ #define VCPU_PKVM_FINALIZED __vcpu_single_flag(cflags, BIT(2)) =20 @@ -1059,6 +1059,8 @@ struct kvm_vcpu_arch { #define vcpu_has_sve(vcpu) kvm_has_sve((vcpu)->kvm) #endif =20 +#define vcpu_has_vec(vcpu) vcpu_has_sve(vcpu) + #ifdef CONFIG_ARM64_PTR_AUTH #define vcpu_has_ptrauth(vcpu) \ ((cpus_have_final_cap(ARM64_HAS_ADDRESS_AUTH) || \ @@ -1561,7 +1563,7 @@ struct kvm *kvm_arch_alloc_vm(void); int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature); bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu); =20 -#define kvm_arm_vcpu_sve_finalized(vcpu) vcpu_get_flag(vcpu, VCPU_SVE_FINA= LIZED) +#define kvm_arm_vcpu_vec_finalized(vcpu) vcpu_get_flag(vcpu, VCPU_VEC_FINA= LIZED) =20 #define kvm_has_mte(kvm) \ (system_supports_mte() && \ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/as= m/kvm.h index ed5f3892674c..4d789871bec1 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -107,6 +107,12 @@ struct kvm_regs { #define KVM_ARM_VCPU_HAS_EL2 7 /* Support nested virtualization */ #define KVM_ARM_VCPU_HAS_EL2_E2H0 8 /* Limit NV support to E2H RES0 */ =20 +/* + * An alias for _SVE since we finalize VL configuration for both SVE and S= ME + * simultaneously. + */ +#define KVM_ARM_VCPU_VEC KVM_ARM_VCPU_SVE + struct kvm_vcpu_init { __u32 target; __u32 features[7]; diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 16ba5e9ac86c..f38b95a73169 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -342,7 +342,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (!vcpu_has_sve(vcpu)) return -ENOENT; =20 - if (kvm_arm_vcpu_sve_finalized(vcpu)) + if (kvm_arm_vcpu_vec_finalized(vcpu)) return -EPERM; /* too late! */ =20 if (WARN_ON(vcpu->arch.sve_state)) @@ -497,7 +497,7 @@ static int get_sve_reg(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (ret) return ret; =20 - if (!kvm_arm_vcpu_sve_finalized(vcpu)) + if (!kvm_arm_vcpu_vec_finalized(vcpu)) return -EPERM; =20 if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset, @@ -523,7 +523,7 @@ static int set_sve_reg(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (ret) return ret; =20 - if (!kvm_arm_vcpu_sve_finalized(vcpu)) + if (!kvm_arm_vcpu_vec_finalized(vcpu)) return -EPERM; =20 if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr, @@ -657,7 +657,7 @@ static unsigned long num_sve_regs(const struct kvm_vcpu= *vcpu) return 0; =20 /* Policed by KVM_GET_REG_LIST: */ - WARN_ON(!kvm_arm_vcpu_sve_finalized(vcpu)); + WARN_ON(!kvm_arm_vcpu_vec_finalized(vcpu)); =20 return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */) + 1; /* KVM_REG_ARM64_SVE_VLS */ @@ -675,7 +675,7 @@ static int copy_sve_reg_indices(const struct kvm_vcpu *= vcpu, return 0; =20 /* Policed by KVM_GET_REG_LIST: */ - WARN_ON(!kvm_arm_vcpu_sve_finalized(vcpu)); + WARN_ON(!kvm_arm_vcpu_vec_finalized(vcpu)); =20 /* * Enumerate this first, so that userspace can save/restore in diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 338505cb0171..a461f192230a 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -420,7 +420,7 @@ static int pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp= _vcpu, struct kvm_vcpu *h int ret =3D 0; =20 if (!vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) { - vcpu_clear_flag(vcpu, VCPU_SVE_FINALIZED); + vcpu_clear_flag(vcpu, VCPU_VEC_FINALIZED); return 0; } =20 diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 959532422d3a..f7c63e145d54 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -92,7 +92,7 @@ static void kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu) * Finalize vcpu's maximum SVE vector length, allocating * vcpu->arch.sve_state as necessary. */ -static int kvm_vcpu_finalize_sve(struct kvm_vcpu *vcpu) +static int kvm_vcpu_finalize_vec(struct kvm_vcpu *vcpu) { void *buf; unsigned int vl; @@ -122,21 +122,21 @@ static int kvm_vcpu_finalize_sve(struct kvm_vcpu *vcp= u) } =09 vcpu->arch.sve_state =3D buf; - vcpu_set_flag(vcpu, VCPU_SVE_FINALIZED); + vcpu_set_flag(vcpu, VCPU_VEC_FINALIZED); return 0; } =20 int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature) { switch (feature) { - case KVM_ARM_VCPU_SVE: - if (!vcpu_has_sve(vcpu)) + case KVM_ARM_VCPU_VEC: + if (!vcpu_has_vec(vcpu)) return -EINVAL; =20 - if (kvm_arm_vcpu_sve_finalized(vcpu)) + if (kvm_arm_vcpu_vec_finalized(vcpu)) return -EPERM; =20 - return kvm_vcpu_finalize_sve(vcpu); + return kvm_vcpu_finalize_vec(vcpu); } =20 return -EINVAL; @@ -144,7 +144,7 @@ int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int fe= ature) =20 bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu) { - if (vcpu_has_sve(vcpu) && !kvm_arm_vcpu_sve_finalized(vcpu)) + if (vcpu_has_vec(vcpu) && !kvm_arm_vcpu_vec_finalized(vcpu)) return false; =20 return true; @@ -163,7 +163,7 @@ void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu) kfree(vcpu->arch.ccsidr); } =20 -static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu) +static void kvm_vcpu_reset_vec(struct kvm_vcpu *vcpu) { if (vcpu_has_sve(vcpu)) memset(vcpu->arch.sve_state, 0, vcpu_sve_state_size(vcpu)); @@ -203,11 +203,11 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu) if (loaded) kvm_arch_vcpu_put(vcpu); =20 - if (!kvm_arm_vcpu_sve_finalized(vcpu)) { + if (!kvm_arm_vcpu_vec_finalized(vcpu)) { if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) kvm_vcpu_enable_sve(vcpu); } else { - kvm_vcpu_reset_sve(vcpu); + kvm_vcpu_reset_vec(vcpu); } =20 if (vcpu_el1_is_32bit(vcpu)) --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07D3126FA52; Fri, 22 Aug 2025 01:55:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827709; cv=none; b=g0LBzgrx0zd4o1moCybjDrdI06WH0ALvUYrC1hbVKdktGJFPozcF/YCVBDlSkKblJdDO28APltfiW1iOof0Z+6qYve6zhVcylDz8ayB+Hbc3MiiNdvWuLFUHqnYMyO1Xo9s3QBNTwzPtm1yNherGprf4x+Gnl5BBTI5DLhCIx4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827709; c=relaxed/simple; bh=syt/RShWgXU9dy1JZh2eOSAyZGqhM0UCo5LVYbwVY3g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iWUuZJS5miXiIn2UdR8isWD8czYsqAOGrGA1Kzrxi1U78qh5Jc7qg4+UfREP1aPdAVGoAz+uUCRwu9rRlz/5t3QDOcG3hN3jAj7OGnJdLRGoZ41stGkrSTw2OCPBa0Buv/J2BWPAg8ehbtiuxx799obaBsd7yChWJU3Tu1O1Q3s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qT3sroW7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qT3sroW7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8F80EC4CEEB; Fri, 22 Aug 2025 01:55:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827708; bh=syt/RShWgXU9dy1JZh2eOSAyZGqhM0UCo5LVYbwVY3g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qT3sroW7QOscHIDuV397YnVh6J+VKfZttVfoTDuyondvItY/9n1FR6vmsrbGr78bP uTswIDoJt5jVoLqPCS/t+kLaoLf+RHUxvNI4VGSbYocpSJ0BofzQwGP+lH10DWkS/n 8UHEqZD/5zUOe65PtrxE1GAbSe9VU9+rH6q7ROrBtRVc+0FLvKG8zI8E6j9CrxGlQO gev8IWlYC8N5p8wqIPAyRFAj5cw8vYi+uGffo0BeOs3CSnBTyyVYLkWCUV5//FLo78 SNKr4X0YC6A9wFXFBrJi0o7SCrHNvlhB0k4QbHwkL4bpLElmMaGtFgwjCfYMuo1T34 24Rg4l9uEzX4A== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:40 +0100 Subject: [PATCH v7 11/29] KVM: arm64: Document the KVM ABI for SME Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-11-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=13384; i=broonie@kernel.org; h=from:subject:message-id; bh=syt/RShWgXU9dy1JZh2eOSAyZGqhM0UCo5LVYbwVY3g=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83BMU9bt++mCb0zXk+fxPwMjP7YPwVgb5Dn5 dp0oi6tBOKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNwQAKCRAk1otyXVSH 0P8fB/9Io9GdHFLicY58I/zR+WfU68tD1XMRyrN0tV8r7SnSKeyQXc00mRATTnUPm/CXh9bXpWZ 2fCMg492FJz7FiGoNBX44kMlCZk21yShO9kFLP8y2kLeWz8ZjiE1Q0MLj2MRKvwsQ8PJxVi5LMX xqEo0TZix/EH6uF6NuwuoS4u31iBCWr0rMHccJz/CTmRWZW+A6O5LiqfnLgbVkyQrxWUadR4WGg t4eGRrNN9CGwcU7jdX6oFZye/GShDbZw4k65X2ruWIQtk8mAesl1GY+MqoXc1A898B8C8NlH9iM HLgFSf5vAfiokO+leiATddHZHfxYZiYDLVv5myVBEofUaShH X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME, the Scalable Matrix Extension, is an arm64 extension which adds support for matrix operations, with core concepts patterned after SVE. SVE introduced some complication in the ABI since it adds new vector floating point registers with runtime configurable size, the size being controlled by a prameter called the vector length (VL). To provide control of this to VMMs we offer two phase configuration of SVE, SVE must first be enabled for the vCPU with KVM_ARM_VCPU_INIT(KVM_ARM_VCPU_SVE), after which vector length may then be configured but the configurably sized floating point registers are inaccessible until finalized with a call to KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE) after which the configurably sized registers can be accessed. SME introduces an additional independent configurable vector length which as well as controlling the size of the new ZA register also provides an alternative view of the configurably sized SVE registers (known as streaming mode) with the guest able to switch between the two modes as it pleases. There is also a fixed sized register ZT0 introduced in SME2. As well as streaming mode the guest may enable and disable ZA and (where SME2 is available) ZT0 dynamically independently of streaming mode. These modes are controlled via the system register SVCR. We handle the configuration of the vector length for SME in a similar manner to SVE, requiring initialization and finalization of the feature with a pseudo register controlling the available SME vector lengths as for SVE. Further, if the guest has both SVE and SME then finalizing one prevents further configuration of the vector length for the other. Where both SVE and SME are configured for the guest we always present the SVE registers to userspace as having the larger of the configured maximum SVE and SME vector lengths, discarding extra data at load time and zero padding on read as required if the active vector length is lower. Note that this means that enabling or disabling streaming mode while the guest is stopped will not zero Zn or Pn as it will when the guest is running, but it does allow SVCR, Zn and Pn to be read and written in any order. Userspace access to ZA and (if configured) ZT0 is always available, they will be zeroed when the guest runs if disabled in SVCR and the value read will be zero if the guest stops with them disabled. This mirrors the behaviour of the architecture, enabling access causes ZA and ZT0 to be zeroed, while allowing access to SVCR, ZA and ZT0 to be performed in any order. If SME is enabled for a guest without SVE then the FPSIMD Vn registers must be accessed via the low 128 bits of the SVE Zn registers as is the case when SVE is enabled. This is not ideal but allows access to SVCR and the registers in any order without duplication or ambiguity about which values should take effect. This may be an issue for VMMs that are unaware of SME on systems that implement it without SVE if they let SME be enabled, the lack of access to Vn may surprise them, but it seems like an unusual implementation choice. For SME unware VMMs on systems with both SVE and SME support the SVE registers may be larger than expected, this should be less disruptive than on a system without SVE as they will simply ignore the high bits of the registers. Signed-off-by: Mark Brown --- Documentation/virt/kvm/api.rst | 117 +++++++++++++++++++++++++++++--------= ---- 1 file changed, 82 insertions(+), 35 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 6aa40ee05a4a..71f46b342641 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -406,7 +406,7 @@ Errors: instructions from device memory (arm64) ENOSYS data abort outside memslots with no syndrome info and KVM_CAP_ARM_NISV_TO_USER not enabled (arm64) - EPERM SVE feature set but not finalized (arm64) + EPERM SVE or SME feature set but not finalized (arm64) =3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 This ioctl is used to run a guest virtual cpu. While there are no @@ -2600,12 +2600,12 @@ Specifically: 0x6020 0000 0010 00d5 FPCR 32 fp_regs.fpcr =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D= =3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D =20 -.. [1] These encodings are not accepted for SVE-enabled vcpus. See - :ref:`KVM_ARM_VCPU_INIT`. +.. [1] These encodings are not accepted for SVE enabled vcpus. See + :ref:`KVM_ARM_VCPU_INIT`. They are also not accepted when SME is + enabled without SVE and the vcpu is in streaming mode. =20 The equivalent register content can be accessed via bits [127:0] of - the corresponding SVE Zn registers instead for vcpus that have SVE - enabled (see below). + the corresponding SVE Zn registers in these cases (see below). =20 arm64 CCSIDR registers are demultiplexed by CSSELR value:: =20 @@ -2636,24 +2636,34 @@ arm64 SVE registers have the following bit patterns= :: 0x6050 0000 0015 060 FFR bits[256*slice + 255 : 256*sli= ce] 0x6060 0000 0015 ffff KVM_REG_ARM64_SVE_VLS pseudo-regis= ter =20 -Access to register IDs where 2048 * slice >=3D 128 * max_vq will fail with -ENOENT. max_vq is the vcpu's maximum supported vector length in 128-bit -quadwords: see [2]_ below. +arm64 SME registers have the following bit patterns: + + 0x6080 0000 0017 00 ZA.H[n] bits[2048*slice + 2047 : 2= 048*slice] + 0x60XX 0000 0017 0100 ZT0 + 0x6060 0000 0017 fffe KVM_REG_ARM64_SME_VLS pseudo-regis= ter + +Access to Z, P or ZA register IDs where 2048 * slice >=3D 128 * max_vq +will fail with ENOENT. max_vq is the vcpu's maximum supported vector +length in 128-bit quadwords: see [2]_ below. + +Access to the ZA and ZT0 registers is only available if SVCR.ZA is set +to 1. =20 These registers are only accessible on vcpus for which SVE is enabled. See KVM_ARM_VCPU_INIT for details. =20 -In addition, except for KVM_REG_ARM64_SVE_VLS, these registers are not -accessible until the vcpu's SVE configuration has been finalized -using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE). See KVM_ARM_VCPU_INIT -and KVM_ARM_VCPU_FINALIZE for more information about this procedure. +In addition, except for KVM_REG_ARM64_SVE_VLS and +KVM_REG_ARM64_SME_VLS, these registers are not accessible until the +vcpu's SVE and SME configuration has been finalized using +KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC). See KVM_ARM_VCPU_INIT and +KVM_ARM_VCPU_FINALIZE for more information about this procedure. =20 -KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector -lengths supported by the vcpu to be discovered and configured by -userspace. When transferred to or from user memory via KVM_GET_ONE_REG -or KVM_SET_ONE_REG, the value of this register is of type -__u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the set of vector lengths as -follows:: +KVM_REG_ARM64_SVE_VLS and KVM_ARM64_VCPU_SME_VLS are pseudo-registers +that allows the set of vector lengths supported by the vcpu to be +discovered and configured by userspace. When transferred to or from +user memory via KVM_GET_ONE_REG or KVM_SET_ONE_REG, the value of this +register is of type __u64[KVM_ARM64_SVE_VLS_WORDS], and encodes the +set of vector lengths as follows:: =20 __u64 vector_lengths[KVM_ARM64_SVE_VLS_WORDS]; =20 @@ -2665,19 +2675,25 @@ follows:: /* Vector length vq * 16 bytes not supported */ =20 .. [2] The maximum value vq for which the above condition is true is - max_vq. This is the maximum vector length available to the guest on - this vcpu, and determines which register slices are visible through - this ioctl interface. + max_vq. This is the maximum vector length currently available to + the guest on this vcpu, and determines which register slices are + visible through this ioctl interface. + + If SME is supported then the max_vq used for the Z and P registers + then while SVCR.SM is 1 this vector length will be the maximum SME + vector length available for the guest, otherwise it will be the + maximum SVE vector length available. =20 (See Documentation/arch/arm64/sve.rst for an explanation of the "vq" nomenclature.) =20 -KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT. -KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that -the host supports. +KVM_REG_ARM64_SVE_VLS and KVM_REG_ARM_SME_VLS are only accessible +after KVM_ARM_VCPU_INIT. KVM_ARM_VCPU_INIT initialises them to the +best set of vector lengths that the host supports. =20 -Userspace may subsequently modify it if desired until the vcpu's SVE -configuration is finalized using KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE). +Userspace may subsequently modify these registers if desired until the +vcpu's SVE and SME configuration is finalized using +KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC). =20 Apart from simply removing all vector lengths from the host set that exceed some value, support for arbitrarily chosen sets of vector lengths @@ -2685,8 +2701,8 @@ is hardware-dependent and may not be available. Atte= mpting to configure an invalid set of vector lengths via KVM_SET_ONE_REG will fail with EINVAL. =20 -After the vcpu's SVE configuration is finalized, further attempts to -write this register will fail with EPERM. +After the vcpu's SVE or SME configuration is finalized, further +attempts to write these registers will fail with EPERM. =20 arm64 bitmap feature firmware pseudo-registers have the following bit patt= ern:: =20 @@ -3469,6 +3485,7 @@ The initial values are defined as: - General Purpose registers, including PC and SP: set to 0 - FPSIMD/NEON registers: set to 0 - SVE registers: set to 0 + - SME registers: set to 0 - System registers: Reset to their architecturally defined values as for a warm reset to EL1 (resp. SVC) or EL2 (in the case of EL2 being enabled). @@ -3512,7 +3529,7 @@ Possible features: =20 - KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only). Depends on KVM_CAP_ARM_SVE. - Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE): + Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC): =20 * After KVM_ARM_VCPU_INIT: =20 @@ -3520,7 +3537,7 @@ Possible features: initial value of this pseudo-register indicates the best set of vector lengths possible for a vcpu on this host. =20 - * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE): + * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC}): =20 - KVM_RUN and KVM_GET_REG_LIST are not available; =20 @@ -3533,11 +3550,40 @@ Possible features: KVM_SET_ONE_REG, to modify the set of vector lengths available for the vcpu. =20 - * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_SVE): + * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC): =20 - the KVM_REG_ARM64_SVE_VLS pseudo-register is immutable, and can no longer be written using KVM_SET_ONE_REG. =20 + - KVM_ARM_VCPU_SME: Enables SME for the CPU (arm64 only). + Depends on KVM_CAP_ARM_SME. + Requires KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC): + + * After KVM_ARM_VCPU_INIT: + + - KVM_REG_ARM64_SME_VLS may be read using KVM_GET_ONE_REG: the + initial value of this pseudo-register indicates the best set of + vector lengths possible for a vcpu on this host. + + * Before KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC}): + + - KVM_RUN and KVM_GET_REG_LIST are not available; + + - KVM_GET_ONE_REG and KVM_SET_ONE_REG cannot be used to access + the scalable architectural SVE registers + KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() or + KVM_REG_ARM64_SVE_FFR, the matrix register + KVM_REG_ARM64_SME_ZA() or the LUT register KVM_REG_ARM64_ZT(); + + - KVM_REG_ARM64_SME_VLS may optionally be written using + KVM_SET_ONE_REG, to modify the set of vector lengths available + for the vcpu. + + * After KVM_ARM_VCPU_FINALIZE(KVM_ARM_VCPU_VEC): + + - the KVM_REG_ARM64_SME_VLS pseudo-register is immutable, and can + no longer be written using KVM_SET_ONE_REG. + - KVM_ARM_VCPU_HAS_EL2: Enable Nested Virtualisation support, booting the guest from EL2 instead of EL1. Depends on KVM_CAP_ARM_EL2. @@ -5120,11 +5166,12 @@ Errors: =20 Recognised values for feature: =20 - =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D - arm64 KVM_ARM_VCPU_SVE (requires KVM_CAP_ARM_SVE) - =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + arm64 KVM_ARM_VCPU_VEC (requires KVM_CAP_ARM_SVE or KVM_CAP_ARM_SME) + arm64 KVM_ARM_VCPU_SVE (alias for KVM_ARM_VCPU_VEC) + =3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 -Finalizes the configuration of the specified vcpu feature. +Finalizes the configuration of the specified vcpu features. =20 The vcpu must already have been initialised, enabling the affected feature= , by means of a successful :ref:`KVM_ARM_VCPU_INIT ` call wi= th the --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED8041E51FE; Fri, 22 Aug 2025 01:55:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827713; cv=none; b=ZDTPvf6DRaZoVW10oc/mteQTk6z3pub8glf5UQk17k6OEa+n5FHkPK+i6awLgkXNDUknUZ1uWa+y460pzHrg96Wi5jTPFqklFpqZvhu3NgLIJYw+zV7C1po6H55YL5vfo+In4LO7r2iV5x1CP2dAGhgT1nxq4D3or9XdhwaCndA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827713; c=relaxed/simple; bh=m/G5Vt7qKGaxjn4aWQkuI02V12W35pAJXakUbFGbMwk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pV7kCs7cbV7+BzUzfHXA1ec6iPcdNfW+2bsoWTEfkAIH+x/u/L4fLkNQDC26MXXKUlyUqOwQrmdBFKpJC1ILw830rmR1VwJBtbIX+ozDTv9t2/zpgvt/MeQO8+NmxJI4DU7wSBspbQ9FfZhf8n3V+mlXlWZv7505E4sR0hjcSJg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TBs7dgTi; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TBs7dgTi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4E793C116C6; Fri, 22 Aug 2025 01:55:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827712; bh=m/G5Vt7qKGaxjn4aWQkuI02V12W35pAJXakUbFGbMwk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TBs7dgTiwh33hv551ZAHacgP58uPQrtlwAfievM10cbZMLZ6YvFe0/4cWcjLdNqKv dJ4nWR4GbklXM+OfJFVpW2MNG5aINaEaqFCT11dCcs7yotRGqQ+t20BlNQ89MUDO37 PlyRSDmZu0o97E8JGQBhESKEeclK5695cI8l3No9RrkNEBIVGxLe/AYjXdCpSihg+v eAfuKZSSPO1+SnzEm0k+XkMPYcELOybFb+GpNhMxqQ4c/0K1UORwcT+1qVDkkwGcim Wd88UwLTwgOZVFkjCUBv6cgVT0KMMCj7PFpznXBKnmwZu9q9KbJDUnOqryyM+1U8vK 84TmF+ba+wTlA== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:41 +0100 Subject: [PATCH v7 12/29] KVM: arm64: Define internal features for SME Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-12-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=3292; i=broonie@kernel.org; h=from:subject:message-id; bh=m/G5Vt7qKGaxjn4aWQkuI02V12W35pAJXakUbFGbMwk=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83BBFv+sv999YKibb/D21tUr8ymdJtyRKoBm AXXkUQkZIiJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNwQAKCRAk1otyXVSH 0I9YB/kBcl0vQdFBdBbs73JgIp62ggW/IZ29f+yPbCDfX/xl6R7HQpRZ6rpNdjHvCGis+jqrVK3 yH/TUy+BfbwkLoPMvcmkg9SUIaK3fHROvZx4OIzZ62tF/7nOUuNyuhVV+dFMPBVHrhNFlH2qGcE 8Zb7gAVFDJYJcc11evXdHOYEL+d9r1MbluwaaYif1CkpTbZFxLMzZ1EZkSYq+kQzwCuxT4mCw6M vNsdKaUOX246fbmk87gboKH3UThG0RBjafi8s3I1Z4M8Q6d6ous25bjLykInO1UsvReOAkFawcX mSS0rXhzHhu+cIhIPcsL83JiKp+ZkG4GoFX435g9w3fnx1FR X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB In order to simplify interdependencies in the rest of the series define the feature detection for SME and it's subfeatures. Due to the need for vector length configuration we define a flag for SME like for SVE. We also have two subfeatures which add architectural state, FA64 and SME2, which are configured via the normal ID register scheme. Also provide helpers which check if the vCPU is in streaming mode or has ZA enabled. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 35 ++++++++++++++++++++++++++++++++++- arch/arm64/kvm/sys_regs.c | 2 +- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 88d184aac789..98761b601457 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -355,6 +355,8 @@ struct kvm_arch { #define KVM_ARCH_FLAG_GUEST_HAS_SVE 9 /* MIDR_EL1, REVIDR_EL1, and AIDR_EL1 are writable from userspace */ #define KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS 10 + /* SME exposed to guest */ +#define KVM_ARCH_FLAG_GUEST_HAS_SME 11 unsigned long flags; =20 /* VM-wide vCPU feature set */ @@ -1059,7 +1061,16 @@ struct kvm_vcpu_arch { #define vcpu_has_sve(vcpu) kvm_has_sve((vcpu)->kvm) #endif =20 -#define vcpu_has_vec(vcpu) vcpu_has_sve(vcpu) +#define kvm_has_sme(kvm) (system_supports_sme() && \ + test_bit(KVM_ARCH_FLAG_GUEST_HAS_SME, &(kvm)->arch.flags)) + +#ifdef __KVM_NVHE_HYPERVISOR__ +#define vcpu_has_sme(vcpu) kvm_has_sme(kern_hyp_va((vcpu)->kvm)) +#else +#define vcpu_has_sme(vcpu) kvm_has_sme((vcpu)->kvm) +#endif + +#define vcpu_has_vec(vcpu) (vcpu_has_sve(vcpu) || vcpu_has_sme(vcpu)) =20 #ifdef CONFIG_ARM64_PTR_AUTH #define vcpu_has_ptrauth(vcpu) \ @@ -1705,6 +1716,28 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64= val); #define kvm_has_sctlr2(k) \ (kvm_has_feat((k), ID_AA64MMFR3_EL1, SCTLRX, IMP)) =20 +#define kvm_has_fa64(k) \ + (system_supports_fa64() && \ + kvm_has_feat((k), ID_AA64SMFR0_EL1, FA64, IMP)) + +#define kvm_has_sme2(k) \ + (system_supports_sme2() && \ + kvm_has_feat((k), ID_AA64PFR1_EL1, SME, SME2)) + +#ifdef __KVM_NVHE_HYPERVISOR__ +#define vcpu_has_sme2(vcpu) kvm_has_sme2(kern_hyp_va((vcpu)->kvm)) +#define vcpu_has_fa64(vcpu) kvm_has_fa64(kern_hyp_va((vcpu)->kvm)) +#else +#define vcpu_has_sme2(vcpu) kvm_has_sme2((vcpu)->kvm) +#define vcpu_has_fa64(vcpu) kvm_has_fa64((vcpu)->kvm) +#endif + +#define vcpu_in_streaming_mode(vcpu) \ + (__vcpu_sys_reg(vcpu, SVCR) & SVCR_SM_MASK) + +#define vcpu_za_enabled(vcpu) \ + (__vcpu_sys_reg(vcpu, SVCR) & SVCR_ZA_MASK) + static inline bool kvm_arch_has_irq_bypass(void) { return true; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 82ffb3b3b3cf..111b07a78787 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1782,7 +1782,7 @@ static unsigned int sve_visibility(const struct kvm_v= cpu *vcpu, static unsigned int sme_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { - if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SME, IMP)) + if (vcpu_has_sme(vcpu)) return 0; =20 return REG_HIDDEN; --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 761E41E51FE; Fri, 22 Aug 2025 01:55:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827716; cv=none; b=dIx0BInMuKT/rZeXrSwjwnm1eTBUKds3OCD7cKg+oNfAC0PutaPq1FKuT5/PZe44CAPAU5Fsn/bDsNPD29IdbovyL4ts6HNqvlzreBpPKGkIsqNlGN3FjBpjAwEvle/gMDP3RwoRiKGSWwKSrNxi6MDXTDger74QNDVWZyHqfek= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827716; c=relaxed/simple; bh=JcuB5ad9okGlXfOvq/M2PLI+WEiTQG4p3nyWXh3yr4c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KJOx2zejJvPg6gaqFFunQ8mAqS7qBjL1HqbB7LxSeInGB/osraRH1Ev7vYAh3XgWZn6cO56s3HUIXlpS0mM8xPslCZwRpZypBBrNrcAgnNk0mq3RVYGNWynXKCV0lng+UkD4pBSQLnGz0Exd6F8F9kAHpDBykkZaFTmdvfUslnQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TxJBRy4B; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TxJBRy4B" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0C949C4CEED; Fri, 22 Aug 2025 01:55:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827716; bh=JcuB5ad9okGlXfOvq/M2PLI+WEiTQG4p3nyWXh3yr4c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TxJBRy4BElKmGssn/oPyIydK7siRMUN67lZC2fbwAQAUHx3OXdkSY/SRCeLVVGYZ/ 1G//mwpqC3mDnyp/T0PogWKZQHRm32/6WBh/vATFEP+a6sEH6jJXHBA/iw9rDslucI R/HYclgTmiY4lA0hs9O0/sW6drG4DHWSr4GIRHRDlsvRPFDaHULQORSJIsZcyA2f8v B+wMt95zPHMio3fH1ZNj/FysRHJJl/nPk23h8sxeHVr9V3CWSYzTQE+AJFi3jGpcHA qlGiCAWvWDjtXCUO9rDmuxMMoChpiiixb+9iVa5ERhDI6LZWrXFzz4NTqFlFAtsVfu ci5+zfkagLJHQ== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:42 +0100 Subject: [PATCH v7 13/29] KVM: arm64: Rename sve_state_reg_region Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-13-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=2352; i=broonie@kernel.org; h=from:subject:message-id; bh=JcuB5ad9okGlXfOvq/M2PLI+WEiTQG4p3nyWXh3yr4c=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83C32/fF+7vJ0QyOE9+3q+NxhA/xjngeyDc0 QcIxgvldM2JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNwgAKCRAk1otyXVSH 0P4rB/4vaaQhmA5bOgn6t6N+tIcos+QUPnK4+NAYZT7YjYjib34p6kw1JAcMmYbNJLzM7SBki6D pixEtkvuxIRciZcrQgb9XkMMielc1vXkq9ETfDrYcKuagLtrXZES0Llz162JyrYm1r6RNUPJXCc QXUJhmeIvnnV8xLR4BVjYUgYXsot9eFxPQ5QO85rFnB5mLJqbPq8ohNmPZE9HtLxf3UrfA8cGJM jO6XPLJrQtc1aTWlJo5l0a2yVhIKLkIaawX+mdU8G3BwQ/fbm92A8bS9Ugcs+lEZ6oNdbvGQKqn TIEUPQX5TEMVtuk1iM/6SnqFUHZdONrkDjMJ5w3v6uwueMvq X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB As for SVE we will need to pull parts of dynamically sized registers out of a block of memory for SME so we will use a similar code pattern for this. Rename the current struct sve_state_reg_region in preparation for this. No functional change. Signed-off-by: Mark Brown --- arch/arm64/kvm/guest.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index f38b95a73169..6eb273b525d5 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -404,9 +404,9 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) */ #define vcpu_sve_slices(vcpu) 1 =20 -/* Bounds of a single SVE register slice within vcpu->arch.sve_state */ -struct sve_state_reg_region { - unsigned int koffset; /* offset into sve_state in kernel memory */ +/* Bounds of a single register slice within vcpu->arch.s[mv]e_state */ +struct vec_state_reg_region { + unsigned int koffset; /* offset into s[mv]e_state in kernel memory */ unsigned int klen; /* length in kernel memory */ unsigned int upad; /* extra trailing padding in user memory */ }; @@ -415,7 +415,7 @@ struct sve_state_reg_region { * Validate SVE register ID and get sanitised bounds for user/kernel SVE * register copy */ -static int sve_reg_to_region(struct sve_state_reg_region *region, +static int sve_reg_to_region(struct vec_state_reg_region *region, struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) { @@ -485,7 +485,7 @@ static int sve_reg_to_region(struct sve_state_reg_regio= n *region, static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) { int ret; - struct sve_state_reg_region region; + struct vec_state_reg_region region; char __user *uptr =3D (char __user *)reg->addr; =20 /* Handle the KVM_REG_ARM64_SVE_VLS pseudo-reg as a special case: */ @@ -511,7 +511,7 @@ static int get_sve_reg(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) { int ret; - struct sve_state_reg_region region; + struct vec_state_reg_region region; const char __user *uptr =3D (const char __user *)reg->addr; =20 /* Handle the KVM_REG_ARM64_SVE_VLS pseudo-reg as a special case: */ --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B2381B043F; Fri, 22 Aug 2025 01:55:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827720; cv=none; b=D8Yj7z8+kzebC759bah3JlpuOls4+vfxzYaW+bVQJ53U4olW+9jRau2Sa6vsxkhCl7ptw3spHvs79vt3viyQKFrlANzmOtk7pYWMJz3Yl1rCkT8DKmu7CvWYL9hvC7PsbscOM+YfDCml9gSNmWLhQ+kZ/nXz3bdLuy28WgBeJ0k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827720; c=relaxed/simple; bh=c+TpgbYUfXA/JhZ2KpmwCWf1keJZ+h/x6ZLMET666u0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I4xg07G2iVpI71naZ1rz04i08wPdqcrGeQz/awpQOqugVMy6g7aRBBYYOqv4ZsMAZhAv9yj6Pm3HYeVC2HQao+E0/F/VQ94hWoexoQXii/o/O/1Zh89DW06k69O4iOEiCkZlUww5YUdWVicy3DkamYz11I8/CBVmb3TM5bHIfN4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JcvmEJw1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JcvmEJw1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BD88AC4CEEB; Fri, 22 Aug 2025 01:55:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827720; bh=c+TpgbYUfXA/JhZ2KpmwCWf1keJZ+h/x6ZLMET666u0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JcvmEJw1GtnykTPhT7IAggVJJ8rG7NWdXZd5pWE48Mu9EMdhTiV0MLE7FwWZJI76h iFEBL1zIoLP9xNKnoCEWQJkKrQP9YVuGqxAQRe9wbvNFflBrRdnPx5pfWm579R0Mk5 NZstQ3PU3eS8YRXHbhbQrLU1aSlt89TPEwZzC2LWc9+7gOrU1Hi8fq0YhydpXpDezp cX14VzxEO4Efx+ievb1W47MFrUjRe4lzm9fv2M2Pw2kHNYppkIEtfSDTmpKFSOYTzi XWk3IooWo2ulwQEzpDlqSP9B3ai+tWc/v54EnjTVXkFHq2ifVG+FJX5hMcGnFYdb7X QOUjVKuTGwO5g== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:43 +0100 Subject: [PATCH v7 14/29] KVM: arm64: Store vector lengths in an array Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-14-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=11784; i=broonie@kernel.org; h=from:subject:message-id; bh=c+TpgbYUfXA/JhZ2KpmwCWf1keJZ+h/x6ZLMET666u0=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83DfBKWaOwDiMFHehIAnu0HyBhxniSlwIqRa UJoWBOTpbaJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNwwAKCRAk1otyXVSH 0DPWB/9HWcFxc37MR2Sa/+np/fM3WTDvg+1x6ER4Rnykk5d6GUeyZUrRAo8suSHnr9nr7U3clR2 N0Vue0c7rKfbNxLm8V10FH5o5tZ8DUzKjMtfIR6OoF1M/dVxyML65atfWyUkEEwccZ722e8dX5Z nDDmQhddnDHFw/f56Xrdt+xqr+QIrvPmAeVuqP+GrRoEoKjH4LuS4gGtHnH7Hzl5MnhqPKdzVaC aY1bJrlUG/LHeRI6HncPuBu8Q5eolRJdJuT+kgx6SR6cPIPWgjZWGxCAwbm7dXDvp0PBWBjn8md 31lfTRLCCuitGjza6qv4sVB3hH2GL+9ivYDYb+qTBYvwdp6Y X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME adds a second vector length configured in a very similar way to the SVE vector length, in order to facilitate future code sharing for SME refactor our storage of vector lengths to use an array like the host does. We do not yet take much advantage of this so the intermediate code is not as clean as might be. No functional change. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 17 +++++++++++------ arch/arm64/include/asm/kvm_hyp.h | 2 +- arch/arm64/include/asm/kvm_pkvm.h | 2 +- arch/arm64/kvm/fpsimd.c | 2 +- arch/arm64/kvm/guest.c | 6 +++--- arch/arm64/kvm/hyp/include/hyp/switch.h | 6 +++--- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 +++--- arch/arm64/kvm/hyp/nvhe/pkvm.c | 7 ++++--- arch/arm64/kvm/reset.c | 22 +++++++++++----------- 9 files changed, 38 insertions(+), 32 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 98761b601457..59b88206d14c 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -76,8 +76,10 @@ enum kvm_mode kvm_get_mode(void); static inline enum kvm_mode kvm_get_mode(void) { return KVM_MODE_NONE; }; #endif =20 -extern unsigned int __ro_after_init kvm_sve_max_vl; -extern unsigned int __ro_after_init kvm_host_sve_max_vl; +extern unsigned int __ro_after_init kvm_max_vl[ARM64_VEC_MAX]; +extern unsigned int __ro_after_init kvm_host_max_vl[ARM64_VEC_MAX]; +DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use); + int __init kvm_arm_init_sve(void); =20 u32 __attribute_const__ kvm_target_cpu(void); @@ -813,7 +815,7 @@ struct kvm_vcpu_arch { */ void *sve_state; enum fp_type fp_type; - unsigned int sve_max_vl; + unsigned int max_vl[ARM64_VEC_MAX]; =20 /* Stage 2 paging state used by the hardware on next switch */ struct kvm_s2_mmu *hw_mmu; @@ -1095,9 +1097,12 @@ struct kvm_vcpu_arch { =20 /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ #define vcpu_sve_pffr(vcpu) (kern_hyp_va((vcpu)->arch.sve_state) + \ - sve_ffr_offset((vcpu)->arch.sve_max_vl)) + sve_ffr_offset((vcpu)->arch.max_vl[ARM64_VEC_SVE])) + +#define vcpu_vec_max_vq(vcpu, type) sve_vq_from_vl((vcpu)->arch.max_vl[typ= e]) + +#define vcpu_sve_max_vq(vcpu) vcpu_vec_max_vq(vcpu, ARM64_VEC_SVE) =20 -#define vcpu_sve_max_vq(vcpu) sve_vq_from_vl((vcpu)->arch.sve_max_vl) =20 #define vcpu_sve_zcr_elx(vcpu) \ (unlikely(is_hyp_ctxt(vcpu)) ? ZCR_EL2 : ZCR_EL1) @@ -1116,7 +1121,7 @@ struct kvm_vcpu_arch { __size_ret; \ }) =20 -#define vcpu_sve_state_size(vcpu) sve_state_size_from_vl((vcpu)->arch.sve_= max_vl) +#define vcpu_sve_state_size(vcpu) sve_state_size_from_vl((vcpu)->arch.max_= vl[ARM64_VEC_SVE]) =20 /* * Only use __vcpu_sys_reg/ctxt_sys_reg if you know you want the diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_= hyp.h index e6be1f5d0967..0ad5a66e0d25 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -145,6 +145,6 @@ extern u64 kvm_nvhe_sym(id_aa64smfr0_el1_sys_val); =20 extern unsigned long kvm_nvhe_sym(__icache_flags); extern unsigned int kvm_nvhe_sym(kvm_arm_vmid_bits); -extern unsigned int kvm_nvhe_sym(kvm_host_sve_max_vl); +extern unsigned int kvm_nvhe_sym(kvm_host_max_vl[ARM64_VEC_MAX]); =20 #endif /* __ARM64_KVM_HYP_H__ */ diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm= _pkvm.h index ea58282f59bb..6925606f2263 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -166,7 +166,7 @@ static inline size_t pkvm_host_sve_state_size(void) return 0; =20 return size_add(sizeof(struct cpu_sve_state), - SVE_SIG_REGS_SIZE(sve_vq_from_vl(kvm_host_sve_max_vl))); + SVE_SIG_REGS_SIZE(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]))); } =20 struct pkvm_mapping { diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 9158353d8be3..1f4fcc8b5554 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -75,7 +75,7 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) */ fp_state.st =3D &vcpu->arch.ctxt.fp_regs; fp_state.sve_state =3D vcpu->arch.sve_state; - fp_state.sve_vl =3D vcpu->arch.sve_max_vl; + fp_state.sve_vl =3D vcpu->arch.max_vl[ARM64_VEC_SVE]; fp_state.sme_state =3D NULL; fp_state.svcr =3D __ctxt_sys_reg(&vcpu->arch.ctxt, SVCR); fp_state.fpmr =3D __ctxt_sys_reg(&vcpu->arch.ctxt, FPMR); diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 6eb273b525d5..81f2b1111180 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -318,7 +318,7 @@ static int get_sve_vls(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (!vcpu_has_sve(vcpu)) return -ENOENT; =20 - if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl))) + if (WARN_ON(!sve_vl_valid(vcpu->arch.max_vl[ARM64_VEC_SVE]))) return -EINVAL; =20 memset(vqs, 0, sizeof(vqs)); @@ -356,7 +356,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (vq_present(vqs, vq)) max_vq =3D vq; =20 - if (max_vq > sve_vq_from_vl(kvm_sve_max_vl)) + if (max_vq > sve_vq_from_vl(kvm_max_vl[ARM64_VEC_SVE])) return -EINVAL; =20 /* @@ -375,7 +375,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) return -EINVAL; =20 /* vcpu->arch.sve_state will be alloc'd by kvm_vcpu_finalize_sve() */ - vcpu->arch.sve_max_vl =3D sve_vl_from_vq(max_vq); + vcpu->arch.max_vl[ARM64_VEC_SVE] =3D sve_vl_from_vq(max_vq); =20 return 0; } diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/i= nclude/hyp/switch.h index d5620e02787f..cd76129c6630 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -578,8 +578,8 @@ static inline void __hyp_sve_save_host(void) struct cpu_sve_state *sve_state =3D *host_data_ptr(sve_state); =20 sve_state->zcr_el1 =3D read_sysreg_el1(SYS_ZCR); - write_sysreg_s(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, SYS_ZCR_EL2); - __sve_save_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_sve_max_vl= ), + write_sysreg_s(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1, SYS_ZC= R_EL2); + __sve_save_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_max_vl[ARM= 64_VEC_SVE]), &sve_state->fpsr, true); } @@ -634,7 +634,7 @@ static inline void fpsimd_lazy_switch_to_host(struct kv= m_vcpu *vcpu) zcr_el2 =3D vcpu_sve_max_vq(vcpu) - 1; write_sysreg_el2(zcr_el2, SYS_ZCR); } else { - zcr_el2 =3D sve_vq_from_vl(kvm_host_sve_max_vl) - 1; + zcr_el2 =3D sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1; write_sysreg_el2(zcr_el2, SYS_ZCR); =20 zcr_el1 =3D vcpu_sve_max_vq(vcpu) - 1; diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/h= yp-main.c index 3206b2c07f82..76be13efcfcb 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -34,7 +34,7 @@ static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu) */ sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL2); __sve_save_state(vcpu_sve_pffr(vcpu), &vcpu->arch.ctxt.fp_regs.fpsr, true= ); - write_sysreg_s(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, SYS_ZCR_EL2); + write_sysreg_s(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1, SYS_ZC= R_EL2); } =20 static void __hyp_sve_restore_host(void) @@ -50,8 +50,8 @@ static void __hyp_sve_restore_host(void) * that was discovered, if we wish to use larger VLs this will * need to be revisited. */ - write_sysreg_s(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, SYS_ZCR_EL2); - __sve_restore_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_sve_max= _vl), + write_sysreg_s(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1, SYS_ZC= R_EL2); + __sve_restore_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_max_vl[= ARM64_VEC_SVE]), &sve_state->fpsr, true); write_sysreg_el1(sve_state->zcr_el1, SYS_ZCR); diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index a461f192230a..65c49a5c7091 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -20,7 +20,7 @@ unsigned long __icache_flags; /* Used by kvm_get_vttbr(). */ unsigned int kvm_arm_vmid_bits; =20 -unsigned int kvm_host_sve_max_vl; +unsigned int kvm_host_max_vl[ARM64_VEC_MAX]; =20 /* * The currently loaded hyp vCPU for each physical CPU. Used only when @@ -425,7 +425,8 @@ static int pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp= _vcpu, struct kvm_vcpu *h } =20 /* Limit guest vector length to the maximum supported by the host. */ - sve_max_vl =3D min(READ_ONCE(host_vcpu->arch.sve_max_vl), kvm_host_sve_ma= x_vl); + sve_max_vl =3D min(READ_ONCE(host_vcpu->arch.max_vl[ARM64_VEC_SVE]), + kvm_host_max_vl[ARM64_VEC_SVE]); sve_state_size =3D sve_state_size_from_vl(sve_max_vl); sve_state =3D kern_hyp_va(READ_ONCE(host_vcpu->arch.sve_state)); =20 @@ -439,7 +440,7 @@ static int pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp= _vcpu, struct kvm_vcpu *h goto err; =20 vcpu->arch.sve_state =3D sve_state; - vcpu->arch.sve_max_vl =3D sve_max_vl; + vcpu->arch.max_vl[ARM64_VEC_SVE] =3D sve_max_vl; =20 return 0; err: diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index f7c63e145d54..a8684a1346ec 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -32,7 +32,7 @@ =20 /* Maximum phys_shift supported for any VM on this host */ static u32 __ro_after_init kvm_ipa_limit; -unsigned int __ro_after_init kvm_host_sve_max_vl; +unsigned int __ro_after_init kvm_host_max_vl[ARM64_VEC_MAX]; =20 /* * ARMv8 Reset Values @@ -46,14 +46,14 @@ unsigned int __ro_after_init kvm_host_sve_max_vl; #define VCPU_RESET_PSTATE_SVC (PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \ PSR_AA32_I_BIT | PSR_AA32_F_BIT) =20 -unsigned int __ro_after_init kvm_sve_max_vl; +unsigned int __ro_after_init kvm_max_vl[ARM64_VEC_MAX]; =20 int __init kvm_arm_init_sve(void) { if (system_supports_sve()) { - kvm_sve_max_vl =3D sve_max_virtualisable_vl(); - kvm_host_sve_max_vl =3D sve_max_vl(); - kvm_nvhe_sym(kvm_host_sve_max_vl) =3D kvm_host_sve_max_vl; + kvm_max_vl[ARM64_VEC_SVE] =3D sve_max_virtualisable_vl(); + kvm_host_max_vl[ARM64_VEC_SVE] =3D sve_max_vl(); + kvm_nvhe_sym(kvm_host_max_vl[ARM64_VEC_SVE]) =3D kvm_host_max_vl[ARM64_V= EC_SVE]; =20 /* * The get_sve_reg()/set_sve_reg() ioctl interface will need @@ -61,16 +61,16 @@ int __init kvm_arm_init_sve(void) * order to support vector lengths greater than * VL_ARCH_MAX: */ - if (WARN_ON(kvm_sve_max_vl > VL_ARCH_MAX)) - kvm_sve_max_vl =3D VL_ARCH_MAX; + if (WARN_ON(kvm_max_vl[ARM64_VEC_SVE] > VL_ARCH_MAX)) + kvm_max_vl[ARM64_VEC_SVE] =3D VL_ARCH_MAX; =20 /* * Don't even try to make use of vector lengths that * aren't available on all CPUs, for now: */ - if (kvm_sve_max_vl < sve_max_vl()) + if (kvm_max_vl[ARM64_VEC_SVE] < sve_max_vl()) pr_warn("KVM: SVE vector length for guests limited to %u bytes\n", - kvm_sve_max_vl); + kvm_max_vl[ARM64_VEC_SVE]); } =20 return 0; @@ -78,7 +78,7 @@ int __init kvm_arm_init_sve(void) =20 static void kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu) { - vcpu->arch.sve_max_vl =3D kvm_sve_max_vl; + vcpu->arch.max_vl[ARM64_VEC_SVE] =3D kvm_max_vl[ARM64_VEC_SVE]; =20 /* * Userspace can still customize the vector lengths by writing @@ -99,7 +99,7 @@ static int kvm_vcpu_finalize_vec(struct kvm_vcpu *vcpu) size_t reg_sz; int ret; =20 - vl =3D vcpu->arch.sve_max_vl; + vl =3D vcpu->arch.max_vl[ARM64_VEC_SVE]; =20 /* * Responsibility for these properties is shared between --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05A15285C97; Fri, 22 Aug 2025 01:55:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827724; cv=none; b=cn6v1lBfKWZhf3pHKzTnlhvDhRBY0hdscBSsMw+Hc8BI0SYM8O6yAdMe4G1xRBf0ElpFjaV+Qpfa+4g5c+kfJaJZDaTDdwmFe6uPhCT4P9vbL37sTfTosD/iBqPDBHwnFOnYryl8j+g5TdIhzpSsbykVLQw0Q8zeDLVHNYmueoA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827724; c=relaxed/simple; bh=MHP76p9ZYAtyF4GOnpjIu8qVdvdMlEFvQbs8UnH2ZLM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OOeBk0RXOAjaOWCq279huD9YHLceiiazG/h/OI0+JvQQ5XzYxeEVFaB6neK9R5qmei4F3AMAsqeIYQ4XHn06oJNA6TjuBrF3MDhbKl27Die+W22K5mcVQJgTYaLLnwNeKJogVIJax2n5vn5++zHzxealo8ErXlD5ha6Sqq2RMeI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hM8kG8N3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hM8kG8N3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 83DF0C116C6; Fri, 22 Aug 2025 01:55:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827723; bh=MHP76p9ZYAtyF4GOnpjIu8qVdvdMlEFvQbs8UnH2ZLM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=hM8kG8N352g3+rFnQiiFU5aviAxpteUtNHfYzUDZsxiW29ogsLd999dKERsFuPyyI RfITQHWSddlkyOPk1fK43W9rhXp3R4BSRdeXsbhPLHuXainBNwlEJC2e/7LDvNIWtL jWOmowDTuLVgM+qdEe1SWUb6LSV1teapGHWEaISEOA5x6mVa/fQh/5QyvsGgAGwBEd 60JY7w+e6pl8zYs4HRrQUc2bmSo8OTrUMbWFywjLpaWJVoSwmxQ2k9L+BwJZiV64ub eO8a6qDG3VIJ8sIDEtMiAlkyolmzCU/7pZCsm1izJ4KJEUMv34od2IyQHLiWqTJLwU v4g4t3rFT67Ww== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:44 +0100 Subject: [PATCH v7 15/29] KVM: arm64: Implement SME vector length configuration Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-15-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=10123; i=broonie@kernel.org; h=from:subject:message-id; bh=MHP76p9ZYAtyF4GOnpjIu8qVdvdMlEFvQbs8UnH2ZLM=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83EYP4HZjlxKWdR5yN3UpVGX45iqXdg906Io Lh6rYpXvuSJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNxAAKCRAk1otyXVSH 0MzVB/9A6cQN8/O/loHIz0HjkKgHOQKFEa2/p/PP/tjHvV8ZtjSqvoWfFnqs1N0J6eLyXlp6pkG wAU+D4JMvX12SDkxj/J7c/ckEPu2gxi/8N1VIrz5I3Ogt4SGcKJe4+2mH3eo87u1QpxSapb2O35 4MIAq3i+YodqVegOWulIt0DHo+pxwL3JEFXTV+clKiaHczeZodi4FWAuMMEKgByufipSKRqMrKj mQCHqnSlmnA5fx3hkYH6Ha6AGbFM9snANDfr3cZD177tJzUlwy3qy0TTehOyzYsMRSBCjf4WgsN OKqBCaTeaS+mLjAea65DmVVFo84vyNgXhnIAxmwvIxrrBiGe X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME implements a vector length which architecturally looks very similar to that for SVE, configured in a very similar manner. This controls the vector length used for the ZA matrix register, and for the SVE vector and predicate registers when in streaming mode. The only substantial difference is that unlike SVE the architecture does not guarantee that any particular vector length will be implemented. Configuration for SME vector lengths is done using a virtual register as for SVE, hook up the implementation for the virtual register. Since we do not yet have support for any of the new SME registers stub register access functions are provided that only allow VL configuration. These will be extended as the SME specific registers, as for SVE. Since vq_available() is currently only defined for CONFIG_SVE add a stub for builds where that is disabled. Signed-off-by: Mark Brown --- arch/arm64/include/asm/fpsimd.h | 1 + arch/arm64/include/asm/kvm_host.h | 24 ++++++++++-- arch/arm64/include/uapi/asm/kvm.h | 9 +++++ arch/arm64/kvm/guest.c | 82 +++++++++++++++++++++++++++++++----= ---- 4 files changed, 96 insertions(+), 20 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index 0ecdd7dcf623..38c24c6485ad 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -340,6 +340,7 @@ static inline int sve_max_vl(void) return -EINVAL; } =20 +static inline bool vq_available(enum vec_type type, unsigned int vq) { ret= urn false; } static inline bool sve_vq_available(unsigned int vq) { return false; } =20 static inline void sve_user_disable(void) { BUILD_BUG(); } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 59b88206d14c..4348f297b5ae 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -812,8 +812,15 @@ struct kvm_vcpu_arch { * low 128 bits of the SVE Z registers. When the core * floating point code saves the register state of a task it * records which view it saved in fp_type. + * + * If SME support is also present then it provides an + * alternative view of the SVE registers accessed as for the Z + * registers when PSTATE.SM is 1, plus an additional set of + * SME specific state in the matrix register ZA and LUT + * register ZT0. */ void *sve_state; + void *sme_state; enum fp_type fp_type; unsigned int max_vl[ARM64_VEC_MAX]; =20 @@ -1095,14 +1102,23 @@ struct kvm_vcpu_arch { =20 #define vcpu_gp_regs(v) (&(v)->arch.ctxt.regs) =20 -/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ -#define vcpu_sve_pffr(vcpu) (kern_hyp_va((vcpu)->arch.sve_state) + \ - sve_ffr_offset((vcpu)->arch.max_vl[ARM64_VEC_SVE])) - #define vcpu_vec_max_vq(vcpu, type) sve_vq_from_vl((vcpu)->arch.max_vl[typ= e]) =20 #define vcpu_sve_max_vq(vcpu) vcpu_vec_max_vq(vcpu, ARM64_VEC_SVE) +#define vcpu_sme_max_vq(vcpu) vcpu_vec_max_vq(vcpu, ARM64_VEC_SME) + +#define vcpu_sve_max_vl(vcpu) ((vcpu)->arch.max_vl[ARM64_VEC_SVE]) +#define vcpu_sme_max_vl(vcpu) ((vcpu)->arch.max_vl[ARM64_VEC_SME]) =20 +#define vcpu_max_vl(vcpu) max(vcpu_sve_max_vl(vcpu), vcpu_sme_max_vl(vcpu)) +#define vcpu_max_vq(vcpu) sve_vq_from_vl(vcpu_max_vl(vcpu)) + +#define vcpu_cur_sve_vl(vcpu) (vcpu_in_streaming_mode(vcpu) ? \ + vcpu_sme_max_vl(vcpu) : vcpu_sve_max_vl(vcpu)) + +/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ +#define vcpu_sve_pffr(vcpu) (kern_hyp_va((vcpu)->arch.sve_state) + \ + sve_ffr_offset(vcpu_cur_sve_vl(vcpu))) =20 #define vcpu_sve_zcr_elx(vcpu) \ (unlikely(is_hyp_ctxt(vcpu)) ? ZCR_EL2 : ZCR_EL1) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/as= m/kvm.h index 4d789871bec1..5220797361e0 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -354,6 +354,15 @@ struct kvm_arm_counter_offset { #define KVM_ARM64_SVE_VLS_WORDS \ ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1) =20 +/* SME registers */ +#define KVM_REG_ARM64_SME (0x17 << KVM_REG_ARM_COPROC_SHIFT) + +/* Vector lengths pseudo-register: */ +#define KVM_REG_ARM64_SME_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SME | \ + KVM_REG_SIZE_U512 | 0xffff) +#define KVM_ARM64_SME_VLS_WORDS \ + ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1) + /* Bitmap feature firmware registers */ #define KVM_REG_ARM_FW_FEAT_BMAP (0x0016 << KVM_REG_ARM_COPROC_SHIFT) #define KVM_REG_ARM_FW_FEAT_BMAP_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64= | \ diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 81f2b1111180..bcb0d565f1a4 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -310,22 +310,20 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const = struct kvm_one_reg *reg) #define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64) #define vq_present(vqs, vq) (!!((vqs)[vq_word(vq)] & vq_mask(vq))) =20 -static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +static int get_vec_vls(enum vec_type vec_type, struct kvm_vcpu *vcpu, + const struct kvm_one_reg *reg) { unsigned int max_vq, vq; u64 vqs[KVM_ARM64_SVE_VLS_WORDS]; =20 - if (!vcpu_has_sve(vcpu)) - return -ENOENT; - - if (WARN_ON(!sve_vl_valid(vcpu->arch.max_vl[ARM64_VEC_SVE]))) + if (WARN_ON(!sve_vl_valid(vcpu->arch.max_vl[vec_type]))) return -EINVAL; =20 memset(vqs, 0, sizeof(vqs)); =20 - max_vq =3D vcpu_sve_max_vq(vcpu); + max_vq =3D vcpu_vec_max_vq(vcpu, vec_type); for (vq =3D SVE_VQ_MIN; vq <=3D max_vq; ++vq) - if (sve_vq_available(vq)) + if (vq_available(vec_type, vq)) vqs[vq_word(vq)] |=3D vq_mask(vq); =20 if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs))) @@ -334,40 +332,41 @@ static int get_sve_vls(struct kvm_vcpu *vcpu, const s= truct kvm_one_reg *reg) return 0; } =20 -static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +static int set_vec_vls(enum vec_type vec_type, struct kvm_vcpu *vcpu, + const struct kvm_one_reg *reg) { unsigned int max_vq, vq; u64 vqs[KVM_ARM64_SVE_VLS_WORDS]; =20 - if (!vcpu_has_sve(vcpu)) - return -ENOENT; - if (kvm_arm_vcpu_vec_finalized(vcpu)) return -EPERM; /* too late! */ =20 - if (WARN_ON(vcpu->arch.sve_state)) + if (WARN_ON(!sve_vl_valid(vcpu->arch.max_vl[vec_type]))) return -EINVAL; =20 if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs))) return -EFAULT; =20 + if (WARN_ON(vcpu->arch.sve_state || vcpu->arch.sme_state)) + return -EINVAL; + max_vq =3D 0; for (vq =3D SVE_VQ_MIN; vq <=3D SVE_VQ_MAX; ++vq) if (vq_present(vqs, vq)) max_vq =3D vq; =20 - if (max_vq > sve_vq_from_vl(kvm_max_vl[ARM64_VEC_SVE])) + if (max_vq > sve_vq_from_vl(kvm_max_vl[vec_type])) return -EINVAL; =20 /* * Vector lengths supported by the host can't currently be * hidden from the guest individually: instead we can only set a - * maximum via ZCR_EL2.LEN. So, make sure the available vector + * maximum via xCR_EL2.LEN. So, make sure the available vector * lengths match the set requested exactly up to the requested * maximum: */ for (vq =3D SVE_VQ_MIN; vq <=3D max_vq; ++vq) - if (vq_present(vqs, vq) !=3D sve_vq_available(vq)) + if (vq_present(vqs, vq) !=3D vq_available(vec_type, vq)) return -EINVAL; =20 /* Can't run with no vector lengths at all: */ @@ -375,11 +374,27 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const s= truct kvm_one_reg *reg) return -EINVAL; =20 /* vcpu->arch.sve_state will be alloc'd by kvm_vcpu_finalize_sve() */ - vcpu->arch.max_vl[ARM64_VEC_SVE] =3D sve_vl_from_vq(max_vq); + vcpu->arch.max_vl[vec_type] =3D sve_vl_from_vq(max_vq); =20 return 0; } =20 +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +{ + if (!vcpu_has_sve(vcpu)) + return -ENOENT; + + return get_vec_vls(ARM64_VEC_SVE, vcpu, reg); +} + +static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +{ + if (!vcpu_has_sve(vcpu)) + return -ENOENT; + + return set_vec_vls(ARM64_VEC_SVE, vcpu, reg); +} + #define SVE_REG_SLICE_SHIFT 0 #define SVE_REG_SLICE_BITS 5 #define SVE_REG_ID_SHIFT (SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS) @@ -533,6 +548,39 @@ static int set_sve_reg(struct kvm_vcpu *vcpu, const st= ruct kvm_one_reg *reg) return 0; } =20 +static int get_sme_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +{ + if (!vcpu_has_sme(vcpu)) + return -ENOENT; + + return get_vec_vls(ARM64_VEC_SME, vcpu, reg); +} + +static int set_sme_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +{ + if (!vcpu_has_sme(vcpu)) + return -ENOENT; + + return set_vec_vls(ARM64_VEC_SME, vcpu, reg); +} + +static int get_sme_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +{ + /* Handle the KVM_REG_ARM64_SME_VLS pseudo-reg as a special case: */ + if (reg->id =3D=3D KVM_REG_ARM64_SME_VLS) + return get_sme_vls(vcpu, reg); + + return -EINVAL; +} + +static int set_sme_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) +{ + /* Handle the KVM_REG_ARM64_SME_VLS pseudo-reg as a special case: */ + if (reg->id =3D=3D KVM_REG_ARM64_SME_VLS) + return set_sme_vls(vcpu, reg); + + return -EINVAL; +} int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *r= egs) { return -EINVAL; @@ -775,6 +823,7 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct= kvm_one_reg *reg) case KVM_REG_ARM_FW_FEAT_BMAP: return kvm_arm_get_fw_reg(vcpu, reg); case KVM_REG_ARM64_SVE: return get_sve_reg(vcpu, reg); + case KVM_REG_ARM64_SME: return get_sme_reg(vcpu, reg); } =20 if (is_timer_reg(reg->id)) @@ -795,6 +844,7 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct= kvm_one_reg *reg) case KVM_REG_ARM_FW_FEAT_BMAP: return kvm_arm_set_fw_reg(vcpu, reg); case KVM_REG_ARM64_SVE: return set_sve_reg(vcpu, reg); + case KVM_REG_ARM64_SME: return set_sme_reg(vcpu, reg); } =20 if (is_timer_reg(reg->id)) --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2C292874F0; Fri, 22 Aug 2025 01:55:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827727; cv=none; b=G8VTVQukCj4dFsCbgXr91mp7lqhMMlIj6z8I7yItrAnaiPrzKT/iEQ/jpnzxaC7OVryaIQramMKjG1NjWjCnd/a7s73YPcDLV/xDvdhhXLeitcfQrEDs4HpxKI45h+aOh8g1rUWdtRbgmJqw0epKUgCdPi/HKvyjCj0qq38PoRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827727; c=relaxed/simple; bh=0fLGhfB6VaFN9V2OPaprNenzTUhxjwQ4WMNFeuSowXY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=R1KKCegy/PkcmGKwftNkNc+aisTs2rXP9JNgciGdC9IVFIpttImjOtp9XanyjuLplMmh9BiufYlW0kU17JjP2fspT7tPsK5PLQh/0xmbCl6zTzd5GrIB/VudUyh6lkBsI5pPCd29GEK7LK11dxa3UswG1bzE6ojeEkVkjnv3nDg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ctQGiHWa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ctQGiHWa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 46436C116B1; Fri, 22 Aug 2025 01:55:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827727; bh=0fLGhfB6VaFN9V2OPaprNenzTUhxjwQ4WMNFeuSowXY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ctQGiHWaV26ejoLFO4zfHMMBN+KUc6cNP0jdCLGWRg3j96fF72rkN15gBCxn5/Kig IBDvnTVM1yM9bP5VzjJ5xQR0GRbH3uYA/2Mh2qDWX2Bu+iIOW5UUk7I7+KMT94MOUQ ipOw14avng2D9P09EX7uO62QuTCsSiz6Bne/TW9x1WTKLitn3zzQxmVhor58FFrNuZ XDhjkLQH3mBsgtG/LmrS0xoeBVUYlOPp+xZk4Lqj0dddU20Wd9Xdp5FUxy+ZVBMlph k+skK76Dj43h4Yd3jR5b8OtYF2GqWZWOtSD9IoKQROjy8Amg458Y8dJ1CsudXrgyP8 w875mxdQrc8Ag== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:45 +0100 Subject: [PATCH v7 16/29] KVM: arm64: Support SME control registers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-16-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=4807; i=broonie@kernel.org; h=from:subject:message-id; bh=0fLGhfB6VaFN9V2OPaprNenzTUhxjwQ4WMNFeuSowXY=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83EVDbH8kbLyWgiAxxl33xkta6QdpR/6PkP0 j82HY5UiZCJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNxAAKCRAk1otyXVSH 0OkpB/9IdtL6rqg4nxPNX61/jxuwXDiCWZIT8+8Qp+Iks4x8mMoZgjnHDnXU/i6pcbHvMHEcUY4 X20+MCiX5y4rL/JXAyHXhk2aHrvbU4qfLxYc/nUpCTGB0ccvgQcy+lWqZD8OpbSDJD64jpdenWu W5JdwHMc2zaQpGfjdOlav33LrU3bfGOkf4DIkcNINoqaQuWVjJ7K/Jg1DbSUldjlyfLXwDEvpop mJYeRyfsOIq57WawUPEgr/5Eymvd2HtuvAunQkWnhU/EJ8wXb2z07oRhhxohYZLJBZExDMJQMjb sVuv0qnTpn5xymaGkQmiUuFO3e6f+JyaaiIzmKXrrtlXtE0G X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME is configured by the system registers SMCR_EL1 and SMCR_EL2, add definitions and userspace access for them. These control the SME vector length in a manner similar to that for SVE and also have feature enable bits for SME2 and FA64. A subsequent patch will add management of them for guests as part of the general floating point context switch, as is done for the equivalent SVE registers. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/include/asm/vncr_mapping.h | 1 + arch/arm64/kvm/sys_regs.c | 37 +++++++++++++++++++++++++++++++= +++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 4348f297b5ae..edb2acdb4bd1 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -506,6 +506,7 @@ enum vcpu_sysreg { CPTR_EL2, /* Architectural Feature Trap Register (EL2) */ HACR_EL2, /* Hypervisor Auxiliary Control Register */ ZCR_EL2, /* SVE Control Register (EL2) */ + SMCR_EL2, /* SME Control Register (EL2) */ TTBR0_EL2, /* Translation Table Base Register 0 (EL2) */ TTBR1_EL2, /* Translation Table Base Register 1 (EL2) */ TCR_EL2, /* Translation Control Register (EL2) */ @@ -544,6 +545,7 @@ enum vcpu_sysreg { VNCR(ACTLR_EL1),/* Auxiliary Control Register */ VNCR(CPACR_EL1),/* Coprocessor Access Control */ VNCR(ZCR_EL1), /* SVE Control */ + VNCR(SMCR_EL1), /* SME Control */ VNCR(TTBR0_EL1),/* Translation Table Base Register 0 */ VNCR(TTBR1_EL1),/* Translation Table Base Register 1 */ VNCR(TCR_EL1), /* Translation Control Register */ diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm= /vncr_mapping.h index f6ec500ad3fa..5ab6a964bccf 100644 --- a/arch/arm64/include/asm/vncr_mapping.h +++ b/arch/arm64/include/asm/vncr_mapping.h @@ -44,6 +44,7 @@ #define VNCR_HDFGWTR_EL2 0x1D8 #define VNCR_ZCR_EL1 0x1E0 #define VNCR_HAFGRTR_EL2 0x1E8 +#define VNCR_SMCR_EL1 0x1F0 #define VNCR_TTBR0_EL1 0x200 #define VNCR_TTBR1_EL1 0x210 #define VNCR_FAR_EL1 0x220 diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 111b07a78787..81742e9237c0 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -142,6 +142,7 @@ static bool get_el2_to_el1_mapping(unsigned int reg, MAPPED_EL2_SYSREG(ELR_EL2, ELR_EL1, NULL ); MAPPED_EL2_SYSREG(SPSR_EL2, SPSR_EL1, NULL ); MAPPED_EL2_SYSREG(ZCR_EL2, ZCR_EL1, NULL ); + MAPPED_EL2_SYSREG(SMCR_EL2, SMCR_EL1, NULL ); MAPPED_EL2_SYSREG(CONTEXTIDR_EL2, CONTEXTIDR_EL1, NULL ); MAPPED_EL2_SYSREG(SCTLR2_EL2, SCTLR2_EL1, NULL ); default: @@ -2589,6 +2590,37 @@ static bool access_gic_elrsr(struct kvm_vcpu *vcpu, return true; } =20 +static unsigned int sme_el2_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + return __el2_visibility(vcpu, rd, sme_visibility); +} + +static bool access_smcr_el2(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + unsigned int vq; + u64 smcr; + + if (guest_hyp_sve_traps_enabled(vcpu)) { + kvm_inject_nested_sve_trap(vcpu); + return true; + } + + if (!p->is_write) { + p->regval =3D vcpu_read_sys_reg(vcpu, SMCR_EL2); + return true; + } + + smcr =3D p->regval; + vq =3D SYS_FIELD_GET(SMCR_ELx, LEN, smcr) + 1; + vq =3D min(vq, vcpu_sme_max_vq(vcpu)); + vcpu_write_sys_reg(vcpu, SYS_FIELD_PREP(SMCR_ELx, LEN, vq - 1), + SMCR_EL2); + return true; +} + static unsigned int s1poe_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { @@ -3035,7 +3067,7 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { { SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility =3D sve= _visibility }, { SYS_DESC(SYS_TRFCR_EL1), undef_access }, { SYS_DESC(SYS_SMPRI_EL1), undef_access }, - { SYS_DESC(SYS_SMCR_EL1), undef_access }, + { SYS_DESC(SYS_SMCR_EL1), NULL, reset_val, SMCR_EL1, 0, .visibility =3D s= me_visibility }, { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 }, { SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 }, { SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 }, @@ -3391,6 +3423,9 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { =20 EL2_REG_VNCR(HCRX_EL2, reset_val, 0), =20 + EL2_REG_FILTERED(SMCR_EL2, access_smcr_el2, reset_val, 0, + sme_el2_visibility), + EL2_REG(TTBR0_EL2, access_rw, reset_val, 0), EL2_REG(TTBR1_EL2, access_rw, reset_val, 0), EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1), --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BAA411FBEA6; Fri, 22 Aug 2025 01:55:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827731; cv=none; b=dLSvP2CLp9r/nnfgBXSX/9CG1RGhYBrVDefsJ1TIe9rMss4KAK/16lh+3cMyga7E4wT5SNrveOJDn7jRsJoMNyphCaOS1oJnl1kJKuXKdyU0GAbhzSsVHXxuxBboLJh/vLx3+36yqsKoPpjVhHgeNlZfzS3wIgzxqevx30wLXD0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827731; c=relaxed/simple; bh=s9OgbUV3jMegR4yK5YJZn39bA8MN2bqc20M/qGI/rlg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ig/H/aLnrrKFgneC0p1zBdw/FnBVWYrFgBDjPtgSZ4Y6hXEeWENYYufcarPFoNHCWnFsQM+GMDdTfAsajdXQkh6pB9aaQV03C1wzXcgZWpv7MbTWpr9Hw9AbeP+lSseDDX16HWUP6sfbUiqPlgryvBChzCTpgsgYIP4P7MpRil4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r8+F/bPw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="r8+F/bPw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05D9FC4CEEB; Fri, 22 Aug 2025 01:55:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827731; bh=s9OgbUV3jMegR4yK5YJZn39bA8MN2bqc20M/qGI/rlg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=r8+F/bPwDnjx3PW+1K+PfYpsYZOG3boGlYS+v7yXc7666DiMo7cMMmz/C1F/CjieN A0V1++nJtJzwRwweFNbHcrf/TWyOGGvb5J0eZYOg3Tzr3/SNfFV6V4n+2qSPH46jxl Ql2ZGOO4r0dl93hQ9pTxaMKQ57LaGgjenFlNsb++ZBXX804NZCHK7cmGKqzhs23HyF Y2YNpLNtHsiAw0cp1Qr84ek3m2FuXqGauacG70TP1Bs5/hDmoscVDIW1EM4RDM7/PQ v5u6UK97sPmkW7U4+SZPAQlR+X2zsoZb7BUUmbg2a3KvvJIJYoB6iZ621Tx48+J843 s5C+NDIoLew9Q== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:46 +0100 Subject: [PATCH v7 17/29] KVM: arm64: Support TPIDR2_EL0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-17-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=3465; i=broonie@kernel.org; h=from:subject:message-id; bh=s9OgbUV3jMegR4yK5YJZn39bA8MN2bqc20M/qGI/rlg=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83FGVS0KWqKNvAlONV3hETel4NcSUAM/aj0j 0aoaNpVSJKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNxQAKCRAk1otyXVSH 0NzWB/9KKtPaXuIKr/ECc2Rv/FcTi1K4u1461JdAw19F2JZS2w0WMjSSN+prsvnTIFjqaA27yzm kZxn+CdPlsC3RwDbbgnjTZ8OzsG1wcMltmWAGyzbnbbi4pPE8y3bzED/RqusY4UROoav0ULUPTX Rd2QJNU99KfdK0R2wPtITQyZy2B4dyA7gyX5IePoGQfmZ9IpMSBc551EvH57sLEfOJZ3OOYUw32 mfpOMd8YYv0T7iyM9udn5dtJEHlIJo1IoKlanksKx6Avq9Rm0OQUwQqoMDgsLvbUtv/ubKMlzFO 1NCSjIB6blIgQNFm88TNL/rbX6ggGBpBtHLogWsi3M2Zj97O X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME adds a new thread ID register, TPIDR2_EL0. This is used in userspace for delayed saving of the ZA state but in terms of the architecture is not really connected to SME other than being part of FEAT_SME. It has an independent fine grained trap and the runtime connection with the rest of SME is purely software defined. Expose the register as a system register if the guest supports SME, context switching it along with the other EL0 TPIDRs. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 15 +++++++++++++++ arch/arm64/kvm/sys_regs.c | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index edb2acdb4bd1..632c74397fa9 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -450,6 +450,7 @@ enum vcpu_sysreg { CSSELR_EL1, /* Cache Size Selection Register */ TPIDR_EL0, /* Thread ID, User R/W */ TPIDRRO_EL0, /* Thread ID, User R/O */ + TPIDR2_EL0, /* Thread ID, Register 2 */ TPIDR_EL1, /* Thread ID, Privileged */ CNTKCTL_EL1, /* Timer Control Register (EL1) */ PAR_EL1, /* Physical Address Register */ diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hy= p/include/hyp/sysreg-sr.h index 5624fd705ae3..8c3b3d6df99f 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -88,6 +88,17 @@ static inline bool ctxt_has_sctlr2(struct kvm_cpu_contex= t *ctxt) return kvm_has_sctlr2(kern_hyp_va(vcpu->kvm)); } =20 +static inline bool ctxt_has_sme(struct kvm_cpu_context *ctxt) +{ + struct kvm_vcpu *vcpu; + + if (!system_supports_sme()) + return false; + + vcpu =3D ctxt_to_vcpu(ctxt); + return kvm_has_sme(kern_hyp_va(vcpu->kvm)); +} + static inline bool ctxt_is_guest(struct kvm_cpu_context *ctxt) { return host_data_ptr(host_ctxt) !=3D ctxt; @@ -127,6 +138,8 @@ static inline void __sysreg_save_user_state(struct kvm_= cpu_context *ctxt) { ctxt_sys_reg(ctxt, TPIDR_EL0) =3D read_sysreg(tpidr_el0); ctxt_sys_reg(ctxt, TPIDRRO_EL0) =3D read_sysreg(tpidrro_el0); + if (ctxt_has_sme(ctxt)) + ctxt_sys_reg(ctxt, TPIDR2_EL0) =3D read_sysreg_s(SYS_TPIDR2_EL0); } =20 static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) @@ -204,6 +217,8 @@ static inline void __sysreg_restore_user_state(struct k= vm_cpu_context *ctxt) { write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL0), tpidr_el0); write_sysreg(ctxt_sys_reg(ctxt, TPIDRRO_EL0), tpidrro_el0); + if (ctxt_has_sme(ctxt)) + write_sysreg_s(ctxt_sys_reg(ctxt, TPIDR2_EL0), SYS_TPIDR2_EL0); } =20 static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt, diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 81742e9237c0..4166d396450d 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -3243,7 +3243,8 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { .visibility =3D s1poe_visibility }, { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 }, { SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 }, - { SYS_DESC(SYS_TPIDR2_EL0), undef_access }, + { SYS_DESC(SYS_TPIDR2_EL0), NULL, reset_unknown, TPIDR2_EL0, + .visibility =3D sme_visibility}, =20 { SYS_DESC(SYS_SCXTNUM_EL0), undef_access }, =20 --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 945E61BCA1C; Fri, 22 Aug 2025 01:55:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827739; cv=none; b=nGDnliahkMQtT0rNy3fB9BxaxAEjUqw0l2uo6AlTguGSq4t80eOOh4abRdRt/KkABSlPiQX5yOU2XBRqARR1iERD4SJkxZpWuhX0ltvH86QFVSbTgwGQaac2ucieEIt8UVUBqQ5t4ZNALfk+F9+VoBXeULZOJCYLMCeQcNTaaSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827739; c=relaxed/simple; bh=IOvRUXTwez4vce4kM+TbWeJxICUO2t5XVZ3KjPI4DQM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RVhinI/qrU09788XoFnrg2abYeRSEEn8a0i8fIkKtfKC1c1dtdk+iU9tU7Fzqv7wk/hONCB3VFgAvz6KHiOUI0Xs9sqNcWHaJJb2zms/sm1wSu3nGQrmTL/EBg6NSeNIV5gVeGn86vfIzIBWUAe/dusle+lHG43Sry+l1RIGog0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LkTr4XKz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LkTr4XKz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BC743C116B1; Fri, 22 Aug 2025 01:55:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827735; bh=IOvRUXTwez4vce4kM+TbWeJxICUO2t5XVZ3KjPI4DQM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LkTr4XKzSXMDetbtF3VAbW2WQY9IeETcVprfxGalWVAbsO5aZi+TWpSb6MHvp+V20 5ETu6ZXMm9KdrwfWQXIsuB7uObYgw/hTi5zM0KAAb7h01n3YWg+7s2nBT+5K4X7ZQm D0k5AXIP+xHYzuXZ+K3rydVeShuzw3PcTOL73YPJ0K4B3AKZ8Y+b4ObVdI7BuO9X3u yiD5rrttGIbp7uJz7mqEHJhoB3er3srWwdw+poTgzuCczDDtBlsLS7jVOryH0s5B6c F7NXYwtOJb8dx4gm8DPqkcadhubnVTBfALnEznAe3YsBqczCNVRvok6+VqVAUwg2L4 dGLSx3lsfAwjA== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:47 +0100 Subject: [PATCH v7 18/29] KVM: arm64: Support SME identification registers for guests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-18-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=8730; i=broonie@kernel.org; h=from:subject:message-id; bh=IOvRUXTwez4vce4kM+TbWeJxICUO2t5XVZ3KjPI4DQM=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83GfeRhm6vELQacBT8HaenDNhdCViMFhS/0O xrz6Vm1TnqJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNxgAKCRAk1otyXVSH 0P/9B/94rs3QmdVFCbJZmIaRUyQuiw2t4Opl7ShKmrUq2jbrv7zGyVGMn4DP2gIjY90bynjPbii Yn2iBP8fu6WhVXqyMrDHXIX1MtQ+jtHvNAvrQtThmM99/mSDYhD5W+SVf1S56d4XTiqehhQ2+3m u3NlSXjPDAzDfVXAKztR/4+6rHXHNYl29yMv4W+/i18p5iwB7XQ9KB1QDUPjcVji1IUhU8dBSt3 8F1w3h1o5pkjV3jgnEtI3LZIkd9jFmD8XiCFS74H5O3qBdjqxGhmgUDfOJFxu/QbZgsm22Yozre 4OO74092Hm+vCYF2YaBXUd7kargwdjZZA/c3GoYySU+tb2on X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB The primary register for identifying SME is ID_AA64PFR1_EL1.SME. This is hidden from guests unless SME is enabled by the VMM. When it is visible it is writable and can be used to control the availability of SME2. There is also a new register ID_AA64SMFR0_EL1 which we make writable, forcing it to all bits 0 if SME is disabled. This includes the field SMEver giving the SME version, userspace is responsible for ensuring the value is consistent with ID_AA64PFR1_EL1.SME. It also includes FA64, a separately enableable extension which provides the full FPSIMD and SVE instruction set including FFR in streaming mode. Userspace can control the availability of FA64 by writing to this field. The other features enumerated there only add new instructions, there are no architectural controls for these. There is a further identification register SMIDR_EL1 which provides a basic description of the SME microarchitecture, in a manner similar to MIDR_EL1 for the PE. It also describes support for priority management and a basic affinity description for shared SME units, plus some RES0 space. We do not support priority management for guests so this is hidden from guests, along with any new fields. As for MIDR_EL1 and REVIDR_EL1 we expose the implementer and revision information to guests with the raw value from the CPU we are running on, this may present issues for asymmetric systems or for migration as it does for the existing registers. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 3 +++ arch/arm64/kvm/config.c | 8 +------ arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 11 +++++++++ arch/arm64/kvm/hyp/nvhe/pkvm.c | 4 +++- arch/arm64/kvm/sys_regs.c | 37 ++++++++++++++++++++++++++= ---- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 632c74397fa9..5225dd9b752c 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -402,6 +402,7 @@ struct kvm_arch { u64 revidr_el1; u64 aidr_el1; u64 ctr_el0; + u64 smidr_el1; =20 /* Masks for VNCR-backed and general EL2 sysregs */ struct kvm_sysreg_masks *sysreg_masks; @@ -1646,6 +1647,8 @@ static inline u64 *__vm_id_reg(struct kvm_arch *ka, u= 32 reg) return &ka->revidr_el1; case SYS_AIDR_EL1: return &ka->aidr_el1; + case SYS_SMIDR_EL1: + return &ka->smidr_el1; default: WARN_ON_ONCE(1); return NULL; diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c index da66c4a14775..a08e89e210d8 100644 --- a/arch/arm64/kvm/config.c +++ b/arch/arm64/kvm/config.c @@ -208,14 +208,8 @@ static bool feat_anerr(struct kvm *kvm) =20 static bool feat_sme_smps(struct kvm *kvm) { - /* - * Revists this if KVM ever supports SME -- this really should - * look at the guest's view of SMIDR_EL1. Funnily enough, this - * is not captured in the JSON file, but only as a note in the - * ARM ARM. - */ return (kvm_has_feat(kvm, FEAT_SME) && - (read_sysreg_s(SYS_SMIDR_EL1) & SMIDR_EL1_SMPS)); + (kvm_read_vm_id_reg(kvm, SYS_SMIDR_EL1) & SMIDR_EL1_SMPS)); } =20 static bool feat_spe_fds(struct kvm *kvm) diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hy= p/include/hyp/sysreg-sr.h index 8c3b3d6df99f..d921db152119 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -125,6 +125,17 @@ static inline u64 ctxt_midr_el1(struct kvm_cpu_context= *ctxt) return kvm_read_vm_id_reg(kvm, SYS_MIDR_EL1); } =20 +static inline u64 ctxt_smidr_el1(struct kvm_cpu_context *ctxt) +{ + struct kvm *kvm =3D kern_hyp_va(ctxt_to_vcpu(ctxt)->kvm); + + if (!(ctxt_is_guest(ctxt) && + test_bit(KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS, &kvm->arch.flags))) + return read_sysreg_s(SYS_SMIDR_EL1); + + return kvm_read_vm_id_reg(kvm, SYS_SMIDR_EL1); +} + static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt) { *ctxt_mdscr_el1(ctxt) =3D read_sysreg(mdscr_el1); diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 65c49a5c7091..fc9fb2e693f6 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -338,8 +338,10 @@ static void pkvm_init_features_from_host(struct pkvm_h= yp_vm *hyp_vm, const struc host_kvm->arch.vcpu_features, KVM_VCPU_MAX_FEATURES); =20 - if (test_bit(KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS, &host_arch_flags)) + if (test_bit(KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS, &host_arch_flags)) { hyp_vm->kvm.arch.midr_el1 =3D host_kvm->arch.midr_el1; + hyp_vm->kvm.arch.smidr_el1 =3D host_kvm->arch.smidr_el1; + } =20 return; } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 4166d396450d..36ba1986e7a1 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1612,7 +1612,9 @@ static u64 __kvm_read_sanitised_id_reg(const struct k= vm_vcpu *vcpu, val &=3D ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_MTE_frac); } =20 - val &=3D ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME); + if (!vcpu_has_sme(vcpu)) + val &=3D ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_SME); + val &=3D ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_RNDR_trap); val &=3D ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_NMI); val &=3D ~ARM64_FEATURE_MASK(ID_AA64PFR1_EL1_GCS); @@ -1731,6 +1733,10 @@ static unsigned int id_visibility(const struct kvm_v= cpu *vcpu, if (!vcpu_has_sve(vcpu)) return REG_RAZ; break; + case SYS_ID_AA64SMFR0_EL1: + if (!vcpu_has_sme(vcpu)) + return REG_RAZ; + break; } =20 return 0; @@ -1758,10 +1764,25 @@ static unsigned int raz_visibility(const struct kvm= _vcpu *vcpu, =20 /* cpufeature ID register access trap handlers */ =20 +static bool hidden_id_reg(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + switch (reg_to_encoding(r)) { + case SYS_SMIDR_EL1: + return !vcpu_has_sme(vcpu); + default: + return false; + } +} + static bool access_id_reg(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) { + if (hidden_id_reg(vcpu, p, r)) + return bad_trap(vcpu, p, r, "write to hidden ID register"); + if (p->is_write) return write_to_read_only(vcpu, p, r); =20 @@ -2789,12 +2810,15 @@ static bool access_imp_id_reg(struct kvm_vcpu *vcpu, static u64 __ro_after_init boot_cpu_midr_val; static u64 __ro_after_init boot_cpu_revidr_val; static u64 __ro_after_init boot_cpu_aidr_val; +static u64 __ro_after_init boot_cpu_smidr_val; =20 static void init_imp_id_regs(void) { boot_cpu_midr_val =3D read_sysreg(midr_el1); boot_cpu_revidr_val =3D read_sysreg(revidr_el1); boot_cpu_aidr_val =3D read_sysreg(aidr_el1); + if (system_supports_sme()) + boot_cpu_smidr_val =3D read_sysreg_s(SYS_SMIDR_EL1); } =20 static u64 reset_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_de= sc *r) @@ -2806,6 +2830,8 @@ static u64 reset_imp_id_reg(struct kvm_vcpu *vcpu, co= nst struct sys_reg_desc *r) return boot_cpu_revidr_val; case SYS_AIDR_EL1: return boot_cpu_aidr_val; + case SYS_SMIDR_EL1: + return boot_cpu_smidr_val; default: KVM_BUG_ON(1, vcpu->kvm); return 0; @@ -2972,7 +2998,6 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { ID_AA64PFR1_EL1_MTE_frac | ID_AA64PFR1_EL1_NMI | ID_AA64PFR1_EL1_RNDR_trap | - ID_AA64PFR1_EL1_SME | ID_AA64PFR1_EL1_RES0 | ID_AA64PFR1_EL1_MPAM_frac | ID_AA64PFR1_EL1_RAS_frac | @@ -2983,7 +3008,7 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { ID_AA64PFR2_EL1_MTESTOREONLY), ID_UNALLOCATED(4,3), ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0), - ID_HIDDEN(ID_AA64SMFR0_EL1), + ID_WRITABLE(ID_AA64SMFR0_EL1, ~ID_AA64SMFR0_EL1_RES0), ID_UNALLOCATED(4,6), ID_WRITABLE(ID_AA64FPFR0_EL1, ~ID_AA64FPFR0_EL1_RES0), =20 @@ -3185,7 +3210,11 @@ static const struct sys_reg_desc sys_reg_descs[] =3D= { { SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1, .set_user =3D set_clidr, .val =3D ~CLIDR_EL1_RES0 }, { SYS_DESC(SYS_CCSIDR2_EL1), undef_access }, - { SYS_DESC(SYS_SMIDR_EL1), undef_access }, + IMPLEMENTATION_ID(SMIDR_EL1, (SMIDR_EL1_NSMC | SMIDR_EL1_HIP | + SMIDR_EL1_AFFINITY2 | + SMIDR_EL1_IMPLEMENTER | + SMIDR_EL1_REVISION | SMIDR_EL1_SH | + SMIDR_EL1_AFFINITY)), IMPLEMENTATION_ID(AIDR_EL1, GENMASK_ULL(63, 0)), { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 }, ID_FILTERED(CTR_EL0, ctr_el0, --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 51BFD28B4E1; Fri, 22 Aug 2025 01:55:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827740; cv=none; b=HSyYLN14HfEGx7FKVS2wuDOu519tJUV7JNFV/99/3VjC1TZR2ci5PpO0K8c/cFGxEw4sPSUmoGV9c62yErAGipm9+s+jpUnj83ZbnbQEUUvVxNxeWkq2wtbgQH78RVu0v5LmHyHHt2G2wx3JM2r3bdwecod3ZJEusFGgBe6nVpw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827740; c=relaxed/simple; bh=MAZZlV6eUub7krRK8EsIsDbLy5E7LRegIDDazNCSgqc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qtaaX5t6/x4ovmomS2LrEXk8NAONVeuCDC/mj21nUz7hE51GdknujeAH8QvzQOze3qvCxgyPBFGhX7rUHndmE7gY8GRfdVFK9Ix0zXPIrl87cq72qs7GY2l3Vemj5Sy0dgqXkVkXRVE7Vcd6sro3YQYbCGMCiiNxB7y6hV5vbsw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=O7iXix1R; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="O7iXix1R" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7D02EC116C6; Fri, 22 Aug 2025 01:55:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827738; bh=MAZZlV6eUub7krRK8EsIsDbLy5E7LRegIDDazNCSgqc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=O7iXix1RKZNh2lmsBj4W6gcd1LHSVXPjast+WjRtkx98q/SrGxEwv/brh8N6lZHEI bSeqJdkvRmUJ2/bKSS9ROu6NenEu7LGoUi9NlIEbdZRd+chk913p7Y9F12wd9InYaG LTnP/X4PaJcnp7JeUp9LmqFLwHvrgck1My0W7M/DVD9gZij+ZzV31cQ8oX8yGrDckd 6Un9hXICytN2+/+8G2i1zNNNlqxi3HH60Zj2yxBQsFRmfCTaTkgCv07ZvH7pzMoJRR 06bWp04nB3ErekjkRjA4GiOt11Qklj3anwQacBXHVOA5OXZAYj7fsabfUZXMkh3BHk lU9dVIcwroynQ== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:48 +0100 Subject: [PATCH v7 19/29] KVM: arm64: Support SME priority registers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-19-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=5778; i=broonie@kernel.org; h=from:subject:message-id; bh=MAZZlV6eUub7krRK8EsIsDbLy5E7LRegIDDazNCSgqc=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83H47ZqfLuXd4yOwd5EVdItCuq2sPS1eGpde mHGkH2o35qJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNxwAKCRAk1otyXVSH 0P9eB/97Bd330dA9+rISpYO8P3owtayHYl6ppE+RRcQRLCTSW66rnx+myThRCp2keOvzuKs4D9i awk653VM268WAi6iBZmCK0uBNhsc+n3ifvdh42034+S+yKU32DwxdHt6yOs2/XPCVhw+grdK7V1 3Pd2QrVAVTCryf7xwa7qzp7ZR7fCvtg1J5prh1i7S5gOC2NPEEYxulAlEI4jSPr7HTCK1BG5yla uilBns4GTAARETTMqhASgdYKkg5pA9otUPM1veAdbq9rnXDbib20oB1FEzvM9TPCuxFaEN3lBAp mYc4JQonbLFuk6kJrk3Hc5hYgUBBGPRnYNOQmuicC6LhoCfg X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME has optional support for configuring the relative priorities of PEs in systems where they share a single SME hardware block, known as a SMCU. Currently we do not have any support for this in Linux and will also hide it from KVM guests, pending experience with practical implementations. The interface for configuring priority support is via two new system registers, these registers are always defined when SME is available. The register SMPRI_EL1 allows control of SME execution priorities. Since we disable SME priority support for guests this register is RES0, define it as such and enable fine grained traps for SMPRI_EL1 to ensure that guests can't write to it even if the hardware supports priorites. Since the register should be readable with fixed contents we only trap writes, not reads. There is also an EL2 register SMPRIMAP_EL2 for virtualisation of priorities, this is RES0 when priority configuration is not supported but has no specific traps available. When saving state from a nested guest we overwite any value the guest stored. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/include/asm/vncr_mapping.h | 1 + arch/arm64/kvm/hyp/vhe/sysreg-sr.c | 7 +++++++ arch/arm64/kvm/sys_regs.c | 33 +++++++++++++++++++++++++++++++= +- 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 5225dd9b752c..ebc516fe09db 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -548,6 +548,7 @@ enum vcpu_sysreg { VNCR(CPACR_EL1),/* Coprocessor Access Control */ VNCR(ZCR_EL1), /* SVE Control */ VNCR(SMCR_EL1), /* SME Control */ + VNCR(SMPRIMAP_EL2), /* Streaming Mode Priority Mapping Register */ VNCR(TTBR0_EL1),/* Translation Table Base Register 0 */ VNCR(TTBR1_EL1),/* Translation Table Base Register 1 */ VNCR(TCR_EL1), /* Translation Control Register */ diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm= /vncr_mapping.h index 5ab6a964bccf..670a2f81847c 100644 --- a/arch/arm64/include/asm/vncr_mapping.h +++ b/arch/arm64/include/asm/vncr_mapping.h @@ -45,6 +45,7 @@ #define VNCR_ZCR_EL1 0x1E0 #define VNCR_HAFGRTR_EL2 0x1E8 #define VNCR_SMCR_EL1 0x1F0 +#define VNCR_SMPRIMAP_EL2 0x1F0 #define VNCR_TTBR0_EL1 0x200 #define VNCR_TTBR1_EL1 0x210 #define VNCR_FAR_EL1 0x220 diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sy= sreg-sr.c index f28c6cf4fe1b..07aa4378c58a 100644 --- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c @@ -80,6 +80,13 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vc= pu) =20 if (ctxt_has_sctlr2(&vcpu->arch.ctxt)) __vcpu_assign_sys_reg(vcpu, SCTLR2_EL2, read_sysreg_el1(SYS_SCTLR2)); + + /* + * We block SME priorities so SMPRIMAP_EL2 is RES0, however we + * do not have traps to block access so the guest might have + * updated the state, overwrite anything there. + */ + __vcpu_assign_sys_reg(vcpu, SMPRIMAP_EL2, 0); } =20 static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 36ba1986e7a1..7284705a5f0a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -552,6 +552,15 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu, return read_zero(vcpu, p); } =20 +static int set_res0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + u64 val) +{ + if (val) + return -EINVAL; + + return 0; +} + /* * ARMv8.1 mandates at least a trivial LORegion implementation, where all = the * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0 @@ -1819,6 +1828,15 @@ static unsigned int fp8_visibility(const struct kvm_= vcpu *vcpu, return REG_HIDDEN; } =20 +static unsigned int sme_raz_visibility(const struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) +{ + if (vcpu_has_sme(vcpu)) + return REG_RAZ; + + return REG_HIDDEN; +} + static u64 sanitise_id_aa64pfr0_el1(const struct kvm_vcpu *vcpu, u64 val) { if (!vcpu_has_sve(vcpu)) @@ -3091,7 +3109,14 @@ static const struct sys_reg_desc sys_reg_descs[] =3D= { =20 { SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility =3D sve= _visibility }, { SYS_DESC(SYS_TRFCR_EL1), undef_access }, - { SYS_DESC(SYS_SMPRI_EL1), undef_access }, + + /* + * SMPRI_EL1 is UNDEF when SME is disabled, the UNDEF is + * handled via FGU which is handled without consulting this + * table. + */ + { SYS_DESC(SYS_SMPRI_EL1), trap_raz_wi, .visibility =3D sme_raz_visibilit= y }, + { SYS_DESC(SYS_SMCR_EL1), NULL, reset_val, SMCR_EL1, 0, .visibility =3D s= me_visibility }, { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 }, { SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 }, @@ -3453,6 +3478,9 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { =20 EL2_REG_VNCR(HCRX_EL2, reset_val, 0), =20 + { SYS_DESC(SYS_SMPRIMAP_EL2), .reg =3D SMPRIMAP_EL2, + .access =3D trap_raz_wi, .set_user =3D set_res0, .reset =3D reset_val, + .val =3D 0, .visibility =3D sme_el2_visibility }, EL2_REG_FILTERED(SMCR_EL2, access_smcr_el2, reset_val, 0, sme_el2_visibility), =20 @@ -5379,6 +5407,9 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) compute_fgu(kvm, HFGITR2_GROUP); compute_fgu(kvm, HDFGRTR2_GROUP); =20 + if (kvm_has_feat(kvm, ID_AA64PFR1_EL1, SME, IMP)) + kvm->arch.fgt[HFGWTR_GROUP] |=3D HFGWTR_EL2_nSMPRI_EL1_MASK; + set_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags); out: mutex_unlock(&kvm->arch.config_lock); --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 135E528E571; Fri, 22 Aug 2025 01:55:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827744; cv=none; b=Dia/iWaK1BK7kwrYfsVAHF1NWCwz1K9BdAHqVDD9jTWbct6cn7TGUFnMADYnTdWtnzsIhLv0c2Z/63FRe13Ah62EGnOcKUSedgW35wdWILq8StPmWa+F5G5osd/l9c1cOcHNMd2Xgak0ec1GspT9Gv8Y9mSoULUE/YQFtD1nfSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827744; c=relaxed/simple; bh=eko0M/1IoNzmkVmBa1f5aR4hGKuIltnrGwhCOTIwAnI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SsWiotIeD51YYNeN8Ko57wysV8syh2ZvhP+FCgDqea+NTCidBsm0zREjD2pvmqfb4SnMbPLga2GJ8OY8grynsl+eO82ZOphSYFoUP9kX1Sech4K6yiTm7uNa2UoVZ28A4QTZrqFwctxXnGVw9yFhls1WlWYGT7s1oqMFlHwu+2A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S2+QZuHp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="S2+QZuHp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C82BC113D0; Fri, 22 Aug 2025 01:55:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827742; bh=eko0M/1IoNzmkVmBa1f5aR4hGKuIltnrGwhCOTIwAnI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=S2+QZuHpH6eDMNPX0FRylkbgWM9BVxPu0FszJe82QsLIqdG4OpnJKpN74QrkOt6e2 A61hNPAoEClh879pkGje4WXMFKztvuFAu+qzOfj50Av9Q+7SHTwGmm/t1JyuhOE3F1 TUP6uLPEpjqQWFBzWtRVWPe/wdYzDudikj7pi7Zg8l15XWLjEkzGukcAwaS45gJAC2 /fygnpvEkGkTMJDIx0HmbG56C9f2kyan6G5nro4wEKANozOV7/woRJQ79iHWhD9KS9 li5pFbkMW66PXHhPR/kl01TwgEmJfhlxqVnFdI8NsRsuQS08o4qRhWE0gxFpsAUfH6 LqS8hJO+FKh8A== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:49 +0100 Subject: [PATCH v7 20/29] KVM: arm64: Provide assembly for SME register access Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-20-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=1851; i=broonie@kernel.org; h=from:subject:message-id; bh=eko0M/1IoNzmkVmBa1f5aR4hGKuIltnrGwhCOTIwAnI=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83I+IndHAqLMki3155WeFFGLW5uEdsLLqc8X Ls4dDo7JIiJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNyAAKCRAk1otyXVSH 0Fr5B/95xLO97ePuVChS1XQAhqSMl+jf/Cdb+OuygtjCY9ba7d8h39WXZZJbUb4pXLSlqVm5uJw 0WkQ4a/IbbKwJaI4NnVtO3pBZtJvGnqn8lGAEGgXoBO7MOH7Z30uzt8mOMBjXQLPTXkZ5OiIEh9 A+j7eugheVEU2xth82Lgvr5lCX0v17pHomg68+D/YnGx0VL120/Wg0K3D3+i/x1CxZi7pMpPFqr mONxfpY2l5V1rKP4S2tD7WIAdOuh426oG5YfR7d6H7ux/+1ej1Ept7b658CWwxtLa7BDiqgj+xW I8X51+VFH0i52BYefy3WzyFKdlHLXwBCIS9nmmvw593Q5hpj X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Provide versions of the SME state save and restore functions for the hypervisor to allow it to restore ZA and ZT for guests. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_hyp.h | 3 +++ arch/arm64/kvm/hyp/fpsimd.S | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_= hyp.h index 0ad5a66e0d25..1c31d8b26aa9 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -115,6 +115,9 @@ void __fpsimd_save_state(struct user_fpsimd_state *fp_r= egs); void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs); void __sve_save_state(void *sve_pffr, u32 *fpsr, int save_ffr); void __sve_restore_state(void *sve_pffr, u32 *fpsr, int restore_ffr); +int __sve_get_vl(void); +void __sme_save_state(void const *state, bool restore_zt); +void __sme_restore_state(void const *state, bool restore_zt); =20 u64 __guest_enter(struct kvm_vcpu *vcpu); =20 diff --git a/arch/arm64/kvm/hyp/fpsimd.S b/arch/arm64/kvm/hyp/fpsimd.S index 6e16cbfc5df2..44a1b0a483da 100644 --- a/arch/arm64/kvm/hyp/fpsimd.S +++ b/arch/arm64/kvm/hyp/fpsimd.S @@ -29,3 +29,29 @@ SYM_FUNC_START(__sve_save_state) sve_save 0, x1, x2, 3 ret SYM_FUNC_END(__sve_save_state) + +SYM_FUNC_START(__sve_get_vl) + _sve_rdvl 0, 1 + ret +SYM_FUNC_END(__sve_get_vl) + +SYM_FUNC_START(__sme_save_state) + _sme_rdsvl 2, 1 // x2 =3D VL/8 + sme_save_za 0, x2, 12 // Leaves x0 pointing to the end of ZA + + cbz x1, 1f + _str_zt 0 +1: + ret +SYM_FUNC_END(__sme_save_state) + +SYM_FUNC_START(__sme_restore_state) + _sme_rdsvl 2, 1 // x2 =3D VL/8 + sme_load_za 0, x2, 12 // Leaves x0 pointing to end of ZA + + cbz x1, 1f + _ldr_zt 0 + +1: + ret +SYM_FUNC_END(__sme_restore_state) --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C1AD1212550; Fri, 22 Aug 2025 01:55:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827746; cv=none; b=K0SFG+eD6HNB7f/+6qnbHlDYS8s52rV2/rP7T9WMqLvzNQqpqrm8ihpjpcYq/fgmMvLJt0MnSTysyFAmjMFbk1pCBB9aRfixp0IhxNwTuoz+4xrLvxKoKVqoAyGeIUVO71oKZMd2zSef2Rmuetao80rniUvsXaXQva6b7aYGI54= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827746; c=relaxed/simple; bh=00XRQFjc7Pzb86pKVTknY1kmQGmcMmO43+orrAnZ8z0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y7Haf3XpwU/4GPre49qfXepO82eRdxiPRpWLEgmNxjWfQbL5y1FLVLPm3ZIqU+T+SEaFZEoUVCNsSSETRQgS2MeMigqkcMRVBtSC3/AaiS7ONhpT8Dwlaz7vyIwSRqWNBuCCSiDAEAfjN0MVubYK5UL0h23OcV2h6cHSw9MYzrE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RUQdJE+X; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RUQdJE+X" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EF3BBC4CEED; Fri, 22 Aug 2025 01:55:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827746; bh=00XRQFjc7Pzb86pKVTknY1kmQGmcMmO43+orrAnZ8z0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=RUQdJE+Xuki5V9clByjP5zYrRj7Sszgq1hOzJSyPd+QmJYFY2EPxIoK20Ui6ng4aP htG1dZ67YQHvHLt/1FzKwGKfopqH0VJYJz7GKbIOTw0M0P96k11O3903fmvES2166S HXtl0iljMbMDwOQsiREmzR3aLKEk33Z5R5ArdqSasaL4Vr+E3Gk8dqHz7hvUlCn0Qx qAnues4oSAWzVToR2KHiyXOi+zWpRkjzo1fJjCH5/OiI3jnsufdAz/2ZAzgohdpYnW 9n66zzJkheC4djh1Myv5lB8+6YI9vM718EuVh9KFquPiP4BoOh59D1UhPA11rurieo QdP21RjQRRIGA== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:50 +0100 Subject: [PATCH v7 21/29] KVM: arm64: Support userspace access to streaming mode Z and P registers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-21-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=4047; i=broonie@kernel.org; h=from:subject:message-id; bh=00XRQFjc7Pzb86pKVTknY1kmQGmcMmO43+orrAnZ8z0=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83IKm2oypArYGqg+pqZWs9DTXs95FBP9jgYO OJRgeOqH3aJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNyAAKCRAk1otyXVSH 0MnUCACCJjSn5O51eX/ek6Zku0QM1vXCv3HNJTRLC8sEO0fqBuEjqobfCnMXdJRM4bWdTENregn hZPkXmFALqadp563O4ppMfYj5w0VQ5yOMZkVqFxICrfh0+btKz4H6mTAJqNKdLEHNnpT/D2oLGa vlx1Hg+ljF+IwRJZUyo566eRdn82izA/4NnBbTvItTo9sbPtXH5ArxvUNCoMrCF9PnL0cs6FA0F QjaXaIO/kuZl5cpQnWrexV5peXmbR6UIlPC/S7AySyIzi4v6NK/XHsz1H4DwvAp4XFQaIcTbLgm YnFue90UqF9jQSiWzHmytep1Va2YZHTkjWcipvp0fMHMuwpe X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME introduces a mode called streaming mode where the Z, P and optionally FFR registers can be accessed using the SVE instructions but with the SME vector length. Reflect this in the ABI for accessing the guest registers by making the vector length for the vcpu reflect the vector length that would be seen by the guest were it running, using the SME vector length when the guest is configured for streaming mode. Since SME may be present without SVE we also update the existing checks for access to the Z, P and V registers to check for either SVE or streaming mode. When not in streaming mode the guest floating point state may be accessed via the V registers. Any VMM that supports SME must be aware of the need to configure streaming mode prior to writing the floating point registers that this creates. Signed-off-by: Mark Brown --- arch/arm64/kvm/guest.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index bcb0d565f1a4..013d66febf10 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -73,6 +73,11 @@ static u64 core_reg_offset_from_id(u64 id) return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE); } =20 +static bool vcpu_has_sve_regs(const struct kvm_vcpu *vcpu) +{ + return vcpu_has_sve(vcpu) || vcpu_in_streaming_mode(vcpu); +} + static int core_reg_size_from_offset(const struct kvm_vcpu *vcpu, u64 off) { int size; @@ -110,9 +115,10 @@ static int core_reg_size_from_offset(const struct kvm_= vcpu *vcpu, u64 off) /* * The KVM_REG_ARM64_SVE regs must be used instead of * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on - * SVE-enabled vcpus: + * SVE-enabled vcpus or when a SME enabled vcpu is in + * streaming mode: */ - if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off)) + if (vcpu_has_sve_regs(vcpu) && core_reg_offset_is_vreg(off)) return -EINVAL; =20 return size; @@ -426,6 +432,24 @@ struct vec_state_reg_region { unsigned int upad; /* extra trailing padding in user memory */ }; =20 +/* + * We represent the Z and P registers to userspace using either the + * SVE or SME vector length, depending on which features the guest has + * and if the guest is in streaming mode. + */ +static unsigned int vcpu_sve_cur_vq(struct kvm_vcpu *vcpu) +{ + unsigned int vq =3D 0; + + if (vcpu_has_sve(vcpu)) + vq =3D vcpu_sve_max_vq(vcpu); + + if (vcpu_in_streaming_mode(vcpu)) + vq =3D vcpu_sme_max_vq(vcpu); + + return vq; +} + /* * Validate SVE register ID and get sanitised bounds for user/kernel SVE * register copy @@ -466,7 +490,7 @@ static int sve_reg_to_region(struct vec_state_reg_regio= n *region, if (!vcpu_has_sve(vcpu) || (reg->id & SVE_REG_SLICE_MASK) > 0) return -ENOENT; =20 - vq =3D vcpu_sve_max_vq(vcpu); + vq =3D vcpu_sve_cur_vq(vcpu); =20 reqoffset =3D SVE_SIG_ZREG_OFFSET(vq, reg_num) - SVE_SIG_REGS_OFFSET; @@ -476,7 +500,7 @@ static int sve_reg_to_region(struct vec_state_reg_regio= n *region, if (!vcpu_has_sve(vcpu) || (reg->id & SVE_REG_SLICE_MASK) > 0) return -ENOENT; =20 - vq =3D vcpu_sve_max_vq(vcpu); + vq =3D vcpu_sve_cur_vq(vcpu); =20 reqoffset =3D SVE_SIG_PREG_OFFSET(vq, reg_num) - SVE_SIG_REGS_OFFSET; @@ -515,6 +539,9 @@ static int get_sve_reg(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (!kvm_arm_vcpu_vec_finalized(vcpu)) return -EPERM; =20 + if (!vcpu_has_sve_regs(vcpu)) + return -EBUSY; + if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset, region.klen) || clear_user(uptr + region.klen, region.upad)) @@ -541,6 +568,9 @@ static int set_sve_reg(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (!kvm_arm_vcpu_vec_finalized(vcpu)) return -EPERM; =20 + if (!vcpu_has_sve_regs(vcpu)) + return -EBUSY; + if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr, region.klen)) return -EFAULT; --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72B2B1C549F; Fri, 22 Aug 2025 01:55:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827750; cv=none; b=rWIpnjOiaBxNv1/HBfveOBc5n48KlYUUY56dkDmEJfxDzebrR2i+y+/v60Kxf6iHlTd7GEjAV3LtkJt+UDxLkXwSJehqP0Ep1ebKeBHk9j8Sy/D9xCBI6XaM/57alSKHrl+lfjr5xQhLoRlK8HWRBSqZh0kT8+XdbK0FP3hSAM0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827750; c=relaxed/simple; bh=K/O9CttzW0zt3QhDrAZF6NQXIZmkZnmyhsSNH3lWRrU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I+4yje2QVeVgpJRsO9RYkfZ8MyId3dfGJ3rh46SpCbA8UgGAvwXM2nicY5UVfai5RsA/k+n5WoCAh4TNdiLZCuplpQDc0qqdCmzGz2zuMIGJJzlxWYI7vIiCoTIqUi/Vgs2+zaoI16ZfsnQwJV03BjNJbMOoTFgQtZ5qJSGyfIc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HqfTMJEI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HqfTMJEI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1C7EC116B1; Fri, 22 Aug 2025 01:55:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827750; bh=K/O9CttzW0zt3QhDrAZF6NQXIZmkZnmyhsSNH3lWRrU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=HqfTMJEIIm0RVp8DdAwJ+7iOeQtGnXVoOOecL9qzpJ0rGiAk9eG5mToRPG9SUMT+m KVEZc3EJgTO1NVp4flTSaBHr0ZX0M3TqrAHeFyJ9lzLQcI4rR1oHCYv7lPVEIL82/Q pqCNkHMRuvnF6FKOOr+T0PvEICS2YMP8BT3pYFtyEEOYHZZxwwG32rq5CmJ+HUV2sN 95FdQFPFrXG4DxzufZm/vwTMnfOodVp9+3NzKTyWDHEK3YrGLGBN0HiPIfRweZ65cA Q17cxZTsQfO8k+A3IDWZgKcSNZoJjiathuDmGZzKyDBi1FZlrcsauiOSQ9yIWY8nvv l4iuD6pt5aKDg== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:51 +0100 Subject: [PATCH v7 22/29] KVM: arm64: Flush register state on writes to SVCR.SM and SVCR.ZA Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-22-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=3621; i=broonie@kernel.org; h=from:subject:message-id; bh=K/O9CttzW0zt3QhDrAZF6NQXIZmkZnmyhsSNH3lWRrU=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83JJXqzXqJ5OVr99ci+V6a3vGPLFRimUnWeH SqoJHNeNkqJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNyQAKCRAk1otyXVSH 0KcDCACFKvDYoPHrzdlHonB/UTvZ8IgbysGU4q7TsbxOb/15KCQ3dSgpF8h+AZv0rf/dtANxjvK ASSmvXR17WouQrUCoLU3WV4fYAPsouahjr2mWOW0t2VoX/CKHVZy23Vxb0zQlf+PvjuYJisW+LN E0yK6rcJk7oXRjKG/+YBdtx/HvCmmTD6g3huORstNbALGrrjSyYfEw5MdkfeURJa4tASPsWxcZt Sr3Au71YQW1bJoydFA+pT/9oYz4eYRSkgBQx7Ca14IecKv8TiGOmy76zaH0q/9UeqELUveAU6ds SWtLBtLuaYWbRgryRPEjE8WEOsY09f1hWKF18jB1fc56XlP9 X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Writes to the physical SVCR.SM and SVCR.ZA change the state of PSTATE.SM and PSTATE.ZA, causing other floating point state to reset. Emulate this behaviour for writes done via the KVM userspace ABI. Setting PSTATE.ZA to 1 causes ZA and ZT0 to be reset to 0, these are stored in sme_state. Setting PSTATE.ZA to 0 causes ZA and ZT0 to become inaccesible so no reset is needed. Any change in PSTATE.SM causes the V, Z, P, FFR and FPMR registers to be reset to 0 and FPSR to be reset to 0x800009f. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 24 ++++++++++++++++++++++++ arch/arm64/kvm/sys_regs.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index ebc516fe09db..8e5c16372b83 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1144,6 +1144,30 @@ struct kvm_vcpu_arch { =20 #define vcpu_sve_state_size(vcpu) sve_state_size_from_vl((vcpu)->arch.max_= vl[ARM64_VEC_SVE]) =20 +#define vcpu_sme_state(vcpu) (kern_hyp_va((vcpu)->arch.sme_state)) + +#define sme_state_size_from_vl(vl, sme2) ({ \ + size_t __size_ret; \ + unsigned int __vq; \ + \ + if (WARN_ON(!sve_vl_valid(vl))) { \ + __size_ret =3D 0; \ + } else { \ + __vq =3D sve_vq_from_vl(vl); \ + __size_ret =3D ZA_SIG_REGS_SIZE(__vq); \ + if (sme2) \ + __size_ret +=3D ZT_SIG_REG_SIZE; \ + } \ + \ + __size_ret; \ +}) + +#define vcpu_sme_state_size(vcpu) ({ \ + unsigned long __vl; \ + __vl =3D (vcpu)->arch.max_vl[ARM64_VEC_SME]; \ + sme_state_size_from_vl(__vl, vcpu_has_sme2(vcpu)); \ +}) + /* * Only use __vcpu_sys_reg/ctxt_sys_reg if you know you want the * memory backed version of a register, and not the one most recently diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 7284705a5f0a..0752e119c056 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -788,6 +788,33 @@ static unsigned int hidden_visibility(const struct kvm= _vcpu *vcpu, return REG_HIDDEN; } =20 +static int set_svcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + u64 val) +{ + u64 old =3D __vcpu_sys_reg(vcpu, rd->reg); + + if (val & SVCR_RES0) + return -EINVAL; + + if ((val & SVCR_ZA) && !(old & SVCR_ZA) && vcpu->arch.sme_state) + memset(vcpu->arch.sme_state, 0, vcpu_sme_state_size(vcpu)); + + if ((val & SVCR_SM) !=3D (old & SVCR_SM)) { + memset(vcpu->arch.ctxt.fp_regs.vregs, 0, + sizeof(vcpu->arch.ctxt.fp_regs.vregs)); + + if (vcpu->arch.sve_state) + memset(vcpu->arch.sve_state, 0, + vcpu_sve_state_size(vcpu)); + + __vcpu_assign_sys_reg(vcpu, FPMR, 0); + vcpu->arch.ctxt.fp_regs.fpsr =3D 0x800009f; + } + + __vcpu_assign_sys_reg(vcpu, rd->reg, val); + return 0; +} + static unsigned int pmu_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { @@ -3248,7 +3275,7 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { CTR_EL0_DminLine_MASK | CTR_EL0_L1Ip_MASK | CTR_EL0_IminLine_MASK), - { SYS_DESC(SYS_SVCR), undef_access, reset_val, SVCR, 0, .visibility =3D s= me_visibility }, + { SYS_DESC(SYS_SVCR), undef_access, reset_val, SVCR, 0, .visibility =3D s= me_visibility, .set_user =3D set_svcr }, { SYS_DESC(SYS_FPMR), undef_access, reset_val, FPMR, 0, .visibility =3D f= p8_visibility }, =20 { PMU_SYS_REG(PMCR_EL0), .access =3D access_pmcr, .reset =3D reset_pmcr, --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 360201C549F; Fri, 22 Aug 2025 01:55:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827754; cv=none; b=pex9y1dm2k8LjepOlJcgT9gtBCJtumTKBN1hn+EbdIw0n0vDYZr/fKPbHIGP/0z9eDSkHV7KKUUrRLmq+4c2Abmu2LPNOjo66XAQ1y24MHZJUVBtjGFFwXGcipzhMlnZmZDL+v7dpSHrMvbujgDVLXsEE5qez2+Zz3hIONLzGLY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827754; c=relaxed/simple; bh=n9Gv38zt8zDnvl+mS5Ep0oghSoUg5vKLb32ofFnUTn0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IVzSKDv7zD21DsIfezMn5bA+4Ihoto8BuIjECQnd9uw5/mhADtX49xUHfAUQ4yWlXUEm9E3M8k1HW1P9NisN7Ci5q3HLrL32ztAKcQfRtMxyxnnjZ31jSUwCh4+TV0yfbplZlTlKDl0kd7Y2c+d+DJgsofrW0Pn4j6lLIzp5gEY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=p3yi+wqj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="p3yi+wqj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6FDE7C4CEEB; Fri, 22 Aug 2025 01:55:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827753; bh=n9Gv38zt8zDnvl+mS5Ep0oghSoUg5vKLb32ofFnUTn0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=p3yi+wqjAUsKUm9GSDC/SkSY5nlBFCVlPjU7hz/NSZre8PH/dKIftXilMe0BiKHcb tT1lu9o+07qH3KHBzwS3r7M10Q7VzHs58S+g4+u6/2BGtM1TsxYEYs/Y07foVME7oM 1mqBaDaI5XazRFG/kxQkN0MgarG6M4KuaRjXC/OjqzwHYZNQCd8cdg3d+KiIpx2/fU i2yvL4TLQnlU4g117o1r4LMn+EzFxou77wUSUDzetXkCoBjhNnjKxgYn6yZJgP2qTC 3bjxx+0754hCJFoLspdHY7lPQT362v5mIrt+Y0GtkgXCNj1gxSSkBr1xXcHNtDB8KY 4WKmWHk1DE68Q== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:52 +0100 Subject: [PATCH v7 23/29] KVM: arm64: Expose SME specific state to userspace Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-23-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=6845; i=broonie@kernel.org; h=from:subject:message-id; bh=n9Gv38zt8zDnvl+mS5Ep0oghSoUg5vKLb32ofFnUTn0=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83Ko0Xchu4vZSqd6tIrzjroUAKs8laNGERfe J644DAWe06JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNygAKCRAk1otyXVSH 0IlSB/0dA7TY4Jg6ouSMPF0xvCY0VBXXhjVAbDgyrgVZXkvCAD9oF6+uyQRmU9Tt+n77vu0zKaD rIDjbO46Qt4SXKPUPbAQEfNgRz+2ZZYZmAS/w1OBF+BVKwwn8LI8JkdxOkiGqxoP8BsPy510XtT c9byqEo2C1ON9Pbcaf/Cxc/htvhZA+/MEZsJOS66BZDb8NmICr5Nl3OrKuKO7HlLA/brSNWeky/ DhR12tkYUpkkSPBWn9ObXLLjJnEkuY1DOIoO+xHYXhjkYB47cxHiNdmZAxHu44uXa/7eowkFAcP fibU6p6Gr5fxpzEuWe/biF4FrUe47kt3L/Jf1BvzfDQamxRN X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME introduces two new registers, the ZA matrix register and the ZT0 LUT register. Both of these registers are only accessible when PSTATE.ZA is set and ZT0 is only present if SME2 is enabled for the guest. Provide support for configuring these from VMMs. The ZA matrix is a single SVL*SVL register which is available when PSTATE.ZA is set. We follow the pattern established by the architecture itself and expose this to userspace as a series of horizontal SVE vectors with the streaming mode vector length, using the format already established for the SVE vectors themselves. ZT0 is a single register with a refreshingly fixed size 512 bit register which is like ZA accessible only when PSTATE.ZA is set. Add support for it to the userspace API, as with ZA we allow the register to be read or written regardless of the state of PSTATE.ZA in order to simplify userspace usage. The value will be reset to 0 whenever PSTATE.ZA changes from 0 to 1, userspace can read stale values but these are not observable by the guest without manipulation of PSTATE.ZA by userspace. While there is currently only one ZT register the naming as ZT0 and the instruction encoding clearly leave room for future extensions adding more ZT registers. This encoding can readily support such an extension if one is introduced. Signed-off-by: Mark Brown --- arch/arm64/include/uapi/asm/kvm.h | 17 ++++++ arch/arm64/kvm/guest.c | 114 ++++++++++++++++++++++++++++++++++= +++- 2 files changed, 129 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/as= m/kvm.h index 5220797361e0..cf75a830f17a 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -357,6 +357,23 @@ struct kvm_arm_counter_offset { /* SME registers */ #define KVM_REG_ARM64_SME (0x17 << KVM_REG_ARM_COPROC_SHIFT) =20 +#define KVM_ARM64_SME_VQ_MIN __SVE_VQ_MIN +#define KVM_ARM64_SME_VQ_MAX __SVE_VQ_MAX + +/* ZA and ZTn occupy blocks at the following offsets within this range: */ +#define KVM_REG_ARM64_SME_ZA_BASE 0 +#define KVM_REG_ARM64_SME_ZT_BASE 0x600 + +#define KVM_ARM64_SME_MAX_ZAHREG (__SVE_VQ_BYTES * KVM_ARM64_SME_VQ_MAX) + +#define KVM_REG_ARM64_SME_ZAHREG(n, i) \ + (KVM_REG_ARM64 | KVM_REG_ARM64_SME | KVM_REG_ARM64_SME_ZA_BASE | \ + KVM_REG_SIZE_U2048 | \ + (((n) & (KVM_ARM64_SME_MAX_ZAHREG - 1)) << 5) | \ + ((i) & (KVM_ARM64_SVE_MAX_SLICES - 1))) + +#define KVM_REG_ARM64_SME_ZTREG_SIZE (512 / 8) + /* Vector lengths pseudo-register: */ #define KVM_REG_ARM64_SME_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SME | \ KVM_REG_SIZE_U512 | 0xffff) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 013d66febf10..734120a76623 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -594,23 +594,133 @@ static int set_sme_vls(struct kvm_vcpu *vcpu, const = struct kvm_one_reg *reg) return set_vec_vls(ARM64_VEC_SME, vcpu, reg); } =20 +/* + * Validate SVE register ID and get sanitised bounds for user/kernel SVE + * register copy + */ +static int sme_reg_to_region(struct vec_state_reg_region *region, + struct kvm_vcpu *vcpu, + const struct kvm_one_reg *reg) +{ + /* reg ID ranges for ZA.H[n] registers */ + unsigned int vq =3D vcpu_sme_max_vq(vcpu) - 1; + const u64 za_h_max =3D vq * __SVE_VQ_BYTES; + const u64 zah_id_min =3D KVM_REG_ARM64_SME_ZAHREG(0, 0); + const u64 zah_id_max =3D KVM_REG_ARM64_SME_ZAHREG(za_h_max - 1, + SVE_NUM_SLICES - 1); + unsigned int reg_num; + + unsigned int reqoffset, reqlen; /* User-requested offset and length */ + unsigned int maxlen; /* Maximum permitted length */ + + size_t sme_state_size; + + reg_num =3D (reg->id & SVE_REG_ID_MASK) >> SVE_REG_ID_SHIFT; + + if (reg->id >=3D zah_id_min && reg->id <=3D zah_id_max) { + if (!vcpu_has_sme(vcpu) || (reg->id & SVE_REG_SLICE_MASK) > 0) + return -ENOENT; + + /* ZA is exposed as SVE vectors ZA.H[n] */ + reqoffset =3D ZA_SIG_ZAV_OFFSET(vq, reg_num) - + ZA_SIG_REGS_OFFSET; + reqlen =3D KVM_SVE_ZREG_SIZE; + maxlen =3D SVE_SIG_ZREG_SIZE(vq); + } else if (reg->id =3D=3D KVM_REG_ARM64_SME_ZT_BASE) { + /* ZA is exposed as SVE vectors ZA.H[n] */ + if (!kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SME, SME2) || + (reg->id & SVE_REG_SLICE_MASK) > 0 || + reg_num > 0) + return -ENOENT; + + /* ZT0 is stored after ZA */ + reqlen =3D KVM_REG_ARM64_SME_ZTREG_SIZE; + maxlen =3D KVM_REG_ARM64_SME_ZTREG_SIZE; + } else { + return -EINVAL; + } + + sme_state_size =3D vcpu_sme_state_size(vcpu); + if (WARN_ON(!sme_state_size)) + return -EINVAL; + + region->koffset =3D array_index_nospec(reqoffset, sme_state_size); + region->klen =3D min(maxlen, reqlen); + region->upad =3D reqlen - region->klen; + + return 0; +} + +/* + * ZA is exposed as an array of horizontal vectors with the same + * format as SVE, mirroring the architecture's LDR ZA[Wv, offs], [Xn] + * instruction. + */ + static int get_sme_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) { + int ret; + struct vec_state_reg_region region; + char __user *uptr =3D (char __user *)reg->addr; + /* Handle the KVM_REG_ARM64_SME_VLS pseudo-reg as a special case: */ if (reg->id =3D=3D KVM_REG_ARM64_SME_VLS) return get_sme_vls(vcpu, reg); =20 - return -EINVAL; + /* Try to interpret reg ID as an architectural SME register... */ + ret =3D sme_reg_to_region(®ion, vcpu, reg); + if (ret) + return ret; + + if (!kvm_arm_vcpu_vec_finalized(vcpu)) + return -EPERM; + + /* + * None of the SME specific registers are accessible unless + * PSTATE.ZA is set. + */ + if (!vcpu_za_enabled(vcpu)) + return -EINVAL; + + if (copy_from_user(vcpu->arch.sme_state + region.koffset, uptr, + region.klen)) + return -EFAULT; + + return 0; } =20 static int set_sme_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *re= g) { + int ret; + struct vec_state_reg_region region; + char __user *uptr =3D (char __user *)reg->addr; + /* Handle the KVM_REG_ARM64_SME_VLS pseudo-reg as a special case: */ if (reg->id =3D=3D KVM_REG_ARM64_SME_VLS) return set_sme_vls(vcpu, reg); =20 - return -EINVAL; + /* Try to interpret reg ID as an architectural SME register... */ + ret =3D sme_reg_to_region(®ion, vcpu, reg); + if (ret) + return ret; + + if (!kvm_arm_vcpu_vec_finalized(vcpu)) + return -EPERM; + + /* + * None of the SME specific registers are accessible unless + * PSTATE.ZA is set. + */ + if (!vcpu_za_enabled(vcpu)) + return -EINVAL; + + if (copy_from_user(vcpu->arch.sme_state + region.koffset, uptr, + region.klen)) + return -EFAULT; + + return 0; } + int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *r= egs) { return -EINVAL; --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 995BA29B22F; Fri, 22 Aug 2025 01:55:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827757; cv=none; b=gJhqLOEK46AieCClChvxIKELOVAblymB0UxqmtTbk700DpRnrzIu8O+0g8FsHZcuSeckIUVoxiQN1p4ACEQNeYbxbNnaa0Vg2zmQw3gz6DybRCk+/1A7FU5toPq5ovD6nOpIyA6icLzKoUeJ/ICgNiS037Gg0RDrqRVDyImlTIA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827757; c=relaxed/simple; bh=uilO8cZAVKYy6IefMKWSiW3palj0kkYE94hzaj93Noc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GjBfqTgTNwprFtD5PknbH8u2gxa9sYzYlqaSrO8pE3X/GBYb70cr7JWJ37nkImvKrzZ2vhj2/Jc6GGvrYzj5XEjC3yHyBNRbADE+dOj/uvztOBqJAfESD2c1ChYLKci4LVOvjTvDACCSfjWpge0u+PKY5vz8J6x8T+HW6nrjQGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ROBmLZN1; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ROBmLZN1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2CF6DC116C6; Fri, 22 Aug 2025 01:55:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827757; bh=uilO8cZAVKYy6IefMKWSiW3palj0kkYE94hzaj93Noc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ROBmLZN15AZLKWylBo3TXidSodXsrjyjRkP3IaneBySJAfW7BFwq1gG8Fyqa1RqaY Z+Zsevjs3x8tn00JywIFZmxcXt3CmG3fqLl7GJJLfLBYVBzh0DNt1MiBibINSl13TU 9fkZmRNe2wSzaCli8+e5Y0Vu/OJ2RcqwJ6PxCsxQ1pRZ7gVPN5DgPOoJGUVJexdByU efa3cUUHOnXP3taHtxuyVjyZn/n5k0FQXSOT77t37yjWeC+KTaT6tAYOcjgPUgXYj9 V82ye+M5u3RM+3HBZfx7Wfzaw7E5SJDSzWqxfz/fwiMBD1Zz/WFdhWkQ/ElEBj6D3j 3awbySUmsTkKw== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:53 +0100 Subject: [PATCH v7 24/29] KVM: arm64: Context switch SME state for guests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-24-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=18718; i=broonie@kernel.org; h=from:subject:message-id; bh=uilO8cZAVKYy6IefMKWSiW3palj0kkYE94hzaj93Noc=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83LadVoGj26NeZ+sIWnf0mqlLBRMnCkkvElP 0lcojh1bH+JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNywAKCRAk1otyXVSH 0Kw2B/9fHFu7LcbgispHFwGazGwjK1Ec6LIFklDD2D9b4kGkRzw4GAkSaOWeOH1AfQExU9WW0uS l5x+UPrcfhRyLWuH/w9jqSRMsBN72t9gD6VVqqdl284td7MV7Unkbm2nqh4KkRrXzOUtZeeaNbV AEzSnjK8kOaVZOBIHxvfyZGim5A3rQGDZWp7RW9OPaBq6YcDW4hPxPZkPFqSWFZaIVFXNSnNan8 i7N2rpABaVxFTi8AlU+nFtIapfQQDS+fKEEOlv5iquTPmPmw/G1nX9ZmkdSfVUApATiHL4s8tHr BSZFKWVE0md8uuuW1XEijH5uNK8kwRqiKhzyKEmUgAQx6Cs/ X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB If the guest has SME state we need to context switch that state, provide support for that for normal guests. SME has three sets of registers, ZA, ZT (only present for SME2) and also streaming SVE which replaces the standard floating point registers when active. The first two are fairly straightforward, they are accessible only when PSTATE.ZA is set and we can reuse the assembly from the host to save and load them from a single contiguous buffer. When PSTATE.ZA is not set then these registers are inaccessible, when the guest enables PSTATE.ZA all bits will be set to 0 by that and nothing is required on restore. Streaming mode is slightly more complicated, when enabled via PSTATE.SM it provides a version of the SVE registers using the SME vector length and may optionally omit the FFR register. SME may also be present without SVE. The register state is stored in sve_state as for non-streaming SVE mode, we make an initial selection of registers to update based on the guest SVE support and then override this when loading SVCR if streaming mode is enabled. A further complication is that when the hardware is in streaming mode guest operations that are invalid in in streaming mode will generate SME exceptions. There are also subfeature exceptions for SME2 controlled via SMCR which generate distinct exception codes. In many situations these exceptions are routed directly to the lower ELs with no opportunity for the hypervisor to intercept. So that guests do not see unexpected exception types due to the actual hardware configuration not being what the guest configured we update the SMCRs and SVCR even if the guest does not own the registers. Since in order to avoid duplication with SME we now restore the register state outside of the SVE specific restore function we need to move the restore of the effective VL for nested guests to a separate restore function run after loading the floating point register state, along with the similar handling required for SME. The selection of which vector length to use is handled by vcpu_sve_pffr(). Signed-off-by: Mark Brown --- arch/arm64/include/asm/fpsimd.h | 10 +++ arch/arm64/include/asm/kvm_emulate.h | 6 ++ arch/arm64/include/asm/kvm_host.h | 4 + arch/arm64/kvm/fpsimd.c | 25 ++++-- arch/arm64/kvm/hyp/include/hyp/switch.h | 151 ++++++++++++++++++++++++++++= ++-- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 80 +++++++++++++++-- 6 files changed, 255 insertions(+), 21 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index 38c24c6485ad..40b56fba9c54 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -442,6 +442,15 @@ static inline size_t sme_state_size(struct task_struct= const *task) write_sysreg_s(__new, (reg)); \ } while (0) =20 +#define sme_cond_update_smcr_vq(val, reg) \ + do { \ + u64 __smcr =3D read_sysreg_s((reg)); \ + u64 __new =3D __smcr & ~SMCR_ELx_LEN_MASK; \ + __new |=3D (val) & SMCR_ELx_LEN_MASK; \ + if (__smcr !=3D __new) \ + write_sysreg_s(__new, (reg)); \ + } while (0) + #else =20 static inline void sme_user_disable(void) { BUILD_BUG(); } @@ -471,6 +480,7 @@ static inline size_t sme_state_size(struct task_struct = const *task) } =20 #define sme_cond_update_smcr(val, fa64, zt0, reg) do { } while (0) +#define sme_cond_update_smcr_vq(val, reg) do { } while (0) =20 #endif /* ! CONFIG_ARM64_SME */ =20 diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/= kvm_emulate.h index fa8a08a1ccd5..d71ccea726f2 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -674,4 +674,10 @@ static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu) vcpu->arch.hcrx_el2 |=3D HCRX_EL2_SCTLR2En; } } + +static inline bool guest_hyp_sme_traps_enabled(const struct kvm_vcpu *vcpu) +{ + return __guest_hyp_cptr_xen_trap_enabled(vcpu, SMEN); +} + #endif /* __ARM64_KVM_EMULATE_H__ */ diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 8e5c16372b83..fa646da80e3e 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -738,6 +738,7 @@ struct kvm_host_data { =20 /* Used by pKVM only. */ u64 fpmr; + u64 smcr_el1; =20 /* Ownership of the FP regs */ enum { @@ -1128,6 +1129,9 @@ struct kvm_vcpu_arch { #define vcpu_sve_zcr_elx(vcpu) \ (unlikely(is_hyp_ctxt(vcpu)) ? ZCR_EL2 : ZCR_EL1) =20 +#define vcpu_sme_smcr_elx(vcpu) \ + (unlikely(is_hyp_ctxt(vcpu)) ? SMCR_EL2 : SMCR_EL1) + #define sve_state_size_from_vl(sve_max_vl) ({ \ size_t __size_ret; \ unsigned int __vq; \ diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 1f4fcc8b5554..8fb8c55e50b3 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -69,19 +69,25 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) WARN_ON_ONCE(!irqs_disabled()); =20 if (guest_owns_fp_regs()) { - /* - * Currently we do not support SME guests so SVCR is - * always 0 and we just need a variable to point to. - */ fp_state.st =3D &vcpu->arch.ctxt.fp_regs; fp_state.sve_state =3D vcpu->arch.sve_state; fp_state.sve_vl =3D vcpu->arch.max_vl[ARM64_VEC_SVE]; - fp_state.sme_state =3D NULL; + fp_state.sme_state =3D vcpu->arch.sme_state; + fp_state.sme_vl =3D vcpu->arch.max_vl[ARM64_VEC_SME]; fp_state.svcr =3D __ctxt_sys_reg(&vcpu->arch.ctxt, SVCR); fp_state.fpmr =3D __ctxt_sys_reg(&vcpu->arch.ctxt, FPMR); fp_state.fp_type =3D &vcpu->arch.fp_type; + fp_state.sme_features =3D 0; + if (kvm_has_fa64(vcpu->kvm)) + fp_state.sme_features |=3D SMCR_ELx_FA64; + if (kvm_has_sme2(vcpu->kvm)) + fp_state.sme_features |=3D SMCR_ELx_EZT0; =20 + /* + * For SME only hosts fpsimd_save() will override the + * state selection if we are in streaming mode. + */ if (vcpu_has_sve(vcpu)) fp_state.to_save =3D FP_STATE_SVE; else @@ -90,6 +96,15 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) fpsimd_bind_state_to_cpu(&fp_state); =20 clear_thread_flag(TIF_FOREIGN_FPSTATE); + } else { + /* + * We might have enabled SME to configure traps but + * insist the host doesn't run the hypervisor with SME + * enabled, ensure it's disabled again. + */ + if (system_supports_sme()) { + sme_smstop(); + } } } =20 diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/i= nclude/hyp/switch.h index cd76129c6630..c128b4d25a2d 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -551,6 +551,29 @@ static inline bool kvm_hyp_handle_mops(struct kvm_vcpu= *vcpu, u64 *exit_code) return true; } =20 +static inline void __hyp_sme_restore_guest(struct kvm_vcpu *vcpu, + bool *restore_sve, + bool *restore_ffr) +{ + bool has_fa64 =3D vcpu_has_fa64(vcpu); + bool has_sme2 =3D vcpu_has_sme2(vcpu); + + sme_cond_update_smcr(vcpu_sme_max_vq(vcpu) - 1, has_fa64, has_sme2, + SYS_SMCR_EL2); + + write_sysreg_el1(__vcpu_sys_reg(vcpu, SMCR_EL1), SYS_SMCR); + + write_sysreg_s(__vcpu_sys_reg(vcpu, SVCR), SYS_SVCR); + + if (vcpu_in_streaming_mode(vcpu)) { + *restore_sve =3D true; + *restore_ffr =3D has_fa64; + } + + if (vcpu_za_enabled(vcpu)) + __sme_restore_state(vcpu_sme_state(vcpu), has_sme2); +} + static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu) { /* @@ -558,19 +581,25 @@ static inline void __hyp_sve_restore_guest(struct kvm= _vcpu *vcpu) * vCPU. Start off with the max VL so we can load the SVE state. */ sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL2); - __sve_restore_state(vcpu_sve_pffr(vcpu), - &vcpu->arch.ctxt.fp_regs.fpsr, - true); =20 + write_sysreg_el1(__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)), SYS_ZCR); +} + +static inline void __hyp_nv_restore_guest_vls(struct kvm_vcpu *vcpu) +{ /* * The effective VL for a VM could differ from the max VL when running a * nested guest, as the guest hypervisor could select a smaller VL. Slap * that into hardware before wrapping up. */ - if (is_nested_ctxt(vcpu)) + if (!is_nested_ctxt(vcpu)) + return; + + if (vcpu_has_sve(vcpu)) sve_cond_update_zcr_vq(__vcpu_sys_reg(vcpu, ZCR_EL2), SYS_ZCR_EL2); =20 - write_sysreg_el1(__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)), SYS_ZCR); + if (vcpu_has_sme(vcpu)) + sme_cond_update_smcr_vq(__vcpu_sys_reg(vcpu, SMCR_EL2), SYS_SMCR_EL2); } =20 static inline void __hyp_sve_save_host(void) @@ -584,10 +613,40 @@ static inline void __hyp_sve_save_host(void) true); } =20 +static inline void kvm_sme_configure_traps(struct kvm_vcpu *vcpu) +{ + u64 smcr_el1, smcr_el2; + u64 svcr; + + if (!vcpu_has_sme(vcpu)) + return; + + /* A guest hypervisor may restrict the effective max VL. */ + if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) + smcr_el2 =3D __vcpu_sys_reg(vcpu, SMCR_EL2); + else + smcr_el2 =3D vcpu_sme_max_vq(vcpu) - 1; + + if (vcpu_has_fa64(vcpu)) + smcr_el2 |=3D SMCR_ELx_FA64; + if (vcpu_has_sme2(vcpu)) + smcr_el2 |=3D SMCR_ELx_EZT0; + + write_sysreg_el2(smcr_el2, SYS_SMCR); + + smcr_el1 =3D __vcpu_sys_reg(vcpu, vcpu_sme_smcr_elx(vcpu)); + write_sysreg_el1(smcr_el1, SYS_SMCR); + + svcr =3D __vcpu_sys_reg(vcpu, SVCR); + write_sysreg_s(svcr, SYS_SVCR); +} + static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu) { u64 zcr_el1, zcr_el2; =20 + kvm_sme_configure_traps(vcpu); + if (!guest_owns_fp_regs()) return; =20 @@ -607,8 +666,50 @@ static inline void fpsimd_lazy_switch_to_guest(struct = kvm_vcpu *vcpu) =20 static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu) { + u64 smcr_el1, smcr_el2; u64 zcr_el1, zcr_el2; =20 + if (vcpu_has_sme(vcpu)) { + /* + * __deactivate_cptr_traps( disabled traps), but there + * hasn't necessarily been a context synchronization + * event yet. + */ + isb(); + + smcr_el1 =3D read_sysreg_el1(SYS_SMCR); + __vcpu_assign_sys_reg(vcpu, vcpu_sme_smcr_elx(vcpu), smcr_el1); + + smcr_el2 =3D 0; + if (system_supports_fa64()) + smcr_el2 |=3D SMCR_ELx_FA64; + if (system_supports_sme2()) + smcr_el2 |=3D SMCR_ELx_EZT0; + + /* + * The guest's state is always saved using the guest's max VL. + * Ensure that the host has the guest's max VL active such that + * the host can save the guest's state lazily, but don't + * artificially restrict the host to the guest's max VL. + */ + if (has_vhe()) { + smcr_el2 |=3D vcpu_sme_max_vq(vcpu) - 1; + write_sysreg_el2(smcr_el2, SYS_SMCR); + } else { + smcr_el1 =3D smcr_el2; + smcr_el2 |=3D sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SME]) - 1; + write_sysreg_el2(smcr_el2, SYS_SMCR); + + smcr_el1 |=3D vcpu_sve_max_vq(vcpu) - 1; + write_sysreg_el1(smcr_el1, SYS_SMCR); + } + + if (guest_owns_fp_regs()) { + u64 svcr =3D read_sysreg_s(SYS_SVCR); + __vcpu_assign_sys_reg(vcpu, SVCR, svcr); + } + } + if (!guest_owns_fp_regs()) return; =20 @@ -645,6 +746,16 @@ static inline void fpsimd_lazy_switch_to_host(struct k= vm_vcpu *vcpu) =20 static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu) { + /* + * The hypervisor refuses to run if streaming mode or ZA is + * enabled, we only need to save SMCR_EL1 for SME. For pKVM + * we will restore this, reset SMCR_EL2 to a fixed value and + * disable streaming mode and ZA to avoid any state being + * leaked. + */ + if (system_supports_sme()) + *host_data_ptr(smcr_el1) =3D read_sysreg_el1(SYS_SMCR); + /* * Non-protected kvm relies on the host restoring its sve state. * Protected kvm restores the host's sve state as not to reveal that @@ -669,14 +780,17 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu = *vcpu) */ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_= code) { - bool sve_guest; - u8 esr_ec; + bool restore_sve, restore_ffr; + bool sve_guest, sme_guest; + u8 esr_ec, esr_iss_smtc; =20 if (!system_supports_fpsimd()) return false; =20 sve_guest =3D vcpu_has_sve(vcpu); + sme_guest =3D vcpu_has_sme(vcpu); esr_ec =3D kvm_vcpu_trap_get_class(vcpu); + esr_iss_smtc =3D ESR_ELx_SME_ISS_SMTC((kvm_vcpu_get_esr(vcpu))); =20 /* Only handle traps the vCPU can support here: */ switch (esr_ec) { @@ -695,6 +809,15 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vc= pu *vcpu, u64 *exit_code) if (guest_hyp_sve_traps_enabled(vcpu)) return false; break; + case ESR_ELx_EC_SME: + if (!sme_guest) + return false; + if (guest_hyp_sme_traps_enabled(vcpu)) + return false; + if (!kvm_has_sme2(vcpu->kvm) && + (esr_iss_smtc =3D=3D ESR_ELx_SME_ISS_SMTC_ZT_DISABLED)) + return false; + break; default: return false; } @@ -710,8 +833,20 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vc= pu *vcpu, u64 *exit_code) kvm_hyp_save_fpsimd_host(vcpu); =20 /* Restore the guest state */ + + /* These may be overridden for a SME guest */ + restore_sve =3D sve_guest; + restore_ffr =3D sve_guest; + if (sve_guest) __hyp_sve_restore_guest(vcpu); + if (sme_guest) + __hyp_sme_restore_guest(vcpu, &restore_sve, &restore_ffr); + + if (restore_sve) + __sve_restore_state(vcpu_sve_pffr(vcpu), + &vcpu->arch.ctxt.fp_regs.fpsr, + restore_ffr); else __fpsimd_restore_state(&vcpu->arch.ctxt.fp_regs); =20 @@ -722,6 +857,8 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcp= u *vcpu, u64 *exit_code) if (!(read_sysreg(hcr_el2) & HCR_RW)) write_sysreg(__vcpu_sys_reg(vcpu, FPEXC32_EL2), fpexc32_el2); =20 + __hyp_nv_restore_guest_vls(vcpu); + *host_data_ptr(fp_owner) =3D FP_STATE_GUEST_OWNED; =20 /* diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/h= yp-main.c index 76be13efcfcb..ccbe0389c0b7 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -26,14 +26,17 @@ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context = *host_ctxt); =20 static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu) { + bool save_ffr =3D !vcpu_in_streaming_mode(vcpu) || vcpu_has_fa64(vcpu); + __vcpu_assign_sys_reg(vcpu, ZCR_EL1, read_sysreg_el1(SYS_ZCR)); + /* * On saving/restoring guest sve state, always use the maximum VL for * the guest. The layout of the data when saving the sve state depends * on the VL, so use a consistent (i.e., the maximum) guest VL. */ sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL2); - __sve_save_state(vcpu_sve_pffr(vcpu), &vcpu->arch.ctxt.fp_regs.fpsr, true= ); + __sve_save_state(vcpu_sve_pffr(vcpu), &vcpu->arch.ctxt.fp_regs.fpsr, save= _ffr); write_sysreg_s(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1, SYS_ZC= R_EL2); } =20 @@ -57,9 +60,63 @@ static void __hyp_sve_restore_host(void) write_sysreg_el1(sve_state->zcr_el1, SYS_ZCR); } =20 -static void fpsimd_sve_flush(void) +static void __hyp_sme_save_guest(struct kvm_vcpu *vcpu) { - *host_data_ptr(fp_owner) =3D FP_STATE_HOST_OWNED; + __vcpu_assign_sys_reg(vcpu, SMCR_EL1, read_sysreg_el1(SYS_SMCR)); + __vcpu_assign_sys_reg(vcpu, SVCR, read_sysreg_s(SYS_SVCR)); + + /* + * On saving/restoring guest sve state, always use the maximum VL for + * the guest. The layout of the data when saving the sve state depends + * on the VL, so use a consistent (i.e., the maximum) guest VL. + * + * We restore the FA64 and SME2 enables for the host since we + * will always restore the host configuration so if host and + * guest VLs are the same we might suppress an update. + */ + sme_cond_update_smcr(vcpu_sme_max_vq(vcpu) - 1, system_supports_fa64(), + system_supports_sme2(), SYS_SMCR_EL2); + + if (vcpu_za_enabled(vcpu)) + __sme_save_state(vcpu_sme_state(vcpu), vcpu_has_sme2(vcpu)); +} + +static void __hyp_sme_restore_host(void) +{ + /* + * The hypervisor refuses to run if we are in streaming mode + * or have ZA enabled so there is no SME specific state to + * restore other than the system registers. + * + * Note that this constrains the PE to the maximum shared VL + * that was discovered, if we wish to use larger VLs this will + * need to be revisited. + */ + sme_cond_update_smcr(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SME]) - 1, + cpus_have_final_cap(ARM64_SME_FA64), + cpus_have_final_cap(ARM64_SME2), SYS_SMCR_EL2); + + write_sysreg_el1(*host_data_ptr(smcr_el1), SYS_SMCR); + + sme_smstop(); +} + +static void fpsimd_sve_flush(struct kvm_vcpu *vcpu) +{ + /* + * If the guest has SME then we need to restore the trap + * controls in SMCR and mode in SVCR in order to ensure that + * traps generated directly to EL1 have the correct types, + * otherwise we can defer until we load the guest state. + */ + if (vcpu_has_sme(vcpu)) { + kvm_hyp_save_fpsimd_host(vcpu); + kvm_sme_configure_traps(vcpu); + + *host_data_ptr(fp_owner) =3D FP_STATE_FREE; + } else { + *host_data_ptr(fp_owner) =3D FP_STATE_HOST_OWNED; + } } =20 static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) @@ -75,7 +132,10 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) */ isb(); =20 - if (vcpu_has_sve(vcpu)) + if (vcpu_has_sme(vcpu)) + __hyp_sme_save_guest(vcpu); + + if (vcpu_has_sve(vcpu) || vcpu_in_streaming_mode(vcpu)) __hyp_sve_save_guest(vcpu); else __fpsimd_save_state(&vcpu->arch.ctxt.fp_regs); @@ -84,6 +144,9 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) if (has_fpmr) __vcpu_assign_sys_reg(vcpu, FPMR, read_sysreg_s(SYS_FPMR)); =20 + if (system_supports_sme()) + __hyp_sme_restore_host(); + if (system_supports_sve()) __hyp_sve_restore_host(); else @@ -121,7 +184,7 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vc= pu) { struct kvm_vcpu *host_vcpu =3D hyp_vcpu->host_vcpu; =20 - fpsimd_sve_flush(); + fpsimd_sve_flush(host_vcpu); flush_debug_state(hyp_vcpu); =20 hyp_vcpu->vcpu.arch.ctxt =3D host_vcpu->arch.ctxt; @@ -203,10 +266,9 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_conte= xt *host_ctxt) struct pkvm_hyp_vcpu *hyp_vcpu =3D pkvm_get_loaded_hyp_vcpu(); =20 /* - * KVM (and pKVM) doesn't support SME guests for now, and - * ensures that SME features aren't enabled in pstate when - * loading a vcpu. Therefore, if SME features enabled the host - * is misbehaving. + * KVM (and pKVM) refuses to run if PSTATE.{SM,ZA} are + * enabled. Therefore, if SME features enabled the + * host is misbehaving. */ if (unlikely(system_supports_sme() && read_sysreg_s(SYS_SVCR))) { ret =3D -EINVAL; --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE8CC2BD031; Fri, 22 Aug 2025 01:56:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827761; cv=none; b=UW3Q9Aaiw8scfuKc2jIo6CR7AVJJNIDvUql0PwrCE66BoreptwtNszPjQmWX05P738yBxMF5q6aEZfMDeF12a+FkEbsxMvBMji8C1Cw4fYql++LY/XA44bZB1+w+Idnz688lkRDtW0juNuLfAZg56l2AStDX+ItWRmu1bNfQxZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827761; c=relaxed/simple; bh=NTFrR4Ul2FjKNCZg2te+RhXOLPTLiTRbz6mCjfo2Vis=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MUWyRHxHk6zXSL3tImWUo/iiKI/CtpK0Ne+ihUciapJM2sk5hHRmInYk9yb3gDPBpjlmMa05m+T7ldahbJvpJMm23tJxtoet7G7QR82euIVx3VACqGyRETl0C2fJ7NnGcawE9XYLJGWh3e5s98euWNdcfkKo8nleWw0SwmnuE+A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vFzSqMBe; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vFzSqMBe" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E30A0C4CEEB; Fri, 22 Aug 2025 01:55:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827761; bh=NTFrR4Ul2FjKNCZg2te+RhXOLPTLiTRbz6mCjfo2Vis=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=vFzSqMBeOaH40A7B0Jnjdq108ldYJIEuEC7FdvPT8pJ0WCVyD9b57OsiSgpPbwJRr lCEAPq8UgATdZuL0OHBflicn4mKlwuUs3PQHr5uW8LH7nHHsW1soEi2cCpyt+wBXlK Yp+s4eo/6h8FuRaobiZtvcBaaFgHrEC1MJUs5sFkCrpn8bx7nn4ABJ+v6e0nJwBaOY 0vbqROYlNXYOa0t5WUfNiqqeF5Add9g8njpy7vL+YD15N1DN66z0SSFHRajiVx0/jH UaFezOrgxEmnvPShzVNFxCwUjXln+B3JG5R+ueCG60N7/JZ2AMkIIx5tVE7HNfvyeC R1DqDiwcPwJwA== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:54 +0100 Subject: [PATCH v7 25/29] KVM: arm64: Handle SME exceptions Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-25-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=6175; i=broonie@kernel.org; h=from:subject:message-id; bh=NTFrR4Ul2FjKNCZg2te+RhXOLPTLiTRbz6mCjfo2Vis=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83L1eAEauMA75PPXYSGXSKCEjgzIsyz7GWSV xvH+3YGyrmJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNywAKCRAk1otyXVSH 0A2DB/94nXwg0bS6zk1vGd+TbpOSIKQdrdokTcbQQaE8E4c6TX30yeyg/wpb+YaW08H9TX+/XEI XXVA6x1UAFa9zET6o+N8ZTDmvgwq2q4c6s1hXnoX8B62BmFvvkp2Ele0kOvSOBSDtgyDUutlOys XKHWnXc5rs7bWzzYc0AML9mS1MQJ5oK14it60utq8t0fyEiKs2w2DOCbk1g3gcpG6tcAleG8DiS w/MVbro+wLb5xPfX4AR5mpAH1FFR8gPRO6wcF2fv43PRbSWt4MuPCEk4BvhhRaqFVw9CttQfKyg k6h6AxxmByUaC3Ji3aWNSp2zaO2Qs4+Lmj2W1blXkU237oqc X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB The access control for SME follows the same structure as for the base FP and SVE extensions, with control being via CPACR_ELx.SMEN and CPTR_EL2.TSM mirroring the equivalent FPSIMD and SVE controls in those registers. Add handling for these controls and exceptions mirroring the existing handling for FPSIMD and SVE. Signed-off-by: Mark Brown --- arch/arm64/kvm/handle_exit.c | 14 ++++++++++++++ arch/arm64/kvm/hyp/include/hyp/switch.h | 11 ++++++----- arch/arm64/kvm/hyp/nvhe/switch.c | 4 +++- arch/arm64/kvm/hyp/vhe/switch.c | 17 ++++++++++++----- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index a598072f36d2..d96f3a585d70 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -232,6 +232,19 @@ static int handle_sve(struct kvm_vcpu *vcpu) return 1; } =20 +/* + * Guest access to SME registers should be routed to this handler only + * when the system doesn't support SME. + */ +static int handle_sme(struct kvm_vcpu *vcpu) +{ + if (guest_hyp_sme_traps_enabled(vcpu)) + return kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu)); + + kvm_inject_undefined(vcpu); + return 1; +} + /* * Two possibilities to handle a trapping ptrauth instruction: * @@ -385,6 +398,7 @@ static exit_handle_fn arm_exit_handlers[] =3D { [ESR_ELx_EC_SVC64] =3D handle_svc, [ESR_ELx_EC_SYS64] =3D kvm_handle_sys_reg, [ESR_ELx_EC_SVE] =3D handle_sve, + [ESR_ELx_EC_SME] =3D handle_sme, [ESR_ELx_EC_ERET] =3D kvm_handle_eret, [ESR_ELx_EC_IABT_LOW] =3D kvm_handle_guest_abort, [ESR_ELx_EC_DABT_LOW] =3D kvm_handle_guest_abort, diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/i= nclude/hyp/switch.h index c128b4d25a2d..9375afa96b71 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -69,11 +69,8 @@ static inline void __activate_cptr_traps_nvhe(struct kvm= _vcpu *vcpu) { u64 val =3D CPTR_NVHE_EL2_RES1 | CPTR_EL2_TAM | CPTR_EL2_TTA; =20 - /* - * Always trap SME since it's not supported in KVM. - * TSM is RES1 if SME isn't implemented. - */ - val |=3D CPTR_EL2_TSM; + if (!vcpu_has_sme(vcpu) || !guest_owns_fp_regs()) + val |=3D CPTR_EL2_TSM; =20 if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs()) val |=3D CPTR_EL2_TZ; @@ -101,6 +98,8 @@ static inline void __activate_cptr_traps_vhe(struct kvm_= vcpu *vcpu) val |=3D CPACR_EL1_FPEN; if (vcpu_has_sve(vcpu)) val |=3D CPACR_EL1_ZEN; + if (vcpu_has_sme(vcpu)) + val |=3D CPACR_EL1_SMEN; } =20 if (!vcpu_has_nv(vcpu)) @@ -142,6 +141,8 @@ static inline void __activate_cptr_traps_vhe(struct kvm= _vcpu *vcpu) val &=3D ~CPACR_EL1_FPEN; if (!(SYS_FIELD_GET(CPACR_EL1, ZEN, cptr) & BIT(0))) val &=3D ~CPACR_EL1_ZEN; + if (!(SYS_FIELD_GET(CPACR_EL1, SMEN, cptr) & BIT(0))) + val &=3D ~CPACR_EL1_SMEN; =20 if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S2POE, IMP)) val |=3D cptr & CPACR_EL1_E0POE; diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/swi= tch.c index ccd575d5f6de..79a3e5c290f9 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -175,6 +175,7 @@ static const exit_handler_fn hyp_exit_handlers[] =3D { [ESR_ELx_EC_CP15_32] =3D kvm_hyp_handle_cp15_32, [ESR_ELx_EC_SYS64] =3D kvm_hyp_handle_sysreg, [ESR_ELx_EC_SVE] =3D kvm_hyp_handle_fpsimd, + [ESR_ELx_EC_SME] =3D kvm_hyp_handle_fpsimd, [ESR_ELx_EC_FP_ASIMD] =3D kvm_hyp_handle_fpsimd, [ESR_ELx_EC_IABT_LOW] =3D kvm_hyp_handle_iabt_low, [ESR_ELx_EC_DABT_LOW] =3D kvm_hyp_handle_dabt_low, @@ -186,7 +187,8 @@ static const exit_handler_fn pvm_exit_handlers[] =3D { [0 ... ESR_ELx_EC_MAX] =3D NULL, [ESR_ELx_EC_SYS64] =3D kvm_handle_pvm_sys64, [ESR_ELx_EC_SVE] =3D kvm_handle_pvm_restricted, - [ESR_ELx_EC_FP_ASIMD] =3D kvm_hyp_handle_fpsimd, + [ESR_ELx_EC_SME] =3D kvm_handle_pvm_restricted, + [ESR_ELx_EC_FP_ASIMD] =3D kvm_handle_pvm_restricted, [ESR_ELx_EC_IABT_LOW] =3D kvm_hyp_handle_iabt_low, [ESR_ELx_EC_DABT_LOW] =3D kvm_hyp_handle_dabt_low, [ESR_ELx_EC_WATCHPT_LOW] =3D kvm_hyp_handle_watchpt_low, diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switc= h.c index e482181c6632..86a892966a18 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -448,22 +448,28 @@ static bool kvm_hyp_handle_cpacr_el1(struct kvm_vcpu = *vcpu, u64 *exit_code) return true; } =20 -static bool kvm_hyp_handle_zcr_el2(struct kvm_vcpu *vcpu, u64 *exit_code) +static bool kvm_hyp_handle_vec_cr_el2(struct kvm_vcpu *vcpu, u64 *exit_cod= e) { u32 sysreg =3D esr_sys64_to_sysreg(kvm_vcpu_get_esr(vcpu)); =20 if (!vcpu_has_nv(vcpu)) return false; =20 - if (sysreg !=3D SYS_ZCR_EL2) + switch (sysreg) { + case SYS_ZCR_EL2: + case SYS_SMCR_EL2: + break; + default: return false; + } =20 if (guest_owns_fp_regs()) return false; =20 /* - * ZCR_EL2 traps are handled in the slow path, with the expectation - * that the guest's FP context has already been loaded onto the CPU. + * ZCR_EL2 and SMCR_EL2 traps are handled in the slow path, + * with the expectation that the guest's FP context has + * already been loaded onto the CPU. * * Load the guest's FP context and unconditionally forward to the * slow path for handling (i.e. return false). @@ -483,7 +489,7 @@ static bool kvm_hyp_handle_sysreg_vhe(struct kvm_vcpu *= vcpu, u64 *exit_code) if (kvm_hyp_handle_cpacr_el1(vcpu, exit_code)) return true; =20 - if (kvm_hyp_handle_zcr_el2(vcpu, exit_code)) + if (kvm_hyp_handle_vec_cr_el2(vcpu, exit_code)) return true; =20 return kvm_hyp_handle_sysreg(vcpu, exit_code); @@ -512,6 +518,7 @@ static const exit_handler_fn hyp_exit_handlers[] =3D { [0 ... ESR_ELx_EC_MAX] =3D NULL, [ESR_ELx_EC_CP15_32] =3D kvm_hyp_handle_cp15_32, [ESR_ELx_EC_SYS64] =3D kvm_hyp_handle_sysreg_vhe, + [ESR_ELx_EC_SME] =3D kvm_hyp_handle_fpsimd, [ESR_ELx_EC_SVE] =3D kvm_hyp_handle_fpsimd, [ESR_ELx_EC_FP_ASIMD] =3D kvm_hyp_handle_fpsimd, [ESR_ELx_EC_IABT_LOW] =3D kvm_hyp_handle_iabt_low, --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1AA472BDC04; Fri, 22 Aug 2025 01:56:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827765; cv=none; b=GgC+33I+9IoXtHG38Zpb6q01Zw2l2d6pXA6rPEBAbT5BLBWfdC/QbviUkfV7INYgByR3hDTeiTCsQ1FJKOMxVs31MYe5miXnBPvIdnruWBMSrl2tpdin+XfQfqCBH26sTzgHejfHUJ2Z6d29OiTgNt9YIe8raFoYdMuD5S1zRMw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827765; c=relaxed/simple; bh=ApIjPu6tr41pN88JrHKurRe18MYIB0RS0vVGxBjI5iI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XMcRM4cJOUo0iH6eVi2A4wRVc15mIq2PyNkuNkNjSnKkapx0UNDD5oqn77ENPY3dG7r83zwz9yzdhK0LeRhv8klJKLRfgtI0kT1L5OYOpj9Wg4pre8mHvbWdmtl800+AhAAvU8n6kJ+WPEmwOp6dTXi7svuT+8F2z3m/FDjz9vE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qwK4r9Py; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qwK4r9Py" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A6900C4CEED; Fri, 22 Aug 2025 01:56:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827765; bh=ApIjPu6tr41pN88JrHKurRe18MYIB0RS0vVGxBjI5iI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qwK4r9Py1WNdLXRolIsS2xDD8JZJhqzFwqK+ySVueAtJyHFnEQPFhxQfXvud2TzED AYF1c7+e2p11M2YJHpEuisx5nOTdu2hxjXXLVmBSqYAdD2lS3WYP/oKCAA1QX++V1q XVjl8YMs/q4b3awokyte6bcF5GeVev3zYfeQlVraKxZQuOFRobv0CWwxSddUljpBDh m8wu3T/SfYqaCtXCwNljFPSugY4tG0M/0FJj1yxzeeOJNR/5f3nAkCS9mWbLb5OfHM tWcyM4e5vZLk0/lrGq0g+hJmxHkjNDi2K4tkjymW4vzCLvgrK6TDntzNJie2XU/dxb CgVMyZBlGmuWQ== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:55 +0100 Subject: [PATCH v7 26/29] KVM: arm64: Expose SME to nested guests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-26-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=1234; i=broonie@kernel.org; h=from:subject:message-id; bh=ApIjPu6tr41pN88JrHKurRe18MYIB0RS0vVGxBjI5iI=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83MctByn9lZGlMQrCOz++sZYZV3/BxfsPz/F KPOJwdzE3qJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNzAAKCRAk1otyXVSH 0F8yB/sFH7V+bkn2VfS0isUHveeJS62fiiB5c3YS3JAVQ41jZpkvIm2k6AAkqorbB6LxXiwdkrZ rx3xTr8Q3KUrjWok7+55CSTU8K/SNKwH2OYYXXYsFKjEPtA7KN+Aaw63IUzqgSmDrovAOUH6SI+ 5Yu0HHJ9CyKK/ghNSJD8QwerdqfyQXeZXucZ62++Yq/02G1e+wJTAyIC2tvqGYcoTEE5z0aKR9D VAdEUMAvWAo68qn1FSBneDg6JvJr+TB57KF1XNmpEvHVn5MCTCe8SF7laOSI+ekUFdbhhT1GS/b V2ByGttxzG+ZONQtxG4WC8NuL7b3NowIv5Z0Gmfe//B90HqX X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB With support for context switching SME state in place allow access to SME in nested guests. The SME floating point state is handled along with all the other floating point state, SME specific floating point exceptions are directed into the same handlers as other floating point exceptions with NV specific handling for the vector lengths already in place. TPIDR2_EL0 is context switched along with the other TPIDRs as part of the main guest register context switch. SME priority support is currently masked from all guests including nested ones. Signed-off-by: Mark Brown --- arch/arm64/kvm/nested.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 153b3e11b115..804694f2dc9a 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -1458,9 +1458,10 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 va= l) break; =20 case SYS_ID_AA64PFR1_EL1: - /* Only support BTI, SSBS, CSV2_frac */ + /* Only support BTI, SSBS, SME, CSV2_frac */ val &=3D (ID_AA64PFR1_EL1_BT | ID_AA64PFR1_EL1_SSBS | + ID_AA64PFR1_EL1_SME | ID_AA64PFR1_EL1_CSV2_frac); break; =20 --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 28382216E26; Fri, 22 Aug 2025 01:56:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827769; cv=none; b=Gn/1x3V1quitF9RuGgon2YQxSpkklmLkHYkWDKarRalBe5kujB4BQuHPx7lU+0++kjiPefmbxWx3ZfJpgeQTgugCiAD3/++5ivcoj6MbyCBZVBW+o77B3KsXRuOMWret/NhFcOkhDV9GiM8UPFYCz+V/kpope+9Z74n/lenhlXY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827769; c=relaxed/simple; bh=XqEN3TlOUqdTV/4QilKcAUW5tU01fUqiX4rm0wGB/6w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lgkPj6jmVy+w8wfrU9ytDoM9gddEuiM4azxmxRVSzNs2jVgpNEZLE2XoQosBliNCUSfwML3hg8beQ0FAI5BlZ12WKvIvfKDr5xMjPR9XymFQmuE4DsO5ZwJFvM5mEGvMvD/DYEBPt/2+0zoyLGiJppasl6ASO2CqgIt54aBKqV0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kK+sICmh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kK+sICmh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6324FC4CEEB; Fri, 22 Aug 2025 01:56:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827768; bh=XqEN3TlOUqdTV/4QilKcAUW5tU01fUqiX4rm0wGB/6w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kK+sICmh8HRFi5On9NzQbJy/G4BkN9XZhhdbRoLEWamcMK+ZaVIIElsqXZnnqsXk1 w0we63q8BEvRrtKNeZAqfug2Fhp4nO2+oUh2E35qNGwpeodvZPvwhOYgvHlxzQ72J9 XL2oPnrVHk1tnxOOoLS9tqrE4LZU7G55G8aPVJtaSYEvopVJGh1u5cQeWKxgF8Xy6y ihNmV/2yJduARDTtJYWzC3Ekhu/H1T+0X9QmXjponapJIur34v/WZVGH5/4Zf33S0e 9xktn7IBuN/cvGA8uz2zleA+iY33zyhIEm+yFhlOFwZZ+MafMU2blaFALtHonnIGPh uMavUqY/V8Qmw== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:56 +0100 Subject: [PATCH v7 27/29] KVM: arm64: Provide interface for configuring and enabling SME for guests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-27-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=15759; i=broonie@kernel.org; h=from:subject:message-id; bh=XqEN3TlOUqdTV/4QilKcAUW5tU01fUqiX4rm0wGB/6w=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83N6uR89ZP91AV4v809vI+YZl9xEKG3WYgRd PzCHLxcoNeJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNzQAKCRAk1otyXVSH 0AmpB/wMMSRdG6SyiFuAkvaRbnBwJpClQW4mhCh2b0t9YabsjAwGJfd+83G+Cy7Ene5G/d0u6S5 437lmqZKWlLpstyTrxBUB1oeBprlJbZd1S2MH3q6rl3jLcuGCMQprm8vz2JrpIjX2qoIJk0uGSg j1csTR4jO6iuu2pr/orvFtPGRUpviqvgjrsUBo5LE/EU3yzjUgWkCkRMWtFIfsOMrLFIRr/9/iF 4Wqg7u4d3DkEckx11+k8UD6he25Ttg7JdSq8i3jOqmwHPEefYMobwuFIOjU0FMswadxKfMuWSbe Y+9/WUwxiUxJNjSRxZGB9egQD7ufG/OxBTSRL/8WDGKU+YIw X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Since SME requires configuration of a vector length in order to know the size of both the streaming mode SVE state and ZA array we implement a capability for it and require that it be enabled and finalized before the SME specific state can be accessed, similarly to SVE. Due to the overlap with sizing the SVE state we finalise both SVE and SME with a single finalization, preventing any further changes to the SVE and SME configuration once KVM_ARM_VCPU_VEC (an alias for _VCPU_SVE) has been finalised. This is not a thing of great elegance but it ensures that we never have a state where one of SVE or SME is finalised and the other not, avoiding complexity. SME is supported for normal and protected guests. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 12 +++- arch/arm64/include/uapi/asm/kvm.h | 1 + arch/arm64/kvm/arm.c | 10 ++++ arch/arm64/kvm/hyp/nvhe/pkvm.c | 76 +++++++++++++++++++----- arch/arm64/kvm/hyp/nvhe/sys_regs.c | 6 ++ arch/arm64/kvm/reset.c | 116 +++++++++++++++++++++++++++++++--= ---- include/uapi/linux/kvm.h | 1 + 7 files changed, 189 insertions(+), 33 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index fa646da80e3e..809cd1843386 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -39,7 +39,7 @@ =20 #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS =20 -#define KVM_VCPU_MAX_FEATURES 9 +#define KVM_VCPU_MAX_FEATURES 10 #define KVM_VCPU_VALID_FEATURES (BIT(KVM_VCPU_MAX_FEATURES) - 1) =20 #define KVM_REQ_SLEEP \ @@ -81,6 +81,7 @@ extern unsigned int __ro_after_init kvm_host_max_vl[ARM64= _VEC_MAX]; DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use); =20 int __init kvm_arm_init_sve(void); +int __init kvm_arm_init_sme(void); =20 u32 __attribute_const__ kvm_target_cpu(void); void kvm_reset_vcpu(struct kvm_vcpu *vcpu); @@ -1146,7 +1147,14 @@ struct kvm_vcpu_arch { __size_ret; \ }) =20 -#define vcpu_sve_state_size(vcpu) sve_state_size_from_vl((vcpu)->arch.max_= vl[ARM64_VEC_SVE]) +#define vcpu_sve_state_size(vcpu) ({ \ + unsigned int __max_vl; \ + \ + __max_vl =3D max((vcpu)->arch.max_vl[ARM64_VEC_SVE], \ + (vcpu)->arch.max_vl[ARM64_VEC_SME]); \ + \ + sve_state_size_from_vl(__max_vl); \ +}) =20 #define vcpu_sme_state(vcpu) (kern_hyp_va((vcpu)->arch.sme_state)) =20 diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/as= m/kvm.h index cf75a830f17a..4fb0d7353d54 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -106,6 +106,7 @@ struct kvm_regs { #define KVM_ARM_VCPU_PTRAUTH_GENERIC 6 /* VCPU uses generic authentication= */ #define KVM_ARM_VCPU_HAS_EL2 7 /* Support nested virtualization */ #define KVM_ARM_VCPU_HAS_EL2_E2H0 8 /* Limit NV support to E2H RES0 */ +#define KVM_ARM_VCPU_SME 9 /* enable SME for this CPU */ =20 /* * An alias for _SVE since we finalize VL configuration for both SVE and S= ME diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 888f7c7abf54..ec74c6bd072f 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -392,6 +392,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long = ext) case KVM_CAP_ARM_SVE: r =3D system_supports_sve(); break; + case KVM_CAP_ARM_SME: + r =3D system_supports_sme(); + break; case KVM_CAP_ARM_PTRAUTH_ADDRESS: case KVM_CAP_ARM_PTRAUTH_GENERIC: r =3D kvm_has_full_ptr_auth(); @@ -1442,6 +1445,9 @@ static unsigned long system_supported_vcpu_features(v= oid) if (!system_supports_sve()) clear_bit(KVM_ARM_VCPU_SVE, &features); =20 + if (!system_supports_sme()) + clear_bit(KVM_ARM_VCPU_SME, &features); + if (!kvm_has_full_ptr_auth()) { clear_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, &features); clear_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, &features); @@ -2849,6 +2855,10 @@ static __init int kvm_arm_init(void) if (err) return err; =20 + err =3D kvm_arm_init_sme(); + if (err) + return err; + err =3D kvm_arm_vmid_alloc_init(); if (err) { kvm_err("Failed to initialize VMID allocator.\n"); diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index fc9fb2e693f6..ce3e13acc25c 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -148,10 +148,6 @@ static int pkvm_check_pvm_cpu_features(struct kvm_vcpu= *vcpu) !kvm_has_feat(kvm, ID_AA64PFR0_EL1, AdvSIMD, IMP)) return -EINVAL; =20 - /* No SME support in KVM right now. Check to catch if it changes. */ - if (kvm_has_feat(kvm, ID_AA64PFR1_EL1, SME, IMP)) - return -EINVAL; - return 0; } =20 @@ -364,6 +360,11 @@ static void pkvm_init_features_from_host(struct pkvm_h= yp_vm *hyp_vm, const struc kvm->arch.flags |=3D host_arch_flags & BIT(KVM_ARCH_FLAG_GUEST_HAS_SVE); } =20 + if (kvm_pvm_ext_allowed(KVM_CAP_ARM_SME)) { + set_bit(KVM_ARM_VCPU_SME, allowed_features); + kvm->arch.flags |=3D host_arch_flags & BIT(KVM_ARCH_FLAG_GUEST_HAS_SME); + } + bitmap_and(kvm->arch.vcpu_features, host_kvm->arch.vcpu_features, allowed_features, KVM_VCPU_MAX_FEATURES); } @@ -386,6 +387,18 @@ static void unpin_host_sve_state(struct pkvm_hyp_vcpu = *hyp_vcpu) sve_state + vcpu_sve_state_size(&hyp_vcpu->vcpu)); } =20 +static void unpin_host_sme_state(struct pkvm_hyp_vcpu *hyp_vcpu) +{ + void *sme_state; + + if (!vcpu_has_feature(&hyp_vcpu->vcpu, KVM_ARM_VCPU_SME)) + return; + + sme_state =3D kern_hyp_va(hyp_vcpu->vcpu.arch.sme_state); + hyp_unpin_shared_mem(sme_state, + sme_state + vcpu_sme_state_size(&hyp_vcpu->vcpu)); +} + static void unpin_host_vcpus(struct pkvm_hyp_vcpu *hyp_vcpus[], unsigned int nr_vcpus) { @@ -399,6 +412,7 @@ static void unpin_host_vcpus(struct pkvm_hyp_vcpu *hyp_= vcpus[], =20 unpin_host_vcpu(hyp_vcpu->host_vcpu); unpin_host_sve_state(hyp_vcpu); + unpin_host_sme_state(hyp_vcpu); } } =20 @@ -413,23 +427,35 @@ static void init_pkvm_hyp_vm(struct kvm *host_kvm, st= ruct pkvm_hyp_vm *hyp_vm, pkvm_init_features_from_host(hyp_vm, host_kvm); } =20 -static int pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp_vcpu, struct kvm_v= cpu *host_vcpu) +static int pkvm_vcpu_init_vec(struct pkvm_hyp_vcpu *hyp_vcpu, struct kvm_v= cpu *host_vcpu) { struct kvm_vcpu *vcpu =3D &hyp_vcpu->vcpu; - unsigned int sve_max_vl; - size_t sve_state_size; - void *sve_state; + unsigned int sve_max_vl, sme_max_vl; + size_t sve_state_size, sme_state_size; + void *sve_state, *sme_state; int ret =3D 0; =20 - if (!vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) { + if (!vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE) && + !vcpu_has_feature(vcpu, KVM_ARM_VCPU_SME)) { vcpu_clear_flag(vcpu, VCPU_VEC_FINALIZED); return 0; } =20 /* Limit guest vector length to the maximum supported by the host. */ - sve_max_vl =3D min(READ_ONCE(host_vcpu->arch.max_vl[ARM64_VEC_SVE]), - kvm_host_max_vl[ARM64_VEC_SVE]); - sve_state_size =3D sve_state_size_from_vl(sve_max_vl); + if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) + sve_max_vl =3D min(READ_ONCE(host_vcpu->arch.max_vl[ARM64_VEC_SVE]), + kvm_host_max_vl[ARM64_VEC_SVE]); + else + sve_max_vl =3D 0; + + if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SME)) + sme_max_vl =3D min(READ_ONCE(host_vcpu->arch.max_vl[ARM64_VEC_SME]), + kvm_host_max_vl[ARM64_VEC_SME]); + else + sme_max_vl =3D 0; + + /* We need SVE storage for the larger of normal or streaming mode */ + sve_state_size =3D sve_state_size_from_vl(max(sve_max_vl, sme_max_vl)); sve_state =3D kern_hyp_va(READ_ONCE(host_vcpu->arch.sve_state)); =20 if (!sve_state || !sve_state_size) { @@ -441,12 +467,36 @@ static int pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *h= yp_vcpu, struct kvm_vcpu *h if (ret) goto err; =20 + if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SME)) { + sme_state_size =3D sme_state_size_from_vl(sme_max_vl, + vcpu_has_sme2(vcpu)); + sme_state =3D kern_hyp_va(READ_ONCE(host_vcpu->arch.sme_state)); + + if (!sme_state || !sme_state_size) { + ret =3D -EINVAL; + goto err_sve_mapped; + } + + ret =3D hyp_pin_shared_mem(sme_state, sme_state + sme_state_size); + if (ret) + goto err_sve_mapped; + } else { + sme_state =3D 0; + } + vcpu->arch.sve_state =3D sve_state; vcpu->arch.max_vl[ARM64_VEC_SVE] =3D sve_max_vl; =20 + vcpu->arch.sme_state =3D sme_state; + vcpu->arch.max_vl[ARM64_VEC_SME] =3D sme_max_vl; + return 0; + +err_sve_mapped: + hyp_unpin_shared_mem(sve_state, sve_state + sve_state_size); err: clear_bit(KVM_ARM_VCPU_SVE, vcpu->kvm->arch.vcpu_features); + clear_bit(KVM_ARM_VCPU_SME, vcpu->kvm->arch.vcpu_features); return ret; } =20 @@ -476,7 +526,7 @@ static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp= _vcpu, if (ret) goto done; =20 - ret =3D pkvm_vcpu_init_sve(hyp_vcpu, host_vcpu); + ret =3D pkvm_vcpu_init_vec(hyp_vcpu, host_vcpu); done: if (ret) unpin_host_vcpu(host_vcpu); diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/s= ys_regs.c index 1ddd9ed3cbb3..eed177dfcb96 100644 --- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c +++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c @@ -66,6 +66,11 @@ static bool vm_has_ptrauth(const struct kvm *kvm) kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_PTRAUTH_GENERIC); } =20 +static bool vm_has_sme(const struct kvm *kvm) +{ + return system_supports_sme() && kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_SM= E); +} + static bool vm_has_sve(const struct kvm *kvm) { return system_supports_sve() && kvm_vcpu_has_feature(kvm, KVM_ARM_VCPU_SV= E); @@ -102,6 +107,7 @@ static const struct pvm_ftr_bits pvmid_aa64pfr0[] =3D { }; =20 static const struct pvm_ftr_bits pvmid_aa64pfr1[] =3D { + MAX_FEAT_FUNC(ID_AA64PFR1_EL1, SME, SME2, vm_has_sme), MAX_FEAT(ID_AA64PFR1_EL1, BT, IMP), MAX_FEAT(ID_AA64PFR1_EL1, SSBS, SSBS2), MAX_FEAT_ENUM(ID_AA64PFR1_EL1, MTE_frac, NI), diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index a8684a1346ec..e6dc04267cbb 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -76,6 +76,34 @@ int __init kvm_arm_init_sve(void) return 0; } =20 +int __init kvm_arm_init_sme(void) +{ + if (system_supports_sme()) { + kvm_max_vl[ARM64_VEC_SME] =3D sme_max_virtualisable_vl(); + kvm_host_max_vl[ARM64_VEC_SME] =3D sme_max_vl(); + kvm_nvhe_sym(kvm_host_max_vl[ARM64_VEC_SME]) =3D kvm_host_max_vl[ARM64_V= EC_SME]; + + /* + * The get_sve_reg()/set_sve_reg() ioctl interface will need + * to be extended with multiple register slice support in + * order to support vector lengths greater than + * VL_ARCH_MAX: + */ + if (WARN_ON(kvm_max_vl[ARM64_VEC_SME] > VL_ARCH_MAX)) + kvm_max_vl[ARM64_VEC_SME] =3D VL_ARCH_MAX; + + /* + * Don't even try to make use of vector lengths that + * aren't available on all CPUs, for now: + */ + if (kvm_max_vl[ARM64_VEC_SME] < sme_max_vl()) + pr_warn("KVM: SME vector length for guests limited to %u bytes\n", + kvm_max_vl[ARM64_VEC_SME]); + } + + return 0; +} + static void kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu) { vcpu->arch.max_vl[ARM64_VEC_SVE] =3D kvm_max_vl[ARM64_VEC_SVE]; @@ -88,42 +116,86 @@ static void kvm_vcpu_enable_sve(struct kvm_vcpu *vcpu) set_bit(KVM_ARCH_FLAG_GUEST_HAS_SVE, &vcpu->kvm->arch.flags); } =20 +static void kvm_vcpu_enable_sme(struct kvm_vcpu *vcpu) +{ + vcpu->arch.max_vl[ARM64_VEC_SME] =3D kvm_max_vl[ARM64_VEC_SME]; + + /* + * Userspace can still customize the vector lengths by writing + * KVM_REG_ARM64_SME_VLS. Allocation is deferred until + * kvm_arm_vcpu_finalize(), which freezes the configuration. + */ + set_bit(KVM_ARCH_FLAG_GUEST_HAS_SME, &vcpu->kvm->arch.flags); +} + /* - * Finalize vcpu's maximum SVE vector length, allocating - * vcpu->arch.sve_state as necessary. + * Finalize vcpu's maximum vector lengths, allocating + * vcpu->arch.sve_state and vcpu->arch.sme_state as necessary. */ static int kvm_vcpu_finalize_vec(struct kvm_vcpu *vcpu) { - void *buf; + void *sve_state, *sme_state; unsigned int vl; - size_t reg_sz; int ret; =20 - vl =3D vcpu->arch.max_vl[ARM64_VEC_SVE]; - /* * Responsibility for these properties is shared between * kvm_arm_init_sve(), kvm_vcpu_enable_sve() and * set_sve_vls(). Double-check here just to be sure: */ - if (WARN_ON(!sve_vl_valid(vl) || vl > sve_max_virtualisable_vl() || - vl > VL_ARCH_MAX)) - return -EIO; + if (vcpu_has_sve(vcpu)) { + vl =3D vcpu->arch.max_vl[ARM64_VEC_SVE]; + if (WARN_ON(!sve_vl_valid(vl) || + vl > sve_max_virtualisable_vl() || + vl > VL_ARCH_MAX)) + return -EIO; + } =20 - reg_sz =3D vcpu_sve_state_size(vcpu); - buf =3D kzalloc(reg_sz, GFP_KERNEL_ACCOUNT); - if (!buf) + /* Similarly for SME */ + if (vcpu_has_sme(vcpu)) { + vl =3D vcpu->arch.max_vl[ARM64_VEC_SME]; + if (WARN_ON(!sve_vl_valid(vl) || + vl > sme_max_virtualisable_vl() || + vl > VL_ARCH_MAX)) + return -EIO; + } + + sve_state =3D kzalloc(vcpu_sve_state_size(vcpu), GFP_KERNEL_ACCOUNT); + if (!sve_state) return -ENOMEM; =20 - ret =3D kvm_share_hyp(buf, buf + reg_sz); - if (ret) { - kfree(buf); - return ret; + ret =3D kvm_share_hyp(sve_state, sve_state + vcpu_sve_state_size(vcpu)); + if (ret) + goto err_sve_alloc; + + if (vcpu_has_sme(vcpu)) { + sme_state =3D kzalloc(vcpu_sme_state_size(vcpu), + GFP_KERNEL_ACCOUNT); + if (!sme_state) { + ret =3D -ENOMEM; + goto err_sve_map; + } + + ret =3D kvm_share_hyp(sme_state, + sme_state + vcpu_sme_state_size(vcpu)); + if (ret) + goto err_sme_alloc; + } else { + sme_state =3D NULL; } -=09 - vcpu->arch.sve_state =3D buf; + + vcpu->arch.sve_state =3D sve_state; + vcpu->arch.sme_state =3D sme_state; vcpu_set_flag(vcpu, VCPU_VEC_FINALIZED); return 0; + +err_sme_alloc: + kfree(sme_state); +err_sve_map: + kvm_unshare_hyp(sve_state, sve_state + vcpu_sve_state_size(vcpu)); +err_sve_alloc: + kfree(sve_state); + return ret; } =20 int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature) @@ -153,12 +225,16 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu) void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu) { void *sve_state =3D vcpu->arch.sve_state; + void *sme_state =3D vcpu->arch.sme_state; =20 kvm_unshare_hyp(vcpu, vcpu + 1); if (sve_state) kvm_unshare_hyp(sve_state, sve_state + vcpu_sve_state_size(vcpu)); kfree(sve_state); free_page((unsigned long)vcpu->arch.ctxt.vncr_array); + if (sme_state) + kvm_unshare_hyp(sme_state, sme_state + vcpu_sme_state_size(vcpu)); + kfree(sme_state); kfree(vcpu->arch.vncr_tlb); kfree(vcpu->arch.ccsidr); } @@ -167,6 +243,8 @@ static void kvm_vcpu_reset_vec(struct kvm_vcpu *vcpu) { if (vcpu_has_sve(vcpu)) memset(vcpu->arch.sve_state, 0, vcpu_sve_state_size(vcpu)); + if (vcpu_has_sme(vcpu)) + memset(vcpu->arch.sme_state, 0, vcpu_sme_state_size(vcpu)); } =20 /** @@ -206,6 +284,8 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu) if (!kvm_arm_vcpu_vec_finalized(vcpu)) { if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SVE)) kvm_vcpu_enable_sve(vcpu); + if (vcpu_has_feature(vcpu, KVM_ARM_VCPU_SME)) + kvm_vcpu_enable_sme(vcpu); } else { kvm_vcpu_reset_vec(vcpu); } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index f0f0d49d2544..8aacbc837b6e 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -962,6 +962,7 @@ struct kvm_enable_cap { #define KVM_CAP_ARM_EL2_E2H0 241 #define KVM_CAP_RISCV_MP_STATE_RESET 242 #define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243 +#define KVM_CAP_ARM_SME 244 =20 struct kvm_irq_routing_irqchip { __u32 irqchip; --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98217212568; Fri, 22 Aug 2025 01:56:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827772; cv=none; b=m1JhAovoT4ST611fPkQLVEK9+ZZtpsmISobh0mioF+vwfj2nG80TH9mX1dBAEYy9zgaNbF7bP+KTihFT5xe2a2QNleBgGtS5giu6xkAkg98/LwxIzmb23G6ZBMPWWxggwcTu+vcUHVnL5cvGdHHI4z4kCpj/1lE+rZZEWshV53Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827772; c=relaxed/simple; bh=ZvTUw7NPQ0p4ee6PuzgOvjpUagMHBpEvC3cvgofAwS0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Y8f/frpSn+dGFKQMuHDFjwi50TCKWq25N25D9uK5MNyxxN0AoS15VJPdxO67CY9vlHgIOfYOhsq0cW7SwsI+7YiiG/JeXUIuvYLLXwSxMbTC/VhwoCTr+JNLc/R5gN/rD8rqDvplSpwJz8rDSyjzjgTXaZX3QCb6q+QATM0SB9c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gBl+zA5R; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gBl+zA5R" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25B30C116B1; Fri, 22 Aug 2025 01:56:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827772; bh=ZvTUw7NPQ0p4ee6PuzgOvjpUagMHBpEvC3cvgofAwS0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gBl+zA5R7oUSSx7KRdJpdV6ZbsZZ/iIPbBv3OrjWPdJM3K0IRbBNh+LdXNM7kxrkj CqbdZOD91MOebufmJT7YltFBuCmw5L3iiDQi9Dl2F+rYpjTPck6o5FX09joXWj+i7j grVXwyXbVs5yWNX+IUqsCQ5CrbRnJDkCYpVGgvfNCG6imt8bw4a9RttPWv3KKA+5E5 lHTtgVQQr8dWQ95RGgY8hLRKygAYMAU617sbJJvPrCaXP13ijSBI3L9kFEshhy2wOQ ceRBhaSi8oEatWrN/Sb6fEqvPwPG7hAAO2VWGGw8z8CWMO9EZ/Lk8zcpuwMfcXG/ma /Chf608r/lRWQ== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:57 +0100 Subject: [PATCH v7 28/29] KVM: arm64: selftests: Add SME system registers to get-reg-list Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-28-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=3013; i=broonie@kernel.org; h=from:subject:message-id; bh=ZvTUw7NPQ0p4ee6PuzgOvjpUagMHBpEvC3cvgofAwS0=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83OuWRF/YCFv/kLUPVZ347uLjDU2lPDUmc3r 3ZmR/vo6uyJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNzgAKCRAk1otyXVSH 0LDEB/9NwqkA1r0mkynUGd0cpQqIOSKJN58O5yKVNJw4FaRLCJjF+FEij5qL/tShskY9TTUgaLB Gf4vBsx0B0BqC4KAGK1YEriim7t+5YHdT3Z8wRJv9a+6Mijkp1yTivil/Y9QUT/Ivn3b+7Al1pL BQY4ZxjuK+uSbyClydk+3ESgNSRZApRFnhT28nKIXv2uf5mUUS5/6KGVDgxy5kgCRaU92iJTwox ufImvkmQH9I0e4l/dR0yqQeMe721u4A8jcezobgztFzT1hKXpLaZu2StdxHgGhUCbU+POtW5/f9 v+VWFvniHK1rQE5zly7PB+PrOJVneHjnWtgAnFu9oBsvCVtF X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB SME adds a number of new system registers, update get-reg-list to check for them based on the visibility of SME. Signed-off-by: Mark Brown --- tools/testing/selftests/kvm/arm64/get-reg-list.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/arm64/get-reg-list.c b/tools/testi= ng/selftests/kvm/arm64/get-reg-list.c index 011fad95dd02..54b371330f57 100644 --- a/tools/testing/selftests/kvm/arm64/get-reg-list.c +++ b/tools/testing/selftests/kvm/arm64/get-reg-list.c @@ -61,7 +61,13 @@ static struct feature_id_reg feat_id_regs[] =3D { REG_FEAT(HFGITR2_EL2, ID_AA64MMFR0_EL1, FGT, FGT2), REG_FEAT(HDFGRTR2_EL2, ID_AA64MMFR0_EL1, FGT, FGT2), REG_FEAT(HDFGWTR2_EL2, ID_AA64MMFR0_EL1, FGT, FGT2), - REG_FEAT(ZCR_EL2, ID_AA64PFR0_EL1, SVE, IMP), + REG_FEAT(SMCR_EL1, ID_AA64PFR1_EL1, SME, IMP), + REG_FEAT(SMCR_EL2, ID_AA64PFR1_EL1, SME, IMP), + REG_FEAT(SMIDR_EL1, ID_AA64PFR1_EL1, SME, IMP), + REG_FEAT(SMPRI_EL1, ID_AA64PFR1_EL1, SME, IMP), + REG_FEAT(SMPRIMAP_EL2, ID_AA64PFR1_EL1, SME, IMP), + REG_FEAT(TPIDR2_EL0, ID_AA64PFR1_EL1, SME, IMP), + REG_FEAT(SVCR, ID_AA64PFR1_EL1, SME, IMP), REG_FEAT(SCTLR2_EL1, ID_AA64MMFR3_EL1, SCTLRX, IMP), REG_FEAT(VDISR_EL2, ID_AA64PFR0_EL1, RAS, IMP), REG_FEAT(VSESR_EL2, ID_AA64PFR0_EL1, RAS, IMP), @@ -351,6 +357,7 @@ static __u64 base_regs[] =3D { ARM64_SYS_REG(3, 0, 0, 0, 0), /* MIDR_EL1 */ ARM64_SYS_REG(3, 0, 0, 0, 6), /* REVIDR_EL1 */ ARM64_SYS_REG(3, 1, 0, 0, 1), /* CLIDR_EL1 */ + ARM64_SYS_REG(3, 1, 0, 0, 6), /* SMIDR_EL1 */ ARM64_SYS_REG(3, 1, 0, 0, 7), /* AIDR_EL1 */ ARM64_SYS_REG(3, 3, 0, 0, 1), /* CTR_EL0 */ ARM64_SYS_REG(2, 0, 0, 0, 4), @@ -482,6 +489,8 @@ static __u64 base_regs[] =3D { ARM64_SYS_REG(3, 0, 1, 0, 1), /* ACTLR_EL1 */ ARM64_SYS_REG(3, 0, 1, 0, 2), /* CPACR_EL1 */ KVM_ARM64_SYS_REG(SYS_SCTLR2_EL1), + ARM64_SYS_REG(3, 0, 1, 2, 4), /* SMPRI_EL1 */ + ARM64_SYS_REG(3, 0, 1, 2, 6), /* SMCR_EL1 */ ARM64_SYS_REG(3, 0, 2, 0, 0), /* TTBR0_EL1 */ ARM64_SYS_REG(3, 0, 2, 0, 1), /* TTBR1_EL1 */ ARM64_SYS_REG(3, 0, 2, 0, 2), /* TCR_EL1 */ @@ -502,9 +511,11 @@ static __u64 base_regs[] =3D { ARM64_SYS_REG(3, 0, 13, 0, 4), /* TPIDR_EL1 */ ARM64_SYS_REG(3, 0, 14, 1, 0), /* CNTKCTL_EL1 */ ARM64_SYS_REG(3, 2, 0, 0, 0), /* CSSELR_EL1 */ + ARM64_SYS_REG(3, 3, 4, 2, 2), /* SVCR */ ARM64_SYS_REG(3, 3, 10, 2, 4), /* POR_EL0 */ ARM64_SYS_REG(3, 3, 13, 0, 2), /* TPIDR_EL0 */ ARM64_SYS_REG(3, 3, 13, 0, 3), /* TPIDRRO_EL0 */ + ARM64_SYS_REG(3, 3, 13, 0, 5), /* TPIDR2_EL0 */ ARM64_SYS_REG(3, 3, 14, 0, 1), /* CNTPCT_EL0 */ ARM64_SYS_REG(3, 3, 14, 2, 1), /* CNTP_CTL_EL0 */ ARM64_SYS_REG(3, 3, 14, 2, 2), /* CNTP_CVAL_EL0 */ @@ -713,6 +724,8 @@ static __u64 el2_regs[] =3D { SYS_REG(HFGITR_EL2), SYS_REG(HACR_EL2), SYS_REG(ZCR_EL2), + SYS_REG(SMPRIMAP_EL2), + SYS_REG(SMCR_EL2), SYS_REG(HCRX_EL2), SYS_REG(TTBR0_EL2), SYS_REG(TTBR1_EL2), --=20 2.39.5 From nobody Sat Oct 4 00:26:53 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B44D12222D2; Fri, 22 Aug 2025 01:56:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827776; cv=none; b=cEWpwoftC+Ze7Iy55zdrRggBnLSPovUxk2ekeLHxAYKp68EsryGzpF9N+lqicfRmfPVlBqI0LD9VCvzEUh1Euba+Vjila+WiYTfcW8hyDKBi3ks/cQC9ZzO9YD7I43Mdq/KXwzJ38xtJIsirzdtezkGIVdosTG2anebDxIBt7F4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755827776; c=relaxed/simple; bh=nitp/ehKgCus2GLbBQJBw9hgUMhrPQICaIiiL3f5Pj4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aJFDx2LypB0XJm9VrhqVyZPLzNAshG/zBT70eoGBGZ1X9phLrRyveQZKqSOsNcI0y0d9QL7rk/K9JKPOslH31Dh7qmhbeTkSkopVYdrXgTlwfV/Bk+gdDq4g9cyUmDXK4ltnjOzzLWuDfMXglDHCX962ShWI3g1NRyH/YfnDY5w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uIVA9tZN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uIVA9tZN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D7DD0C113D0; Fri, 22 Aug 2025 01:56:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1755827776; bh=nitp/ehKgCus2GLbBQJBw9hgUMhrPQICaIiiL3f5Pj4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=uIVA9tZNIo6iHDNR/x6rF2D1tzPnqJJ6tnfD7c4Cc0e4UaSfZJqNs2Ps5kkbIlDq+ hm8s3aRDF6sbxn/HPcsYlDUDfgiBaXmu3QDyZHKDLAmthftVd1qmIKvIwbDXXkoyoH qMKsL1MTVuim3EUX6Y1oJnSb9depeFJxDrcbBy+r9vhophoei0srSRO+lp9KTmexGl 4sJJ3mWQJgSR1LJBrw4vSbCL4W1u/JVNs1lcXeDPj5VvLbyuHOjSkaWwMOI5DaZOie aQIJd42m1O+sQ5wy06KJPOmHn42iyMOi5xoPZxAmyoS/aNBaI68YfF38TE8kVSxWP8 yTh31aIjMr+pg== From: Mark Brown Date: Fri, 22 Aug 2025 02:53:58 +0100 Subject: [PATCH v7 29/29] KVM: arm64: selftests: Add SME to set_id_regs test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250822-kvm-arm64-sme-v7-29-7a65d82b8b10@kernel.org> References: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> In-Reply-To: <20250822-kvm-arm64-sme-v7-0-7a65d82b8b10@kernel.org> To: Marc Zyngier , Oliver Upton , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan Cc: Dave Martin , Fuad Tabba , Mark Rutland , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, Mark Brown X-Mailer: b4 0.15-dev-cff91 X-Developer-Signature: v=1; a=openpgp-sha256; l=3326; i=broonie@kernel.org; h=from:subject:message-id; bh=nitp/ehKgCus2GLbBQJBw9hgUMhrPQICaIiiL3f5Pj4=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBop83PorixV4VK+Ax/84bQ+IpyKr+GJjtxCwDZa IXOskJlULyJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCaKfNzwAKCRAk1otyXVSH 0HfpB/9xtpA9aNmFd7Bdg9XrF2Ky+JDU5oGPTztnwxo1ks0T+w61WY8TkPMmOOYTBkEhp2WAnsw JslR3dYosV2sOj+dSFQOkapk/N2rhrsY+9p/rj7BnUwtWyEQ0fEtmT7C8VFTlDnfNZM/Qb5eltP gBEcg1YRCgEvLlpIs8ZHgd1WfR7AyvVyEew81eU8F9isEKIgi/n5/+XzFCnODX161EW8kmqx+ce 0zzqMuluMKozarzBlekHiWV03ylyguUMnj+SuWal6/Tc9I4nGwdNsqLa8Hvbh8NDHYg26oazmZ0 Tvtz1l6Ubjc6zOIGh1N+iBYskQcK0WIRI4mPocSKToI0BW77 X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Add coverage of the SME ID registers to set_id_regs, ID_AA64PFR1_EL1.SME becomes writable and we add ID_AA64SMFR_EL1 and it's subfields. Signed-off-by: Mark Brown --- tools/testing/selftests/kvm/arm64/set_id_regs.c | 27 +++++++++++++++++++++= +++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testin= g/selftests/kvm/arm64/set_id_regs.c index d3bf9204409c..f3f15145aa69 100644 --- a/tools/testing/selftests/kvm/arm64/set_id_regs.c +++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c @@ -196,6 +196,28 @@ static const struct reg_ftr_bits ftr_id_aa64mmfr3_el1[= ] =3D { REG_FTR_END, }; =20 +static const struct reg_ftr_bits ftr_id_aa64smfr0_el1[] =3D { + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, FA64, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, LUTv2, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, SMEver, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, I16I64, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, F64F64, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, I16I32, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, B16B16, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, F16F16, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, F8F16, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, F8F32, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, I8I32, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, F16F32, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, B16F32, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, BI32I32, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, F32F32, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, SF8FMA, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, SF8DP4, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, SF8DP2, 0), + REG_FTR_END, +}; + static const struct reg_ftr_bits ftr_id_aa64zfr0_el1[] =3D { REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ZFR0_EL1, F64MM, 0), REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64ZFR0_EL1, F32MM, 0), @@ -227,6 +249,7 @@ static struct test_feature_reg test_regs[] =3D { TEST_REG(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1_el1), TEST_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2_el1), TEST_REG(SYS_ID_AA64MMFR3_EL1, ftr_id_aa64mmfr3_el1), + TEST_REG(SYS_ID_AA64SMFR0_EL1, ftr_id_aa64smfr0_el1), TEST_REG(SYS_ID_AA64ZFR0_EL1, ftr_id_aa64zfr0_el1), }; =20 @@ -243,6 +266,7 @@ static void guest_code(void) GUEST_REG_SYNC(SYS_ID_AA64MMFR0_EL1); GUEST_REG_SYNC(SYS_ID_AA64MMFR1_EL1); GUEST_REG_SYNC(SYS_ID_AA64MMFR2_EL1); + GUEST_REG_SYNC(SYS_ID_AA64SMFR0_EL1); GUEST_REG_SYNC(SYS_ID_AA64ZFR0_EL1); GUEST_REG_SYNC(SYS_CTR_EL0); GUEST_REG_SYNC(SYS_MIDR_EL1); @@ -784,7 +808,8 @@ int main(void) ARRAY_SIZE(ftr_id_aa64isar2_el1) + ARRAY_SIZE(ftr_id_aa64pfr0_el1) + ARRAY_SIZE(ftr_id_aa64pfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr0_el1) + ARRAY_SIZE(ftr_id_aa64mmfr1_el1) + ARRAY_SIZE(ftr_id_aa64mmfr2_el1) + - ARRAY_SIZE(ftr_id_aa64mmfr3_el1) + ARRAY_SIZE(ftr_id_aa64zfr0_el1) - + ARRAY_SIZE(ftr_id_aa64mmfr3_el1) + ARRAY_SIZE(ftr_id_aa64smfr0_el1) + + ARRAY_SIZE(ftr_id_aa64zfr0_el1) - ARRAY_SIZE(test_regs) + 3 + MPAM_IDREG_TEST + MTE_IDREG_TEST; =20 ksft_set_plan(test_cnt); --=20 2.39.5