提交 8c56c1a5 编写于 作者: P Pavel Fedin 提交者: Paolo Bonzini

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.
Signed-off-by: NStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: NPavel Fedin <p.fedin@samsung.com>
Message-Id: <006e01d12377$0b9c2d40$22d487c0$@samsung.com>
Reviewed-by: NMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
上级 bc92e4e9
...@@ -1628,8 +1628,10 @@ static int kvm_init(MachineState *ms) ...@@ -1628,8 +1628,10 @@ static int kvm_init(MachineState *ms)
kvm_state = s; kvm_state = s;
if (kvm_eventfds_allowed) {
s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; 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_add = kvm_coalesce_mmio_region;
s->memory_listener.listener.coalesced_mmio_del = kvm_uncoalesce_mmio_region; s->memory_listener.listener.coalesced_mmio_del = kvm_uncoalesce_mmio_region;
......
...@@ -18,12 +18,14 @@ ...@@ -18,12 +18,14 @@
#include "exec/ioport.h" #include "exec/ioport.h"
#include "qapi/visitor.h" #include "qapi/visitor.h"
#include "qemu/bitops.h" #include "qemu/bitops.h"
#include "qemu/error-report.h"
#include "qom/object.h" #include "qom/object.h"
#include "trace.h" #include "trace.h"
#include <assert.h> #include <assert.h>
#include "exec/memory-internal.h" #include "exec/memory-internal.h"
#include "exec/ram_addr.h" #include "exec/ram_addr.h"
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
//#define DEBUG_UNASSIGNED //#define DEBUG_UNASSIGNED
...@@ -1136,6 +1138,32 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr, ...@@ -1136,6 +1138,32 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
return r; 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, MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t data, uint64_t data,
...@@ -1149,6 +1177,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr, ...@@ -1149,6 +1177,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
adjust_endianness(mr, &data, size); 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) { if (mr->ops->write) {
return access_with_adjusted_size(addr, &data, size, return access_with_adjusted_size(addr, &data, size,
mr->ops->impl.min_access_size, mr->ops->impl.min_access_size,
...@@ -1667,6 +1700,8 @@ void memory_region_clear_global_locking(MemoryRegion *mr) ...@@ -1667,6 +1700,8 @@ void memory_region_clear_global_locking(MemoryRegion *mr)
mr->global_locking = false; mr->global_locking = false;
} }
static bool userspace_eventfd_warning;
void memory_region_add_eventfd(MemoryRegion *mr, void memory_region_add_eventfd(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
unsigned size, unsigned size,
...@@ -1683,6 +1718,13 @@ void memory_region_add_eventfd(MemoryRegion *mr, ...@@ -1683,6 +1718,13 @@ void memory_region_add_eventfd(MemoryRegion *mr,
}; };
unsigned i; 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) { if (size) {
adjust_endianness(mr, &mrfd.data, size); adjust_endianness(mr, &mrfd.data, size);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册