dpdk源码---vfio(zym)

news/2024/11/28 23:37:51/

主要想找到从nvme设备 到 vfio驱动的代码路径

[spdk/lib/nvme/nvme_pcie.c]

nvme_pcie_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,bool direct_connect) (nvme_tcp,nvme_rdma等都有自己的scan,probe等函数,统一被封装起来,如下)

1 int nvme_transport_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,
2      bool direct_connect)
3 {
4  NVME_TRANSPORT_CALL(probe_ctx->trid.trtype, ctrlr_scan, (probe_ctx, direct_connect));
5 }

1.nvme_pcie_ctrl_scan:

 1 int2 nvme_pcie_ctrlr_scan(struct spdk_nvme_probe_ctx *probe_ctx,3              bool direct_connect)4 {5     .......//若probe_ctx中有指定nvme pci id,has_pci_addr=true6     if (enum_ctx.has_pci_addr == false) {7         return spdk_pci_enumerate(spdk_pci_nvme_get_driver(),//若没有指定8                       pcie_nvme_enum_cb, &enum_ctx);9     } else {
10         return spdk_pci_device_attach(spdk_pci_nvme_get_driver(),//指定了话直接attach
11                           pcie_nvme_enum_cb, &enum_ctx, &enum_ctx.pci_addr);
12     }
13 

spdk_pci_enumerate:

 1 int2 spdk_pci_enumerate(struct spdk_pci_driver *driver,3            spdk_pci_enum_cb enum_cb,4            void *enum_ctx)5 {6     struct spdk_pci_device *dev;7     int rc;8 9     cleanup_pci_devices();
10 
11     pthread_mutex_lock(&g_pci_mutex);
12     TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { //遍历g_pci_devices
13         if (dev->internal.attached ||
14             dev->internal.driver != driver ||
15             dev->internal.pending_removal) {
16             continue;
17         }
18 
19         rc = enum_cb(enum_ctx, dev);// 从g_pci_devices找到我们要的driver,那么调用回调函数进行后续的ctrl_construct工作
20         if (rc == 0) {
21             dev->internal.attached = true;//构建成功,attach设置为true
22         } else if (rc < 0) {
23             pthread_mutex_unlock(&g_pci_mutex);
24             return -1;
25         }
26     }
27     pthread_mutex_unlock(&g_pci_mutex);
28 
29     if (!driver->is_registered) {//若改driver还没注册,那么register到rte_pci_bus.driver_list
30         driver->is_registered = true;
31         rte_pci_register(&driver->driver);
32     }
33 //上面不是找到了吗,下面这些是干啥?为啥要scan和probe??上面只是放到rte_pci_bus.driver_list了,后面还需做什么?
34     driver->cb_fn = enum_cb;
35     driver->cb_arg = enum_ctx;
36 
37     if (rte_bus_scan() != 0 || rte_bus_probe() != 0) {//若bus scan和probe都不成功
38         driver->cb_arg = NULL;
39         driver->cb_fn = NULL;
40         return -1;
41     }
42 
43     driver->cb_arg = NULL;
44     driver->cb_fn = NULL;
45 
46     cleanup_pci_devices();
47     return 0;
48 }

回调函数pcie_nvme_enum_cb:

主要是执行nvme_ctrlr_probe(&trid, enum_ctx->probe_ctx, pci_dev) 从而构建相应type的ctrl:nvme_transport_ctrlr_construct(trid, &opts, devhandle),这些不放在这里介绍,会在spdk的源码解读里面分析。

rte_pci_register:

1 /* register a driver */
2 void
3 rte_pci_register(struct rte_pci_driver *driver)
4 {
5     TAILQ_INSERT_TAIL(&rte_pci_bus.driver_list, driver, next);
6     driver->bus = &rte_pci_bus;
7 }//注意这个struct rte_pci_bus rte_pci_bus = { .bus = {  .scan = rte_pci_scan,  .probe = rte_pci_probe,  .find_device = pci_find_device,  .plug = pci_plug,  .unplug = pci_unplug,  .parse = pci_parse,  .dma_map = pci_dma_map,  .dma_unmap = pci_dma_unmap,  .get_iommu_class = rte_pci_get_iommu_class,  .dev_iterate = rte_pci_dev_iterate,  .hot_unplug_handler = pci_hot_unplug_handler,  .sigbus_handler = pci_sigbus_handler, }, .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list), .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list),};

