Re: [PATCH v13 02/32] arm64/fpsimd: Ensure all of ZCR_EL1 is initialised from idle
From: Mark Rutland <mark.rutland@arm.com>
Date: 2026-07-24 15:16:22
Also in:
kvm, kvmarm, linux-doc, linux-kselftest, lkml
On Thu, Jul 23, 2026 at 01:58:11PM +0100, Mark Rutland wrote:
On Mon, Jul 20, 2026 at 12:07:29AM +0100, Mark Brown wrote:quoted
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 <broonie@kernel.org>While this happens to work today, this is a more general architecture problem, and I think we should cc stable such that kernels will work reliably on future hardware. All stable kernels support SVE, so this needs to go as far back as v5.10.y. One minor comment below, but with that fixed up (and a CC stable): Acked-by: Mark Rutland <mark.rutland@arm.com>
Sorry, having looked at some of the later patches I think this isn't quite right even with those changes, as we wouldn't have necessary context synchronization in all cases. I'll need to dig a bit more to come up with a more concrete solution. Mark.
quoted
+void fpsimd_suspend_exit(void) { u64 smcr = 0; - if (!system_supports_sme()) - return; + if (system_supports_sve()) + write_sysreg_s(0, SYS_ZCR_EL1); - if (system_supports_fa64()) - smcr |= SMCR_ELx_FA64; - if (system_supports_sme2()) - smcr |= SMCR_ELx_EZT0; + if (system_supports_sme()) {We should move the 'smcr' variable into this block. That way it's scoped to where it matters.quoted
+ if (system_supports_fa64()) + smcr |= SMCR_ELx_FA64; + if (system_supports_sme2()) + smcr |= SMCR_ELx_EZT0; - 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); + } }Mark.