• vfio-iommu-map-unmap


    https://github.com/awilliam/tests/blob/master/vfio-iommu-map-unmap.c

    #include <errno.h>
    #include <libgen.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    #include <linux/ioctl.h>
    #include <linux/vfio.h>
    
    #define MAP_SIZE (1UL * 1024 * 1024 * 1024)
    #define MAP_CHUNK (4 * 1024)
    #define REALLOC_INTERVAL 30
    
    void usage(char *name)
    {
        printf("usage: %s ssss:bb:dd.f
    ", name);
        printf("	ssss: PCI segment, ex. 0000
    ");
        printf("	bb:   PCI bus, ex. 01
    ");
        printf("	dd:   PCI device, ex. 06
    ");
        printf("	f:    PCI function, ex. 0
    ");
    }
    
    int main(int argc, char **argv)
    {
        int seg, bus, slot, func;
        int ret, container, group, groupid;
        char path[50], iommu_group_path[50], *group_name;
        struct stat st;
        ssize_t len;
        unsigned long i, count;
        void *vaddr;
        void **maps;
        struct vfio_group_status group_status = {
            .argsz = sizeof(group_status)
        };
        struct vfio_iommu_type1_dma_map dma_map = {
            .argsz = sizeof(dma_map)
        };
        struct vfio_iommu_type1_dma_unmap dma_unmap = {
            .argsz = sizeof(dma_unmap)
        };
    
        if (argc != 2) {
            usage(argv[0]);
            return -1;
        }
    
        /* Boilerplate vfio setup */
        ret = sscanf(argv[1], "%04x:%02x:%02x.%d", &seg, &bus, &slot, &func);
        if (ret != 4) {
            usage(argv[0]);
            return -1;
        }
    
        container = open("/dev/vfio/vfio", O_RDWR);
        if (container < 0) {
            printf("Failed to open /dev/vfio/vfio, %d (%s)
    ",
                   container, strerror(errno));
            return container;
        }
    
        snprintf(path, sizeof(path),
             "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/",
             seg, bus, slot, func);
    
        ret = stat(path, &st);
        if (ret < 0) {
            printf("No such device
    ");
            return  ret;
        }
    
        strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1);
    
        len = readlink(path, iommu_group_path, sizeof(iommu_group_path));
        if (len <= 0) {
            printf("No iommu_group for device
    ");
            return -1;
        }
    
        iommu_group_path[len] = 0;
        group_name = basename(iommu_group_path);
    
        if (sscanf(group_name, "%d", &groupid) != 1) {
            printf("Unknown group
    ");
            return -1;
        }
    
        snprintf(path, sizeof(path), "/dev/vfio/%d", groupid);
        group = open(path, O_RDWR);
        if (group < 0) {
            printf("Failed to open %s, %d (%s)
    ",
                   path, group, strerror(errno));
            return group;
        }
    
        ret = ioctl(group, VFIO_GROUP_GET_STATUS, &group_status);
        if (ret) {
            printf("ioctl(VFIO_GROUP_GET_STATUS) failed
    ");
            return ret;
        }
    
        if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) {
            printf("Group not viable, are all devices attached to vfio?
    ");
            return -1;
        }
    
        ret = ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);
        if (ret) {
            printf("Failed to set group container
    ");
            return ret;
        }
    
        ret = ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);
        if (ret) {
            printf("Failed to set IOMMU
    ");
            return ret;
        }
    
        /* Test code */
        dma_map.flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE;
        dma_map.size = MAP_CHUNK;
        dma_unmap.size = MAP_SIZE;
        dma_unmap.iova = 0;
    
        /* Track our mmaps for re-use */
        maps = malloc(sizeof(void *) * (MAP_SIZE/dma_map.size));
        if (!maps) {
            printf("Failed to allocate map (%s)
    ", strerror(errno));
            return -1;
        }
    
        memset(maps, 0, sizeof(void *) * (MAP_SIZE/dma_map.size));
    
        for (count = 0;; count++) {
    
            /* Every REALLOC_INTERVAL, dump our mappings to give THP something to collapse */
            if (count % REALLOC_INTERVAL == 0) {
                for (i = 0; i < MAP_SIZE/dma_map.size; i++) {
                    if (maps[i]) {
                        munmap(maps[i], dma_map.size);
                        maps[i] = NULL;
                    }
                }
                if (count) {
                    printf("	%ld
    ", count);
                    //return 0;
                }
                printf("|");
                fflush(stdout);
            }
    
            /* Map MAP_CHUNK at a time, each chunk is pinned on map, so THP can't do anything until unmap */
            for (i = dma_map.iova = 0; i < MAP_SIZE/dma_map.size; i++, dma_map.iova += dma_map.size) {
                if (!maps[i]) {
                    maps[i] = mmap(NULL, dma_map.size,
                            PROT_READ | PROT_WRITE,
                            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
                    if (maps[i] == MAP_FAILED) {
                        printf("Failed to mmap memory (%s)
    ", strerror(errno));
                        return -1;
                    }
                }
    
                ret = madvise(maps[i], dma_map.size, MADV_HUGEPAGE);
                if (ret) {
                    printf("Madvise failed (%s)
    ", strerror(errno));
                }
    
                dma_map.vaddr = (unsigned long)maps[i];
    
                ret = ioctl(container, VFIO_IOMMU_MAP_DMA, &dma_map);
                if (ret) {
                    printf("Failed to map memory (%s)
    ",
                        strerror(errno));
                    return ret;
                }
            }
    
            printf("+");
            fflush(stdout);
    
            /* Unmap everything at once */
            ret = ioctl(container, VFIO_IOMMU_UNMAP_DMA, &dma_unmap);
            if (ret) {
                printf("Failed to unmap memory (%s)
    ", strerror(errno));
                return ret;
            }
    
            printf("-");
            fflush(stdout);
        }
    
        return 0;
    }
  • 相关阅读:
    python 协程
    数据库中的一对多,多对多实例
    source命令
    HTTP 协议报文解析
    html中的body和head有什么区别??
    xml json
    内置函数bytes()
    MySQL中的日期和时间函数
    MySQL中的数值函数
    MySQL中的字符串函数
  • 原文地址:https://www.cnblogs.com/dream397/p/13832356.html
Copyright © 2020-2023  润新知