diff options
-rw-r--r-- | Documentation/virtual/kvm/devices/arm-vgic.txt | 10 | ||||
-rw-r--r-- | arch/arm/kvm/arm.c | 1 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/kvm.h | 1 | ||||
-rw-r--r-- | virt/kvm/arm/vgic.c | 63 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 5 |
6 files changed, 79 insertions, 2 deletions
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt new file mode 100644 index 000000000000..38f27f709a99 --- /dev/null +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt | |||
@@ -0,0 +1,10 @@ | |||
1 | ARM Virtual Generic Interrupt Controller (VGIC) | ||
2 | =============================================== | ||
3 | |||
4 | Device types supported: | ||
5 | KVM_DEV_TYPE_ARM_VGIC_V2 ARM Generic Interrupt Controller v2.0 | ||
6 | |||
7 | Only one VGIC instance may be instantiated through either this API or the | ||
8 | legacy KVM_CREATE_IRQCHIP api. The created VGIC will act as the VM interrupt | ||
9 | controller, requiring emulated user-space devices to inject interrupts to the | ||
10 | VGIC instead of directly to CPUs. | ||
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index c9fe9d71be73..cc7c41af9c38 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -190,6 +190,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
190 | case KVM_CAP_IRQCHIP: | 190 | case KVM_CAP_IRQCHIP: |
191 | r = vgic_present; | 191 | r = vgic_present; |
192 | break; | 192 | break; |
193 | case KVM_CAP_DEVICE_CTRL: | ||
193 | case KVM_CAP_USER_MEMORY: | 194 | case KVM_CAP_USER_MEMORY: |
194 | case KVM_CAP_SYNC_MMU: | 195 | case KVM_CAP_SYNC_MMU: |
195 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: | 196 | case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 4ecf10775c4f..1f46f66f60ab 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -1075,6 +1075,7 @@ struct kvm_device *kvm_device_from_filp(struct file *filp); | |||
1075 | extern struct kvm_device_ops kvm_mpic_ops; | 1075 | extern struct kvm_device_ops kvm_mpic_ops; |
1076 | extern struct kvm_device_ops kvm_xics_ops; | 1076 | extern struct kvm_device_ops kvm_xics_ops; |
1077 | extern struct kvm_device_ops kvm_vfio_ops; | 1077 | extern struct kvm_device_ops kvm_vfio_ops; |
1078 | extern struct kvm_device_ops kvm_arm_vgic_v2_ops; | ||
1078 | 1079 | ||
1079 | #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT | 1080 | #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT |
1080 | 1081 | ||
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 902f12461873..b647c2917391 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h | |||
@@ -853,6 +853,7 @@ struct kvm_device_attr { | |||
853 | #define KVM_DEV_VFIO_GROUP 1 | 853 | #define KVM_DEV_VFIO_GROUP 1 |
854 | #define KVM_DEV_VFIO_GROUP_ADD 1 | 854 | #define KVM_DEV_VFIO_GROUP_ADD 1 |
855 | #define KVM_DEV_VFIO_GROUP_DEL 2 | 855 | #define KVM_DEV_VFIO_GROUP_DEL 2 |
856 | #define KVM_DEV_TYPE_ARM_VGIC_V2 5 | ||
856 | 857 | ||
857 | /* | 858 | /* |
858 | * ioctls for VM fds | 859 | * ioctls for VM fds |
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 | }; | ||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 03c97e7ae4ca..3efba97bdce2 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -2273,6 +2273,11 @@ static int kvm_ioctl_create_device(struct kvm *kvm, | |||
2273 | ops = &kvm_vfio_ops; | 2273 | ops = &kvm_vfio_ops; |
2274 | break; | 2274 | break; |
2275 | #endif | 2275 | #endif |
2276 | #ifdef CONFIG_KVM_ARM_VGIC | ||
2277 | case KVM_DEV_TYPE_ARM_VGIC_V2: | ||
2278 | ops = &kvm_arm_vgic_v2_ops; | ||
2279 | break; | ||
2280 | #endif | ||
2276 | default: | 2281 | default: |
2277 | return -ENODEV; | 2282 | return -ENODEV; |
2278 | } | 2283 | } |