#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
 #define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
 
+/*
+ * number of register slices required to cover each whole SVE register on vcpu
+ * NOTE: If you are tempted to modify this, you must also to rework
+ * sve_reg_to_region() to match:
+ */
+#define vcpu_sve_slices(vcpu) 1
+
 /* Bounds of a single SVE register slice within vcpu->arch.sve_state */
 struct sve_state_reg_region {
        unsigned int koffset;   /* offset into sve_state in kernel memory */
        return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
 }
 
+static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
+{
+       /* Only the first slice ever exists, for now */
+       const unsigned int slices = vcpu_sve_slices(vcpu);
+
+       if (!vcpu_has_sve(vcpu))
+               return 0;
+
+       return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
+}
+
+static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu,
+                               u64 __user *uindices)
+{
+       /* Only the first slice ever exists, for now */
+       const unsigned int slices = vcpu_sve_slices(vcpu);
+       u64 reg;
+       unsigned int i, n;
+       int num_regs = 0;
+
+       if (!vcpu_has_sve(vcpu))
+               return 0;
+
+       for (i = 0; i < slices; i++) {
+               for (n = 0; n < SVE_NUM_ZREGS; n++) {
+                       reg = KVM_REG_ARM64_SVE_ZREG(n, i);
+                       if (put_user(reg, uindices++))
+                               return -EFAULT;
+
+                       num_regs++;
+               }
+
+               for (n = 0; n < SVE_NUM_PREGS; n++) {
+                       reg = KVM_REG_ARM64_SVE_PREG(n, i);
+                       if (put_user(reg, uindices++))
+                               return -EFAULT;
+
+                       num_regs++;
+               }
+
+               reg = KVM_REG_ARM64_SVE_FFR(i);
+               if (put_user(reg, uindices++))
+                       return -EFAULT;
+
+               num_regs++;
+       }
+
+       return num_regs;
+}
+
 /**
  * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
  *
        unsigned long res = 0;
 
        res += num_core_regs(vcpu);
+       res += num_sve_regs(vcpu);
        res += kvm_arm_num_sys_reg_descs(vcpu);
        res += kvm_arm_get_fw_num_regs(vcpu);
        res += NUM_TIMER_REGS;
                return ret;
        uindices += ret;
 
+       ret = copy_sve_reg_indices(vcpu, uindices);
+       if (ret)
+               return ret;
+       uindices += ret;
+
        ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
        if (ret)
                return ret;