Skip to content

Commit e93f8a0

Browse files
committed
KVM: convert io_bus to SRCU
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
1 parent a983fb2 commit e93f8a0

File tree

9 files changed

+101
-75
lines changed

9 files changed

+101
-75
lines changed

arch/ia64/kvm/kvm-ia64.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,10 @@ static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
241241
return 0;
242242
mmio:
243243
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,
245245
p->size, &p->data);
246246
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,
248248
p->size, &p->data);
249249
if (r)
250250
printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);

arch/x86/kvm/i8254.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -645,13 +645,13 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
645645
kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
646646

647647
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);
649649
if (ret < 0)
650650
goto fail;
651651

652652
if (flags & KVM_PIT_SPEAKER_DUMMY) {
653653
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,
655655
&pit->speaker_dev);
656656
if (ret < 0)
657657
goto fail_unregister;
@@ -660,7 +660,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
660660
return pit;
661661

662662
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);
664664

665665
fail:
666666
if (pit->irq_source_id >= 0)

arch/x86/kvm/i8259.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,9 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
533533
* Initialize PIO device
534534
*/
535535
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);
537539
if (ret < 0) {
538540
kfree(s);
539541
return NULL;

arch/x86/kvm/x86.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2851,7 +2851,7 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
28512851
!kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v))
28522852
return 0;
28532853

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);
28552855
}
28562856

28572857
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)
28602860
!kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v))
28612861
return 0;
28622862

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);
28642864
}
28652865

28662866
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)
33453345
int r;
33463346

33473347
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,
33493349
vcpu->arch.pio.size, pd);
33503350
else
3351-
r = kvm_io_bus_write(&vcpu->kvm->pio_bus, vcpu->arch.pio.port,
3352-
vcpu->arch.pio.size, pd);
3351+
r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
3352+
vcpu->arch.pio.port, vcpu->arch.pio.size,
3353+
pd);
33533354
return r;
33543355
}
33553356

@@ -3360,7 +3361,7 @@ static int pio_string_write(struct kvm_vcpu *vcpu)
33603361
int i, r = 0;
33613362

33623363
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,
33643365
io->port, io->size, pd)) {
33653366
r = -EOPNOTSUPP;
33663367
break;

include/linux/kvm_host.h

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,20 @@ struct kvm_io_bus {
5757
struct kvm_io_device *devs[NR_IOBUS_DEVS];
5858
};
5959

60-
void kvm_io_bus_init(struct kvm_io_bus *bus);
61-
void kvm_io_bus_destroy(struct kvm_io_bus *bus);
62-
int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len,
63-
const void *val);
64-
int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len,
60+
enum kvm_bus {
61+
KVM_MMIO_BUS,
62+
KVM_PIO_BUS,
63+
KVM_NR_BUSES
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,
6569
void *val);
66-
int __kvm_io_bus_register_dev(struct kvm_io_bus *bus,
67-
struct kvm_io_device *dev);
68-
int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,
70+
int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx,
6971
struct kvm_io_device *dev);
70-
void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus,
71-
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);
72+
int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
73+
struct kvm_io_device *dev);
7474

