aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/arm/vgic.c
diff options
context:
space:
mode:
Diffstat (limited to 'virt/kvm/arm/vgic.c')
-rw-r--r--virt/kvm/arm/vgic.c63
1 files changed, 61 insertions, 2 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 5e9df47778fb..b15d6c17a090 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1433,20 +1433,45 @@ out:
1433 1433
1434int kvm_vgic_create(struct kvm *kvm) 1434int kvm_vgic_create(struct kvm *kvm)
1435{ 1435{
1436 int ret = 0; 1436 int i, vcpu_lock_idx = -1, ret = 0;
1437 struct kvm_vcpu *vcpu;
1437 1438
1438 mutex_lock(&kvm->lock); 1439 mutex_lock(&kvm->lock);
1439 1440
1440 if (atomic_read(&kvm->online_vcpus) || kvm->arch.vgic.vctrl_base) { 1441 if (kvm->arch.vgic.vctrl_base) {
1441 ret = -EEXIST; 1442 ret = -EEXIST;
1442 goto out; 1443 goto out;
1443 } 1444 }
1444 1445
1446 /*
1447 * Any time a vcpu is run, vcpu_load is called which tries to grab the
1448 * vcpu->mutex. By grabbing the vcpu->mutex of all VCPUs we ensure
1449 * that no other VCPUs are run while we create the vgic.
1450 */
1451 kvm_for_each_vcpu(i, vcpu, kvm) {
1452 if (!mutex_trylock(&vcpu->mutex))
1453 goto out_unlock;
1454 vcpu_lock_idx = i;
1455 }
1456
1457 kvm_for_each_vcpu(i, vcpu, kvm) {
1458 if (vcpu->arch.has_run_once) {
1459 ret = -EBUSY;
1460 goto out_unlock;
1461 }
1462 }
1463
1445 spin_lock_init(&kvm->arch.vgic.lock); 1464 spin_lock_init(&kvm->arch.vgic.lock);
1446 kvm->arch.vgic.vctrl_base = vgic_vctrl_base; 1465 kvm->arch.vgic.vctrl_base = vgic_vctrl_base;
1447 kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; 1466 kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
1448 kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; 1467 kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
1449 1468
1469out_unlock:
1470 for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
1471 vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
1472 mutex_unlock(&vcpu->mutex);
1473 }
1474
1450out: 1475out:
1451 mutex_unlock(&kvm->lock); 1476 mutex_unlock(&kvm->lock);
1452 return ret; 1477 return ret;
@@ -1510,3 +1535,37 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
1510 mutex_unlock(&kvm->lock); 1535 mutex_unlock(&kvm->lock);
1511 return r; 1536 return r;
1512} 1537}
1538
1539static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1540{
1541 return -ENXIO;
1542}
1543
1544static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1545{
1546 return -ENXIO;
1547}
1548
1549static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
1550{
1551 return -ENXIO;
1552}
1553
1554static void vgic_destroy(struct kvm_device *dev)
1555{
1556 kfree(dev);
1557}
1558
1559static int vgic_create(struct kvm_device *dev, u32 type)
1560{
1561 return kvm_vgic_create(dev->kvm);
1562}
1563
1564struct kvm_device_ops kvm_arm_vgic_v2_ops = {
1565 .name = "kvm-arm-vgic",
1566 .create = vgic_create,
1567 .destroy = vgic_destroy,
1568 .set_attr = vgic_set_attr,
1569 .get_attr = vgic_get_attr,
1570 .has_attr = vgic_has_attr,
1571};