From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 4EDDF37F8DA; Sun, 19 Jul 2026 23:10:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502603; cv=none; b=dVrpqfwPZwoE2OU0/LUvP/xEBzghAHhfoyJv6yleHvcm/DmoBcQDds/FBRz0fcx6+mCuEEDMA4UoV9NtQT9OZ+/o9R+rGBWHtOzpvDg3hqckkdNhgJTAbRDMPgMGz9yNLC0xnliF2xZunS9E9QkqGFX7/1l1QUlUckrgHbOeNyM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502603; c=relaxed/simple; bh=gzzsP4OMBAKH5syutaWFaVFk6QC8CDQSj953+mInO7w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dLmLbygwin6/RTylqaxHg4J8w9GZD9miGT1Jn9gIy9NS+yOs9UjhYGcg8hZyz5x+EgXCByVdkidtGkKL6wbU275mZirfQ7cdQQ/WDGQiHqrSETgkPjykjH57KE8vD+Mi49UMuiYYnlD138+djJczfih5PKS23kKz803+muK4r2c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EJ9sE2Ri; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EJ9sE2Ri" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0285D1F00A3F; Sun, 19 Jul 2026 23:09:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502602; bh=/QjA1AblP9L+Kt9SpYOOkyJVVOOzYmepn7GTlwZFelA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=EJ9sE2RiBUQxCFuiFPXydF8h+uV9Oy9JfnZoPElmM2kbR/b2HQejIeI4k1dz+0tfG 0P49uU3jU0v84VcJ6AD2Um3eelB7mOANMLTF30BVxg9fQXIlYVE0dgc15Vw0UhfwPo IX9pugXmLBGZCV3UHjx5Zzl9MnJTfSoWWdDyD2WVfiyE2NzZvcvXFHWV5Ackr4rtBv 355Vo5lNfnAPlLp41NxPp8/0yEBmKzIKslEneDX5X7+sfpeG+rHXA3L5pVwgShi0ju RwDG05tfDUJMIKG3AT5ecklSdjgHc8sFlKUQDPv5VMuCa8gLO2dU4U3G06Cv4bcurj snfa3LAeqSBnA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:28 +0100 Subject: [PATCH v13 01/32] arm64/sysreg: Define full value read/modify/write helpers 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: <20260720-kvm-arm64-sme-v13-1-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=951; i=broonie@kernel.org; h=from:subject:message-id; bh=gzzsP4OMBAKH5syutaWFaVFk6QC8CDQSj953+mInO7w=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkoZMR/6y1nJ/QvDSknCa6UuF/9J5+arAKAY E1vwX612VKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZKAAKCRAk1otyXVSH 0CKVB/9VsKJu9cgSiiJyfHAFOEYwnpjgfc124TY52Kf6BosY1o36PT/bvwe8l2uc+BC88AVO8qc UYH/G90hEkt+KVOeXtuYPKuqjDap3wbBeoCBneyrdzbzRH2wbZqzYji6pqncQonOWyYVhBbLxtZ fQ4AqxqOeNqSdjoKAVGEhPKki7hQHZyVLgoYrtahZsV+StV98fdPqWPAA+/y4Mm4+2ubVUzH6s+ XZ805kjF0PARqHXiJ515UsgZbK/t0dugTEE9Ey99qbxAx30nayxoM1M4utxzSpLUzyvEicTYFKR JcVWUZKHwFgqGR5rLjJCgC8Cat2hDBIpjw2GVeunOjuK9EaV X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB We have read/modify write helpers for updating bitfields in sysregs if they have changed but we do not have them for updating the whole register. Define sysreg_cond_update() for that. Signed-off-by: Mark Brown --- arch/arm64/include/asm/sysreg.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysre= g.h index 7aa08d59d494..4b96449e0ffa 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -1235,6 +1235,12 @@ write_sysreg_s(__scs_new, sysreg); \ } while (0) =20 +#define sysreg_cond_update(sysreg, val) \ + sysreg_clear_set(sysreg, ~0UL, val) + +#define sysreg_cond_update_s(sysreg, val) \ + sysreg_clear_set_s(sysreg, ~0UL, val) + #define write_sysreg_hcr(__val) do { \ if (IS_ENABLED(CONFIG_AMPERE_ERRATUM_AC04_CPU_23) && \ (!system_capabilities_finalized() || \ --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 A61C32B9B7; Sun, 19 Jul 2026 23:10:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502607; cv=none; b=EgoGY5p9V+7XGCS7BzgcUXRErxPmA3C+2WPQmfbWi1bDo8QiEaPuHELu6QDs3rao/UWZXrf+sqoe+/nvAjhiu4FAie+/6mINsWHmWlrBsCu4rIMPqKw36Qmwf3TRJ8xVuHZ6irJnWgYUbscnQEbcihKRrev0ywXqrENIFOHUVG8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502607; c=relaxed/simple; bh=clF88Q4Q++Obbm8UOSQg/p4rzpktP8Z7HgDS1dOLUf4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZG7NScw01tLKiQKqGt+zyqEvxLD+zAbJRgsFsgBa9aZk11Z1RszuYj/nHammp56boRo0dSrMrAB6Q0c3BiOmqKKv/HrF5R+sMCCUg+zDGvdCYdTgP+gLbtzNARfSaYeU41nrR2n24xT4kppsmIJ8b895cNNx9ZFn4mpJoA5WTeU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ca09oOBj; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ca09oOBj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5F4571F000E9; Sun, 19 Jul 2026 23:10:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502606; bh=eTfU+3gRILRsep1OeyOpzQlJd2O1qxNpsyVnL6cFMrQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=Ca09oOBjr3+encUJ/u9jcpCA+2WrhlONLFPknKiiUcSm4bZHip3bDeoBOLkSMesBq 2RW2SyTgnVnVumqBdav7dnqGTVbRfUJcc34lVW1QB2Zi1QgcVmKdKeXrbrWseu03Wo HJEWORWveBQv5blLK2xc6yFkuaVh84AdeX/oZYxudZX/lRNSnNxwSvF31aZjOxsk0g j/0aUk0hD21BZuAykxhPwloFAOgK2EDMXHDm8fJe+S57ecKDt+HioAycJ+V8gbRAsI 47lgLFHB0H/nsSIwOXfeSvnM16v6EhsW7Juyn5tZg9DgHeJvC+5KR3qra7bLnti+gy x61rNMMeK7u2Q== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:29 +0100 Subject: [PATCH v13 02/32] arm64/fpsimd: Ensure all of ZCR_EL1 is initialised from idle 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: <20260720-kvm-arm64-sme-v13-2-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3682; i=broonie@kernel.org; h=from:subject:message-id; bh=clF88Q4Q++Obbm8UOSQg/p4rzpktP8Z7HgDS1dOLUf4=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVko7WT9BD6E6lLZIiVH1XDlT15U/QuOW9/ff EG0PpVJG8+JATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZKAAKCRAk1otyXVSH 0DnvB/0QktPiWkbF6fHJalPB1OgY3yy/F0vT9g6NTN8UCrvSd3lZaVgD48hOfO31NeHgEpI0BCv u7bv+ZhtnVfktppXY2fBsk2lBx7TfDeIc3biWpbonSJSRusyf9yaPyG9WYG3YMgkSR94bQsozsz ijjEyS0r7VPN5KWNTleYrmAaPlo5LorS7EvOKJutXWcrmDMC1HlNZ6HsrwecBF9Tms6ap421H98 SgWdwXt0iyxrTfEgUQMy3tPr666H/oDpA3svzX8VAwFI2nIDBFHIvwCwO7cn1qY5YGgabEX/cTM mwZCcT0TXFu0pRWE9fwBX1stg0jaEOq+QzBH9AEyk75K9vcW X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB At present when exiting from idle we do not fully reinitialise ZCR_EL1, we update ZCR_EL1.LEN with a read/modify/write cycle when loading task state but never set any of the other bits to an explicit value. Since currently they are all architecturally RES0 or RAZ/WI this is not a practical issue but it may become one if further fields are defined in the register so we should explicitly configure the whole register. Rename the existing sme_suspend_exit() (which handles this for SME) to fpsimd_suspend_exit() and add set ZCR_EL1 to 0 there, if needed LEN will be updated when loading task state. Signed-off-by: Mark Brown Acked-by: Mark Rutland --- arch/arm64/include/asm/fpsimd.h | 4 ++-- arch/arm64/kernel/fpsimd.c | 24 +++++++++++++----------- arch/arm64/kernel/suspend.c | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index a67d5774e672..e13a85320ab6 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -364,6 +364,8 @@ extern void cpu_enable_sme2(const struct arm64_cpu_capa= bilities *__unused); extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused); extern void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__unused); =20 +extern void fpsimd_suspend_exit(void); + /* * Helpers to translate bit indices in sve_vq_map to VQ values (and * vice versa). This allows find_next_bit() to be used to find the @@ -623,7 +625,6 @@ static inline unsigned int sme_get_vl(void) extern void sme_alloc(struct task_struct *task, bool flush); extern int sme_set_current_vl(unsigned long arg); extern int sme_get_current_vl(void); -extern void sme_suspend_exit(void); =20 static inline size_t __sme_state_size(unsigned int sme_vl) { @@ -779,7 +780,6 @@ static inline int sme_max_vl(void) { return 0; } static inline int sme_max_virtualisable_vl(void) { return 0; } static inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; } static inline int sme_get_current_vl(void) { return -EINVAL; } -static inline void sme_suspend_exit(void) { } =20 static inline size_t __sme_state_size(unsigned int sme_vl) { diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index e7f1682a3059..78c9d8dab545 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1279,24 +1279,26 @@ void __init sme_setup(void) get_sme_default_vl()); } =20 -void sme_suspend_exit(void) +#endif /* CONFIG_ARM64_SME */ + +void fpsimd_suspend_exit(void) { u64 smcr =3D 0; =20 - if (!system_supports_sme()) - return; + if (system_supports_sve()) + write_sysreg_s(0, SYS_ZCR_EL1); =20 - if (system_supports_fa64()) - smcr |=3D SMCR_ELx_FA64; - if (system_supports_sme2()) - smcr |=3D SMCR_ELx_EZT0; + if (system_supports_sme()) { + if (system_supports_fa64()) + smcr |=3D SMCR_ELx_FA64; + if (system_supports_sme2()) + smcr |=3D SMCR_ELx_EZT0; =20 - write_sysreg_s(smcr, SYS_SMCR_EL1); - write_sysreg_s(0, SYS_SMPRI_EL1); + write_sysreg_s(smcr, SYS_SMCR_EL1); + write_sysreg_s(0, SYS_SMPRI_EL1); + } } =20 -#endif /* CONFIG_ARM64_SME */ - /* * Trapped SVE access * diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index eaaff94329cd..e02728d14e0d 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c @@ -81,7 +81,7 @@ void notrace __cpu_suspend_exit(void) */ spectre_v4_enable_mitigation(NULL); =20 - sme_suspend_exit(); + fpsimd_suspend_exit(); =20 /* Restore additional feature-specific configuration */ ptrauth_suspend_exit(); --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 1C66E37F8BD; Sun, 19 Jul 2026 23:10:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502612; cv=none; b=aUwBcbbjNVZtsO/b90OSHXRBbPgvlPIaEDSJPvbF+hUOWXSDd9S+l+rRdUsMN0ECJJUeOHF3juWjZYTofLkeN9SfqhqHifQwAOuc5QK4j++aHQhiJA/PyS9ct/+gzNXC04aK/PX/d1+w/OvSmAMcxAl2Eil3nP24+VXLC28usNU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502612; c=relaxed/simple; bh=/aZpqNOmfe5bYCE+xrs9pBCTsRM6wC0+Qw9617Xjl1A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OIL4zlAA2OxB+Fa3hjQnZP4ZO4wXIU1JQInScZeIV9HSH9qF+YAZAhcmACyt09sbvGztJgjQaEaA5mMojtGVu3Tkk/+WkI02SngkQeHtKVHpfCZL7SdexG5IHIW2JDeExubWqURQUmmAiIeK7RAeOfMRNXCwHgJc/WpSdfqKb2A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=omFuwHYH; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="omFuwHYH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B07DE1F00A3D; Sun, 19 Jul 2026 23:10:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502610; bh=nxaaIcinJ0gCQmFX7l1OGW5liSHlFeSV9iaYkQM1VXg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=omFuwHYHtHVA2wQ4tPYZxSZPMfxQLJhVG6A5U9eVS0/UD+w/lfOPNX8or3PFui6RS GV8UhntUxdts53VBafCRbfCJjTgjaQFNaBa/uh0M0jQv2lUQT6zhk3b+MA7uGjAQ84 JVeBoPJiFXl4WDn9r1DIHHoabSVa6grzXzzHzJHGZUpYiZ9AalH0eXlDG1cld5Q0Am VscwfZ8HNBJHFDukKoi5lckHiXPlsWDeqQZcUF7gWwOwg+ts7zXAkvDdNuPBXJibwg 7xqXhO2zHEcH6JPlQOluEZsfk1AWGPrdRvVsEIxvVV79zf85PjuzvI3j9JOQshLmWE +MyKVD14cvZ4Q== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:30 +0100 Subject: [PATCH v13 03/32] arm64/fpsimd: Configure all ZCR/SMCR bits when loading task 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: <20260720-kvm-arm64-sme-v13-3-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=7491; i=broonie@kernel.org; h=from:subject:message-id; bh=/aZpqNOmfe5bYCE+xrs9pBCTsRM6wC0+Qw9617Xjl1A=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkpaLGrwReqnj3W8sg5ftnMspkp6xhMmoVe5 UW2AxO0tmaJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZKQAKCRAk1otyXVSH 0K4eB/97mlMktazoOsAKi0NsebZMBi1vLbLL5QOJ1FNM4RrNn4A7PnH2xjfZ2HV6t+MLm4b80XJ AJ1F4s7Vqf2kBmXyidCU5I6cEpn7K2COgxO927eCxmXlmdMgbe/v9Tp7JCL7sXjy3bnrkjDTgth U9KNEDPw691mg/cMuDkNvdv0FA34e4UqVLM2g2NAa1aS0voNpngWG9rkcYwP4N5PidQH3sbLaOi olQi9fPhueWj1q/Q4T3Hnmf9/PgpXsxbQiNYuWPC9Yr/cUgQWePzKi5iSABFamcmxeN3KqzdQYB 3JgsLak8UlFor5DHKcAuajikmZ84faJjAsWSsrVjLe80aiWu X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Currently, when loading a task's SVE and/or SME state, we configure ZCR_ELx.LEN and/or SMCR_ELx.LEN with read-modify-write sequences, preserving all other bits of the registers (e.g. SMCR_ELx.{FA64,ZT0}). This relies on all the other bits already holding the expected value for the task. It would be simpler and more robust to configure all the bits without a read-modify-write sequence: - Doing so will remove the need to configure these registers during feature detection and when returning from idle, simplifying the code and removing some redundant writes to the registers. - Doing so will permit KVM to clobber other bits of the registers when no task state is bound. Along with other changes (e.g. when saving state), this will make it possible for KVM to expose a different configuration to guests (e.g. disabling ZT0 for vCPUs, even if ZT0 is exposed to userspace). While SMCR_ELx.LEN and ZCR_ELx.LEN are self synchronizing SMCR_ELx.FA64 and SMCR_ELx.EZT0 are not so we add an isb() if those have changed. This could be further optimised by considering if the SME configuration of the loaded state means we will rely on the newly configured values but for clarity this is not done here, it can be improved in future. Signed-off-by: Mark Brown --- arch/arm64/include/asm/fpsimd.h | 2 - arch/arm64/kernel/cpufeature.c | 2 - arch/arm64/kernel/fpsimd.c | 84 +++++++++++++++++++------------------= ---- 3 files changed, 38 insertions(+), 50 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index e13a85320ab6..59f3c4a9e390 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -360,8 +360,6 @@ struct arm64_cpu_capabilities; extern void cpu_enable_fpsimd(const struct arm64_cpu_capabilities *__unuse= d); extern void cpu_enable_sve(const struct arm64_cpu_capabilities *__unused); extern void cpu_enable_sme(const struct arm64_cpu_capabilities *__unused); -extern void cpu_enable_sme2(const struct arm64_cpu_capabilities *__unused); -extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused); extern void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__unused); =20 extern void fpsimd_suspend_exit(void); diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9a22df0c5120..0609dce1989e 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -2992,7 +2992,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) }, { @@ -3000,7 +2999,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 78c9d8dab545..b868db2982ee 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -277,6 +277,27 @@ void task_set_vl_onexec(struct task_struct *task, enum= vec_type type, task->thread.vl_onexec[type] =3D vl; } =20 +static unsigned long task_zcr(const struct task_struct *task) +{ + unsigned long vq =3D sve_vq_from_vl(task_get_sve_vl(task)); + unsigned long zcr =3D vq - 1; + + return zcr; +} + +static unsigned long task_smcr(const struct task_struct *task) +{ + unsigned long vq =3D sve_vq_from_vl(task_get_sme_vl(task)); + unsigned long smcr =3D vq - 1; + + if (system_supports_fa64()) + smcr |=3D SMCR_ELx_FA64; + if (system_supports_sme2()) + smcr |=3D SMCR_ELx_EZT0; + + return smcr; +} + /* * TIF_SME controls whether a task can use SME without trapping while * in userspace, when TIF_SME is set then we must have storage @@ -377,10 +398,8 @@ static void task_fpsimd_load(void) if (!thread_sm_enabled(¤t->thread)) WARN_ON_ONCE(!test_and_set_thread_flag(TIF_SVE)); =20 - if (test_thread_flag(TIF_SVE)) { - unsigned long vq =3D sve_vq_from_vl(task_get_sve_vl(current)); - sysreg_clear_set_s(SYS_ZCR_EL1, ZCR_ELx_LEN, vq - 1); - } + if (system_supports_sve()) + sysreg_cond_update_s(SYS_ZCR_EL1, task_zcr(current)); =20 restore_sve_regs =3D true; restore_ffr =3D true; @@ -402,12 +421,17 @@ 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 */ if (test_thread_flag(TIF_SME)) { - unsigned long vq =3D sve_vq_from_vl(sme_vl); - sysreg_clear_set_s(SYS_SMCR_EL1, SMCR_ELx_LEN, vq - 1); + u64 old_smcr =3D read_sysreg_s(SYS_SMCR_EL1); + u64 new_smcr =3D task_smcr(current); + + sysreg_cond_update_s(SYS_SMCR_EL1, new_smcr); + + /* FA64 and EZT0 are not self synchronising */ + old_smcr &=3D SMCR_ELx_FA64 | SMCR_ELx_EZT0; + new_smcr &=3D SMCR_ELx_FA64 | SMCR_ELx_EZT0; + if (old_smcr !=3D new_smcr) + isb(); } =20 write_sysreg_s(current->thread.svcr, SYS_SVCR); @@ -1217,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]; @@ -1283,20 +1287,10 @@ void __init sme_setup(void) =20 void fpsimd_suspend_exit(void) { - u64 smcr =3D 0; - - if (system_supports_sve()) - write_sysreg_s(0, SYS_ZCR_EL1); - - if (system_supports_sme()) { - if (system_supports_fa64()) - smcr |=3D SMCR_ELx_FA64; - if (system_supports_sme2()) - smcr |=3D SMCR_ELx_EZT0; + if (!system_supports_sme()) + return; =20 - write_sysreg_s(smcr, SYS_SMCR_EL1); - write_sysreg_s(0, SYS_SMPRI_EL1); - } + write_sysreg_s(0, SYS_SMPRI_EL1); } =20 /* @@ -1338,8 +1332,7 @@ void do_sve_acc(unsigned long esr, struct pt_regs *re= gs) * any effective streaming mode SVE state. */ if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { - unsigned long vq =3D sve_vq_from_vl(task_get_sve_vl(current)); - sysreg_clear_set_s(SYS_ZCR_EL1, ZCR_ELx_LEN, vq - 1); + sysreg_cond_update_s(SYS_ZCR_EL1, task_zcr(current)); sve_flush_live(); fpsimd_bind_task_to_cpu(); } else { @@ -1474,8 +1467,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *re= gs) WARN_ON(1); =20 if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { - unsigned long vq =3D sve_vq_from_vl(task_get_sme_vl(current)); - sysreg_clear_set_s(SYS_SMCR_EL1, SMCR_ELx_LEN, vq - 1); + sysreg_cond_update_s(SYS_SMCR_EL1, task_smcr(current)); =20 fpsimd_bind_task_to_cpu(); } else { --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 5415D37FF46; Sun, 19 Jul 2026 23:10:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502624; cv=none; b=acuRfoOOOv7XzDrSMFY9e53q/yor606OlBy2PJJ9PLkEofFZOqHqh4rAxsF213AgdHNqYh1U+nmEi2QULwthUgP6t216Dwf+9rGTHeDaRDPhQwbqdCAoeXEI0IvEiff9NP2kC1VaZ9hNvG9tivBuir1x14ginOSC8gx8sE5JW38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502624; c=relaxed/simple; bh=ee4vBGEdpju7o7htpyCkV88y2wT1UDGGt62IPZtgiFU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ncme1FS5Mutpwm9dy+SS9tMu2TTJAVz499h6zm08K7eauw/1jvY927MKN9rj1L7wJf33xfG9nyUWUM8V0BAT+Ufjc04HW9u3kRShGvSAppaJ/nFXD/Nl/sFjbKNFBbxe+v63Ns5Iqzznr1eMZpE8MGCJAModJUHPS4X4p+TW8uM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N0f57J8l; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="N0f57J8l" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 124641F000E9; Sun, 19 Jul 2026 23:10:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502615; bh=7ZxSdy74Ay4v2Qdu4MSA5Ypp/4SsT82/WB2mwBgc3ik=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=N0f57J8lqH8ZdaPRomNnI8s9v8EWpunYRvgxSafSGrad4lDc5hSR94fxzdp00OwRC TvDCUn1cQBdW1fXQ7gIUem3KyN92YS5I70ldcMzwMMltkXfA09QC78WHYdMNJ/MdTS 4eMvsI0veanGKQA6JoyKTvmcyQ8cQJ2FgfWVWRRy+GJ+kYQuOK8ggjTeeGdw/Ai8wp +VST5eGPoj0t9RnO0InBwei9nXL+2q/duyPtKksHRqVAkGNjxQNragLS4z/zrv0MDk WgxvoDVz2orvUVw8vmlFQ2PSoeKNUZWUY47lmFGXyA7LOOE7oUbjzxV2eLe78j0P52 BrjOnauAg3cZw== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:31 +0100 Subject: [PATCH v13 04/32] 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: <20260720-kvm-arm64-sme-v13-4-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=4661; i=broonie@kernel.org; h=from:subject:message-id; bh=ee4vBGEdpju7o7htpyCkV88y2wT1UDGGt62IPZtgiFU=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkq8sb8hg2ZdWlI61m0C5jJ3WZS7AQQANu4D k1GNwWE1MSJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZKgAKCRAk1otyXVSH 0G5kB/9yGIAfVt7vcNEJCJuzFdqbmHVCMQl7s9L9IfX6Nw1wzdeUDjF5z4hwWs58PB7J1PZlC4f nIET8M81PX0K6kkvvypEMLlZTqWtGGiztkDH6JYkTHupSiWFjd4hdNyMIzwQgPjAsCKup9UnNs4 wPEF9e6bcVwo8czvDiy3HSrr0rR8lUoRKk0UKleoyeF45hFiULSFEpM3Jylhn88fGXrZYWXcTT0 ViYwRE8fWfy8IcX68UDL4aGJi4faFbjqXHK7E47uJQJdaVidzyGooeY9+S8xgyeIF6J096GCEHh pGR0nFnFxcqaTDYvxL22Z9WLTf9BsWoQIprBk25Qj963SExq 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, instead of only storing the SME VL to use we store the SMCR value. This includes all the enable controls for the subfeatures along the vector length. In order to keep the code paths for the vector extensions consistent also adjust the SVE path to store a ZCR value instead of the VL, since no fields other than LEN are currently defined for ZCR this is much less of a meaningful change. Signed-off-by: Mark Brown --- arch/arm64/include/asm/fpsimd.h | 4 ++-- arch/arm64/kernel/fpsimd.c | 16 ++++++++-------- arch/arm64/kvm/fpsimd.c | 3 ++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index 59f3c4a9e390..395606e01e18 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -166,8 +166,8 @@ struct cpu_fp_state { struct arm64_sme_state *sme_state; u64 *svcr; u64 *fpmr; - unsigned int sve_vl; - unsigned int sme_vl; + u64 smcr; + u64 zcr; enum fp_type *fp_type; enum fp_type to_save; }; diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index b868db2982ee..b5535f8c9bd9 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -474,7 +474,7 @@ static void fpsimd_save_user_state(void) /* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */ bool save_sve_regs =3D false; bool save_ffr; - unsigned int vl; + unsigned int vq; =20 WARN_ON(!system_supports_fpsimd()); WARN_ON(preemptible()); @@ -498,7 +498,7 @@ static void fpsimd_save_user_state(void) last->to_save =3D=3D FP_STATE_SVE) { save_sve_regs =3D true; save_ffr =3D true; - vl =3D last->sve_vl; + vq =3D SYS_FIELD_GET(ZCR_ELx, LEN, last->zcr) + 1; } =20 if (system_supports_sme()) { @@ -508,19 +508,19 @@ static void fpsimd_save_user_state(void) =20 if (*svcr & SVCR_ZA_MASK) sme_save_state(last->sme_state, - system_supports_sme2()); + last->smcr & 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(); - vl =3D last->sme_vl; + save_ffr =3D last->smcr & SMCR_ELx_FA64; + vq =3D SYS_FIELD_GET(SMCR_ELx, LEN, last->smcr) + 1; } } =20 if (IS_ENABLED(CONFIG_ARM64_SVE) && save_sve_regs) { /* Get the configured VL from RDVL, will account for SM */ - if (WARN_ON(sve_get_vl() !=3D vl)) { + if (WARN_ON(sve_get_vl() !=3D sve_vl_from_vq(vq))) { /* * Can't save the user regs, so current would * re-enter user with corrupt state. @@ -1712,8 +1712,8 @@ static void fpsimd_bind_task_to_cpu(void) last->st =3D ¤t->thread.uw.fpsimd_state; last->sve_state =3D current->thread.sve_state; last->sme_state =3D current->thread.sme_state; - last->sve_vl =3D task_get_sve_vl(current); - last->sme_vl =3D task_get_sme_vl(current); + last->zcr =3D task_zcr(current); + last->smcr =3D task_smcr(current); last->svcr =3D ¤t->thread.svcr; last->fpmr =3D ¤t->thread.uw.fpmr; last->fp_type =3D ¤t->thread.fp_type; diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 3f6b1e29cd6b..567dd43970c5 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -89,7 +89,8 @@ 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.zcr =3D vcpu_sve_max_vq(vcpu) - 1; + fp_state.smcr =3D 0; 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); --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 9BC9A37F8BD; Sun, 19 Jul 2026 23:10:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502620; cv=none; b=g9HNxonpV+XERVGzket+MRjSMNSYPmuV40b3L6O47hPcNjZj2DINmZ1PGmu4xy68tEOFKMhljzkeQ1qRNGgcaj5257HWbQUBgUFgJLzF+Fw4ybMZJ2oLxRoZ0lzdEgm5ph50sgrJDZPoFSD1nf9kD2xbp2nb6fKhdUl7ZV48Gt8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502620; c=relaxed/simple; bh=+zyEiRn4TZGrkp1zrM7y7JLFFhEzfJlzJup4jyLspPk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZiI5mfLL3wdwDju2shHH+DCkhECiSsoYrzDyiUUvcGN1LTWkM3B1v6Znud2hGkzVatLpZhr85VIgXu+yKLMlB6B+jDiXedLBf50DnnH0pUt+Qdj48L2Rq9WoY0vUCT4sZnyxtjEmNm3MoPjv1Si0jxq1IfNUI1WgiA8uVA3U0iA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RZcn60qK; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RZcn60qK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 603871F00A3A; Sun, 19 Jul 2026 23:10:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502619; bh=NedY6/OlzwTYxAtSditYiHpWbPSndrvxVk87IdXM00s=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=RZcn60qKqWUeqexSTmP40SRqFeZ6/8h5A5I+G7j7pYzDaIpVHshhnROKKVo/smlvg jlkNEXHhbvXUFKTZopUg49/sSYprnU/zD9LQj5tUe4JFTGwa51LSMVy2pDtWk5oJOl 8E9JsYyS86bQstmy2rhi/FAuhrTZlsgDO0T7D5SLGB3QH1MjXfJuQUnQrozY73SzBP RdB4VqeSEbTyYsDP/1Gn8T11kC1Qn/DeuRBPjYdbF4bna+JT3fWXLG50aCGmrueeKp 9e3/UZV68YYzZnAsDZM7SSYElQs+nkwkUlHBRoLhipUF6LosTds/xUMhHLyIaXLWh3 U7C84ZffO0DkQ== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:32 +0100 Subject: [PATCH v13 05/32] arm64/sve: Factor virtualizable VL discovery out of SVE specific code 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: <20260720-kvm-arm64-sme-v13-5-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=2856; i=broonie@kernel.org; h=from:subject:message-id; bh=+zyEiRn4TZGrkp1zrM7y7JLFFhEzfJlzJup4jyLspPk=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkrxveMIWtmYorGSKcx5B2y2hXm1FuAf3p3s oVBySvNN6mJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZKwAKCRAk1otyXVSH 0IZNB/941fd8pdEduv+KVtwJ7DqG2jArwAHyIGwrXJWnObUMpcQ+JLh79PcqhiF/4AcFRIImaTx 75IMeQ0/QbL2kS1Ra/C7cQ9cQjcOVJawH89iPJqn20jDmC7wZWxBuKJ7MsEiywgGUkxuYiOsv7Z jKF5csamwIm8qH4RucIXoUi/86nzr2lcn9UKfaE234U4tFWHMvUa9yOdlrFyHDt+zmx7+HIrZ8C ypP952b5GpwJamyFu8/a/mjvCPVaSiB6feL2GsY2EzjEWxjJt6SHMVwtrg4yNbt7FZjgpTIaKYs oTgH8LvIqr8naveNhHpL5kmDkhxMYHLrruG/ZSfo3148m59y X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB In preparation for reuising it for SME pull the code for discovering the maximum virtualizable vector length out of sve_setup() into a separate function, updating to return 0 without a WARN_ON() for the case where no virtualisable VL exists. For SVE this case is architecturally invalid but for SME it is valid if ill advised. Signed-off-by: Mark Brown --- arch/arm64/kernel/fpsimd.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index b5535f8c9bd9..314f5d61be11 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1118,6 +1118,29 @@ int vec_verify_vq_map(enum vec_type type) return 0; } =20 +static int __init vec_virtualisable_vl(struct vl_info *info) +{ + DECLARE_BITMAP(partial_only_map, SVE_VQ_MAX); + unsigned long b_min_partial, b_max_virt; + + bitmap_andnot(partial_only_map, info->vq_partial_map, info->vq_map, + SVE_VQ_MAX); + b_min_partial =3D find_last_bit(partial_only_map, SVE_VQ_MAX); + + /* All implemented VLs are virtualisable */ + if (b_min_partial >=3D SVE_VQ_MAX) + return info->max_vl; + + b_max_virt =3D find_next_bit(info->vq_map, SVE_VQ_MAX, b_min_partial); + + /* No implemented VLs are virtualisable */ + if (b_max_virt >=3D SVE_VQ_MAX) + return 0; + + /* At least one virtualisable VL exists */ + return sve_vl_from_vq(__bit_to_vq(b_max_virt)); +} + void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p) { write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1); @@ -1129,8 +1152,6 @@ void cpu_enable_sve(const struct arm64_cpu_capabiliti= es *__always_unused p) void __init sve_setup(void) { struct vl_info *info =3D &vl_info[ARM64_VEC_SVE]; - DECLARE_BITMAP(tmp_map, SVE_VQ_MAX); - unsigned long b; int max_bit; =20 if (!system_supports_sve()) @@ -1153,21 +1174,7 @@ void __init sve_setup(void) */ set_sve_default_vl(find_supported_vector_length(ARM64_VEC_SVE, 64)); =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) - /* No non-virtualisable VLs found */ - info->max_virtualisable_vl =3D SVE_VQ_MAX; - else if (WARN_ON(b =3D=3D SVE_VQ_MAX - 1)) - /* No virtualisable VLs? This is architecturally forbidden. */ - info->max_virtualisable_vl =3D SVE_VQ_MIN; - else /* b + 1 < SVE_VQ_MAX */ - 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; + info->max_virtualisable_vl =3D vec_virtualisable_vl(info); =20 pr_info("%s: maximum available vector length %u bytes per vector\n", info->name, info->max_vl); --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 060A637F8C1; Sun, 19 Jul 2026 23:10:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502627; cv=none; b=KydQlwTHa+DY7ZqiIGBX4zTWR8wy0Mui1Fm4330RWRTHXWzjKiytsSPDYUC75QNZrEdZ54MSUS795Ho+WwAuZzpbtJDKNOGxOAwkRe2OmCb0JSEdv3hxkNeZSK/11fnwdTI0N+7WGMR8hydxqz6z8Dia2xZn2VoEh44e+9LPHgA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502627; c=relaxed/simple; bh=vCPRPRr90nIU5ipka6gLN1cgvgNbXJf93goO/9YP1u8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rgXKj4Pw+e4MuTRFvcb8Q3zPBw8CPXA18bp6CBGKDEI6+7RqlbDm/Z7UJowzmPiS27ddO8QwiVd9/JPoSOJDFOox3c+OvOe/jt26PwKJc7r5yP1sOgCSzY5rWijtd3HlSkKik4V52OZFmo8CLibUUlgs82Y2TI0LnMMV4XXMnno= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UxtE5rYS; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UxtE5rYS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD68A1F00A3D; Sun, 19 Jul 2026 23:10:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502623; bh=85yZYCsmLUumgp2Ut8btqefYFUysunePTPypRChJllc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=UxtE5rYSJV7kiDY13Ngck1Han+RSfZGFH1OYfi7uOYOm7cGjAhna7ozNYUvGJdHVN rWaay2ePSw2wh33cEgMfdjLX2Owic3mlYQIUuufoACIfprxzOYW45BT2wjvVJ+gDAW Sns5+GfEmISgG7qTo+VAeXzIjaoJxOiSjaQ9OsImv6r1QI33xOGegutJTT07+wQHmV 7TcPjAQHB5FlxGWZV0hgisVN4wKEb3RujRJAE+/azag+o4+QbxekEc3ipLyz3vI8S+ Eb3ZL8ew8tx1DMpbIwzXtNClGqQl9rcdTNKn9W+HVpVNbh8bNQgon1eCqrmUfjioKM +qTFYl53FZvqQ== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:33 +0100 Subject: [PATCH v13 06/32] 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: <20260720-kvm-arm64-sme-v13-6-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1384; i=broonie@kernel.org; h=from:subject:message-id; bh=vCPRPRr90nIU5ipka6gLN1cgvgNbXJf93goO/9YP1u8=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVks/jmqhVMG8IO8nHz8qNNomFhkac2J8q7Ak s3NYvOuL8qJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZLAAKCRAk1otyXVSH 0LQIB/4/MNP+lcZla/p9yTUwxLsmBOqBakpA6WR2OAQmiT84K7TTqUwb46t+8XDWAKGFRCJiPif DptEpOaM4959PUGj/Xub784vEnIcgQvoMd3svgwB9oRrmxsn4Q6QbzZt9+mciYmQXdmACNtmUWC 6DESysGrpyfchvENqdPNXouDccvPc0I/A7t5zAumyumZni6ErlkiTM931eaqA2fI5YXxAtwG4l7 FlYcZkgdOOu4CBQinmxRkaHxXt2aZHvipZeiJdRAXxGGdTNR/H38kwLM5OkpROJJFMJqUx8HUlx /Fny0364G1vIaHTu9IrUBPH0HE12KdQklQ0vslAIR3uEFnqs 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 0. Signed-off-by: Mark Brown --- arch/arm64/kernel/fpsimd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 314f5d61be11..7f2c44bd9fd5 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -1281,6 +1281,7 @@ void __init sme_setup(void) * minimum available VL will be used. */ set_sme_default_vl(find_supported_vector_length(ARM64_VEC_SME, 32)); + info->max_virtualisable_vl =3D vec_virtualisable_vl(info); =20 pr_info("SME: minimum available vector length %u bytes per vector\n", info->min_vl); @@ -1288,6 +1289,10 @@ void __init sme_setup(void) 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 #endif /* CONFIG_ARM64_SME */ --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 144B33803DA; Sun, 19 Jul 2026 23:10:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502629; cv=none; b=X+OuTOOSU8OGEaTl7IaLSh0prMsiYN60oM3rcyOKeYj/0kW6GXi5H6poYtCXhRU5xyfqbd6r2GJ6J+R8gFIt+Q3wKVULe2zskuaIopDg22sHQZnhHv/3OD2N2Xb8Iq2gbqpAhov30YbNzZiqr2VFKA9nWthZBujUugx+mK2sbYI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502629; c=relaxed/simple; bh=LQ82hLeixhPo51PUrjrzXUzX6f0ySuwDN5dUrbNo3NM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qph7JRHSzZXwAAmHqgLLX/Xmy1zG7TVTN7rdp04fzoM7ukmMlwpx9gPy9DC1okm4JSyt9hc1jr9m3YM0mV9xRKs7cDaHMnHlx+zHtT/nJ6AWkvxmjaRLq0CKFW194IzY3yESOPXlxZFLLqtByTHCyMzlGn/j93zBagDdulmTpfE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lo+44WdH; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lo+44WdH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06F111F00A3E; Sun, 19 Jul 2026 23:10:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502627; bh=kHHDIsQbOpwZi830OTqOQ3hDBLn1pO6beb+B2zMHong=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=lo+44WdHWR5FaVr2MBCA2Oi12puRxO33IEUwiiwkesDFzeJfFzlmbpsGDUGo9pfO7 alscwjcwFtUfcrjoOeTXvNfrIeKqYMZNofGvqAqzXVnH+5ygn9gfeMqrcSENMmyPKJ BqalFy7DICoPecWYv4c7YbA1r3fjK+fTqaCszo4SNy0ZIzr4xj28mRcskaqPTUocS5 h25SS9MFv+Hrr6v5/NRTeNIYBxiyJ97Yg6RCaNuqKE1KNsCFqtY9viO4HRTCeSTUYK YAQGRm1pvqmL3ZM8ZbEol+nyjQEJVm4GaKr3HfjXaLwXhuA4jYGA0wJ3z4xJHYhsJX GyLJHjDwh85DA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:34 +0100 Subject: [PATCH v13 07/32] KVM: arm64: Remove bitrotted comment on handle_sve() 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: <20260720-kvm-arm64-sme-v13-7-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=842; i=broonie@kernel.org; h=from:subject:message-id; bh=LQ82hLeixhPo51PUrjrzXUzX6f0ySuwDN5dUrbNo3NM=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVksEu2TfVUeiwJxJfegVrA3okXWKBKbLNFG6 7+06mW1CBWJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZLAAKCRAk1otyXVSH 0AtOB/4nD3lNzZzEhkQxDTqe121DOffEM7mPd0/E/XOXQUbMwYpopWzhfFY3H9+GRkIARvq2Z4q kXFMMb6Gttx+24ZE3LaswzpFPQCevP85rdp2rPR+Iztfb44hzeYKNvGm5loa82w8778+AiNKzfX dLGZdPeRKpbqdZu7NWhWSJ9UyNx1mKmdbDhIDeKYpbTc4TVe0R0qVB/pcuc8pDvsinuhjrk0qj7 Agd+KsKJthnwRIzFG3mFkZrFYNduL1YTD8VgksqPTTRXdT1KAhusF163mjw9XFJuJezdBcdNFhf huZn5D47QZhk0jCoUoWdg8vOhb70Ml8GoDxwSozEGwdCKpD6 X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB The comment for handle_sve() says that we only call it if the guest does not support SVE but it is now also used for nested guests which have enabled traps at EL2. Just remove the comment. Signed-off-by: Mark Brown --- arch/arm64/kvm/handle_exit.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 54aedf93c78b..f674cd25d894 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -224,10 +224,6 @@ static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu) return 1; } =20 -/* - * Guest access to SVE registers should be routed to this handler only - * when the system doesn't support SVE. - */ static int handle_sve(struct kvm_vcpu *vcpu) { if (guest_hyp_sve_traps_enabled(vcpu)) --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 881643806AD; Sun, 19 Jul 2026 23:10:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502633; cv=none; b=DCmykrZxmdgV1lR2zA6FO6kUdAe5fhktZrtifLogDL42WZg13tLiU0Nn4Zyxt0uTx6nEZqRNIuK8Ex9jgyUQ5EpxW+pPw4RGtdTrlAWVcOmbFG07gdS5PciFnVubIv4DajTO8TzfXjFwQ36sPkF+J4NrnH3fCJyv1CFX+wu3zFY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502633; c=relaxed/simple; bh=u65dLobDDTfZ3Plqj3qN97beHdtUOk+/y5QgneNdn5w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fIMn+728lyCxGnv4RT1bysJXuiIod5FriQCNKfLXMtlaTl+jy1fSvgzFpaRQPJNgvUBLzZ4CM2FTRRu8jU0KRdD0FgQJrDUlRp1zRW6iZE08OG8lqfnUk6GTwBBRvjJm0UvaBBeX2bG2YRl0mMnYW9ebgPn7lTwAu6toMuxxsuE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hdXyEEzJ; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hdXyEEzJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 571431F000E9; Sun, 19 Jul 2026 23:10:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502632; bh=Ng0eoSfPdDRfiXjYHgTRJSjiJJN1g/dJiDj1pJZB0R0=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=hdXyEEzJRFbgjLtyC/lq1G4FbKuRVlOSgHD0q1QQoQ/gIAgy7tMtKLTxhgwiSITF9 Ko5UhCDHeBmrIf0dAdHF1wbnPOuEVSxyz52sXHzeNpkwiWkNbe45/IoOu1U9+I6N7R I+6QJDcoycnIl2afhe7OS4Yw4D1JNqvnN5CpJQHPc8U4iQLtBnV6F3lfe4anmposdf M9OvDCFNRVjAWzdUcDrgfyAuS1CHuP6pn+svPuoVZ8bYQMhkyUdZLF25ywGCk8E9mj SQMhw1joyq7iZnq2vAkSO8U0+YOobAlXnCcESOlhakIKoFEUmZ58uXlFRGPWVsJZAR kSUxfB+53qHKQ== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:35 +0100 Subject: [PATCH v13 08/32] KVM: arm64: Handle FEAT_IDST for guest accesses to hidden 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: <20260720-kvm-arm64-sme-v13-8-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3302; i=broonie@kernel.org; h=from:subject:message-id; bh=u65dLobDDTfZ3Plqj3qN97beHdtUOk+/y5QgneNdn5w=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVktAsIYP374sv1xm9qZtN9am1d8QeKvklDxA UIjA3x2+huJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZLQAKCRAk1otyXVSH 0HRVB/4u8LqyVRGfm1HCUwUlndcEylq/XCAG1KSUHIsmDxlV/k7cGXPEAFE7xIU4k3gCnmjmpci YgJjYWjtJbMmaIt+0dNFLhzomj8pGk18eNILi0jpr5TleZdX/tUg9DWlPjUXAGjSSojFqdN1eR5 4iKoesXM3npTTKZBtnLKdvcvYYmrLSgZB5EbPSE9c11P8QoesDUuumRRGlPEVFdS1kJY7+QITC9 X7HqCBbHPdjH5MX1LbUiQINNM4LnVvbhYKaSTq7H9FXmnXjUQO2YrpKtwdVsz+D/T/wsWdQIjOQ 6TgjtBeRfsQY+HIzELsouDRQddytVajvf8esv2zLXWGfC7ib X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB In preparation for adding support for SMIDR_EL1 which is only available in systems with SME factor out the FEAT_IDST injection from emulate-nested.c into a helper and use it when handling hidden ID registers, ensuring that we provide FEAT_IDST behaviour for them. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_emulate.h | 1 + arch/arm64/kvm/emulate-nested.c | 6 +----- arch/arm64/kvm/inject_fault.c | 15 +++++++++++++++ arch/arm64/kvm/sys_regs.c | 6 +++++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/= kvm_emulate.h index 5bf3d7e1d92c..994afbf479fc 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -45,6 +45,7 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu); void kvm_skip_instr32(struct kvm_vcpu *vcpu); =20 void kvm_inject_undefined(struct kvm_vcpu *vcpu); +void kvm_inject_undefined_idreg(struct kvm_vcpu *vcpu); void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr); int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr); int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr); diff --git a/arch/arm64/kvm/emulate-nested.c b/arch/arm64/kvm/emulate-neste= d.c index e688bc5139c1..f49b7b311d09 100644 --- a/arch/arm64/kvm/emulate-nested.c +++ b/arch/arm64/kvm/emulate-nested.c @@ -2669,11 +2669,7 @@ bool triage_sysreg_trap(struct kvm_vcpu *vcpu, int *= sr_index) * helper for the purpose of dealing with FEAT_IDST. */ if (in_feat_id_space(¶ms)) { - if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, IMP)) - kvm_inject_sync(vcpu, kvm_vcpu_get_esr(vcpu)); - else - kvm_inject_undefined(vcpu); - + kvm_inject_undefined_idreg(vcpu); return true; } =20 diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index 89982bd3345f..e2f519ca3045 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -331,6 +331,21 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) inject_undef64(vcpu); } =20 +/** + * kvm_inject_undefined_idreg - emulate UnimplementedIDRegister() pseudoco= de + * @vcpu: The vCPU in which to inject the exception + * + * It is assumed that this code is called from the VCPU thread and that the + * VCPU therefore is not currently executing guest code. + */ +void kvm_inject_undefined_idreg(struct kvm_vcpu *vcpu) +{ + if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR2_EL1, IDS, IMP)) + kvm_inject_sync(vcpu, kvm_vcpu_get_esr(vcpu)); + else + kvm_inject_undefined(vcpu); +} + static bool serror_is_masked(struct kvm_vcpu *vcpu) { return (*vcpu_cpsr(vcpu) & PSR_A_BIT) && !effective_sctlr2_nmea(vcpu); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 5d5c579d4579..b352cd323e30 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -4759,7 +4759,11 @@ static void perform_access(struct kvm_vcpu *vcpu, =20 /* Check for regs disabled by runtime config */ if (sysreg_hidden(vcpu, r)) { - kvm_inject_undefined(vcpu); + if (in_feat_id_space(params)) { + kvm_inject_undefined_idreg(vcpu); + } else { + kvm_inject_undefined(vcpu); + } return; } =20 --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 95E833803C8; Sun, 19 Jul 2026 23:10:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502640; cv=none; b=YFT1L8132ipWKUi95eO5Ksh84SlXbU1F6DjWaUGEr+HnZmnvPFdfw6uLKcHQo4B1hC0QK5WlLRAldstT5wIKxhlh4Ck/I970uj0jIDfZRoJjItCHkj3YwlRCdNGkmfR3bxkxzBpQiwKKUUTfwSUUvkjeLnLfYUePcfFGc6NRLR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502640; c=relaxed/simple; bh=1qAIu+pXeO/t0Rjmal4q8j7FSwr2awFBos2cAAJK0lg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oNT332WKxnFLs7Dx3iEisdF79jhWU6EY1SzhF1wrs6Esb1qBCEWgg51nzZgc0p6Tncc7krV9C/rchZN8TDR4MNfPCIQD+vao6iMXHtLhs+oB8wpJRpJXmvCE1utCd3Hzl932gXGVonrmDzlHIW5y0i8p41BgKrqare77cjw274E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lKZST2U7; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lKZST2U7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A42441F00A3A; Sun, 19 Jul 2026 23:10:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502636; bh=+YU88ZRUFkvSVuCkK74k+hG8HaktkRVNfkNeUzR+i14=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=lKZST2U7ubjF94vzjCLR7/tBNZHKWq/SqHHaeYDDFUgkJRTsm/NYPp1dN28Grf1zc ezK3qcf4oUDbMhB58cHm3ldJGm0lU0htcVBcvOit1dcOqGuY82vy9kePDBfQa+K934 QTvvnwrFe77Xd/sSbjtQmBs8BDG0ZJCAOiKNCpW0OsJEZKUaQifOXxDa6e0UG8RwU+ eo7D+AaFTnwz9JpcCsWjrMBRgU8L25wEK8kqY4ZZuzzCtPd1U4CMDwcbyykhhXnVPt TWJaEZj0NUzizt9RGJSJz7JiHRrVKz+M1wFuEBOtB0fC4n5JNIvuesw8L06i+sgsqt zVopxsQUaJK8g== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:36 +0100 Subject: [PATCH v13 09/32] 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: <20260720-kvm-arm64-sme-v13-9-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=4004; i=broonie@kernel.org; h=from:subject:message-id; bh=1qAIu+pXeO/t0Rjmal4q8j7FSwr2awFBos2cAAJK0lg=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkuuB2WFjp/yCHTYWLJwZ//ZY+ziiL++zNgW 7XZWKWf06iJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZLgAKCRAk1otyXVSH 0IOAB/9zm0mTMrpACLfYQpRp5JTRK32UJLPDANkxqiujJAMEA2cYcOIiCgWaIDyKrlbL4JHlx/u lzEHf8UVQaXur8zc9E2qtt1ZJRLIGz6K+wGp+A0s7OVC3USUcnBgvYuedaWSFSabNL/sc9R+wwB NnKmKXctmfhytkAl+fKtrs/01ruaaYRZqrVbNfNTybysrw0gdiRT9mfZD7rVeXcPOJ9scdp2FTH ir/6Ss2e8oBTBQyrpK2YM8dC+340heBL/7UDYXKBbjWaJTC9RQFANscflSgZl+XbXbbhMqFVkIL oxHg5yvNLBElRbkKSaCmMQcmOYBs8zMO9fYbBPBqb2GnIMjG 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. Reviewed-by: Fuad Tabba Reviewed-by: Jean-Philippe Brucker 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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 44B8F380FFF; Sun, 19 Jul 2026 23:10:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502642; cv=none; b=PvSdvbd8SzGw08LurGRKgKc5ltucp0cf1S83BYM23Vbc5hnkyb9cWZfqpNtTOKzBByZcyk9Nxw/u4EBqZdLzgtW69bXmL/j+pzmZU8nudlHxymcIoiVFWrk4HMI2fzCibomJGUcKXe3ezk/FKf9PLIGHMe/O5KNVc1IRx2CyhkM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502642; c=relaxed/simple; bh=z7S7gabtTQubvf1C5BhMhuZ4burPUnffHou5hS57R50=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=i6+EqtN4mcBwmq/1k601Nzu5jI4n8W6ZQZ5RZV+rPgP89RQ5m2G6qnevpWV6KiUueZ2U85qhkzZovjnxNgnEH7kvK3L0PNQN9bwEvYKSy6v1MaThoMOBQopNVo3LFHctd25+hDolfEaO8eD+Gm/vNIn7uevvLWBRN9fDIXOwNBI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PrrORKpb; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PrrORKpb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EFC0D1F000E9; Sun, 19 Jul 2026 23:10:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502640; bh=I4xrVSbCp5yAA6Gucb4v+xBsvRi+5+69PJv2auOuOQs=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=PrrORKpbNCWlbjDLQM5rtzLD14bkwDFh9Hg6fcX8hLkkpn6yYM1D3nYeFZUOikNDx Tfv8RL/6fcdY+kSRLkfJUFQ9rYsa/MzxfWLXLcpPumbK2InF1C4/Yuq4MXddxP8dmz QUe9wI4J6WjRhITUc5GV6QAPGDM9OZxcaU78SSY7ffnuABPEINKC3QmpsX1ekUbaIC v6QqXNW6ip/eq2dlfVnb2VWCp32PgBXRYl7IwNXWwQHCBg1na6d+P2YseGojugJoZ1 9kCMXdR0lZprDFzXhElReoXOCA7A6OWJX3/Rkuvu50b4AKnMqjR6YWBrxbarTO02aa LQhQxw7GgTkGg== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:37 +0100 Subject: [PATCH v13 10/32] 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: <20260720-kvm-arm64-sme-v13-10-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=7699; i=broonie@kernel.org; h=from:subject:message-id; bh=z7S7gabtTQubvf1C5BhMhuZ4burPUnffHou5hS57R50=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkv8SEy05TyU0xo0oHhfgzHjlvMV2Zv0DG1v elZwqqIUpSJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZLwAKCRAk1otyXVSH 0IdqB/9l++1aCYkyNdIdzjHJsKTRqv7As0cb+9gpA7uanfxfs2JU7i9xhKjAAB900UFm7SyIHWl zRnRXlN2Tu5GQybCdzCvj/d475t6ZN2f+JXUXZpesVXkpbieMMsLObYI/QRV3fDmsD9CgCM4rAI t66DApI6H/ZzT/WN3E/FwssOf4t3Vv/LRMY4Krmk8rHnxdtQICRdg5mHHSzrP3QC3drN1Cr6Q0j RsLv2tHGihtBTtnIJEn9CZVAC95s6IXBQY/qwjwH710qe0MYHLerlGu9rLP4attuNgcALHXhgBb 0oRpkTxh4vtYxit3Me7/aBQ/1XsKrpAdGjmGIKfZ3saMYltN 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. Reviewed-by: Fuad Tabba Reviewed-by: Jean-Philippe Brucker 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 | 12 ++++++------ arch/arm64/kvm/hyp/nvhe/pkvm.c | 2 +- arch/arm64/kvm/reset.c | 20 ++++++++++---------- 5 files changed, 28 insertions(+), 20 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index bae2c4f92ef5..8b746b1a1e53 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1037,8 +1037,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 @@ -1133,6 +1133,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) || \ @@ -1505,7 +1507,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 1c13bfa2d38a..83af99ca4e1b 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 b01d6622b872..0b789f73bf7c 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)) @@ -374,7 +374,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const str= uct kvm_one_reg *reg) if (max_vq < SVE_VQ_MIN) return -EINVAL; =20 - /* vcpu->arch.sve_state will be alloc'd by kvm_vcpu_finalize_sve() */ + /* vcpu->arch.sve_state will be alloc'd by kvm_vcpu_finalize_vec() */ vcpu->arch.sve_max_vl =3D sve_vl_from_vq(max_vq); =20 return 0; @@ -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, (void *)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((void *)vcpu->arch.sve_state + region.koffset, uptr, @@ -599,7 +599,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 */ @@ -617,7 +617,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 3b2c4fbc34d8..9d7f632f01f8 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -454,7 +454,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 b963fd975aac..0fae62a9eaef 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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 4CDB5381B1A; Sun, 19 Jul 2026 23:10:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502646; cv=none; b=rC3/48cp580hRwzVSGHMPyHJlutkgSP7+OrqPQxwKWxcdOCoLOwsFhOkGX3mSB/Z1DdCJIPr3GmCxJy28G+BU1ApVVErlH5i6IafzJXL7buZEG8eYoqm+nHgwRmiK2iP/Pq5Sx6xPpp1tNBCW7vOmulTpmwV7ZXy0mGAAqX0Bmc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502646; c=relaxed/simple; bh=01MOCCSmzfiDMZ4P33yBk6+tJ6PaDO0mQnR5AsHR3Mw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UZ74M/C+MoX/fb1E5bgCGg1OoY+bklMT5UyAt7u9nGkdKATZiDvHtAJGoqHlkXHyJ48jOqRsGH0N8qUq0p1WhAfVdOtfj75CfwumXOJd4ILeYt5hFStktGBelCKvr0k/kK9LDnjnMBP/bMzVn7obed23wfQsqLBapDFO3hwu8pA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IfHDFrQB; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IfHDFrQB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4C3981F00A3A; Sun, 19 Jul 2026 23:10:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502645; bh=LBGo8J9fHQYp9Dr1R4CvmQH4U2pyd2XsXoly5P/hfh8=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=IfHDFrQBLNpytDktGMnouQN8B1XFyV+D+AvTPpuL1AknmQ/Ci1yEQf1yxgPxOo8iz vXHeUEmy4NqNAdmCtDEJ6i5q+mIYqK1+7QZoKXzhKIHpO91nWWDeaLWk2Yo+DIywlb w6G8tcwYa1h7nmeLeMvVMZzXO6ii057LkC9cbI7yx2VGqaKh8sFkii9zrHGea/SY8d bNiBpcXbzTpnf+iO1mh5tTEjlW5+Klud2QuT5Kxb75I+wiq5/Orq7pYZ6gyaau72Rj 6wP320xoiZdrgQHOSSgNW9gL4HlbP+3d53WxyKuhnb+ibM+o/VNRvvqCQAe+s/+A7r tEHikMQoNUQzg== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:38 +0100 Subject: [PATCH v13 11/32] KVM: arm64: Remove special case for FP state loading from ZCR_EL2 traps 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: <20260720-kvm-arm64-sme-v13-11-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3261; i=broonie@kernel.org; h=from:subject:message-id; bh=01MOCCSmzfiDMZ4P33yBk6+tJ6PaDO0mQnR5AsHR3Mw=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkwVVmjUITqV+2fMkyW3FbqdCcZlHZbvTxH/ gMFed0EwvOJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZMAAKCRAk1otyXVSH 0AdyB/9fjpYwqxCrDAwM14AF8+P6b1/+CNObcTxTKwn07ZLl68QIk+6o8eGvdh28nPIRGmww+cb MKbQJkFS2P0ga0f4v5qX1YOlMCFRt6ZU9V6rKkUQGWMYVBN89ZHzKXTIpX1js7zTq9xrs0zOLWs NEVXnyOozKzghDsdLaf8xjBadaHoGzqUb9LchV/86GGjxdOdajY66xxJNDJYpyGYhcltjH8Rme1 e3F/mUAELIwvDhwbdnfCCVay5O7zdEvIkrtj0gyt4KHHPS+SatqTxwm923tnYblATk94CY19ZEv ri+md7EkG78lofrPA6FDRP3Uio3mKUim4JgvSpqXGr607oI0 X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB As part of adding the nested virtualisation support commit 0cfc85b8f5cf3 ("KVM: arm64: nv: Load guest FP state for ZCR_EL2 trap") added code which handles access to ZCR_EL2 from a guest as a SVE access trap. While the reasoning for this was not specifically articulated in the commit log it was part of the lazy switching mechanism that we used to have for ZCR_ELx. Since commit 59419f10045bc ("KVM: arm64: Eagerly switch ZCR_EL{1,2}") this mechanism has been removed. We now switch ZCR_EL2 in the hypervisor when transitioning between guest and host, meaning that we no longer need the special casing. Remove the redundant special casing, this simplifies the code and will make the implementation of SME support (which architecturally follows a similar pattern to SVE) easier. Accesses to ZCR_EL2 from a nested EL2 will use the standard system register access handling path which works with the in memory copy, and if the FP state is not yet loaded any floating point operations will cause an access trap which we handle by loading the state. Signed-off-by: Mark Brown --- arch/arm64/kvm/hyp/include/hyp/switch.h | 4 ---- arch/arm64/kvm/hyp/vhe/switch.c | 27 --------------------------- 2 files changed, 31 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/i= nclude/hyp/switch.h index 18131e395e24..b4680baffc6e 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -601,10 +601,6 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vc= pu *vcpu, u64 *exit_code) if (guest_hyp_fpsimd_traps_enabled(vcpu)) return false; break; - case ESR_ELx_EC_SYS64: - if (WARN_ON_ONCE(!is_hyp_ctxt(vcpu))) - return false; - fallthrough; case ESR_ELx_EC_SVE: if (!sve_guest) return false; diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switc= h.c index bbe9cebd3d9d..625fe81a20b1 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -458,30 +458,6 @@ 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) -{ - u32 sysreg =3D esr_sys64_to_sysreg(kvm_vcpu_get_esr(vcpu)); - - if (!vcpu_has_nv(vcpu)) - return false; - - if (sysreg !=3D SYS_ZCR_EL2) - return false; - - if (guest_owns_fp_regs()) - return false; - - /* - * 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. - * - * Load the guest's FP context and unconditionally forward to the - * slow path for handling (i.e. return false). - */ - kvm_hyp_handle_fpsimd(vcpu, exit_code); - return false; -} - static bool kvm_hyp_handle_sysreg_vhe(struct kvm_vcpu *vcpu, u64 *exit_cod= e) { if (kvm_hyp_handle_tlbi_el2(vcpu, exit_code)) @@ -493,9 +469,6 @@ 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)) - return true; - return kvm_hyp_handle_sysreg(vcpu, exit_code); } =20 --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 D9D803803F7; Sun, 19 Jul 2026 23:10:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502651; cv=none; b=adWf5npkMRNehFSn7OLteNZ363ed9zyTShbnsaRDkcIwuAakx56iovKtE+1gRx+EjuWbgmAz6E8fc++Z1jPXhD0Dw5zLkjfVNR7Qexz9liJuxyqOkiPdvqcoAIBuLvVfb/TgMeMEMZ4GO7t0tyP/3/sXD3a8Ryo2ihqToX2N+SQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502651; c=relaxed/simple; bh=sk5UV4D8nxCJMJ3xILivF4E7O/FkNOR/tMjqIGqB6Y0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CtAzmbU4V6RD7vaKiRlazBBckTO0gwh1/96H4ynaCvTDXuC6xk+90LJW2ldGfpp+blxZlUMlsO1avmpzP1SxheRJoivVrjZoiesmAONiKZeIzTodVSjsgxn2BGpkMeUR46mJV1tCvBPltZKmtfHL9e1UEw8QjFQsv0lWp33tsLc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j7YH/ZeC; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="j7YH/ZeC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 98D321F000E9; Sun, 19 Jul 2026 23:10:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502649; bh=/D7A+/K09S6yFl/i+7JwiO/DHtiAAbsIdjqdAGJ7jGk=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=j7YH/ZeCcuUssPiRCEZVbO2hN8Ozd1nuiqVP2Q2dcGXfjTdSGryXl+fM2naIdrOCE zA0ykelNAn1oRgI+6Egoyh0pq/l6avq5UeVdAE5QTIHEcOlZcU8GpFD7PHcAi30CcD tRwF+RXGTzkfv2BOQy62rKHPxb0s5ujjXdZF1H9lU5oM0EkpGCH9dinLCmgQCLMzxj KIm6n1zvu1ztdBdKWf10yII3J5vBS6qY1UJrjN7I/hiCzyK2AF5PYp0geizz7+pmn3 6x5+Tgkh+iZYbyXD3jMvHsWQE2CIKKgGH4+dnc55Fjg12FmoiD3x3mXbXlm6o7sUnU 1pSKgcvr3UC4A== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:39 +0100 Subject: [PATCH v13 12/32] 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: <20260720-kvm-arm64-sme-v13-12-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3307; i=broonie@kernel.org; h=from:subject:message-id; bh=sk5UV4D8nxCJMJ3xILivF4E7O/FkNOR/tMjqIGqB6Y0=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkwTNOtFEXfazfu6PadtIzIGZDK6qlXVMYcs vpCNxtkJhqJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZMAAKCRAk1otyXVSH 0M9OB/0WkbYRiGnVCTEg8Nb8HLWnAa5UZu1OMM4e9pqP+1mMFRKuUdPlHivFhOAVBChGyZtGP3o GLObsc9YKmZ8Y7hlgTiiieWM9UKVsNLYDFrmSdeWeLsg3OTL4uolCGQT10UXGZ0ssSSXTyG3vL7 Minw6VWRRJbsSH6XPkk2AGCBTunD5aYQStQAmdKANHxnjg+uatH6Dwspf5W7FQ6jX4gIbTry6Ya WtnJw9DPRzuPydn2qOvsMIAQJpUaAm/YgOjzRrwevVWpp/WyS/AWt1Cg9LW4+XDX6vQYvsu8O5e 0hdJnvl271uo+mhfQLt86L0lcRqXLAZOeK//YnmEvRkXd8/2 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 its 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. Reviewed-by: Fuad Tabba 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 8b746b1a1e53..8e185e43fbff 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -367,6 +367,8 @@ struct kvm_arch { #define KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS 10 /* Unhandled SEAs are taken to userspace */ #define KVM_ARCH_FLAG_EXIT_SEA 11 + /* SME exposed to guest */ +#define KVM_ARCH_FLAG_GUEST_HAS_SME 12 unsigned long flags; =20 /* VM-wide vCPU feature set */ @@ -1133,7 +1135,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) \ @@ -1650,6 +1661,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 b352cd323e30..ba8a3ed8f5ff 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -2028,7 +2028,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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 EBBE83803F7; Sun, 19 Jul 2026 23:10:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502655; cv=none; b=T0qjMqXFd72byY0+0aJbYYxSSNCs/5Kt9MMmpWZesB6zAlkDOgvwD3lrO/6Jkbaf2QOYzvXVVQJMIswC7zesnUsvLQiH+rNkX8YrAhp56MGmUvU/Rq3vEHOCoHgNgGRNBv9Z112cKREKOkESSwary5zPymCUl7qBY31WDThmquE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502655; c=relaxed/simple; bh=LymwA3DqasGC4ZFs4/KMSvspNgOVO26BbyCDy7Uzk5Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DgKxcmGtyjarjabiIQp2od71FAFnLz2FXLzfwaz1soz4ZBVaM9xEgAW54oREeu46yltLErqWCKCzCNgWSPWiT0xIrOXxQFdUYqHHQ/8gV4vBpKun8W995qOiI/frqXQ8CXrkz/UKkg0J4SsTZ9SV0cNyn/onL/pWDZmOEEjrvHM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mWl78oUn; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mWl78oUn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E59F51F00A3A; Sun, 19 Jul 2026 23:10:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502653; bh=H8WckkdslO+jqzhb243ic0W1zpfpgFKz9U8uw4dwQBU=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=mWl78oUnvxwHaXL/sHj+CLVk86T8Unu5lpazkkW9i0xXcU8s4TIoR382HNxxWUDaf zuaNPqTNTYwSfPz2r01pv7bvjyOvcnAQKNkPqlEgx6PVZBTZjyMYaZwRVbwxytScRd nv87qSWLGHgIUgAqPuEn407oF+/qZyxIm9elNIWmBVxVV8ney9UR5cPICwJX0iE3Id PlGeJOCwgK83dVSZQIZ5WtjxzctO+Vh0ZeiqehGfilq2tkXrZ9R+YCGS6SBwvRmVfb B7pcp8ClMilje4YIL8EUZggg84LS/5HGNWQ8sxSAOrWEe/XbI46SxeAqyvLvhAdShp ORDAnfbw2DqPw== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:40 +0100 Subject: [PATCH v13 13/32] 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: <20260720-kvm-arm64-sme-v13-13-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=2449; i=broonie@kernel.org; h=from:subject:message-id; bh=LymwA3DqasGC4ZFs4/KMSvspNgOVO26BbyCDy7Uzk5Q=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkxKQcZdJy3CgVlsYTB2yBImeJBskXWawsGh PIdrMofXbeJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZMQAKCRAk1otyXVSH 0PZPB/9wYDWSSwuJoaXegbkA3ojn0bg5GFt/VB8ePBzOuLDDSDK98wtdtnisSNGdTEQEODMmlwE TRHMG9m6rYm1abTicdktsE/jloy/lefN5lah0N5YueiMYZ502dFHWXLv9pGw2O0dp/cGhJwVX+j EP70Uq7RVtOrF3B2q+m982KWKilxk3T0TtNRFs0rc2lpsX987oc1SyzsoqPoH6iDDuTgE9TWCS6 HXbfXb4kusiaYk1tkwJH2BabGn1PNNLvLZqgfT/zaxdFwnWlwxA7HGR+deaKEEPK+lGi+HS2Zjn vH88tZpsJAdaC5HrQgbTFBFigIpgUA/HS3O9xkfPcrvudQxq 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. Reviewed-by: Fuad Tabba Reviewed-by: Jean-Philippe Brucker 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 0b789f73bf7c..3ae751e72c95 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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 475B1380FD0; Sun, 19 Jul 2026 23:10:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502659; cv=none; b=BPTtJozOUCDpgVABRX8jZNSw8O38pcCyC0du4QJYde6c9tyrlDhdBk5MbHcZ+mKzBIyLlzi5QrpfUVgDUvKaJZUdP+TM2NbTfk/nXtdQe9wrk/Mw7PHpT+VdGd0KDWfuXOSgOckluIZ1eu/+PwSOnc7g5p5VTG8jp0Ii+DbPY9Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502659; c=relaxed/simple; bh=JNOo3GJkWaqu/L2VdRhHtEu5Tolq0xfTclwXoJgGYB4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I/CDkzq9YDaQn5Hyc2F86ArBaTLGjzEH9VeKChMdytiYXi8c1uvvnusy3kgMq2UkiV+2V2wue99FrCzO5gfKCGzjOBQIZ8PyCu6X8mPHXGZm5IaGKSr5n99gVpv0vSKRkUM7VbFl7CVPe+GU+0gWXVMe51OYa6+ndXKSGcdg5uk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RUSJgx+L; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RUSJgx+L" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 418D11F000E9; Sun, 19 Jul 2026 23:10:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502658; bh=TxWn7nfyePTUgvRGwskv4O6R7x4vo8M2+kHo4ElhjEY=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=RUSJgx+Lwb2cRYn80/Nq8YbtHWKB2fcBEYbvOyybixhmX5NXigVSmjvkKnXV98nlE j5KHixCkZsg0ap2837dWK4FEtI1jtjlhX/inVJXiEiOETiFNgg9MqrGbX4Lb6wxCq9 ZasWhdPo2gdJBBBGScpgE+KlJfh1vH73QPnrY9e4j/Y2pYxhWHI2tbARxAMPjoKmZ3 ighly6Wy7MfFMgxlNiC+GIqrnaPJ5NY77pBROJ0jKup+W/8eQ30p+tm3TRBuDV4mlS 9DmJVAIgtA3rugki/rq//fmyzL0NJZiJpOcQtI06FeeqdoOEGo4ln0gcM+ydZVMjbB AqDA9R22iZuTA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:41 +0100 Subject: [PATCH v13 14/32] 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: <20260720-kvm-arm64-sme-v13-14-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=10749; i=broonie@kernel.org; h=from:subject:message-id; bh=JNOo3GJkWaqu/L2VdRhHtEu5Tolq0xfTclwXoJgGYB4=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkyM1K1xJZ+7juw5qi9C3iVumpeGIKMEVMYA sJoc3z647eJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZMgAKCRAk1otyXVSH 0L+MB/42alkEJJ8T91bs5L05g8W048G03pe11c4UzLtZmpI2vjwMa+9otxcL9BdsxkHEFHVxESl DvpFCaeFPOBuASFUHonjS86l4HWGo65GpP9eO9mzVuuyB+yfUWCevqSOtkfZ4tubW1vFOnl3bDj aWjYNIalWaKrtxqe8eEjY2zY78f+vQSY5IgD59qjqXO/ut/IAke5/KaaR4bvQ/TLKXNDqgedYMb t2Jx4BzrT0tqG/Qpcd3CFIVoyH/D5rptNn2+FML1vs6/3pIkHHZHSZmkh5kq5OHI2UB8l57Ijjg h2cJ4I1VjDIAU1HPmV5KgxHZkuASSKVvkrq0fojYcueArSgw 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 | 11 ++++++----- arch/arm64/include/asm/kvm_hyp.h | 2 +- arch/arm64/include/asm/kvm_pkvm.h | 2 +- arch/arm64/kvm/guest.c | 6 +++--- arch/arm64/kvm/hyp/include/hyp/switch.h | 4 ++-- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 4 ++-- arch/arm64/kvm/hyp/nvhe/pkvm.c | 7 ++++--- arch/arm64/kvm/reset.c | 22 +++++++++++----------- 8 files changed, 30 insertions(+), 28 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 8e185e43fbff..5e071381ae5b 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -77,8 +77,9 @@ 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]; + int __init kvm_arm_init_sve(void); =20 u32 __attribute_const__ kvm_target_cpu(void); @@ -857,7 +858,7 @@ struct kvm_vcpu_arch { */ struct arm64_sve_state *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; @@ -1100,7 +1101,7 @@ struct kvm_vcpu_arch { /* KVM is currently emulating an L2 to L1 exception */ #define IN_NESTED_EXCEPTION __vcpu_single_flag(sflags, BIT(9)) =20 -#define vcpu_sve_max_vq(vcpu) sve_vq_from_vl((vcpu)->arch.sve_max_vl) +#define vcpu_sve_max_vq(vcpu) sve_vq_from_vl((vcpu)->arch.max_vl[ARM64_VEC= _SVE]) =20 #define vcpu_sve_zcr_elx(vcpu) \ (unlikely(is_hyp_ctxt(vcpu)) ? ZCR_EL2 : ZCR_EL1) @@ -1119,7 +1120,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 #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \ KVM_GUESTDBG_USE_SW_BP | \ diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_= hyp.h index 4974492744cc..3d05533a0f67 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -150,7 +150,7 @@ 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]); extern unsigned long kvm_nvhe_sym(hyp_nr_cpus); extern unsigned int kvm_nvhe_sym(hyp_gicv3_nr_lr); =20 diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm= _pkvm.h index 74fedd9c5ff0..d4d22acf2fe7 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -188,7 +188,7 @@ static inline size_t pkvm_host_sve_state_size(void) if (!system_supports_sve()) return 0; =20 - return SVE_SIG_REGS_SIZE(sve_vq_from_vl(kvm_host_sve_max_vl)); + return 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/guest.c b/arch/arm64/kvm/guest.c index 3ae751e72c95..2370bb0ad94e 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_vec() */ - 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 b4680baffc6e..35e8d952c7b6 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -493,7 +493,7 @@ static inline void __hyp_sve_save_host(void) struct arm64_sve_state *sve_regs =3D *host_data_ptr(sve_regs); =20 ctxt_sys_reg(hctxt, ZCR_EL1) =3D read_sysreg_el1(SYS_ZCR); - 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); sve_save_state(sve_regs, true); fpsimd_save_common(&hctxt->fp_regs); } @@ -548,7 +548,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 d3c69de698f4..14e24e257dcc 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -40,7 +40,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(kern_hyp_va(vcpu->arch.sve_state), true); fpsimd_save_common(&vcpu->arch.ctxt.fp_regs); - 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) @@ -57,7 +57,7 @@ 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); + write_sysreg_s(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1, SYS_ZC= R_EL2); sve_load_state(sve_regs, true); fpsimd_load_common(&hctxt->fp_regs); write_sysreg_el1(ctxt_sys_reg(hctxt, ZCR_EL1), SYS_ZCR); diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index 9d7f632f01f8..d49f7f327adf 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -22,7 +22,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 in protected = mode @@ -459,7 +459,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 @@ -473,7 +474,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 0fae62a9eaef..fee01c38fa13 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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E46A7381AE9; Sun, 19 Jul 2026 23:11:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502664; cv=none; b=LoifNvP07Ohnho7PGOV7EDTcv1razXpGtQ35e7ZdIQbctc3/et1tHCjJG2jCn3pgmspSvZGgmxln49FonBKr5/F+C9QW87RBYlkcQxDZ3AQ8AVQysCPMwBn8fgXInMVlJrG/B8bgfxMzsLdq8732wMGNTCZILxCsHRrBm6viNvY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502664; c=relaxed/simple; bh=bJ6/1BPMmH6cmZPVFQnhedk6wX18ttIgJVNhwPNun9Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iNkcYvXsFF/BeEIAc2FvHdqhx0sMK1fv2+/S41Kn68a73JQMIE0GZTNf2W8/2bdpXlJs/tD47VhyujE6Agn6Ej3+gGRYt/4L364NUqMRF8XniSrm52ndtx5VLoNh8JGIExuXdiOAoEADZRSZ+NwzVIVTI0jw+SSjqnhZ+adyWYI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=glRgAns1; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="glRgAns1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 914CC1F00ADF; Sun, 19 Jul 2026 23:10:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502662; bh=9uIaB06tZng9peZX4GAyF9EMCE3RvorRheB3h8LExDA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=glRgAns12r4ZtTb+IfvaIncB3CwZ8YtWt5cAQQi1og/rYhiVyWW01tUPMW4S+GdYO Y/29w6lrklV3fHrCoYQHLO6H3wn4EV+x2rqhzixo5jSIC+8ZzB8wmmBwEfY0K9xcA1 fh5FwteBF8zc8E1WxwBh1PNz/8pbKxbaxXq86I1rQdQ+OUlG9wlsTsO62Ox6uNajO3 ZKHNr/Cz2dR3ie63Zirs/ctbqgD2H+D8MgcyCepuyCCtzllQwz4MbXlYcgrIRiHbDd yqG+Om8RiJWWWF4EQ1fawxb108WcznoXZEfH/EwYEhl1JmJRAM1MGlj3kFt/qkusZv FRIp0UrrG/+Cw== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:42 +0100 Subject: [PATCH v13 15/32] KVM: arm64: Factor SVE code out of fpsimd_lazy_switch_to_host() 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: <20260720-kvm-arm64-sme-v13-15-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=2931; i=broonie@kernel.org; h=from:subject:message-id; bh=bJ6/1BPMmH6cmZPVFQnhedk6wX18ttIgJVNhwPNun9Q=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVkzHZ4fRCHElMqfCb5+rQ+Li82PCjHzy8RfL AW6xr2OGaKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZMwAKCRAk1otyXVSH 0HJdB/9MAtlVIPjFw6KwuvU2d3bKxxeGEzGE+PLj2Jxi4YenzXTNyLkRRvrTSujosJY6u/vRjQ+ 6zDxvphe0kxQoQGbM4hd531iZYT34MLqIKyj4IY2zxCHJO6EE8Nm4Abhv4SEb6GuYdD/zGHoA1q 7BwB7pD/11LyRyYQgs87Yic/LQI2SFTXwyKZAeopVQrcuqL0qJiYoVItpu0FhgO7yxLe6GPdAeP Av6teNKTLsokTL9QyrG2QBUEDO/qpSNKC1jI8W37ws+GLFECXhgbrJZpQoJs5BLwsYXwVxqnFfb L6SkEBdAvLxHesavtPF6ffpAK8RoXoPlgZx+iLjvGZlobFdz X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB Since the function will grow as a result of adding SME support move the SVE code out of fpsimd_lazy_switch_to_host(). No functional change, just code motion. Reviewed-by: Jean-Philippe Brucker Signed-off-by: Mark Brown --- arch/arm64/kvm/hyp/include/hyp/switch.h | 48 ++++++++++++++++++-----------= ---- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/i= nclude/hyp/switch.h index 35e8d952c7b6..ce586110c226 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -519,11 +519,11 @@ 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) +static inline void sve_lazy_switch_to_host(struct kvm_vcpu *vcpu) { u64 zcr_el1, zcr_el2; =20 - if (!guest_owns_fp_regs()) + if (!vcpu_has_sve(vcpu)) return; =20 /* @@ -534,29 +534,35 @@ static inline void fpsimd_lazy_switch_to_host(struct = kvm_vcpu *vcpu) * synchronization event, we don't need an ISB here to avoid taking * traps for anything that was exposed to the guest. */ - if (vcpu_has_sve(vcpu)) { - zcr_el1 =3D read_sysreg_el1(SYS_ZCR); - __vcpu_assign_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu), zcr_el1); + zcr_el1 =3D read_sysreg_el1(SYS_ZCR); + __vcpu_assign_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu), zcr_el1); =20 - /* - * 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()) { - 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_max_vl[ARM64_VEC_SVE]) - 1; - write_sysreg_el2(zcr_el2, SYS_ZCR); - - zcr_el1 =3D vcpu_sve_max_vq(vcpu) - 1; - write_sysreg_el1(zcr_el1, SYS_ZCR); - } + /* + * 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()) { + 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_max_vl[ARM64_VEC_SVE]) - 1; + write_sysreg_el2(zcr_el2, SYS_ZCR); + + zcr_el1 =3D vcpu_sve_max_vq(vcpu) - 1; + write_sysreg_el1(zcr_el1, SYS_ZCR); } } =20 +static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu) +{ + if (!guest_owns_fp_regs()) + return; + + sve_lazy_switch_to_host(vcpu); +} + static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *hctxt =3D host_data_ptr(host_ctxt); --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 0D341381AE9; Sun, 19 Jul 2026 23:11:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502668; cv=none; b=HKLtE6tfmTkUnQ3FJ8xDkmnI71PQfHWglr6VSFltIYfj5LFC9l2nHQLv1GZc3KlKJB0MyJwFcBrdMdnrBYAinV2794/3fAsbax6PDKiPleFkAHz6W6374qpMnHvudKGG6n2bFkhJG4r3gimaDvcxZoa3GHYAk7OWaJyjtIlS2mo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502668; c=relaxed/simple; bh=NRO2PrOVNEiF3gyeRCWVVzXVVhp969GrzVhDSoP3Gic=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Uy21d+auYhm7pN0rGvNlyajvffYppRQP6x7OCllPWPLp41Ws0BGFUXhHIkNma/eQsC+D0zrvXVOdC6lmeCB9ko9bQAsieYpJ3eDCbr219qnUGEqJSVeHKqY7K6MiBiqwvo9ZjsF5bWQ6igzB6oiCUXVcJ5xqBMpIf3iaub5BNXI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nMfU4p75; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nMfU4p75" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ED11D1F000E9; Sun, 19 Jul 2026 23:11:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502666; bh=OxrqaJSXrvgytjhm4lmC0/NimnBOV08f5ynrGa3ygDg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=nMfU4p75CoG1R+gA67VgnUiz5AJEFOqTdZPQHaVPfFeHKDbVHChxlKw4ZV1nh/mMf ft/K4iIR1RV/R4IWfW50ryU/YU4myukIQG0sAJOYdbrFPTZw0SRPh3W5cO5So8YtQb S83RS8+fU0XVU6UXm0xJw9BxDm9eHhPLzm3JEBvBQ6242sQJ+e0mr0CrF6DD19OGla jf7CB7myOLbg7XXp9y2Shdl/UgK9OVRgXKcAl+R1D6/+ygUNqNCU7Qb6/BsikO89nC nP/kAPkMnxePEl5VxWhZPj3ZnGlraIXTT5xDWgfL1pKlyF+8T94jby2sgwZV89XaBd n9tBo6Jqjy2ig== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:43 +0100 Subject: [PATCH v13 16/32] 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: <20260720-kvm-arm64-sme-v13-16-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=12759; i=broonie@kernel.org; h=from:subject:message-id; bh=NRO2PrOVNEiF3gyeRCWVVzXVVhp969GrzVhDSoP3Gic=; b=kA0DAAoBJNaLcl1Uh9AByyZiAGpdWTOjh2rP5i7XctVjRLnCtrCqjYfJOYPZPn/ITBHf/9tgF 4kBMwQAAQoAHRYhBK3maKpnVxi1n+Kf6iTWi3JdVIfQBQJqXVkzAAoJECTWi3JdVIfQgYQH/RNa +SvqCtV8cD9l87iai58kUx4zF96YW0JxqjdWO1kAVkUzNybo35t2fbYy9LPM1qmnGtgXPI55O8Z 5UZ4oCR/aIJRuOEWphVWeNExUxnjSNgdXzMVQBGr796u8Y6MUeMlUEKipTKoEBrqjVs/5szBT4P D16Bq/8WLJXpx0w6MPoI5V7YqHUegh8PVb8NUW5HBag4PQ34brm3GXR8HhIxHs3xheYolF11k8a WGdr1c0NnzhCFqJ5VON54/fXGaPLtxxDDX/DXNZyTowKp5FfumGyGoE0O6ecMkU+7A+FiYXc8a+ BWQzWyGPTM1Nbgk6XqoOsK49/Ub0sXXJeV/kSdI= 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 parameter 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 present the SVE registers to userspace as having the maximum vector length of the currently active vector type as configured via SVCR.SM, imposing an ordering requirement on userspace. Userspace access to ZA and (if configured) ZT0 is only available when SVCR.ZA is 1. Reviewed-by: Fuad Tabba Signed-off-by: Mark Brown --- Documentation/virt/kvm/api.rst | 127 +++++++++++++++++++++++++++++--------= ---- 1 file changed, 91 insertions(+), 36 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index a5f9ee92f43e..a3bb4a82a9f9 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 @@ -2607,11 +2607,11 @@ Specifically: =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`. + :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 @@ -2642,24 +2642,38 @@ 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:: =20 -These registers are only accessible on vcpus for which SVE is enabled. -See KVM_ARM_VCPU_INIT for details. + 0x6080 0000 0017 ZA[n] bits[2048*slice + 2047 : 204= 8*slice] + 0x6060 0000 0017 0600 ZT0 + 0x6060 0000 0017 fffe KVM_REG_ARM64_SME_VLS pseudo-regis= ter =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. +Access to Z, P, FFR or ZA register IDs where 2048 * slice >=3D 128 * +max_vq will fail with ENOENT. max_vq is the vcpu's current maximum +supported vector length in 128-bit quadwords: see [2]_ below. =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:: +Changing the value of SVCR.SM will result in the contents of registers +that are architecturally reset by entering or exiting streaming mode +being reset. When restoring the values of these registers for a VM +with SME support it is important that SVCR.SM be configured first. + +Access to the ZA and ZT0 registers is only available if SVCR.ZA is set +to 1. These registers are only accessible on vcpus for which SME is +enabled. See KVM_ARM_VCPU_INIT for details. + +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. + +KVM_REG_ARM64_SVE_VLS and KVM_REG_ARM64_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 @@ -2671,19 +2685,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. Note that these slices + should not be confused with the architectural "ZA tile slice". + + If SME is supported and SVCR.SM is 1, then the max_vq used for the + Z and P registers is the maximum SME vector length. Otherwise + it is the maximum SVE vector length. =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_ARM64_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 @@ -2691,8 +2711,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 @@ -3491,6 +3511,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). @@ -3534,7 +3555,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 @@ -3542,7 +3563,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 @@ -3555,11 +3576,41 @@ 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_ZAHREG() or the LUT register + KVM_REG_ARM64_SME_ZTREG(); + + - 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. @@ -5156,11 +5207,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 @@ -8885,6 +8937,9 @@ aforementioned registers before the first KVM_RUN. Th= ese registers are VM scoped, meaning that the same set of values are presented on all vCPUs in a given VM. =20 +When SME is supported by the VM SMIDR_EL1 is also controlled by this +capability. + 7.43 KVM_CAP_RISCV_MP_STATE_RESET --------------------------------- =20 --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 53A9A3803DB; Sun, 19 Jul 2026 23:11:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502672; cv=none; b=X+pU8q7RuUoyb9ckGYTiAetNjfjzN9N1yOKPb25X4Pb806JVYMBsna9tEqQlkGXZacMstJhARqoYbSrHDDmP8n2JTf4ltbPbo+V9RVPYDb2QXDD9lDTLexPAbcuB7VDPAGkUraeTuMbO3ymH1w5nF8vx99zBmb2NXk3ZgSUVPSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502672; c=relaxed/simple; bh=7uWd78YrETEBlnxZLyY92owXALEc9hsIXnY5pRwnl04=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=D77c00ivMHQYBGvHFouEjqi3tn6fjR/nLRYp+9cBhu5cr3aLQG5j1OjwS5kTCQo+iwwnASwEew/TLRURjBnH3e2UjD1raoJiUro8hLzHWkr7WWtF6KW5uvgwJ9OKfDaSyF5mJR+v942fN4hCgu20TeudHVW50MjIdkKFpPdkHBE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=atSL56GE; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="atSL56GE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 49A341F00A3D; Sun, 19 Jul 2026 23:11:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502671; bh=I8M00Ym6Erozlc1l5acQwt+RlGrG09FFVsuFSY+a9Iw=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=atSL56GEQ5WUYL6asgJ7xtpGrifk2n4AAkjQZTmRtaoqqRWW2QBwGD1rK5zVf7bKP ymoVIFXDlxi8MspOVZAQiXSj3gDhwLAbmzU4QeMXoHONfbDje0lZ+tFdINAmjMKJRE uUL+glNya7CDBm42UOlp9BUtBzlifOMIygblENQIkU/RIZpYe85jx7skdS6ektZ9cw 0RT5ahbq4TBAAmdieF751Xck2NrQYsiBof2g+LaqZmEp6XZ914rRKC3xnUdsV6CRdO dN4iTqQaUK/eymZqGkZmdK1/CkwMjz05I+flkbOihd/B9x7zbgOL5zfueg7p8wIqgI t9uMj5u9IfOSg== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:44 +0100 Subject: [PATCH v13 17/32] 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: <20260720-kvm-arm64-sme-v13-17-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=9943; i=broonie@kernel.org; h=from:subject:message-id; bh=7uWd78YrETEBlnxZLyY92owXALEc9hsIXnY5pRwnl04=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk0Jr4g+ILcW5esh+rz2fBjl0EAFkITzNtPZ Uqv9vXaYQiJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZNAAKCRAk1otyXVSH 0BwrB/404GZMcjVJ5hAKAcU6VpXCPKtg7K5/XUd6VRbACUMbimmZPkD8YU8Wam1Pa6BtwnILJ5E cZ6JjjafR/g5GetiMJLPVkNkplDp4KD37wlBoNoXr3Vmr4+SmHcWvijTFz7ccNMd0vjdZvOxqWP kX3FCywNFa3E+O4NotlB/rFDjSf2h/Q+WMjfJYYVd/Bdf+XVR0QZPayMcWZa20RrXI9K8EPPfEp Gx7ZOqUETw3+b2aDZYupHg1m2tHibBZXnacfw3NM3T377MBOUxnchHfkbdht8h3Vlblv/dA80m2 1Zaour2NMcqZeGbF4yl4Jn7aH/WVV0UpunVqEFLVcU0I22pB 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 | 19 +++++++++- arch/arm64/include/uapi/asm/kvm.h | 7 ++++ arch/arm64/kvm/guest.c | 80 +++++++++++++++++++++++++++++++----= ---- 4 files changed, 89 insertions(+), 18 deletions(-) diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsim= d.h index 395606e01e18..d4a88c31f22f 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -544,6 +544,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 5e071381ae5b..858341eb1e8f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -855,8 +855,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. */ struct arm64_sve_state *sve_state; + struct arm64_sme_state *sme_state; enum fp_type fp_type; unsigned int max_vl[ARM64_VEC_MAX]; =20 @@ -1101,7 +1108,15 @@ struct kvm_vcpu_arch { /* KVM is currently emulating an L2 to L1 exception */ #define IN_NESTED_EXCEPTION __vcpu_single_flag(sflags, BIT(9)) =20 -#define vcpu_sve_max_vq(vcpu) sve_vq_from_vl((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) +#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]) + +#define vcpu_max_vl(vcpu) max(vcpu_sve_max_vl(vcpu), vcpu_sme_max_vl(vcpu)) =20 #define vcpu_sve_zcr_elx(vcpu) \ (unlikely(is_hyp_ctxt(vcpu)) ? ZCR_EL2 : ZCR_EL1) @@ -1120,7 +1135,7 @@ 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) sve_state_size_from_vl(vcpu_sve_max_vl(v= cpu)) =20 #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \ KVM_GUESTDBG_USE_SW_BP | \ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/as= m/kvm.h index 83af99ca4e1b..15d53300914b 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -354,6 +354,13 @@ 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 | 0xfffe) + /* 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 2370bb0ad94e..48e6b500f531 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,18 +332,16 @@ 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))) @@ -356,18 +352,18 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const s= truct kvm_one_reg *reg) 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 +371,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_vec() */ - 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 +545,40 @@ 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; @@ -711,6 +757,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 return kvm_arm_sys_reg_get_reg(vcpu, reg); @@ -728,6 +775,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 return kvm_arm_sys_reg_set_reg(vcpu, reg); --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 C567C386541; Sun, 19 Jul 2026 23:11:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502677; cv=none; b=fUsS0oKcKZaaVV6Af6owXqB0wBytrsI77kix5ExfklGRViStlZplodv2ab89Sba8VKsNr9q9xG+nU+pgtPAi0EkjnBXCPtf6gNm7aEJ/OJ5QJNzATzXGZkabMoeUVhSkAIRlAZeB8H8UDiuouirt6EQe5YuKN5+N+DWlR/rKjHE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502677; c=relaxed/simple; bh=H+o/3748vgny3lGilz48bxpWfmNuNNC3E7l3zKXni58=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aSNbw+JbSSBwhadwb/nOL5xVlRxWijHDiYMIj+4ONq0y0nkyRUIkQFRhUUdEDKI38JdOzR4hkv/iCf5C8y1VJt+EjYnoGFpvXu1xEusTB+VWWs/lqVXMxDCF72WjOhze9Tj7oxxXezcbwHvuD/O3xuqXU3y32UplFoMJMtdaIrQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CR+AGo53; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CR+AGo53" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9CC421F0155D; Sun, 19 Jul 2026 23:11:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502675; bh=J1zy4AKaHiqNQMXG5h+LXU01eSdMuOzbdR0P6vsnTdA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=CR+AGo53oGMaQUwOjnmXma5GmYVF5o/SepsWJGYHNUf7HJ8TR7x9J5kLdj2IClBPj WyoOnqjRTPv5ljDWLgUV+qgOXvt8s5n3bwEE9/4Rr4sHH37wWv8ui+VqL+beI0uLbM QoNNYSxhuYsxiIRTOrMjVYJp4Fj59zOkQVMxs5PPur3pm2djv5x8hFqjkTt9WjOm82 eNv/5gbX+zTzNuwEU0yVdg4l3ooWE1sRVJMCic+eAhO1x4DpuqvsH8ACxxNOUY9TzJ 18ktmc/+oqQGiGRjFyHEIwuatdXDIoXC5s4EwapW6GYzzuQo/VmkJxjpx/GjWlqSbS ig8O7e3YIo9oQ== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:45 +0100 Subject: [PATCH v13 18/32] 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: <20260720-kvm-arm64-sme-v13-18-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=7447; i=broonie@kernel.org; h=from:subject:message-id; bh=H+o/3748vgny3lGilz48bxpWfmNuNNC3E7l3zKXni58=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk188gckL59zgCkDG26AMosOkiyC8cqSWqM2 9xeUsl7p0GJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZNQAKCRAk1otyXVSH 0EZXB/9VPLqT4wWMIEOBirPK12gveDEDPbIVu+XFQ65v3JS5ZmksL7X7stlxE5cEy1jntxH0jDC dk3X851UHuxqt9q5XWbq4OybuDKnou0JXk7rVXhu7m391QXJiUtbt5QvrhUjFvptDMiJ8/1mHzq 68EORrVaQsMx2hSi0rEJmEQMl+KaCrB6NvYMumYVIMDneDNpn/Do+GpXDpKG5d1D/q68uM7wt4u MIBKurzwXVONibhANXllZX1m9lqSwYyRc7rr+gg1UcKGCN1qXkr5oKT+xsNvxYx5AiuPD5U5AEg 5+05IQORhZUXhxmntceE9NsgmAQETa3K41Dg72est0yejA7J 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_emulate.h | 15 +++++++++++++++ arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/include/asm/vncr_mapping.h | 1 + arch/arm64/kvm/nested.c | 5 +++++ arch/arm64/kvm/sys_regs.c | 31 ++++++++++++++++++++++++++++++- 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/= kvm_emulate.h index 994afbf479fc..b5dc8a4c320a 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -90,6 +90,15 @@ static inline void kvm_inject_nested_sve_trap(struct kvm= _vcpu *vcpu) kvm_inject_nested_sync(vcpu, esr); } =20 +static inline void kvm_inject_nested_sme_trap(struct kvm_vcpu *vcpu, + u64 smtc) +{ + u64 esr =3D FIELD_PREP(ESR_ELx_EC_MASK, ESR_ELx_EC_SME) | + ESR_ELx_IL | smtc; + + kvm_inject_nested_sync(vcpu, esr); +} + #if defined(__KVM_VHE_HYPERVISOR__) || defined(__KVM_NVHE_HYPERVISOR__) static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu) { @@ -689,4 +698,10 @@ static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu) vcpu->arch.hcrx_el2 |=3D HCRX_EL2_EnASR; } } + +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 858341eb1e8f..796b6e3a50f7 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -546,6 +546,7 @@ enum vcpu_sysreg { MDCR_EL2, /* Monitor Debug Configuration Register (EL2) */ CNTHCTL_EL2, /* Counter-timer Hypervisor Control register */ ZCR_EL2, /* SVE Control Register (EL2) */ + SMCR_EL2, /* SME Control Register (EL2) */ =20 /* Any VNCR-capable reg goes after this point */ MARKER(__VNCR_START__), @@ -554,6 +555,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 14366d35ce82..c3bf92ac52d4 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/nested.c b/arch/arm64/kvm/nested.c index fb54f6dad995..50e25ab9b604 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -1920,6 +1920,11 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu) resx.res1 =3D ZCR_ELx_RES1; set_sysreg_masks(kvm, ZCR_EL2, resx); =20 + /* SMCR_EL2 - bits 8:4 are RAZ/WI so treat them as RES0 */ + resx.res0 =3D SMCR_ELx_RES0 | GENMASK_ULL(8, 4); + resx.res1 =3D SMCR_ELx_RES1; + set_sysreg_masks(kvm, SMCR_EL2, resx); + out: for (enum vcpu_sysreg sr =3D __SANITISED_REG_START__; sr < NR_SYS_REGS; s= r++) __vcpu_rmw_sys_reg(vcpu, sr, |=3D, 0); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index ba8a3ed8f5ff..24bbe30c075a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -121,6 +121,7 @@ static enum sr_loc_attr locate_direct_register(const st= ruct kvm_vcpu *vcpu, case ELR_EL1: case SPSR_EL1: case ZCR_EL1: + case SMCR_EL1: case SCTLR2_EL1: /* * EL1 registers which have an ELx2 mapping are loaded if @@ -241,6 +242,7 @@ static u64 read_sr_from_cpu(enum vcpu_sysreg reg) case ELR_EL1: val =3D read_sysreg_s(SYS_ELR_EL12); break; case SPSR_EL1: val =3D read_sysreg_s(SYS_SPSR_EL12); break; case ZCR_EL1: val =3D read_sysreg_s(SYS_ZCR_EL12); break; + case SMCR_EL1: val =3D read_sysreg_s(SYS_SMCR_EL12); break; case SCTLR2_EL1: val =3D read_sysreg_s(SYS_SCTLR2_EL12); break; case TPIDR_EL0: val =3D read_sysreg_s(SYS_TPIDR_EL0); break; case TPIDRRO_EL0: val =3D read_sysreg_s(SYS_TPIDRRO_EL0); break; @@ -279,6 +281,7 @@ static void write_sr_to_cpu(enum vcpu_sysreg reg, u64 v= al) case ELR_EL1: write_sysreg_s(val, SYS_ELR_EL12); break; case SPSR_EL1: write_sysreg_s(val, SYS_SPSR_EL12); break; case ZCR_EL1: write_sysreg_s(val, SYS_ZCR_EL12); break; + case SMCR_EL1: write_sysreg_s(val, SYS_SMCR_EL12); break; case SCTLR2_EL1: write_sysreg_s(val, SYS_SCTLR2_EL12); break; case TPIDR_EL0: write_sysreg_s(val, SYS_TPIDR_EL0); break; case TPIDRRO_EL0: write_sysreg_s(val, SYS_TPIDRRO_EL0); break; @@ -2830,6 +2833,12 @@ static unsigned int sve_el2_visibility(const struct = kvm_vcpu *vcpu, return __el2_visibility(vcpu, rd, sve_visibility); } =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 unsigned int vncr_el2_visibility(const struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd) { @@ -2872,6 +2881,23 @@ static bool access_zcr_el2(struct kvm_vcpu *vcpu, return true; } =20 +static bool access_smcr_el2(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + if (guest_hyp_sme_traps_enabled(vcpu)) { + kvm_inject_nested_sme_trap(vcpu, ESR_ELx_SME_ISS_SMTC_SME_DISABLED); + return false; + } + + if (!p->is_write) + p->regval =3D __vcpu_sys_reg(vcpu, SMCR_EL2); + else + __vcpu_assign_sys_reg(vcpu, SMCR_EL2, p->regval); + + return true; +} + static bool access_gic_vtr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) @@ -3386,7 +3412,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 }, @@ -3754,6 +3780,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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 EE6AC38236D; Sun, 19 Jul 2026 23:11:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502681; cv=none; b=U2MFwuDZ5ze17a01P4nOOr5eZyqQ4ZtORnsT4wkVCAUwfUlxxbBKmHrHVTXWKu6M9OLYPyqrggdBsnHgwnABFF2d1x+A2/YT1Lr9aWsiss7rgTbvdoolS5DzXIvBR6ezY1NNzflu3IZqbuwS57oi8r6TeQgdMEclJJuL/X4zoR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502681; c=relaxed/simple; bh=OLmfKw1OWtsaEUazoIIIWYByRIJqe5QP2QutP6yHROg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pWl5Yh+FmAuD5Y4DQ2mp7t3mP5M+vegeB+MT42dNU5QdIVNE9Ro7rp3Y1l8vZYlX4ppjoiDDq3ydFFe95hxt1MFeGWzpLV850J19lRvJZDB5hu/SRRei0pwbFYwlJ/rBBsuu6PV0P5CsjuwGtZ8qxgCfcEbI3OShvKGtJ8vuOQQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=e4MxLCXS; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="e4MxLCXS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EA0B11F000E9; Sun, 19 Jul 2026 23:11:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502679; bh=8QKfeY6MF9dpRy4jWvo6mGVT4QR36ThS7v75EfE7dSs=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=e4MxLCXSPf2kWjpkFRE2nPg0lQkG1x+47uXc9IEtSlaJ14wMlQSZKOmNKoyL1rXHR EKvB4ZrrwOCohaPC7ALCyxWk4ni6YPA+C9njsTkLAhIyrdoi79dWLB+G5yPKa4/McO 8gEmBhBW9BrIJV9Ne2/jdTNIUAAhM/OrFt6P4QpanKGzNeBgBjRBSaRkLas9YBLirS xh5WUeeE23/7z+xdU40svoksStoz5mcvfGmFPUO0dKruxG1DtBdD3nMSkOv4LraeoU BTmlzdSMCtHFtKAmsP0z9uPBqsU8lr3dMxKTSLcohl3SJJRbigvd9v9uIspEI6oEY7 dD12q7aDEjpww== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:46 +0100 Subject: [PATCH v13 19/32] 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: <20260720-kvm-arm64-sme-v13-19-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=4705; i=broonie@kernel.org; h=from:subject:message-id; bh=OLmfKw1OWtsaEUazoIIIWYByRIJqe5QP2QutP6yHROg=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk2dyjNwO2ydr9q0peDQtfzHdNngXOQCLdoG 377ZZxBElWJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZNgAKCRAk1otyXVSH 0HaAB/9VVxYov3R1QcHJyuQ6qd55dsBztQ+F2tpkMMGvGTD/UpGd21sgtg8A2Ii1gKKYl2a60hf JLDWcrm7vkS1EpVnTjgTX+XTP/4EoGXWYOSmXxtJdFAU6CMm7h01pHqXvWC6MKqRrtafE5QD1h0 odfd39iIY8mFfmZ3GnqagTyH08egKxQsZQe/f/9PNlupQwCeRrEVH74MPkUzbh73l0aTNeU+D40 UF49C558n14kC8CMsE3t1UsOu1zDUvSmqwhUsxKMQY3Eqv59mVM8prhGLTCkLf/1pfzjE30op5X HHns3LxAnQ4hmG0dhPbHNWgH4Ev1pkbFZnMI8y907jl0ZXzR 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. Reviewed-by: Fuad Tabba Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 12 ++++++++++++ arch/arm64/kvm/sys_regs.c | 6 +++++- 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 796b6e3a50f7..da7e572822a1 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -460,6 +460,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..0fd4092e4f25 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -88,6 +88,14 @@ 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; + + 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 +135,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 +214,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 24bbe30c075a..8f19caac6008 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -131,6 +131,7 @@ static enum sr_loc_attr locate_direct_register(const st= ruct kvm_vcpu *vcpu, =20 case TPIDR_EL0: case TPIDRRO_EL0: + case TPIDR2_EL0: case TPIDR_EL1: case PAR_EL1: case DACR32_EL2: @@ -246,6 +247,7 @@ static u64 read_sr_from_cpu(enum vcpu_sysreg reg) case SCTLR2_EL1: val =3D read_sysreg_s(SYS_SCTLR2_EL12); break; case TPIDR_EL0: val =3D read_sysreg_s(SYS_TPIDR_EL0); break; case TPIDRRO_EL0: val =3D read_sysreg_s(SYS_TPIDRRO_EL0); break; + case TPIDR2_EL0: val =3D read_sysreg_s(SYS_TPIDR2_EL0); break; case TPIDR_EL1: val =3D read_sysreg_s(SYS_TPIDR_EL1); break; case PAR_EL1: val =3D read_sysreg_par(); break; case DACR32_EL2: val =3D read_sysreg_s(SYS_DACR32_EL2); break; @@ -285,6 +287,7 @@ static void write_sr_to_cpu(enum vcpu_sysreg reg, u64 v= al) case SCTLR2_EL1: write_sysreg_s(val, SYS_SCTLR2_EL12); break; case TPIDR_EL0: write_sysreg_s(val, SYS_TPIDR_EL0); break; case TPIDRRO_EL0: write_sysreg_s(val, SYS_TPIDRRO_EL0); break; + case TPIDR2_EL0: write_sysreg_s(val, SYS_TPIDR2_EL0); break; case TPIDR_EL1: write_sysreg_s(val, SYS_TPIDR_EL1); break; case PAR_EL1: write_sysreg_s(val, SYS_PAR_EL1); break; case DACR32_EL2: write_sysreg_s(val, SYS_DACR32_EL2); break; @@ -3598,7 +3601,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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 B5215382F0C; Sun, 19 Jul 2026 23:11:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502686; cv=none; b=tumKDhHeYeMrdvpY4Z3eU+JPekQaqMQwBW2CCM88JnOnspqPhQUt4LgEAO0Eqi/J2Hsjbd0TD1x1AyzVzWMT4vkJEyXV3sLpUlVAOspxEwmVlABL5gX69/Nw+l+v3IWuMtzqQRi7QttBrlIRqnXnuKOfZxVA0k1mrIsG7eV7phI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502686; c=relaxed/simple; bh=jUFGq0+icNwT/iYb+BgbYtlTqmLb6rTTJWQ/OH31Z3M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=grSOh8IrpFtVazxmbwFJI2K410dJazA2j9VLRvI7XdJ+/jX8hJYCCZ2Y4UZEWcgRgD7kD/Vub6vCY+aJYMnteZCvNleSZW91aauw6hpgYbW+bdKruM+yFsPDiWZVl3WPRr9SAvSlFQpwmenfOXl3LGFeh+4exhRNyvxU2mYcd+Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fLuAB16M; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fLuAB16M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 457DB1F00A3A; Sun, 19 Jul 2026 23:11:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502684; bh=Vyvgwe2bx2dMjhTv9BT8Y3V+NK2lIb8ZDTnayo4YW1U=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=fLuAB16MkkOeLbyqPMy5WPMmk4GEbJp9zOqlOKy17Y2kZl/OVJI8h2Cb3bhMtpVFF tORDcHG3pxi1K38vh+NpfszVZbH2WT09/lSPUdR3chkED3aU/CMbZJrB8hHNnhTchq Pk/b9bdFzA4uoqJ+J/3hJhODhjkYQ9sBJ3Iulb6vXIyKOEIT2UDpI0Dlo2RXT5DB7y rc2P77ZBd7ug4/uoOOUWMla4zCPcxA6X0mwJewK2cUrY6n49qh1n/cQaGRb2J7r/Qi 8x6DOwQRepyqtIbgkZKqiv+Lwwppndv0iI6zn2QwGV4XohVeq3T9a8ij1iMS8HeQ1L fBardkLXw3UAA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:47 +0100 Subject: [PATCH v13 20/32] 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: <20260720-kvm-arm64-sme-v13-20-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=9449; i=broonie@kernel.org; h=from:subject:message-id; bh=jUFGq0+icNwT/iYb+BgbYtlTqmLb6rTTJWQ/OH31Z3M=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk3yTMAvBMEIV+vecNalUWKkHlwIDiqJuc3f o1Oz9591kyJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZNwAKCRAk1otyXVSH 0DzwB/sFPMC46Xkm+HFi62G9r06cck3V/VhdxryVgz94WysJ8TQi3Sk2n8uF9FuB89X7sLFu06W UoBiBPLDwYKjmXT6qaQXFhhl37nFI8/bzgtMJGA3mvzx5g2QlCaix7bqQ8gFqLSKZegu7/3N0kE Ktuu95tmmdQdBTMSFZUgWhbgHJeux8QMAyR43LR01d4kZOS5/AjuNUEun3S8Du7/cV94ZCfuDpc st1L2y8DKf0wf2qP56plry7UIUnt86o4i2qqfWEyT/UYcOZOKTwHNNrw5IPYXPuWKf3dUYY3ZXu EWytZm7jvdm3YOb9AczYx/73GgV8lKhM+qT8VwblvU+X96Jl 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. In order to avoid any confusion in the KVM implementation we force ID_AA64PFR1_EL1.SME to advertise SME when SME is enabled for the guest. 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 fields defined in future. 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/nvhe/pkvm.c | 4 ++- arch/arm64/kvm/sys_regs.c | 55 ++++++++++++++++++++++++++++++++++-= ---- 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index da7e572822a1..e8c2907aacd2 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -410,6 +410,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; @@ -1585,6 +1586,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 0622162b089e..cb6f3ea556c2 100644 --- a/arch/arm64/kvm/config.c +++ b/arch/arm64/kvm/config.c @@ -281,14 +281,8 @@ static bool feat_anerr(struct kvm *kvm) =20 static bool feat_sme_smps(struct kvm *kvm) { - /* - * Revisit 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/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c index d49f7f327adf..620f3395ea4e 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -357,8 +357,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 8f19caac6008..9a993e76da18 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1951,6 +1951,7 @@ static inline bool is_vm_ftr_id_reg(u32 id) case SYS_MIDR_EL1: case SYS_REVIDR_EL1: case SYS_AIDR_EL1: + case SYS_SMIDR_EL1: return true; default: return (sys_reg_Op0(id) =3D=3D 3 && sys_reg_Op1(id) =3D=3D 0 && @@ -1979,7 +1980,11 @@ static unsigned int id_visibility(const struct kvm_v= cpu *vcpu, =20 switch (id) { case SYS_ID_AA64ZFR0_EL1: - if (!vcpu_has_sve(vcpu)) + if (!vcpu_has_sve(vcpu) && !vcpu_has_sme(vcpu)) + return REG_RAZ; + break; + case SYS_ID_AA64SMFR0_EL1: + if (!vcpu_has_sme(vcpu)) return REG_RAZ; break; } @@ -2101,7 +2106,9 @@ static u64 sanitise_id_aa64pfr1_el1(const struct kvm_= vcpu *vcpu, u64 val) SYS_FIELD_GET(ID_AA64PFR0_EL1, RAS, pfr0) =3D=3D ID_AA64PFR0_EL1_RA= S_IMP)) val &=3D ~ID_AA64PFR1_EL1_RAS_frac; =20 - val &=3D ~ID_AA64PFR1_EL1_SME; + if (!kvm_has_sme(vcpu->kvm)) + val &=3D ~ID_AA64PFR1_EL1_SME; + val &=3D ~ID_AA64PFR1_EL1_RNDR_trap; val &=3D ~ID_AA64PFR1_EL1_NMI; val &=3D ~ID_AA64PFR1_EL1_GCS; @@ -2316,6 +2323,15 @@ static int set_id_aa64pfr1_el1(struct kvm_vcpu *vcpu, user_val |=3D hw_val & ID_AA64PFR1_EL1_MTE_frac_MASK; } =20 + /* + * Prevent userspace removing SME from the ID registers while + * leaving the capability enabled, avoiding potential bugs. + */ + if (kvm_has_sme(vcpu->kvm) && + SYS_FIELD_GET(ID_AA64PFR1_EL1, SME, user_val) =3D=3D 0) + user_val |=3D SYS_FIELD_PREP(ID_AA64PFR1_EL1, SME, + ID_AA64PFR1_EL1_SME_IMP); + return set_id_reg(vcpu, rd, user_val); } =20 @@ -3119,8 +3135,11 @@ static bool access_imp_id_reg(struct kvm_vcpu *vcpu, return access_id_reg(vcpu, p, r); =20 /* - * Otherwise, fall back to the old behavior of returning the value of - * the current CPU. + * Otherwise, fall back to the old behavior of returning the + * value of the current CPU for REVIDR_EL1 and AIDR_EL1, or + * use whatever the sanitised reset value we have is for other + * registers not exposed prior to writability support for + * these registers. */ switch (reg_to_encoding(r)) { case SYS_REVIDR_EL1: @@ -3129,6 +3148,9 @@ static bool access_imp_id_reg(struct kvm_vcpu *vcpu, case SYS_AIDR_EL1: p->regval =3D read_sysreg(aidr_el1); break; + case SYS_SMIDR_EL1: + p->regval =3D read_id_reg(vcpu, r); + break; default: WARN_ON_ONCE(1); } @@ -3139,12 +3161,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) @@ -3156,6 +3181,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 & r->val; default: KVM_BUG_ON(1, vcpu->kvm); return 0; @@ -3204,6 +3231,16 @@ static int set_imp_id_reg(struct kvm_vcpu *vcpu, con= st struct sys_reg_desc *r, .val =3D mask, \ } =20 +#define IMPLEMENTATION_ID_FILTERED(reg, mask, reg_visibility) { \ + SYS_DESC(SYS_##reg), \ + .access =3D access_imp_id_reg, \ + .get_user =3D get_id_reg, \ + .set_user =3D set_imp_id_reg, \ + .reset =3D reset_imp_id_reg, \ + .visibility =3D reg_visibility, \ + .val =3D mask, \ + } + static u64 reset_mdcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { __vcpu_assign_sys_reg(vcpu, r->reg, vcpu->kvm->arch.nr_pmu_counters); @@ -3320,7 +3357,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_MTE)), @@ -3331,7 +3367,7 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { ID_AA64PFR2_EL1_GCIE)), 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 @@ -3544,6 +3580,13 @@ static const struct sys_reg_desc sys_reg_descs[] =3D= { { SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr }, { SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1, .set_user =3D set_clidr, .val =3D ~CLIDR_EL1_RES0 }, + IMPLEMENTATION_ID_FILTERED(SMIDR_EL1, + (SMIDR_EL1_NSMC | SMIDR_EL1_HIP | + SMIDR_EL1_AFFINITY2 | + SMIDR_EL1_IMPLEMENTER | + SMIDR_EL1_REVISION | SMIDR_EL1_SH | + SMIDR_EL1_AFFINITY), + sme_visibility), 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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 9F788388E42; Sun, 19 Jul 2026 23:11:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502689; cv=none; b=SveIwIq/lU+x2JY5HXMFop4/w7/La6Jnld4O3HZjh1lP+N6pISkFmc6EsXc6YUbOwTfhJKlHC6Ku6p6IbbXln2lBfMlH9XFIASCemCeHAiYkm3Iwz7oOOwcex2XiCbSO8g0Tg/kXr6j1WPysgyZ8p/tk2EkJPuRrrQBQxb2n1+U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502689; c=relaxed/simple; bh=cYBJzWXUlFEk0NCpM7UpFBgugRQeF0dNkZ0uZU3Aefg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tNO3d2eSQxvDU1HWfia+w5nIPyNSJ9oF8GkK15jm4/R7QsdZdH5UtR89zxauSsKbBN1+IvWxeTLkEYY3h/Sabc9wUFJLHHTb9RQXkhnaZ6Y79IL2W++HipYOVPcPhLYHfMJHOZYkAz4eHLmM/os+dWXZNkz7sJHANKz7U+4bl9E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IOtmILhc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IOtmILhc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 93BC41F000E9; Sun, 19 Jul 2026 23:11:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502688; bh=A2bN4tIPltWwBewhT2VmWsvljJVWBjMJb/lk1RQjUJ4=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=IOtmILhcbqIUhxae31DsVCunrfgtE0ROBNka7Z0bKekDcNFFw6Y/9wo/REPNXAIjO oQQRbkMY3haHLFt4PUAtqpzgUQXgrJw++byfuL5j/SXI24i2Apl7wzPxy6W6UICoib jMgosrpmbUMARo7oB4j5Y/L7fKOMC2/rwcRNRHskLNRuyjU+TvQEbBnUPqRcyF6QX+ LFJP/OHlFUC/gyYLaxMpO/QN538pOTokHfuWew4niG3SEXMay0jMiS9RtTwMcn9dpu g5yZvpRD67txmc2U/b4rM5eA6/7uP9Wm/QaHUK5r0RSueqfVsLj6zgcsUjTIbIFP0s jEux23gWF92XA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:48 +0100 Subject: [PATCH v13 21/32] 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: <20260720-kvm-arm64-sme-v13-21-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=7564; i=broonie@kernel.org; h=from:subject:message-id; bh=cYBJzWXUlFEk0NCpM7UpFBgugRQeF0dNkZ0uZU3Aefg=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk3tB8szMB9+eqVoV3/1i6IZy25QvXGAvukL R+8AAH4gCKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZNwAKCRAk1otyXVSH 0Jg+B/wMjCKDiE34S79TmLVqvdR3dnQUw+kJoRpDcGqW636f5wXtrcYe2m7WBsTWseCKIqDOfWy 0G13ignCjEElwKDxdGJpqfQQzmERzuO2qt7E+QjK9+2Zd0hro9ORJJTs7neqf0Dv4mFZl7BcrYF LwAmKcSX6kJ1FKhDE9edMvxmFo86EczWE2tvEN0gPE1MocZy8yek62z1+OTn06X/DZQ60hMdauo Jk28JSXs0MW0aoNsN0RHktmRUtJ+Tq5ZPOOgDgHdGZ5jf4JHZiAf+ua2397N0MCXNV6K0Rw38RH URjN+kEElaj8pUfQ5ePfeXe1KIwF/er4i4fVGvG5oVwTH9RQ 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 with no storage allocated and enable fine grained traps for SMPRI_EL1 to ensure that guests can't write to it even if the hardware supports priorities. Since the register should be readable with fixed contents we only trap writes, not reads. Since there is no host support for using priorities the register currently left with a value of 0 by the host so we do not need to update the value for guests. There is also an EL2 register SMPRIMAP_EL2 for virtualisation of priorities which is VNCR mapped, this is RES0 when priority configuration is not supported but has no register specific traps available. When saving state from a nested guest we overwrite any value the guest stored. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 5 +++++ arch/arm64/include/asm/vncr_mapping.h | 1 + arch/arm64/kvm/config.c | 7 +++++-- arch/arm64/kvm/hyp/vhe/sysreg-sr.c | 7 +++++++ arch/arm64/kvm/nested.c | 7 +++++++ arch/arm64/kvm/sys_regs.c | 25 ++++++++++++++++++++++++- 6 files changed, 49 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index e8c2907aacd2..6574c286f50f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -558,6 +558,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 */ @@ -1691,6 +1692,10 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64= val); (system_supports_sme2() && \ kvm_has_feat((k), ID_AA64PFR1_EL1, SME, SME2)) =20 +#define kvm_has_smps(k) \ + (kvm_has_sme(k) && \ + (kvm_read_vm_id_reg(k, SYS_SMIDR_EL1) & SMIDR_EL1_SMPS)) + #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)) diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm= /vncr_mapping.h index c3bf92ac52d4..f6152fbbfe03 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 0x1F8 #define VNCR_TTBR0_EL1 0x200 #define VNCR_TTBR1_EL1 0x210 #define VNCR_FAR_EL1 0x220 diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c index cb6f3ea556c2..bc7f29a48399 100644 --- a/arch/arm64/kvm/config.c +++ b/arch/arm64/kvm/config.c @@ -281,8 +281,7 @@ static bool feat_anerr(struct kvm *kvm) =20 static bool feat_sme_smps(struct kvm *kvm) { - return (kvm_has_feat(kvm, FEAT_SME) && - (kvm_read_vm_id_reg(kvm, SYS_SMIDR_EL1) & SMIDR_EL1_SMPS)); + return kvm_has_smps(kvm); } =20 static bool feat_spe_fds(struct kvm *kvm) @@ -1677,6 +1676,10 @@ static void __compute_hfgwtr(struct kvm_vcpu *vcpu) =20 if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) *vcpu_fgt(vcpu, HFGWTR_EL2) |=3D HFGWTR_EL2_TCR_EL1; + + /* Emulate RES0 for SMPRI_EL1 until we support priorities */ + if (cpus_have_final_cap(ARM64_SME)) + *vcpu_fgt(vcpu, HFGWTR_EL2) &=3D ~HFGWTR_EL2_nSMPRI_EL1; } =20 static void __compute_hdfgwtr(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sy= sreg-sr.c index be685b63e8cf..0fe7153eab08 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/nested.c b/arch/arm64/kvm/nested.c index 50e25ab9b604..7de9b7f8f90a 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -1925,6 +1925,13 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu) resx.res1 =3D SMCR_ELx_RES1; set_sysreg_masks(kvm, SMCR_EL2, resx); =20 + /* SMPRMAP_EL2 - RES0 with SME but without priority mapping */ + if (!kvm_has_smps(kvm)) { + resx.res0 =3D GENMASK_ULL(63, 0); + resx.res1 =3D 0; + set_sysreg_masks(kvm, SMPRIMAP_EL2, resx); + } + out: for (enum vcpu_sysreg sr =3D __SANITISED_REG_START__; sr < NR_SYS_REGS; s= r++) __vcpu_rmw_sys_reg(vcpu, sr, |=3D, 0); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 9a993e76da18..827502e3249a 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -779,6 +779,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 @@ -2054,6 +2063,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)) @@ -3450,7 +3468,10 @@ 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 }, + + { SYS_DESC(SYS_SMPRI_EL1), .access =3D trap_raz_wi, .set_user =3D set_res= 0, + .get_user =3D get_raz_reg, .val =3D 0, .visibility =3D sme_raz_visibili= ty }, + { 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 }, @@ -3827,6 +3848,8 @@ static const struct sys_reg_desc sys_reg_descs[] =3D { =20 EL2_REG_VNCR(HCRX_EL2, reset_val, 0), =20 + EL2_REG_FILTERED(SMPRIMAP_EL2, access_rw, reset_val, 0, + sme_el2_visibility), EL2_REG_FILTERED(SMCR_EL2, access_smcr_el2, reset_val, 0, sme_el2_visibility), =20 --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 E333A38944D; Sun, 19 Jul 2026 23:11:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502694; cv=none; b=QPtVAZOT5ibIRCnKJ1P1rOHUiTpfoMZdJe7CSQAkbCJ9FQ+ubiNLVzdVZ6RvbHBE3IrjjnMC/T0t/ztJvs5E18EnVrqHL6+6d1o80X/hc6SciH/7NBE4RrmYPisasLEasl4ZBoXhOQwrIlvjMn7dLw6p0B0PkKUKVa6DOKJSO+8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502694; c=relaxed/simple; bh=tF/rTI6kXtiaueeuMEdKDBM0umIPPyuiK559017fv78=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=S8wI+dbqbKL8QJmTd7NY9gsdtXixCedXt+MjiF+s+jmSxQpX1fjHouv7t7V8SyGnf3eW+c8qxrMz2Yq8LrS8SstlYMEEFdCaZ52S3hquAuq0evHiVMn78O13bBuj570+S6IABSis3BBZ/1qGYHUDNEZF4VaEjEhdcmVENHzv4/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eNRvKHFw; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eNRvKHFw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E29CC1F00A3D; Sun, 19 Jul 2026 23:11:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502692; bh=09GSqoIFH97qhBcTcWix53S4U0RqlEqjOFCeSslb6OA=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=eNRvKHFwdAyLQU9GTKrLNzoZmjWpffh1MAcH2esJfruW5N7bDD0k38zDey5j6y4A6 ogDuekcugkH/oObOEOXcK4rru6my/LS+oJG34St+Sbmc0/Jn0EwtNL3A//mcrCmE1B FYpcnOam2wrFOsIFhw07UJsZoeYOLjl1bQXIDTrSyzQWWVsCMekKZE2TDaIFBPePId me9+UVDq4NYsAag15A5IOoUtUwdAF/8ERXTb0l9wz1r775GXjSPIUGGHtB2sD0LnTK auBY/m1snXBxsgo/EXHf76gQEqBbsvU8YBQurroDnLQnHFxJD5Bn9pvxLATweSj7gk 82hE/rVbvNMCA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:49 +0100 Subject: [PATCH v13 22/32] 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: <20260720-kvm-arm64-sme-v13-22-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=6944; i=broonie@kernel.org; h=from:subject:message-id; bh=tF/rTI6kXtiaueeuMEdKDBM0umIPPyuiK559017fv78=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk4dNeNxf5g+4y7GoMNNlqNIh88nlaLMWtSi cmDLNynEciJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZOAAKCRAk1otyXVSH 0OTKB/wIkLqIsYRjKDq3CwdlRnqFJjOegFm+1z5GvN0+rKB/1gL8im51tu9wMnpmOXKLEPV+3bU OOLXiSA0O6EAImE5iPu0h0zQbi2PlHAtbkQEgwYV4w+1vonanODY2BNt2xJTL9KGzG+XPv5XYdf d2rGBvhWYtB/Kuul8qolm1Qu3/pEvPngwdvgpoRYzQ9mqT0EYwHy03RrrN2mTIUG27z0WYzqAjD 44v+XM25vj5n0/rt7PuEVpUKE/4h3QCAzN5KlmUeBNKX39pMXim7zss3xiztr1nCQY5RwwHpkxx Q6TvXJRdj2inNQIeyvHvI9gP9JyzQG2J1tlDEdKI489ALAfB 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. Since this makes the set of registers that are visible depend on the current state of the vCPU also add processing of PSCI reset requests to register enumeration similarly to register reads and writes. Signed-off-by: Mark Brown --- arch/arm64/kvm/arm.c | 9 ++++++ arch/arm64/kvm/guest.c | 83 +++++++++++++++++++++++++++++++++++++++-------= ---- 2 files changed, 74 insertions(+), 18 deletions(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 50adfff75be8..d43cfdcaee64 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -1882,6 +1882,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp, r =3D -EFAULT; if (copy_from_user(®_list, user_list, sizeof(reg_list))) break; + + /* + * We could owe a reset due to PSCI. Handle the pending reset + * here since for SME the set of registers varies depending + * on vCPU state. + */ + if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu)) + kvm_reset_vcpu(vcpu); + n =3D reg_list.n; reg_list.n =3D kvm_arm_num_regs(vcpu); if (copy_to_user(user_list, ®_list, sizeof(reg_list))) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 48e6b500f531..110cc7f7527a 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -73,6 +73,19 @@ 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 bool vcpu_ffr_enabled(const struct kvm_vcpu *vcpu) +{ + if (vcpu_in_streaming_mode(vcpu)) + return vcpu_has_fa64(vcpu); + else + return vcpu_has_sve(vcpu); +} + static int core_reg_size_from_offset(const struct kvm_vcpu *vcpu, u64 off) { int size; @@ -110,9 +123,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; @@ -423,6 +437,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 @@ -460,20 +492,25 @@ static int sve_reg_to_region(struct vec_state_reg_reg= ion *region, reg_num =3D (reg->id & SVE_REG_ID_MASK) >> SVE_REG_ID_SHIFT; =20 if (reg->id >=3D zreg_id_min && reg->id <=3D zreg_id_max) { - if (!vcpu_has_sve(vcpu) || (reg->id & SVE_REG_SLICE_MASK) > 0) + if (!vcpu_has_sve_regs(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; reqlen =3D KVM_SVE_ZREG_SIZE; maxlen =3D SVE_SIG_ZREG_SIZE(vq); } else if (reg->id >=3D preg_id_min && reg->id <=3D preg_id_max) { - if (!vcpu_has_sve(vcpu) || (reg->id & SVE_REG_SLICE_MASK) > 0) + if (!vcpu_has_sve_regs(vcpu) || (reg->id & SVE_REG_SLICE_MASK) > 0) return -ENOENT; =20 - vq =3D vcpu_sve_max_vq(vcpu); + if (!vcpu_ffr_enabled(vcpu) && + (reg->id >=3D KVM_REG_ARM64_SVE_FFR(0)) && + (reg->id <=3D KVM_REG_ARM64_SVE_FFR(SVE_NUM_SLICES - 1))) + return -ENOENT; + + vq =3D vcpu_sve_cur_vq(vcpu); =20 reqoffset =3D SVE_SIG_PREG_OFFSET(vq, reg_num) - SVE_SIG_REGS_OFFSET; @@ -640,15 +677,21 @@ static unsigned long num_core_regs(const struct kvm_v= cpu *vcpu) static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu) { const unsigned int slices =3D vcpu_sve_slices(vcpu); + int regs, ret; =20 - if (!vcpu_has_sve(vcpu)) + if (!vcpu_has_sve(vcpu) && !vcpu_in_streaming_mode(vcpu)) return 0; =20 /* Policed by KVM_GET_REG_LIST: */ 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 */ + regs =3D SVE_NUM_PREGS + SVE_NUM_ZREGS; + if (vcpu_ffr_enabled(vcpu)) + regs++; /* FFR */ + ret =3D regs * slices; + if (vcpu_has_sve(vcpu)) + ret++; /* KVM_REG_ARM64_SVE_VLS */ + return ret; } =20 static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, @@ -659,7 +702,7 @@ static int copy_sve_reg_indices(const struct kvm_vcpu *= vcpu, unsigned int i, n; int num_regs =3D 0; =20 - if (!vcpu_has_sve(vcpu)) + if (!vcpu_has_sve_regs(vcpu)) return 0; =20 /* Policed by KVM_GET_REG_LIST: */ @@ -669,10 +712,12 @@ static int copy_sve_reg_indices(const struct kvm_vcpu= *vcpu, * Enumerate this first, so that userspace can save/restore in * the order reported by KVM_GET_REG_LIST: */ - reg =3D KVM_REG_ARM64_SVE_VLS; - if (put_user(reg, uindices++)) - return -EFAULT; - ++num_regs; + if (vcpu_has_sve(vcpu)) { + reg =3D KVM_REG_ARM64_SVE_VLS; + if (put_user(reg, uindices++)) + return -EFAULT; + ++num_regs; + } =20 for (i =3D 0; i < slices; i++) { for (n =3D 0; n < SVE_NUM_ZREGS; n++) { @@ -689,10 +734,12 @@ static int copy_sve_reg_indices(const struct kvm_vcpu= *vcpu, num_regs++; } =20 - reg =3D KVM_REG_ARM64_SVE_FFR(i); - if (put_user(reg, uindices++)) - return -EFAULT; - num_regs++; + if (vcpu_ffr_enabled(vcpu)) { + reg =3D KVM_REG_ARM64_SVE_FFR(i); + if (put_user(reg, uindices++)) + return -EFAULT; + num_regs++; + } } =20 return num_regs; --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 998C3383985; Sun, 19 Jul 2026 23:11:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502698; cv=none; b=dhqbtS4a4bgiwOT6mb6m5Fu4kJGTvWeyyiWRwfWjpcWwEo9d41JWvRtkbIUGKzv40+ofbcAJTAY8bfuXDAmU/47AT4P/PIqwBnYj6RpxFiHWrVpFuu3v2fDEgUl4ROn/oL4w61oYwe4nyCwT1U7Nz2uc62VsLQ+8J7LD5QlYkvQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502698; c=relaxed/simple; bh=smeCg9dfluu2jVyRmyUbJ43Gu0kVuoH5Oy7fiw1EXQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=E7yGXbKby/4EDh5815NZd8mSBh/6XzKf2xTfoS4Lo3E3arFwriPl78jIUn0aPREVho/kN2jS/aFlB/k4M7PXBqvFl12Vo6/1FI8UVGD5WMPIBUWTrB8BVu54at8sduOSFCTT6GPo/qZ9q4ruTmDG8nBymP+mMU12HfBT8r4mZNw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QXjNmfdf; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QXjNmfdf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3BC031F000E9; Sun, 19 Jul 2026 23:11:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502697; bh=qUAiHFykeyeMsRtI4ws0Xq5TjSptXUqvEwAkGiCNvkk=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=QXjNmfdfgkaJSkKACm5jsdjjXy5ZCspvzkirk4wS2bJ6vY1WGL9qpeY/ERnlw0vJb eRyHdLeiSG7XA391xkzdQsaizXmFuJHmsZuuPujG5j0QjWGg/twaoWXe4PaJ7UOCz4 Zqihx1mbgDCDXu6BJOUCjV5+hI3hMD6/fDLPkYOoDVRz9l4xKzFBwOj7sojSYBn+2Z vxvkmcoLCYWoQT/QIxYPNgTL2Gb1QQ1Vvcoq+OmdoRLwjig1YShlybeu9HBvN23MbF s0gZqwvZnYufBo4pe74JFwMyLlbaEFQQvEkdsBcv8nlNMdVb3ctGP9htnBT5bhfcjI YNh5ZEogsRv7Q== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:50 +0100 Subject: [PATCH v13 23/32] 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: <20260720-kvm-arm64-sme-v13-23-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=5357; i=broonie@kernel.org; h=from:subject:message-id; bh=smeCg9dfluu2jVyRmyUbJ43Gu0kVuoH5Oy7fiw1EXQo=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk5wf74d/IyOURWeDScGlye099xAOyqga6nC rd0mqvnRgKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZOQAKCRAk1otyXVSH 0LdgB/wKfySzR7bDqvc9GDdBMRSKvPtBCTyfrmOMokjcmeifSfGfqtB3qoU1UOQ9js9uxIWYF9m AJmx7XS8RWvEeOqnB8AflYFTIdQmjRuRzlX/qggd1pV4f/lroHAkgLcOXuxPr/sybWJQ1a6IKom 2V/XxQ2uLAmpucG/UKeOYLfJsWjpX6iNB6Un669hrTNJ5G9DgD9yp6WS8YcruiA8U+l29DOM3gu YWFd/yP/hwuCThBUVDSoV/1UjOM2+O+mqU/2jk4IHCUUrK0YLIWLOLk+YDDTS1VFgKULOx/kxqw CYUxRnoZw0mcryGPiEGCCqY38s8Wkp70wiz93ss/Y9qP0vmI 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 inaccessib= le 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. Rather than introduce a requirement that the vector configuration be finalised before writing to SVCR we check for this before updating the SVE and SME specific state, when finalisation happens they will be allocated with an initial state of 0. Similarly in order to avoid ordering requirements between finalisation and writes to the ID registers we always allocate space for ZT0 if the hardware supports it, this is 512 bits per vCPU. The overwhelming majority of practical systems with SME are expected to want use SME2, there is very little practical reason to disable it other than for feature testing, and the additional complexity seems more likely to lead to bugs than deliver practical benefits. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 28 ++++++++++++++++++++++++++++ arch/arm64/include/asm/sysreg.h | 2 ++ arch/arm64/kvm/sys_regs.c | 30 +++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 6574c286f50f..cafc43776ac3 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1142,6 +1142,34 @@ struct kvm_vcpu_arch { =20 #define vcpu_sve_state_size(vcpu) sve_state_size_from_vl(vcpu_sve_max_vl(v= cpu)) =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_BYTES; \ + } \ + \ + __size_ret; \ +}) + +/* + * Always provide space for ZT0 to avoid ordering requirements with ID + * register writes and vector finalization. + */ +#define vcpu_sme_state_size(vcpu) ({ \ + unsigned long __vl; \ + __vl =3D (vcpu)->arch.max_vl[ARM64_VEC_SME]; \ + sme_state_size_from_vl(__vl, system_supports_sme2()); \ +}) + #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \ KVM_GUESTDBG_USE_SW_BP | \ KVM_GUESTDBG_USE_HW | \ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysre= g.h index 4b96449e0ffa..b434320de1a7 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -1108,6 +1108,8 @@ #define gicr_insn(insn) read_sysreg_s(GICV5_OP_GICR_##insn) #define gic_insn(v, insn) write_sysreg_s(v, GICV5_OP_GIC_##insn) =20 +#define FPSR_RESET_VALUE 0x800009f + #ifdef __ASSEMBLER__ =20 .macro mrs_s, rt, sreg diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 827502e3249a..f55a8d65cfc2 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1015,6 +1015,34 @@ static unsigned int hidden_visibility(const struct k= vm_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) && + kvm_arm_vcpu_vec_finalized(vcpu)) + 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 (kvm_arm_vcpu_vec_finalized(vcpu)) + 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 FPSR_RESET_VALUE; + } + + __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) { @@ -3616,7 +3644,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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 C2C69381B15; Sun, 19 Jul 2026 23:11:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502703; cv=none; b=Im01xFwJwt56c+4p3hTTZz5UWv/dAbP3Bj0UE14K1nBn2brZw/i9iy4zvRDv+2dFG2MYGqexdkqEb6s3ALRyBjnXijbVouZyJ5eymuJ2KeNRcvdaHvn3KACsH6FoPmgIz/+If7JeI5FEObbLaFEmcVdE0CPHToe2VrS7WnB0meI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502703; c=relaxed/simple; bh=OWLQ+fStXa0u76ZwF0nDRlLR1/mZJ3iEmSPjs0EDopk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Lij5N9da+pFjOpG2uG4yoF3O22AHqoTH2Fl3QOd0FAwvFaY7QLkpMMxGhguGIpdaYmHRA6nExBmefnELqpqNVDFA7V0INNVOLh90OURlHXHytI7z/Hrz3ZeRKfGKx6V2HXAxU9X7P5rCSGoZgF6vdL9Fc5P/RAX+chzHT6ckypA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OGKZQoaU; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OGKZQoaU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8D5D11F00A3A; Sun, 19 Jul 2026 23:11:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502701; bh=cQTVOv3doodlzyRyF79rD7oVUshuooj7eTaIdQCTKvI=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=OGKZQoaUep5d5TFU6XJxsr1haz5wvHczP9UeXDlM+vSfVWIiTQUmoi6+oj2KHTByn cJRljvUSxNQg2/US09cLUSIi6jz5dZJOpcdGmTWytRsn4vZuG/zva6VZL2lZnUm7Q0 J+9wGpnpPpEj0IyN5eCX0JIlSxbfIINYVSaWTieiQ13rZPkSLnvsDXH8pqLpJwEsDd gzgHyO4/xm2qLqKtVqV0LsOjgNJB9MRmXil9tIMaqplOchIYMm4gPJKnOTvm3Ubynx HBGowHclKwDEONT6zZ2BExOkc0hc/2Ojx1ndZEk0/boREE5ffPIM1SAvYkTh++ZL2p RD4KbLA88TkzQ== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:51 +0100 Subject: [PATCH v13 24/32] 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: <20260720-kvm-arm64-sme-v13-24-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=9460; i=broonie@kernel.org; h=from:subject:message-id; bh=OWLQ+fStXa0u76ZwF0nDRlLR1/mZJ3iEmSPjs0EDopk=; b=owGbwMvMwMWocq27KDak/QLjabUkhqzYSKuKX4mN7Hp3J/55oHO4bJFJzMq+IOe5k+bY90/8y mbGtEask9GYhYGRi0FWTJFl7bOMVenhElvnP5r/CmYQKxPIFAYuTgGYiKAY+185b1cJy6bYpUeX 3zx5iW3GA+WFUeI771q/3Fk/70PXFXZu94kO3Ep62uU6Kz+eTHU+evGNgFSLifgp496kX1ed5iV WV8u9XM8foP3l6kPBB2cM/yqo2ylH8nwJMNvGu0GOj+s364Nd8bF+ocmJUdPevHzEGMP6j+U1yz qGg37m56OuGu5h233HuTGi70FKgHq+gmHsirdvLZqfr3iakiotGlHe3Xbzu2TTBwHrRev/V7B5M c56pKH2deN81t6Dna6/qha6PmayfaXKr5p1RuCmpPlnQ6vMR0d1TfiSuXJYoh97dKjcK7zHm1R0 7IN8ss5Zy2//m+UtHfgbm8w86uPFg/uMIj1VdCeF5bwEAA== 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 is done in the architecture for both ZA and ZT0 the value will be reset to 0 whenever PSTATE.ZA changes from 0 to 1 and the registers are inaccessible when PSTATE.ZA is 0. 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 | 20 ++++ arch/arm64/kvm/guest.c | 186 ++++++++++++++++++++++++++++++++++= +++- 2 files changed, 204 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/as= m/kvm.h index 15d53300914b..deccb034fce3 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -357,6 +357,26 @@ 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 16 + +/* 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) +#define KVM_REG_ARM64_SME_ZTREG(n) \ + (KVM_REG_ARM64 | KVM_REG_ARM64_SME | KVM_REG_ARM64_SME_ZT_BASE | \ + KVM_REG_SIZE_U512 | (n)) + /* Vector lengths pseudo-register: */ #define KVM_REG_ARM64_SME_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SME | \ KVM_REG_SIZE_U512 | 0xfffe) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 110cc7f7527a..1b85f0383628 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -598,22 +598,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 +#define ZAH_REG_SLICE_SHIFT 0 +#define ZAH_REG_SLICE_BITS 5 +#define ZAH_REG_ID_SHIFT (ZAH_REG_SLICE_SHIFT + ZAH_REG_SLICE_BITS) +#define ZAH_REG_ID_BITS 8 + +#define ZAH_REG_SLICE_MASK \ + GENMASK(ZAH_REG_SLICE_SHIFT + ZAH_REG_SLICE_BITS - 1, \ + ZAH_REG_SLICE_SHIFT) +#define ZAH_REG_ID_MASK \ + GENMASK(ZAH_REG_ID_SHIFT + ZAH_REG_ID_BITS - 1, ZAH_REG_ID_SHIFT) + +/* + * Validate SME register ID and get sanitised bounds for user/kernel SME + * 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); + 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 & ZAH_REG_ID_MASK) >> ZAH_REG_ID_SHIFT; + + if (reg->id >=3D zah_id_min && reg->id <=3D zah_id_max) { + if (!vcpu_has_sme(vcpu) || (reg->id & ZAH_REG_SLICE_MASK) > 0) + return -ENOENT; + + if (!vcpu_za_enabled(vcpu)) + return -EBUSY; + + /* 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_ZTREG(0)) { + if (!kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SME, SME2)) + return -ENOENT; + + if (!vcpu_za_enabled(vcpu)) + return -EBUSY; + + /* ZT0 is stored after ZA */ + reqoffset =3D ZA_SIG_REGS_SIZE(vq); + 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; + + if (copy_to_user(uptr, (void *)vcpu->arch.sme_state + region.koffset, + region.klen) || + clear_user(uptr + region.klen, region.upad)) + 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; + + if (copy_from_user((void *)vcpu->arch.sme_state + region.koffset, uptr, + region.klen)) + return -EFAULT; + + return 0; } =20 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *r= egs) @@ -694,6 +805,27 @@ static unsigned long num_sve_regs(const struct kvm_vcp= u *vcpu) return ret; } =20 +static unsigned long num_sme_regs(const struct kvm_vcpu *vcpu) +{ + const unsigned int slices =3D vcpu_sve_slices(vcpu); + int regs; + + if (!vcpu_has_sme(vcpu)) + return 0; + + /* Policed by KVM_GET_REG_LIST: */ + WARN_ON(!kvm_arm_vcpu_vec_finalized(vcpu)); + + /* KVM_REG_ARM64_SME_VLS */ + regs =3D 1; + + /* ZA, and ZT0 if SME2 */ + if (vcpu_za_enabled(vcpu)) + regs +=3D (slices * vcpu_sme_max_vl(vcpu)) + vcpu_has_sme2(vcpu); + + return regs; +} + static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user *uindices) { @@ -745,6 +877,50 @@ static int copy_sve_reg_indices(const struct kvm_vcpu = *vcpu, return num_regs; } =20 +static int copy_sme_reg_indices(const struct kvm_vcpu *vcpu, + u64 __user *uindices) +{ + const unsigned int slices =3D vcpu_sve_slices(vcpu); + u64 reg; + unsigned int i, n; + int num_regs =3D 0; + + if (!vcpu_has_sme(vcpu)) + return 0; + + /* Policed by KVM_GET_REG_LIST: */ + WARN_ON(!kvm_arm_vcpu_vec_finalized(vcpu)); + + /* + * Enumerate this first, so that userspace can save/restore in + * the order reported by KVM_GET_REG_LIST: + */ + reg =3D KVM_REG_ARM64_SME_VLS; + if (put_user(reg, uindices++)) + return -EFAULT; + ++num_regs; + + if (vcpu_za_enabled(vcpu)) { + for (i =3D 0; i < slices; i++) { + for (n =3D 0; n < vcpu_sme_max_vl(vcpu); n++) { + reg =3D KVM_REG_ARM64_SME_ZAHREG(n, i); + if (put_user(reg, uindices++)) + return -EFAULT; + num_regs++; + } + } + + if (vcpu_has_sme2(vcpu)) { + reg =3D KVM_REG_ARM64_SME_ZTREG(0); + if (put_user(reg, uindices++)) + return -EFAULT; + num_regs++; + } + } + + return num_regs; +} + /** * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG * @vcpu: the vCPU pointer @@ -757,6 +933,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu) =20 res +=3D num_core_regs(vcpu); res +=3D num_sve_regs(vcpu); + res +=3D num_sme_regs(vcpu); res +=3D kvm_arm_num_sys_reg_descs(vcpu); res +=3D kvm_arm_get_fw_num_regs(vcpu); =20 @@ -784,6 +961,11 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u6= 4 __user *uindices) return ret; uindices +=3D ret; =20 + ret =3D copy_sme_reg_indices(vcpu, uindices); + if (ret < 0) + return ret; + uindices +=3D ret; + ret =3D kvm_arm_copy_fw_reg_indices(vcpu, uindices); if (ret < 0) return ret; --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 1916238E8CE; Sun, 19 Jul 2026 23:11:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502707; cv=none; b=s0LN5XV0cFDJd8Qd1Q77OjqfJjuTxZmghbJp5W8XYV2oUEAPima1RvnqblPrmF1IwlGFRjN5wTZR7/Vln49/gp7uryrZYLu4KIIN1eEN5qOGW0vQSiAHWbnToJ0YuFaEnvvT168LOdIdGj6QLOH9iYD3GO+y9lWyI4GfIguZyJc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502707; c=relaxed/simple; bh=V9lhbJTygqd7i1P+aMU/FsUCdWItdRpf+EOnavENZ1I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ApiWsXEYnydFxRsCSBMk9MWpUmzd1UyTXnmwh2WjuhtXyoRvr1mjYJ6e91i2vPVvUIlV4ymQlnwKRa7aol7QtrNVYm4Kv/jxc/Lapcw/nHYK0DdoO3zOqfHCZ2lyo4dtjKIZUW7wlBL/lYobg7dNz/POIxiltMcAJAYnMF0wvJw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aVIDhyNP; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aVIDhyNP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E06C61F00A3D; Sun, 19 Jul 2026 23:11:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502705; bh=HghW6M6niObkOasBxAde9LGFXC86Em82YvIc/IyzCPs=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=aVIDhyNPcoEfrgRwi7a6blEvdPumF5cziPxbLsjuFPPS7XqyMWFSozvY0vSXDHYqy J7/u1p26XkuKLTD6Gj2lNkJcHI9RvKjemEer8uR4jqqE06J41yjjZHXIvtm8/uHAaV ckZ7FlZkar5YrV3yAc+QTU3D0iibKsAW1f9KshPZrqQvmCg85x28xceO1usMzCpTGr suyUt4SWlRy+OeHOCQeUfVjL39PVjOxbJxbnix5W9FpT/+MSYfkXViNJxN40gzBkJQ 6jbL/jna0x909pPw5Q7vME/d1TP0covA8D4T1HAHTZlCeVJ2kt4J/Uww/1RZc2XDDC X45TQKbV4qx7w== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:52 +0100 Subject: [PATCH v13 25/32] 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: <20260720-kvm-arm64-sme-v13-25-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=21393; i=broonie@kernel.org; h=from:subject:message-id; bh=V9lhbJTygqd7i1P+aMU/FsUCdWItdRpf+EOnavENZ1I=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk6UIbKMeC2EnUMs1R0vvu6Hesy+s/5Ne3IR 51v8U/nSPOJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZOgAKCRAk1otyXVSH 0FU/B/4lfINIS2dtgabwnUxtIU68UrpB1kjI+bhtm4WLWOPnX9heM/R/LlABWiJcTlewmN8Hr4L JwV8Ao8iQeoUTZ1jgvkEsgb/nJQDJZaNACbo66suZaEXDoF+G/YgvDyxLB+cHlbnHIzUB2jHJwg tvwDuk2j5QlpgWZEtPOkDxB4WlNhotbif6s5+kGu/OzlMnU92lh1o9PTSouE23J2kRTpVXcjo5n 5TcDJ330YMaRGRgcMEjSdTQFvdAk76H+nAzGde5KLA0bjhFiIDXA7vZLIdcdaX2mOXA1KiVgCgB V8HGJPZN8HRHD62SEw8yxqMgSndtNXkSRfh1RynXlHpcNE0I 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. For nested guests we also need to forward exceptions generated as the result of SMCR_EL2.EZT0 being disabled in the guest. 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. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 25 ++-- arch/arm64/kvm/fpsimd.c | 26 ++++- arch/arm64/kvm/hyp/include/hyp/switch.h | 197 ++++++++++++++++++++++++++++= ++-- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 131 ++++++++++++++++++--- 4 files changed, 337 insertions(+), 42 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index cafc43776ac3..7ebe7b6cc96e 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1126,6 +1126,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; \ @@ -1140,10 +1143,20 @@ struct kvm_vcpu_arch { __size_ret; \ }) =20 -#define vcpu_sve_state_size(vcpu) sve_state_size_from_vl(vcpu_sve_max_vl(v= cpu)) +#define vcpu_sve_state_size(vcpu) sve_state_size_from_vl(vcpu_max_vl(vcpu)) =20 #define vcpu_sme_state(vcpu) (kern_hyp_va((vcpu)->arch.sme_state)) =20 +/* + * Always provide space for ZT0 to avoid ordering requirements with ID + * register writes and vector finalization. + */ +#define vcpu_sme_state_size(vcpu) ({ \ + unsigned long __vl; \ + __vl =3D (vcpu)->arch.max_vl[ARM64_VEC_SME]; \ + sme_state_size_from_vl(__vl, system_supports_sme2()); \ +}) + #define sme_state_size_from_vl(vl, sme2) ({ \ size_t __size_ret; \ unsigned int __vq; \ @@ -1160,16 +1173,6 @@ struct kvm_vcpu_arch { __size_ret; \ }) =20 -/* - * Always provide space for ZT0 to avoid ordering requirements with ID - * register writes and vector finalization. - */ -#define vcpu_sme_state_size(vcpu) ({ \ - unsigned long __vl; \ - __vl =3D (vcpu)->arch.max_vl[ARM64_VEC_SME]; \ - sme_state_size_from_vl(__vl, system_supports_sme2()); \ -}) - #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \ KVM_GUESTDBG_USE_SW_BP | \ KVM_GUESTDBG_USE_HW | \ diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 567dd43970c5..bb0bf8d81522 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -83,19 +83,24 @@ 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.zcr =3D vcpu_sve_max_vq(vcpu) - 1; - fp_state.smcr =3D 0; - fp_state.sme_state =3D NULL; + fp_state.smcr =3D vcpu_sme_max_vq(vcpu) - 1; + fp_state.sme_state =3D vcpu->arch.sme_state; 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; =20 + if (kvm_has_fa64(vcpu->kvm)) + fp_state.smcr |=3D SMCR_ELx_FA64; + if (kvm_has_sme2(vcpu->kvm)) + fp_state.smcr |=3D SMCR_ELx_EZT0; + + /* + * For SME only guests 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 @@ -104,6 +109,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 ce586110c226..2eabffb640e9 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -462,6 +462,44 @@ static inline bool kvm_hyp_handle_mops(struct kvm_vcpu= *vcpu, u64 *exit_code) return true; } =20 +/* The SMCR_EL2 for non-nested guests */ +static inline u64 __hyp_smcr_el2(struct kvm_vcpu *vcpu) +{ + u64 smcr_el2; + + /* + * The vCPU's saved SVE state layout always matches the max VL of the + * vCPU. + */ + 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; + + return smcr_el2; +} + +static inline void __hyp_sme_restore_guest(struct kvm_vcpu *vcpu, + bool *restore_sve, + bool *restore_ffr) +{ + /* EZT0 and FA64 are not self synchronizing */ + sysreg_cond_update_s(SYS_SMCR_EL2, __hyp_smcr_el2(vcpu)); + isb(); + + if (vcpu_in_streaming_mode(vcpu)) { + *restore_sve =3D true; + *restore_ffr =3D vcpu_has_fa64(vcpu); + } + + if (vcpu_za_enabled(vcpu)) + sme_load_state(kern_hyp_va(vcpu->arch.sme_state), + vcpu_has_sme2(vcpu)); + + write_sysreg_el1(__vcpu_sys_reg(vcpu, vcpu_sme_smcr_elx(vcpu)), SYS_SMCR); +} + static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu) { u64 zcr_el2 =3D vcpu_sve_max_vq(vcpu) - 1; @@ -471,20 +509,45 @@ 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(zcr_el2, SYS_ZCR_EL2); - sve_load_state(kern_hyp_va(vcpu->arch.sve_state), true); - fpsimd_load_common(&vcpu->arch.ctxt.fp_regs); + write_sysreg_el1(__vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)), SYS_ZCR); +} + +static inline u64 __hyp_smcr_el2_nested(struct kvm_vcpu *vcpu) +{ + u64 max_len =3D vcpu_sme_max_vq(vcpu) - 1; + u64 smcr_el2 =3D SYS_FIELD_GET(SMCR_ELx, LEN, + __vcpu_sys_reg(vcpu, SMCR_EL2)); + + smcr_el2 =3D min(max_len, smcr_el2); + + if (vcpu_has_fa64(vcpu)) + smcr_el2 |=3D __vcpu_sys_reg(vcpu, SMCR_EL2) & SMCR_ELx_FA64; + if (vcpu_has_sme2(vcpu)) + smcr_el2 |=3D __vcpu_sys_reg(vcpu, SMCR_EL2) & SMCR_ELx_EZT0; + + return smcr_el2; +} + +static inline void __hyp_nv_restore_guest_vls(struct kvm_vcpu *vcpu) +{ + if (!is_nested_ctxt(vcpu)) + return; =20 /* * 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 (vcpu_has_sve(vcpu)) { + u64 zcr_el2 =3D vcpu_sve_max_vq(vcpu) - 1; + zcr_el2 =3D min(zcr_el2, __vcpu_sys_reg(vcpu, ZCR_EL2)); sve_cond_update_zcr_vq(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)) + sysreg_cond_update_s(SYS_SMCR_EL2, __hyp_smcr_el2_nested(vcpu)); } =20 static inline void __hyp_sve_save_host(void) @@ -498,10 +561,38 @@ static inline void __hyp_sve_save_host(void) fpsimd_save_common(&hctxt->fp_regs); } =20 +static inline void kvm_sme_configure_traps(struct kvm_vcpu *vcpu) +{ + u64 smcr_el1, smcr_el2, svcr; + + if (!vcpu_has_sme(vcpu)) + return; + + if (is_nested_ctxt(vcpu)) + smcr_el2 =3D __hyp_smcr_el2_nested(vcpu); + else + smcr_el2 =3D __hyp_smcr_el2(vcpu); + sysreg_cond_update_s(SYS_SMCR_EL2, smcr_el2); + + 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 + /* + * We always load the SME control registers that affect traps + * since if they are not configured as expected by the guest + * then it may have exceptions that it does not expect + * directly delivered. + */ + kvm_sme_configure_traps(vcpu); + if (!guest_owns_fp_regs()) return; =20 @@ -555,8 +646,59 @@ static inline void sve_lazy_switch_to_host(struct kvm_= vcpu *vcpu) } } =20 +static inline void sme_lazy_switch_to_host(struct kvm_vcpu *vcpu) +{ + u64 smcr_el1, smcr_el2; + + if (!vcpu_has_sme(vcpu)) + return; + + /* + * __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); + /* Guest might not have had EZT0 or FA64 */ + isb(); + } 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_sme_max_vq(vcpu) - 1; + write_sysreg_el1(smcr_el1, SYS_SMCR); + } + + __vcpu_assign_sys_reg(vcpu, SVCR, read_sysreg_s(SYS_SVCR)); +} + static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu) { + /* + * We always load the control registers for the guest so we + * always restore state for the host. + */ + sme_lazy_switch_to_host(vcpu); + if (!guest_owns_fp_regs()) return; =20 @@ -567,6 +709,16 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *= vcpu) { struct kvm_cpu_context *hctxt =3D host_data_ptr(host_ctxt); =20 + /* + * 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()) + ctxt_sys_reg(hctxt, 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 @@ -591,14 +743,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) { @@ -613,6 +768,20 @@ 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 (esr_iss_smtc =3D=3D ESR_ELx_SME_ISS_SMTC_ZT_DISABLED) { + if (!kvm_has_sme2(kern_hyp_va(vcpu->kvm))) + return false; + + if (vcpu_has_nv(vcpu) && + !(__vcpu_sys_reg(vcpu, SMCR_EL2) & SMCR_ELx_EZT0)) + return false; + } + break; default: return false; } @@ -628,10 +797,22 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_v= cpu *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); - else + if (sme_guest) + __hyp_sme_restore_guest(vcpu, &restore_sve, &restore_ffr); + + if (restore_sve) { + sve_load_state(kern_hyp_va(vcpu->arch.sve_state), restore_ffr); + fpsimd_load_common(&vcpu->arch.ctxt.fp_regs); + } else { fpsimd_load_state(&vcpu->arch.ctxt.fp_regs); + } =20 if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) write_sysreg_s(__vcpu_sys_reg(vcpu, FPMR), SYS_FPMR); @@ -640,6 +821,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 14e24e257dcc..33fd3bcb112a 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -31,16 +31,28 @@ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context = *host_ctxt); =20 static void __hyp_sve_save_guest(struct kvm_vcpu *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(kern_hyp_va(vcpu->arch.sve_state), true); + bool save_ffr =3D !vcpu_in_streaming_mode(vcpu) || vcpu_has_fa64(vcpu); + + if (vcpu_has_sve(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); + } + + /* Ensure ZCR/SMCR updates for VL are seen */ + isb(); + sve_save_state(kern_hyp_va(vcpu->arch.sve_state), save_ffr); fpsimd_save_common(&vcpu->arch.ctxt.fp_regs); - write_sysreg_s(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1, SYS_ZC= R_EL2); + + if (system_supports_sve()) + write_sysreg_s(sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SVE]) - 1, + SYS_ZCR_EL2); } =20 static void __hyp_sve_restore_host(void) @@ -63,9 +75,76 @@ static void __hyp_sve_restore_host(void) write_sysreg_el1(ctxt_sys_reg(hctxt, 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; + unsigned long smcr_el2; + + __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. + */ + smcr_el2 =3D vcpu_sme_max_vq(vcpu) - 1; + if (system_supports_fa64()) + smcr_el2 |=3D SMCR_ELx_FA64; + if (system_supports_sme2()) + smcr_el2 |=3D SMCR_ELx_EZT0; + sysreg_cond_update_s(SYS_SMCR_EL2, smcr_el2); + + if (vcpu_za_enabled(vcpu)) { + isb(); + sme_save_state(vcpu_sme_state(vcpu), vcpu_has_sme2(vcpu)); + } +} + +static void __hyp_sme_restore_host(void) +{ + struct kvm_cpu_context *hctxt =3D host_data_ptr(host_ctxt); + u64 smcr_el2; + + /* + * 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. + */ + smcr_el2 =3D sve_vq_from_vl(kvm_host_max_vl[ARM64_VEC_SME]) - 1; + if (system_supports_fa64()) + smcr_el2 |=3D SMCR_ELx_FA64; + if (system_supports_sme2()) + smcr_el2 |=3D SMCR_ELx_EZT0; + sysreg_cond_update_s(SYS_SMCR_EL2, smcr_el2); + + write_sysreg_el1(ctxt_sys_reg(hctxt, 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) @@ -73,8 +152,18 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) struct kvm_cpu_context *hctxt =3D host_data_ptr(host_ctxt); bool has_fpmr; =20 - if (!guest_owns_fp_regs()) + if (!guest_owns_fp_regs()) { + /* + * We always at least partially configure SME for the + * guest due to traps. + */ + if (vcpu_has_sme(vcpu)) { + /* Ensure __deactivate_cptr_traps() is visible */ + isb(); + __hyp_sme_restore_host(); + } return; + } =20 /* * Traps have been disabled by __deactivate_cptr_traps(), but there @@ -82,7 +171,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); @@ -91,6 +183,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 @@ -128,11 +223,12 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_= vcpu) { struct kvm_vcpu *host_vcpu =3D hyp_vcpu->host_vcpu; =20 - fpsimd_sve_flush(); flush_debug_state(hyp_vcpu); =20 hyp_vcpu->vcpu.arch.ctxt =3D host_vcpu->arch.ctxt; =20 + fpsimd_sve_flush(&hyp_vcpu->vcpu); + /* __hyp_running_vcpu must be NULL in a guest context. */ hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu =3D NULL; =20 @@ -223,10 +319,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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 41362381B15; Sun, 19 Jul 2026 23:11:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502711; cv=none; b=K6UDE1nZ72+90WvZxyzdiSyk9oC8go83+AHMfG+ifs3r4paQIJN+U3IbFNO+hr3o4Xcti60LLtGjfh6erg6RtQIk7HpZN2TRh7dIo9S4MnRwJHqZvxnwIlSJDX6kEVST+XjV6ZlH5lT0MrYMPzXSDus4FiIwJ7+LEedMwsANvPk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502711; c=relaxed/simple; bh=/V2DHbBTPReofZe1HQ+FEeJ8vnQLj7k1VzICcoZuutU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B9U6hm6K0AI+q7CktDS7HdsDKOJ50DS+Lei211epEhP4RYNYn1SKxDsiZ8jXCDinRt1rVcbHRgSwte5ZbQLl3D9pCRsyvgopHSBDo7vXzp3InOy/NUJHBYxzlKQzjZNOT84ORdL/rpLMBHZoUoMq4W83x9SlokCYiVdkGxfs/eo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=U2TZN9Yk; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="U2TZN9Yk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E0601F000E9; Sun, 19 Jul 2026 23:11:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502710; bh=b7MommBkO+e3Lshh90ju5gAfW2OCnzsFwyfx+L/ofMI=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=U2TZN9YkXy8tKubch5qFJVPAWb135k2i3Uk3/V9Igt8PoOMx6A9100yn+vu4sBwqc 9OnmgiIcpNnb0ovUhaDUJwZb5uekMaeb7Scxxxz3JJ6Qncf/omfJ6mMhZRg2UkyaNQ CXTArejgni+1UFl4u52MXXuiBLLxMYhCh6FSUAhNQvd8xX+4JcpiEjPKSJbaijuQTB Rk3T0+vejePDnXImj3hjZdzj692Go7J+nJbuvzEMhLseRi+SggFVVjGLuEpojgbrhW o0HlKP4MOGseBMAC4qstLWlfEX5w/oJXxKzLDh5uXzsLO8rXbUbgoDxsD3HDX0E/um cTEU8bg0ae69A== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:53 +0100 Subject: [PATCH v13 26/32] 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: <20260720-kvm-arm64-sme-v13-26-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=4959; i=broonie@kernel.org; h=from:subject:message-id; bh=/V2DHbBTPReofZe1HQ+FEeJ8vnQLj7k1VzICcoZuutU=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk7tA4g1AXbw5CzGAwC7Hipu/k89oJfl38ov 7bfv1y9k8CJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZOwAKCRAk1otyXVSH 0HsPB/97fDqYBSjKxZ3dd6l/czkSqcfOtuqMqV84Pua1+3sq79ziwQ2/FlswJEih2N8gdt0UvPS 3v45ijuSoj2K9TlFnMwt0dbDNSKsN1mIUQ3kDEnmrc/eYUYjVS/at79Xq135+abrKmyIbZ8D3wI 55ekkcfAF8or6x2nhWV+WSjyBwEBGeBx075eoR87WK8aFzXb9wsuvXLIUVAjK0A3Phu/Rkmk3vE i/4PVKthQTuYtR+MVAggDcYKvEC4hw7+63zcLj9fWAk8/Vg60bx3aT2ZZHWRfZhfO8bMgwf5YuI 6eD8M79dNqGaC8yMhd51DJXXcLMnNkUyRJNWv4w04Nd+qfT0 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, plus handling for emulation of SMCR_EL2.EZT0. Signed-off-by: Mark Brown --- arch/arm64/kvm/handle_exit.c | 19 +++++++++++++++++++ arch/arm64/kvm/hyp/include/hyp/switch.h | 11 ++++++----- arch/arm64/kvm/hyp/nvhe/switch.c | 2 ++ arch/arm64/kvm/hyp/vhe/switch.c | 1 + 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index f674cd25d894..24d54e977a31 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -233,6 +233,24 @@ static int handle_sve(struct kvm_vcpu *vcpu) return 1; } =20 +static int handle_sme(struct kvm_vcpu *vcpu) +{ + u64 esr =3D kvm_vcpu_get_esr(vcpu); + + if (guest_hyp_sme_traps_enabled(vcpu)) + return kvm_inject_nested_sync(vcpu, esr); + + /* Reinject SME EZT0 traps that were enabled by the guest. */ + if (vcpu_has_sme2(vcpu) && + ESR_ELx_EC(esr) =3D=3D ESR_ELx_EC_SME && + ESR_ELx_SME_ISS_SMTC(esr) =3D=3D ESR_ELx_SME_ISS_SMTC_ZT_DISABLED && + !(__vcpu_sys_reg(vcpu, SMCR_EL2) & SMCR_ELx_EZT0)) + return kvm_inject_nested_sync(vcpu, esr); + + kvm_inject_undefined(vcpu); + return 1; +} + /* * Two possibilities to handle a trapping ptrauth instruction: * @@ -386,6 +404,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 2eabffb640e9..5987b550ad34 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -67,11 +67,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; @@ -99,6 +96,8 @@ static inline void __activate_cptr_traps_vhe(struct kvm_v= cpu *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)) @@ -140,6 +139,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, S1POE, 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 7318e3e6a5f3..2d5029dbfb00 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -196,6 +196,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, @@ -208,6 +209,7 @@ static const exit_handler_fn pvm_exit_handlers[] =3D { [ESR_ELx_EC_HVC64] =3D kvm_handle_pvm_hvc64, [ESR_ELx_EC_SYS64] =3D kvm_handle_pvm_sys64, [ESR_ELx_EC_SVE] =3D kvm_handle_pvm_restricted, + [ESR_ELx_EC_SME] =3D kvm_handle_pvm_restricted, [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, diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switc= h.c index 625fe81a20b1..2931a1a1fe90 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -495,6 +495,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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 DF713381B15; Sun, 19 Jul 2026 23:11:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502716; cv=none; b=J1zQtiYFI0e1Mdu/aOfERL51RRhD+vBHNMLt2z+vDJHRyLzNeEHt+FhzZX3HqKsTlfuHlcK7Umn7RqDxcqYLIghITJdWTL7/4bmx+ETza/3rmDmPG5M5QiWm3zlWPYJ1x1FBoc2qqjHRZMGHTw5L0ejCggK4VXKvBmLAAj33tNQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502716; c=relaxed/simple; bh=hn1y/Ii/xUjl5TfgGrGM2KMGs+69hqwXhinvJnIOmPQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UM6vZnYVKzSsAG+KT4t6tZy8Wp7jA23Fslgfl/gQ3D9gWixp1X8GS9P9I6sBdbP87eip3bQZHZqI9gVPrladvIHXFMqFx5R5ouvMQGifD3fTWuc3xBqMlUISlfYoXEwssoqlCDm7HPYWkXkwjJM5maZWnGLuqHruLwsnQJsLSXs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c141UijV; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c141UijV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8DB8D1F00A3D; Sun, 19 Jul 2026 23:11:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502714; bh=0sz8gGxyAlkQMG+rUT9zspvd+PY5FDI251nuvd5HfjQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=c141UijV90dOfxJQJR7hg//rHLStvXnj+ICH6TcRlXifhTOAVR2jQZTXFsqDlRbTC zzkKQ3nAyE7m/flMUlffRcvh2F5KcaQh501/WPxk4LZyJhr2iSvgibe5ZkQMBI5Qd1 IVviqhfmb/ysDcvRbdDldy25KLYeMuJBKo4/W4yWWjTg65az2clRuyKG31q6ewxA+6 87RlfXzIYPudPGurbD+A/JarqhD87HhTksX/lZUzgBwOGOSGWIH3QglWWFGM6OtqEe vvS3z5y3UnOGZKTUJbL0UDaDNexk5vYwerBuXvu56fgVmgaBhO7fo8aSB0PM3SURiz 8RqHnrGw7z7lA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:54 +0100 Subject: [PATCH v13 27/32] 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: <20260720-kvm-arm64-sme-v13-27-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=2042; i=broonie@kernel.org; h=from:subject:message-id; bh=hn1y/Ii/xUjl5TfgGrGM2KMGs+69hqwXhinvJnIOmPQ=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk8nQnmN3m+uGAvuZGpAWgUu53Wf+RRuZH0/ cDlJNuNbiyJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZPAAKCRAk1otyXVSH 0IorB/9CVjtR+do2u9SU5XXbIj5Z/P4o6NWAArtRleoYGdv9x1iD4a8PQ1xXIXi7xmB3V7B39if /AYdqI7yxQiNG/5G+yWNw5cgUH+68ec3SxNXeOQSqjrydddIgx5YGG/dW50vBbUmj5ZJgeu6bob 6pI9MY26qaXxQQ7rQbT233TWOCHdRdfO2cVg5AzDZfa3WiKwXNLUZrH2+e5MrxOb9Da637aniRD 8w+dv+BS+xJZyQ1/4dFeyFj7ygrsfJXExC5CRjBKhzAjCWdtnnvz3tU/bHJGrpUURWMq4C4QAaO 1BN65V9aBsc0jY77rIe12YC2fAuOdfbHP2+Y59IqbNWyd1Ik 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. Reviewed-by: Fuad Tabba Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_nested.h | 2 ++ arch/arm64/kvm/nested.c | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/k= vm_nested.h index cdf3e8422ea1..9df3cea39b09 100644 --- a/arch/arm64/include/asm/kvm_nested.h +++ b/arch/arm64/include/asm/kvm_nested.h @@ -42,6 +42,8 @@ static inline u64 translate_cptr_el2_to_cpacr_el1(u64 cpt= r_el2) cpacr_el1 |=3D CPACR_EL1_FPEN; if (!(cptr_el2 & CPTR_EL2_TZ)) cpacr_el1 |=3D CPACR_EL1_ZEN; + if (!(cptr_el2 & CPTR_EL2_TSM)) + cpacr_el1 |=3D CPACR_EL1_SMEN; =20 cpacr_el1 |=3D cptr_el2 & (CPTR_EL2_TCPAC | CPTR_EL2_TAM); =20 diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 7de9b7f8f90a..cc80d4c8ec20 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -1630,14 +1630,13 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 v= al) break; =20 case SYS_ID_AA64PFR1_EL1: - /* Only support BTI, SSBS, CSV2_frac */ + /* Only support BTI, SME, SSBS, CSV2_frac */ val &=3D ~(ID_AA64PFR1_EL1_PFAR | ID_AA64PFR1_EL1_MTEX | ID_AA64PFR1_EL1_THE | ID_AA64PFR1_EL1_GCS | ID_AA64PFR1_EL1_MTE_frac | ID_AA64PFR1_EL1_NMI | - ID_AA64PFR1_EL1_SME | ID_AA64PFR1_EL1_RES0 | ID_AA64PFR1_EL1_MPAM_frac | ID_AA64PFR1_EL1_MTE); --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 3EDE53803D6; Sun, 19 Jul 2026 23:11:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502720; cv=none; b=jgVYMz8RoGwbQPGZnCv+ni4uIagpaubYpizuKqeYZk4l3FZ6jj231KZXdkFVk5rMxWOo3D7fYapTKt2FafV+B79LTcn57tFhhl0vPIu/kp/s6pdkDjALQ8Qq3znvU5GCHTlz9oEsYZTFOGPl+95WXaKlrfIcZkYlAVsWNfbMKmw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502720; c=relaxed/simple; bh=7tbTLnVOf/qMi6R0X/VXVjod7XC3yhz9lSuJVtJZ6T8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CD8MECxIVb4WKwf60C/yXc8RO6QnUCRMzOLIVmLeefyfCRTaGjrC5zOIa+5ujzYn6VrX1/YaOUpaDWgDTimjscNy1SB7CLWNdqO1KQUGDr/DTs1kd4oeJ1bWP4Vs5jj9ZNNUtca7nvAb+/gpN/dppEOK0nrIajLDeihVvRP/cp4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BhSOZqj+; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BhSOZqj+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DE6701F000E9; Sun, 19 Jul 2026 23:11:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502718; bh=eaZvGnhLQSjMntDc8m6x8zXFe1AuggL07xOSGmQJdv0=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=BhSOZqj+GwmZ+NZLUXirIzLuDbFkB8xDqGCmsQqo1gBWJ2hnOolA20glLoJ199i4u tkt64cbI86xsHBQhnvl4Nzja+HK94lfhAASxv7U6yIJQ78lmkYKFrFaNw7f9AyYcKR ZFZaQhHPz9QFBYXXtggpwFT0BJZ0fidiw+kGFXNvFsWhAHt+Ji5dt4zDR4QBGlO1n0 43rqMPhTgi4pfG8Dzd+QqOHaclnN1NeyMeH2jkLFpO6dhuiPqfrEGNX+VsKFwv/27u h/sBxrAb2Hpo5TRVkGPcLprCv5cu3LlylB6NVpwHiRgM6HqI4gt3lj4tmu0txXFPN8 kI9mq+b57Kk3Q== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:55 +0100 Subject: [PATCH v13 28/32] 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: <20260720-kvm-arm64-sme-v13-28-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=16419; i=broonie@kernel.org; h=from:subject:message-id; bh=7tbTLnVOf/qMi6R0X/VXVjod7XC3yhz9lSuJVtJZ6T8=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk9YGWa9kRFtWHmSCkGz225Cza7W77USkhmi +CAu6hM7zWJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZPQAKCRAk1otyXVSH 0ODuB/9wGykj8EreBsyF/cwpASz2APtHW+2aLe/Qa2nwFrZGB5QJVQmlGSvTORA3z+hKayEh/a9 B6ErlMy8V9CwxzNUC6Y/i/BzcU+D4DKIg1p5+ZQPzWyZc8FEXMt11/UuCFgMNDYH1C6OIP+mnsf w2SjPujEwgSD+Phyfyk7w126tThPYcBSWZBP60vY04lgfgZAWkNoV0NvXTXrCd9bZ7KDpwde83i 9JwLHjdcnm/6LI6C5IeIuGCb4ssRhXPuYjUVdCK2wKcHlCKcZZcLZedeGhsJWGUF6r0vV/d5CVD 10sxVT8gKoxkmne7u8tXo8y6kTOJZNPR23vSEieee0UarZrS 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. Since unlike SVE there is no architecturally manadated vector length which must be supported by all PEs we detect the case where the feature is supported but there is no shared VL and hide the feature. SME is supported for normal guests only. Signed-off-by: Mark Brown --- arch/arm64/include/asm/kvm_host.h | 8 ++- arch/arm64/include/uapi/asm/kvm.h | 1 + arch/arm64/kvm/arm.c | 10 ++++ arch/arm64/kvm/hyp/nvhe/pkvm.c | 81 ++++++++++++++++++++----- arch/arm64/kvm/hyp/nvhe/sys_regs.c | 6 ++ arch/arm64/kvm/reset.c | 119 +++++++++++++++++++++++++++++++--= ---- include/uapi/linux/kvm.h | 1 + 7 files changed, 192 insertions(+), 34 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 7ebe7b6cc96e..ab395b6d5c95 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_max_vl[ARM64_VEC_= MAX]; extern unsigned int __ro_after_init kvm_host_max_vl[ARM64_VEC_MAX]; =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); @@ -1804,4 +1805,9 @@ static __always_inline enum fgt_group_id __fgt_reg_to= _group_id(enum vcpu_sysreg =20 long kvm_get_cap_for_kvm_ioctl(unsigned int ioctl, long *ext); =20 +static inline bool system_supports_sme_virt(void) +{ + return system_supports_sme() && sme_max_virtualisable_vl(); +} + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/as= m/kvm.h index deccb034fce3..db240ba5555f 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 d43cfdcaee64..1b30470abde8 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -463,6 +463,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_virt(); + break; case KVM_CAP_ARM_PTRAUTH_ADDRESS: case KVM_CAP_ARM_PTRAUTH_GENERIC: r =3D kvm_has_full_ptr_auth(); @@ -1569,6 +1572,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_virt()) + 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); @@ -3041,6 +3047,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 620f3395ea4e..ed9ce39ee92f 100644 --- a/arch/arm64/kvm/hyp/nvhe/pkvm.c +++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c @@ -150,10 +150,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 @@ -386,6 +382,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_pkvm_ext_allowed(kvm, 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); } @@ -400,7 +401,8 @@ static void unpin_host_sve_state(struct pkvm_hyp_vcpu *= hyp_vcpu) { void *sve_state; =20 - if (!vcpu_has_feature(&hyp_vcpu->vcpu, KVM_ARM_VCPU_SVE)) + if (!vcpu_has_feature(&hyp_vcpu->vcpu, KVM_ARM_VCPU_SVE) && + !vcpu_has_feature(&hyp_vcpu->vcpu, KVM_ARM_VCPU_SME)) return; =20 sve_state =3D hyp_vcpu->vcpu.arch.sve_state; @@ -408,6 +410,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 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) { @@ -421,6 +435,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 @@ -447,23 +462,35 @@ static void init_pkvm_hyp_vm(struct kvm *host_kvm, st= ruct pkvm_hyp_vm *hyp_vm, mmu->pgt =3D &hyp_vm->pgt; } =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) { @@ -475,12 +502,37 @@ 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)) { + /* Space for ZT0 is always allocated to simplify the code. */ + sme_state_size =3D sme_state_size_from_vl(sme_max_vl, + system_supports_sme2()); + 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 NULL; + } + 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 @@ -540,7 +592,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); @@ -926,6 +978,7 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_v= cpu *host_vcpu, if (ret) { unpin_host_vcpu(host_vcpu); unpin_host_sve_state(hyp_vcpu); + unpin_host_sme_state(hyp_vcpu); } unlock: hyp_spin_unlock(&vm_table_lock); diff --git a/arch/arm64/kvm/hyp/nvhe/sys_regs.c b/arch/arm64/kvm/hyp/nvhe/s= ys_regs.c index 8c3fbb413a06..e2d8a28be8f5 100644 --- a/arch/arm64/kvm/hyp/nvhe/sys_regs.c +++ b/arch/arm64/kvm/hyp/nvhe/sys_regs.c @@ -67,6 +67,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); @@ -103,6 +108,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 fee01c38fa13..c0c605ff22bd 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -76,6 +76,31 @@ int __init kvm_arm_init_sve(void) return 0; } =20 +int __init kvm_arm_init_sme(void) +{ + if (system_supports_sme()) { + 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]; + } + + if (system_supports_sme_virt()) { + kvm_max_vl[ARM64_VEC_SME] =3D sme_max_virtualisable_vl(); + + 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 +113,90 @@ 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; + } else { + vcpu->arch.max_vl[ARM64_VEC_SVE] =3D 0; + } =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; + } else { + vcpu->arch.max_vl[ARM64_VEC_SME] =3D 0; + } + + 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,20 +226,26 @@ 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); } =20 static void kvm_vcpu_reset_vec(struct kvm_vcpu *vcpu) { - if (vcpu_has_sve(vcpu)) + if (vcpu_has_sve(vcpu) || vcpu_has_sme(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 +285,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 419011097fa8..9291538489ac 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -997,6 +997,7 @@ struct kvm_enable_cap { #define KVM_CAP_S390_KEYOP 247 #define KVM_CAP_S390_VSIE_ESAMODE 248 #define KVM_CAP_S390_HPAGE_2G 249 +#define KVM_CAP_ARM_SME 250 =20 struct kvm_irq_routing_irqchip { __u32 irqchip; --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 4F2E53B14D4; Sun, 19 Jul 2026 23:12:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502724; cv=none; b=iIeCDZclEY/HJr+HMKQO4r6eKSsceRp2TJrbjzP2eNnq3gVMHCIlCfttTnLsTxBRIXeZQiDeEyGHqGZd2weaXPm3Zr9f5Mxuj9C3SbIM3tdXJJvozWBSqIe1pOAM3+VKIRDhOyg5AYq7sPpP1JA0UZbaDkYPn+isTSt28WQYWYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502724; c=relaxed/simple; bh=3zzAFIxW4QntGIfc+v0S58ciMfKRPipxII9rhMorBnU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WuwLx2tDmpxtGonTdyO4mSIZ5cXNOKG/sheUOCfse3NXNdz7fh/qBPfdStnPDpdiv0f/2tpQrobApHOt9xiqwRDT1OMJ3YDISQG9CHFSnJTh6VtJuyqujHzPkrHlYU37E46TgI45k1Z87RXzYxeMtwsqG4r6NmuHM2ybC4jCHCQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WdEWLgim; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WdEWLgim" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3F3DC1F00A3A; Sun, 19 Jul 2026 23:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502723; bh=V9/QBsgUl+YAHSU3KRVgzfp7o3z60FnCLy+stiPlLsM=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=WdEWLgimdUnWOOMh7FlriNY5lB2TMDa7fzH5p8GdEXBClHyHlkgeLOYDw8BDUkGGP Yuj416Tx9I3dwbAJa1JeMc5LYada72J7fxsTKb8CPnFHL9vJYEpbqxsCQOg7aMG1hi hyoTxbfjfpk26uDaubCPqQ/oRXoFFnHLbfmQ+UTP+r7GFW5L+jI62yPOQxW3ckXyss Z5+iUf0aip6JDmGutBekHnVQPdvnqX9Yk692nG0AWDM7JAzEtqQ06CBI0QtT0QpwLg H2F0KMN4ov7a1Nakx0FGTwo42gla5yYn3gPObx/ZnNM6XhmdVHU5HEy8aLny8x9paC bgzIp18v0KqVA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:56 +0100 Subject: [PATCH v13 29/32] KVM: arm64: selftests: Remove spurious check for single bit safe values 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: <20260720-kvm-arm64-sme-v13-29-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=1200; i=broonie@kernel.org; h=from:subject:message-id; bh=3zzAFIxW4QntGIfc+v0S58ciMfKRPipxII9rhMorBnU=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk+i+hoFBVdo38ozyAZpmD7uyLRsmokr6on0 fvkE/s4sISJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZPgAKCRAk1otyXVSH 0OZAB/4+liUc/7Segb5Y98e5swH5Q6abXU8BYD9Up2joacK6G3YdivbA7aQZrxhqP3HgvrAHH2S YTOoePIimv09sem9sOv23eUrx6fk8bEqNogZya4N4P/ate5M9m5kZ3kP9BjhaXgVtwj994o0h9g 2I/zqxMSggIJCnKsU+husmvow72vRFhpCkHOdxVgVM4CdJHow8i9uR1mbLsdAISjd4go0oeu7Vc WVpqqHZm+B9cntnQBFpYdrgRKyXGP3YKPYYX92P4CXjgU654VHF/D8oD3XTGP3xXEMfv+PF8pyw ZivDGw/E+XryeI+5WhQ5Rbev+pALkxLlbNPNyXN5krbnr+Na X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB get_safe_value() currently asserts that bitfields it is generating a safe value for must be more than one bit wide but in actual fact it should always be possible to generate a safe value to write to a bitfield even if it is just the current value and the function correctly handles that. Remove the assert. Fixes: bf09ee918053e ("KVM: arm64: selftests: Remove ARM64_FEATURE_FIELD_BI= TS and its last user") Reviewed-by: Ben Horgan Signed-off-by: Mark Brown --- tools/testing/selftests/kvm/arm64/set_id_regs.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testin= g/selftests/kvm/arm64/set_id_regs.c index 7429a1055df5..9eceac84e297 100644 --- a/tools/testing/selftests/kvm/arm64/set_id_regs.c +++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c @@ -279,8 +279,6 @@ u64 get_safe_value(const struct reg_ftr_bits *ftr_bits,= u64 ftr) { u64 ftr_max =3D ftr_bits->mask >> ftr_bits->shift; =20 - TEST_ASSERT(ftr_max > 1, "This test doesn't support single bit features"); - if (ftr_bits->sign =3D=3D FTR_UNSIGNED) { switch (ftr_bits->type) { case FTR_EXACT: --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 EF786384CE1; Sun, 19 Jul 2026 23:12:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502729; cv=none; b=rk8Pz364iHUNxgeXpuwcfBvdUqS82KNUv3cSTELzy36E2lZoe7rgnvUJ/2BAMfna3ZPhENUa8sAGmDFFeB/HSmsFy87ab6x9lGEIsW5fjWwcLVZw3OJ5Qh7Gj4bJAeNzxcLb5ax2VYn6DWYzbW9hk+jaITR1yADu7jbGP7ePoBo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502729; c=relaxed/simple; bh=DoSXFT1XFLMt5bL77ymD5uWM5fFd8Skxma7c37DB6O8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mJ54TH7Zblw+H0s2KloU81+5zymNVLHnuELpaCuOS3e5YmqbrBItM7TdalrvG2Onfxe0SPy2wgVIc7k7C9nHzfLu3+t1/EWjKzaSP68EKFrw0vuOcUTwbEjUqaxqvxHpQiTYSjcTm/WVoqccWGsKKBCqn66dmX0hvnkFlQGjOBI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VHItgEX6; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VHItgEX6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9C2801F000E9; Sun, 19 Jul 2026 23:12:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502727; bh=k6q2RcAVUcHJXSDerZte/wZkUxNLtsu6zF4B+0lVk2U=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=VHItgEX6/YP2Ozy/roLHwG3vf3bR69hSpR1DUlRiB81FP7Gbm5ey4b6DhDJpNcmbr TLk5dNTHYuEsw/0fZpNl6QDoGh0z6zUmlT2JJ20h9vCoDigNdDagYZRKqzlU+GhfcI 8x+uCcb2Yee4Y+quz/okcIyNoRuyDN03TYOrq7gZ/qiaGxgUmF4CJdXYpyPSwWLtwo RAWgc4xkrEMp0j1KaL6F6nMMfNVbZ4/OzqIsSyrncER7wNtWkEq4zxMlyFocVDd/Uh tJzgtloC8ctgNyMqkAGCgGSigPKJI7CiHVY6BI+CBHPZfp4LeuGF93jZsoPcP1XtPH dVUKaBcSFMvuA== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:57 +0100 Subject: [PATCH v13 30/32] KVM: arm64: selftests: Skip impossible invalid value tests 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: <20260720-kvm-arm64-sme-v13-30-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3690; i=broonie@kernel.org; h=from:subject:message-id; bh=DoSXFT1XFLMt5bL77ymD5uWM5fFd8Skxma7c37DB6O8=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk+ePDwSiD4VpzeYE3Id9Rc+zhBWemm3WIxc k5BrRZvK1yJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZPgAKCRAk1otyXVSH 0AdJB/wP/giklcwigwFEGFkW6wN64uXabgyc3gw+Vbq+QvoRCYFBOd/fUghgQKbm155Ze2D8KyK MnBusZQAzlKmg/sFstsLmakD/2vTWZOLjLblcx9dLnzlHoi/bCS8ynS0DYHu5RcDwdvT8sIs/Vg xzXqk3GCIdWl7L/Fe4ApJK65MYGRjFa91uJfHf+6EzuiGfEXhXZykSweG9xQe+qcFUzcPKe0E2t lJtfSUcnd5gbPzM5M4sxvdHL030+dol1TIi2qtt9C/QXkaWC1QuPZANzx57gIZ2Z1HB4EfEHSNr w5R5Www7gZwUifp6pFf1/H2RfcdcPriBjttYHs2MerjIUzVC X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB The set_id_regs test currently assumes that there will always be invalid values available in bitfields for it to generate but this may not be the case if the architecture has defined meanings for every possible value for the bitfield. An assert added in commit bf09ee918053e ("KVM: arm64: selftests: Remove ARM64_FEATURE_FIELD_BITS and its last user") refuses to run for single bit fields which will show the issue most readily but there is no reason wider ones can't show the same issue. Rework the tests for invalid value to check if an invalid value can be generated and skip the test if not, removing the assert. Signed-off-by: Mark Brown --- tools/testing/selftests/kvm/arm64/set_id_regs.c | 64 +++++++++++++++++++++= ---- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testin= g/selftests/kvm/arm64/set_id_regs.c index 9eceac84e297..da9349bf31ab 100644 --- a/tools/testing/selftests/kvm/arm64/set_id_regs.c +++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c @@ -327,54 +327,95 @@ u64 get_safe_value(const struct reg_ftr_bits *ftr_bit= s, u64 ftr) } =20 /* Return an invalid value to a given ftr_bits an ftr value */ -u64 get_invalid_value(const struct reg_ftr_bits *ftr_bits, u64 ftr) +u64 get_invalid_value(const struct reg_ftr_bits *ftr_bits, u64 ftr, bool *= skip) { u64 ftr_max =3D ftr_bits->mask >> ftr_bits->shift; =20 - TEST_ASSERT(ftr_max > 1, "This test doesn't support single bit features"); + *skip =3D false; =20 if (ftr_bits->sign =3D=3D FTR_UNSIGNED) { switch (ftr_bits->type) { case FTR_EXACT: ftr =3D max((u64)ftr_bits->safe_val + 1, ftr + 1); + if (ftr >=3D ftr_max) + *skip =3D true; break; case FTR_LOWER_SAFE: + if (ftr =3D=3D ftr_max) + *skip =3D true; ftr++; break; case FTR_HIGHER_SAFE: + if (ftr =3D=3D 0) + *skip =3D true; ftr--; break; case FTR_HIGHER_OR_ZERO_SAFE: - if (ftr =3D=3D 0) + switch (ftr) { + case 0: ftr =3D ftr_max; - else + break; + case 1: + *skip =3D true; + break; + default: ftr--; + break; + } break; default: + *skip =3D true; break; } } else if (ftr !=3D ftr_max) { switch (ftr_bits->type) { case FTR_EXACT: ftr =3D max((u64)ftr_bits->safe_val + 1, ftr + 1); + if (ftr >=3D ftr_max) + *skip =3D true; break; case FTR_LOWER_SAFE: ftr++; break; case FTR_HIGHER_SAFE: - ftr--; + /* FIXME: "need to check for the actual highest." */ + if (ftr =3D=3D 0 || ftr =3D=3D ftr_max) + *skip =3D true; + else + ftr--; break; case FTR_HIGHER_OR_ZERO_SAFE: - if (ftr =3D=3D 0) - ftr =3D ftr_max - 1; - else + switch (ftr) { + case 0: + if (ftr_max > 1) + ftr =3D ftr_max - 1; + else + *skip =3D true; + break; + case 1: + *skip =3D true; + break; + default: ftr--; + break; + } break; default: + *skip =3D true; break; } } else { - ftr =3D 0; + switch (ftr_bits->type) { + case FTR_LOWER_SAFE: + if (ftr =3D=3D 0) + *skip =3D true; + else + ftr =3D 0; + break; + default: + *skip =3D true; + break; + } } =20 return ftr; @@ -409,12 +450,15 @@ static void test_reg_set_fail(struct kvm_vcpu *vcpu, = u64 reg, u8 shift =3D ftr_bits->shift; u64 mask =3D ftr_bits->mask; u64 val, old_val, ftr; + bool skip; int r; =20 val =3D vcpu_get_reg(vcpu, reg); ftr =3D (val & mask) >> shift; =20 - ftr =3D get_invalid_value(ftr_bits, ftr); + ftr =3D get_invalid_value(ftr_bits, ftr, &skip); + if (skip) + return; =20 old_val =3D val; ftr <<=3D shift; --=20 2.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 F32573B6BF1; Sun, 19 Jul 2026 23:12:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502733; cv=none; b=eWHVF/tB33NekykCEzeRzevn/zKROHihF9VjSAycxOQAp1XWaJ8+BMOgubgXLEIkWexBtreWxBz2cxqlz0v2l7Ei/50yPrmrPJPFUuynljRDmok5H72YwceFSygV9ZVtizRYvrYCmrcV313vJ5/UU7Ly0lHXdo0VdEGmc5lf9l0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502733; c=relaxed/simple; bh=I21JH58CR/AbSnYTHYyjog9l03x/hS5CLetpI7AAePU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JYpjPA9QTFS3m25iS0OMK0rr8nzODomCpxjGsGDAk/yk3podPmMFO3HmXuXWL8dV1mlD7nflz9VWsqK1QaxXXvWzbPgSvOkFLYXF73L+XMWha47NptXbuybk99tsj77OONPuKvPPXMMrDoDrBkN2NljUbu6qAXw4DsK+zivS13Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gk68iheG; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gk68iheG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EC8011F00ADE; Sun, 19 Jul 2026 23:12:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502731; bh=xQPjYFjbIcAmw/vy47XjvylGbXgKpoMyOES+M/yVDZc=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=gk68iheGGeBlO/D3hN2G7SIkPZ9UnndwVxpgJ0VU06DNS3GHGRqae8B1kmhiZv70q ehIs9D87XgTHXPpHu8RW05yrA3YZSC1FIzqtO+DfJEgg7QjO/c14vMOLxnr/F7Xel8 Xvd8Rp6cH0n5xLRvlAtzvJCpXnzJFmSXgitnTaw8XbakqxcDab5sud5lG/C0gdbLMZ HNxi6iQYodaCrQQ9KS/fNo3iTGfaD/SpP1MCsWP1fN+kLXXT6dkfLhfn+Qs/IDJuWN DWVPEjdILxq4PEsgiqScMa3ieA0ptAD1wloaOVfrUjZAfM4LTEO9KJOMQ2jOp2q7jW z2CfSFD5bhswg== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:58 +0100 Subject: [PATCH v13 31/32] 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: <20260720-kvm-arm64-sme-v13-31-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3018; i=broonie@kernel.org; h=from:subject:message-id; bh=I21JH58CR/AbSnYTHYyjog9l03x/hS5CLetpI7AAePU=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVk/lK0YUl/cK8VlgLUT9a9L2FGYBj04Shosk xgAJXeYxzKJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZPwAKCRAk1otyXVSH 0M+vB/9+8EBa+OkLa8yKHbdU44Xgx4s1d3kwbL1fS0ukDHn/KW93mHAkL9hs0FfLdK7cdohDPhk CfCp4nJK1TUEcxHk8D2pGGZgACuKDb3SPQuFsk0ynKgDZCNMIDdUOGwFUxZkVYVlvOOMVAvgcvk Rp8LEeVKe00w+DBQonc6rnLXJXKrbqln+6uG/9N1xJf44WGbb6lgBAsgw80jCvySWK+PRVAziB8 mPGa3CyVP+UXmexh5S08O7ySNEVp6hlyp1afGD35raX0M+FLM9uSEM/2Q5wiFBIpNnXSmPDwORA 8IUGl38C+cBWrnCSc4glAsjkK1MBfzUw3siblPylLp6jfO7l 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 0a3a94c4cca1..876c4719e2e2 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(SCTLR2_EL2, ID_AA64MMFR3_EL1, SCTLRX, IMP), REG_FEAT(VDISR_EL2, ID_AA64PFR0_EL1, RAS, IMP), @@ -367,6 +373,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), @@ -498,6 +505,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 */ @@ -518,9 +527,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 */ @@ -730,6 +741,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.47.3 From nobody Sat Jul 25 03:20:30 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 9846A3803DC; Sun, 19 Jul 2026 23:12:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502737; cv=none; b=iHgOhOVYpT1GuE8ERInDNbRgZpI7I0hKKdoRDpr63lVgUZnyTQzlDKO160n4wusg1vwLNO0BOpwBlRXcitsGXWCNE2OXv9DwzIIvsnGSpMtVddR5yxksHhAEcwPCdKTmFJiEDD9hDj1xPvuoA2pvtsMOXwklsWyp7c6CLxGKPhI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784502737; c=relaxed/simple; bh=q7gRFDO7XUzOJdjKk7dinZEmMYgpMJThzBI3Uxs/+tg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nPquszOeJ7EOXImaCFtxlqKl6bbSFUsLydY3Sxr2V4LA12P82kRkMCtjmVVcLT5lSTDuTnOgSv1TnAZ66bXyDXSDRUevXAggDB0+DCP5W/7NoiMNUvofA85spDSAiHLuPV3CNayXFdgpnA5iy5K6dyIAlospGoaQtxtKpTo7C4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TGc7RTRm; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TGc7RTRm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4993D1F000E9; Sun, 19 Jul 2026 23:12:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1784502736; bh=XECF9ZZpHN11rgO/zTL5kqZIcvgfBhcTmPU6H51lc1c=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=TGc7RTRmFm6L7ZZkyZWskOec514SOobW5z7Se9S1hJWQjXZzHq9K+WCBoWz1SHIGO c60uphJG67brwIYAOF77JF2/zSMcMzqARbTw9Vy40BYU+7NBWUXBjcvUPUmylcTz2G YI5B4zwzf/03dZvRIRl0+2c5Ajvvch1kpJXyggXA4vAbCpnqup+CSuShLz0GZezcpD HuGwqnijDJgR9WElWjL95BWbFoz6NRBo/Qf+vMfxnnjSx15oT6E+6nOUsUktE4FzaB SUi2aP/JOFcP3fresAcVLj+dI7W1NHgf0ORx4zMVfYC4QTc7EBn1Px6mXqr4/UEi28 M1KWXxC6byH4Q== From: Mark Brown Date: Mon, 20 Jul 2026 00:07:59 +0100 Subject: [PATCH v13 32/32] 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: <20260720-kvm-arm64-sme-v13-32-d9abd3ffa245@kernel.org> References: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> In-Reply-To: <20260720-kvm-arm64-sme-v13-0-d9abd3ffa245@kernel.org> To: Marc Zyngier , Joey Gouly , Catalin Marinas , Suzuki K Poulose , Will Deacon , Paolo Bonzini , Jonathan Corbet , Shuah Khan , Oliver Upton Cc: Dave Martin , Fuad Tabba , Mark Rutland , Ben Horgan , Jean-Philippe Brucker , 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, Peter Maydell , Eric Auger , Mark Brown X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3538; i=broonie@kernel.org; h=from:subject:message-id; bh=q7gRFDO7XUzOJdjKk7dinZEmMYgpMJThzBI3Uxs/+tg=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBqXVlAU1/Dwy5C+mmI5SgTi15+8XjLgHbk8SqV6 ShOKnvTPJqJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCal1ZQAAKCRAk1otyXVSH 0JuZB/4kseTKPVKXThQDY2bEISdVlTmhZqswc0T/a6N3EXUE7O+LA/5T8xG/qaDINMEH/2JfdAV 7N/vRWuM7qp5aTXe1qUswh7YC8OFixPgivU8A70LQ5sOv/OtPN9b603WoW0aM0v3sG5Rw5VQquu 7UCWgSftrnasfBvqCDFnOVe1Z+BJXwPH+gaWD1E4hB3jk1a/Fj/KcCtqRrcjIJlF/iLG971uLk8 GF5PadJUrDWm8XdmMP6w73Px2LLPQ1Dm244nq4P8GTEyNJe8He0k8uXSG3Y96EbtdsbB5PmLYnx a8ckTP2dqHjpyQ09xqATpHMkOmsCyPb3dQ6wtSHy7wGJS8gB 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_AA64SMFR0_EL1 and it's subfields. Signed-off-by: Mark Brown --- tools/testing/selftests/kvm/arm64/set_id_regs.c | 30 +++++++++++++++++++++= ++++ 1 file changed, 30 insertions(+) diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testin= g/selftests/kvm/arm64/set_id_regs.c index da9349bf31ab..26db507f6e73 100644 --- a/tools/testing/selftests/kvm/arm64/set_id_regs.c +++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c @@ -155,6 +155,7 @@ static const struct reg_ftr_bits ftr_id_aa64pfr0_el1[] = =3D { static const struct reg_ftr_bits ftr_id_aa64pfr1_el1[] =3D { REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, DF2, 0), REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, CSV2_frac, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, SME, 0), REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, SSBS, ID_AA64PFR1_EL1_SSBS_= NI), REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64PFR1_EL1, BT, 0), REG_FTR_END, @@ -212,6 +213,33 @@ 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_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, SBitPerm, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, AES, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, SFEXPA, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, STMOP, 0), + REG_FTR_BITS(FTR_LOWER_SAFE, ID_AA64SMFR0_EL1, SMOP4, 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), @@ -244,6 +272,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 @@ -263,6 +292,7 @@ static void guest_code(void) GUEST_REG_SYNC(SYS_ID_AA64MMFR1_EL1); GUEST_REG_SYNC(SYS_ID_AA64MMFR2_EL1); GUEST_REG_SYNC(SYS_ID_AA64MMFR3_EL1); + GUEST_REG_SYNC(SYS_ID_AA64SMFR0_EL1); GUEST_REG_SYNC(SYS_ID_AA64ZFR0_EL1); GUEST_REG_SYNC(SYS_MPIDR_EL1); GUEST_REG_SYNC(SYS_CLIDR_EL1); --=20 2.47.3