aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorGregory Haskins <ghaskins@novell.com>2009-07-07 17:08:44 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:33:12 -0400
commit090b7aff27120cdae76a346a70db394844fea598 (patch)
tree4676410f57a44d7c0fba9d791fc77d7850ad1d51 /virt/kvm
parentfef07aae9cd9ed82f94228c311b35360f1f38902 (diff)
KVM: make io_bus interface more robust
Today kvm_io_bus_regsiter_dev() returns void and will internally BUG_ON if it fails. We want to create dynamic MMIO/PIO entries driven from userspace later in the series, so we need to enhance the code to be more robust with the following changes: 1) Add a return value to the registration function 2) Fix up all the callsites to check the return code, handle any failures, and percolate the error up to the caller. 3) Add an unregister function that collapses holes in the array Signed-off-by: Gregory Haskins <ghaskins@novell.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/coalesced_mmio.c8
-rw-r--r--virt/kvm/ioapic.c8
-rw-r--r--virt/kvm/kvm_main.c39
3 files changed, 46 insertions, 9 deletions
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 0352f81ecc0b..04d69cd7049b 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -92,6 +92,7 @@ static const struct kvm_io_device_ops coalesced_mmio_ops = {
92int kvm_coalesced_mmio_init(struct kvm *kvm) 92int kvm_coalesced_mmio_init(struct kvm *kvm)
93{ 93{
94 struct kvm_coalesced_mmio_dev *dev; 94 struct kvm_coalesced_mmio_dev *dev;
95 int ret;
95 96
96 dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL); 97 dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
97 if (!dev) 98 if (!dev)
@@ -100,9 +101,12 @@ int kvm_coalesced_mmio_init(struct kvm *kvm)
100 kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops); 101 kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops);
101 dev->kvm = kvm; 102 dev->kvm = kvm;
102 kvm->coalesced_mmio_dev = dev; 103 kvm->coalesced_mmio_dev = dev;
103 kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &dev->dev);
104 104
105 return 0; 105 ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &dev->dev);
106 if (ret < 0)
107 kfree(dev);
108
109 return ret;
106} 110}
107 111
108int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, 112int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index b91fbb215447..fa05f67423ab 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -342,6 +342,7 @@ static const struct kvm_io_device_ops ioapic_mmio_ops = {
342int kvm_ioapic_init(struct kvm *kvm) 342int kvm_ioapic_init(struct kvm *kvm)
343{ 343{
344 struct kvm_ioapic *ioapic; 344 struct kvm_ioapic *ioapic;
345 int ret;
345 346
346 ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL); 347 ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL);
347 if (!ioapic) 348 if (!ioapic)
@@ -350,7 +351,10 @@ int kvm_ioapic_init(struct kvm *kvm)
350 kvm_ioapic_reset(ioapic); 351 kvm_ioapic_reset(ioapic);
351 kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops); 352 kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops);
352 ioapic->kvm = kvm; 353 ioapic->kvm = kvm;
353 kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &ioapic->dev); 354 ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &ioapic->dev);
354 return 0; 355 if (ret < 0)
356 kfree(ioapic);
357
358 return ret;
355} 359}
356 360
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index fc1b58a72757..9c2fd025b8ae 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2533,21 +2533,50 @@ int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val)
2533 return -EOPNOTSUPP; 2533 return -EOPNOTSUPP;
2534} 2534}
2535 2535
2536void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, 2536int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,
2537 struct kvm_io_device *dev) 2537 struct kvm_io_device *dev)
2538{ 2538{
2539 int ret;
2540
2539 down_write(&kvm->slots_lock); 2541 down_write(&kvm->slots_lock);
2540 __kvm_io_bus_register_dev(bus, dev); 2542 ret = __kvm_io_bus_register_dev(bus, dev);
2541 up_write(&kvm->slots_lock); 2543 up_write(&kvm->slots_lock);
2544
2545 return ret;
2542} 2546}
2543 2547
2544/* An unlocked version. Caller must have write lock on slots_lock. */ 2548/* An unlocked version. Caller must have write lock on slots_lock. */
2545void __kvm_io_bus_register_dev(struct kvm_io_bus *bus, 2549int __kvm_io_bus_register_dev(struct kvm_io_bus *bus,
2546 struct kvm_io_device *dev) 2550 struct kvm_io_device *dev)
2547{ 2551{
2548 BUG_ON(bus->dev_count > (NR_IOBUS_DEVS-1)); 2552 if (bus->dev_count > NR_IOBUS_DEVS-1)
2553 return -ENOSPC;
2549 2554
2550 bus->devs[bus->dev_count++] = dev; 2555 bus->devs[bus->dev_count++] = dev;
2556
2557 return 0;
2558}
2559
2560void kvm_io_bus_unregister_dev(struct kvm *kvm,
2561 struct kvm_io_bus *bus,
2562 struct kvm_io_device *dev)
2563{
2564 down_write(&kvm->slots_lock);
2565 __kvm_io_bus_unregister_dev(bus, dev);
2566 up_write(&kvm->slots_lock);
2567}
2568
2569/* An unlocked version. Caller must have write lock on slots_lock. */
2570void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus,
2571 struct kvm_io_device *dev)
2572{
2573 int i;
2574
2575 for (i = 0; i < bus->dev_count; i++)
2576 if (bus->devs[i] == dev) {
2577 bus->devs[i] = bus->devs[--bus->dev_count];
2578 break;
2579 }
2551} 2580}
2552 2581
2553static struct notifier_block kvm_cpu_notifier = { 2582static struct notifier_block kvm_cpu_notifier = {