@@ -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);
@@ -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;
}
@@ -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;
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 <reijiw@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(+)