diff options
author | Thanos Makatos <thanos.makatos@nutanix.com> | 2020-11-16 10:53:58 -0500 |
---|---|---|
committer | Thanos <tmakatos@gmail.com> | 2020-11-18 16:50:58 +0000 |
commit | 6f99bd0acf54fa4f5c74de6bb50b894746f6302c (patch) | |
tree | 6663f8e12814cc5c3a49a4d80554fa4bff660037 /samples | |
parent | a351594624cfc6e6cd97b1aaf48c62ba2ae0fc43 (diff) | |
download | libvfio-user-6f99bd0acf54fa4f5c74de6bb50b894746f6302c.zip libvfio-user-6f99bd0acf54fa4f5c74de6bb50b894746f6302c.tar.gz libvfio-user-6f99bd0acf54fa4f5c74de6bb50b894746f6302c.tar.bz2 |
client/server sample: trigger IRQ based on alarm
This avoid having to manually send USR1 to the server.
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/client.c | 135 | ||||
-rw-r--r-- | samples/server.c | 19 |
2 files changed, 80 insertions, 74 deletions
diff --git a/samples/client.c b/samples/client.c index 14f81b5..c3a4588 100644 --- a/samples/client.c +++ b/samples/client.c @@ -243,13 +243,9 @@ static int configure_irqs(int sock) { int i, ret; - size_t size; struct vfio_irq_set irq_set; - struct vfio_user_irq_info vfio_user_irq_info; - struct vfio_user_header hdr; uint16_t msg_id = 1; int irq_fd; - uint64_t val; for (i = 0; i < LM_DEV_NUM_IRQS; i++) { /* TODO move body of loop into function */ struct vfio_irq_info vfio_irq_info = { @@ -293,43 +289,7 @@ configure_irqs(int sock) return ret; } - printf("client waiting for server to trigger INTx\n"); - printf("(send SIGUSR1 to the server trigger INTx)\n"); - - ret = read(irq_fd, &val, sizeof val); - if (ret == -1) { - ret = -errno; - perror("server failed to trigger IRQ"); - return ret; - } - - printf("INTx triggered!\n"); - - msg_id++; - - size = sizeof(vfio_user_irq_info); - ret = recv_vfio_user_msg(sock, &hdr, false, &msg_id, &vfio_user_irq_info, - &size); - if (ret < 0) { - fprintf(stderr, "failed to receive IRQ message: %s\n", strerror(-ret)); - return ret; - } - if (vfio_user_irq_info.subindex >= irq_set.count) { - fprintf(stderr, "bad IRQ %d, max=%d\n", vfio_user_irq_info.subindex, - irq_set.count); - return -ENOENT; - } - - ret = send_vfio_user_msg(sock, msg_id, true, VFIO_USER_VM_INTERRUPT, - NULL, 0, NULL, 0); - if (ret < 0) { - fprintf(stderr, "failed to send reply for VFIO_USER_VM_INTERRUPT: " - "%s\n", strerror(-ret)); - return ret; - } - printf("INTx messaged triggered!\n"); - - return 0; + return irq_fd; } static int @@ -396,10 +356,49 @@ access_region(int sock, int region, bool is_write, uint64_t offset, } static int -access_bar0(int sock) +wait_for_irqs(int sock, int irq_fd) +{ + int ret; + uint64_t val; + size_t size; + struct vfio_user_irq_info vfio_user_irq_info; + struct vfio_user_header hdr; + uint16_t msg_id = 1; + + ret = read(irq_fd, &val, sizeof val); + if (ret == -1) { + return -1; + } + printf("INTx triggered!\n"); + + size = sizeof(vfio_user_irq_info); + ret = recv_vfio_user_msg(sock, &hdr, false, &msg_id, &vfio_user_irq_info, + &size); + if (ret < 0) { + fprintf(stderr, "failed to receive IRQ message: %s\n", strerror(-ret)); + return ret; + } + if (vfio_user_irq_info.subindex >= 1) { + fprintf(stderr, "bad IRQ %d, max=1\n", vfio_user_irq_info.subindex); + return -ENOENT; + } + + ret = send_vfio_user_msg(sock, msg_id, true, VFIO_USER_VM_INTERRUPT, + NULL, 0, NULL, 0); + if (ret < 0) { + fprintf(stderr, "failed to send reply for VFIO_USER_VM_INTERRUPT: " + "%s\n", strerror(-ret)); + return ret; + } + printf("INTx messaged triggered!\n"); + + return 0; +} + +static int +access_bar0(int sock, int irq_fd) { - time_t t = time(NULL); - const int sleep_time = 1; + time_t t = 1; int ret = access_region(sock, LM_DEV_BAR0_REG_IDX, true, 0, &t, sizeof t); if (ret < 0) { @@ -409,8 +408,6 @@ access_bar0(int sock) printf("wrote to BAR0: %ld\n", t); - sleep(sleep_time); - ret = access_region(sock, LM_DEV_BAR0_REG_IDX, false, 0, &t, sizeof t); if (ret < 0) { fprintf(stderr, "failed to read from BAR0: %s\n", strerror(-ret)); @@ -419,7 +416,7 @@ access_bar0(int sock) printf("read from BAR0: %ld\n", t); - assert(t >= sleep_time); + ret = wait_for_irqs(sock, irq_fd); return 0; } @@ -701,7 +698,7 @@ migrate_from(int sock) int main(int argc, char *argv[]) { - int ret, sock; + int ret, sock, irq_fd; struct vfio_user_dma_region *dma_regions; struct vfio_device_info client_dev_info = {0}; int *dma_region_fds; @@ -756,6 +753,17 @@ int main(int argc, char *argv[]) return ret; } + /* try to access a bogus region, we should het an error */ + ret = access_region(sock, 0xdeadbeef, false, 0, &ret, sizeof ret); + if (ret != -EINVAL) { + fprintf(stderr, + "expected -EINVAL accessing bogus region, got %d instead\n", + ret); + return ret; + } + + + /* XXX VFIO_USER_DEVICE_GET_INFO */ ret = get_device_info(sock, &client_dev_info); if (ret < 0) { @@ -816,17 +824,15 @@ int main(int argc, char *argv[]) } /* - * XXX VFIO_USER_REGION_READ and VFIO_USER_REGION_WRITE - * - * BAR0 in the server does not support memory mapping so it must be accessed - * via explicit messages. + * XXX VFIO_USER_DEVICE_GET_IRQ_INFO and VFIO_IRQ_SET_ACTION_TRIGGER + * Query interrupts and configure an eventfd to be associated with INTx. */ - ret = access_bar0(sock); + ret = configure_irqs(sock); if (ret < 0) { - fprintf(stderr, "failed to access BAR0: %s\n", strerror(-ret)); + fprintf(stderr, "failed to configure IRQs: %s\n", strerror(-ret)); exit(EXIT_FAILURE); } - + irq_fd = ret; dirty_bitmap.argsz = sizeof dirty_bitmap; dirty_bitmap.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_START; @@ -840,13 +846,14 @@ int main(int argc, char *argv[]) } /* - * XXX VFIO_USER_DEVICE_GET_IRQ_INFO and VFIO_IRQ_SET_ACTION_TRIGGER - * Query interrupts, configure an eventfd to be associated with INTx, and - * finally wait for the server to fire the interrupt. + * XXX VFIO_USER_REGION_READ and VFIO_USER_REGION_WRITE + * + * BAR0 in the server does not support memory mapping so it must be accessed + * via explicit messages. */ - ret = configure_irqs(sock); + ret = access_bar0(sock, irq_fd); if (ret < 0) { - fprintf(stderr, "failed to configure IRQs: %s\n", strerror(-ret)); + fprintf(stderr, "failed to access BAR0: %s\n", strerror(-ret)); exit(EXIT_FAILURE); } @@ -904,14 +911,6 @@ int main(int argc, char *argv[]) ret = migrate_from(sock); } - /* - * Try to touch BAR0, we should get an error as the device is stopped. - */ - ret = access_bar0(sock); - if (ret != EINVAL) { - fprintf(stderr, "expected an error, got %d instead\n", ret); - } - return 0; } diff --git a/samples/server.c b/samples/server.c index c814c2e..c5cd0e1 100644 --- a/samples/server.c +++ b/samples/server.c @@ -41,6 +41,7 @@ #include <openssl/md5.h> #include <sys/mman.h> #include <sys/param.h> +#include <sys/time.h> #include "../lib/muser.h" #include "../lib/muser_priv.h" @@ -53,6 +54,7 @@ struct dma_regions { #define NR_DMA_REGIONS 96 struct server_data { + lm_ctx_t *lm_ctx; time_t bar0; uint8_t *bar1; struct dma_regions regions[NR_DMA_REGIONS]; @@ -82,6 +84,13 @@ bar0_access(void *pvt, char * const buf, size_t count, loff_t offset, } if (is_write) { + struct itimerval new = {.it_value.tv_sec = *(time_t*)buf}; + lm_log(server_data->lm_ctx, LM_DBG, + "arming timer to trigger in %d seconds", new.it_value.tv_sec); + if (setitimer(ITIMER_REAL, &new, NULL) != 0) { + lm_log(server_data->lm_ctx, LM_ERR, "failed to arm timer: %m"); + return -1; + } memcpy(&server_data->bar0, buf, count); } else { time_t delta = time(NULL) - server_data->bar0; @@ -104,7 +113,7 @@ bool irq_triggered = false; static void _sa_handler(int signum) { int _errno = errno; - if (signum == SIGUSR1) { + if (signum == SIGALRM) { irq_triggered = true; } errno = _errno; @@ -365,13 +374,11 @@ int main(int argc, char *argv[]){ }; sigemptyset(&act.sa_mask); - if (sigaction(SIGUSR1, &act, NULL) == -1) { - fprintf(stderr, "failed to register signal handler\n"); - ret = -EFAULT; - goto out; + if (sigaction(SIGALRM, &act, NULL) == -1) { + err(EXIT_FAILURE, "failed to register signal handler"); } - lm_ctx = lm_ctx_create(&dev_info); + server_data.lm_ctx = lm_ctx = lm_ctx_create(&dev_info); if (lm_ctx == NULL) { fprintf(stderr, "failed to initialize device emulation\n"); ret = -1; |