memory: move ioeventfd ops to MemoryListener
This way the accelerator (kvm) can handle them directly. Signed-off-by: Avi Kivity <avi@redhat.com> Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
0e0d36b446
commit
80a1ea3748
14
hw/vhost.c
14
hw/vhost.c
@ -720,6 +720,18 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
|
|||||||
0, virtio_queue_get_desc_size(vdev, idx));
|
0, virtio_queue_get_desc_size(vdev, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vhost_eventfd_add(MemoryListener *listener,
|
||||||
|
MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vhost_eventfd_del(MemoryListener *listener,
|
||||||
|
MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
|
int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
|
||||||
{
|
{
|
||||||
uint64_t features;
|
uint64_t features;
|
||||||
@ -751,6 +763,8 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
|
|||||||
.log_sync = vhost_log_sync,
|
.log_sync = vhost_log_sync,
|
||||||
.log_global_start = vhost_log_global_start,
|
.log_global_start = vhost_log_global_start,
|
||||||
.log_global_stop = vhost_log_global_stop,
|
.log_global_stop = vhost_log_global_stop,
|
||||||
|
.eventfd_add = vhost_eventfd_add,
|
||||||
|
.eventfd_del = vhost_eventfd_del,
|
||||||
.priority = 10
|
.priority = 10
|
||||||
};
|
};
|
||||||
hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
|
hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
|
||||||
|
78
kvm-all.c
78
kvm-all.c
@ -28,6 +28,7 @@
|
|||||||
#include "kvm.h"
|
#include "kvm.h"
|
||||||
#include "bswap.h"
|
#include "bswap.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "exec-memory.h"
|
||||||
|
|
||||||
/* This check must be after config-host.h is included */
|
/* This check must be after config-host.h is included */
|
||||||
#ifdef CONFIG_EVENTFD
|
#ifdef CONFIG_EVENTFD
|
||||||
@ -718,6 +719,81 @@ static void kvm_log_global_stop(struct MemoryListener *listener)
|
|||||||
assert(r >= 0);
|
assert(r >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kvm_mem_ioeventfd_add(MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(match_data && section->size == 4);
|
||||||
|
|
||||||
|
r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
|
||||||
|
data, true);
|
||||||
|
if (r < 0) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kvm_mem_ioeventfd_del(MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = kvm_set_ioeventfd_mmio_long(fd, section->offset_within_address_space,
|
||||||
|
data, false);
|
||||||
|
if (r < 0) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kvm_io_ioeventfd_add(MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(match_data && section->size == 2);
|
||||||
|
|
||||||
|
r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
|
||||||
|
data, true);
|
||||||
|
if (r < 0) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kvm_io_ioeventfd_del(MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = kvm_set_ioeventfd_pio_word(fd, section->offset_within_address_space,
|
||||||
|
data, false);
|
||||||
|
if (r < 0) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kvm_eventfd_add(MemoryListener *listener,
|
||||||
|
MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
if (section->address_space == get_system_memory()) {
|
||||||
|
kvm_mem_ioeventfd_add(section, match_data, data, fd);
|
||||||
|
} else {
|
||||||
|
kvm_io_ioeventfd_add(section, match_data, data, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kvm_eventfd_del(MemoryListener *listener,
|
||||||
|
MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
if (section->address_space == get_system_memory()) {
|
||||||
|
kvm_mem_ioeventfd_del(section, match_data, data, fd);
|
||||||
|
} else {
|
||||||
|
kvm_io_ioeventfd_del(section, match_data, data, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static MemoryListener kvm_memory_listener = {
|
static MemoryListener kvm_memory_listener = {
|
||||||
.region_add = kvm_region_add,
|
.region_add = kvm_region_add,
|
||||||
.region_del = kvm_region_del,
|
.region_del = kvm_region_del,
|
||||||
@ -726,6 +802,8 @@ static MemoryListener kvm_memory_listener = {
|
|||||||
.log_sync = kvm_log_sync,
|
.log_sync = kvm_log_sync,
|
||||||
.log_global_start = kvm_log_global_start,
|
.log_global_start = kvm_log_global_start,
|
||||||
.log_global_stop = kvm_log_global_stop,
|
.log_global_stop = kvm_log_global_stop,
|
||||||
|
.eventfd_add = kvm_eventfd_add,
|
||||||
|
.eventfd_del = kvm_eventfd_del,
|
||||||
.priority = 10,
|
.priority = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
74
memory.c
74
memory.c
@ -202,8 +202,6 @@ struct AddressSpaceOps {
|
|||||||
void (*range_del)(AddressSpace *as, FlatRange *fr);
|
void (*range_del)(AddressSpace *as, FlatRange *fr);
|
||||||
void (*log_start)(AddressSpace *as, FlatRange *fr);
|
void (*log_start)(AddressSpace *as, FlatRange *fr);
|
||||||
void (*log_stop)(AddressSpace *as, FlatRange *fr);
|
void (*log_stop)(AddressSpace *as, FlatRange *fr);
|
||||||
void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
|
|
||||||
void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FOR_EACH_FLAT_RANGE(var, view) \
|
#define FOR_EACH_FLAT_RANGE(var, view) \
|
||||||
@ -369,37 +367,11 @@ static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(fd->match_data && int128_get64(fd->addr.size) == 4);
|
|
||||||
|
|
||||||
r = kvm_set_ioeventfd_mmio_long(fd->fd, int128_get64(fd->addr.start),
|
|
||||||
fd->data, true);
|
|
||||||
if (r < 0) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = kvm_set_ioeventfd_mmio_long(fd->fd, int128_get64(fd->addr.start),
|
|
||||||
fd->data, false);
|
|
||||||
if (r < 0) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const AddressSpaceOps address_space_ops_memory = {
|
static const AddressSpaceOps address_space_ops_memory = {
|
||||||
.range_add = as_memory_range_add,
|
.range_add = as_memory_range_add,
|
||||||
.range_del = as_memory_range_del,
|
.range_del = as_memory_range_del,
|
||||||
.log_start = as_memory_log_start,
|
.log_start = as_memory_log_start,
|
||||||
.log_stop = as_memory_log_stop,
|
.log_stop = as_memory_log_stop,
|
||||||
.ioeventfd_add = as_memory_ioeventfd_add,
|
|
||||||
.ioeventfd_del = as_memory_ioeventfd_del,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static AddressSpace address_space_memory = {
|
static AddressSpace address_space_memory = {
|
||||||
@ -493,35 +465,9 @@ static void as_io_range_del(AddressSpace *as, FlatRange *fr)
|
|||||||
int128_get64(fr->addr.size));
|
int128_get64(fr->addr.size));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(fd->match_data && int128_get64(fd->addr.size) == 2);
|
|
||||||
|
|
||||||
r = kvm_set_ioeventfd_pio_word(fd->fd, int128_get64(fd->addr.start),
|
|
||||||
fd->data, true);
|
|
||||||
if (r < 0) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = kvm_set_ioeventfd_pio_word(fd->fd, int128_get64(fd->addr.start),
|
|
||||||
fd->data, false);
|
|
||||||
if (r < 0) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const AddressSpaceOps address_space_ops_io = {
|
static const AddressSpaceOps address_space_ops_io = {
|
||||||
.range_add = as_io_range_add,
|
.range_add = as_io_range_add,
|
||||||
.range_del = as_io_range_del,
|
.range_del = as_io_range_del,
|
||||||
.ioeventfd_add = as_io_ioeventfd_add,
|
|
||||||
.ioeventfd_del = as_io_ioeventfd_del,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static AddressSpace address_space_io = {
|
static AddressSpace address_space_io = {
|
||||||
@ -653,6 +599,8 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
|
|||||||
unsigned fds_old_nb)
|
unsigned fds_old_nb)
|
||||||
{
|
{
|
||||||
unsigned iold, inew;
|
unsigned iold, inew;
|
||||||
|
MemoryRegionIoeventfd *fd;
|
||||||
|
MemoryRegionSection section;
|
||||||
|
|
||||||
/* Generate a symmetric difference of the old and new fd sets, adding
|
/* Generate a symmetric difference of the old and new fd sets, adding
|
||||||
* and deleting as necessary.
|
* and deleting as necessary.
|
||||||
@ -664,13 +612,27 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
|
|||||||
&& (inew == fds_new_nb
|
&& (inew == fds_new_nb
|
||||||
|| memory_region_ioeventfd_before(fds_old[iold],
|
|| memory_region_ioeventfd_before(fds_old[iold],
|
||||||
fds_new[inew]))) {
|
fds_new[inew]))) {
|
||||||
as->ops->ioeventfd_del(as, &fds_old[iold]);
|
fd = &fds_old[iold];
|
||||||
|
section = (MemoryRegionSection) {
|
||||||
|
.address_space = as->root,
|
||||||
|
.offset_within_address_space = int128_get64(fd->addr.start),
|
||||||
|
.size = int128_get64(fd->addr.size),
|
||||||
|
};
|
||||||
|
MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion,
|
||||||
|
fd->match_data, fd->data, fd->fd);
|
||||||
++iold;
|
++iold;
|
||||||
} else if (inew < fds_new_nb
|
} else if (inew < fds_new_nb
|
||||||
&& (iold == fds_old_nb
|
&& (iold == fds_old_nb
|
||||||
|| memory_region_ioeventfd_before(fds_new[inew],
|
|| memory_region_ioeventfd_before(fds_new[inew],
|
||||||
fds_old[iold]))) {
|
fds_old[iold]))) {
|
||||||
as->ops->ioeventfd_add(as, &fds_new[inew]);
|
fd = &fds_new[inew];
|
||||||
|
section = (MemoryRegionSection) {
|
||||||
|
.address_space = as->root,
|
||||||
|
.offset_within_address_space = int128_get64(fd->addr.start),
|
||||||
|
.size = int128_get64(fd->addr.size),
|
||||||
|
};
|
||||||
|
MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion,
|
||||||
|
fd->match_data, fd->data, fd->fd);
|
||||||
++inew;
|
++inew;
|
||||||
} else {
|
} else {
|
||||||
++iold;
|
++iold;
|
||||||
|
4
memory.h
4
memory.h
@ -185,6 +185,10 @@ struct MemoryListener {
|
|||||||
void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
|
void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
|
||||||
void (*log_global_start)(MemoryListener *listener);
|
void (*log_global_start)(MemoryListener *listener);
|
||||||
void (*log_global_stop)(MemoryListener *listener);
|
void (*log_global_stop)(MemoryListener *listener);
|
||||||
|
void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd);
|
||||||
|
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd);
|
||||||
/* Lower = earlier (during add), later (during del) */
|
/* Lower = earlier (during add), later (during del) */
|
||||||
unsigned priority;
|
unsigned priority;
|
||||||
QTAILQ_ENTRY(MemoryListener) link;
|
QTAILQ_ENTRY(MemoryListener) link;
|
||||||
|
14
xen-all.c
14
xen-all.c
@ -487,6 +487,18 @@ static void xen_log_global_stop(MemoryListener *listener)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xen_eventfd_add(MemoryListener *listener,
|
||||||
|
MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xen_eventfd_del(MemoryListener *listener,
|
||||||
|
MemoryRegionSection *section,
|
||||||
|
bool match_data, uint64_t data, int fd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static MemoryListener xen_memory_listener = {
|
static MemoryListener xen_memory_listener = {
|
||||||
.region_add = xen_region_add,
|
.region_add = xen_region_add,
|
||||||
.region_del = xen_region_del,
|
.region_del = xen_region_del,
|
||||||
@ -495,6 +507,8 @@ static MemoryListener xen_memory_listener = {
|
|||||||
.log_sync = xen_log_sync,
|
.log_sync = xen_log_sync,
|
||||||
.log_global_start = xen_log_global_start,
|
.log_global_start = xen_log_global_start,
|
||||||
.log_global_stop = xen_log_global_stop,
|
.log_global_stop = xen_log_global_stop,
|
||||||
|
.eventfd_add = xen_eventfd_add,
|
||||||
|
.eventfd_del = xen_eventfd_del,
|
||||||
.priority = 10,
|
.priority = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user