ARM64_FTR_END,
 };
 
-static const struct arm64_ftr_bits ftr_zcr[] = {
-       ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE,
-               ZCR_ELx_LEN_SHIFT, ZCR_ELx_LEN_WIDTH, 0),       /* LEN */
-       ARM64_FTR_END,
-};
-
 static const struct arm64_ftr_bits ftr_smcr[] = {
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE,
                SMCR_ELx_LEN_SHIFT, SMCR_ELx_LEN_WIDTH, 0),     /* LEN */
        ARM64_FTR_REG(SYS_ID_AA64MMFR3_EL1, ftr_id_aa64mmfr3),
 
        /* Op1 = 0, CRn = 1, CRm = 2 */
-       ARM64_FTR_REG(SYS_ZCR_EL1, ftr_zcr),
        ARM64_FTR_REG(SYS_SMCR_EL1, ftr_smcr),
 
        /* Op1 = 1, CRn = 0, CRm = 0 */
 
        if (IS_ENABLED(CONFIG_ARM64_SVE) &&
            id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
-               info->reg_zcr = read_zcr_features();
-               init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
+               sve_kernel_enable(NULL);
                vec_init_vq_map(ARM64_VEC_SVE);
        }
 
        taint |= check_update_ftr_reg(SYS_ID_AA64SMFR0_EL1, cpu,
                                      info->reg_id_aa64smfr0, boot->reg_id_aa64smfr0);
 
+       /* Probe vector lengths */
        if (IS_ENABLED(CONFIG_ARM64_SVE) &&
            id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1))) {
-               info->reg_zcr = read_zcr_features();
-               taint |= check_update_ftr_reg(SYS_ZCR_EL1, cpu,
-                                       info->reg_zcr, boot->reg_zcr);
-
-               /* Probe vector lengths */
-               if (!system_capabilities_finalized())
+               if (!system_capabilities_finalized()) {
+                       sve_kernel_enable(NULL);
                        vec_update_vq_map(ARM64_VEC_SVE);
+               }
        }
 
        if (IS_ENABLED(CONFIG_ARM64_SME) &&
 
 static void verify_sve_features(void)
 {
-       u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
-       u64 zcr = read_zcr_features();
-
-       unsigned int safe_len = safe_zcr & ZCR_ELx_LEN_MASK;
-       unsigned int len = zcr & ZCR_ELx_LEN_MASK;
-
-       if (len < safe_len || vec_verify_vq_map(ARM64_VEC_SVE)) {
+       if (vec_verify_vq_map(ARM64_VEC_SVE)) {
                pr_crit("CPU%d: SVE: vector length support mismatch\n",
                        smp_processor_id());
                cpu_die_early();
        }
-
-       /* Add checks on other ZCR bits here if necessary */
 }
 
 static void verify_sme_features(void)
 
        isb();
 }
 
-/*
- * Read the pseudo-ZCR used by cpufeatures to identify the supported SVE
- * vector length.
- *
- * Use only if SVE is present.
- * This function clobbers the SVE vector length.
- */
-u64 read_zcr_features(void)
-{
-       /*
-        * Set the maximum possible VL, and write zeroes to all other
-        * bits to see if they stick.
-        */
-       sve_kernel_enable(NULL);
-       write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL1);
-
-       /* Return LEN value that would be written to get the maximum VL */
-       return sve_vq_from_vl(sve_get_vl()) - 1;
-}
-
 void __init sve_setup(void)
 {
        struct vl_info *info = &vl_info[ARM64_VEC_SVE];
-       u64 zcr;
        DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
        unsigned long b;
+       int max_bit;
 
        if (!system_supports_sve())
                return;
        if (WARN_ON(!test_bit(__vq_to_bit(SVE_VQ_MIN), info->vq_map)))
                set_bit(__vq_to_bit(SVE_VQ_MIN), info->vq_map);
 
-       zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
-       info->max_vl = sve_vl_from_vq((zcr & ZCR_ELx_LEN_MASK) + 1);
-
-       /*
-        * Sanity-check that the max VL we determined through CPU features
-        * corresponds properly to sve_vq_map.  If not, do our best:
-        */
-       if (WARN_ON(info->max_vl != find_supported_vector_length(ARM64_VEC_SVE,
-                                                                info->max_vl)))
-               info->max_vl = find_supported_vector_length(ARM64_VEC_SVE,
-                                                           info->max_vl);
+       max_bit = find_first_bit(info->vq_map, SVE_VQ_MAX);
+       info->max_vl = sve_vl_from_vq(__bit_to_vq(max_bit));
 
        /*
         * For the default VL, pick the maximum supported value <= 64.