rte_bus_scan()和rte_bus_probe() 对所有bus进行scan和probe,若是pci_bus,执行的是上面注册的

.scan = rte_pci_scan, .probe = rte_pci_probe,

回到 1 中的attach函数:

spdk_pci_device_attach:跟原来看的有些不一样,之前看的版本直接调用的是rte_pci_scan

 1 int2 spdk_pci_device_attach(struct spdk_pci_driver *driver,3                spdk_pci_enum_cb enum_cb,4                void *enum_ctx, struct spdk_pci_addr *pci_address)5 {6     struct spdk_pci_device *dev;7     int rc;8     char bdf[32];9 
10     spdk_pci_addr_fmt(bdf, sizeof(bdf), pci_address);
11 
12     cleanup_pci_devices();
13 
14     TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
15         if (spdk_pci_addr_compare(&dev->addr, pci_address) == 0) {
16             break;
17         }
18     }
19 
20     if (dev != NULL && dev->internal.driver == driver) {
21         pthread_mutex_lock(&g_pci_mutex);
22         if (dev->internal.attached || dev->internal.pending_removal) {
23             pthread_mutex_unlock(&g_pci_mutex);
24             return -1;
25         }
26 
27         rc = enum_cb(enum_ctx, dev);//执行construct ctrl等
28         if (rc == 0) {
29             dev->internal.attached = true;
30         }
31         pthread_mutex_unlock(&g_pci_mutex);
32         return rc;
33     }
34 
35     if (!driver->is_registered) {
36         driver->is_registered = true;
37         rte_pci_register(&driver->driver);//register到rte_pci_bus.driver_list
38     }
39 
40     driver->cb_fn = enum_cb;
41     driver->cb_arg = enum_ctx;
42 
43 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0)
44     int i = 0;
45 
46     do {
47         rc = rte_eal_hotplug_add("pci", bdf, "");
48     } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT);
49 
50     if (i > 1 && rc == -EEXIST) {
51         /* Even though the previous request timed out, the device
52          * was attached successfully.
53          */
54         rc = 0;
55     }
56 #else
57     rc = rte_eal_dev_attach(bdf, "");//这个函数在旧版本的dpdk中
58 #endif
59 
60     driver->cb_arg = NULL;
61     driver->cb_fn = NULL;
62 
63     cleanup_pci_devices();
64     return rc == 0 ? 0 : -1;
65 }

rte_eal_hotplug_add:

