Skip to content

Commit abef069

Browse files
brooniectmarinas
authored andcommitted
arm64/sve: Remove ZCR pseudo register from cpufeature code
For reasons that are not currently apparent during cpufeature enumeration we maintain a pseudo register for ZCR which records the maximum supported vector length using the value that would be written to ZCR_EL1.LEN to configure it. This is not exposed to userspace and is not sufficient for detecting unsupportable configurations, we need the more detailed checks in vec_update_vq_map() for that since we can't cope with missing vector lengths on late CPUs and KVM requires an exactly matching set of supported vector lengths as EL1 can enumerate VLs directly with the hardware. Remove the code, replacing the usage in sve_setup() with a query of the vq_map. Signed-off-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 6465e26 commit abef069

File tree

4 files changed

+9
-60
lines changed

4 files changed

+9
-60
lines changed

arch/arm64/include/asm/cpu.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,6 @@ struct cpuinfo_arm64 {
6464

6565
struct cpuinfo_32bit aarch32;
6666

67-
/* pseudo-ZCR for recording maximum ZCR_EL1 LEN value: */
68-
u64 reg_zcr;
69-
7067
/* pseudo-SMCR for recording maximum SMCR_EL1 LEN value: */
7168
u64 reg_smcr;
7269
};

arch/arm64/include/asm/fpsimd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ extern void sme_kernel_enable(const struct arm64_cpu_capabilities *__unused);
128128
extern void sme2_kernel_enable(const struct arm64_cpu_capabilities *__unused);
129129
extern void fa64_kernel_enable(const struct arm64_cpu_capabilities *__unused);
130130

131-
extern u64 read_zcr_features(void);
132131
extern u64 read_smcr_features(void);
133132

134133
/*

arch/arm64/kernel/cpufeature.c

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -611,12 +611,6 @@ static const struct arm64_ftr_bits ftr_id_dfr1[] = {
611611
ARM64_FTR_END,
612612
};
613613

614-
static const struct arm64_ftr_bits ftr_zcr[] = {
615-
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE,
616-
ZCR_ELx_LEN_SHIFT, ZCR_ELx_LEN_WIDTH, 0), /* LEN */
617-
ARM64_FTR_END,
618-
};
619-
620614
static const struct arm64_ftr_bits ftr_smcr[] = {
621615
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE,
622616
SMCR_ELx_LEN_SHIFT, SMCR_ELx_LEN_WIDTH, 0), /* LEN */
@@ -736,7 +730,6 @@ static const struct __ftr_reg_entry {
736730
ARM64_FTR_REG(SYS_ID_AA64MMFR3_EL1, ftr_id_aa64mmfr3),
737731

738732
/* Op1 = 0, CRn = 1, CRm = 2 */
739-
ARM64_FTR_REG(SYS_ZCR_EL1, ftr_zcr),
740733
ARM64_FTR_REG(SYS_SMCR_EL1, ftr_smcr),
741734

742735
/* Op1 = 1, CRn = 0, CRm = 0 */
@@ -1040,8 +1033,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
10401033

10411034
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
10421035
id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1043-
info->reg_zcr = read_zcr_features();
1044-
init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
1036+
sve_kernel_enable(NULL);
10451037
vec_init_vq_map(ARM64_VEC_SVE);
10461038
}
10471039

@@ -1289,15 +1281,13 @@ void update_cpu_features(int cpu,
12891281
taint |= check_update_ftr_reg(SYS_ID_AA64SMFR0_EL1, cpu,
12901282
info->reg_id_aa64smfr0, boot->reg_id_aa64smfr0);
12911283

1284+
/* Probe vector lengths */
12921285
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
12931286
id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
1294-
info->reg_zcr = read_zcr_features();
1295-
taint |= check_update_ftr_reg(SYS_ZCR_EL1, cpu,
1296-
info->reg_zcr, boot->reg_zcr);
1297-
1298-
/* Probe vector lengths */
1299-
if (!system_capabilities_finalized())
1287+
if (!system_capabilities_finalized()) {
1288+
sve_kernel_enable(NULL);
13001289
vec_update_vq_map(ARM64_VEC_SVE);
1290+
}
13011291
}
13021292

13031293
if (IS_ENABLED(CONFIG_ARM64_SME) &&
@@ -3153,19 +3143,11 @@ static void verify_local_elf_hwcaps(void)
31533143

31543144
static void verify_sve_features(void)
31553145
{
3156-
u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
3157-
u64 zcr = read_zcr_features();
3158-
3159-
unsigned int safe_len = safe_zcr & ZCR_ELx_LEN_MASK;
3160-
unsigned int len = zcr & ZCR_ELx_LEN_MASK;
3161-
3162-
if (len < safe_len || vec_verify_vq_map(ARM64_VEC_SVE)) {
3146+
if (vec_verify_vq_map(ARM64_VEC_SVE)) {
31633147
pr_crit("CPU%d: SVE: vector length support mismatch\n",
31643148
smp_processor_id());
31653149
cpu_die_early();
31663150
}
3167-
3168-
/* Add checks on other ZCR bits here if necessary */
31693151
}
31703152

31713153
static void verify_sme_features(void)

arch/arm64/kernel/fpsimd.c

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,32 +1170,12 @@ void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
11701170
isb();
11711171
}
11721172

1173-
/*
1174-
* Read the pseudo-ZCR used by cpufeatures to identify the supported SVE
1175-
* vector length.
1176-
*
1177-
* Use only if SVE is present.
1178-
* This function clobbers the SVE vector length.
1179-
*/
1180-
u64 read_zcr_features(void)
1181-
{
1182-
/*
1183-
* Set the maximum possible VL, and write zeroes to all other
1184-
* bits to see if they stick.
1185-
*/
1186-
sve_kernel_enable(NULL);
1187-
write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL1);
1188-
1189-
/* Return LEN value that would be written to get the maximum VL */
1190-
return sve_vq_from_vl(sve_get_vl()) - 1;
1191-
}
1192-
11931173
void __init sve_setup(void)
11941174
{
11951175
struct vl_info *info = &vl_info[ARM64_VEC_SVE];
1196-
u64 zcr;
11971176
DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
11981177
unsigned long b;
1178+
int max_bit;
11991179

12001180
if (!system_supports_sve())
12011181
return;
@@ -1208,17 +1188,8 @@ void __init sve_setup(void)
12081188
if (WARN_ON(!test_bit(__vq_to_bit(SVE_VQ_MIN), info->vq_map)))
12091189
set_bit(__vq_to_bit(SVE_VQ_MIN), info->vq_map);
12101190

1211-
zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
1212-
info->max_vl = sve_vl_from_vq((zcr & ZCR_ELx_LEN_MASK) + 1);
1213-
1214-
/*
1215-
* Sanity-check that the max VL we determined through CPU features
1216-
* corresponds properly to sve_vq_map. If not, do our best:
1217-
*/
1218-
if (WARN_ON(info->max_vl != find_supported_vector_length(ARM64_VEC_SVE,
1219-
info->max_vl)))
1220-
info->max_vl = find_supported_vector_length(ARM64_VEC_SVE,
1221-
info->max_vl);
1191+
max_bit = find_first_bit(info->vq_map, SVE_VQ_MAX);
1192+
info->max_vl = sve_vl_from_vq(__bit_to_vq(max_bit));
12221193

12231194
/*
12241195
* For the default VL, pick the maximum supported value <= 64.

0 commit comments

Comments
 (0)