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;
    }
  • 相关阅读:
    [BZOJ1657] [Usaco2006 Mar] Mooo 奶牛的歌声 (单调栈)
    [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)
    [BZOJ1015] [JSOI2008] 星球大战starwar (并查集)
    [BZOJ1007] [HNOI2008] 水平可见直线 (凸包)
    [BZOJ1061] [Noi2008] 志愿者招募 (费用流)
    [BZOJ1051] [HAOI2006] 受欢迎的牛 (强联通分量)
    BZOJ2299: [HAOI2011]向量
    BZOJ2783: [JLOI2012]树
    BZOJ3521: [Poi2014]Salad Bar
    BZOJ2429: [HAOI2006]聪明的猴子
  • 原文地址:https://www.cnblogs.com/dream397/p/13658987.html
Copyright © 2011-2022 走看看