aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorswapnili <swapnil.ingle@nutanix.com>2020-11-18 09:10:44 +0100
committerGitHub <noreply@github.com>2020-11-18 09:10:44 +0100
commit7f3b16acc80614fa2303d89fcce34ba21a327592 (patch)
tree829b144f6921133c5aff36d8d336a4d763aaea21
parent0eb8d4f83cfc43cd50d799e7b1bd23698ccc60aa (diff)
parent0a3cf29466b3785c12c9fbae502df5351137ec03 (diff)
downloadlibvfio-user-7f3b16acc80614fa2303d89fcce34ba21a327592.zip
libvfio-user-7f3b16acc80614fa2303d89fcce34ba21a327592.tar.gz
libvfio-user-7f3b16acc80614fa2303d89fcce34ba21a327592.tar.bz2
Merge pull request #92 from swapnili/master
Cleanup and warning fixes
-rw-r--r--lib/cap.c7
-rw-r--r--lib/dma.h4
-rw-r--r--lib/muser_ctx.c21
-rw-r--r--samples/CMakeLists.txt4
-rw-r--r--samples/client.c5
-rw-r--r--samples/gpio-pci-idio-16.c5
-rw-r--r--samples/server.c28
-rw-r--r--samples/test_dma_map.c216
-rw-r--r--samples/test_mmap.c199
-rw-r--r--samples/test_read.c263
10 files changed, 45 insertions, 707 deletions
diff --git a/lib/cap.c b/lib/cap.c
index 451c85a..c8c302c 100644
--- a/lib/cap.c
+++ b/lib/cap.c
@@ -209,6 +209,7 @@ handle_pm_write(lm_ctx_t *lm_ctx, uint8_t *cap, char *const buf,
return -EINVAL;
}
assert(false); /* FIXME implement */
+ break;
case offsetof(struct pmcap, pmcs):
if (count != sizeof(struct pmcs)) {
return -EINVAL;
@@ -413,14 +414,15 @@ caps_create(lm_ctx_t *lm_ctx, lm_cap_t **lm_caps, int nr_caps)
struct caps *caps;
if (nr_caps <= 0 || nr_caps >= LM_MAX_CAPS) {
- err = EINVAL;
- goto out;
+ errno = EINVAL;
+ return NULL;
}
assert(lm_caps != NULL);
caps = calloc(1, sizeof *caps);
if (caps == NULL) {
+ err = ENOMEM;
goto out;
}
@@ -466,6 +468,7 @@ out:
if (err) {
free(caps);
caps = NULL;
+ errno = err;
}
return caps;
}
diff --git a/lib/dma.h b/lib/dma.h
index 7715b89..987d8ba 100644
--- a/lib/dma.h
+++ b/lib/dma.h
@@ -303,7 +303,9 @@ dma_unmap_addr(dma_controller_t *dma,
int r;
r = dma_addr_to_sg(dma, dma_addr, len, &sg, 1, PROT_NONE);
- assert(r == 1);
+ if (r != 1) {
+ assert(false);
+ }
dma_unmap_sg(dma, &sg, &iov, 1);
}
diff --git a/lib/muser_ctx.c b/lib/muser_ctx.c
index 9224b11..a9a6bdb 100644
--- a/lib/muser_ctx.c
+++ b/lib/muser_ctx.c
@@ -139,13 +139,21 @@ static inline int recv_blocking(int sock, void *buf, size_t len, int flags)
int ret, fret;
fret = fcntl(sock, F_SETFL, f & ~O_NONBLOCK);
- assert(fret != -1);
+ if (fret == -1) {
+ ret = -errno;
+ fprintf(stderr, "failed to set O_NONBLOCK: %m\n");
+ goto out;
+ }
ret = recv(sock, buf, len, flags);
fret = fcntl(sock, F_SETFL, f);
- assert(fret != -1);
+ if (fret == -1) {
+ ret = -errno;
+ fprintf(stderr, "failed to unset O_NONBLOCK: %m\n");
+ }
+out:
return ret;
}
@@ -693,7 +701,6 @@ irqs_set_data_bool(lm_ctx_t *lm_ctx, struct vfio_irq_set *irq_set, void *data)
eventfd_t val;
assert(data != NULL);
-
for (i = irq_set->start, d8 = data; i < (irq_set->start + irq_set->count);
i++, d8++) {
efd = lm_ctx->irqs.efds[i];
@@ -1314,7 +1321,8 @@ handle_migration_data_offset(lm_ctx_t *lm_ctx, __u64 *offset, bool is_write)
/*
* data_offset is invariant during an iteration.
*/
- break;
+ ret = 0;
+ break;
default:
/*
* reading data_offset is undefined out of sequence
@@ -1323,7 +1331,6 @@ handle_migration_data_offset(lm_ctx_t *lm_ctx, __u64 *offset, bool is_write)
return -EINVAL;
}
-
*offset = lm_ctx->migration.iter.offset + sizeof(struct vfio_device_migration_info);
return ret;
@@ -1361,7 +1368,7 @@ static ssize_t
handle_migration_region_access(lm_ctx_t *lm_ctx, char *buf, size_t count,
loff_t pos, bool is_write)
{
- int ret;
+ int ret = -EINVAL;
assert(lm_ctx != NULL);
assert(buf != NULL);
@@ -1626,7 +1633,7 @@ static int
handle_device_set_irqs(lm_ctx_t *lm_ctx, uint32_t size,
int *fds, int nr_fds, struct vfio_irq_set *irq_set)
{
- void *data;
+ void *data = NULL;
assert(lm_ctx != NULL);
assert(irq_set != NULL);
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index 49a9201..bb963da 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -28,10 +28,6 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
-add_executable(test_read test_read.c)
-add_executable(test_mmap test_mmap.c)
-add_executable(test_dma_map test_dma_map.c)
-
add_executable(server server.c)
target_link_libraries(server muser ssl crypto)
add_executable(client client.c ../lib/muser_ctx.c ../lib/muser_pci.c ../lib/dma.c ../lib/cap.c)
diff --git a/samples/client.c b/samples/client.c
index d6be91d..bd8d2b3 100644
--- a/samples/client.c
+++ b/samples/client.c
@@ -550,7 +550,7 @@ static int handle_dma_io(int sock, struct vfio_user_dma_region *dma_regions,
static int
get_dirty_bitmaps(int sock, struct vfio_user_dma_region *dma_regions,
- int nr_dma_regions)
+ UNUSED int nr_dma_regions)
{
struct vfio_iommu_type1_dirty_bitmap dirty_bitmap = {0};
struct vfio_iommu_type1_dirty_bitmap_get bitmaps[2];
@@ -566,7 +566,8 @@ get_dirty_bitmaps(int sock, struct vfio_user_dma_region *dma_regions,
char data[ARRAY_SIZE(bitmaps)];
assert(dma_regions != NULL);
- assert(nr_dma_regions >= (int)ARRAY_SIZE(bitmaps));
+ //FIXME: Is below assert correct?
+ //assert(nr_dma_regions >= (int)ARRAY_SIZE(bitmaps));
for (i = 0; i < ARRAY_SIZE(bitmaps); i++) {
bitmaps[i].iova = dma_regions[i].addr;
diff --git a/samples/gpio-pci-idio-16.c b/samples/gpio-pci-idio-16.c
index 9a79d0c..d9bfa0e 100644
--- a/samples/gpio-pci-idio-16.c
+++ b/samples/gpio-pci-idio-16.c
@@ -114,9 +114,6 @@ int main(int argc, char *argv[])
lm_ctx = lm_ctx_create(&dev_info);
if (lm_ctx == NULL) {
- if (errno == EINTR) {
- goto out;
- }
fprintf(stderr, "failed to initialize device emulation: %m\n");
return -1;
}
@@ -126,7 +123,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "failed to realize device emulation: %m\n");
}
}
-out:
+
lm_ctx_destroy(lm_ctx);
return ret;
}
diff --git a/samples/server.c b/samples/server.c
index 01978f3..5e3c89e 100644
--- a/samples/server.c
+++ b/samples/server.c
@@ -96,6 +96,8 @@ bar1_access(UNUSED void *pvt, UNUSED char * const buf, UNUSED size_t count,
UNUSED loff_t offset, UNUSED const bool is_write)
{
assert(false);
+
+ return -ENOTSUP;
}
bool irq_triggered = false;
@@ -207,6 +209,8 @@ 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)
@@ -264,7 +268,9 @@ migration_read_data(void *pvt, UNUSED void *buf, __u64 size,
{
struct server_data *server_data = pvt;
- assert(server_data->migration.data_size >= size);
+ if (server_data->migration.data_size < size) {
+ assert(false);
+ }
return 0;
}
@@ -273,6 +279,8 @@ static size_t
migration_write_data(UNUSED void *pvt, UNUSED void *data, UNUSED __u64 size)
{
assert(false);
+
+ return 0;
}
int main(int argc, char *argv[]){
@@ -283,7 +291,6 @@ int main(int argc, char *argv[]){
struct server_data server_data = {0};
int nr_sparse_areas = 2, size = 1024, i;
struct lm_sparse_mmap_areas *sparse_areas;
-
lm_ctx_t *lm_ctx;
while ((opt = getopt(argc, argv, "v")) != -1) {
@@ -310,7 +317,8 @@ int main(int argc, char *argv[]){
sparse_areas = calloc(1, sizeof(*sparse_areas) +
(nr_sparse_areas * sizeof(struct lm_mmap_area)));
if (sparse_areas == NULL) {
- err(EXIT_FAILURE, "MMAP sparse areas ENOMEM");
+ ret = -ENOMEM;
+ fprintf(stderr, "MMAP sparse areas ENOMEM\n");
goto out;
}
sparse_areas->nr_mmap_areas = nr_sparse_areas;
@@ -359,15 +367,16 @@ int main(int argc, char *argv[]){
sigemptyset(&act.sa_mask);
if (sigaction(SIGUSR1, &act, NULL) == -1) {
- err(EXIT_FAILURE, "failed to register signal handler");
+ fprintf(stderr, "failed to register signal handler\n");
+ ret = -EFAULT;
+ goto out;
}
lm_ctx = lm_ctx_create(&dev_info);
if (lm_ctx == NULL) {
- if (errno == EINTR) {
- goto out;
- }
- err(EXIT_FAILURE, "failed to initialize device emulation");
+ fprintf(stderr, "failed to initialize device emulation\n");
+ ret = -1;
+ goto out;
}
do {
@@ -394,8 +403,9 @@ int main(int argc, char *argv[]){
fprintf(stderr, "failed to realize device emulation: %s\n",
strerror(-ret));
}
-out:
lm_ctx_destroy(lm_ctx);
+
+out:
free(server_data.bar1);
free(sparse_areas);
return ret;
diff --git a/samples/test_dma_map.c b/samples/test_dma_map.c
deleted file mode 100644
index e797b57..0000000
--- a/samples/test_dma_map.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Userspace mediated device sample application
- *
- * Copyright (c) 2019, Nutanix Inc. All rights reserved.
- * Author: Thanos Makatos <thanos@nutanix.com>
- * Swapnil Ingle <swapnil.ingle@nutanix.com>
- * Felipe Franciosi <felipe@nutanix.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Nutanix nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <stdbool.h>
-#include <string.h>
-#include <linux/vfio.h>
-#include <limits.h>
-#include <assert.h>
-#include <sys/ioctl.h>
-#include <inttypes.h>
-#include <err.h>
-#include "../lib/muser_priv.h"
-
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array))
-
-#define VFIO_PATH "/dev/vfio/"
-#define VFIO_CTR_PATH VFIO_PATH "vfio"
-#define SYSFS_PCI_DEV_PATH "/sys/bus/pci/devices/"
-#define SYSFS_IOMMU_GROUP "/iommu_group"
-
-static int
-pci_group_id(const char *bdf)
-{
- char *dev_path;
- char group_path[PATH_MAX];
- int group_id;
-
- assert(bdf);
-
- asprintf(&dev_path, SYSFS_PCI_DEV_PATH "%s" SYSFS_IOMMU_GROUP, bdf);
- memset(group_path, 0, sizeof(group_path));
- readlink(dev_path, group_path, sizeof(group_path));
- free(dev_path);
- sscanf(basename(group_path), "%d", &group_id);
- return group_id;
-}
-
-static void*
-test_map_dma(const int fd, void *vaddr, unsigned long size, unsigned long iova)
-{
- int err;
- struct vfio_iommu_type1_dma_map dma_map = {
- .argsz = sizeof(dma_map),
- .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
- .vaddr = (unsigned long long)vaddr,
- .iova = iova,
- .size = size,
- };
- fprintf(stderr, "attempting to MAP_DMA IOVA=%llx\n", dma_map.iova);
-
- err = ioctl(fd, VFIO_IOMMU_MAP_DMA, &dma_map);
- if (err) {
- fprintf(stderr, "failed to MAP_DMA: %d (%s)\n", err,
- strerror(errno));
- return NULL;
- }
-
- return (void*)dma_map.vaddr;
-}
-
-static void
-test_unmap_dma(const int fd, unsigned long size, unsigned long long iova)
-{
- int err;
- struct vfio_iommu_type1_dma_unmap dma_unmap = {
- .argsz = sizeof dma_unmap,
- .size = size,
- .iova = iova,
- .flags = 0
- };
-
- err = ioctl(fd, VFIO_IOMMU_UNMAP_DMA, &dma_unmap);
- if (err) {
- perror("UNMAP_DMA\n");
- return;
- }
- printf("unmapped IOVA=%llx\n", dma_unmap.iova);
-}
-
-static int
-get_container_fd(const char *path)
-{
- int err, vfio_ctr_fd, vfio_grp_fd, vfio_dev_fd;
- char *grp_path;
-
- vfio_ctr_fd = open(VFIO_CTR_PATH, O_RDWR);
- assert(vfio_ctr_fd >= 0);
-
- // Open the VFIO entry for this device's IOMMU GROUP.
- err = asprintf(&grp_path, VFIO_PATH "%d", pci_group_id(path));
- assert(err > 0);
- vfio_grp_fd = open(grp_path, O_RDWR);
- assert(vfio_grp_fd >= 0);
- free(grp_path);
-
- // Add the group to the container.
- err = ioctl(vfio_grp_fd, VFIO_GROUP_SET_CONTAINER, &vfio_ctr_fd);
- assert(!err);
-
- // Enable IOMMU type 1 on container.
- err = ioctl(vfio_ctr_fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU);
- assert(!err);
-
- // Get a device fd from VFIO.
- vfio_dev_fd = ioctl(vfio_grp_fd, VFIO_GROUP_GET_DEVICE_FD, path);
- assert(vfio_dev_fd >= 0);
-
- return vfio_ctr_fd;
-}
-
-int main(int argc, char * argv[])
-{
- int vfio_ctr_fd;
- void *dma_map_addr;
- struct iovec dma_regions[] = {
- {.iov_base = (void*)0x0, .iov_len = 1 << 21},
- {.iov_base = (void*)(1 << 21), .iov_len = 1 << 21},
- };
- size_t i;
- bool huge = true;
- int fd;
- int flags = MAP_SHARED;
- void *vaddr;
- size_t size = 1 << 23; /* FIXME */
- int ret;
-
- if (argc != 2) {
- fprintf(stderr, "usage: %s <MUSER device UUID>\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- vfio_ctr_fd = get_container_fd(argv[1]);
-
- if (huge) {
- char template[] = "/dev/hugepages/XXXXXX";
- fd = mkstemp(template);
- assert(fd != -1);
- }
-
- ret = lseek(fd, size, SEEK_END);
- if (ret == -1) {
- err(EXIT_FAILURE, "failed to seek at %lu", size);
- }
-
- /*
- * Allocate some space and setup a DMA mapping.
- * It *must* be MAP_SHARED.
- */
- vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
- if (vaddr == MAP_FAILED) {
- err(EXIT_FAILURE, "failed to mmap");
- }
-
- for (i = 0; i < ARRAY_SIZE(dma_regions); i++) {
- if ((unsigned long long)dma_regions[i].iov_base + dma_regions[i].iov_len > size
- || (huge && (dma_regions[i].iov_len < (1 << 21)))) {
- err(EXIT_FAILURE, "bad IOVA %#lx-%#lx\n",
- (unsigned long)dma_regions[i].iov_base,
- (unsigned long)dma_regions[i].iov_base + dma_regions[i].iov_len);
- }
- dma_map_addr = test_map_dma(vfio_ctr_fd, vaddr,
- dma_regions[i].iov_len,
- (unsigned long)dma_regions[i].iov_base);
- if (!dma_map_addr)
- exit(EXIT_FAILURE);
- }
-
- printf("press enter to continue\n");
- getchar();
-
- for (i = 0; i < ARRAY_SIZE(dma_regions); i++) {
- test_unmap_dma(vfio_ctr_fd,
- (unsigned long long)dma_regions[i].iov_len,
- (unsigned long long)dma_regions[i].iov_base);
- }
- return 0;
-}
diff --git a/samples/test_mmap.c b/samples/test_mmap.c
deleted file mode 100644
index 02c32f1..0000000
--- a/samples/test_mmap.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Userspace mediated device sample application
- *
- * Copyright (c) 2019, Nutanix Inc. All rights reserved.
- * Author: Thanos Makatos <thanos@nutanix.com>
- * Swapnil Ingle <swapnil.ingle@nutanix.com>
- * Felipe Franciosi <felipe@nutanix.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Nutanix nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <stdbool.h>
-#include <string.h>
-#include <linux/vfio.h>
-#include <limits.h>
-#include <assert.h>
-#include <sys/ioctl.h>
-#include <inttypes.h>
-
-#define VFIO_PATH "/dev/vfio/"
-#define VFIO_CTR_PATH VFIO_PATH "vfio"
-#define SYSFS_PCI_DEV_PATH "/sys/bus/pci/devices/"
-#define SYSFS_IOMMU_GROUP "/iommu_group"
-
-static int
-pci_group_id(const char *bdf)
-{
- char *dev_path;
- char group_path[PATH_MAX];
- int group_id;
-
- assert(bdf);
-
- asprintf(&dev_path, SYSFS_PCI_DEV_PATH "%s" SYSFS_IOMMU_GROUP, bdf);
- memset(group_path, 0, sizeof(group_path));
- readlink(dev_path, group_path, sizeof(group_path));
- free(dev_path);
- sscanf(basename(group_path), "%d", &group_id);
- return group_id;
-}
-
-static inline void*
-test_map_dma(const int fd, const unsigned long size, const unsigned long iova)
-{
- int err;
- struct vfio_iommu_type1_dma_map dma_map = {
- .argsz = sizeof(dma_map),
- .size = size,
- .iova = iova,
- .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
- };
-
- /* Allocate some space and setup a DMA mapping */
- /* FIXME it *must* be MAP_SHARED */
- dma_map.vaddr = (unsigned long long)mmap(0, size, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_ANONYMOUS, 0, 0);
- if (dma_map.vaddr == (unsigned long)MAP_FAILED) {
- perror("failed to map DMA");
- return NULL;
- }
- printf("%llx\n", dma_map.vaddr);
- strcpy((char*)dma_map.vaddr, "foo");
-
- fprintf(stderr, "attempting to MAP_DMA IOVA=%llx\n", dma_map.iova);
-
- err = ioctl(fd, VFIO_IOMMU_MAP_DMA, &dma_map);
- if (err) {
- fprintf(stderr, "failed to MAP_DMA: %d (errno=%d)", err, errno);
- return NULL;
- }
- printf("[%s]\n", (char*)dma_map.vaddr);
-
- return (void*)dma_map.vaddr;
-}
-
-static inline void
-test_unmap_dma(const int fd, const unsigned long size, const unsigned long iova)
-{
- int err;
- struct vfio_iommu_type1_dma_unmap dma_unmap = {
- .argsz = sizeof dma_unmap,
- .size = size,
- .iova = iova,
- .flags = 0
- };
-
- err = ioctl(fd, VFIO_IOMMU_UNMAP_DMA, &dma_unmap);
- if (err) {
- perror("UNMAP_DMA\n");
- return;
- }
- printf("unmapped IOVA=%llx\n", dma_unmap.iova);
-}
-
-int main(int argc, char * argv[])
-{
- int err, vfio_ctr_fd, vfio_grp_fd, vfio_dev_fd;
- char *grp_path;
-#ifdef DEBUG
- struct vfio_group_status grp_status;
-#endif
- struct vfio_iommu_type1_info iommu_info;
- void *dma_map_addr = NULL;
-
- if (argc != 2) {
- printf("Usage: %s <device bdf in full>\n", argv[0]);
- printf(" ex: %s 0000:82:00.0\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- vfio_ctr_fd = open(VFIO_CTR_PATH, O_RDWR);
- assert(vfio_ctr_fd >= 0);
-
-#ifdef DEBUG
- err = ioctl(vfio_ctr_fd, VFIO_GET_API_VERSION);
- assert(err == VFIO_API_VERSION);
- err = ioctl(vfio_ctr_fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU);
- assert(err == 1);
-#endif
-
- // Open the VFIO entry for this device's IOMMU GROUP.
- err = asprintf(&grp_path, VFIO_PATH "%d", pci_group_id(argv[1]));
- assert(err > 0);
- vfio_grp_fd = open(grp_path, O_RDWR);
- assert(vfio_grp_fd >= 0);
- free(grp_path);
-
-#ifdef DEBUG
- // Ensure group is viable.
- memset(&grp_status, 0, sizeof(grp_status));
- grp_status.argsz = sizeof(grp_status);
- err = ioctl(vfio_grp_fd, VFIO_GROUP_GET_STATUS, &grp_status);
- assert(!err);
- assert((grp_status.flags & VFIO_GROUP_FLAGS_VIABLE) == 1);
-#endif
-
- // Add the group to the container.
- err = ioctl(vfio_grp_fd, VFIO_GROUP_SET_CONTAINER, &vfio_ctr_fd);
- assert(!err);
-
- // Enable IOMMU type 1 on container.
- err = ioctl(vfio_ctr_fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU);
- assert(!err);
-
- // Fetch IOMMU information from VFIO.
- memset(&iommu_info, 0, sizeof(iommu_info));
- iommu_info.argsz = sizeof(iommu_info);
- err = ioctl(vfio_ctr_fd, VFIO_IOMMU_GET_INFO, &iommu_info);
- assert(!err);
-
- // Get a device fd from VFIO.
- vfio_dev_fd = ioctl(vfio_grp_fd, VFIO_GROUP_GET_DEVICE_FD, argv[1]);
- assert(vfio_dev_fd >= 0);
-
- void *p;
- p = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE,
- MAP_SHARED, vfio_dev_fd, 0);
- assert(p != MAP_FAILED);
- printf("%p\n", p);
- printf("%s\n", (char*)p);
-
- dma_map_addr = test_map_dma(vfio_ctr_fd, 4096, 0xdeadbeef000);
- if (!dma_map_addr)
- exit(EXIT_FAILURE);
- test_unmap_dma(vfio_ctr_fd, 4096, 0xdeadbeef000);
-
- return 0;
-}
diff --git a/samples/test_read.c b/samples/test_read.c
deleted file mode 100644
index d8798c3..0000000
--- a/samples/test_read.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Userspace mediated device sample application
- *
- * Copyright (c) 2019, Nutanix Inc. All rights reserved.
- * Author: Thanos Makatos <thanos@nutanix.com>
- * Swapnil Ingle <swapnil.ingle@nutanix.com>
- * Felipe Franciosi <felipe@nutanix.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Nutanix nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <stdbool.h>
-#include <string.h>
-#include <linux/vfio.h>
-#include <limits.h>
-#include <assert.h>
-#include <sys/ioctl.h>
-#include <inttypes.h>
-
-#define VFIO_PATH "/dev/vfio/"
-#define VFIO_CTR_PATH VFIO_PATH "vfio"
-#define SYSFS_MUSER_DEV_PATH "/sys/class/muser/muser/"
-#define SYSFS_IOMMU_GROUP "/iommu_group"
-
-static int
-test_read(int vfio_dev_fd, off_t offset)
-{
- size_t bytes, i;
- char buf[256];
-
- memset(buf, 0, sizeof(buf));
- printf("* Reading %zd bytes at %#zx\n", sizeof(buf), offset);
- bytes = pread(vfio_dev_fd, buf, sizeof(buf), offset);
- printf("** bytes = %zd\n", bytes);
- assert(bytes == sizeof(buf));
- printf("** Read %zd bytes\n", bytes);
-
- for (i = 0; i < sizeof(buf); i++) {
- if (i % 16 == 0) {
- printf("%04lX:", i);
- }
- printf(" %02hhX", buf[i]);
- if (i % 16 == 15) {
- printf("\n");
- }
- }
- if (i % 16 != 0) {
- printf("\n");
- }
-
- return 0;
-}
-
-static int
-pci_group_id(const char *uuid)
-{
- char *dev_path;
- char group_path[PATH_MAX];
- int group_id;
-
- assert(uuid != NULL);
-
- asprintf(&dev_path, SYSFS_MUSER_DEV_PATH "%s" SYSFS_IOMMU_GROUP, uuid);
- memset(group_path, 0, sizeof(group_path));
- readlink(dev_path, group_path, sizeof(group_path));
- free(dev_path);
- sscanf(basename(group_path), "%d", &group_id);
- return group_id;
-}
-
-void print_sparse_mmap_info(struct vfio_region_info *reg)
-{
- struct vfio_region_info_cap_sparse_mmap *sparse;
-
- printf("argsz %u, cap_off %u\n", reg->argsz, reg->cap_offset);
- if (reg->cap_offset) {
- sparse = (struct vfio_region_info_cap_sparse_mmap *)
- ((void *)reg + reg->cap_offset);
- printf("cap_hdr: id %u version %u\n", sparse->header.id,
- sparse->header.version);
- printf("sparse: nr_areas %u, off 0x%llx size 0x%llx\n", sparse->nr_areas,
- sparse->areas[0].offset, sparse->areas[0].size);
- }
-}
-
-int
-main(int argc, char * argv[])
-{
- int vfio_ctr_fd, vfio_grp_fd, vfio_dev_fd;
- char *grp_path;
- size_t size = 0;
- int i;
- int err;
-
- if (argc != 2) {
- printf("Usage: %s <muser_dev_uuid>\n", argv[0]);
- return EXIT_FAILURE;
- }
-
- // Create a new VFIO container.
- printf("* Creating new VFIO container...\n");
- vfio_ctr_fd = open(VFIO_CTR_PATH, O_RDWR);
- assert(vfio_ctr_fd >= 0);
- printf("** vfio_ctr_fd = %d\n", vfio_ctr_fd);
-
- // Ensure kernel VFIO is compatible.
- printf("* Fetching VFIO API version...\n");
- err = ioctl(vfio_ctr_fd, VFIO_GET_API_VERSION);
- assert(err == VFIO_API_VERSION);
-
- // Ensure VFIO supports TYPE1 IOMMU.
- printf("* Checking for IOMMU TYPE1 extension in VFIO...\n");
- err = ioctl(vfio_ctr_fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU);
- assert(err == 1);
-
- // Open the VFIO entry for this device's IOMMU GROUP.
- err = asprintf(&grp_path, VFIO_PATH "%d", pci_group_id(argv[1]));
- assert(err > 0);
- printf("* Opening the VFIO group (%s)...\n", grp_path);
- vfio_grp_fd = open(grp_path, O_RDWR);
- assert(vfio_grp_fd >= 0);
- printf("** vfio_grp_fd = %d\n", vfio_grp_fd);
- free(grp_path);
-
- // Ensure group is viable.
- struct vfio_group_status grp_status;
- printf("* Ensuring all devices in this group are bound to VFIO...\n");
- memset(&grp_status, 0, sizeof(grp_status));
- grp_status.argsz = sizeof(grp_status);
- err = ioctl(vfio_grp_fd, VFIO_GROUP_GET_STATUS, &grp_status);
- assert(!err);
- assert((grp_status.flags & VFIO_GROUP_FLAGS_VIABLE) == 1);
-
- // Add the group to the container.
- printf("* Adding group to container...\n");
- err = ioctl(vfio_grp_fd, VFIO_GROUP_SET_CONTAINER, &vfio_ctr_fd);
- assert(!err);
-
- // Enable IOMMU type 1 on container.
- printf("* Setting IOMMU Type 1 on container...\n");
- err = ioctl(vfio_ctr_fd, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU);
- assert(!err);
-
- // Fetch IOMMU information from VFIO.
- struct vfio_iommu_type1_info iommu_info;
- printf("* Fetching IOMMU information...\n");
- memset(&iommu_info, 0, sizeof(iommu_info));
- iommu_info.argsz = sizeof(iommu_info);
- err = ioctl(vfio_ctr_fd, VFIO_IOMMU_GET_INFO, &iommu_info);
- assert(!err);
-
- // Get a device fd from VFIO.
- printf("* Getting a device (%s) fd from group...\n", argv[1]);
- vfio_dev_fd = ioctl(vfio_grp_fd, VFIO_GROUP_GET_DEVICE_FD, argv[1]);
- assert(vfio_dev_fd >= 0);
- printf("** vfio_dev_fd = %d\n", vfio_dev_fd);
-
- // Fetch device information.
- printf("* Fetching device information...\n");
- struct vfio_device_info dev_info;
- memset(&dev_info, 0, sizeof(dev_info));
- dev_info.argsz = sizeof(dev_info);
- err = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_INFO, &dev_info);
- assert(err == 0);
- assert(dev_info.num_regions <= VFIO_PCI_NUM_REGIONS);
-
- // Fetch region information for this device.
- struct vfio_region_info *reg_info[VFIO_PCI_NUM_REGIONS] = {0};
- struct vfio_region_info *reg;
- printf("* Fetching information for %u regions\n", dev_info.num_regions);
- for (i = 0; i < (int)dev_info.num_regions; i++) {
- size = sizeof(struct vfio_region_info);
- reg = calloc(1, size);
- assert(reg != NULL);
- reg->argsz = size;
- reg->index = i;
-retry:
- err = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_REGION_INFO, reg);
- if (err != 0) {
- // This region doesn't exist or isn't accessible.
- printf("** %d: Region info unavailable\n", i);
- memset(reg, 0, size);
- } else {
- printf("** %d: argsz=0x%X, flags=0x%X, index=0x%X, "
- "size=0x%llX, offset=0x%llX\n",
- i,
- reg->argsz,
- reg->flags,
- reg->index,
- reg->size,
- reg->offset);
- if (reg->argsz > size) {
- size = reg->argsz;
- reg = realloc(reg, reg->argsz);
- goto retry;
- }
- print_sparse_mmap_info(reg);
- }
- reg_info[i] = reg;
- }
-
- // Fetch irq information for this device.
- struct vfio_irq_info irq_info[VFIO_PCI_NUM_IRQS];
- printf("* Fetching information for %u irqs\n", dev_info.num_irqs);
- for (i = 0; i < (int)dev_info.num_irqs; i++) {
- memset(&irq_info[i], 0, sizeof(irq_info[i]));
- irq_info[i].argsz = sizeof(irq_info[i]);
- irq_info[i].index = i;
- err = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, irq_info[i]);
- if (err != 0) {
- // This irq doesn't exist or isn't accessible.
- printf("** %d: Irq info unavailable\n", i);
- memset(&irq_info[i], 0, sizeof(irq_info[i]));
- } else {
- printf("** %d: argsz=0x%X, flags=0x%X, index=0x%X, count=%u\n",
- i,
- irq_info[i].argsz,
- irq_info[i].flags,
- irq_info[i].index,
- irq_info[i].count);
- }
- }
-
- // Test.
- err = test_read(vfio_dev_fd, reg_info[VFIO_PCI_CONFIG_REGION_INDEX]->offset);
- assert(!err);
- for (i = 0; i < (int)dev_info.num_regions; i++) {
- free(reg_info[i]);
- }
-
- return 0;
-}