IRQFD function allows registering of an @eventfd and @irq. @irq will be
injected inside guest when @eventfd is written into.
IOEVENTFD function allows registering an @eventfd and a guest physical
address, @addr, along with optional data. A poll() on @eventfd will be
woken up when guest attempts to access @addr.
Signed-off-by: Srivatsa Vaddagiri <quic_svaddagi@quicinc.com>
---
include/sysemu/gunyah_int.h | 1 +
accel/gunyah/gunyah-all.c | 94 +++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)
diff --git a/include/sysemu/gunyah_int.h b/include/sysemu/gunyah_int.h
index 0967b2d7d7..8c0b479f62 100644
--- a/include/sysemu/gunyah_int.h
+++ b/include/sysemu/gunyah_int.h
@@ -49,5 +49,6 @@ struct GUNYAHState {
int gunyah_create_vm(void);
int gunyah_vm_ioctl(int type, ...);
void *gunyah_cpu_thread_fn(void *arg);
+int gunyah_add_irqfd(int irqfd, int label, Error **errp);
#endif /* GUNYAH_INT_H */
diff --git a/accel/gunyah/gunyah-all.c b/accel/gunyah/gunyah-all.c
index 19f96225a0..948ccfbeee 100644
--- a/accel/gunyah/gunyah-all.c
+++ b/accel/gunyah/gunyah-all.c
@@ -24,11 +24,21 @@
#include "qemu/error-report.h"
#include "exec/address-spaces.h"
#include "hw/boards.h"
+#include "qapi/error.h"
+#include "qemu/event_notifier.h"
static void gunyah_region_add(MemoryListener *listener,
MemoryRegionSection *section);
static void gunyah_region_del(MemoryListener *listener,
MemoryRegionSection *section);
+static void gunyah_mem_ioeventfd_add(MemoryListener *listener,
+ MemoryRegionSection *section,
+ bool match_data, uint64_t data,
+ EventNotifier *e);
+static void gunyah_mem_ioeventfd_del(MemoryListener *listener,
+ MemoryRegionSection *section,
+ bool match_data, uint64_t data,
+ EventNotifier *e);
static int gunyah_ioctl(int type, ...)
{
@@ -65,6 +75,8 @@ static MemoryListener gunyah_memory_listener = {
.priority = MEMORY_LISTENER_PRIORITY_ACCEL,
.region_add = gunyah_region_add,
.region_del = gunyah_region_del,
+ .eventfd_add = gunyah_mem_ioeventfd_add,
+ .eventfd_del = gunyah_mem_ioeventfd_del,
};
int gunyah_create_vm(void)
@@ -319,6 +331,88 @@ void gunyah_set_swiotlb_size(uint64_t size)
s->swiotlb_size = size;
}
+int gunyah_add_irqfd(int irqfd, int label, Error **errp)
+{
+ int ret;
+ struct gh_fn_desc fdesc;
+ struct gh_fn_irqfd_arg ghirqfd;
+
+ fdesc.type = GH_FN_IRQFD;
+ fdesc.arg_size = sizeof(struct gh_fn_irqfd_arg);
+ fdesc.arg = (__u64)(&ghirqfd);
+
+ ghirqfd.fd = irqfd;
+ ghirqfd.label = label;
+ ghirqfd.flags = GH_IRQFD_FLAGS_LEVEL;
+
+ ret = gunyah_vm_ioctl(GH_VM_ADD_FUNCTION, &fdesc);
+ if (ret) {
+ error_setg_errno(errp, errno, "GH_FN_IRQFD failed");
+ }
+
+ return ret;
+}
+
+static int gunyah_set_ioeventfd_mmio(int fd, hwaddr addr,
+ uint32_t size, uint32_t data, bool datamatch, bool assign)
+{
+ int ret;
+ struct gh_fn_ioeventfd_arg io;
+ struct gh_fn_desc fdesc;
+
+ io.fd = fd;
+ io.datamatch = datamatch ? data : 0;
+ io.len = size;
+ io.addr = addr;
+ io.flags = datamatch ? GH_IOEVENTFD_FLAGS_DATAMATCH : 0;
+
+ fdesc.type = GH_FN_IOEVENTFD;
+ fdesc.arg_size = sizeof(struct gh_fn_ioeventfd_arg);
+ fdesc.arg = (__u64)(&io);
+
+ if (assign) {
+ ret = gunyah_vm_ioctl(GH_VM_ADD_FUNCTION, &fdesc);
+ } else {
+ ret = gunyah_vm_ioctl(GH_VM_REMOVE_FUNCTION, &fdesc);
+ }
+
+ return ret;
+}
+
+static void gunyah_mem_ioeventfd_add(MemoryListener *listener,
+ MemoryRegionSection *section,
+ bool match_data, uint64_t data,
+ EventNotifier *e)
+{
+ int fd = event_notifier_get_fd(e);
+ int r;
+
+ r = gunyah_set_ioeventfd_mmio(fd, section->offset_within_address_space,
+ int128_get64(section->size), data, match_data,
+ true);
+ if (r < 0) {
+ error_report("error adding ioeventfd: %s", strerror(errno));
+ exit(1);
+ }
+}
+
+static void gunyah_mem_ioeventfd_del(MemoryListener *listener,
+ MemoryRegionSection *section,
+ bool match_data, uint64_t data,
+ EventNotifier *e)
+{
+ int fd = event_notifier_get_fd(e);
+ int r;
+
+ r = gunyah_set_ioeventfd_mmio(fd, section->offset_within_address_space,
+ int128_get64(section->size), data, match_data,
+ false);
+ if (r < 0) {
+ error_report("error deleting ioeventfd: %s", strerror(errno));
+ exit(1);
+ }
+}
+
void *gunyah_cpu_thread_fn(void *arg)
{
CPUState *cpu = arg;
--
2.25.1