|
@@ -1729,15 +1729,12 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
|
|
* Initialize the vgic_cpu struct and vgic_dist struct fields pertaining to
|
|
* Initialize the vgic_cpu struct and vgic_dist struct fields pertaining to
|
|
* this vcpu and enable the VGIC for this VCPU
|
|
* this vcpu and enable the VGIC for this VCPU
|
|
*/
|
|
*/
|
|
-int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
|
|
|
|
|
|
+static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
|
|
{
|
|
{
|
|
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
|
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
|
struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
|
|
struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
- if (vcpu->vcpu_id >= dist->nr_cpus)
|
|
|
|
- return -EBUSY;
|
|
|
|
-
|
|
|
|
for (i = 0; i < dist->nr_irqs; i++) {
|
|
for (i = 0; i < dist->nr_irqs; i++) {
|
|
if (i < VGIC_NR_PPIS)
|
|
if (i < VGIC_NR_PPIS)
|
|
vgic_bitmap_set_irq_val(&dist->irq_enabled,
|
|
vgic_bitmap_set_irq_val(&dist->irq_enabled,
|
|
@@ -1757,8 +1754,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
|
|
vgic_cpu->nr_lr = vgic->nr_lr;
|
|
vgic_cpu->nr_lr = vgic->nr_lr;
|
|
|
|
|
|
vgic_enable(vcpu);
|
|
vgic_enable(vcpu);
|
|
-
|
|
|
|
- return 0;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void kvm_vgic_destroy(struct kvm *kvm)
|
|
void kvm_vgic_destroy(struct kvm *kvm)
|
|
@@ -1802,8 +1797,17 @@ static int vgic_init_maps(struct kvm *kvm)
|
|
int nr_cpus, nr_irqs;
|
|
int nr_cpus, nr_irqs;
|
|
int ret, i;
|
|
int ret, i;
|
|
|
|
|
|
- nr_cpus = dist->nr_cpus = KVM_MAX_VCPUS;
|
|
|
|
|
|
+ if (dist->nr_cpus) /* Already allocated */
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ nr_cpus = dist->nr_cpus = atomic_read(&kvm->online_vcpus);
|
|
|
|
+ if (!nr_cpus) /* No vcpus? Can't be good... */
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If nobody configured the number of interrupts, use the
|
|
|
|
+ * legacy one.
|
|
|
|
+ */
|
|
if (!dist->nr_irqs)
|
|
if (!dist->nr_irqs)
|
|
dist->nr_irqs = VGIC_NR_IRQS_LEGACY;
|
|
dist->nr_irqs = VGIC_NR_IRQS_LEGACY;
|
|
|
|
|
|
@@ -1849,6 +1853,9 @@ static int vgic_init_maps(struct kvm *kvm)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ for (i = VGIC_NR_PRIVATE_IRQS; i < dist->nr_irqs; i += 4)
|
|
|
|
+ vgic_set_target_reg(kvm, 0, i);
|
|
|
|
+
|
|
out:
|
|
out:
|
|
if (ret)
|
|
if (ret)
|
|
kvm_vgic_destroy(kvm);
|
|
kvm_vgic_destroy(kvm);
|
|
@@ -1867,6 +1874,7 @@ out:
|
|
*/
|
|
*/
|
|
int kvm_vgic_init(struct kvm *kvm)
|
|
int kvm_vgic_init(struct kvm *kvm)
|
|
{
|
|
{
|
|
|
|
+ struct kvm_vcpu *vcpu;
|
|
int ret = 0, i;
|
|
int ret = 0, i;
|
|
|
|
|
|
if (!irqchip_in_kernel(kvm))
|
|
if (!irqchip_in_kernel(kvm))
|
|
@@ -1884,6 +1892,12 @@ int kvm_vgic_init(struct kvm *kvm)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ ret = vgic_init_maps(kvm);
|
|
|
|
+ if (ret) {
|
|
|
|
+ kvm_err("Unable to allocate maps\n");
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
|
|
ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
|
|
vgic->vcpu_base, KVM_VGIC_V2_CPU_SIZE);
|
|
vgic->vcpu_base, KVM_VGIC_V2_CPU_SIZE);
|
|
if (ret) {
|
|
if (ret) {
|
|
@@ -1891,11 +1905,13 @@ int kvm_vgic_init(struct kvm *kvm)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- for (i = VGIC_NR_PRIVATE_IRQS; i < kvm->arch.vgic.nr_irqs; i += 4)
|
|
|
|
- vgic_set_target_reg(kvm, 0, i);
|
|
|
|
|
|
+ kvm_for_each_vcpu(i, vcpu, kvm)
|
|
|
|
+ kvm_vgic_vcpu_init(vcpu);
|
|
|
|
|
|
kvm->arch.vgic.ready = true;
|
|
kvm->arch.vgic.ready = true;
|
|
out:
|
|
out:
|
|
|
|
+ if (ret)
|
|
|
|
+ kvm_vgic_destroy(kvm);
|
|
mutex_unlock(&kvm->lock);
|
|
mutex_unlock(&kvm->lock);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -1936,10 +1952,6 @@ int kvm_vgic_create(struct kvm *kvm)
|
|
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
|
|
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
|
|
kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
|
|
kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
|
|
|
|
|
|
- ret = vgic_init_maps(kvm);
|
|
|
|
- if (ret)
|
|
|
|
- kvm_err("Unable to allocate maps\n");
|
|
|
|
-
|
|
|
|
out_unlock:
|
|
out_unlock:
|
|
for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
|
|
for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
|
|
vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
|
|
vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
|
|
@@ -2140,6 +2152,10 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
|
|
|
|
|
|
mutex_lock(&dev->kvm->lock);
|
|
mutex_lock(&dev->kvm->lock);
|
|
|
|
|
|
|
|
+ ret = vgic_init_maps(dev->kvm);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
|
|
if (cpuid >= atomic_read(&dev->kvm->online_vcpus)) {
|
|
ret = -EINVAL;
|
|
ret = -EINVAL;
|
|
goto out;
|
|
goto out;
|