aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoffer Dall <christoffer.dall@linaro.org>2013-10-25 12:29:18 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2013-12-21 13:01:16 -0500
commit7330672befe6269e575f79b924a7068b26c144b4 (patch)
tree1eb2d427d0be36103633b623182b65e8a3dfbf42
parente1ba0207a1b3714bb3f000e506285ae5123cdfa7 (diff)
KVM: arm-vgic: Support KVM_CREATE_DEVICE for VGIC
Support creating the ARM VGIC device through the KVM_CREATE_DEVICE ioctl, which can then later be leveraged to use the KVM_{GET/SET}_DEVICE_ATTR, which is useful both for setting addresses in a more generic API than the ARM-specific one and is useful for save/restore of VGIC state. Adds KVM_CAP_DEVICE_CTRL to ARM capabilities. Note that we change the check for creating a VGIC from bailing out if any VCPUs were created, to bailing out if any VCPUs were ever run. This is an important distinction that shouldn't break anything, but allows creating the VGIC after the VCPUs have been created. Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r--Documentation/virtual/kvm/devices/arm-vgic.txt10
-rw-r--r--arch/arm/kvm/arm.c1
-rw-r--r--include/linux/kvm_host.h1
-rw-r--r--include/uapi/linux/kvm.h1
-rw-r--r--virt/kvm/arm/vgic.c63
-rw-r--r--virt/kvm/kvm_main.c5
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 @@
1ARM Virtual Generic Interrupt Controller (VGIC)
2===============================================
3
4Device types supported:
5 KVM_DEV_TYPE_ARM_VGIC_V2 ARM Generic Interrupt Controller v2.0
6
7Only one VGIC instance may be instantiated through either this API or the
8legacy KVM_CREATE_IRQCHIP api. The created VGIC will act as the VM interrupt
9controller, requiring emulated user-space devices to inject interrupts to the
10VGIC 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);
1075extern struct kvm_device_ops kvm_mpic_ops; 1075extern struct kvm_device_ops kvm_mpic_ops;
1076extern struct kvm_device_ops kvm_xics_ops; 1076extern struct kvm_device_ops kvm_xics_ops;
1077extern struct kvm_device_ops kvm_vfio_ops; 1077extern struct kvm_device_ops kvm_vfio_ops;
1078extern 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
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};
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 }