aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--arch/x86/kvm/i8254.c20
-rw-r--r--arch/x86/kvm/i8259.c9
-rw-r--r--include/linux/kvm_host.h10
-rw-r--r--virt/kvm/coalesced_mmio.c8
-rw-r--r--virt/kvm/ioapic.c8
-rw-r--r--virt/kvm/kvm_main.c39
6 files changed, 79 insertions, 15 deletions
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 9b62c57ba6e4..137e54817102 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -605,6 +605,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
605{ 605{
606 struct kvm_pit *pit; 606 struct kvm_pit *pit;
607 struct kvm_kpit_state *pit_state; 607 struct kvm_kpit_state *pit_state;
608 int ret;
608 609
609 pit = kzalloc(sizeof(struct kvm_pit), GFP_KERNEL); 610 pit = kzalloc(sizeof(struct kvm_pit), GFP_KERNEL);
610 if (!pit) 611 if (!pit)
@@ -639,14 +640,29 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
639 kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); 640 kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
640 641
641 kvm_iodevice_init(&pit->dev, &pit_dev_ops); 642 kvm_iodevice_init(&pit->dev, &pit_dev_ops);
642 __kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev); 643 ret = __kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev);
644 if (ret < 0)
645 goto fail;
643 646
644 if (flags & KVM_PIT_SPEAKER_DUMMY) { 647 if (flags & KVM_PIT_SPEAKER_DUMMY) {
645 kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops); 648 kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops);
646 __kvm_io_bus_register_dev(&kvm->pio_bus, &pit->speaker_dev); 649 ret = __kvm_io_bus_register_dev(&kvm->pio_bus,
650 &pit->speaker_dev);
651 if (ret < 0)
652 goto fail_unregister;
647 } 653 }
648 654
649 return pit; 655 return pit;
656
657fail_unregister:
658 __kvm_io_bus_unregister_dev(&kvm->pio_bus, &pit->dev);
659
660fail:
661 if (pit->irq_source_id >= 0)
662 kvm_free_irq_source_id(kvm, pit->irq_source_id);
663
664 kfree(pit);
665 return NULL;
650} 666}
651 667
652void kvm_free_pit(struct kvm *kvm) 668void kvm_free_pit(struct kvm *kvm)
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index e4bcbddecb36..daf4606b0293 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -539,6 +539,8 @@ static const struct kvm_io_device_ops picdev_ops = {
539struct kvm_pic *kvm_create_pic(struct kvm *kvm) 539struct kvm_pic *kvm_create_pic(struct kvm *kvm)
540{ 540{
541 struct kvm_pic *s; 541 struct kvm_pic *s;
542 int ret;
543
542 s = kzalloc(sizeof(struct kvm_pic), GFP_KERNEL); 544 s = kzalloc(sizeof(struct kvm_pic), GFP_KERNEL);
543 if (!s) 545 if (!s)
544 return NULL; 546 return NULL;
@@ -555,6 +557,11 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
555 * Initialize PIO device 557 * Initialize PIO device
556 */ 558 */
557 kvm_iodevice_init(&s->dev, &picdev_ops); 559 kvm_iodevice_init(&s->dev, &picdev_ops);
558 kvm_io_bus_register_dev(kvm, &kvm->pio_bus, &s->dev); 560 ret = kvm_io_bus_register_dev(kvm, &kvm->pio_bus, &s->dev);
561 if (ret < 0) {
562 kfree(s);
563 return NULL;
564 }
565
559 return s; 566 return s;
560} 567}
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 077e8bb875a9..983b0bdeb3ff 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -64,10 +64,14 @@ int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len,
64 const void *val); 64 const void *val);
65int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, 65int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len,
66 void *val); 66 void *val);
67void __kvm_io_bus_register_dev(struct kvm_io_bus *bus, 67int __kvm_io_bus_register_dev(struct kvm_io_bus *bus,
68 struct kvm_io_device *dev);
69int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,
70 struct kvm_io_device *dev);
71void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus,
72 struct kvm_io_device *dev);
73void kvm_io_bus_unregister_dev(struct kvm *kvm, struct kvm_io_bus *bus,
68 struct kvm_io_device *dev); 74 struct kvm_io_device *dev);
69void kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,
70 struct kvm_io_device *dev);
71 75
72struct kvm_vcpu { 76struct kvm_vcpu {
73 struct kvm *kvm; 77 struct kvm *kvm;
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 = {