diff options
-rw-r--r-- | lib/dma.c | 15 | ||||
-rw-r--r-- | lib/dma.h | 5 | ||||
-rw-r--r-- | lib/libvfio-user.c | 7 | ||||
-rw-r--r-- | test/mocks.c | 7 | ||||
-rw-r--r-- | test/unit-tests.c | 28 |
5 files changed, 45 insertions, 17 deletions
@@ -215,7 +215,7 @@ dma_controller_destroy(dma_controller_t *dma) int dma_controller_add_region(dma_controller_t *dma, dma_addr_t dma_addr, size_t size, - int fd, off_t offset) + int fd, off_t offset, uint32_t prot) { int idx; dma_memory_region_t *region; @@ -243,7 +243,13 @@ dma_controller_add_region(dma_controller_t *dma, */ vfu_log(dma->vfu_ctx, LOG_ERR, "bad fd=%d for new DMA region %#lx-%#lx, existing fd=%d\n", - fd, offset, offset + size, region->fd); + fd, offset, offset + size - 1, region->fd); + goto err; + } + if (region->prot != prot) { + vfu_log(dma->vfu_ctx, LOG_ERR, "bad prot=%#x " + "for new DMA region %#lx-%#lx, existing prot=%#x\n", + prot, offset, offset + size - 1, region->prot); goto err; } return idx; @@ -284,12 +290,13 @@ dma_controller_add_region(dma_controller_t *dma, region->size = size; region->page_size = page_size; region->offset = offset; + region->prot = prot; region->fd = fd; region->refcnt = 0; if (fd != -1) { - region->virt_addr = dma_map_region(region, PROT_READ | PROT_WRITE, - 0, region->size); + region->virt_addr = dma_map_region(region, region->prot, 0, + region->size); if (region->virt_addr == MAP_FAILED) { vfu_log(dma->vfu_ctx, LOG_ERR, "failed to memory map DMA region %#lx-%#lx: %s\n", @@ -83,6 +83,9 @@ struct vfu_ctx; typedef struct { dma_addr_t dma_addr; // DMA address of this region + uint32_t prot; // memory protection of the mapping + // defined in sys/mman.h + size_t size; // Size of this region int fd; // File descriptor to mmap int page_size; // Page size of this fd @@ -116,7 +119,7 @@ dma_controller_destroy(dma_controller_t *dma); int dma_controller_add_region(dma_controller_t *dma, dma_addr_t dma_addr, size_t size, - int fd, off_t offset); + int fd, off_t offset, uint32_t prot); int dma_controller_remove_region(dma_controller_t *dma, diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c index c0503ff..2b95b43 100644 --- a/lib/libvfio-user.c +++ b/lib/libvfio-user.c @@ -519,7 +519,8 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map, dma_regions[i].addr, dma_regions[i].size, fd, - dma_regions[i].offset); + dma_regions[i].offset, + dma_regions[i].prot); if (ret < 0) { if (fd != -1) { close(fd); @@ -534,10 +535,10 @@ handle_dma_map_or_unmap(vfu_ctx_t *vfu_ctx, uint32_t size, bool map, } ret = 0; vfu_log(vfu_ctx, LOG_DEBUG, - "added DMA region %#lx-%#lx offset=%#lx fd=%d", + "added DMA region %#lx-%#lx offset=%#lx fd=%d prot=%#x", dma_regions[i].addr, dma_regions[i].addr + dma_regions[i].size - 1, - dma_regions[i].offset, fd); + dma_regions[i].offset, fd, dma_regions[i].prot); } else { ret = dma_controller_remove_region(vfu_ctx->dma, dma_regions[i].addr, diff --git a/test/mocks.c b/test/mocks.c index faa8ed4..7f7fc02 100644 --- a/test/mocks.c +++ b/test/mocks.c @@ -47,10 +47,12 @@ struct function int __wrap_dma_controller_add_region(dma_controller_t *dma, dma_addr_t dma_addr, - size_t size, int fd, off_t offset) + size_t size, int fd, off_t offset, + uint32_t prot) { if (!is_patched(dma_controller_add_region)) { - return __real_dma_controller_add_region(dma, dma_addr, size, fd, offset); + return __real_dma_controller_add_region(dma, dma_addr, size, fd, offset, + prot); } check_expected_ptr(dma); @@ -58,6 +60,7 @@ __wrap_dma_controller_add_region(dma_controller_t *dma, dma_addr_t dma_addr, check_expected(size); check_expected(fd); check_expected(offset); + check_expected(prot); return mock(); } diff --git a/test/unit-tests.c b/test/unit-tests.c index 30cc71c..135eabe 100644 --- a/test/unit-tests.c +++ b/test/unit-tests.c @@ -85,7 +85,8 @@ test_dma_map_without_fd(void **state __attribute__((unused))) struct vfio_user_dma_region r = { .addr = 0xdeadbeef, .size = 0xcafebabe, - .offset = 0x8badf00d + .offset = 0x8badf00d, + .prot = PROT_NONE }; int fd; @@ -96,6 +97,7 @@ test_dma_map_without_fd(void **state __attribute__((unused))) expect_value(__wrap_dma_controller_add_region, size, r.size); expect_value(__wrap_dma_controller_add_region, fd, -1); expect_value(__wrap_dma_controller_add_region, offset, r.offset); + expect_value(__wrap_dma_controller_add_region, prot, r.prot); assert_int_equal(0, handle_dma_map_or_unmap(&vfu_ctx, size, true, &fd, 0, &r)); } @@ -113,13 +115,15 @@ test_dma_add_regions_mixed(void **state __attribute__((unused))) [0] = { .addr = 0xdeadbeef, .size = 0x1000, - .offset = 0 + .offset = 0, + .prot = PROT_NONE }, [1] = { .addr = 0xcafebabe, .size = 0x1000, .offset = 0x1000, - .flags = VFIO_USER_F_DMA_REGION_MAPPABLE + .flags = VFIO_USER_F_DMA_REGION_MAPPABLE, + .prot = PROT_READ|PROT_WRITE } }; int fd = 0x0badf00d; @@ -132,11 +136,13 @@ test_dma_add_regions_mixed(void **state __attribute__((unused))) expect_value(__wrap_dma_controller_add_region, size, r[0].size); expect_value(__wrap_dma_controller_add_region, fd, -1); expect_value(__wrap_dma_controller_add_region, offset, r[0].offset); + expect_value(__wrap_dma_controller_add_region, prot, r[0].prot); expect_value(__wrap_dma_controller_add_region, dma, vfu_ctx.dma); expect_value(__wrap_dma_controller_add_region, dma_addr, r[1].addr); expect_value(__wrap_dma_controller_add_region, size, r[1].size); expect_value(__wrap_dma_controller_add_region, fd, fd); expect_value(__wrap_dma_controller_add_region, offset, r[1].offset); + expect_value(__wrap_dma_controller_add_region, prot, r[1].prot); assert_int_equal(0, handle_dma_map_or_unmap(&vfu_ctx, sizeof r, true, &fd, 1, r)); } @@ -161,13 +167,15 @@ test_dma_add_regions_mixed_partial_failure(void **state __attribute__((unused))) .addr = 0xcafebabe, .size = 0x1000, .offset = 0x1000, - .flags = VFIO_USER_F_DMA_REGION_MAPPABLE + .flags = VFIO_USER_F_DMA_REGION_MAPPABLE, + .prot = PROT_READ }, [2] = { .addr = 0xbabecafe, .size = 0x1000, .offset = 0x2000, - .flags = VFIO_USER_F_DMA_REGION_MAPPABLE + .flags = VFIO_USER_F_DMA_REGION_MAPPABLE, + .prot = PROT_READ|PROT_WRITE } }; int fds[] = {0xa, 0xb}; @@ -180,6 +188,7 @@ test_dma_add_regions_mixed_partial_failure(void **state __attribute__((unused))) expect_value(__wrap_dma_controller_add_region, size, r[0].size); expect_value(__wrap_dma_controller_add_region, fd, -1); expect_value(__wrap_dma_controller_add_region, offset, r[0].offset); + expect_value(__wrap_dma_controller_add_region, prot, r[0].prot); will_return(__wrap_dma_controller_add_region, 0); /* 2nd region */ @@ -188,6 +197,7 @@ test_dma_add_regions_mixed_partial_failure(void **state __attribute__((unused))) expect_value(__wrap_dma_controller_add_region, size, r[1].size); expect_value(__wrap_dma_controller_add_region, fd, fds[0]); expect_value(__wrap_dma_controller_add_region, offset, r[1].offset); + expect_value(__wrap_dma_controller_add_region, prot, r[1].prot); will_return(__wrap_dma_controller_add_region, 0); /* 3rd region */ @@ -196,6 +206,7 @@ test_dma_add_regions_mixed_partial_failure(void **state __attribute__((unused))) expect_value(__wrap_dma_controller_add_region, size, r[2].size); expect_value(__wrap_dma_controller_add_region, fd, fds[1]); expect_value(__wrap_dma_controller_add_region, offset, r[2].offset); + expect_value(__wrap_dma_controller_add_region, prot, r[2].prot); will_return(__wrap_dma_controller_add_region, -0x1234); patch(close); @@ -227,8 +238,9 @@ test_dma_map_return_value(void **state __attribute__((unused))) expect_value(__wrap_dma_controller_add_region, size, r.size); expect_value(__wrap_dma_controller_add_region, fd, -1); expect_value(__wrap_dma_controller_add_region, offset, r.offset); + expect_value(__wrap_dma_controller_add_region, prot, r.prot); will_return(__wrap_dma_controller_add_region, 2); - + assert_int_equal(0, handle_dma_map_or_unmap(&vfu_ctx, sizeof(struct vfio_user_dma_region), true, &fd, 0, &r)); @@ -245,7 +257,8 @@ test_dma_controller_add_region_no_fd(void **state __attribute__((unused))) off_t offset = 0; dma_memory_region_t *r; - assert_int_equal(0, dma_controller_add_region(&dma, dma_addr, size, fd, offset)); + assert_int_equal(0, dma_controller_add_region(&dma, dma_addr, size, fd, + offset, PROT_NONE)); assert_int_equal(1, dma.nregions); r = &dma.regions[0]; assert_ptr_equal(NULL, r->virt_addr); @@ -255,6 +268,7 @@ test_dma_controller_add_region_no_fd(void **state __attribute__((unused))) assert_int_equal(offset, r->offset); assert_int_equal(fd, r->fd); assert_int_equal(0, r->refcnt); + assert_int_equal(PROT_NONE, r->prot); } static void |