LINUX.ORG.RU

История изменений

Исправление dimon555, (текущая версия) :

#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h> /* strcat */
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h> /* exit */
#include <unistd.h> /* getopt */
#include <inttypes.h>
#include <stdbool.h>
#include <linux/vfio.h>

int 
main(int argc, char *argv[])
{
    int opt;
    char group_file[255] = "/dev/vfio/";
    char dev_bdf[255];
    int container, group, device, rc;

    struct vfio_group_status group_status = {
        .argsz = sizeof(group_status) };

    typedef struct {
        struct vfio_pci_hot_reset hotr;
        __s32 group_fd;
    } __attribute__((packed)) vfio_rst_data;

    vfio_rst_data hot_rst;

    while((opt = getopt(argc, argv, "g:s:")) != -1) {
        switch(opt) {
            case 'g':
                strcat(group_file, optarg);
                printf("group dev: %s\n", group_file);
                break;
            case 's':
                strcpy(dev_bdf, optarg);
                printf("device bdf: %s\n", dev_bdf);
                break;
            default:
                fprintf(stderr, "Unknown option: %s\n", optarg);
                exit(EXIT_FAILURE);
        }
    }

    /* Open new container*/
    container = open("/dev/vfio/vfio", O_RDWR);

    rc = ioctl(container, VFIO_GET_API_VERSION);
    printf("VFIO_GET_API_VERSION returned 0x%x, VFIO_API_VERSION = %d\n",
           rc, VFIO_API_VERSION);

    rc = ioctl(container, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU);
    printf("VFIO_CHECK_EXTENSION returned 0x%x, VFIO_TYPE1_IOMMU = %d\n",
           rc, VFIO_TYPE1_IOMMU);

    /* Open group */
    group = open(group_file, O_RDWR);

    /* Test group */
    ioctl(group, VFIO_GROUP_GET_STATUS, &group_status);
    printf("iommu_group %s status: argsz=0x%x, flags=0x%x\n",
           group_file, group_status.argsz, group_status.flags);

    /* Add group to the container */
    ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);

    /* Enable IOMMU */
    ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);

    /* Get a file descriptor for the device */
    device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, dev_bdf);

    hot_rst.hotr.argsz = sizeof(vfio_rst_data);
    hot_rst.hotr.flags = 0;
    hot_rst.hotr.count = 1;
    hot_rst.group_fd = group;
    /* Bus hot reset */
    ioctl(device, VFIO_DEVICE_PCI_HOT_RESET, &hot_rst);
    
    /* reset device */
    printf("Device reset.\n");
    ioctl(device, VFIO_DEVICE_RESET);

    printf("IOMMU group unset container.\n");
    ioctl(group, VFIO_GROUP_UNSET_CONTAINER, &container);

    close(group);
    close(container);
    return 0;
}

потом нужно
gcc text.c -o vfio_reset
$ readlink /sys/bus/pci/devices/0000:01:00.0/iommu_group
(тут узнается число iommu group)

и потом
sudo ./vfio_reset -g 8 -s 0000:01:00.0

где 8 то самое число

этот конечный вариант не тестировал
от старого варианта остались всякие левые инклуды

главное это VFIO_DEVICE_PCI_HOT_RESET
проверь vfio.h на системе, чтобы он был
p.s. нужно ещё забайндить девайсы на vfio-pci драйвер

Исходная версия dimon555, :

#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h> /* strcat */
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h> /* exit */
#include <unistd.h> /* getopt */
#include <inttypes.h>
#include <stdbool.h>
#include <linux/vfio.h>

int 
main(int argc, char *argv[])
{
    int opt;
    char group_file[255] = "/dev/vfio/";
    char dev_bdf[255];
    int container, group, device, rc;

    struct vfio_group_status group_status = {
        .argsz = sizeof(group_status) };

    typedef struct {
        struct vfio_pci_hot_reset hotr;
        __s32 group_fd;
    } __attribute__((packed)) vfio_rst_data;

    vfio_rst_data hot_rst;

    while((opt = getopt(argc, argv, "g:s:")) != -1) {
        switch(opt) {
            case 'g':
                strcat(group_file, optarg);
                printf("group dev: %s\n", group_file);
                break;
            case 's':
                strcpy(dev_bdf, optarg);
                printf("device bdf: %s\n", dev_bdf);
                break;
            default:
                fprintf(stderr, "Unknown option: %s\n", optarg);
                exit(EXIT_FAILURE);
        }
    }

    /* Open new container*/
    container = open("/dev/vfio/vfio", O_RDWR);

    rc = ioctl(container, VFIO_GET_API_VERSION);
    printf("VFIO_GET_API_VERSION returned 0x%x, VFIO_API_VERSION = %d\n",
           rc, VFIO_API_VERSION);

    rc = ioctl(container, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU);
    printf("VFIO_CHECK_EXTENSION returned 0x%x, VFIO_TYPE1_IOMMU = %d\n",
           rc, VFIO_TYPE1_IOMMU);

    /* Open group */
    group = open(group_file, O_RDWR);

    /* Test group */
    ioctl(group, VFIO_GROUP_GET_STATUS, &group_status);
    printf("iommu_group %s status: argsz=0x%x, flags=0x%x\n",
           group_file, group_status.argsz, group_status.flags);

    /* Add group to the container */
    ioctl(group, VFIO_GROUP_SET_CONTAINER, &container);

    /* Enable IOMMU */
    ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU);

    /* Get a file descriptor for the device */
    device = ioctl(group, VFIO_GROUP_GET_DEVICE_FD, dev_bdf);

    hot_rst.hotr.argsz = sizeof(vfio_rst_data);
    hot_rst.hotr.flags = 0;
    hot_rst.hotr.count = 1;
    hot_rst.group_fd = group;
    /* Bus hot reset */
    ioctl(device, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, &hot_rst);
    
    /* reset device */
    printf("Device reset.\n");
    ioctl(device, VFIO_DEVICE_RESET);

    printf("IOMMU group unset container.\n");
    ioctl(group, VFIO_GROUP_UNSET_CONTAINER, &container);

    close(group);
    close(container);
    return 0;
}

потом нужно
gcc text.c -o vfio_reset
$ readlink /sys/bus/pci/devices/0000:01:00.0/iommu_group
(тут узнается число iommu group)

и потом
sudo ./vfio_reset -g 8 -s 0000:01:00.0

где 8 то самое число

этот конечный вариант не тестировал
от старого варианта остались всякие левые инклуды

главное это VFIO_DEVICE_PCI_HOT_RESET
проверь vfio.h на системе, чтобы он был
p.s. нужно ещё забайндить девайсы на vfio-pci драйвер