--------rte_dev_probe(devargs)

 1 int2 rte_dev_probe(const char *devargs)3 {4     struct eal_dev_mp_req req;5     struct rte_device *dev;6     int ret;7 8     memset(&req, 0, sizeof(req));9     req.t = EAL_DEV_REQ_TYPE_ATTACH;
10     strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
11 
12     if (rte_eal_process_type() != RTE_PROC_PRIMARY) {//不是primary进程
13         /**
14          * If in secondary process, just send IPC request to
15          * primary process.
16          */
17         ret = eal_dev_hotplug_request_to_primary(&req);//那么给primary进程发attch的请求
18         if (ret != 0) {
19             RTE_LOG(ERR, EAL,
20                 "Failed to send hotplug request to primary\n");
21             return -ENOMSG;
22         }
23         if (req.result != 0)
24             RTE_LOG(ERR, EAL,
25                 "Failed to hotplug add device\n");
26         return req.result;
27     }
28 
29     /* attach a shared device from primary start from here: */
31     /* primary attach the new device itself. */
32     ret = local_dev_probe(devargs, &dev);//其中会执行da->bus->scan()
33 
34     if (ret != 0) {
35         RTE_LOG(ERR, EAL,
36             "Failed to attach device on primary process\n");
37 
38         /**
39          * it is possible that secondary process failed to attached a
40          * device that primary process have during initialization,
41          * so for -EEXIST case, we still need to sync with secondary
42          * process.
43          */
44         if (ret != -EEXIST)
45             return ret;
46     }
47 
48     /* primary send attach sync request to secondary. */
49     ret = eal_dev_hotplug_request_to_secondary(&req);//给secondary进程发消息同步attach情况
50 
51     /* if any communication error, we need to rollback. */
52     if (ret != 0) {
53         RTE_LOG(ERR, EAL,
54             "Failed to send hotplug add request to secondary\n");
55         ret = -ENOMSG;
56         goto rollback;
57     }
59     /**
60      * if any secondary failed to attach, we need to consider if rollback
61      * is necessary.
62      */
63     if (req.result != 0) {
64         RTE_LOG(ERR, EAL,
65             "Failed to attach device on secondary process\n");
66         ret = req.result;
67 
68         /* for -EEXIST, we don't need to rollback. */
69         if (ret == -EEXIST)
70             return ret;
71         goto rollback;
72     }
73 
74     return 0;
75 
76 rollback:
77     req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK;
78 
79     /* primary send rollback request to secondary. */
80     if (eal_dev_hotplug_request_to_secondary(&req) != 0)
81         RTE_LOG(WARNING, EAL,
82             "Failed to rollback device attach on secondary."
83             "Devices in secondary may not sync with primary\n");
84 
85     /* primary rollback itself. */
86     if (local_dev_remove(dev) != 0)
87         RTE_LOG(WARNING, EAL,
88             "Failed to rollback device attach on primary."
89             "Devices in secondary may not sync with primary\n");
90 
91     return ret;
92 }

local_dev_probe:

最终也是调用rte_pci_scan和pci_probe_all_drivers

 1 /* probe device at local process. */2 int3 local_dev_probe(const char *devargs, struct rte_device **new_dev)4 {5     struct rte_device *dev;6     struct rte_devargs *da;7     int ret;8 9     *new_dev = NULL;
10     da = calloc(1, sizeof(*da));
11     if (da == NULL)
12         return -ENOMEM;
13 
14     ret = rte_devargs_parse(da, devargs);
15     if (ret)
16         goto err_devarg;
17 
18     if (da->bus->plug == NULL) {
19         RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)\n",
20             da->bus->name);
21         ret = -ENOTSUP;
22         goto err_devarg;
23     }
24 
25     ret = rte_devargs_insert(&da);
26     if (ret)
27         goto err_devarg;
28 
29     /* the rte_devargs will be referenced in the matching rte_device */
30     ret = da->bus->scan();//pci的话执行register函数中注册的rte_pci_scan
31     if (ret)
32         goto err_devarg;
33 
34     dev = da->bus->find_device(NULL, cmp_dev_name, da->name);
35     if (dev == NULL) {
36         RTE_LOG(ERR, EAL, "Cannot find device (%s)\n",
37             da->name);
38         ret = -ENODEV;
39         goto err_devarg;
40     }
41     /* Since there is a matching device, it is now its responsibility
42      * to manage the devargs we've just inserted. From this point
43      * those devargs shouldn't be removed manually anymore.
44      */
45 
46     ret = dev->bus->plug(dev);//rte_pci_plug中执行的是pci_probe_all_drivers(RTE_DEV_TO_PCI(dev))
47     if (ret > 0)
48         ret = -ENOTSUP;
49 
50     if (ret && !rte_dev_is_probed(dev)) { /* if hasn't ever succeeded */
51         RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n",
52             dev->name);
53         return ret;
54     }
55 
56     *new_dev = dev;
57     return ret;
58 
59 err_devarg:
60     if (rte_devargs_remove(da) != 0) {
61         free(da->args);
62         free(da);
63     }
64     return ret;
65 }

所以 1 中 nvme_pcie_ctrl_scan 不管是spdk_pci_enumerate还是spdk_pci_device_attach,核心的流程都是一样的:

执行回调函数pcie_nvme_enum_cb;

rte_pci_scan

