diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2009-12-23 11:35:24 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-03-01 10:35:45 -0500 |
commit | e93f8a0f821e290ac5149830110a5f704db7a1fc (patch) | |
tree | f88a5e97286031a8105d63a069a4131b74dab113 | |
parent | a983fb238728e1123177e8058d4f644b949a7d05 (diff) |
KVM: convert io_bus to SRCU
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 4 | ||||
-rw-r--r-- | arch/x86/kvm/i8254.c | 6 | ||||
-rw-r--r-- | arch/x86/kvm/i8259.c | 4 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 13 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 27 | ||||
-rw-r--r-- | virt/kvm/coalesced_mmio.c | 4 | ||||
-rw-r--r-- | virt/kvm/eventfd.c | 8 | ||||
-rw-r--r-- | virt/kvm/ioapic.c | 4 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 106 |
9 files changed, 101 insertions, 75 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index b2e4d16dd39e..d0ad538f0083 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -241,10 +241,10 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
241 | return 0; | 241 | return 0; |
242 | mmio: | 242 | mmio: |
243 | if (p->dir) | 243 | if (p->dir) |
244 | r = kvm_io_bus_read(&vcpu->kvm->mmio_bus, p->addr, | 244 | r = kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, p->addr, |
245 | p->size, &p->data); | 245 | p->size, &p->data); |
246 | else | 246 | else |
247 | r = kvm_io_bus_write(&vcpu->kvm->mmio_bus, p->addr, | 247 | r = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, p->addr, |
248 | p->size, &p->data); | 248 | p->size, &p->data); |
249 | if (r) | 249 | if (r) |
250 | printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr); | 250 | printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr); |
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 15578f180e59..4b433de02e5b 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c | |||
@@ -645,13 +645,13 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) | |||
645 | kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); | 645 | kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); |
646 | 646 | ||
647 | kvm_iodevice_init(&pit->dev, &pit_dev_ops); | 647 | kvm_iodevice_init(&pit->dev, &pit_dev_ops); |
648 | ret = __kvm_io_bus_register_dev(&kvm->pio_bus, &pit->dev); | 648 | ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &pit->dev); |
649 | if (ret < 0) | 649 | if (ret < 0) |
650 | goto fail; | 650 | goto fail; |
651 | 651 | ||
652 | if (flags & KVM_PIT_SPEAKER_DUMMY) { | 652 | if (flags & KVM_PIT_SPEAKER_DUMMY) { |
653 | kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops); | 653 | kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops); |
654 | ret = __kvm_io_bus_register_dev(&kvm->pio_bus, | 654 | ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, |
655 | &pit->speaker_dev); | 655 | &pit->speaker_dev); |
656 | if (ret < 0) | 656 | if (ret < 0) |
657 | goto fail_unregister; | 657 | goto fail_unregister; |
@@ -660,7 +660,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) | |||
660 | return pit; | 660 | return pit; |
661 | 661 | ||
662 | fail_unregister: | 662 | fail_unregister: |
663 | __kvm_io_bus_unregister_dev(&kvm->pio_bus, &pit->dev); | 663 | kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev); |
664 | 664 | ||
665 | fail: | 665 | fail: |
666 | if (pit->irq_source_id >= 0) | 666 | if (pit->irq_source_id >= 0) |
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index d057c0cbd245..b7d145b20953 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c | |||
@@ -533,7 +533,9 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm) | |||
533 | * Initialize PIO device | 533 | * Initialize PIO device |
534 | */ | 534 | */ |
535 | kvm_iodevice_init(&s->dev, &picdev_ops); | 535 | kvm_iodevice_init(&s->dev, &picdev_ops); |
536 | ret = kvm_io_bus_register_dev(kvm, &kvm->pio_bus, &s->dev); | 536 | down_write(&kvm->slots_lock); |
537 | ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, &s->dev); | ||
538 | up_write(&kvm->slots_lock); | ||
537 | if (ret < 0) { | 539 | if (ret < 0) { |
538 | kfree(s); | 540 | kfree(s); |
539 | return NULL; | 541 | return NULL; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 28127c936c3b..9b42673df4af 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -2851,7 +2851,7 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, | |||
2851 | !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v)) | 2851 | !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v)) |
2852 | return 0; | 2852 | return 0; |
2853 | 2853 | ||
2854 | return kvm_io_bus_write(&vcpu->kvm->mmio_bus, addr, len, v); | 2854 | return kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, len, v); |
2855 | } | 2855 | } |
2856 | 2856 | ||
2857 | static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) | 2857 | static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) |
@@ -2860,7 +2860,7 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) | |||
2860 | !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v)) | 2860 | !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v)) |
2861 | return 0; | 2861 | return 0; |
2862 | 2862 | ||
2863 | return kvm_io_bus_read(&vcpu->kvm->mmio_bus, addr, len, v); | 2863 | return kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, len, v); |
2864 | } | 2864 | } |
2865 | 2865 | ||
2866 | static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, | 2866 | static int kvm_read_guest_virt(gva_t addr, void *val, unsigned int bytes, |
@@ -3345,11 +3345,12 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) | |||
3345 | int r; | 3345 | int r; |
3346 | 3346 | ||
3347 | if (vcpu->arch.pio.in) | 3347 | if (vcpu->arch.pio.in) |
3348 | r = kvm_io_bus_read(&vcpu->kvm->pio_bus, vcpu->arch.pio.port, | 3348 | r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port, |
3349 | vcpu->arch.pio.size, pd); | 3349 | vcpu->arch.pio.size, pd); |
3350 | else | 3350 | else |
3351 | r = kvm_io_bus_write(&vcpu->kvm->pio_bus, vcpu->arch.pio.port, | 3351 | r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS, |
3352 | vcpu->arch.pio.size, pd); | 3352 | vcpu->arch.pio.port, vcpu->arch.pio.size, |
3353 | pd); | ||
3353 | return r; | 3354 | return r; |
3354 | } | 3355 | } |
3355 | 3356 | ||
@@ -3360,7 +3361,7 @@ static int pio_string_write(struct kvm_vcpu *vcpu) | |||
3360 | int i, r = 0; | 3361 | int i, r = 0; |
3361 | 3362 | ||
3362 | for (i = 0; i < io->cur_count; i++) { | 3363 | for (i = 0; i < io->cur_count; i++) { |
3363 | if (kvm_io_bus_write(&vcpu->kvm->pio_bus, | 3364 | if (kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS, |
3364 | io->port, io->size, pd)) { | 3365 | io->port, io->size, pd)) { |
3365 | r = -EOPNOTSUPP; | 3366 | r = -EOPNOTSUPP; |
3366 | break; | 3367 | break; |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 20941c0f4045..5e9cb902550b 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -57,20 +57,20 @@ struct kvm_io_bus { | |||
57 | struct kvm_io_device *devs[NR_IOBUS_DEVS]; | 57 | struct kvm_io_device *devs[NR_IOBUS_DEVS]; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | void kvm_io_bus_init(struct kvm_io_bus *bus); | 60 | enum kvm_bus { |
61 | void kvm_io_bus_destroy(struct kvm_io_bus *bus); | 61 | KVM_MMIO_BUS, |
62 | int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len, | 62 | KVM_PIO_BUS, |
63 | const void *val); | 63 | KVM_NR_BUSES |
64 | int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, | 64 | }; |
65 | |||
66 | int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, | ||
67 | int len, const void *val); | ||
68 | int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len, | ||
65 | void *val); | 69 | void *val); |
66 | int __kvm_io_bus_register_dev(struct kvm_io_bus *bus, | 70 | int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, |
67 | struct kvm_io_device *dev); | ||
68 | int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, | ||
69 | struct kvm_io_device *dev); | 71 | struct kvm_io_device *dev); |
70 | void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus, | 72 | int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, |
71 | struct kvm_io_device *dev); | 73 | struct kvm_io_device *dev); |
72 | void kvm_io_bus_unregister_dev(struct kvm *kvm, struct kvm_io_bus *bus, | ||
73 | struct kvm_io_device *dev); | ||
74 | 74 | ||
75 | struct kvm_vcpu { | 75 | struct kvm_vcpu { |
76 | struct kvm *kvm; | 76 | struct kvm *kvm; |
@@ -171,8 +171,7 @@ struct kvm { | |||
171 | atomic_t online_vcpus; | 171 | atomic_t online_vcpus; |
172 | struct list_head vm_list; | 172 | struct list_head vm_list; |
173 | struct mutex lock; | 173 | struct mutex lock; |
174 | struct kvm_io_bus mmio_bus; | 174 | struct kvm_io_bus *buses[KVM_NR_BUSES]; |
175 | struct kvm_io_bus pio_bus; | ||
176 | #ifdef CONFIG_HAVE_KVM_EVENTFD | 175 | #ifdef CONFIG_HAVE_KVM_EVENTFD |
177 | struct { | 176 | struct { |
178 | spinlock_t lock; | 177 | spinlock_t lock; |
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c index d68e6c68e0ff..a736a93ca7b7 100644 --- a/virt/kvm/coalesced_mmio.c +++ b/virt/kvm/coalesced_mmio.c | |||
@@ -110,7 +110,9 @@ int kvm_coalesced_mmio_init(struct kvm *kvm) | |||
110 | dev->kvm = kvm; | 110 | dev->kvm = kvm; |
111 | kvm->coalesced_mmio_dev = dev; | 111 | kvm->coalesced_mmio_dev = dev; |
112 | 112 | ||
113 | ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &dev->dev); | 113 | down_write(&kvm->slots_lock); |
114 | ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, &dev->dev); | ||
115 | up_write(&kvm->slots_lock); | ||
114 | if (ret < 0) | 116 | if (ret < 0) |
115 | goto out_free_dev; | 117 | goto out_free_dev; |
116 | 118 | ||
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index a9d3fc6c681c..315a586ec4d5 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c | |||
@@ -463,7 +463,7 @@ static int | |||
463 | kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) | 463 | kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) |
464 | { | 464 | { |
465 | int pio = args->flags & KVM_IOEVENTFD_FLAG_PIO; | 465 | int pio = args->flags & KVM_IOEVENTFD_FLAG_PIO; |
466 | struct kvm_io_bus *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus; | 466 | enum kvm_bus bus_idx = pio ? KVM_PIO_BUS : KVM_MMIO_BUS; |
467 | struct _ioeventfd *p; | 467 | struct _ioeventfd *p; |
468 | struct eventfd_ctx *eventfd; | 468 | struct eventfd_ctx *eventfd; |
469 | int ret; | 469 | int ret; |
@@ -518,7 +518,7 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) | |||
518 | 518 | ||
519 | kvm_iodevice_init(&p->dev, &ioeventfd_ops); | 519 | kvm_iodevice_init(&p->dev, &ioeventfd_ops); |
520 | 520 | ||
521 | ret = __kvm_io_bus_register_dev(bus, &p->dev); | 521 | ret = kvm_io_bus_register_dev(kvm, bus_idx, &p->dev); |
522 | if (ret < 0) | 522 | if (ret < 0) |
523 | goto unlock_fail; | 523 | goto unlock_fail; |
524 | 524 | ||
@@ -542,7 +542,7 @@ static int | |||
542 | kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) | 542 | kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) |
543 | { | 543 | { |
544 | int pio = args->flags & KVM_IOEVENTFD_FLAG_PIO; | 544 | int pio = args->flags & KVM_IOEVENTFD_FLAG_PIO; |
545 | struct kvm_io_bus *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus; | 545 | enum kvm_bus bus_idx = pio ? KVM_PIO_BUS : KVM_MMIO_BUS; |
546 | struct _ioeventfd *p, *tmp; | 546 | struct _ioeventfd *p, *tmp; |
547 | struct eventfd_ctx *eventfd; | 547 | struct eventfd_ctx *eventfd; |
548 | int ret = -ENOENT; | 548 | int ret = -ENOENT; |
@@ -565,7 +565,7 @@ kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) | |||
565 | if (!p->wildcard && p->datamatch != args->datamatch) | 565 | if (!p->wildcard && p->datamatch != args->datamatch) |
566 | continue; | 566 | continue; |
567 | 567 | ||
568 | __kvm_io_bus_unregister_dev(bus, &p->dev); | 568 | kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev); |
569 | ioeventfd_release(p); | 569 | ioeventfd_release(p); |
570 | ret = 0; | 570 | ret = 0; |
571 | break; | 571 | break; |
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 38a2d20b89de..f326a6f301cc 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -372,7 +372,9 @@ int kvm_ioapic_init(struct kvm *kvm) | |||
372 | kvm_ioapic_reset(ioapic); | 372 | kvm_ioapic_reset(ioapic); |
373 | kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops); | 373 | kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops); |
374 | ioapic->kvm = kvm; | 374 | ioapic->kvm = kvm; |
375 | ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &ioapic->dev); | 375 | down_write(&kvm->slots_lock); |
376 | ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, &ioapic->dev); | ||
377 | up_write(&kvm->slots_lock); | ||
376 | if (ret < 0) | 378 | if (ret < 0) |
377 | kfree(ioapic); | 379 | kfree(ioapic); |
378 | 380 | ||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index c680f7b64c6f..659bc12ad16a 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -85,6 +85,8 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, | |||
85 | static int hardware_enable_all(void); | 85 | static int hardware_enable_all(void); |
86 | static void hardware_disable_all(void); | 86 | static void hardware_disable_all(void); |
87 | 87 | ||
88 | static void kvm_io_bus_destroy(struct kvm_io_bus *bus); | ||
89 | |||
88 | static bool kvm_rebooting; | 90 | static bool kvm_rebooting; |
89 | 91 | ||
90 | static bool largepages_enabled = true; | 92 | static bool largepages_enabled = true; |
@@ -367,7 +369,7 @@ static int kvm_init_mmu_notifier(struct kvm *kvm) | |||
367 | 369 | ||
368 | static struct kvm *kvm_create_vm(void) | 370 | static struct kvm *kvm_create_vm(void) |
369 | { | 371 | { |
370 | int r = 0; | 372 | int r = 0, i; |
371 | struct kvm *kvm = kvm_arch_create_vm(); | 373 | struct kvm *kvm = kvm_arch_create_vm(); |
372 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 374 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
373 | struct page *page; | 375 | struct page *page; |
@@ -391,6 +393,14 @@ static struct kvm *kvm_create_vm(void) | |||
391 | goto out_err; | 393 | goto out_err; |
392 | if (init_srcu_struct(&kvm->srcu)) | 394 | if (init_srcu_struct(&kvm->srcu)) |
393 | goto out_err; | 395 | goto out_err; |
396 | for (i = 0; i < KVM_NR_BUSES; i++) { | ||
397 | kvm->buses[i] = kzalloc(sizeof(struct kvm_io_bus), | ||
398 | GFP_KERNEL); | ||
399 | if (!kvm->buses[i]) { | ||
400 | cleanup_srcu_struct(&kvm->srcu); | ||
401 | goto out_err; | ||
402 | } | ||
403 | } | ||
394 | 404 | ||
395 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 405 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
396 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); | 406 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); |
@@ -416,11 +426,9 @@ static struct kvm *kvm_create_vm(void) | |||
416 | atomic_inc(&kvm->mm->mm_count); | 426 | atomic_inc(&kvm->mm->mm_count); |
417 | spin_lock_init(&kvm->mmu_lock); | 427 | spin_lock_init(&kvm->mmu_lock); |
418 | spin_lock_init(&kvm->requests_lock); | 428 | spin_lock_init(&kvm->requests_lock); |
419 | kvm_io_bus_init(&kvm->pio_bus); | ||
420 | kvm_eventfd_init(kvm); | 429 | kvm_eventfd_init(kvm); |
421 | mutex_init(&kvm->lock); | 430 | mutex_init(&kvm->lock); |
422 | mutex_init(&kvm->irq_lock); | 431 | mutex_init(&kvm->irq_lock); |
423 | kvm_io_bus_init(&kvm->mmio_bus); | ||
424 | init_rwsem(&kvm->slots_lock); | 432 | init_rwsem(&kvm->slots_lock); |
425 | atomic_set(&kvm->users_count, 1); | 433 | atomic_set(&kvm->users_count, 1); |
426 | spin_lock(&kvm_lock); | 434 | spin_lock(&kvm_lock); |
@@ -435,6 +443,8 @@ out: | |||
435 | out_err: | 443 | out_err: |
436 | hardware_disable_all(); | 444 | hardware_disable_all(); |
437 | out_err_nodisable: | 445 | out_err_nodisable: |
446 | for (i = 0; i < KVM_NR_BUSES; i++) | ||
447 | kfree(kvm->buses[i]); | ||
438 | kfree(kvm->memslots); | 448 | kfree(kvm->memslots); |
439 | kfree(kvm); | 449 | kfree(kvm); |
440 | return ERR_PTR(r); | 450 | return ERR_PTR(r); |
@@ -480,6 +490,7 @@ void kvm_free_physmem(struct kvm *kvm) | |||
480 | 490 | ||
481 | static void kvm_destroy_vm(struct kvm *kvm) | 491 | static void kvm_destroy_vm(struct kvm *kvm) |
482 | { | 492 | { |
493 | int i; | ||
483 | struct mm_struct *mm = kvm->mm; | 494 | struct mm_struct *mm = kvm->mm; |
484 | 495 | ||
485 | kvm_arch_sync_events(kvm); | 496 | kvm_arch_sync_events(kvm); |
@@ -487,8 +498,8 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
487 | list_del(&kvm->vm_list); | 498 | list_del(&kvm->vm_list); |
488 | spin_unlock(&kvm_lock); | 499 | spin_unlock(&kvm_lock); |
489 | kvm_free_irq_routing(kvm); | 500 | kvm_free_irq_routing(kvm); |
490 | kvm_io_bus_destroy(&kvm->pio_bus); | 501 | for (i = 0; i < KVM_NR_BUSES; i++) |
491 | kvm_io_bus_destroy(&kvm->mmio_bus); | 502 | kvm_io_bus_destroy(kvm->buses[i]); |
492 | kvm_coalesced_mmio_free(kvm); | 503 | kvm_coalesced_mmio_free(kvm); |
493 | #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) | 504 | #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) |
494 | mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm); | 505 | mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm); |
@@ -1949,12 +1960,7 @@ static struct notifier_block kvm_reboot_notifier = { | |||
1949 | .priority = 0, | 1960 | .priority = 0, |
1950 | }; | 1961 | }; |
1951 | 1962 | ||
1952 | void kvm_io_bus_init(struct kvm_io_bus *bus) | 1963 | static void kvm_io_bus_destroy(struct kvm_io_bus *bus) |
1953 | { | ||
1954 | memset(bus, 0, sizeof(*bus)); | ||
1955 | } | ||
1956 | |||
1957 | void kvm_io_bus_destroy(struct kvm_io_bus *bus) | ||
1958 | { | 1964 | { |
1959 | int i; | 1965 | int i; |
1960 | 1966 | ||
@@ -1963,13 +1969,15 @@ void kvm_io_bus_destroy(struct kvm_io_bus *bus) | |||
1963 | 1969 | ||
1964 | kvm_iodevice_destructor(pos); | 1970 | kvm_iodevice_destructor(pos); |
1965 | } | 1971 | } |
1972 | kfree(bus); | ||
1966 | } | 1973 | } |
1967 | 1974 | ||
1968 | /* kvm_io_bus_write - called under kvm->slots_lock */ | 1975 | /* kvm_io_bus_write - called under kvm->slots_lock */ |
1969 | int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, | 1976 | int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, |
1970 | int len, const void *val) | 1977 | int len, const void *val) |
1971 | { | 1978 | { |
1972 | int i; | 1979 | int i; |
1980 | struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]); | ||
1973 | for (i = 0; i < bus->dev_count; i++) | 1981 | for (i = 0; i < bus->dev_count; i++) |
1974 | if (!kvm_iodevice_write(bus->devs[i], addr, len, val)) | 1982 | if (!kvm_iodevice_write(bus->devs[i], addr, len, val)) |
1975 | return 0; | 1983 | return 0; |
@@ -1977,59 +1985,71 @@ int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, | |||
1977 | } | 1985 | } |
1978 | 1986 | ||
1979 | /* kvm_io_bus_read - called under kvm->slots_lock */ | 1987 | /* kvm_io_bus_read - called under kvm->slots_lock */ |
1980 | int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) | 1988 | int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, |
1989 | int len, void *val) | ||
1981 | { | 1990 | { |
1982 | int i; | 1991 | int i; |
1992 | struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]); | ||
1993 | |||
1983 | for (i = 0; i < bus->dev_count; i++) | 1994 | for (i = 0; i < bus->dev_count; i++) |
1984 | if (!kvm_iodevice_read(bus->devs[i], addr, len, val)) | 1995 | if (!kvm_iodevice_read(bus->devs[i], addr, len, val)) |
1985 | return 0; | 1996 | return 0; |
1986 | return -EOPNOTSUPP; | 1997 | return -EOPNOTSUPP; |
1987 | } | 1998 | } |
1988 | 1999 | ||
1989 | int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus, | 2000 | /* Caller must have write lock on slots_lock. */ |
1990 | struct kvm_io_device *dev) | 2001 | int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, |
2002 | struct kvm_io_device *dev) | ||
1991 | { | 2003 | { |
1992 | int ret; | 2004 | struct kvm_io_bus *new_bus, *bus; |
1993 | |||
1994 | down_write(&kvm->slots_lock); | ||
1995 | ret = __kvm_io_bus_register_dev(bus, dev); | ||
1996 | up_write(&kvm->slots_lock); | ||
1997 | 2005 | ||
1998 | return ret; | 2006 | bus = kvm->buses[bus_idx]; |
1999 | } | ||
2000 | |||
2001 | /* An unlocked version. Caller must have write lock on slots_lock. */ | ||
2002 | int __kvm_io_bus_register_dev(struct kvm_io_bus *bus, | ||
2003 | struct kvm_io_device *dev) | ||
2004 | { | ||
2005 | if (bus->dev_count > NR_IOBUS_DEVS-1) | 2007 | if (bus->dev_count > NR_IOBUS_DEVS-1) |
2006 | return -ENOSPC; | 2008 | return -ENOSPC; |
2007 | 2009 | ||
2008 | bus->devs[bus->dev_count++] = dev; | 2010 | new_bus = kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL); |
2011 | if (!new_bus) | ||
2012 | return -ENOMEM; | ||
2013 | memcpy(new_bus, bus, sizeof(struct kvm_io_bus)); | ||
2014 | new_bus->devs[new_bus->dev_count++] = dev; | ||
2015 | rcu_assign_pointer(kvm->buses[bus_idx], new_bus); | ||
2016 | synchronize_srcu_expedited(&kvm->srcu); | ||
2017 | kfree(bus); | ||
2009 | 2018 | ||
2010 | return 0; | 2019 | return 0; |
2011 | } | 2020 | } |
2012 | 2021 | ||
2013 | void kvm_io_bus_unregister_dev(struct kvm *kvm, | 2022 | /* Caller must have write lock on slots_lock. */ |
2014 | struct kvm_io_bus *bus, | 2023 | int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, |
2015 | struct kvm_io_device *dev) | 2024 | struct kvm_io_device *dev) |
2016 | { | 2025 | { |
2017 | down_write(&kvm->slots_lock); | 2026 | int i, r; |
2018 | __kvm_io_bus_unregister_dev(bus, dev); | 2027 | struct kvm_io_bus *new_bus, *bus; |
2019 | up_write(&kvm->slots_lock); | ||
2020 | } | ||
2021 | 2028 | ||
2022 | /* An unlocked version. Caller must have write lock on slots_lock. */ | 2029 | new_bus = kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL); |
2023 | void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus, | 2030 | if (!new_bus) |
2024 | struct kvm_io_device *dev) | 2031 | return -ENOMEM; |
2025 | { | ||
2026 | int i; | ||
2027 | 2032 | ||
2028 | for (i = 0; i < bus->dev_count; i++) | 2033 | bus = kvm->buses[bus_idx]; |
2029 | if (bus->devs[i] == dev) { | 2034 | memcpy(new_bus, bus, sizeof(struct kvm_io_bus)); |
2030 | bus->devs[i] = bus->devs[--bus->dev_count]; | 2035 | |
2036 | r = -ENOENT; | ||
2037 | for (i = 0; i < new_bus->dev_count; i++) | ||
2038 | if (new_bus->devs[i] == dev) { | ||
2039 | r = 0; | ||
2040 | new_bus->devs[i] = new_bus->devs[--new_bus->dev_count]; | ||
2031 | break; | 2041 | break; |
2032 | } | 2042 | } |
2043 | |||
2044 | if (r) { | ||
2045 | kfree(new_bus); | ||
2046 | return r; | ||
2047 | } | ||
2048 | |||
2049 | rcu_assign_pointer(kvm->buses[bus_idx], new_bus); | ||
2050 | synchronize_srcu_expedited(&kvm->srcu); | ||
2051 | kfree(bus); | ||
2052 | return r; | ||
2033 | } | 2053 | } |
2034 | 2054 | ||
2035 | static struct notifier_block kvm_cpu_notifier = { | 2055 | static struct notifier_block kvm_cpu_notifier = { |