From 2220f8190ad5334308bf75973d5083204efb86ae Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 17 Apr 2023 11:33:33 -0700 Subject: [PATCH] ANDROID: gunyah: Sync with latest "virt: gunyah: Add ioeventfd" Align ioeventfd handling to Gunyah v13 patches: https://lore.kernel.org/all/20230509204801.2824351-24-quic_eberman@quicinc.com/ Bug: 279506910 Change-Id: I8d66d83bee284eacb4bc9d76d3cbfd52785d9661 Signed-off-by: Elliot Berman --- drivers/virt/gunyah/gunyah_ioeventfd.c | 18 +++++++++--------- drivers/virt/gunyah/vm_mgr.c | 14 +++++++++++--- include/uapi/linux/gunyah.h | 2 +- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/virt/gunyah/gunyah_ioeventfd.c b/drivers/virt/gunyah/gunyah_ioeventfd.c index f61291c17be5..5b1b9fd9ac3a 100644 --- a/drivers/virt/gunyah/gunyah_ioeventfd.c +++ b/drivers/virt/gunyah/gunyah_ioeventfd.c @@ -35,13 +35,17 @@ static struct gh_vm_io_handler_ops io_ops = { static long gh_ioeventfd_bind(struct gh_vm_function_instance *f) { const struct gh_fn_ioeventfd_arg *args = f->argp; - struct eventfd_ctx *ctx = NULL; struct gh_ioeventfd *iofd; + struct eventfd_ctx *ctx; int ret; if (f->arg_size != sizeof(*args)) return -EINVAL; + /* All other flag bits are reserved for future use */ + if (args->flags & ~GH_IOEVENTFD_FLAGS_DATAMATCH) + return -EINVAL; + /* must be natural-word sized, or 0 to ignore length */ switch (args->len) { case 0: @@ -55,15 +59,11 @@ static long gh_ioeventfd_bind(struct gh_vm_function_instance *f) } /* check for range overflow */ - if (args->addr + args->len < args->addr) + if (overflows_type(args->addr + args->len, u64)) return -EINVAL; /* ioeventfd with no length can't be combined with DATAMATCH */ - if (!args->len && (args->flags & GH_IOEVENTFD_DATAMATCH)) - return -EINVAL; - - /* All other flag bits are reserved for future use */ - if (args->flags & ~GH_IOEVENTFD_DATAMATCH) + if (!args->len && (args->flags & GH_IOEVENTFD_FLAGS_DATAMATCH)) return -EINVAL; ctx = eventfd_ctx_fdget(args->fd); @@ -81,7 +81,7 @@ static long gh_ioeventfd_bind(struct gh_vm_function_instance *f) iofd->ctx = ctx; - if (args->flags & GH_IOEVENTFD_DATAMATCH) { + if (args->flags & GH_IOEVENTFD_FLAGS_DATAMATCH) { iofd->io_handler.datamatch = true; iofd->io_handler.len = args->len; iofd->io_handler.data = args->datamatch; @@ -126,5 +126,5 @@ static bool gh_ioevent_compare(const struct gh_vm_function_instance *f, DECLARE_GH_VM_FUNCTION_INIT(ioeventfd, GH_FN_IOEVENTFD, 3, gh_ioeventfd_bind, gh_ioevent_unbind, gh_ioevent_compare); -MODULE_DESCRIPTION("Gunyah ioeventfds"); +MODULE_DESCRIPTION("Gunyah ioeventfd VM Function"); MODULE_LICENSE("GPL"); diff --git a/drivers/virt/gunyah/vm_mgr.c b/drivers/virt/gunyah/vm_mgr.c index cda7d8b26ef4..1ff96c35af56 100644 --- a/drivers/virt/gunyah/vm_mgr.c +++ b/drivers/virt/gunyah/vm_mgr.c @@ -294,9 +294,16 @@ static int _gh_vm_io_handler_compare(const struct rb_node *node, const struct rb return -1; if (n->len > p->len) return 1; - if (n->datamatch < p->datamatch) + /* one of the io handlers doesn't have datamatch and the other does. + * For purposes of comparison, that makes them identical since the + * one that doesn't have datamatch will cover the same handler that + * does. + */ + if (n->datamatch != p->datamatch) + return 0; + if (n->data < p->data) return -1; - if (n->datamatch > p->datamatch) + if (n->data > p->data) return 1; return 0; } @@ -319,7 +326,8 @@ static struct gh_vm_io_handler *gh_vm_mgr_find_io_hdlr(struct gh_vm *ghvm, u64 a struct gh_vm_io_handler key = { .addr = addr, .len = len, - .datamatch = data, + .datamatch = true, + .data = data, }; struct rb_node *node; diff --git a/include/uapi/linux/gunyah.h b/include/uapi/linux/gunyah.h index b747d8a1ce0c..a0ae5673908c 100644 --- a/include/uapi/linux/gunyah.h +++ b/include/uapi/linux/gunyah.h @@ -133,7 +133,7 @@ struct gh_fn_irqfd_arg { __u32 padding; }; -#define GH_IOEVENTFD_DATAMATCH (1UL << 0) +#define GH_IOEVENTFD_FLAGS_DATAMATCH (1UL << 0) /** * struct gh_fn_ioeventfd_arg - Arguments to create an ioeventfd function