aboutsummaryrefslogtreecommitdiff
path: root/samples
diff options
context:
space:
mode:
authorThanos Makatos <thanos.makatos@nutanix.com>2020-09-29 11:35:29 -0400
committerThanos Makatos <thanos.makatos@nutanix.com>2020-09-29 11:35:29 -0400
commit2ea402b215f89a29a8e5163749456588856cf9c9 (patch)
treef91a035f0f8c357e308a38533883576c171fc9db /samples
parent2ac55250a44832bd9e0b585e62e1e4217dda71be (diff)
downloadlibvfio-user-2ea402b215f89a29a8e5163749456588856cf9c9.zip
libvfio-user-2ea402b215f89a29a8e5163749456588856cf9c9.tar.gz
libvfio-user-2ea402b215f89a29a8e5163749456588856cf9c9.tar.bz2
implement VFIO_USER_REGION_READ/VFIO_USER_REGION_WRITE
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'samples')
-rw-r--r--samples/client.c71
-rw-r--r--samples/server.c53
2 files changed, 103 insertions, 21 deletions
diff --git a/samples/client.c b/samples/client.c
index 91ab102..1a336373 100644
--- a/samples/client.c
+++ b/samples/client.c
@@ -36,6 +36,8 @@
#include <errno.h>
#include <sys/mman.h>
#include <sys/eventfd.h>
+#include <time.h>
+#include <err.h>
#include "../lib/muser.h"
#include "../lib/muser_priv.h"
@@ -189,6 +191,46 @@ configure_irqs(int sock)
return 0;
}
+static int
+access_bar0(int sock)
+{
+ struct {
+ struct vfio_user_region_access region_access;
+ time_t t;
+ } __attribute__((packed)) data = {
+ .region_access = {
+ .region = LM_DEV_BAR0_REG_IDX,
+ .count = sizeof(data.t)
+ },
+ .t = time(NULL)
+ };
+ uint16_t msg_id = 1;
+ int ret = send_recv_vfio_user_msg(sock, msg_id, VFIO_USER_REGION_WRITE,
+ &data, sizeof data, NULL, 0, NULL, NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr, "failed to write to BAR0: %s\n", strerror(-ret));
+ return ret;
+ }
+
+ printf("wrote to BAR0: %ld\n", data.t);
+
+ sleep(2);
+
+ msg_id++;
+
+ ret = send_recv_vfio_user_msg(sock, msg_id, VFIO_USER_REGION_READ,
+ &data.region_access, sizeof data.region_access,
+ NULL, 0, NULL, &data.t, sizeof data.t);
+ if (ret < 0) {
+ fprintf(stderr, "failed to read from BAR0: %s\n", strerror(-ret));
+ return ret;
+ }
+
+ printf("read from BAR0: %ld\n", data.t);
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
int ret, sock;
@@ -205,7 +247,7 @@ int main(int argc, char *argv[])
if (argc != 2) {
fprintf(stderr, "usage: %s /path/to/socket\n", argv[0]);
- return -1;
+ exit(EXIT_FAILURE);
}
if ((sock = init_sock(argv[1])) < 0) {
@@ -238,13 +280,11 @@ int main(int argc, char *argv[])
nr_dma_regions = server_max_fds << 1;
if ((fp = tmpfile()) == NULL) {
- perror("failed to create DMA file");
- return -1;
+ err(EXIT_FAILURE, "failed to create DMA file");
}
if ((ret = ftruncate(fileno(fp), nr_dma_regions * sysconf(_SC_PAGESIZE))) == -1) {
- perror("failed to truncate file");
- return -1;
+ err(EXIT_FAILURE,"failed to truncate file");
}
dma_regions = alloca(sizeof *dma_regions * nr_dma_regions);
@@ -296,6 +336,27 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ /*
+ * XXX VFIO_USER_REGION_READ and VFIO_USER_REGION_WRITE
+ *
+ * BAR0 in the server does not support memory mapping so it must be accessed
+ * via explicit messages.
+ */
+ ret = access_bar0(sock);
+ if (ret < 0) {
+ fprintf(stderr, "failed to access BAR0: %s\n", strerror(-ret));
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * FIXME now that region read/write works, change the server implementation
+ * to trigger an interrupt after N seconds, where N is the value written to
+ * BAR0 by the client.
+ */
+
+ /* 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) */
+
return 0;
}
diff --git a/samples/server.c b/samples/server.c
index 6ebb65d..deb986b 100644
--- a/samples/server.c
+++ b/samples/server.c
@@ -41,6 +41,11 @@
#include "../lib/muser.h"
+struct server_data {
+ time_t bar0;
+ uint8_t *bar1;
+};
+
static void
_log(void *pvt, lm_log_lvl_t lvl __attribute__((unused)), char const *msg)
{
@@ -52,29 +57,35 @@ ssize_t
bar0_access(void *pvt, char * const buf, size_t count, loff_t offset,
const bool is_write)
{
- time_t t = time(NULL);
+ struct server_data *server_data = pvt;
if (count != sizeof(time_t) || offset != 0) {
errno = EINVAL;
return -1;
}
- memcpy(buf, &t, count);
+ if (is_write) {
+ memcpy(&server_data->bar0, buf, count);
+ } else {
+ time_t delta = time(NULL) - server_data->bar0;
+ memcpy(buf, &delta, count);
+ }
return count;
}
-lm_ctx_t *lm_ctx;
+ssize_t
+bar1_access(void *pvt, char * const buf, size_t count, loff_t offset,
+ const bool is_write)
+{
+ assert(false);
+}
bool irq_triggered = false;
static void _sa_handler(int signum)
{
int _errno = errno;
if (signum == SIGUSR1) {
- /*
- * FIXME not async-signal-safe becasue lm_irq_trigger prints to the log
- */
- lm_irq_trigger(lm_ctx, 0);
irq_triggered = true;
}
errno = _errno;
@@ -92,7 +103,8 @@ int main(int argc, char *argv[])
bool trans_sock = false, verbose = false;
char opt;
struct sigaction act = {.sa_handler = _sa_handler};
- lm_ctx_t **_lm_ctx;
+ struct server_data server_data;
+ lm_ctx_t *lm_ctx;
while ((opt = getopt(argc, argv, "v")) != -1) {
switch (opt) {
@@ -100,8 +112,7 @@ int main(int argc, char *argv[])
verbose = true;
break;
default: /* '?' */
- fprintf(stderr, "Usage: %s [-d] <IOMMU group>\n", argv[0]);
- exit(EXIT_FAILURE);
+ err(EXIT_FAILURE, "Usage: %s [-d] <IOMMU group>\n", argv[0]);
}
}
@@ -109,6 +120,11 @@ int main(int argc, char *argv[])
err(EXIT_FAILURE, "missing MUSER device UUID");
}
+ server_data.bar1 = malloc(sysconf(_SC_PAGESIZE));
+ if (server_data.bar1 == NULL) {
+ err(EXIT_FAILURE, "BAR1");
+ }
+
lm_dev_info_t dev_info = {
.trans = LM_TRANS_SOCK,
.log = verbose ? _log : NULL,
@@ -119,16 +135,21 @@ int main(int argc, char *argv[])
.size = sizeof(time_t),
.fn = &bar0_access
},
+ .reg_info[LM_DEV_BAR1_REG_IDX] = {
+ .flags = LM_REG_FLAG_RW,
+ .size = sysconf(_SC_PAGESIZE),
+ .fn = &bar1_access
+ },
.irq_count[LM_DEV_INTX_IRQ_IDX] = 1,
},
.uuid = argv[optind],
.unmap_dma = unmap_dma,
- .pvt = &_lm_ctx
+ .pvt = &server_data
};
sigemptyset(&act.sa_mask);
if (sigaction(SIGUSR1, &act, NULL) == -1) {
- fprintf(stderr, "warning: failed to register signal handler: %m\n");
+ err(EXIT_FAILURE, "warning: failed to register signal handler: %m\n");
}
lm_ctx = lm_ctx_create(&dev_info);
@@ -136,16 +157,16 @@ int main(int argc, char *argv[])
if (errno == EINTR) {
goto out;
}
- fprintf(stderr, "failed to initialize device emulation: %m\n");
- return -1;
+ err(EXIT_FAILURE, "failed to initialize device emulation: %m\n");
}
- _lm_ctx = &lm_ctx;
+
do {
ret = lm_ctx_drive(lm_ctx);
if (ret == -EINTR) {
if (irq_triggered) {
- ret = 0;
irq_triggered = false;
+ lm_irq_trigger(lm_ctx, 0);
+ ret = 0;
}
}
} while (ret == 0);