* * 用于映射 resource 资源,并获取 PCI BAR * @param dev:DPDK 中关于某一个 PCI 设备的抽象实例 * @param res_id:说明要获取第几个 BAR * @param uio_res:用来存放 PCI BAR 资源的结构 * @param map_idx、uio_res:数组的计数器 */ int pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx, struct mapped_pci_resource *uio_res, int map_idx) { ..... // 省略 // 打开 /dev/bus/pci/devices/{pci_addr}/resource0..N 文件 if (!wc_activate || fd < 0) { snprintf(devname, sizeof(devname), "%s/" PCI_PRI_FMT "/resource%d", rte_pci_get_sysfs_path(), loc->domain, loc->bus, loc->devid, loc->function, res_idx); /* then try to map resource file */ fd = open(devname, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s ", devname, strerror(errno)); goto error; } } /* try mapping somewhere close to the end of hugepages */ if (pci_map_addr == NULL) pci_map_addr = pci_find_max_end_va(); // 进行 mmap() 映射,拿到 PCI BAR 在进程虚拟空间下的地址 mapaddr = pci_map_resource(pci_map_addr, fd, 0, (size_t)dev->mem_resource[res_idx].len, 0); close(fd); if (mapaddr == MAP_FAILED) goto error; pci_map_addr = RTE_PTR_ADD(mapaddr, (size_t)dev->mem_resource[res_idx].len); // 将拿到的 PCI BAR 映射至进程虚拟空间内的地址存起来 maps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr; maps[map_idx].size = dev->mem_resource[res_idx].len; maps[map_idx].addr = mapaddr; maps[map_idx].offset = 0; strcpy(maps[map_idx].path, devname); dev->mem_resource[res_idx].addr = mapaddr; return 0; error: rte_free(maps[map_idx].path); return -1; } /* * 对 pci/resource0..N 进行 mmap(),将 PCI BAR 空间通过 mmap 的方式映射到进程内部的虚拟空间,供用户态应用来操作设备 */ void * pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size, int additional_flags) { void *mapaddr; // 核心便是这句 mmap,其中要注意的是 offset 必须为 0 mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE, MAP_SHARED | additional_flags, fd, offset); if (mapaddr == MAP_FAILED) { RTE_LOG(ERR, EAL, "%s(): cannot mmap(%d, %p, 0x%zx, 0x%llx): %s (%p) ", __func__, fd, requested_addr, size, (unsigned long long)offset, strerror(errno), mapaddr); } else RTE_LOG(DEBUG, EAL, " PCI memory mapped at %p ", mapaddr); return mapaddr; }