rte_pci_probe/pci_probe_all_drivers (rte_pci_probe也是调用pci_probe_all_drivers)

所以后面我们看 rte_pci_bus.scan(rte_pci_scan)和rte_pci_bus.probe(rte_pci_probe)的实现。

rte_pci_scan:

 1 /*2  * Scan the content of the PCI bus, and the devices in the devices3  * list4  */5 int6 rte_pci_scan(void)7 {8     struct dirent *e;9     DIR *dir;
10     char dirname[PATH_MAX];
11     struct rte_pci_addr addr;
12     
13         ........
14     dir = opendir(rte_pci_get_sysfs_path()); ///sys/bus/pci/devices
15     
16         ........
17     while ((e = readdir(dir)) != NULL) {
18         if (e->d_name[0] == '.')
19             continue;
20 
21         if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &addr) != 0)
22             continue;
23 
24         snprintf(dirname, sizeof(dirname), "%s/%s",
25                 rte_pci_get_sysfs_path(), e->d_name);
26 
27         if (pci_scan_one(dirname, &addr) < 0)//扫描/sys/bus/pci/devices下面每个目录
28             goto error;
29     }
30     closedir(dir);
31     return 0;
32 ..........
33 }

ls /sys/bus/pci/devices/ 0000:00:00.0 0000:00:04.4 0000:00:1c.6 0000:03:00.0 0000:ff:0d.1 0000:ff:12.2 0000:ff:14.5 0000:ff:17.6 0000:00:01.0 0000:00:04.5 0000:00:1c.7 0000:05:00.0 0000:ff:0f.0 0000:ff:12.4 0000:ff:14.6 0000:ff:17.7

  1 /* Scan one pci sysfs entry, and fill the devices list from it. */2 static int3 pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)4 {5     char filename[PATH_MAX];6     unsigned long tmp;7     struct rte_pci_device *dev;8     char driver[PATH_MAX];9     int ret;10 11     dev = malloc(sizeof(*dev));12     if (dev == NULL)13         return -1;14 15     memset(dev, 0, sizeof(*dev));16     dev->device.bus = &rte_pci_bus.bus;17     dev->addr = *addr;18 19     /* get vendor id */20     snprintf(filename, sizeof(filename), "%s/vendor", dirname);21     if (eal_parse_sysfs_value(filename, &tmp) < 0) {22         free(dev);23         return -1;24     }25     dev->id.vendor_id = (uint16_t)tmp;26 27     /* get device id */28     snprintf(filename, sizeof(filename), "%s/device", dirname);29     if (eal_parse_sysfs_value(filename, &tmp) < 0) {30         free(dev);31         return -1;32     }33     dev->id.device_id = (uint16_t)tmp;34 35     /* get subsystem_vendor id */36     snprintf(filename, sizeof(filename), "%s/subsystem_vendor",37          dirname);38     if (eal_parse_sysfs_value(filename, &tmp) < 0) {39         free(dev);40         return -1;41     }42     dev->id.subsystem_vendor_id = (uint16_t)tmp;43 44     /* get subsystem_device id */45     snprintf(filename, sizeof(filename), "%s/subsystem_device",46          dirname);47     if (eal_parse_sysfs_value(filename, &tmp) < 0) {48         free(dev);49         return -1;50     }51     dev->id.subsystem_device_id = (uint16_t)tmp;52 53     /* get class_id */54     snprintf(filename, sizeof(filename), "%s/class",55          dirname);56     if (eal_parse_sysfs_value(filename, &tmp) < 0) {57         free(dev);58         return -1;59     }60     /* the least 24 bits are valid: class, subclass, program interface */61     dev->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;62 63     /* get max_vfs */64     dev->max_vfs = 0;65     snprintf(filename, sizeof(filename), "%s/max_vfs", dirname);66     if (!access(filename, F_OK) &&67         eal_parse_sysfs_value(filename, &tmp) == 0)68         dev->max_vfs = (uint16_t)tmp;69     else {70         /* for non igb_uio driver, need kernel version >= 3.8 */71         snprintf(filename, sizeof(filename),72              "%s/sriov_numvfs", dirname);73         if (!access(filename, F_OK) &&74             eal_parse_sysfs_value(filename, &tmp) == 0)75             dev->max_vfs = (uint16_t)tmp;76     }77 78     /* get numa node, default to 0 if not present */79     snprintf(filename, sizeof(filename), "%s/numa_node",80          dirname);81 82     if (access(filename, F_OK) != -1) {83         if (eal_parse_sysfs_value(filename, &tmp) == 0)84             dev->device.numa_node = tmp;85         else86             dev->device.numa_node = -1;87     } else {88         dev->device.numa_node = 0;89     }90 91     pci_name_set(dev);92 93     /* parse resources */94     snprintf(filename, sizeof(filename), "%s/resource", dirname);95     if (pci_parse_sysfs_resource(filename, dev) < 0) {96         RTE_LOG(ERR, EAL, "%s(): cannot parse resource\n", __func__);97         free(dev);98         return -1;99     }
100 
101     /* parse driver */
102     snprintf(filename, sizeof(filename), "%s/driver", dirname);///sys/bus/pci/drivers
103     ret = pci_get_kernel_driver_by_path(filename, driver, sizeof(driver));
104     if (ret < 0) {
105         RTE_LOG(ERR, EAL, "Fail to get kernel driver\n");
106         free(dev);
107         return -1;
108     }
109 
110     if (!ret) {
111         if (!strcmp(driver, "vfio-pci"))
112             dev->kdrv = RTE_KDRV_VFIO;
113         else if (!strcmp(driver, "igb_uio"))
114             dev->kdrv = RTE_KDRV_IGB_UIO;
115         else if (!strcmp(driver, "uio_pci_generic"))
116             dev->kdrv = RTE_KDRV_UIO_GENERIC;
117         else
118             dev->kdrv = RTE_KDRV_UNKNOWN;
119     } else
120         dev->kdrv = RTE_KDRV_NONE;
121 
122     /* device is valid, add in list (sorted) */
123     if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
124         rte_pci_add_device(dev);
125     } else {
126         struct rte_pci_device *dev2;
127         int ret;
128 
129         TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
130             ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
131             if (ret > 0)
132                 continue;
133 
134             if (ret < 0) {
135                 rte_pci_insert_device(dev2, dev);
136             } else { /* already registered */
137                 if (!rte_dev_is_probed(&dev2->device)) {
138                     dev2->kdrv = dev->kdrv;
139                     dev2->max_vfs = dev->max_vfs;
140                     pci_name_set(dev2);
141                     memmove(dev2->mem_resource,
142                         dev->mem_resource,
143                         sizeof(dev->mem_resource));
144                 } else {
145                     /**
146                      * If device is plugged and driver is
147                      * probed already, (This happens when
148                      * we call rte_dev_probe which will
149                      * scan all device on the bus) we don't
150                      * need to do anything here unless...
151                      **/
152                     if (dev2->kdrv != dev->kdrv ||
153                         dev2->max_vfs != dev->max_vfs)
154                         /*
155                          * This should not happens.
156                          * But it is still possible if
157                          * we unbind a device from
158                          * vfio or uio before hotplug
159                          * remove and rebind it with
160                          * a different configure.
161                          * So we just print out the
162                          * error as an alarm.
163                          */
164                         RTE_LOG(ERR, EAL, "Unexpected device scan at %s!\n",
165                             filename);
166                 }
167                 free(dev);
168             }
169             return 0;
170         }
171 
172         rte_pci_add_device(dev);
173     }
174 
175     return 0;
176 }