7575
struct kvm_vcpu {
7676
struct kvm *kvm;
@@ -171,8 +171,7 @@ struct kvm {
171171
atomic_t online_vcpus;
172172
struct list_head vm_list;
173173
struct mutex lock;
174-
struct kvm_io_bus mmio_bus;
175-
struct kvm_io_bus pio_bus;
174+
struct kvm_io_bus *buses[KVM_NR_BUSES];
176175
#ifdef CONFIG_HAVE_KVM_EVENTFD
177176
struct {
178177
spinlock_t lock;

virt/kvm/coalesced_mmio.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ int kvm_coalesced_mmio_init(struct kvm *kvm)
110110
dev->kvm = kvm;
111111
kvm->coalesced_mmio_dev = dev;
112112

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);
114116
if (ret < 0)
115117
goto out_free_dev;
116118

virt/kvm/eventfd.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ static int
463463
kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
464464
{
465465
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;
467467
struct _ioeventfd *p;
468468
struct eventfd_ctx *eventfd;
469469
int ret;
@@ -518,7 +518,7 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
518518

519519
kvm_iodevice_init(&p->dev, &ioeventfd_ops);
520520

521-
ret = __kvm_io_bus_register_dev(bus, &p->dev);
521+
ret = kvm_io_bus_register_dev(kvm, bus_idx, &p->dev);
522522
if (ret < 0)
523523
goto unlock_fail;
524524

@@ -542,7 +542,7 @@ static int
542542
kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
543543
{
544544
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;
546546
struct _ioeventfd *p, *tmp;
547547
struct eventfd_ctx *eventfd;
548548
int ret = -ENOENT;
@@ -565,7 +565,7 @@ kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
565565
if (!p->wildcard && p->datamatch != args->datamatch)
566566
continue;
567567

568-
__kvm_io_bus_unregister_dev(bus, &p->dev);
568+
kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
569569
ioeventfd_release(p);
570570
ret = 0;
571571
break;

virt/kvm/ioapic.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,9 @@ int kvm_ioapic_init(struct kvm *kvm)
372372
kvm_ioapic_reset(ioapic);
373373
kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops);
374374
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);
376378
if (ret < 0)
377379
kfree(ioapic);
378380

virt/kvm/kvm_main.c

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
8585
static int hardware_enable_all(void);
8686
static void hardware_disable_all(void);
8787

88+
static void kvm_io_bus_destroy(struct kvm_io_bus *bus);
89+
8890
static bool kvm_rebooting;
8991

9092
static bool largepages_enabled = true;
@@ -367,7 +369,7 @@ static int kvm_init_mmu_notifier(struct kvm *kvm)
367369

368370
static struct kvm *kvm_create_vm(void)
369371
{
370-
int r = 0;
372+
int r = 0, i;
371373
struct kvm *kvm = kvm_arch_create_vm();
372374
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
373375
struct page *page;
@@ -391,6 +393,14 @@ static struct kvm *kvm_create_vm(void)
391393
goto out_err;
392394
if (init_srcu_struct(&kvm->srcu))
393395
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+
}
394404

395405
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
396406
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
@@ -416,11 +426,9 @@ static struct kvm *kvm_create_vm(void)
416426
atomic_inc(&kvm->mm->mm_count);
417427
spin_lock_init(&kvm->mmu_lock);
418428
spin_lock_init(&kvm->requests_lock);
419-
kvm_io_bus_init(&kvm->pio_bus);
420429
kvm_eventfd_init(kvm);
421430
mutex_init(&kvm->lock);
422431
mutex_init(&kvm->irq_lock);
423-
kvm_io_bus_init(&kvm->mmio_bus);
424432
init_rwsem(&kvm->slots_lock);
425433
atomic_set(&kvm->users_count, 1);
426434
spin_lock(&kvm_lock);
@@ -435,6 +443,8 @@ static struct kvm *kvm_create_vm(void)
435443
out_err:
436444
hardware_disable_all();
437445
out_err_nodisable:
446+
for (i = 0; i < KVM_NR_BUSES; i++)
447+
kfree(kvm->buses[i]);
438448
kfree(kvm->memslots);
439449
kfree(kvm);
440450
return ERR_PTR(r);
@@ -480,15 +490,16 @@ void kvm_free_physmem(struct kvm *kvm)
480490

481491
static void kvm_destroy_vm(struct kvm *kvm)
482492
{
493+
int i;
483494
struct mm_struct *mm = kvm->mm;
484495

485496
kvm_arch_sync_events(kvm);
486497
spin_lock(&kvm_lock);
487498
list_del(&kvm->vm_list);
488499
spin_unlock(&kvm_lock);
489500
kvm_free_irq_routing(kvm);
490-
kvm_io_bus_destroy(&kvm->pio_bus);
491-
kvm_io_bus_destroy(&kvm->mmio_bus);
501+
for (i = 0; i < KVM_NR_BUSES; i++)
502+
kvm_io_bus_destroy(kvm->buses[i]);
492503
kvm_coalesced_mmio_free(kvm);
493504
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
494505
mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
@@ -1949,12 +1960,7 @@ static struct notifier_block kvm_reboot_notifier = {
19491960
.priority = 0,
19501961
};
19511962

1952-
void kvm_io_bus_init(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)
1963+
static void kvm_io_bus_destroy(struct kvm_io_bus *bus)
19581964
{
19591965
int i;
19601966

@@ -1963,73 +1969,87 @@ void kvm_io_bus_destroy(struct kvm_io_bus *bus)
19631969

19641970
kvm_iodevice_destructor(pos);
19651971
}
1972+
kfree(bus);
19661973
}
19671974

19681975
/* 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,
19701977
int len, const void *val)
19711978
{
19721979
int i;
1980+
struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]);
19731981
for (i = 0; i < bus->dev_count; i++)
19741982
if (!kvm_iodevice_write(bus->devs[i], addr, len, val))
19751983
return 0;
19761984
return -EOPNOTSUPP;
19771985
}
19781986

19791987
/* 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)
19811990
{
19821991
int i;
1992+
struct kvm_io_bus *bus = rcu_dereference(kvm->buses[bus_idx]);
1993+
19831994
for (i = 0; i < bus->dev_count; i++)
19841995
if (!kvm_iodevice_read(bus->devs[i], addr, len, val))
19851996
return 0;
19861997
return -EOPNOTSUPP;
19871998
}
19881999

1989-
int kvm_io_bus_register_dev(struct kvm *kvm, struct kvm_io_bus *bus,
1990-
struct kvm_io_device *dev)
2000+
/* Caller must have write lock on slots_lock. */
2001+
int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx,
2002+
struct kvm_io_device *dev)
19912003
{
1992-
int ret;
1993-
1994-
down_write(&kvm->slots_lock);
1995-
ret = __kvm_io_bus_register_dev(bus, dev);
1996-
up_write(&kvm->slots_lock);
2004+
struct kvm_io_bus *new_bus, *bus;
19972005

1998-
return ret;
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-
{
2006+
bus = kvm->buses[bus_idx];
20052007
if (bus->dev_count > NR_IOBUS_DEVS-1)
20062008
return -ENOSPC;
20072009

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);
20092018

20102019
return 0;
20112020
}
20122021

2013-
void kvm_io_bus_unregister_dev(struct kvm *kvm,
2014-
struct kvm_io_bus *bus,
2015-
struct kvm_io_device *dev)
2022+
/* Caller must have write lock on slots_lock. */
2023+
int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
2024+
struct kvm_io_device *dev)
20162025
{
2017-
down_write(&kvm->slots_lock);
2018-
__kvm_io_bus_unregister_dev(bus, dev);
2019-
up_write(&kvm->slots_lock);
2020-
}
2026+
int i, r;
2027+
struct kvm_io_bus *new_bus, *bus;
20212028

2022-
/* An unlocked version. Caller must have write lock on slots_lock. */
2023-
void __kvm_io_bus_unregister_dev(struct kvm_io_bus *bus,
2024-
struct kvm_io_device *dev)
2025-
{
2026-
int i;
2029+
new_bus = kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL);
2030+
if (!new_bus)
2031+
return -ENOMEM;
20272032

2028-
for (i = 0; i < bus->dev_count; i++)
2029-
if (bus->devs[i] == dev) {
2030-
bus->devs[i] = bus->devs[--bus->dev_count];
2033+
bus = kvm->buses[bus_idx];
2034+
memcpy(new_bus, bus, sizeof(struct kvm_io_bus));
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];
20312041
break;
20322042
}
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;
20332053
}
20342054

20352055
static struct notifier_block kvm_cpu_notifier = {

0 commit comments

Comments
 (0)