*/
 
 #include <linux/bitmap.h>
+#include <linux/bitops.h>
 #include <linux/bottom_half.h>
 #include <linux/bug.h>
 #include <linux/cache.h>
 #include <asm/sigcontext.h>
 #include <asm/sysreg.h>
 #include <asm/traps.h>
+#include <asm/virt.h>
 
 #define FPEXC_IOF      (1 << 0)
 #define FPEXC_DZF      (1 << 1)
 
 /* Maximum supported vector length across all CPUs (initially poisoned) */
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
+int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
 /* Set of available vector lengths, as vq_to_bit(vq): */
 static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+/* Set of vector lengths present on at least one cpu: */
+static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 static void __percpu *efi_sve_state;
 
 #else /* ! CONFIG_ARM64_SVE */
 
 /* Dummy declaration for code that will be optimised out: */
 extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 extern void __percpu *efi_sve_state;
 
 #endif /* ! CONFIG_ARM64_SVE */
        return sve_prctl_status(0);
 }
 
-/*
- * Bitmap for temporary storage of the per-CPU set of supported vector lengths
- * during secondary boot.
- */
-static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
-
 static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 {
        unsigned int vq, vl;
 void __init sve_init_vq_map(void)
 {
        sve_probe_vqs(sve_vq_map);
+       bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
 }
 
 /*
  */
 void sve_update_vq_map(void)
 {
-       sve_probe_vqs(sve_secondary_vq_map);
-       bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
+       DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+
+       sve_probe_vqs(tmp_map);
+       bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
+       bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
 }
 
 /*
  */
 int sve_verify_vq_map(void)
 {
-       int ret = 0;
+       DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+       unsigned long b;
 
-       sve_probe_vqs(sve_secondary_vq_map);
-       bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
-                     SVE_VQ_MAX);
-       if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
+       sve_probe_vqs(tmp_map);
+
+       bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
+       if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
                pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
                        smp_processor_id());
-               ret = -EINVAL;
+               return -EINVAL;
        }
 
-       return ret;
+       if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
+               return 0;
+
+       /*
+        * For KVM, it is necessary to ensure that this CPU doesn't
+        * support any vector length that guests may have probed as
+        * unsupported.
+        */
+
+       /* Recover the set of supported VQs: */
+       bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
+       /* Find VQs supported that are not globally supported: */
+       bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
+
+       /* Find the lowest such VQ, if any: */
+       b = find_last_bit(tmp_map, SVE_VQ_MAX);
+       if (b >= SVE_VQ_MAX)
+               return 0; /* no mismatches */
+
+       /*
+        * Mismatches above sve_max_virtualisable_vl are fine, since
+        * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
+        */
+       if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
+               pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
+                       smp_processor_id());
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 static void __init sve_efi_setup(void)
 void __init sve_setup(void)
 {
        u64 zcr;
+       DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+       unsigned long b;
 
        if (!system_supports_sve())
                return;
         */
        sve_default_vl = find_supported_vector_length(64);
 
+       bitmap_andnot(tmp_map, sve_vq_partial_map, sve_vq_map,
+                     SVE_VQ_MAX);
+
+       b = find_last_bit(tmp_map, SVE_VQ_MAX);
+       if (b >= SVE_VQ_MAX)
+               /* No non-virtualisable VLs found */
+               sve_max_virtualisable_vl = SVE_VQ_MAX;
+       else if (WARN_ON(b == SVE_VQ_MAX - 1))
+               /* No virtualisable VLs?  This is architecturally forbidden. */
+               sve_max_virtualisable_vl = SVE_VQ_MIN;
+       else /* b + 1 < SVE_VQ_MAX */
+               sve_max_virtualisable_vl = sve_vl_from_vq(bit_to_vq(b + 1));
+
+       if (sve_max_virtualisable_vl > sve_max_vl)
+               sve_max_virtualisable_vl = sve_max_vl;
+
        pr_info("SVE: maximum available vector length %u bytes per vector\n",
                sve_max_vl);
        pr_info("SVE: default vector length %u bytes per vector\n",
                sve_default_vl);
 
+       /* KVM decides whether to support mismatched systems. Just warn here: */
+       if (sve_max_virtualisable_vl < sve_max_vl)
+               pr_warn("SVE: unvirtualisable vector lengths present\n");
+
        sve_efi_setup();
 }