diff options
Diffstat (limited to 'virt/kvm/arm/vgic.c')
-rw-r--r-- | virt/kvm/arm/vgic.c | 63 |
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 | ||
1434 | int kvm_vgic_create(struct kvm *kvm) | 1434 | int 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 | ||
1469 | out_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 | |||
1450 | out: | 1475 | out: |
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 | |||
1539 | static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | ||
1540 | { | ||
1541 | return -ENXIO; | ||
1542 | } | ||
1543 | |||
1544 | static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | ||
1545 | { | ||
1546 | return -ENXIO; | ||
1547 | } | ||
1548 | |||
1549 | static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | ||
1550 | { | ||
1551 | return -ENXIO; | ||
1552 | } | ||
1553 | |||
1554 | static void vgic_destroy(struct kvm_device *dev) | ||
1555 | { | ||
1556 | kfree(dev); | ||
1557 | } | ||
1558 | |||
1559 | static int vgic_create(struct kvm_device *dev, u32 type) | ||
1560 | { | ||
1561 | return kvm_vgic_create(dev->kvm); | ||
1562 | } | ||
1563 | |||
1564 | struct 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 | }; | ||