diff options
author | Ilias Apalodimas <ilias.apalodimas@linaro.org> | 2017-10-21 12:32:12 +0300 |
---|---|---|
committer | Ilias Apalodimas <ilias.apalodimas@linaro.org> | 2017-10-21 12:32:12 +0300 |
commit | 8fa2b0f05b242dae1d55dd22ec6be6c1c218ee1b (patch) | |
tree | e994522ff4164172a8e0e7c1246faff578dad6d0 | |
parent | 4409ebbef747904edd37a246aa8005c52cecdc02 (diff) |
Inital codes to support vfio types parsing
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
-rw-r--r-- | api/vfio_api.c | 65 | ||||
-rw-r--r-- | include/common.h | 10 | ||||
-rw-r--r-- | src/userspace_io.c | 8 |
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; |