1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2015 Intel Corporation 3 */ 4 5 #include <fcntl.h> 6 #include <string.h> 7 #include <unistd.h> 8 #include <sys/types.h> 9 #include <sys/stat.h> 10 #include <sys/mman.h> 11 12 #include <rte_eal.h> 13 #include <rte_pci.h> 14 #include <rte_bus_pci.h> 15 #include <rte_tailq.h> 16 #include <rte_log.h> 17 #include <rte_malloc.h> 18 19 #include "private.h" 20 21 static struct rte_tailq_elem rte_uio_tailq = { 22 .name = "UIO_RESOURCE_LIST", 23 }; 24 EAL_REGISTER_TAILQ(rte_uio_tailq) 25 26 static int 27 pci_uio_map_secondary(struct rte_pci_device *dev) 28 { 29 int fd, i, j; 30 struct mapped_pci_resource *uio_res; 31 struct mapped_pci_res_list *uio_res_list = 32 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 33 34 TAILQ_FOREACH(uio_res, uio_res_list, next) { 35 36 /* skip this element if it doesn't match our PCI address */ 37 if (rte_pci_addr_cmp(&uio_res->pci_addr, &dev->addr)) 38 continue; 39 40 for (i = 0; i != uio_res->nb_maps; i++) { 41 /* 42 * open devname, to mmap it 43 */ 44 fd = open(uio_res->maps[i].path, O_RDWR); 45 if (fd < 0) { 46 RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", 47 uio_res->maps[i].path, strerror(errno)); 48 return -1; 49 } 50 51 void *mapaddr = pci_map_resource(uio_res->maps[i].addr, 52 fd, (off_t)uio_res->maps[i].offset, 53 (size_t)uio_res->maps[i].size, 0); 54 /* fd is not needed in slave process, close it */ 55 close(fd); 56 if (mapaddr != uio_res->maps[i].addr) { 57 RTE_LOG(ERR, EAL, 58 "Cannot mmap device resource file %s to address: %p\n", 59 uio_res->maps[i].path, 60 uio_res->maps[i].addr); 61 if (mapaddr != NULL) { 62 /* unmap addrs correctly mapped */ 63 for (j = 0; j < i; j++) 64 pci_unmap_resource( 65 uio_res->maps[j].addr, 66 (size_t)uio_res->maps[j].size); 67 /* unmap addr wrongly mapped */ 68 pci_unmap_resource(mapaddr, 69 (size_t)uio_res->maps[i].size); 70 } 71 return -1; 72 } 73 dev->mem_resource[i].addr = mapaddr; 74 } 75 return 0; 76 } 77 78 RTE_LOG(ERR, EAL, "Cannot find resource for device\n"); 79 return 1; 80 } 81 82 /* map the PCI resource of a PCI device in virtual memory */ 83 int 84 pci_uio_map_resource(struct rte_pci_device *dev) 85 { 86 int i, map_idx = 0, ret; 87 uint64_t phaddr; 88 struct mapped_pci_resource *uio_res = NULL; 89 struct mapped_pci_res_list *uio_res_list = 90 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 91 92 dev->intr_handle.fd = -1; 93 dev->intr_handle.uio_cfg_fd = -1; 94 95 /* secondary processes - use already recorded details */ 96 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 97 return pci_uio_map_secondary(dev); 98 99 /* allocate uio resource */ 100 ret = pci_uio_alloc_resource(dev, &uio_res); 101 if (ret) 102 return ret; 103 104 /* Map all BARs */ 105 for (i = 0; i != PCI_MAX_RESOURCE; i++) { 106 /* skip empty BAR */ 107 phaddr = dev->mem_resource[i].phys_addr; 108 if (phaddr == 0) 109 continue; 110 111 ret = pci_uio_map_resource_by_index(dev, i, 112 uio_res, map_idx); 113 if (ret) 114 goto error; 115 116 map_idx++; 117 } 118 119 uio_res->nb_maps = map_idx; 120 121 TAILQ_INSERT_TAIL(uio_res_list, uio_res, next); 122 123 return 0; 124 error: 125 for (i = 0; i < map_idx; i++) { 126 pci_unmap_resource(uio_res->maps[i].addr, 127 (size_t)uio_res->maps[i].size); 128 rte_free(uio_res->maps[i].path); 129 } 130 pci_uio_free_resource(dev, uio_res); 131 return -1; 132 } 133 134 static void 135 pci_uio_unmap(struct mapped_pci_resource *uio_res) 136 { 137 int i; 138 139 if (uio_res == NULL) 140 return; 141 142 for (i = 0; i != uio_res->nb_maps; i++) { 143 pci_unmap_resource(uio_res->maps[i].addr, 144 (size_t)uio_res->maps[i].size); 145 if (rte_eal_process_type() == RTE_PROC_PRIMARY) 146 rte_free(uio_res->maps[i].path); 147 } 148 } 149 150 /* remap the PCI resource of a PCI device in anonymous virtual memory */ 151 int 152 pci_uio_remap_resource(struct rte_pci_device *dev) 153 { 154 int i; 155 void *map_address; 156 157 if (dev == NULL) 158 return -1; 159 160 /* Remap all BARs */ 161 for (i = 0; i != PCI_MAX_RESOURCE; i++) { 162 /* skip empty BAR */ 163 if (dev->mem_resource[i].phys_addr == 0) 164 continue; 165 map_address = mmap(dev->mem_resource[i].addr, 166 (size_t)dev->mem_resource[i].len, 167 PROT_READ | PROT_WRITE, 168 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 169 if (map_address == MAP_FAILED) { 170 RTE_LOG(ERR, EAL, 171 "Cannot remap resource for device %s\n", 172 dev->name); 173 return -1; 174 } 175 RTE_LOG(INFO, EAL, 176 "Successful remap resource for device %s\n", 177 dev->name); 178 } 179 180 return 0; 181 } 182 183 static struct mapped_pci_resource * 184 pci_uio_find_resource(struct rte_pci_device *dev) 185 { 186 struct mapped_pci_resource *uio_res; 187 struct mapped_pci_res_list *uio_res_list = 188 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 189 190 if (dev == NULL) 191 return NULL; 192 193 TAILQ_FOREACH(uio_res, uio_res_list, next) { 194 195 /* skip this element if it doesn't match our PCI address */ 196 if (!rte_pci_addr_cmp(&uio_res->pci_addr, &dev->addr)) 197 return uio_res; 198 } 199 return NULL; 200 } 201 202 /* unmap the PCI resource of a PCI device in virtual memory */ 203 void 204 pci_uio_unmap_resource(struct rte_pci_device *dev) 205 { 206 struct mapped_pci_resource *uio_res; 207 struct mapped_pci_res_list *uio_res_list = 208 RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); 209 210 if (dev == NULL) 211 return; 212 213 /* find an entry for the device */ 214 uio_res = pci_uio_find_resource(dev); 215 if (uio_res == NULL) 216 return; 217 218 /* secondary processes - just free maps */ 219 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 220 return pci_uio_unmap(uio_res); 221 222 TAILQ_REMOVE(uio_res_list, uio_res, next); 223 224 /* unmap all resources */ 225 pci_uio_unmap(uio_res); 226 227 /* free uio resource */ 228 rte_free(uio_res); 229 230 /* close fd if in primary process */ 231 close(dev->intr_handle.fd); 232 if (dev->intr_handle.uio_cfg_fd >= 0) { 233 close(dev->intr_handle.uio_cfg_fd); 234 dev->intr_handle.uio_cfg_fd = -1; 235 } 236 237 dev->intr_handle.fd = -1; 238 dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 239 } 240