zoukankan      html  css  js  c++  java
  • mmap PROT_READ | PROT_WRITE

    *
     * 用于映射 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;
    }
  • 相关阅读:
    [zz]利用__FILE__, __LINE__, __FUNCTION__跟踪调试程序
    [zz]va_start() 和 va_end()函数应用
    [zz]shmdt与shmctl的区别
    [zz]GNU C 扩展之__attribute__ 机制简介 [2]
    Linux errno 错误含义速查
    过滤器的简介
    MyBatis中的原理
    文件上传
    mybatis实体为什么要提供一个无参的构造函数
    为什么要有无参构造方法
  • 原文地址:https://www.cnblogs.com/dream397/p/13658987.html
Copyright © 2011-2022 走看看