rte_pci_probe:

------FOREACH_DEVICE_ON_PCIBUS(dev) pci_probe_all_drivers(dev)

------------FOREACH_DRIVER_ON_PCIBUS(dr) rte_pci_probe_one_driver(dr, dev)

  1 /*2  * If vendor/device ID match, call the probe() function of the3  * driver.4  */5 static int6 rte_pci_probe_one_driver(struct rte_pci_driver *dr,7              struct rte_pci_device *dev)8 {9     int ret;10     bool already_probed;11     struct rte_pci_addr *loc;12 13     if ((dr == NULL) || (dev == NULL))14         return -EINVAL;15 16     loc = &dev->addr;17 18     /* The device is not blacklisted; Check if driver supports it */19     if (!rte_pci_match(dr, dev))20         /* Match of device and driver failed */21         return 1;22 23     RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",24             loc->domain, loc->bus, loc->devid, loc->function,25             dev->device.numa_node);26 27     /* no initialization when blacklisted, return without error */28     if (dev->device.devargs != NULL &&29         dev->device.devargs->policy ==30             RTE_DEV_BLACKLISTED) {31         RTE_LOG(INFO, EAL, "  Device is blacklisted, not"32             " initializing\n");33         return 1;34     }35 36     if (dev->device.numa_node < 0) {37         RTE_LOG(WARNING, EAL, "  Invalid NUMA socket, default to 0\n");38         dev->device.numa_node = 0;39     }40 41     already_probed = rte_dev_is_probed(&dev->device);42     if (already_probed && !(dr->drv_flags & RTE_PCI_DRV_PROBE_AGAIN)) {43         RTE_LOG(DEBUG, EAL, "Device %s is already probed\n",44                 dev->device.name);45         return -EEXIST;46     }47 48     RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,49         dev->id.device_id, dr->driver.name);50 51     /*52      * reference driver structure53      * This needs to be before rte_pci_map_device(), as it enables to use54      * driver flags for adjusting configuration.55      */56     if (!already_probed) {57         enum rte_iova_mode dev_iova_mode;58         enum rte_iova_mode iova_mode;59 60         dev_iova_mode = pci_device_iova_mode(dr, dev);//从设备绑定的驱动判断dev_iova_mode,例如若是UIO驱动,则这里是PA61         iova_mode = rte_eal_iova_mode();//dpdk初始化过程判断的,首先会去判断设备的驱动,如果驱动还没注册,那么里面是根据机器上是否有iommu等判断。而spdk中nvme     驱动是在dpdk初始化之后才注册进去的,所以即使是用uio驱动,dpdk给出的iova_mode也是VA,所以这里有点小问题! 62         if (dev_iova_mode != RTE_IOVA_DC &&63             dev_iova_mode != iova_mode) {64             RTE_LOG(ERR, EAL, "  Expecting '%s' IOVA mode but current mode is '%s', not initializing\n",65                 dev_iova_mode == RTE_IOVA_PA ? "PA" : "VA",66                 iova_mode == RTE_IOVA_PA ? "PA" : "VA");67             return -EINVAL;68         }69 70         dev->driver = dr;71     }72 73     if (!already_probed && (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)) {74         /* map resources for devices that use igb_uio */???注释有问题??75         ret = rte_pci_map_device(dev);76         if (ret != 0) {77             dev->driver = NULL;78             return ret;79         }80     }81 82     /* call the driver probe() function */83     ret = dr->probe(dr, dev);  //在哪里?????84     if (already_probed)85         return ret; /* no rollback if already succeeded earlier */86     if (ret) {87         dev->driver = NULL;88         if ((dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) &&89             /* Don't unmap if device is unsupported and90              * driver needs mapped resources.91              */92             !(ret > 0 &&93                 (dr->drv_flags & RTE_PCI_DRV_KEEP_MAPPED_RES)))94             rte_pci_unmap_device(dev);95     } else {96         dev->device.driver = &dr->driver;97     }98 99     return ret;
100 }

