memory: emulate ioeventfd
PATCH 1/1 memory: emulate ioeventfd
The ioeventfd mechanism is used by vhost, dataplane, and virtio-pci to turn guest MMIO/PIO writes into eventfd file descriptor events. This allows arbitrary threads to be notified when the guest writes to a specific MMIO/PIO address.
qtest and TCG do not support ioeventfd because memory writes are not checked against registered ioeventfds in QEMU. This patch implements this in memory_region_dispatch_write() so qtest can use ioeventfd.
Also this patch fixes vhost aborting on some misconfigured old kernels like 3.18.0 on ARM. It is possible to explicitly enable CONFIG_EVENTFD in expert settings, while MMIO binding support in KVM will still be missing.
---
RFC => PATCH:
- Add !kvm_eventfds_enabled() conditions to bypass eventfd injection when not needed
- Renamed "ioeventfd" to "eventfd", just to make words shorter
- Add a one-shot warning about missing MMIO bindings in KVM
--- kvm-all.c | 6 ++++-- memory.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-)
kvm-all.c +4 -2
@@ -1633,8 +1633,10 @@ static int kvm_init(MachineState *ms) kvm_state = s; - s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; - s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; +if (kvm_eventfds_allowed) { + s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; + s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; + } s->memory_listener.listener.coalesced_mmio_add = kvm_coalesce_mmio_region; s->memory_listener.listener.coalesced_mmio_del = kvm_uncoalesce_mmio_region;
memory.c +42 -0
78 lines not on this page · raw message
Signature · 1 line
1.9.5.msysgit.0
Quoted 9 lines · Pavel Fedin
The ioeventfd mechanism is used by vhost, dataplane, and virtio-pci to turn guest MMIO/PIO writes into eventfd file descriptor events. This allows arbitrary threads to be notified when the guest writes to a specific MMIO/PIO address.
qtest and TCG do not support ioeventfd because memory writes are not checked against registered ioeventfds in QEMU. This patch implements this in
memory_region_dispatch_write()so qtest can use ioeventfd.
Quoted 7 lines
Also this patch fixes vhost aborting on some misconfigured old kernels like 3.18.0 on ARM. It is possible to explicitly enable
CONFIG_EVENTFDin expert settings, while MMIO binding support in KVM will still be missing.Signed-off-by Stefan Hajnoczi <[email protected]>Signed-off-by Pavel Fedin <[email protected]>
Quoted 117 lines
---
RFC => PATCH:
- Add !kvm_eventfds_enabled() conditions to bypass eventfd injection when not needed
- Renamed "ioeventfd" to "eventfd", just to make words shorter
- Add a one-shot warning about missing MMIO bindings in KVM--- kvm-all.c | 6 ++++-- memory.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-)kvm-all.c +4
-2@@ -1633,8 +1633,10 @@ static int kvm_init(MachineState *ms) kvm_state = s; - s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; - s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; +if (kvm_eventfds_allowed) { + s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; + s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; + } s->memory_listener.listener.coalesced_mmio_add = kvm_coalesce_mmio_region; s->memory_listener.listener.coalesced_mmio_del = kvm_uncoalesce_mmio_region;memory.c +42
-0@@ -18,12 +18,14 @@#include "exec/ioport.h" #include "qapi/visitor.h" #include "qemu/bitops.h" +#include "qemu/error-report.h" #include "qom/object.h" #include "trace.h" #include <assert.h> #include "exec/memory-internal.h" #include "exec/ram_addr.h" +#include "sysemu/kvm.h" #include "sysemu/sysemu.h" //#define DEBUG_UNASSIGNED @@ -1141,6 +1143,32 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,return r; } +/* Return true if an eventfd was signalled */ +static bool memory_region_dispatch_write_eventfds (MemoryRegion *mr, +hwaddr addr, +uint64_t data, +unsigned size, +MemTxAttrs attrs) +{ +MemoryRegionIoeventfd ioeventfd = { + .addr =addrrange_make (int128_make64 (addr),int128_make64 (size)), + .data = data, + }; +unsigned i; + +for (i =0 ; i < mr->ioeventfd_nb; i++) { + ioeventfd.match_data = mr->ioeventfds[i].match_data; + ioeventfd.e = mr->ioeventfds[i].e; + +if (memory_region_ioeventfd_equal (ioeventfd, mr->ioeventfds[i])) { +event_notifier_set (ioeventfd.e); +return true; + } + } + +return false; +} + MemTxResult memory_region_dispatch_write(MemoryRegion *mr, hwaddr addr, uint64_t data,@@ -1154,6 +1182,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,adjust_endianness (mr, &data, size); +if ((!kvm_eventfds_enabled ()) && +memory_region_dispatch_write_eventfds (mr, addr, data, size, attrs)) { +return MEMTX_OK ; + } +if (mr->ops->write) { return access_with_adjusted_size(addr, &data, size, mr->ops->impl.min_access_size,@@ -1672,6 +1705,8 @@ void memory_region_clear_global_locking(MemoryRegion *mr) mr->global_locking = false; } +static bool userspace_eventfd_warning; + void memory_region_add_eventfd(MemoryRegion *mr, hwaddr addr, unsigned size,@@ -1688,6 +1723,13 @@ void memory_region_add_eventfd(MemoryRegion *mr, };unsigned i; +if (kvm_enabled () && (!(kvm_eventfds_enabled () || + userspace_eventfd_warning))) { + userspace_eventfd_warning = true; +error_report ("Using eventfd without MMIO binding in KVM. " +"Suboptimal performance expected" ); + } +if (size) {adjust_endianness (mr, &mrfd.data, size); }Signature · 1 line
1.9.5.msysgit.0
Quoted 121 lines · Pavel Fedin
The ioeventfd mechanism is used by vhost, dataplane, and virtio-pci to turn guest MMIO/PIO writes into eventfd file descriptor events. This allows arbitrary threads to be notified when the guest writes to a specific MMIO/PIO address.
qtest and TCG do not support ioeventfd because memory writes are not checked against registered ioeventfds in QEMU. This patch implements this in
memory_region_dispatch_write()so qtest can use ioeventfd.Also this patch fixes vhost aborting on some misconfigured old kernels like 3.18.0 on ARM. It is possible to explicitly enable
CONFIG_EVENTFDin expert settings, while MMIO binding support in KVM will still be missing.Signed-off-by Stefan Hajnoczi <[email protected]>Signed-off-by Pavel Fedin <[email protected]>---
RFC => PATCH:
- Add !kvm_eventfds_enabled() conditions to bypass eventfd injection when not needed
- Renamed "ioeventfd" to "eventfd", just to make words shorter
- Add a one-shot warning about missing MMIO bindings in KVM--- kvm-all.c | 6 ++++-- memory.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-)kvm-all.c +4
-2@@ -1633,8 +1633,10 @@ static int kvm_init(MachineState *ms) kvm_state = s; - s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; - s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; +if (kvm_eventfds_allowed) { + s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; + s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; + } s->memory_listener.listener.coalesced_mmio_add = kvm_coalesce_mmio_region; s->memory_listener.listener.coalesced_mmio_del = kvm_uncoalesce_mmio_region;memory.c +35
-0@@ -18,12 +18,14 @@#include "exec/ioport.h" #include "qapi/visitor.h" #include "qemu/bitops.h" +#include "qemu/error-report.h" #include "qom/object.h" #include "trace.h" #include <assert.h> #include "exec/memory-internal.h" #include "exec/ram_addr.h" +#include "sysemu/kvm.h" #include "sysemu/sysemu.h" //#define DEBUG_UNASSIGNED @@ -1141,6 +1143,32 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,return r; } +/* Return true if an eventfd was signalled */ +static bool memory_region_dispatch_write_eventfds (MemoryRegion *mr, +hwaddr addr, +uint64_t data, +unsigned size, +MemTxAttrs attrs) +{ +MemoryRegionIoeventfd ioeventfd = { + .addr =addrrange_make (int128_make64 (addr),int128_make64 (size)), + .data = data, + }; +unsigned i; + +for (i =0 ; i < mr->ioeventfd_nb; i++) { + ioeventfd.match_data = mr->ioeventfds[i].match_data; + ioeventfd.e = mr->ioeventfds[i].e; + +if (memory_region_ioeventfd_equal (ioeventfd, mr->ioeventfds[i])) { +event_notifier_set (ioeventfd.e); +return true; + } + } + +return false; +} + MemTxResult memory_region_dispatch_write(MemoryRegion *mr, hwaddr addr, uint64_t data,@@ -1154,6 +1182,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,adjust_endianness (mr, &data, size); +if ((!kvm_eventfds_enabled ()) && +memory_region_dispatch_write_eventfds (mr, addr, data, size, attrs)) { +return MEMTX_OK ; + } +if (mr->ops->write) { return access_with_adjusted_size(addr, &data, size, mr->ops->impl.min_access_size,@@ -1672,6 +1705,8 @@ void memory_region_clear_global_locking(MemoryRegion *mr) mr->global_locking = false; } +static bool userspace_eventfd_warning; + void memory_region_add_eventfd(MemoryRegion *mr, hwaddr addr, unsigned size,@@ -1688,6 +1723,13 @@ void memory_region_add_eventfd(MemoryRegion *mr, };unsigned i;
memory.c void memory_region_add_eventfd(MemoryRegion *mr, · line 1735
Quoted 10 lines
memory.c +7
-0+if (kvm_enabled () && (!(kvm_eventfds_enabled () || + userspace_eventfd_warning))) { + userspace_eventfd_warning = true; +error_report ("Using eventfd without MMIO binding in KVM. " +"Suboptimal performance expected" ); + } +if (size) {adjust_endianness (mr, &mrfd.data, size); }
Queued for 2.6.
Paolo