aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlias Apalodimas <ilias.apalodimas@linaro.org>2017-10-21 12:32:12 +0300
committerIlias Apalodimas <ilias.apalodimas@linaro.org>2017-10-21 12:32:12 +0300
commit8fa2b0f05b242dae1d55dd22ec6be6c1c218ee1b (patch)
treee994522ff4164172a8e0e7c1246faff578dad6d0
parent4409ebbef747904edd37a246aa8005c52cecdc02 (diff)
Inital codes to support vfio types parsing
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
-rw-r--r--api/vfio_api.c65
-rw-r--r--include/common.h10
-rw-r--r--src/userspace_io.c8
3 files changed, 80 insertions, 3 deletions
diff --git a/api/vfio_api.c b/api/vfio_api.c
index 4c1270b..c24b660 100644
--- a/api/vfio_api.c
+++ b/api/vfio_api.c
@@ -7,6 +7,11 @@
#include <stdio.h>
#include <stdint.h>
#include <linux/vfio.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <common.h>
+#include <uapi/net_mdev.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static const char *vfio_fail_str[] = {
@@ -20,6 +25,14 @@ static const char *vfio_fail_str[] = {
[VFIO_DEVICE_GET_REGION_INFO] = "Failed to get PCI region info",
};
+static const struct cap_to_type_subtype {
+ __u32 type;
+ __u32 subtype;
+} tmatch[] = {
+ [VFIO_NET_MDEV_RX_REGION_INDEX] = { VFIO_NET_DESCRIPTORS, VFIO_NET_MDEV_RX },
+ [VFIO_NET_MDEV_TX_REGION_INDEX] = { VFIO_NET_DESCRIPTORS, VFIO_NET_MDEV_TX },
+};
+
static void vfio_print_fail(int reason)
{
if (reason > ARRAY_SIZE(vfio_fail_str))
@@ -154,6 +167,34 @@ int dma_unmap_type1(int fd, unsigned long sz, void *vaddr, uint64_t iova)
return ret;
}
+static int vfio_match_caps(struct vfio_info_cap_header *hdr, __u32 type,
+ __u32 subtype)
+{
+ struct vfio_region_info_cap_type *cap_type;
+
+ cap_type = container_of(hdr, struct vfio_region_info_cap_type, header);
+
+ return !(cap_type->type == type && cap_type->subtype == subtype);
+}
+
+static struct vfio_info_cap_header *vfio_get_region_info_cap(struct vfio_region_info *info,
+ __u16 id)
+{
+ struct vfio_info_cap_header *hdr;
+ void *ptr = info;
+
+ if (!(info->flags & VFIO_REGION_INFO_FLAG_CAPS))
+ return NULL;
+
+ for (hdr = ptr + info->cap_offset; hdr != ptr; hdr = ptr + hdr->next) {
+ if (hdr->id == id) {
+ return hdr;
+ }
+ }
+
+ return NULL;
+}
+
/**
* Get specific region info
*/
@@ -161,9 +202,13 @@ int vfio_get_region(int device, struct vfio_region_info *region_info,
__u32 region)
{
int ret;
+ struct vfio_info_cap_header *caps = NULL;
+ struct vfio_region_info *info;
+ int extra_region;
/* Test and setup the device */
region_info->index = region;
+ extra_region = region - VFIO_PCI_NUM_REGIONS;
ret = ioctl(device, VFIO_DEVICE_GET_REGION_INFO, region_info);
printf("Region:%d ", region);
@@ -177,6 +222,23 @@ int vfio_get_region(int device, struct vfio_region_info *region_info,
ret = -EINVAL;
}
+ if (region_info->flags & VFIO_REGION_INFO_FLAG_CAPS &&
+ region_info->argsz > sizeof(*region_info)) {
+ info = calloc(1, region_info->argsz);
+ if (!info)
+ return -EINVAL;
+ memcpy(info, region_info, region_info->argsz);
+ ret = ioctl(device, VFIO_DEVICE_GET_REGION_INFO, info);
+ caps = vfio_get_region_info_cap(info, VFIO_REGION_INFO_CAP_TYPE);
+ if (!caps)
+ return -EINVAL;
+ free(info);
+ info = NULL;
+ }
+ if (caps)
+ ret = vfio_match_caps(caps, tmatch[extra_region].type,
+ tmatch[extra_region].subtype);
+
return ret;
}
@@ -193,6 +255,7 @@ void *vfio_mmap_region(int device, __u32 region)
/* api returns -EINVAL for unimplemented bars */
if (!region_info.size || ret)
return NULL;
+
printf("region:%d size %lu, offset 0x%lx, flags 0x%x\n", region,
(unsigned long)region_info.size,
(unsigned long)region_info.offset, region_info.flags);
@@ -200,7 +263,7 @@ void *vfio_mmap_region(int device, __u32 region)
return NULL;
mapped = mmap(NULL, region_info.size, PROT_READ | PROT_WRITE,
- MAP_SHARED, device, region_info.offset);
+ MAP_SHARED, device, region_info.offset);
if (mapped == MAP_FAILED) {
printf("mmap failed\n");
return NULL;
diff --git a/include/common.h b/include/common.h
index 38570d7..2d8da1d 100644
--- a/include/common.h
+++ b/include/common.h
@@ -2,6 +2,16 @@
#define _COMMON_H
#define OPT_DEV (1 << 0)
#define OPT_UUID (1 << 1)
+#include <drivers/driver_ops.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define container_of(ptr, type, member) \
+({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member)); \
+})
+
static inline int uio_quirks(const struct driver_ops *e)
{
diff --git a/src/userspace_io.c b/src/userspace_io.c
index 4677409..41dbbd7 100644
--- a/src/userspace_io.c
+++ b/src/userspace_io.c
@@ -21,6 +21,8 @@
#include <mm_api.h>
#include <common.h>
+#include <uapi/net_mdev.h>
+
/* FIXME modularize driver load */
extern const struct driver_ops r8169_ops;
extern const struct driver_ops e1000e_ops;
@@ -138,12 +140,14 @@ int main(int argc, char *argv[])
goto out;
}
/* XXX FIXME check pointers and munmap properly */
- rxring = vfio_mmap_region(device, VFIO_PCI_NUM_REGIONS + 2);
+ rxring = vfio_mmap_region(device, VFIO_PCI_NUM_REGIONS +
+ VFIO_NET_MDEV_RX_REGION_INDEX);
if (!rxring) {
printf("Cannot map RxRing\n");
goto out;
}
- txring = vfio_mmap_region(device, VFIO_PCI_NUM_REGIONS + 3);
+ txring = vfio_mmap_region(device, VFIO_PCI_NUM_REGIONS +
+ VFIO_NET_MDEV_TX_REGION_INDEX);
if (!txring) {
printf("Cannot map TxRing\n");
goto out;