aboutsummaryrefslogtreecommitdiff
path: root/samples/client.c
diff options
context:
space:
mode:
authorSwapnil Ingle <swapnil.ingle@nutanix.com>2020-10-05 05:07:28 -0400
committerSwapnil Ingle <swapnil.ingle@nutanix.com>2020-10-05 05:49:34 -0400
commit1b72749f95bc02a93c45e91119957a3bf8ea2b5c (patch)
tree48a92b96b23f2836a18446f64df095fc00735365 /samples/client.c
parent8806aee7e8ef57618695a6f8f0611babc72afb69 (diff)
downloadlibvfio-user-1b72749f95bc02a93c45e91119957a3bf8ea2b5c.zip
libvfio-user-1b72749f95bc02a93c45e91119957a3bf8ea2b5c.tar.gz
libvfio-user-1b72749f95bc02a93c45e91119957a3bf8ea2b5c.tar.bz2
Add test for VFIO_USER_DMA_READ and VFIO_USER_DMA_WRITE
Signed-off-by: Swapnil Ingle <swapnil.ingle@nutanix.com>
Diffstat (limited to 'samples/client.c')
-rw-r--r--samples/client.c154
1 files changed, 140 insertions, 14 deletions
diff --git a/samples/client.c b/samples/client.c
index f916e4c..aad15f6 100644
--- a/samples/client.c
+++ b/samples/client.c
@@ -288,6 +288,126 @@ access_bar0(int sock)
return 0;
}
+static int handle_dma_write(int sock, struct vfio_user_dma_region *dma_regions,
+ int nr_dma_regions, int *dma_region_fds)
+{
+ struct vfio_user_dma_region_access dma_access;
+ struct vfio_user_header hdr;
+ int ret, size = sizeof(dma_access), i;
+ uint16_t msg_id;
+ void *data;
+
+ msg_id = 1;
+ ret = recv_vfio_user_msg(sock, &hdr, false, &msg_id, &dma_access, &size);
+ if (ret < 0) {
+ fprintf(stderr, "failed to recieve DMA read: %m\n");
+ return ret;
+ }
+
+ data = calloc(dma_access.count, 1);
+ if (data == NULL) {
+ return -ENOMEM;
+ }
+
+ ret = recv(sock, data, dma_access.count, 0);
+ if (ret < 0) {
+ fprintf(stderr, "failed to recieve DMA read data: %m\n");
+ goto out;
+ }
+
+ for (i = 0; i < nr_dma_regions; i++) {
+ if (dma_regions[i].addr == dma_access.addr) {
+ ret = pwrite(dma_region_fds[i], data, dma_access.count,
+ dma_regions[i].offset);
+ if (ret < 0) {
+ fprintf(stderr, "failed to write data at %#lu: %m\n",
+ dma_regions[i].offset);
+ goto out;
+ }
+ break;
+ }
+ }
+
+ dma_access.count = 0;
+ ret = send_vfio_user_msg(sock, msg_id, true, VFIO_USER_DMA_WRITE,
+ &dma_access, sizeof(dma_access), NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send reply of DMA write: %m\n");
+ }
+
+out:
+ free(data);
+ return ret;
+}
+
+static int handle_dma_read(int sock, struct vfio_user_dma_region *dma_regions,
+ int nr_dma_regions, int *dma_region_fds)
+{
+ struct vfio_user_dma_region_access dma_access, *response;
+ struct vfio_user_header hdr;
+ int ret, size = sizeof(dma_access), i, response_sz;
+ uint16_t msg_id;
+ void *data;
+
+ msg_id = 1;
+ ret = recv_vfio_user_msg(sock, &hdr, false, &msg_id, &dma_access, &size);
+ if (ret < 0) {
+ fprintf(stderr, "failed to recieve DMA read: %m\n");
+ return ret;
+ }
+
+ response_sz = sizeof(dma_access) + dma_access.count;
+ response = calloc(response_sz, 1);
+ if (response == NULL) {
+ return -ENOMEM;
+ }
+ response->count = dma_access.count;
+ data = (char *)response->data;
+
+ for (i = 0; i < nr_dma_regions; i++) {
+ if (dma_regions[i].addr == dma_access.addr) {
+ ret = pread(dma_region_fds[i], data, dma_access.count,
+ dma_regions[i].offset);
+ if (ret < 0) {
+ fprintf(stderr, "failed to write data at %#lu: %m\n",
+ dma_regions[i].offset);
+ goto out;
+ }
+ break;
+ }
+ }
+
+ ret = send_vfio_user_msg(sock, msg_id, true, VFIO_USER_DMA_READ,
+ response, response_sz, NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr, "failed to send reply of DMA write: %m\n");
+ }
+
+out:
+ free(response);
+ return ret;
+}
+
+static int handle_dma_io(int sock, struct vfio_user_dma_region *dma_regions,
+ int nr_dma_regions, int *dma_region_fds)
+{
+ int ret;
+
+ ret = handle_dma_write(sock, dma_regions, nr_dma_regions, dma_region_fds);
+ if (ret < 0) {
+ fprintf(stderr, "failed to handle DMA write data: %m\n");
+ return ret;
+ }
+
+ ret = handle_dma_read(sock, dma_regions, nr_dma_regions, dma_region_fds);
+ if (ret < 0) {
+ fprintf(stderr, "failed to handle DMA read data: %m\n");
+ return ret;
+ }
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
int ret, sock;
@@ -375,20 +495,6 @@ int main(int argc, char *argv[])
}
/*
- * XXX VFIO_USER_DMA_UNMAP
- *
- * unmap the first group of the DMA regions
- */
- ret = send_recv_vfio_user_msg(sock, msg_id, VFIO_USER_DMA_UNMAP,
- dma_regions,
- sizeof *dma_regions * server_max_fds,
- NULL, 0, NULL, NULL, 0);
- if (ret < 0) {
- fprintf(stderr, "failed to unmap DMA regions: %s\n", strerror(-ret));
- return ret;
- }
-
- /*
* XXX VFIO_USER_DEVICE_GET_IRQ_INFO and VFIO_IRQ_SET_ACTION_TRIGGER
* Query interrupts, configure an eventfd to be associated with INTx, and
* finally wait for the server to fire the interrupt.
@@ -399,6 +505,12 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ ret = handle_dma_io(sock, dma_regions, nr_dma_regions, dma_region_fds);
+ if (ret < 0) {
+ fprintf(stderr, "DMA IO failed: %s\n", strerror(-ret));
+ exit(EXIT_FAILURE);
+ }
+
/*
* XXX VFIO_USER_REGION_READ and VFIO_USER_REGION_WRITE
*
@@ -420,6 +532,20 @@ int main(int argc, char *argv[])
/* BAR1 can be memory mapped and read directly */
/* TODO implement the following: write a value in BAR1, a server timer will increase it every second (SIGALARM) */
+ /*
+ * XXX VFIO_USER_DMA_UNMAP
+ *
+ * unmap the first group of the DMA regions
+ */
+ ret = send_recv_vfio_user_msg(sock, msg_id, VFIO_USER_DMA_UNMAP,
+ dma_regions,
+ sizeof *dma_regions * server_max_fds,
+ NULL, 0, NULL, NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr, "failed to unmap DMA regions: %s\n", strerror(-ret));
+ return ret;
+ }
+
return 0;
}