diff options
author | John Levon <john.levon@nutanix.com> | 2021-03-31 16:49:52 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-31 16:49:52 +0100 |
commit | 14b237fc80473bf4419a2bccda4cf7e7d382c174 (patch) | |
tree | 959e0cc1c4d2557f624df6fa5c189a8cdc92993f /samples | |
parent | 0ae00cbb9edcc3879b1276cd61479d668a7f1ec9 (diff) | |
download | libvfio-user-14b237fc80473bf4419a2bccda4cf7e7d382c174.zip libvfio-user-14b237fc80473bf4419a2bccda4cf7e7d382c174.tar.gz libvfio-user-14b237fc80473bf4419a2bccda4cf7e7d382c174.tar.bz2 |
rework DMA callbacks (#396)
This fixes a number of issues with how DMA is handled, based on some changes by
Thanos Makatos:
- rename callbacks to register/unregister, as there is not necessarily
any mapping
- provide the (large) page-aligned mapped start and size, the page size used,
as well as the protection flags: some API users need these
- for convenience, provide the virtual address separately that corresponds to
the mapped region
- we should only require a DMA controller to use vfu_addr_to_sg(),
not an unregister callback
- the callbacks should return errno not -errno
- region removal was incorrectly updating the region array
- various other cleanups and clarifications
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/gpio-pci-idio-16.c | 21 | ||||
-rw-r--r-- | samples/server.c | 46 |
2 files changed, 30 insertions, 37 deletions
diff --git a/samples/gpio-pci-idio-16.c b/samples/gpio-pci-idio-16.c index 26ac62a..1efc291 100644 --- a/samples/gpio-pci-idio-16.c +++ b/samples/gpio-pci-idio-16.c @@ -126,13 +126,12 @@ migration_write_data(UNUSED vfu_ctx_t *vfu_ctx, void *buf, __u64 size, } static void -map_dma(vfu_ctx_t *vfu_ctx UNUSED, uint64_t iova UNUSED, uint64_t len UNUSED, - uint32_t prot UNUSED) +dma_register(UNUSED vfu_ctx_t *vfu_ctx, UNUSED vfu_dma_info_t *info) { } static int -unmap_dma(vfu_ctx_t *vfu_ctx UNUSED, uint64_t iova UNUSED, uint64_t len UNUSED) +dma_unregister(UNUSED vfu_ctx_t *vfu_ctx, UNUSED vfu_dma_info_t *info) { return 0; } @@ -142,7 +141,6 @@ main(int argc, char *argv[]) { int ret; bool verbose = false; - bool dma = false; char opt; struct sigaction act = { .sa_handler = _sa_handler }; vfu_ctx_t *vfu_ctx; @@ -159,16 +157,13 @@ main(int argc, char *argv[]) .write_data = &migration_write_data }; - while ((opt = getopt(argc, argv, "vd")) != -1) { + while ((opt = getopt(argc, argv, "v")) != -1) { switch (opt) { case 'v': verbose = true; break; - case 'd': - dma = true; - break; default: /* '?' */ - fprintf(stderr, "Usage: %s [-d] [-v] <socketpath>\n", argv[0]); + fprintf(stderr, "Usage: %s [-v] <socketpath>\n", argv[0]); exit(EXIT_FAILURE); } } @@ -227,11 +222,9 @@ main(int argc, char *argv[]) err(EXIT_FAILURE, "failed to setup irq counts"); } - if (dma) { - ret = vfu_setup_device_dma_cb(vfu_ctx, map_dma, unmap_dma); - if (ret < 0) { - err(EXIT_FAILURE, "failed to setup DMA"); - } + ret = vfu_setup_device_dma(vfu_ctx, dma_register, dma_unregister); + if (ret < 0) { + err(EXIT_FAILURE, "failed to setup DMA"); } ret = vfu_realize_ctx(vfu_ctx); diff --git a/samples/server.c b/samples/server.c index d5318a3..5130688 100644 --- a/samples/server.c +++ b/samples/server.c @@ -48,8 +48,7 @@ #include "tran_sock.h" struct dma_regions { - uint64_t addr; - uint64_t len; + struct iovec iova; uint32_t prot; }; @@ -152,36 +151,35 @@ static void _sa_handler(int signum) } static void -map_dma(vfu_ctx_t *vfu_ctx, uint64_t iova, uint64_t len, uint32_t prot) +dma_register(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info) { struct server_data *server_data = vfu_get_private(vfu_ctx); int idx; for (idx = 0; idx < NR_DMA_REGIONS; idx++) { - if (server_data->regions[idx].addr == 0 && - server_data->regions[idx].len == 0) + if (server_data->regions[idx].iova.iov_base == NULL && + server_data->regions[idx].iova.iov_len == 0) break; } if (idx >= NR_DMA_REGIONS) { errx(EXIT_FAILURE, "Failed to add dma region, slots full\n"); } - server_data->regions[idx].addr = iova; - server_data->regions[idx].len = len; - server_data->regions[idx].prot = prot; + server_data->regions[idx].iova = info->iova; + server_data->regions[idx].prot = info->prot; } static int -unmap_dma(vfu_ctx_t *vfu_ctx, uint64_t iova, uint64_t len) +dma_unregister(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info) { struct server_data *server_data = vfu_get_private(vfu_ctx); int idx; for (idx = 0; idx < NR_DMA_REGIONS; idx++) { - if (server_data->regions[idx].addr == iova && - server_data->regions[idx].len == len) { - server_data->regions[idx].addr = 0; - server_data->regions[idx].len = 0; + if (server_data->regions[idx].iova.iov_len == info->iova.iov_len && + server_data->regions[idx].iova.iov_base == info->iova.iov_base) { + server_data->regions[idx].iova.iov_base = NULL; + server_data->regions[idx].iova.iov_len = 0; return 0; } } @@ -217,26 +215,28 @@ static void do_dma_io(vfu_ctx_t *vfu_ctx, struct server_data *server_data) assert(vfu_ctx != NULL); - ret = vfu_addr_to_sg(vfu_ctx, server_data->regions[0].addr, count, &sg, - 1, PROT_WRITE); + ret = vfu_addr_to_sg(vfu_ctx, + (vfu_dma_addr_t)server_data->regions[0].iova.iov_base, + count, &sg, 1, PROT_WRITE); if (ret < 0) { - errx(EXIT_FAILURE, "failed to map %#lx-%#lx: %s\n", - server_data->regions[0].addr, - server_data->regions[0].addr + count -1, strerror(-ret)); + errx(EXIT_FAILURE, "failed to map %p-%p: %s\n", + server_data->regions[0].iova.iov_base, + server_data->regions[0].iova.iov_base + count -1, + strerror(-ret)); } memset(buf, 'A', count); get_md5sum(buf, count, md5sum1); - printf("%s: WRITE addr %#lx count %d\n", __func__, - server_data->regions[0].addr, count); + printf("%s: WRITE addr %p count %d\n", __func__, + server_data->regions[0].iova.iov_base, count); ret = vfu_dma_write(vfu_ctx, &sg, buf); if (ret < 0) { errx(EXIT_FAILURE, "vfu_dma_write failed: %s\n", strerror(-ret)); } memset(buf, 0, count); - printf("%s: READ addr %#lx count %d\n", __func__, - server_data->regions[0].addr, count); + printf("%s: READ addr %p count %d\n", __func__, + server_data->regions[0].iova.iov_base, count); ret = vfu_dma_read(vfu_ctx, &sg, buf); if (ret < 0) { errx(EXIT_FAILURE, "vfu_dma_read failed: %s\n", strerror(-ret)); @@ -518,7 +518,7 @@ int main(int argc, char *argv[]) err(EXIT_FAILURE, "failed to setup device reset callbacks"); } - ret = vfu_setup_device_dma_cb(vfu_ctx, &map_dma, &unmap_dma); + ret = vfu_setup_device_dma(vfu_ctx, &dma_register, &dma_unregister); if (ret < 0) { err(EXIT_FAILURE, "failed to setup device DMA callbacks"); } |