All vCPUs that are owned by a VM must have the same values of ID
registers.

Return an error at the very first KVM_RUN for a vCPU if the vCPU has
different values in any ID registers from any other vCPUs that have
already started KVM_RUN once.  Also, return an error if userspace
tries to change a value of ID register for a vCPU that already
started KVM_RUN once.

Changing ID register is still not allowed at present though.

Signed-off-by: Reiji Watanabe <rei...@google.com>
---
 arch/arm64/include/asm/kvm_host.h |  2 ++
 arch/arm64/kvm/arm.c              |  3 +++
 arch/arm64/kvm/sys_regs.c         | 31 +++++++++++++++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 0cd351099adf..69af669308b0 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -745,6 +745,8 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
 long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
                                struct kvm_arm_copy_mte_tags *copy_tags);
 
+int kvm_id_regs_consistency_check(const struct kvm_vcpu *vcpu);
+
 /* Guest/host FPSIMD coordination helpers */
 int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index fe102cd2e518..45ca72a37872 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -620,6 +620,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 
        ret = kvm_arm_pmu_v3_enable(vcpu);
 
+       if (kvm_id_regs_consistency_check(vcpu))
+               return -EPERM;
+
        return ret;
 }
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 8a0b88f9a975..2fe3121d50ca 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1331,6 +1331,10 @@ static int __set_id_reg(struct kvm_vcpu *vcpu,
        if (val != read_id_reg(vcpu, rd, raz) && !GET_ID_REG_INFO(encoding))
                return -EINVAL;
 
+       /* Don't allow to change the reg after the first KVM_RUN. */
+       if (vcpu->arch.has_run_once)
+               return -EINVAL;
+
        if (raz)
                return (val == 0) ? 0 : -EINVAL;
 
@@ -2901,6 +2905,33 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, 
u64 __user *uindices)
        return write_demux_regids(uindices);
 }
 
+int kvm_id_regs_consistency_check(const struct kvm_vcpu *vcpu)
+{
+       int i;
+       const struct kvm_vcpu *t_vcpu;
+
+       /*
+        * Make sure vcpu->arch.has_run_once is visible for others so that
+        * ID regs' consistency between two vCPUs is checked by either one
+        * at least.
+        */
+       smp_mb();
+       WARN_ON(!vcpu->arch.has_run_once);
+
+       kvm_for_each_vcpu(i, t_vcpu, vcpu->kvm) {
+               if (!t_vcpu->arch.has_run_once)
+                       /* ID regs still could be updated. */
+                       continue;
+
+               if (memcmp(&__vcpu_sys_reg(vcpu, ID_REG_BASE),
+                          &__vcpu_sys_reg(t_vcpu, ID_REG_BASE),
+                          sizeof(__vcpu_sys_reg(vcpu, ID_REG_BASE)) *
+                                       KVM_ARM_ID_REG_MAX_NUM))
+                       return -EINVAL;
+       }
+       return 0;
+}
+
 static void id_reg_info_init_all(void)
 {
        int i;
-- 
2.33.0.882.g93a45727a2-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to