Skip to content

Commit 01948b0

Browse files
brooniewilldeacon
authored andcommitted
arm64/fpsimd: Only provide the length to cpufeature for xCR registers
For both SVE and SME we abuse the generic register field comparison support in the cpufeature code as part of our detection of unsupported variations in the vector lengths available to PEs, reporting the maximum vector lengths via ZCR_EL1.LEN and SMCR_EL1.LEN. Since these are configuration registers rather than identification registers the assumptions the cpufeature code makes about how unknown bitfields behave are invalid, leading to warnings when SME features like FA64 are enabled and we hotplug a CPU: CPU features: SANITY CHECK: Unexpected variation in SYS_SMCR_EL1. Boot CPU: 0x0000000000000f, CPU3: 0x0000008000000f CPU features: Unsupported CPU feature variation detected. SVE has no controls other than the vector length so is not yet impacted but the same issue will apply there if any are defined. Since the only field we are interested in having the cpufeature code handle is the length field and we use a custom read function to obtain the value we can avoid these warnings by filtering out all other bits when we return the register value, if we're doing that we don't need to bother reading the register at all and can simply use the RDVL/RDSVL value we were filling in instead. Fixes: 2e0f247 ("arm64/sve: Probe SVE capabilities and usable vector lengths") FixeS: b42990d ("arm64/sme: Identify supported SME vector lengths at boot") Signed-off-by: Mark Brown <broonie@kernel.org> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Link: https://lore.kernel.org/r/20230731-arm64-sme-fa64-hotplug-v2-1-7714c00dd902@kernel.org Signed-off-by: Will Deacon <will@kernel.org>
1 parent d70175b commit 01948b0

File tree

1 file changed

+4
-18
lines changed

1 file changed

+4
-18
lines changed

arch/arm64/kernel/fpsimd.c

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,22 +1178,15 @@ void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
11781178
*/
11791179
u64 read_zcr_features(void)
11801180
{
1181-
u64 zcr;
1182-
unsigned int vq_max;
1183-
11841181
/*
11851182
* Set the maximum possible VL, and write zeroes to all other
11861183
* bits to see if they stick.
11871184
*/
11881185
sve_kernel_enable(NULL);
11891186
write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL1);
11901187

1191-
zcr = read_sysreg_s(SYS_ZCR_EL1);
1192-
zcr &= ~(u64)ZCR_ELx_LEN_MASK; /* find sticky 1s outside LEN field */
1193-
vq_max = sve_vq_from_vl(sve_get_vl());
1194-
zcr |= vq_max - 1; /* set LEN field to maximum effective value */
1195-
1196-
return zcr;
1188+
/* Return LEN value that would be written to get the maximum VL */
1189+
return sve_vq_from_vl(sve_get_vl()) - 1;
11971190
}
11981191

11991192
void __init sve_setup(void)
@@ -1348,9 +1341,6 @@ void fa64_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
13481341
*/
13491342
u64 read_smcr_features(void)
13501343
{
1351-
u64 smcr;
1352-
unsigned int vq_max;
1353-
13541344
sme_kernel_enable(NULL);
13551345

13561346
/*
@@ -1359,12 +1349,8 @@ u64 read_smcr_features(void)
13591349
write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_LEN_MASK,
13601350
SYS_SMCR_EL1);
13611351

1362-
smcr = read_sysreg_s(SYS_SMCR_EL1);
1363-
smcr &= ~(u64)SMCR_ELx_LEN_MASK; /* Only the LEN field */
1364-
vq_max = sve_vq_from_vl(sme_get_vl());
1365-
smcr |= vq_max - 1; /* set LEN field to maximum effective value */
1366-
1367-
return smcr;
1352+
/* Return LEN value that would be written to get the maximum VL */
1353+
return sve_vq_from_vl(sme_get_vl()) - 1;
13681354
}
13691355

13701356
void __init sme_setup(void)

0 commit comments

Comments
 (0)