diff options
author | Thanos Makatos <thanos.makatos@nutanix.com> | 2020-12-15 14:56:32 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-15 14:56:32 +0000 |
commit | 8694149b351e3e125aa8f1740f8d5925e7ec112c (patch) | |
tree | 55fae56b5280eddd8c5c23d8c846fe36425e7ba2 /samples | |
parent | 3148a598f4ac0711d2f46ef9186e51a4779f1bf1 (diff) | |
download | libvfio-user-8694149b351e3e125aa8f1740f8d5925e7ec112c.zip libvfio-user-8694149b351e3e125aa8f1740f8d5925e7ec112c.tar.gz libvfio-user-8694149b351e3e125aa8f1740f8d5925e7ec112c.tar.bz2 |
send file descriptors for sparse areas in get region info (#201)
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/client.c | 55 | ||||
-rw-r--r-- | samples/gpio-pci-idio-16.c | 2 | ||||
-rw-r--r-- | samples/server.c | 19 |
3 files changed, 48 insertions, 28 deletions
diff --git a/samples/client.c b/samples/client.c index 3e3ba54..576815d 100644 --- a/samples/client.c +++ b/samples/client.c @@ -207,10 +207,10 @@ send_device_reset(int sock) /* returns whether a VFIO migration capability is found */ static bool -get_region_vfio_caps(struct vfio_info_cap_header *header) +get_region_vfio_caps(struct vfio_info_cap_header *header, + struct vfio_region_info_cap_sparse_mmap *sparse) { struct vfio_region_info_cap_type *type; - struct vfio_region_info_cap_sparse_mmap *sparse; unsigned int i; bool migr = false; @@ -247,13 +247,12 @@ get_region_vfio_caps(struct vfio_info_cap_header *header) } static void -do_get_device_region_info(int sock, struct vfio_region_info *region_info) +do_get_device_region_info(int sock, struct vfio_region_info *region_info, + int *fds, size_t *nr_fds) { - int ret = vfu_msg(sock, 0, - VFIO_USER_DEVICE_GET_REGION_INFO, - region_info, region_info->argsz, - NULL, - region_info, region_info->argsz); + int ret = vfu_msg_fds(sock, 0, VFIO_USER_DEVICE_GET_REGION_INFO, + region_info, region_info->argsz, NULL, + region_info, region_info->argsz, fds, nr_fds); if (ret < 0) { errx(EXIT_FAILURE, "failed to get device region info: %s", strerror(-ret)); @@ -266,19 +265,24 @@ get_device_region_info(int sock, uint32_t index) struct vfio_region_info *region_info; size_t cap_sz; size_t size = sizeof(struct vfio_region_info); + size_t nr_fds = CLIENT_MAX_FDS; + int fds[nr_fds]; region_info = alloca(size); region_info->argsz = size; region_info->index = index; - do_get_device_region_info(sock, region_info); + do_get_device_region_info(sock, region_info, NULL, 0); if (region_info->argsz > size) { size = region_info->size; region_info = alloca(size); region_info->argsz = size; region_info->index = index; - do_get_device_region_info(sock, region_info); + do_get_device_region_info(sock, region_info, fds, &nr_fds); assert(region_info->size == size); + assert(nr_fds == 2); + assert(fds[0] >= 0); + assert(fds[1] >= 0); } cap_sz = region_info->argsz - sizeof(struct vfio_region_info); @@ -286,7 +290,25 @@ get_device_region_info(int sock, uint32_t index) "cap_sz %lu\n", __func__, index, region_info->offset, region_info->flags, region_info->size, cap_sz); if (cap_sz) { - if (get_region_vfio_caps((struct vfio_info_cap_header*)(region_info + 1))) { + struct vfio_region_info_cap_sparse_mmap *sparse = NULL; + if (get_region_vfio_caps((struct vfio_info_cap_header*)(region_info + 1), + sparse)) { + if (sparse != NULL) { + size_t i; + assert(nr_fds == 2); + assert(sparse->nr_areas == 2); + for (i = 0; i < sparse->nr_areas; i++) { + void *addr = mmap(NULL, sparse->areas[i].size, + PROT_READ | PROT_WRITE, MAP_SHARED, + fds[i], sparse->areas[i].offset); + if (addr == MAP_FAILED) { + err(EXIT_FAILURE, + "failed to mmap sparse region %lu (%#llx-%#llx)", + i, sparse->areas[i].offset, + sparse->areas[i].offset + sparse->areas[i].size - 1); + } + } + } return true; } } @@ -386,7 +408,7 @@ configure_irqs(int sock) ret = vfu_msg_iovec(sock, msg_id, VFIO_USER_DEVICE_SET_IRQS, iovecs, ARRAY_SIZE(iovecs), &irq_fd, 1, - NULL, NULL, 0); + NULL, NULL, 0, NULL, 0); if (ret < 0) { errx(EXIT_FAILURE, "failed to send configure IRQs message: %s", @@ -435,7 +457,7 @@ access_region(int sock, int region, bool is_write, uint64_t offset, ret = vfu_msg_iovec(sock, 0, op, send_iovecs, nr_send_iovecs, NULL, 0, NULL, - &recv_data, recv_data_len); + &recv_data, recv_data_len, NULL, 0); if (ret != 0) { warnx("failed to %s region %d %#lx-%#lx: %s", is_write ? "write to" : "read from", region, offset, @@ -475,8 +497,7 @@ wait_for_irqs(int sock, int irq_fd) printf("INTx triggered!\n"); size = sizeof(vfio_user_irq_info); - ret = vfu_recv(sock, &hdr, false, &msg_id, - &vfio_user_irq_info, &size); + ret = vfu_recv(sock, &hdr, false, &msg_id, &vfio_user_irq_info, &size); if (ret < 0) { errx(EXIT_FAILURE, "failed to receive IRQ message: %s", strerror(-ret)); @@ -664,7 +685,7 @@ get_dirty_bitmaps(int sock, struct vfio_user_dma_region *dma_regions, ret = vfu_msg_iovec(sock, 0, VFIO_USER_DIRTY_PAGES, iovecs, ARRAY_SIZE(iovecs), NULL, 0, - &hdr, data, ARRAY_SIZE(data)); + &hdr, data, ARRAY_SIZE(data), NULL, 0); if (ret != 0) { errx(EXIT_FAILURE, "failed to start dirty page logging: %s", strerror(-ret)); @@ -903,7 +924,7 @@ map_dma_regions(int sock, int max_fds, struct vfio_user_dma_region *dma_regions, ret = vfu_msg_iovec(sock, i, VFIO_USER_DMA_MAP, iovecs, ARRAY_SIZE(iovecs), dma_region_fds + (i * max_fds), max_fds, - NULL, NULL, 0); + NULL, NULL, 0, NULL, 0); if (ret < 0) { errx(EXIT_FAILURE, "failed to map DMA regions: %s", strerror(-ret)); } diff --git a/samples/gpio-pci-idio-16.c b/samples/gpio-pci-idio-16.c index da7c4c0..e31db6d 100644 --- a/samples/gpio-pci-idio-16.c +++ b/samples/gpio-pci-idio-16.c @@ -122,7 +122,7 @@ main(int argc, char *argv[]) } ret = vfu_setup_region(vfu_ctx, VFU_PCI_DEV_BAR2_REGION_IDX, 0x100, - &bar2_access, VFU_REGION_FLAG_RW, NULL, 0, NULL); + &bar2_access, VFU_REGION_FLAG_RW, NULL, 0, -1); if (ret < 0) { fprintf(stderr, "failed to setup region\n"); goto out; diff --git a/samples/server.c b/samples/server.c index a1bedac..7860f86 100644 --- a/samples/server.c +++ b/samples/server.c @@ -232,14 +232,6 @@ static void do_dma_io(vfu_ctx_t *vfu_ctx, struct server_data *server_data) } } -unsigned long map_area(UNUSED void *pvt, UNUSED unsigned long off, - UNUSED unsigned long len) -{ - assert(false); - - return 0; -} - static int device_reset(UNUSED void *pvt) { printf("device reset callback\n"); @@ -386,6 +378,7 @@ int main(int argc, char *argv[]) vfu_pci_hdr_id_t id = {.raw = 0xdeadbeef}; vfu_pci_hdr_ss_t ss = {.raw = 0xcafebabe}; vfu_pci_hdr_cc_t cc = {.pi = 0xab, .scc = 0xcd, .bcc = 0xef}; + FILE *fp; while ((opt = getopt(argc, argv, "v")) != -1) { switch (opt) { @@ -431,7 +424,7 @@ int main(int argc, char *argv[]) } ret = vfu_setup_region(vfu_ctx, VFU_PCI_DEV_BAR0_REGION_IDX, sizeof(time_t), - &bar0_access, VFU_REGION_FLAG_RW, NULL, 0, NULL); + &bar0_access, VFU_REGION_FLAG_RW, NULL, 0, -1); if (ret < 0) { err(EXIT_FAILURE, "failed to setup BAR0 region"); } @@ -440,13 +433,19 @@ int main(int argc, char *argv[]) * Setup BAR1 to be 3 pages in size where only the first and the last pages * are mappable. */ + if ((fp = tmpfile()) == NULL) { + err(EXIT_FAILURE, "failed to create BAR1 file"); + } + if (ftruncate(fileno(fp), 0x3000) == -1) { + err(EXIT_FAILURE, "failed to truncate BAR1 file"); + } struct iovec mmap_areas[] = { { .iov_base = (void*)0, .iov_len = 0x1000 }, { .iov_base = (void*)0x2000, .iov_len = 0x1000 } }; ret = vfu_setup_region(vfu_ctx, VFU_PCI_DEV_BAR1_REGION_IDX, 0x3000, &bar1_access, VFU_REGION_FLAG_RW, - mmap_areas, 3, map_area); + mmap_areas, 2, fileno(fp)); if (ret < 0) { err(EXIT_FAILURE, "failed to setup BAR1 region"); } |