aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorlimiao-intel <105205746+limiao-intel@users.noreply.github.com>2023-06-09 04:51:04 +0800
committerGitHub <noreply@github.com>2023-06-08 21:51:04 +0100
commit74e7348f253c04d43c11082c83f2a51720c7643e (patch)
treef6f24b896e9846c36b9a688f3a8c2caab3d3d7d8 /lib
parente817d2e67835a80761fd33c4a1ed445c3309f3e7 (diff)
downloadlibvfio-user-74e7348f253c04d43c11082c83f2a51720c7643e.zip
libvfio-user-74e7348f253c04d43c11082c83f2a51720c7643e.tar.gz
libvfio-user-74e7348f253c04d43c11082c83f2a51720c7643e.tar.bz2
fix err/req irq fd issue (#731)
When handle_device_set_irqs set err irq/req irq, fd will be filled in vfu_ctx->irqs->efds[] rather than vfu_ctx->irqs->err_efd or vfu_ctx->irqs->req_efd. This patch adds irq index judgment before filling in fd to make sure fd is filled in the correct place. Signed-off-by: Miao Li <miao.li@intel.com> Reviewed-by: John Levon <john.levon@nutanix.com> Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/irq.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/lib/irq.c b/lib/irq.c
index eadad7b..8a5d200 100644
--- a/lib/irq.c
+++ b/lib/irq.c
@@ -180,19 +180,32 @@ irqs_set_state(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set)
cb(vfu_ctx, irq_set->start, irq_set->count, mask);
}
+static int *
+irqs_get_efd(vfu_ctx_t *vfu_ctx, int index, int fd_idx)
+{
+ switch (index) {
+ case VFIO_PCI_ERR_IRQ_INDEX:
+ return &vfu_ctx->irqs->err_efd;
+ case VFIO_PCI_REQ_IRQ_INDEX:
+ return &vfu_ctx->irqs->req_efd;
+ default:
+ return &vfu_ctx->irqs->efds[fd_idx];
+ }
+}
+
static int
irqs_set_data_none(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set)
{
- int efd;
+ int *efd;
uint32_t i;
long ret;
eventfd_t val;
for (i = irq_set->start; i < (irq_set->start + irq_set->count); i++) {
- efd = vfu_ctx->irqs->efds[i];
- if (efd >= 0) {
+ efd = irqs_get_efd(vfu_ctx, irq_set->index, i);
+ if (*efd >= 0) {
val = 1;
- ret = eventfd_write(efd, val);
+ ret = eventfd_write(*efd, val);
if (ret == -1) {
vfu_log(vfu_ctx, LOG_DEBUG,
"IRQ: failed to set data to none: %m");
@@ -208,7 +221,7 @@ static int
irqs_set_data_bool(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set, void *data)
{
uint8_t *d8;
- int efd;
+ int *efd;
uint32_t i;
long ret;
eventfd_t val;
@@ -217,10 +230,10 @@ irqs_set_data_bool(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set, void *data)
for (i = irq_set->start, d8 = data; i < (irq_set->start + irq_set->count);
i++, d8++) {
- efd = vfu_ctx->irqs->efds[i];
- if (efd >= 0 && *d8 == 1) {
+ efd = irqs_get_efd(vfu_ctx, irq_set->index, i);
+ if (*efd >= 0 && *d8 == 1) {
val = 1;
- ret = eventfd_write(efd, val);
+ ret = eventfd_write(*efd, val);
if (ret == -1) {
vfu_log(vfu_ctx, LOG_DEBUG,
"IRQ: failed to set data to bool: %m");
@@ -236,28 +249,37 @@ static int
irqs_set_data_eventfd(vfu_ctx_t *vfu_ctx, struct vfio_irq_set *irq_set,
int *data)
{
- int efd;
+ int *efd;
uint32_t i;
size_t j;
assert(data != NULL);
for (i = irq_set->start, j = 0; i < (irq_set->start + irq_set->count);
i++, j++) {
- efd = vfu_ctx->irqs->efds[i];
- if (efd >= 0) {
- if (close(efd) == -1) {
- vfu_log(vfu_ctx, LOG_DEBUG, "failed to close IRQ fd %d: %m", efd);
+ efd = irqs_get_efd(vfu_ctx, irq_set->index, i);
+ if (*efd >= 0) {
+ if (close(*efd) == -1) {
+ vfu_log(vfu_ctx, LOG_DEBUG, "failed to close IRQ fd %d: %m", *efd);
}
-
- vfu_ctx->irqs->efds[i] = -1;
+ *efd = -1;
}
assert(data[j] >= 0);
/*
* We've already checked in handle_device_set_irqs that
* nr_fds == irq_set->count.
*/
- vfu_ctx->irqs->efds[i] = consume_fd(data, irq_set->count, j);
- vfu_log(vfu_ctx, LOG_DEBUG, "event fd[%d]=%d", i, vfu_ctx->irqs->efds[i]);
+ *efd = consume_fd(data, irq_set->count, j);
+ switch (irq_set->index) {
+ case VFIO_PCI_ERR_IRQ_INDEX:
+ vfu_log(vfu_ctx, LOG_DEBUG, "err fd=%d", *efd);
+ break;
+ case VFIO_PCI_REQ_IRQ_INDEX:
+ vfu_log(vfu_ctx, LOG_DEBUG, "req fd=%d", *efd);
+ break;
+ default:
+ vfu_log(vfu_ctx, LOG_DEBUG, "event fd[%d]=%d", i, *efd);
+ break;
+ }
}
return 0;
@@ -322,6 +344,13 @@ device_set_irqs_validate(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg)
line = __LINE__;
goto invalid;
}
+ // count must be 0 or 1 for ERR/REQ
+ if (((irq_set->index == VFIO_PCI_ERR_IRQ_INDEX) ||
+ (irq_set->index == VFIO_PCI_REQ_IRQ_INDEX)) &&
+ (irq_set->count > 1)) {
+ line = __LINE__;
+ goto invalid;
+ }
// if count == 0, start must be 0 too
if ((irq_set->count == 0) && (irq_set->start != 0)) {
line = __LINE__;