rte_pci_map_device 从这遍开始和vfio,uio等相关

 1 /* Map pci device */2 int3 rte_pci_map_device(struct rte_pci_device *dev)4 {5     int ret = -1;6 7     /* try mapping the NIC resources using VFIO if it exists */8     switch (dev->kdrv) {9     case RTE_KDRV_VFIO:
10 #ifdef VFIO_PRESENT
11         if (pci_vfio_is_enabled())
12             ret = pci_vfio_map_resource(dev);
13 #endif
14         break;
15     case RTE_KDRV_IGB_UIO:
16     case RTE_KDRV_UIO_GENERIC:
17         if (rte_eal_using_phys_addrs()) {
18             /* map resources for devices that use uio */
19             ret = pci_uio_map_resource(dev);
20         }
21         break;
22     default:
23         RTE_LOG(DEBUG, EAL,
24             "  Not managed by a supported kernel driver, skipped\n");
25         ret = 1;
26         break;
27     }
28 
29     return ret;
30 }

pci_vfio_map_resource:

---1---pci_vfio_map_resource_primary 若设primary进程

------pci_vfio_map_resource_secondary

-------2---------rte_vfio_setup_device

------------3------------vfio_mem_event_callback

这三个函数要重点看。。。。

原文链接:https://www.cnblogs.com/yi-mu-xi/p/12441357.html 

