diff options
author | Sasha Levin <levinsasha928@gmail.com> | 2011-07-27 09:00:48 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-09-25 12:17:59 -0400 |
commit | 743eeb0b01d2fbf4154bf87bff1ebb6fb18aeb7a (patch) | |
tree | 5392464930f7e77131d65f32ba96ce4665307629 /include | |
parent | 0d460ffc0956d2dbe12ca9f5f6aa0f8701ea9d73 (diff) |
KVM: Intelligent device lookup on I/O bus
Currently the method of dealing with an IO operation on a bus (PIO/MMIO)
is to call the read or write callback for each device registered
on the bus until we find a device which handles it.
Since the number of devices on a bus can be significant due to ioeventfds
and coalesced MMIO zones, this leads to a lot of overhead on each IO
operation.
Instead of registering devices, we now register ranges which points to
a device. Lookup is done using an efficient bsearch instead of a linear
search.
Performance test was conducted by comparing exit count per second with
200 ioeventfds created on one byte and the guest is trying to access a
different byte continuously (triggering usermode exits).
Before the patch the guest has achieved 259k exits per second, after the
patch the guest does 274k exits per second.
Cc: Avi Kivity <avi@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/kvm_host.h | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index ff4d4062af9d..d0e42f30edf6 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -55,16 +55,16 @@ struct kvm; | |||
55 | struct kvm_vcpu; | 55 | struct kvm_vcpu; |
56 | extern struct kmem_cache *kvm_vcpu_cache; | 56 | extern struct kmem_cache *kvm_vcpu_cache; |
57 | 57 | ||
58 | /* | 58 | struct kvm_io_range { |
59 | * It would be nice to use something smarter than a linear search, TBD... | 59 | gpa_t addr; |
60 | * Thankfully we dont expect many devices to register (famous last words :), | 60 | int len; |
61 | * so until then it will suffice. At least its abstracted so we can change | 61 | struct kvm_io_device *dev; |
62 | * in one place. | 62 | }; |
63 | */ | 63 | |
64 | struct kvm_io_bus { | 64 | struct kvm_io_bus { |
65 | int dev_count; | 65 | int dev_count; |
66 | #define NR_IOBUS_DEVS 300 | 66 | #define NR_IOBUS_DEVS 300 |
67 | struct kvm_io_device *devs[NR_IOBUS_DEVS]; | 67 | struct kvm_io_range range[NR_IOBUS_DEVS]; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | enum kvm_bus { | 70 | enum kvm_bus { |
@@ -77,8 +77,8 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, | |||
77 | int len, const void *val); | 77 | int len, const void *val); |
78 | int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len, | 78 | int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len, |
79 | void *val); | 79 | void *val); |
80 | int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, | 80 | int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, |
81 | struct kvm_io_device *dev); | 81 | int len, struct kvm_io_device *dev); |
82 | int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, | 82 | int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, |
83 | struct kvm_io_device *dev); | 83 | struct kvm_io_device *dev); |
84 | 84 | ||