aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSwapnil Ingle <swapnil.ingle@nutanix.com>2021-08-27 13:18:53 +0200
committerGitHub <noreply@github.com>2021-08-27 13:18:53 +0200
commit080e664ed5e79dcf5ae5a36521cab0ddb7ebc5f0 (patch)
tree5d920a8a71aa57f088aba9a6f881c71121866f69 /lib
parent2ed612697e8fde14e9995cc1ac4dd5143ae8e0b7 (diff)
downloadlibvfio-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.c25
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;
}