【免费订阅,永久学习】学习地址: 

C/C++Linux服务器开发/后台架构师【学习视频教程】

LinuxC/C++服务器开发/架构师 面试题、学习资料、教学视频和学习路线图(资料包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis、MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等),或点击这里加qun免费领取,关注我持续更新哦! ! 

 【免费订阅,永久学习】学习地址: 

 Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家-学习视频教程-腾讯课堂

 

 


http://www.ppmy.cn/news/155651.html

相关文章

Linux系统下安装minio并设置SSL证书进行HTTPS远程连接访问

下载minio并且设置权限 创建一个文件夹用于保存下载的minio mkdir /usr/local/minio在创建的文件夹中用wget下载Linux版本的minio服务端 wget https://dl.min.io/server/minio/release/linux-amd64/minio下载完成后设置权限 chmod x minio启动安装minio默认HTTP访问 启动m…

PTA-学生成绩录入及查询 zym广东外语外贸大学

本题有巨坑&#xff01; 学生成绩表中&#xff0c;一名学生的信息包含如下信息&#xff1a; 学号(11位)、姓名、数学成绩、英语成绩、程序设计成绩、物理成绩。 本题要求编写程序&#xff0c;录入N条学生的信息&#xff0c;并且按查询要求显示学生成绩等信息。 输入格式: 输…

zmy

怎么整积分

网安学习-Python安全开发

目录 Python学习的意义 涉及相关技术 案例一&#xff1a;IP&Whois&系统指纹获取代码段-外网 查询IP whois查询 案例二&#xff1a;CDN&子域名&端口扫描&交互代码段-外网 判断CDN 子域名查询 端口扫描 案例三&#xff1a;Py格式解析环境与可执行…

python安全开发——内外网收集 Socket子域名DNS

前言: 做渗透测试,第一步就是进行信息收集,对于具体的环境下,需要不同的测试需求,通过自己编写的脚本进行测试会有事半功倍的效果,本文主要介绍了在信息收集的时候,我们可能使用到的库函数。 本人水平有限, (一)外网信息收集 1、域名反查IP功…

2022考研该如何准备?zym勿入,因为大佬都不需要考研!

最近有好几个同学问我考研应该怎么准备&#xff1f;要不要买课&#xff1f;我想说的是富人的话买课当然好啊&#xff0c;支持正版。但是现在2022届考研的课基本上都没录完的&#xff0c;而知识的迭代远没有你想象中的快&#xff0c;就像我买了整套2022届的王道408辅导书&#x…

adk安装更新

首先下载zym&#xff0c;这是一个代理服务器软件。如下&#xff0c;代理地址为127.0.0.1&#xff0c;端口号为8580。 然后点击Android SDK Manager的tools选项&#xff0c;选择Settings。将HTTP代理服务器地址设为上面那个软件的127.0.0.1&#xff0c;代理端口设为8580。勾选强…

PHP混淆zym解密

PHP混淆zym解密 最近二开过程中&#xff0c;碰到PHP混淆zym加密的问题&#xff0c;刚开始找了好多网站都是付费的&#xff0c;后来在吾爱破解找到了解决方法。 大神解密及调试过程&#xff0c;详见原文&#xff1a;https://www.52pojie.cn/thread-693641-1-1.html 源码 decry…