Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <dirent.h>
7 : :
8 : : #include <rte_log.h>
9 : : #include <rte_pci.h>
10 : : #include <rte_bus_pci.h>
11 : : #include <rte_malloc.h>
12 : : #include <rte_devargs.h>
13 : : #include <rte_memcpy.h>
14 : : #include <rte_vfio.h>
15 : :
16 : : #include "eal_filesystem.h"
17 : :
18 : : #include "private.h"
19 : : #include "pci_init.h"
20 : :
21 : : /**
22 : : * @file
23 : : * PCI probing using Linux sysfs.
24 : : */
25 : :
26 : : static int
27 : 7053 : pci_get_kernel_driver_by_path(const char *filename, char *dri_name,
28 : : size_t len)
29 : : {
30 : : int count;
31 : : char path[PATH_MAX];
32 : : char *name;
33 : :
34 [ + - ]: 7053 : if (!filename || !dri_name)
35 : : return -1;
36 : :
37 : 7053 : count = readlink(filename, path, PATH_MAX);
38 [ + - ]: 7053 : if (count >= PATH_MAX)
39 : : return -1;
40 : :
41 : : /* For device does not have a driver */
42 [ + + ]: 7053 : if (count < 0)
43 : : return 1;
44 : :
45 : 6397 : path[count] = '\0';
46 : :
47 : 6397 : name = strrchr(path, '/');
48 [ + - ]: 6397 : if (name) {
49 : 6397 : strlcpy(dri_name, name + 1, len);
50 : 6397 : return 0;
51 : : }
52 : :
53 : : return -1;
54 : : }
55 : :
56 : : /* Map pci device */
57 : : int
58 : 159 : rte_pci_map_device(struct rte_pci_device *dev)
59 : : {
60 : : int ret = -1;
61 : :
62 : : /* try mapping the NIC resources using VFIO if it exists */
63 [ - - + ]: 159 : switch (dev->kdrv) {
64 : 0 : case RTE_PCI_KDRV_VFIO:
65 : : #ifdef VFIO_PRESENT
66 [ # # ]: 0 : if (pci_vfio_is_enabled())
67 : 0 : ret = pci_vfio_map_resource(dev);
68 : : #endif
69 : : break;
70 : 0 : case RTE_PCI_KDRV_IGB_UIO:
71 : : case RTE_PCI_KDRV_UIO_GENERIC:
72 [ # # ]: 0 : if (rte_eal_using_phys_addrs()) {
73 : : /* map resources for devices that use uio */
74 : 0 : ret = pci_uio_map_resource(dev);
75 : : }
76 : : break;
77 : 159 : default:
78 : 159 : RTE_LOG(DEBUG, EAL,
79 : : " Not managed by a supported kernel driver, skipped\n");
80 : : ret = 1;
81 : 159 : break;
82 : : }
83 : :
84 : 159 : return ret;
85 : : }
86 : :
87 : : /* Unmap pci device */
88 : : void
89 : 0 : rte_pci_unmap_device(struct rte_pci_device *dev)
90 : : {
91 : : /* try unmapping the NIC resources using VFIO if it exists */
92 [ # # # ]: 0 : switch (dev->kdrv) {
93 : 0 : case RTE_PCI_KDRV_VFIO:
94 : : #ifdef VFIO_PRESENT
95 [ # # ]: 0 : if (pci_vfio_is_enabled())
96 : 0 : pci_vfio_unmap_resource(dev);
97 : : #endif
98 : : break;
99 : 0 : case RTE_PCI_KDRV_IGB_UIO:
100 : : case RTE_PCI_KDRV_UIO_GENERIC:
101 : : /* unmap resources for devices that use uio */
102 : 0 : pci_uio_unmap_resource(dev);
103 : 0 : break;
104 : 0 : default:
105 : 0 : RTE_LOG(DEBUG, EAL,
106 : : " Not managed by a supported kernel driver, skipped\n");
107 : 0 : break;
108 : : }
109 : 0 : }
110 : :
111 : : static int
112 : 0 : find_max_end_va(const struct rte_memseg_list *msl, void *arg)
113 : : {
114 : 0 : size_t sz = msl->len;
115 : 0 : void *end_va = RTE_PTR_ADD(msl->base_va, sz);
116 : : void **max_va = arg;
117 : :
118 [ # # ]: 0 : if (*max_va < end_va)
119 : 0 : *max_va = end_va;
120 : 0 : return 0;
121 : : }
122 : :
123 : : void *
124 : 0 : pci_find_max_end_va(void)
125 : : {
126 : 0 : void *va = NULL;
127 : :
128 : 0 : rte_memseg_list_walk(find_max_end_va, &va);
129 : 0 : return va;
130 : : }
131 : :
132 : :
133 : : /* parse one line of the "resource" sysfs file (note that the 'line'
134 : : * string is modified)
135 : : */
136 : : int
137 : 42318 : pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,
138 : : uint64_t *end_addr, uint64_t *flags)
139 : : {
140 : : union pci_resource_info {
141 : : struct {
142 : : char *phys_addr;
143 : : char *end_addr;
144 : : char *flags;
145 : : };
146 : : char *ptrs[PCI_RESOURCE_FMT_NVAL];
147 : : } res_info;
148 : :
149 [ - + ]: 42318 : if (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3) {
150 : 0 : RTE_LOG(ERR, EAL,
151 : : "%s(): bad resource format\n", __func__);
152 : 0 : return -1;
153 : : }
154 : 42318 : errno = 0;
155 : 42318 : *phys_addr = strtoull(res_info.phys_addr, NULL, 16);
156 : 42318 : *end_addr = strtoull(res_info.end_addr, NULL, 16);
157 : 42318 : *flags = strtoull(res_info.flags, NULL, 16);
158 [ - + ]: 42318 : if (errno != 0) {
159 : 0 : RTE_LOG(ERR, EAL,
160 : : "%s(): bad resource format\n", __func__);
161 : 0 : return -1;
162 : : }
163 : :
164 : : return 0;
165 : : }
166 : :
167 : : /* parse the "resource" sysfs file */
168 : : static int
169 : 7053 : pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
170 : : {
171 : : FILE *f;
172 : : char buf[BUFSIZ];
173 : : int i;
174 : : uint64_t phys_addr, end_addr, flags;
175 : :
176 : 7053 : f = fopen(filename, "r");
177 [ - + ]: 7053 : if (f == NULL) {
178 : 0 : RTE_LOG(ERR, EAL, "Cannot open sysfs resource\n");
179 : 0 : return -1;
180 : : }
181 : :
182 [ + + ]: 49371 : for (i = 0; i<PCI_MAX_RESOURCE; i++) {
183 : :
184 [ - + ]: 42318 : if (fgets(buf, sizeof(buf), f) == NULL) {
185 : 0 : RTE_LOG(ERR, EAL,
186 : : "%s(): cannot read resource\n", __func__);
187 : 0 : goto error;
188 : : }
189 [ - + ]: 42318 : if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
190 : : &end_addr, &flags) < 0)
191 : 0 : goto error;
192 : :
193 [ + + ]: 42318 : if (flags & IORESOURCE_MEM) {
194 : 1476 : dev->mem_resource[i].phys_addr = phys_addr;
195 : 1476 : dev->mem_resource[i].len = end_addr - phys_addr + 1;
196 : : /* not mapped for now */
197 : 1476 : dev->mem_resource[i].addr = NULL;
198 : : }
199 : : }
200 : 7053 : fclose(f);
201 : 7053 : return 0;
202 : :
203 : 0 : error:
204 : 0 : fclose(f);
205 : 0 : return -1;
206 : : }
207 : :
208 : : /* Scan one pci sysfs entry, and fill the devices list from it. */
209 : : static int
210 : 7053 : pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
211 : : {
212 : : char filename[PATH_MAX];
213 : : unsigned long tmp;
214 : : struct rte_pci_device_internal *pdev;
215 : : struct rte_pci_device *dev;
216 : : char driver[PATH_MAX];
217 : : int ret;
218 : :
219 : 7053 : pdev = malloc(sizeof(*pdev));
220 [ - + ]: 7053 : if (pdev == NULL) {
221 : 0 : RTE_LOG(ERR, EAL, "Cannot allocate memory for internal pci device\n");
222 : 0 : return -1;
223 : : }
224 : :
225 : : memset(pdev, 0, sizeof(*pdev));
226 : 7053 : dev = &pdev->device;
227 : 7053 : dev->device.bus = &rte_pci_bus.bus;
228 : 7053 : dev->addr = *addr;
229 : :
230 : : /* get vendor id */
231 : : snprintf(filename, sizeof(filename), "%s/vendor", dirname);
232 [ - + ]: 7053 : if (eal_parse_sysfs_value(filename, &tmp) < 0) {
233 : 0 : pci_free(pdev);
234 : 0 : return -1;
235 : : }
236 : 7053 : dev->id.vendor_id = (uint16_t)tmp;
237 : :
238 : : /* get device id */
239 : : snprintf(filename, sizeof(filename), "%s/device", dirname);
240 [ - + ]: 7053 : if (eal_parse_sysfs_value(filename, &tmp) < 0) {
241 : 0 : pci_free(pdev);
242 : 0 : return -1;
243 : : }
244 : 7053 : dev->id.device_id = (uint16_t)tmp;
245 : :
246 : : /* get subsystem_vendor id */
247 : : snprintf(filename, sizeof(filename), "%s/subsystem_vendor",
248 : : dirname);
249 [ - + ]: 7053 : if (eal_parse_sysfs_value(filename, &tmp) < 0) {
250 : 0 : pci_free(pdev);
251 : 0 : return -1;
252 : : }
253 : 7053 : dev->id.subsystem_vendor_id = (uint16_t)tmp;
254 : :
255 : : /* get subsystem_device id */
256 : : snprintf(filename, sizeof(filename), "%s/subsystem_device",
257 : : dirname);
258 [ - + ]: 7053 : if (eal_parse_sysfs_value(filename, &tmp) < 0) {
259 : 0 : pci_free(pdev);
260 : 0 : return -1;
261 : : }
262 : 7053 : dev->id.subsystem_device_id = (uint16_t)tmp;
263 : :
264 : : /* get class_id */
265 : : snprintf(filename, sizeof(filename), "%s/class",
266 : : dirname);
267 [ - + ]: 7053 : if (eal_parse_sysfs_value(filename, &tmp) < 0) {
268 : 0 : pci_free(pdev);
269 : 0 : return -1;
270 : : }
271 : : /* the least 24 bits are valid: class, subclass, program interface */
272 : 7053 : dev->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID;
273 : :
274 : : /* get max_vfs */
275 : 7053 : dev->max_vfs = 0;
276 : : snprintf(filename, sizeof(filename), "%s/max_vfs", dirname);
277 [ - + - - ]: 7053 : if (!access(filename, F_OK) &&
278 : 0 : eal_parse_sysfs_value(filename, &tmp) == 0)
279 : 0 : dev->max_vfs = (uint16_t)tmp;
280 : : else {
281 : : /* for non igb_uio driver, need kernel version >= 3.8 */
282 : : snprintf(filename, sizeof(filename),
283 : : "%s/sriov_numvfs", dirname);
284 [ - + - - ]: 7053 : if (!access(filename, F_OK) &&
285 : 0 : eal_parse_sysfs_value(filename, &tmp) == 0)
286 : 0 : dev->max_vfs = (uint16_t)tmp;
287 : : }
288 : :
289 : : /* get numa node, default to 0 if not present */
290 : : snprintf(filename, sizeof(filename), "%s/numa_node", dirname);
291 : :
292 [ + - + - ]: 14106 : if (access(filename, F_OK) == 0 &&
293 : 7053 : eal_parse_sysfs_value(filename, &tmp) == 0)
294 : 7053 : dev->device.numa_node = tmp;
295 : : else
296 : 0 : dev->device.numa_node = SOCKET_ID_ANY;
297 : :
298 : 7053 : pci_common_set(dev);
299 : :
300 : : /* parse resources */
301 : : snprintf(filename, sizeof(filename), "%s/resource", dirname);
302 [ - + ]: 7053 : if (pci_parse_sysfs_resource(filename, dev) < 0) {
303 : 0 : RTE_LOG(ERR, EAL, "%s(): cannot parse resource\n", __func__);
304 : 0 : pci_free(pdev);
305 : 0 : return -1;
306 : : }
307 : :
308 : : /* parse driver */
309 : : snprintf(filename, sizeof(filename), "%s/driver", dirname);
310 : 7053 : ret = pci_get_kernel_driver_by_path(filename, driver, sizeof(driver));
311 [ - + ]: 7053 : if (ret < 0) {
312 : 0 : RTE_LOG(ERR, EAL, "Fail to get kernel driver\n");
313 : 0 : pci_free(pdev);
314 : 0 : return -1;
315 : : }
316 : :
317 [ + + ]: 7053 : if (!ret) {
318 [ - + ]: 6397 : if (!strcmp(driver, "vfio-pci"))
319 : 0 : dev->kdrv = RTE_PCI_KDRV_VFIO;
320 [ - + ]: 6397 : else if (!strcmp(driver, "igb_uio"))
321 : 0 : dev->kdrv = RTE_PCI_KDRV_IGB_UIO;
322 [ - + ]: 6397 : else if (!strcmp(driver, "uio_pci_generic"))
323 : 0 : dev->kdrv = RTE_PCI_KDRV_UIO_GENERIC;
324 : : else
325 : 6397 : dev->kdrv = RTE_PCI_KDRV_UNKNOWN;
326 : : } else {
327 : 656 : pci_free(pdev);
328 : 656 : return 0;
329 : : }
330 : : /* device is valid, add in list (sorted) */
331 [ + + ]: 6397 : if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
332 : 165 : rte_pci_add_device(dev);
333 : : } else {
334 : : struct rte_pci_device *dev2;
335 : : int ret;
336 : :
337 [ + - ]: 64944 : TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
338 : 64944 : ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
339 [ + + ]: 64944 : if (ret > 0)
340 : : continue;
341 : :
342 [ + - ]: 6232 : if (ret < 0) {
343 : 6232 : rte_pci_insert_device(dev2, dev);
344 : : } else { /* already registered */
345 [ # # ]: 0 : if (!rte_dev_is_probed(&dev2->device)) {
346 : 0 : dev2->kdrv = dev->kdrv;
347 : 0 : dev2->max_vfs = dev->max_vfs;
348 : 0 : dev2->id = dev->id;
349 : 0 : pci_common_set(dev2);
350 : 0 : memmove(dev2->mem_resource,
351 : 0 : dev->mem_resource,
352 : : sizeof(dev->mem_resource));
353 : : } else {
354 : : /**
355 : : * If device is plugged and driver is
356 : : * probed already, (This happens when
357 : : * we call rte_dev_probe which will
358 : : * scan all device on the bus) we don't
359 : : * need to do anything here unless...
360 : : **/
361 [ # # ]: 0 : if (dev2->kdrv != dev->kdrv ||
362 : 0 : dev2->max_vfs != dev->max_vfs ||
363 [ # # ]: 0 : memcmp(&dev2->id, &dev->id, sizeof(dev2->id)))
364 : : /*
365 : : * This should not happens.
366 : : * But it is still possible if
367 : : * we unbind a device from
368 : : * vfio or uio before hotplug
369 : : * remove and rebind it with
370 : : * a different configure.
371 : : * So we just print out the
372 : : * error as an alarm.
373 : : */
374 : 0 : RTE_LOG(ERR, EAL, "Unexpected device scan at %s!\n",
375 : : filename);
376 : 0 : else if (dev2->device.devargs !=
377 [ # # ]: 0 : dev->device.devargs) {
378 : 0 : rte_devargs_remove(dev2->device.devargs);
379 : 0 : pci_common_set(dev2);
380 : : }
381 : : }
382 : 0 : pci_free(pdev);
383 : : }
384 : 6232 : return 0;
385 : : }
386 : :
387 : 0 : rte_pci_add_device(dev);
388 : : }
389 : :
390 : : return 0;
391 : : }
392 : :
393 : : /*
394 : : * split up a pci address into its constituent parts.
395 : : */
396 : : static int
397 : 7224 : parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
398 : : {
399 : : /* first split on ':' */
400 : : union splitaddr {
401 : : struct {
402 : : char *domain;
403 : : char *bus;
404 : : char *devid;
405 : : char *function;
406 : : };
407 : : char *str[PCI_FMT_NVAL]; /* last element-separator is "." not ":" */
408 : : } splitaddr;
409 : :
410 : 7224 : char *buf_copy = strndup(buf, bufsize);
411 [ + - ]: 7224 : if (buf_copy == NULL)
412 : : return -1;
413 : :
414 [ - + ]: 7224 : if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
415 : : != PCI_FMT_NVAL - 1)
416 : 0 : goto error;
417 : : /* final split is on '.' between devid and function */
418 : 7224 : splitaddr.function = strchr(splitaddr.devid,'.');
419 [ - + ]: 7224 : if (splitaddr.function == NULL)
420 : 0 : goto error;
421 : 7224 : *splitaddr.function++ = '\0';
422 : :
423 : : /* now convert to int values */
424 : 7224 : errno = 0;
425 : 7224 : addr->domain = strtoul(splitaddr.domain, NULL, 16);
426 : 7224 : addr->bus = strtoul(splitaddr.bus, NULL, 16);
427 : 7224 : addr->devid = strtoul(splitaddr.devid, NULL, 16);
428 : 7224 : addr->function = strtoul(splitaddr.function, NULL, 10);
429 [ - + ]: 7224 : if (errno != 0)
430 : 0 : goto error;
431 : :
432 : 7224 : free(buf_copy); /* free the copy made with strdup */
433 : 7224 : return 0;
434 : 0 : error:
435 : 0 : free(buf_copy);
436 : 0 : return -1;
437 : : }
438 : :
439 : : /*
440 : : * Scan the content of the PCI bus, and the devices in the devices
441 : : * list
442 : : */
443 : : int
444 : 169 : rte_pci_scan(void)
445 : : {
446 : : struct dirent *e;
447 : : DIR *dir;
448 : : char dirname[PATH_MAX];
449 : : struct rte_pci_addr addr;
450 : :
451 : : /* for debug purposes, PCI can be disabled */
452 [ + + ]: 169 : if (!rte_eal_has_pci())
453 : : return 0;
454 : :
455 : 168 : dir = opendir(rte_pci_get_sysfs_path());
456 [ - + ]: 168 : if (dir == NULL) {
457 : 0 : RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
458 : : __func__, strerror(errno));
459 : 0 : return -1;
460 : : }
461 : :
462 [ + + ]: 7728 : while ((e = readdir(dir)) != NULL) {
463 [ + + ]: 7560 : if (e->d_name[0] == '.')
464 : 336 : continue;
465 : :
466 [ - + ]: 7224 : if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &addr) != 0)
467 : 0 : continue;
468 : :
469 [ + + ]: 7224 : if (rte_pci_ignore_device(&addr))
470 : 171 : continue;
471 : :
472 : 7053 : snprintf(dirname, sizeof(dirname), "%s/%s",
473 : : rte_pci_get_sysfs_path(), e->d_name);
474 : :
475 [ - + ]: 7053 : if (pci_scan_one(dirname, &addr) < 0)
476 : 0 : goto error;
477 : : }
478 : 168 : closedir(dir);
479 : 168 : return 0;
480 : :
481 : : error:
482 : 0 : closedir(dir);
483 : 0 : return -1;
484 : : }
485 : :
486 : : #if defined(RTE_ARCH_X86)
487 : : bool
488 : 165 : pci_device_iommu_support_va(const struct rte_pci_device *dev)
489 : : {
490 : : #define VTD_CAP_MGAW_SHIFT 16
491 : : #define VTD_CAP_MGAW_MASK (0x3fULL << VTD_CAP_MGAW_SHIFT)
492 : : const struct rte_pci_addr *addr = &dev->addr;
493 : : char filename[PATH_MAX];
494 : : FILE *fp;
495 : 165 : uint64_t mgaw, vtd_cap_reg = 0;
496 : :
497 : 165 : snprintf(filename, sizeof(filename),
498 : : "%s/" PCI_PRI_FMT "/iommu/intel-iommu/cap",
499 : 165 : rte_pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
500 : 165 : addr->function);
501 : :
502 : 165 : fp = fopen(filename, "r");
503 [ + - ]: 165 : if (fp == NULL) {
504 : : /* We don't have an Intel IOMMU, assume VA supported */
505 [ - + ]: 165 : if (errno == ENOENT)
506 : : return true;
507 : :
508 : 0 : RTE_LOG(ERR, EAL, "%s(): can't open %s: %s\n",
509 : : __func__, filename, strerror(errno));
510 : 0 : return false;
511 : : }
512 : :
513 : : /* We have an Intel IOMMU */
514 [ # # ]: 0 : if (fscanf(fp, "%" PRIx64, &vtd_cap_reg) != 1) {
515 : 0 : RTE_LOG(ERR, EAL, "%s(): can't read %s\n", __func__, filename);
516 : 0 : fclose(fp);
517 : 0 : return false;
518 : : }
519 : :
520 : 0 : fclose(fp);
521 : :
522 : 0 : mgaw = ((vtd_cap_reg & VTD_CAP_MGAW_MASK) >> VTD_CAP_MGAW_SHIFT) + 1;
523 : :
524 : : /*
525 : : * Assuming there is no limitation by now. We can not know at this point
526 : : * because the memory has not been initialized yet. Setting the dma mask
527 : : * will force a check once memory initialization is done. We can not do
528 : : * a fallback to IOVA PA now, but if the dma check fails, the error
529 : : * message should advice for using '--iova-mode pa' if IOVA VA is the
530 : : * current mode.
531 : : */
532 : 0 : rte_mem_set_dma_mask(mgaw);
533 : 0 : return true;
534 : : }
535 : : #elif defined(RTE_ARCH_PPC_64)
536 : : bool
537 : : pci_device_iommu_support_va(__rte_unused const struct rte_pci_device *dev)
538 : : {
539 : : /*
540 : : * All POWER systems support an IOMMU, but only IOMMUv2 supports
541 : : * IOVA = VA in DPDK. Check contents of /proc/cpuinfo to find the
542 : : * system.
543 : : *
544 : : * Platform | Model | IOMMU | VA? | Comment
545 : : * ---------+-------+---------+-----+---------------------------------
546 : : * PowerNV | N/A | IOMMUv2 | Yes | OpenPOWER (Bare Metal)
547 : : * pSeries | ~qemu | IOMMUv2 | Yes | PowerVM Logical Partition (LPAR)
548 : : * pSeries | qemu | IOMMUv1 | No | QEMU Virtual Machine
549 : : */
550 : :
551 : : char *line = NULL;
552 : : size_t len = 0;
553 : : char filename[PATH_MAX] = "/proc/cpuinfo";
554 : : FILE *fp = fopen(filename, "r");
555 : : bool pseries = false, powernv = false, qemu = false;
556 : : bool ret = false;
557 : :
558 : : if (fp == NULL) {
559 : : RTE_LOG(ERR, EAL, "%s(): can't open %s: %s\n",
560 : : __func__, filename, strerror(errno));
561 : : return ret;
562 : : }
563 : :
564 : : /* Check the "platform" and "model" fields */
565 : : while (getline(&line, &len, fp) != -1) {
566 : : if (strstr(line, "platform") != NULL) {
567 : : if (strstr(line, "PowerNV") != NULL) {
568 : : RTE_LOG(DEBUG, EAL, "Running on a PowerNV platform\n");
569 : : powernv = true;
570 : : } else if (strstr(line, "pSeries") != NULL) {
571 : : RTE_LOG(DEBUG, EAL, "Running on a pSeries platform\n");
572 : : pseries = true;
573 : : }
574 : : } else if (strstr(line, "model") != NULL) {
575 : : if (strstr(line, "qemu") != NULL) {
576 : : RTE_LOG(DEBUG, EAL, "Found qemu emulation\n");
577 : : qemu = true;
578 : : }
579 : : }
580 : : }
581 : :
582 : : free(line);
583 : : fclose(fp);
584 : :
585 : : if (powernv || (pseries && !qemu))
586 : : ret = true;
587 : : return ret;
588 : : }
589 : : #else
590 : : bool
591 : : pci_device_iommu_support_va(__rte_unused const struct rte_pci_device *dev)
592 : : {
593 : : return true;
594 : : }
595 : : #endif
596 : :
597 : : enum rte_iova_mode
598 : 159 : pci_device_iova_mode(const struct rte_pci_driver *pdrv,
599 : : const struct rte_pci_device *pdev)
600 : : {
601 : : enum rte_iova_mode iova_mode = RTE_IOVA_DC;
602 : :
603 [ - + - ]: 159 : switch (pdev->kdrv) {
604 : 0 : case RTE_PCI_KDRV_VFIO: {
605 : : #ifdef VFIO_PRESENT
606 : : static int is_vfio_noiommu_enabled = -1;
607 : :
608 [ # # ]: 0 : if (is_vfio_noiommu_enabled == -1) {
609 [ # # ]: 0 : if (rte_vfio_noiommu_is_enabled() == 1)
610 : 0 : is_vfio_noiommu_enabled = 1;
611 : : else
612 : 0 : is_vfio_noiommu_enabled = 0;
613 : : }
614 [ # # ]: 0 : if (is_vfio_noiommu_enabled != 0)
615 : : iova_mode = RTE_IOVA_PA;
616 [ # # ]: 0 : else if ((pdrv->drv_flags & RTE_PCI_DRV_NEED_IOVA_AS_VA) != 0)
617 : : iova_mode = RTE_IOVA_VA;
618 : : #endif
619 : : break;
620 : : }
621 : :
622 : : case RTE_PCI_KDRV_IGB_UIO:
623 : : case RTE_PCI_KDRV_UIO_GENERIC:
624 : : iova_mode = RTE_IOVA_PA;
625 : : break;
626 : :
627 : 159 : default:
628 [ - + ]: 159 : if ((pdrv->drv_flags & RTE_PCI_DRV_NEED_IOVA_AS_VA) != 0)
629 : : iova_mode = RTE_IOVA_VA;
630 : : break;
631 : : }
632 : 159 : return iova_mode;
633 : : }
634 : :
635 : : /* Read PCI config space. */
636 : 0 : int rte_pci_read_config(const struct rte_pci_device *device,
637 : : void *buf, size_t len, off_t offset)
638 : : {
639 : 0 : char devname[RTE_DEV_NAME_MAX_LEN] = "";
640 : 0 : const struct rte_intr_handle *intr_handle = device->intr_handle;
641 : :
642 [ # # # ]: 0 : switch (device->kdrv) {
643 : 0 : case RTE_PCI_KDRV_IGB_UIO:
644 : : case RTE_PCI_KDRV_UIO_GENERIC:
645 : 0 : return pci_uio_read_config(intr_handle, buf, len, offset);
646 : : #ifdef VFIO_PRESENT
647 : 0 : case RTE_PCI_KDRV_VFIO:
648 : 0 : return pci_vfio_read_config(device, buf, len, offset);
649 : : #endif
650 : 0 : default:
651 : 0 : rte_pci_device_name(&device->addr, devname,
652 : : RTE_DEV_NAME_MAX_LEN);
653 : 0 : RTE_LOG(ERR, EAL,
654 : : "Unknown driver type for %s\n", devname);
655 : 0 : return -1;
656 : : }
657 : : }
658 : :
659 : : /* Write PCI config space. */
660 : 0 : int rte_pci_write_config(const struct rte_pci_device *device,
661 : : const void *buf, size_t len, off_t offset)
662 : : {
663 : 0 : char devname[RTE_DEV_NAME_MAX_LEN] = "";
664 : 0 : const struct rte_intr_handle *intr_handle = device->intr_handle;
665 : :
666 [ # # # ]: 0 : switch (device->kdrv) {
667 : 0 : case RTE_PCI_KDRV_IGB_UIO:
668 : : case RTE_PCI_KDRV_UIO_GENERIC:
669 : 0 : return pci_uio_write_config(intr_handle, buf, len, offset);
670 : : #ifdef VFIO_PRESENT
671 : 0 : case RTE_PCI_KDRV_VFIO:
672 : 0 : return pci_vfio_write_config(device, buf, len, offset);
673 : : #endif
674 : 0 : default:
675 : 0 : rte_pci_device_name(&device->addr, devname,
676 : : RTE_DEV_NAME_MAX_LEN);
677 : 0 : RTE_LOG(ERR, EAL,
678 : : "Unknown driver type for %s\n", devname);
679 : 0 : return -1;
680 : : }
681 : : }
682 : :
683 : : /* Read PCI MMIO space. */
684 : 0 : int rte_pci_mmio_read(const struct rte_pci_device *device, int bar,
685 : : void *buf, size_t len, off_t offset)
686 : : {
687 : 0 : char devname[RTE_DEV_NAME_MAX_LEN] = "";
688 : :
689 [ # # # ]: 0 : switch (device->kdrv) {
690 : 0 : case RTE_PCI_KDRV_IGB_UIO:
691 : : case RTE_PCI_KDRV_UIO_GENERIC:
692 : 0 : return pci_uio_mmio_read(device, bar, buf, len, offset);
693 : : #ifdef VFIO_PRESENT
694 : 0 : case RTE_PCI_KDRV_VFIO:
695 : 0 : return pci_vfio_mmio_read(device, bar, buf, len, offset);
696 : : #endif
697 : 0 : default:
698 : 0 : rte_pci_device_name(&device->addr, devname,
699 : : RTE_DEV_NAME_MAX_LEN);
700 : 0 : RTE_LOG(ERR, EAL,
701 : : "Unknown driver type for %s\n", devname);
702 : 0 : return -1;
703 : : }
704 : : }
705 : :
706 : : /* Write PCI MMIO space. */
707 : 0 : int rte_pci_mmio_write(const struct rte_pci_device *device, int bar,
708 : : const void *buf, size_t len, off_t offset)
709 : : {
710 : 0 : char devname[RTE_DEV_NAME_MAX_LEN] = "";
711 : :
712 [ # # # ]: 0 : switch (device->kdrv) {
713 : 0 : case RTE_PCI_KDRV_IGB_UIO:
714 : : case RTE_PCI_KDRV_UIO_GENERIC:
715 : 0 : return pci_uio_mmio_write(device, bar, buf, len, offset);
716 : : #ifdef VFIO_PRESENT
717 : 0 : case RTE_PCI_KDRV_VFIO:
718 : 0 : return pci_vfio_mmio_write(device, bar, buf, len, offset);
719 : : #endif
720 : 0 : default:
721 : 0 : rte_pci_device_name(&device->addr, devname,
722 : : RTE_DEV_NAME_MAX_LEN);
723 : 0 : RTE_LOG(ERR, EAL,
724 : : "Unknown driver type for %s\n", devname);
725 : 0 : return -1;
726 : : }
727 : : }
728 : :
729 : : int
730 : 0 : rte_pci_ioport_map(struct rte_pci_device *dev, int bar,
731 : : struct rte_pci_ioport *p)
732 : : {
733 : : int ret = -1;
734 : :
735 [ # # # ]: 0 : switch (dev->kdrv) {
736 : : #ifdef VFIO_PRESENT
737 : 0 : case RTE_PCI_KDRV_VFIO:
738 [ # # ]: 0 : if (pci_vfio_is_enabled())
739 : 0 : ret = pci_vfio_ioport_map(dev, bar, p);
740 : : break;
741 : : #endif
742 : 0 : case RTE_PCI_KDRV_IGB_UIO:
743 : : case RTE_PCI_KDRV_UIO_GENERIC:
744 : 0 : ret = pci_uio_ioport_map(dev, bar, p);
745 : 0 : break;
746 : : default:
747 : : break;
748 : : }
749 : :
750 [ # # ]: 0 : if (!ret)
751 : 0 : p->dev = dev;
752 : :
753 : 0 : return ret;
754 : : }
755 : :
756 : : void
757 : 0 : rte_pci_ioport_read(struct rte_pci_ioport *p,
758 : : void *data, size_t len, off_t offset)
759 : : {
760 [ # # # ]: 0 : switch (p->dev->kdrv) {
761 : : #ifdef VFIO_PRESENT
762 : 0 : case RTE_PCI_KDRV_VFIO:
763 : 0 : pci_vfio_ioport_read(p, data, len, offset);
764 : 0 : break;
765 : : #endif
766 : 0 : case RTE_PCI_KDRV_IGB_UIO:
767 : : case RTE_PCI_KDRV_UIO_GENERIC:
768 : 0 : pci_uio_ioport_read(p, data, len, offset);
769 : 0 : break;
770 : : default:
771 : : break;
772 : : }
773 : 0 : }
774 : :
775 : : void
776 : 0 : rte_pci_ioport_write(struct rte_pci_ioport *p,
777 : : const void *data, size_t len, off_t offset)
778 : : {
779 [ # # # ]: 0 : switch (p->dev->kdrv) {
780 : : #ifdef VFIO_PRESENT
781 : 0 : case RTE_PCI_KDRV_VFIO:
782 : 0 : pci_vfio_ioport_write(p, data, len, offset);
783 : 0 : break;
784 : : #endif
785 : 0 : case RTE_PCI_KDRV_IGB_UIO:
786 : : case RTE_PCI_KDRV_UIO_GENERIC:
787 : 0 : pci_uio_ioport_write(p, data, len, offset);
788 : 0 : break;
789 : : default:
790 : : break;
791 : : }
792 : 0 : }
793 : :
794 : : int
795 : 0 : rte_pci_ioport_unmap(struct rte_pci_ioport *p)
796 : : {
797 : : int ret = -1;
798 : :
799 [ # # # ]: 0 : switch (p->dev->kdrv) {
800 : : #ifdef VFIO_PRESENT
801 : 0 : case RTE_PCI_KDRV_VFIO:
802 [ # # ]: 0 : if (pci_vfio_is_enabled())
803 : 0 : ret = pci_vfio_ioport_unmap(p);
804 : : break;
805 : : #endif
806 : 0 : case RTE_PCI_KDRV_IGB_UIO:
807 : : case RTE_PCI_KDRV_UIO_GENERIC:
808 : 0 : ret = pci_uio_ioport_unmap(p);
809 : 0 : break;
810 : : default:
811 : : break;
812 : : }
813 : :
814 : 0 : return ret;
815 : : }
|