|
@@ -1319,13 +1319,13 @@ void vgic_enable_lpis(struct kvm_vcpu *vcpu)
|
|
|
its_sync_lpi_pending_table(vcpu);
|
|
|
}
|
|
|
|
|
|
-static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
|
|
|
+static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
|
|
|
{
|
|
|
struct vgic_io_device *iodev = &its->iodev;
|
|
|
int ret;
|
|
|
|
|
|
- if (its->initialized)
|
|
|
- return 0;
|
|
|
+ if (!its->initialized)
|
|
|
+ return -EBUSY;
|
|
|
|
|
|
if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
|
|
|
return -ENXIO;
|
|
@@ -1342,9 +1342,6 @@ static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
|
|
|
KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
|
|
|
mutex_unlock(&kvm->slots_lock);
|
|
|
|
|
|
- if (!ret)
|
|
|
- its->initialized = true;
|
|
|
-
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1466,9 +1463,6 @@ static int vgic_its_set_attr(struct kvm_device *dev,
|
|
|
if (type != KVM_VGIC_ITS_ADDR_TYPE)
|
|
|
return -ENODEV;
|
|
|
|
|
|
- if (its->initialized)
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
if (copy_from_user(&addr, uaddr, sizeof(addr)))
|
|
|
return -EFAULT;
|
|
|
|
|
@@ -1484,7 +1478,9 @@ static int vgic_its_set_attr(struct kvm_device *dev,
|
|
|
case KVM_DEV_ARM_VGIC_GRP_CTRL:
|
|
|
switch (attr->attr) {
|
|
|
case KVM_DEV_ARM_VGIC_CTRL_INIT:
|
|
|
- return vgic_its_init_its(dev->kvm, its);
|
|
|
+ its->initialized = true;
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
@@ -1529,3 +1525,30 @@ int kvm_vgic_register_its_device(void)
|
|
|
return kvm_register_device_ops(&kvm_arm_vgic_its_ops,
|
|
|
KVM_DEV_TYPE_ARM_VGIC_ITS);
|
|
|
}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Registers all ITSes with the kvm_io_bus framework.
|
|
|
+ * To follow the existing VGIC initialization sequence, this has to be
|
|
|
+ * done as late as possible, just before the first VCPU runs.
|
|
|
+ */
|
|
|
+int vgic_register_its_iodevs(struct kvm *kvm)
|
|
|
+{
|
|
|
+ struct kvm_device *dev;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ list_for_each_entry(dev, &kvm->devices, vm_node) {
|
|
|
+ if (dev->ops != &kvm_arm_vgic_its_ops)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ ret = vgic_register_its_iodev(kvm, dev->private);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ /*
|
|
|
+ * We don't need to care about tearing down previously
|
|
|
+ * registered ITSes, as the kvm_io_bus framework removes
|
|
|
+ * them for us if the VM gets destroyed.
|
|
|
+ */
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|