diff options
author | Swapnil Ingle <swapnil.ingle@nutanix.com> | 2021-08-27 13:18:53 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-27 13:18:53 +0200 |
commit | 080e664ed5e79dcf5ae5a36521cab0ddb7ebc5f0 (patch) | |
tree | 5d920a8a71aa57f088aba9a6f881c71121866f69 /lib | |
parent | 2ed612697e8fde14e9995cc1ac4dd5143ae8e0b7 (diff) | |
download | libvfio-user-080e664ed5e79dcf5ae5a36521cab0ddb7ebc5f0.zip libvfio-user-080e664ed5e79dcf5ae5a36521cab0ddb7ebc5f0.tar.gz libvfio-user-080e664ed5e79dcf5ae5a36521cab0ddb7ebc5f0.tar.bz2 |
Add support for VFIO_DMA_UNMAP_FLAG_ALL flag (#600)
* Add support for VFIO_DMA_UNMAP_FLAG_ALL flag
Signed-off-by: Swapnil Ingle <swapnil.ingle@nutanix.com>
Reviewed-by: John Levon <john.levon@nutanix.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libvfio-user.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c index 4e6b81f..3cb30ba 100644 --- a/lib/libvfio-user.c +++ b/lib/libvfio-user.c @@ -545,7 +545,8 @@ handle_dma_unmap(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg, struct vfio_user_dma_unmap *dma_unmap) { size_t out_size; - int ret; + int ret = 0; + bool unmap_all = false; char rstr[1024]; assert(vfu_ctx != NULL); @@ -558,6 +559,12 @@ handle_dma_unmap(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg, return ERROR_INT(EINVAL); } + if ((dma_unmap->flags & VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP) && + (dma_unmap->flags & VFIO_DMA_UNMAP_FLAG_ALL)) { + vfu_log(vfu_ctx, LOG_ERR, "invalid DMA flags=%#x", dma_unmap->flags); + return ERROR_INT(EINVAL); + } + snprintf(rstr, sizeof(rstr), "[%#lx, %#lx) flags=%#x", dma_unmap->addr, dma_unmap->addr + dma_unmap->size, dma_unmap->flags); @@ -585,6 +592,13 @@ handle_dma_unmap(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg, * the DMA controller. */ out_size += sizeof(*dma_unmap->bitmap) + dma_unmap->bitmap->size; + } else if (dma_unmap->flags == VFIO_DMA_UNMAP_FLAG_ALL) { + if (dma_unmap->addr || dma_unmap->size) { + vfu_log(vfu_ctx, LOG_ERR, "bad addr=%#lx or size=%#lx, expected " + "both to be zero", dma_unmap->addr, dma_unmap->size); + return ERROR_INT(EINVAL); + } + unmap_all = true; } else if (dma_unmap->flags != 0) { vfu_log(vfu_ctx, LOG_ERR, "bad flags=%#x", dma_unmap->flags); return ERROR_INT(ENOTSUP); @@ -596,6 +610,12 @@ handle_dma_unmap(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg, } memcpy(msg->out_data, dma_unmap, sizeof(*dma_unmap)); + if (unmap_all) { + dma_controller_remove_all_regions(vfu_ctx->dma, + vfu_ctx->dma_unregister, vfu_ctx); + goto out; + } + if (dma_unmap->flags & VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP) { memcpy(msg->out_data + sizeof(*dma_unmap), dma_unmap->bitmap, sizeof(*dma_unmap->bitmap)); ret = dma_controller_dirty_page_get(vfu_ctx->dma, @@ -621,7 +641,10 @@ handle_dma_unmap(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg, "failed to remove DMA region %s: %m", rstr); return ERROR_INT(ret); } + +out: msg->out_size = out_size; + return ret; } |