11306a73bSElena Agostini /* SPDX-License-Identifier: BSD-3-Clause
21306a73bSElena Agostini * Copyright (c) 2021 NVIDIA Corporation & Affiliates
31306a73bSElena Agostini */
41306a73bSElena Agostini
51306a73bSElena Agostini #include <dlfcn.h>
61306a73bSElena Agostini
71306a73bSElena Agostini #include <rte_malloc.h>
81306a73bSElena Agostini #include <rte_pci.h>
91f37cb2bSDavid Marchand #include <bus_pci_driver.h>
101306a73bSElena Agostini #include <rte_byteorder.h>
11*1acb7f54SDavid Marchand #include <dev_driver.h>
121306a73bSElena Agostini
131306a73bSElena Agostini #include <gpudev_driver.h>
1424c77594SElena Agostini
151306a73bSElena Agostini #include <cuda.h>
161306a73bSElena Agostini #include <cudaTypedefs.h>
171306a73bSElena Agostini
1824c77594SElena Agostini #include "common.h"
197850d19fSElena Agostini #include "devices.h"
2024c77594SElena Agostini
211306a73bSElena Agostini #define CUDA_DRIVER_MIN_VERSION 11040
221306a73bSElena Agostini #define CUDA_API_MIN_VERSION 3020
231306a73bSElena Agostini
241306a73bSElena Agostini /* CUDA Driver functions loaded with dlsym() */
251306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuInit)(unsigned int flags);
261306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuDriverGetVersion)(int *driverVersion);
271306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuGetProcAddress)(const char *symbol,
281306a73bSElena Agostini void **pfn, int cudaVersion, uint64_t flags);
291306a73bSElena Agostini
301306a73bSElena Agostini /* CUDA Driver functions loaded with cuGetProcAddress for versioning */
311306a73bSElena Agostini static PFN_cuGetErrorString pfn_cuGetErrorString;
321306a73bSElena Agostini static PFN_cuGetErrorName pfn_cuGetErrorName;
331306a73bSElena Agostini static PFN_cuPointerSetAttribute pfn_cuPointerSetAttribute;
341306a73bSElena Agostini static PFN_cuDeviceGetAttribute pfn_cuDeviceGetAttribute;
351306a73bSElena Agostini static PFN_cuDeviceGetByPCIBusId pfn_cuDeviceGetByPCIBusId;
361306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRetain pfn_cuDevicePrimaryCtxRetain;
371306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRelease pfn_cuDevicePrimaryCtxRelease;
381306a73bSElena Agostini static PFN_cuDeviceTotalMem pfn_cuDeviceTotalMem;
391306a73bSElena Agostini static PFN_cuDeviceGetName pfn_cuDeviceGetName;
401306a73bSElena Agostini static PFN_cuCtxGetApiVersion pfn_cuCtxGetApiVersion;
411306a73bSElena Agostini static PFN_cuCtxSetCurrent pfn_cuCtxSetCurrent;
421306a73bSElena Agostini static PFN_cuCtxGetCurrent pfn_cuCtxGetCurrent;
431306a73bSElena Agostini static PFN_cuCtxGetDevice pfn_cuCtxGetDevice;
441306a73bSElena Agostini static PFN_cuCtxGetExecAffinity pfn_cuCtxGetExecAffinity;
451306a73bSElena Agostini static PFN_cuMemAlloc pfn_cuMemAlloc;
461306a73bSElena Agostini static PFN_cuMemFree pfn_cuMemFree;
471306a73bSElena Agostini static PFN_cuMemHostRegister pfn_cuMemHostRegister;
481306a73bSElena Agostini static PFN_cuMemHostUnregister pfn_cuMemHostUnregister;
491306a73bSElena Agostini static PFN_cuMemHostGetDevicePointer pfn_cuMemHostGetDevicePointer;
501306a73bSElena Agostini static PFN_cuFlushGPUDirectRDMAWrites pfn_cuFlushGPUDirectRDMAWrites;
511306a73bSElena Agostini
521306a73bSElena Agostini static void *cudalib;
531306a73bSElena Agostini static unsigned int cuda_api_version;
541306a73bSElena Agostini static int cuda_driver_version;
5524c77594SElena Agostini static gdr_t gdrc_h;
561306a73bSElena Agostini
571306a73bSElena Agostini #define CUDA_MAX_ALLOCATION_NUM 512
581306a73bSElena Agostini
591306a73bSElena Agostini #define GPU_PAGE_SHIFT 16
601306a73bSElena Agostini #define GPU_PAGE_SIZE (1UL << GPU_PAGE_SHIFT)
611306a73bSElena Agostini
6224c77594SElena Agostini RTE_LOG_REGISTER_DEFAULT(cuda_logtype, NOTICE);
631306a73bSElena Agostini
641306a73bSElena Agostini /* NVIDIA GPU address map */
651306a73bSElena Agostini static const struct rte_pci_id pci_id_cuda_map[] = {
661306a73bSElena Agostini {
671306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
687850d19fSElena Agostini NVIDIA_GPU_A40_DEVICE_ID)
6965ac1464SElena Agostini },
7065ac1464SElena Agostini {
7165ac1464SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
721306a73bSElena Agostini NVIDIA_GPU_A30_24GB_DEVICE_ID)
731306a73bSElena Agostini },
741306a73bSElena Agostini {
751306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
767850d19fSElena Agostini NVIDIA_GPU_A30X_24GB_DPU_DEVICE_ID)
77442876b2SElena Agostini },
78442876b2SElena Agostini {
79442876b2SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
801306a73bSElena Agostini NVIDIA_GPU_A10_24GB_DEVICE_ID)
811306a73bSElena Agostini },
821306a73bSElena Agostini {
831306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
847850d19fSElena Agostini NVIDIA_GPU_A10G_DEVICE_ID)
857850d19fSElena Agostini },
867850d19fSElena Agostini {
877850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
887850d19fSElena Agostini NVIDIA_GPU_A10M_DEVICE_ID)
897850d19fSElena Agostini },
907850d19fSElena Agostini {
917850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
927850d19fSElena Agostini NVIDIA_GPU_A100_40GB_SXM4_DEVICE_ID)
937850d19fSElena Agostini },
947850d19fSElena Agostini {
957850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
967850d19fSElena Agostini NVIDIA_GPU_A100_40GB_PCIE_DEVICE_ID)
977850d19fSElena Agostini },
987850d19fSElena Agostini {
997850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1007850d19fSElena Agostini NVIDIA_GPU_A100_80GB_SXM4_DEVICE_ID)
1017850d19fSElena Agostini },
1027850d19fSElena Agostini {
1037850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1047850d19fSElena Agostini NVIDIA_GPU_A100_80GB_PCIE_DEVICE_ID)
1057850d19fSElena Agostini },
1067850d19fSElena Agostini {
1077850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1087850d19fSElena Agostini NVIDIA_GPU_A100X_80GB_DPU_DEVICE_ID)
1097850d19fSElena Agostini },
1107850d19fSElena Agostini {
1117850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1127850d19fSElena Agostini NVIDIA_GPU_GA100_PG506_207)
1137850d19fSElena Agostini },
1147850d19fSElena Agostini {
1157850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1167850d19fSElena Agostini NVIDIA_GPU_GA100_PCIE)
1177850d19fSElena Agostini },
1187850d19fSElena Agostini {
1197850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1207850d19fSElena Agostini NVIDIA_GPU_GA100_PG506_217)
1217850d19fSElena Agostini },
1227850d19fSElena Agostini {
1237850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1247850d19fSElena Agostini NVIDIA_GPU_V100_16GB_SXM2_DEVICE_ID)
1257850d19fSElena Agostini },
1267850d19fSElena Agostini {
1277850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1287850d19fSElena Agostini NVIDIA_GPU_V100_16GB_DGXS_DEVICE_ID)
1297850d19fSElena Agostini },
1307850d19fSElena Agostini {
1317850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1327850d19fSElena Agostini NVIDIA_GPU_V100_16GB_FHHL_DEVICE_ID)
1337850d19fSElena Agostini },
1347850d19fSElena Agostini {
1357850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1367850d19fSElena Agostini NVIDIA_GPU_V100_16GB_PCIE_DEVICE_ID)
1377850d19fSElena Agostini },
1387850d19fSElena Agostini {
1397850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1407850d19fSElena Agostini NVIDIA_GPU_V100_32GB_SXM2_DEVICE_ID)
14156b5bb50SElena Agostini },
14256b5bb50SElena Agostini {
14356b5bb50SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
14456b5bb50SElena Agostini NVIDIA_GPU_V100_32GB_PCIE_DEVICE_ID)
1451306a73bSElena Agostini },
1461306a73bSElena Agostini {
1471306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1487850d19fSElena Agostini NVIDIA_GPU_V100_32GB_DGXS_DEVICE_ID)
1491306a73bSElena Agostini },
1501306a73bSElena Agostini {
1511306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1527850d19fSElena Agostini NVIDIA_GPU_V100_32GB_SXM3_DEVICE_ID)
1537850d19fSElena Agostini },
1547850d19fSElena Agostini {
1557850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1567850d19fSElena Agostini NVIDIA_GPU_V100_32GB_SXM3_H_DEVICE_ID)
1577850d19fSElena Agostini },
1587850d19fSElena Agostini {
1597850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1607850d19fSElena Agostini NVIDIA_GPU_V100_SXM2)
1617850d19fSElena Agostini },
1627850d19fSElena Agostini {
1637850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1647850d19fSElena Agostini NVIDIA_GPU_V100S_PCIE)
1657850d19fSElena Agostini },
1667850d19fSElena Agostini {
1677850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1687850d19fSElena Agostini NVIDIA_GPU_TITAN_V_CEO_ED)
1697850d19fSElena Agostini },
1707850d19fSElena Agostini {
1717850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1727850d19fSElena Agostini NVIDIA_GPU_GV100GL_PG500_216)
1737850d19fSElena Agostini },
1747850d19fSElena Agostini {
1757850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1767850d19fSElena Agostini NVIDIA_GPU_GV100GL_PG503_216)
1777850d19fSElena Agostini },
1787850d19fSElena Agostini {
1797850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1807850d19fSElena Agostini NVIDIA_GPU_TU102_TITAN_RTX)
1817850d19fSElena Agostini },
1827850d19fSElena Agostini {
1837850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1847850d19fSElena Agostini NVIDIA_GPU_TU102GL_QUADRO_RTX)
1857850d19fSElena Agostini },
1867850d19fSElena Agostini {
1877850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1887850d19fSElena Agostini NVIDIA_GPU_GV100_QUADRO_DEVICE_ID)
1897850d19fSElena Agostini },
1907850d19fSElena Agostini {
1917850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1927850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_4000)
1937850d19fSElena Agostini },
1947850d19fSElena Agostini {
1957850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
1967850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_5000)
1977850d19fSElena Agostini },
1987850d19fSElena Agostini {
1997850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2007850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_6000)
2017850d19fSElena Agostini },
2027850d19fSElena Agostini {
2037850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2047850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_8000)
2057850d19fSElena Agostini },
2067850d19fSElena Agostini {
2077850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2087850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A4000)
2097850d19fSElena Agostini },
2107850d19fSElena Agostini {
2117850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2127850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A6000)
2137850d19fSElena Agostini },
2147850d19fSElena Agostini {
2157850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2167850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A5000)
2177850d19fSElena Agostini },
2187850d19fSElena Agostini {
2197850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2207850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A4500)
2217850d19fSElena Agostini },
2227850d19fSElena Agostini {
2237850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2247850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A5500)
2257850d19fSElena Agostini },
2267850d19fSElena Agostini {
2277850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2287850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A2000)
2297850d19fSElena Agostini },
2307850d19fSElena Agostini {
2317850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2327850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A2000_12GB)
2337850d19fSElena Agostini },
2347850d19fSElena Agostini {
2357850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2367850d19fSElena Agostini NVIDIA_GPU_T4G)
2377850d19fSElena Agostini },
2387850d19fSElena Agostini {
2397850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID,
2407850d19fSElena Agostini NVIDIA_GPU_T4)
2411306a73bSElena Agostini },
2421306a73bSElena Agostini {
2431306a73bSElena Agostini .device_id = 0
2441306a73bSElena Agostini }
2451306a73bSElena Agostini };
2461306a73bSElena Agostini
2471306a73bSElena Agostini /* Device private info */
2481306a73bSElena Agostini struct cuda_info {
2491306a73bSElena Agostini char gpu_name[RTE_DEV_NAME_MAX_LEN];
2501306a73bSElena Agostini CUdevice cu_dev;
2511306a73bSElena Agostini int gdr_supported;
2521306a73bSElena Agostini int gdr_write_ordering;
2531306a73bSElena Agostini int gdr_flush_type;
2541306a73bSElena Agostini };
2551306a73bSElena Agostini
2561306a73bSElena Agostini /* Type of memory allocated by CUDA driver */
2571306a73bSElena Agostini enum mem_type {
2581306a73bSElena Agostini GPU_MEM = 0,
2591306a73bSElena Agostini CPU_REGISTERED,
2600354e8e8SElena Agostini GPU_REGISTERED
2611306a73bSElena Agostini };
2621306a73bSElena Agostini
2631306a73bSElena Agostini /* key associated to a memory address */
2641306a73bSElena Agostini typedef uintptr_t cuda_ptr_key;
2651306a73bSElena Agostini
2661306a73bSElena Agostini /* Single entry of the memory list */
2671306a73bSElena Agostini struct mem_entry {
2681306a73bSElena Agostini CUdeviceptr ptr_d;
269c8557ed4SElena Agostini CUdeviceptr ptr_orig_d;
2701306a73bSElena Agostini void *ptr_h;
2711306a73bSElena Agostini size_t size;
272c8557ed4SElena Agostini size_t size_orig;
2731306a73bSElena Agostini struct rte_gpu *dev;
2741306a73bSElena Agostini CUcontext ctx;
2751306a73bSElena Agostini cuda_ptr_key pkey;
2761306a73bSElena Agostini enum mem_type mtype;
27724c77594SElena Agostini gdr_mh_t mh;
2781306a73bSElena Agostini struct mem_entry *prev;
2791306a73bSElena Agostini struct mem_entry *next;
2801306a73bSElena Agostini };
2811306a73bSElena Agostini
2821306a73bSElena Agostini static struct mem_entry *mem_alloc_list_head;
2831306a73bSElena Agostini static struct mem_entry *mem_alloc_list_tail;
2841306a73bSElena Agostini static uint32_t mem_alloc_list_last_elem;
2851306a73bSElena Agostini
2861306a73bSElena Agostini /* Load the CUDA symbols */
2871306a73bSElena Agostini
2881306a73bSElena Agostini static int
cuda_loader(void)2891306a73bSElena Agostini cuda_loader(void)
2901306a73bSElena Agostini {
2911306a73bSElena Agostini char cuda_path[1024];
2921306a73bSElena Agostini
2931306a73bSElena Agostini if (getenv("CUDA_PATH_L") == NULL)
2941306a73bSElena Agostini snprintf(cuda_path, 1024, "%s", "libcuda.so");
2951306a73bSElena Agostini else
2960105d49eSElena Agostini snprintf(cuda_path, 1024, "%s/%s", getenv("CUDA_PATH_L"), "libcuda.so");
2971306a73bSElena Agostini
2981306a73bSElena Agostini cudalib = dlopen(cuda_path, RTLD_LAZY);
2991306a73bSElena Agostini if (cudalib == NULL) {
3001306a73bSElena Agostini rte_cuda_log(ERR, "Failed to find CUDA library in %s (CUDA_PATH_L=%s)",
3011306a73bSElena Agostini cuda_path, getenv("CUDA_PATH_L"));
3021306a73bSElena Agostini return -1;
3031306a73bSElena Agostini }
3041306a73bSElena Agostini
3051306a73bSElena Agostini return 0;
3061306a73bSElena Agostini }
3071306a73bSElena Agostini
3081306a73bSElena Agostini static int
cuda_sym_func_loader(void)3091306a73bSElena Agostini cuda_sym_func_loader(void)
3101306a73bSElena Agostini {
3111306a73bSElena Agostini if (cudalib == NULL)
3121306a73bSElena Agostini return -1;
3131306a73bSElena Agostini
3141306a73bSElena Agostini sym_cuInit = dlsym(cudalib, "cuInit");
3151306a73bSElena Agostini if (sym_cuInit == NULL) {
3161306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuInit");
3171306a73bSElena Agostini return -1;
3181306a73bSElena Agostini }
3191306a73bSElena Agostini
3201306a73bSElena Agostini sym_cuDriverGetVersion = dlsym(cudalib, "cuDriverGetVersion");
3211306a73bSElena Agostini if (sym_cuDriverGetVersion == NULL) {
3221306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuDriverGetVersion");
3231306a73bSElena Agostini return -1;
3241306a73bSElena Agostini }
3251306a73bSElena Agostini
3261306a73bSElena Agostini sym_cuGetProcAddress = dlsym(cudalib, "cuGetProcAddress");
3271306a73bSElena Agostini if (sym_cuGetProcAddress == NULL) {
3281306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuGetProcAddress");
3291306a73bSElena Agostini return -1;
3301306a73bSElena Agostini }
3311306a73bSElena Agostini
3321306a73bSElena Agostini return 0;
3331306a73bSElena Agostini }
3341306a73bSElena Agostini
3351306a73bSElena Agostini static int
cuda_pfn_func_loader(void)3361306a73bSElena Agostini cuda_pfn_func_loader(void)
3371306a73bSElena Agostini {
3381306a73bSElena Agostini CUresult res;
3391306a73bSElena Agostini
3401306a73bSElena Agostini res = sym_cuGetProcAddress("cuGetErrorString",
3411306a73bSElena Agostini (void **) (&pfn_cuGetErrorString), cuda_driver_version, 0);
3421306a73bSElena Agostini if (res != 0) {
3431306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorString failed with %d", res);
3441306a73bSElena Agostini return -1;
3451306a73bSElena Agostini }
3461306a73bSElena Agostini
3471306a73bSElena Agostini res = sym_cuGetProcAddress("cuGetErrorName",
3481306a73bSElena Agostini (void **)(&pfn_cuGetErrorName), cuda_driver_version, 0);
3491306a73bSElena Agostini if (res != 0) {
3501306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorName failed with %d", res);
3511306a73bSElena Agostini return -1;
3521306a73bSElena Agostini }
3531306a73bSElena Agostini
3541306a73bSElena Agostini res = sym_cuGetProcAddress("cuPointerSetAttribute",
3551306a73bSElena Agostini (void **)(&pfn_cuPointerSetAttribute), cuda_driver_version, 0);
3561306a73bSElena Agostini if (res != 0) {
3571306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuPointerSetAttribute failed with %d", res);
3581306a73bSElena Agostini return -1;
3591306a73bSElena Agostini }
3601306a73bSElena Agostini
3611306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetAttribute",
3621306a73bSElena Agostini (void **)(&pfn_cuDeviceGetAttribute), cuda_driver_version, 0);
3631306a73bSElena Agostini if (res != 0) {
3641306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetAttribute failed with %d", res);
3651306a73bSElena Agostini return -1;
3661306a73bSElena Agostini }
3671306a73bSElena Agostini
3681306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetByPCIBusId",
3691306a73bSElena Agostini (void **)(&pfn_cuDeviceGetByPCIBusId), cuda_driver_version, 0);
3701306a73bSElena Agostini if (res != 0) {
3711306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetByPCIBusId failed with %d", res);
3721306a73bSElena Agostini return -1;
3731306a73bSElena Agostini }
3741306a73bSElena Agostini
3751306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetName",
3761306a73bSElena Agostini (void **)(&pfn_cuDeviceGetName), cuda_driver_version, 0);
3771306a73bSElena Agostini if (res != 0) {
3781306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetName failed with %d", res);
3791306a73bSElena Agostini return -1;
3801306a73bSElena Agostini }
3811306a73bSElena Agostini
3821306a73bSElena Agostini res = sym_cuGetProcAddress("cuDevicePrimaryCtxRetain",
3831306a73bSElena Agostini (void **)(&pfn_cuDevicePrimaryCtxRetain), cuda_driver_version, 0);
3841306a73bSElena Agostini if (res != 0) {
3851306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRetain failed with %d", res);
3861306a73bSElena Agostini return -1;
3871306a73bSElena Agostini }
3881306a73bSElena Agostini
3891306a73bSElena Agostini res = sym_cuGetProcAddress("cuDevicePrimaryCtxRelease",
3901306a73bSElena Agostini (void **)(&pfn_cuDevicePrimaryCtxRelease), cuda_driver_version, 0);
3911306a73bSElena Agostini if (res != 0) {
3921306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRelease failed with %d", res);
3931306a73bSElena Agostini return -1;
3941306a73bSElena Agostini }
3951306a73bSElena Agostini
3961306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceTotalMem",
3971306a73bSElena Agostini (void **)(&pfn_cuDeviceTotalMem), cuda_driver_version, 0);
3981306a73bSElena Agostini if (res != 0) {
3991306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceTotalMem failed with %d", res);
4001306a73bSElena Agostini return -1;
4011306a73bSElena Agostini }
4021306a73bSElena Agostini
4031306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetApiVersion",
4041306a73bSElena Agostini (void **)(&pfn_cuCtxGetApiVersion), cuda_driver_version, 0);
4051306a73bSElena Agostini if (res != 0) {
4061306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetApiVersion failed with %d", res);
4071306a73bSElena Agostini return -1;
4081306a73bSElena Agostini }
4091306a73bSElena Agostini
4101306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetDevice",
4111306a73bSElena Agostini (void **)(&pfn_cuCtxGetDevice), cuda_driver_version, 0);
4121306a73bSElena Agostini if (res != 0) {
4131306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetDevice failed with %d", res);
4141306a73bSElena Agostini return -1;
4151306a73bSElena Agostini }
4161306a73bSElena Agostini
4171306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxSetCurrent",
4181306a73bSElena Agostini (void **)(&pfn_cuCtxSetCurrent), cuda_driver_version, 0);
4191306a73bSElena Agostini if (res != 0) {
4201306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxSetCurrent failed with %d", res);
4211306a73bSElena Agostini return -1;
4221306a73bSElena Agostini }
4231306a73bSElena Agostini
4241306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetCurrent",
4251306a73bSElena Agostini (void **)(&pfn_cuCtxGetCurrent), cuda_driver_version, 0);
4261306a73bSElena Agostini if (res != 0) {
4271306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetCurrent failed with %d", res);
4281306a73bSElena Agostini return -1;
4291306a73bSElena Agostini }
4301306a73bSElena Agostini
4311306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetExecAffinity",
4321306a73bSElena Agostini (void **)(&pfn_cuCtxGetExecAffinity), cuda_driver_version, 0);
4331306a73bSElena Agostini if (res != 0) {
4341306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetExecAffinity failed with %d", res);
4351306a73bSElena Agostini return -1;
4361306a73bSElena Agostini }
4371306a73bSElena Agostini
4381306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemAlloc",
4391306a73bSElena Agostini (void **)(&pfn_cuMemAlloc), cuda_driver_version, 0);
4401306a73bSElena Agostini if (res != 0) {
4411306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemAlloc failed with %d", res);
4421306a73bSElena Agostini return -1;
4431306a73bSElena Agostini }
4441306a73bSElena Agostini
4451306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemFree",
4461306a73bSElena Agostini (void **)(&pfn_cuMemFree), cuda_driver_version, 0);
4471306a73bSElena Agostini if (res != 0) {
4481306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemFree failed with %d", res);
4491306a73bSElena Agostini return -1;
4501306a73bSElena Agostini }
4511306a73bSElena Agostini
4521306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostRegister",
4531306a73bSElena Agostini (void **)(&pfn_cuMemHostRegister), cuda_driver_version, 0);
4541306a73bSElena Agostini if (res != 0) {
4551306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostRegister failed with %d", res);
4561306a73bSElena Agostini return -1;
4571306a73bSElena Agostini }
4581306a73bSElena Agostini
4591306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostUnregister",
4601306a73bSElena Agostini (void **)(&pfn_cuMemHostUnregister), cuda_driver_version, 0);
4611306a73bSElena Agostini if (res != 0) {
4621306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostUnregister failed with %d", res);
4631306a73bSElena Agostini return -1;
4641306a73bSElena Agostini }
4651306a73bSElena Agostini
4661306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostGetDevicePointer",
4671306a73bSElena Agostini (void **)(&pfn_cuMemHostGetDevicePointer), cuda_driver_version, 0);
4681306a73bSElena Agostini if (res != 0) {
4691306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostGetDevicePointer failed with %d", res);
4701306a73bSElena Agostini return -1;
4711306a73bSElena Agostini }
4721306a73bSElena Agostini
4731306a73bSElena Agostini res = sym_cuGetProcAddress("cuFlushGPUDirectRDMAWrites",
4741306a73bSElena Agostini (void **)(&pfn_cuFlushGPUDirectRDMAWrites), cuda_driver_version, 0);
4751306a73bSElena Agostini if (res != 0) {
4761306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve cuFlushGPUDirectRDMAWrites failed with %d", res);
4771306a73bSElena Agostini return -1;
4781306a73bSElena Agostini }
4791306a73bSElena Agostini
4801306a73bSElena Agostini return 0;
4811306a73bSElena Agostini }
4821306a73bSElena Agostini
4831306a73bSElena Agostini /* Generate a key from a memory pointer */
4841306a73bSElena Agostini static cuda_ptr_key
get_hash_from_ptr(void * ptr)4851306a73bSElena Agostini get_hash_from_ptr(void *ptr)
4861306a73bSElena Agostini {
4871306a73bSElena Agostini return (uintptr_t)ptr;
4881306a73bSElena Agostini }
4891306a73bSElena Agostini
4901306a73bSElena Agostini static uint32_t
mem_list_count_item(void)4911306a73bSElena Agostini mem_list_count_item(void)
4921306a73bSElena Agostini {
4931306a73bSElena Agostini return mem_alloc_list_last_elem;
4941306a73bSElena Agostini }
4951306a73bSElena Agostini
4961306a73bSElena Agostini /* Initiate list of memory allocations if not done yet */
4971306a73bSElena Agostini static struct mem_entry *
mem_list_add_item(void)4981306a73bSElena Agostini mem_list_add_item(void)
4991306a73bSElena Agostini {
5001306a73bSElena Agostini /* Initiate list of memory allocations if not done yet */
5011306a73bSElena Agostini if (mem_alloc_list_head == NULL) {
5021306a73bSElena Agostini mem_alloc_list_head = rte_zmalloc(NULL,
5031306a73bSElena Agostini sizeof(struct mem_entry),
5041306a73bSElena Agostini RTE_CACHE_LINE_SIZE);
5051306a73bSElena Agostini if (mem_alloc_list_head == NULL) {
5061306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for memory list");
5071306a73bSElena Agostini return NULL;
5081306a73bSElena Agostini }
5091306a73bSElena Agostini
5101306a73bSElena Agostini mem_alloc_list_head->next = NULL;
5111306a73bSElena Agostini mem_alloc_list_head->prev = NULL;
5121306a73bSElena Agostini mem_alloc_list_tail = mem_alloc_list_head;
5131306a73bSElena Agostini } else {
5141306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = rte_zmalloc(NULL,
5151306a73bSElena Agostini sizeof(struct mem_entry),
5161306a73bSElena Agostini RTE_CACHE_LINE_SIZE);
5171306a73bSElena Agostini
5181306a73bSElena Agostini if (mem_alloc_list_cur == NULL) {
5191306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for memory list");
5201306a73bSElena Agostini return NULL;
5211306a73bSElena Agostini }
5221306a73bSElena Agostini
5231306a73bSElena Agostini mem_alloc_list_tail->next = mem_alloc_list_cur;
5241306a73bSElena Agostini mem_alloc_list_cur->prev = mem_alloc_list_tail;
5251306a73bSElena Agostini mem_alloc_list_tail = mem_alloc_list_tail->next;
5261306a73bSElena Agostini mem_alloc_list_tail->next = NULL;
5271306a73bSElena Agostini }
5281306a73bSElena Agostini
5291306a73bSElena Agostini mem_alloc_list_last_elem++;
5301306a73bSElena Agostini
5311306a73bSElena Agostini return mem_alloc_list_tail;
5321306a73bSElena Agostini }
5331306a73bSElena Agostini
5341306a73bSElena Agostini static struct mem_entry *
mem_list_find_item(cuda_ptr_key pk)5351306a73bSElena Agostini mem_list_find_item(cuda_ptr_key pk)
5361306a73bSElena Agostini {
5371306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = NULL;
5381306a73bSElena Agostini
5391306a73bSElena Agostini if (mem_alloc_list_head == NULL) {
5401306a73bSElena Agostini rte_cuda_log(ERR, "Memory list doesn't exist");
5411306a73bSElena Agostini return NULL;
5421306a73bSElena Agostini }
5431306a73bSElena Agostini
5441306a73bSElena Agostini if (mem_list_count_item() == 0) {
5451306a73bSElena Agostini rte_cuda_log(ERR, "No items in memory list");
5461306a73bSElena Agostini return NULL;
5471306a73bSElena Agostini }
5481306a73bSElena Agostini
5491306a73bSElena Agostini mem_alloc_list_cur = mem_alloc_list_head;
5501306a73bSElena Agostini
5511306a73bSElena Agostini while (mem_alloc_list_cur != NULL) {
5521306a73bSElena Agostini if (mem_alloc_list_cur->pkey == pk)
5531306a73bSElena Agostini return mem_alloc_list_cur;
5541306a73bSElena Agostini mem_alloc_list_cur = mem_alloc_list_cur->next;
5551306a73bSElena Agostini }
5561306a73bSElena Agostini
5571306a73bSElena Agostini return mem_alloc_list_cur;
5581306a73bSElena Agostini }
5591306a73bSElena Agostini
5601306a73bSElena Agostini static int
mem_list_del_item(cuda_ptr_key pk)5611306a73bSElena Agostini mem_list_del_item(cuda_ptr_key pk)
5621306a73bSElena Agostini {
5631306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = NULL;
5641306a73bSElena Agostini
5651306a73bSElena Agostini mem_alloc_list_cur = mem_list_find_item(pk);
5661306a73bSElena Agostini if (mem_alloc_list_cur == NULL)
5671306a73bSElena Agostini return -EINVAL;
5681306a73bSElena Agostini
5691306a73bSElena Agostini /* if key is in head */
57098ddd04cSElena Agostini if (mem_alloc_list_cur->prev == NULL) {
5711306a73bSElena Agostini mem_alloc_list_head = mem_alloc_list_cur->next;
57298ddd04cSElena Agostini if (mem_alloc_list_head != NULL)
57398ddd04cSElena Agostini mem_alloc_list_head->prev = NULL;
57498ddd04cSElena Agostini } else {
5751306a73bSElena Agostini mem_alloc_list_cur->prev->next = mem_alloc_list_cur->next;
5761306a73bSElena Agostini if (mem_alloc_list_cur->next != NULL)
5771306a73bSElena Agostini mem_alloc_list_cur->next->prev = mem_alloc_list_cur->prev;
5781306a73bSElena Agostini }
5791306a73bSElena Agostini
5801306a73bSElena Agostini rte_free(mem_alloc_list_cur);
5811306a73bSElena Agostini
5821306a73bSElena Agostini mem_alloc_list_last_elem--;
5831306a73bSElena Agostini
5841306a73bSElena Agostini return 0;
5851306a73bSElena Agostini }
5861306a73bSElena Agostini
5871306a73bSElena Agostini static int
cuda_dev_info_get(struct rte_gpu * dev,struct rte_gpu_info * info)5881306a73bSElena Agostini cuda_dev_info_get(struct rte_gpu *dev, struct rte_gpu_info *info)
5891306a73bSElena Agostini {
5901306a73bSElena Agostini int ret = 0;
5911306a73bSElena Agostini CUresult res;
5921306a73bSElena Agostini struct rte_gpu_info parent_info;
5931306a73bSElena Agostini CUexecAffinityParam affinityPrm;
5941306a73bSElena Agostini const char *err_string;
5951306a73bSElena Agostini struct cuda_info *private;
5961306a73bSElena Agostini CUcontext current_ctx;
5971306a73bSElena Agostini CUcontext input_ctx;
5981306a73bSElena Agostini
59994220b39SElena Agostini if (dev == NULL) {
60094220b39SElena Agostini rte_errno = ENODEV;
60194220b39SElena Agostini return -rte_errno;
60294220b39SElena Agostini }
6031306a73bSElena Agostini
6041306a73bSElena Agostini /* Child initialization time probably called by rte_gpu_add_child() */
6051306a73bSElena Agostini if (dev->mpshared->info.parent != RTE_GPU_ID_NONE &&
6061306a73bSElena Agostini dev->mpshared->dev_private == NULL) {
6071306a73bSElena Agostini /* Store current ctx */
6081306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx);
6091306a73bSElena Agostini if (res != 0) {
6101306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
6111306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
6121306a73bSElena Agostini err_string);
61394220b39SElena Agostini rte_errno = EPERM;
61494220b39SElena Agostini return -rte_errno;
6151306a73bSElena Agostini }
6161306a73bSElena Agostini
6171306a73bSElena Agostini /* Set child ctx as current ctx */
6181306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
6191306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx);
6201306a73bSElena Agostini if (res != 0) {
6211306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
6221306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
6231306a73bSElena Agostini err_string);
62494220b39SElena Agostini rte_errno = EPERM;
62594220b39SElena Agostini return -rte_errno;
6261306a73bSElena Agostini }
6271306a73bSElena Agostini
6281306a73bSElena Agostini /*
6291306a73bSElena Agostini * Ctx capacity info
6301306a73bSElena Agostini */
6311306a73bSElena Agostini
6321306a73bSElena Agostini /* MPS compatible */
6331306a73bSElena Agostini res = pfn_cuCtxGetExecAffinity(&affinityPrm,
6341306a73bSElena Agostini CU_EXEC_AFFINITY_TYPE_SM_COUNT);
6351306a73bSElena Agostini if (res != 0) {
6361306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
6371306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetExecAffinity failed with %s",
6381306a73bSElena Agostini err_string);
6391306a73bSElena Agostini }
6401306a73bSElena Agostini dev->mpshared->info.processor_count =
6411306a73bSElena Agostini (uint32_t)affinityPrm.param.smCount.val;
6421306a73bSElena Agostini
6431306a73bSElena Agostini ret = rte_gpu_info_get(dev->mpshared->info.parent, &parent_info);
64494220b39SElena Agostini if (ret) {
64594220b39SElena Agostini rte_errno = ENODEV;
64694220b39SElena Agostini return -rte_errno;
64794220b39SElena Agostini }
6481306a73bSElena Agostini dev->mpshared->info.total_memory = parent_info.total_memory;
6491306a73bSElena Agostini
6501fd3de64SElena Agostini dev->mpshared->info.page_size = parent_info.page_size;
6511fd3de64SElena Agostini
6521306a73bSElena Agostini /*
6531306a73bSElena Agostini * GPU Device private info
6541306a73bSElena Agostini */
6551306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL,
6561306a73bSElena Agostini sizeof(struct cuda_info),
6571306a73bSElena Agostini RTE_CACHE_LINE_SIZE);
6581306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) {
6591306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private");
66094220b39SElena Agostini rte_errno = EPERM;
66194220b39SElena Agostini return -rte_errno;
6621306a73bSElena Agostini }
6631306a73bSElena Agostini
6641306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private;
6651306a73bSElena Agostini
6661306a73bSElena Agostini res = pfn_cuCtxGetDevice(&(private->cu_dev));
6671306a73bSElena Agostini if (res != 0) {
6681306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
6691306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetDevice failed with %s",
6701306a73bSElena Agostini err_string);
67194220b39SElena Agostini rte_errno = EPERM;
67294220b39SElena Agostini return -rte_errno;
6731306a73bSElena Agostini }
6741306a73bSElena Agostini
6751306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name,
6761306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN, private->cu_dev);
6771306a73bSElena Agostini if (res != 0) {
6781306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
6791306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s",
6801306a73bSElena Agostini err_string);
68194220b39SElena Agostini rte_errno = EPERM;
68294220b39SElena Agostini return -rte_errno;
6831306a73bSElena Agostini }
6841306a73bSElena Agostini
6851306a73bSElena Agostini /* Restore original ctx as current ctx */
6861306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx);
6871306a73bSElena Agostini if (res != 0) {
6881306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
6891306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
6901306a73bSElena Agostini err_string);
69194220b39SElena Agostini rte_errno = EPERM;
69294220b39SElena Agostini return -rte_errno;
6931306a73bSElena Agostini }
6941306a73bSElena Agostini }
6951306a73bSElena Agostini
6961306a73bSElena Agostini *info = dev->mpshared->info;
6971306a73bSElena Agostini
6981306a73bSElena Agostini return 0;
6991306a73bSElena Agostini }
7001306a73bSElena Agostini
7011306a73bSElena Agostini /*
7021306a73bSElena Agostini * GPU Memory
7031306a73bSElena Agostini */
7041306a73bSElena Agostini
7051306a73bSElena Agostini static int
cuda_mem_alloc(struct rte_gpu * dev,size_t size,unsigned int align,void ** ptr)706c8557ed4SElena Agostini cuda_mem_alloc(struct rte_gpu *dev, size_t size, unsigned int align, void **ptr)
7071306a73bSElena Agostini {
7081306a73bSElena Agostini CUresult res;
7091306a73bSElena Agostini const char *err_string;
7101306a73bSElena Agostini CUcontext current_ctx;
7111306a73bSElena Agostini CUcontext input_ctx;
7121306a73bSElena Agostini unsigned int flag = 1;
7131306a73bSElena Agostini
7141306a73bSElena Agostini if (dev == NULL)
7151306a73bSElena Agostini return -ENODEV;
7161306a73bSElena Agostini
7171306a73bSElena Agostini /* Store current ctx */
7181306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx);
7191306a73bSElena Agostini if (res != 0) {
7201306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
7211306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
7221306a73bSElena Agostini err_string);
72394220b39SElena Agostini rte_errno = EPERM;
72494220b39SElena Agostini return -rte_errno;
7251306a73bSElena Agostini }
7261306a73bSElena Agostini
7271306a73bSElena Agostini /* Set child ctx as current ctx */
7281306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
7291306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx);
7301306a73bSElena Agostini if (res != 0) {
7311306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
7321306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
7331306a73bSElena Agostini err_string);
73494220b39SElena Agostini rte_errno = EPERM;
73594220b39SElena Agostini return -rte_errno;
7361306a73bSElena Agostini }
7371306a73bSElena Agostini
7381306a73bSElena Agostini /* Get next memory list item */
7391306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item();
74094220b39SElena Agostini if (mem_alloc_list_tail == NULL) {
74194220b39SElena Agostini rte_errno = EPERM;
74294220b39SElena Agostini return -rte_errno;
74394220b39SElena Agostini }
7441306a73bSElena Agostini
7451306a73bSElena Agostini /* Allocate memory */
7461306a73bSElena Agostini mem_alloc_list_tail->size = size;
747c8557ed4SElena Agostini mem_alloc_list_tail->size_orig = size + align;
748c8557ed4SElena Agostini
749c8557ed4SElena Agostini res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d),
750c8557ed4SElena Agostini mem_alloc_list_tail->size_orig);
7511306a73bSElena Agostini if (res != 0) {
7521306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
7531306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
7541306a73bSElena Agostini err_string);
75594220b39SElena Agostini rte_errno = EPERM;
75694220b39SElena Agostini return -rte_errno;
7571306a73bSElena Agostini }
7581306a73bSElena Agostini
759c8557ed4SElena Agostini /* Align memory address */
760c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d;
761c8557ed4SElena Agostini if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align)
762c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d += (align -
763c8557ed4SElena Agostini (((uintptr_t)mem_alloc_list_tail->ptr_d) % align));
764c8557ed4SElena Agostini
7651306a73bSElena Agostini /* GPUDirect RDMA attribute required */
7661306a73bSElena Agostini res = pfn_cuPointerSetAttribute(&flag,
7671306a73bSElena Agostini CU_POINTER_ATTRIBUTE_SYNC_MEMOPS,
7681306a73bSElena Agostini mem_alloc_list_tail->ptr_d);
7691306a73bSElena Agostini if (res != 0) {
7701306a73bSElena Agostini rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for "
7711306a73bSElena Agostini "GPU memory at %"PRIu32", err %d",
7721306a73bSElena Agostini (uint32_t)mem_alloc_list_tail->ptr_d, res);
77394220b39SElena Agostini rte_errno = EPERM;
77494220b39SElena Agostini return -rte_errno;
7751306a73bSElena Agostini }
7761306a73bSElena Agostini
7771306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_d);
7781306a73bSElena Agostini mem_alloc_list_tail->ptr_h = NULL;
7791306a73bSElena Agostini mem_alloc_list_tail->dev = dev;
7801306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
7811306a73bSElena Agostini mem_alloc_list_tail->mtype = GPU_MEM;
7821306a73bSElena Agostini
7831306a73bSElena Agostini /* Restore original ctx as current ctx */
7841306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx);
7851306a73bSElena Agostini if (res != 0) {
7861306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
7871306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
7881306a73bSElena Agostini err_string);
78994220b39SElena Agostini rte_errno = EPERM;
79094220b39SElena Agostini return -rte_errno;
7911306a73bSElena Agostini }
7921306a73bSElena Agostini
7931306a73bSElena Agostini *ptr = (void *)mem_alloc_list_tail->ptr_d;
7941306a73bSElena Agostini
7951306a73bSElena Agostini return 0;
7961306a73bSElena Agostini }
7971306a73bSElena Agostini
7981306a73bSElena Agostini static int
cuda_mem_register(struct rte_gpu * dev,size_t size,void * ptr)7991306a73bSElena Agostini cuda_mem_register(struct rte_gpu *dev, size_t size, void *ptr)
8001306a73bSElena Agostini {
8011306a73bSElena Agostini CUresult res;
8021306a73bSElena Agostini const char *err_string;
8031306a73bSElena Agostini CUcontext current_ctx;
8041306a73bSElena Agostini CUcontext input_ctx;
8051306a73bSElena Agostini unsigned int flag = 1;
8061306a73bSElena Agostini int use_ptr_h = 0;
8071306a73bSElena Agostini
8081306a73bSElena Agostini if (dev == NULL)
8091306a73bSElena Agostini return -ENODEV;
8101306a73bSElena Agostini
8111306a73bSElena Agostini /* Store current ctx */
8121306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx);
8131306a73bSElena Agostini if (res != 0) {
8141306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
8151306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
8161306a73bSElena Agostini err_string);
81794220b39SElena Agostini rte_errno = EPERM;
81894220b39SElena Agostini return -rte_errno;
8191306a73bSElena Agostini }
8201306a73bSElena Agostini
8211306a73bSElena Agostini /* Set child ctx as current ctx */
8221306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
8231306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx);
8241306a73bSElena Agostini if (res != 0) {
8251306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
8261306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
8271306a73bSElena Agostini err_string);
82894220b39SElena Agostini rte_errno = EPERM;
82994220b39SElena Agostini return -rte_errno;
8301306a73bSElena Agostini }
8311306a73bSElena Agostini
8321306a73bSElena Agostini /* Get next memory list item */
8331306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item();
83494220b39SElena Agostini if (mem_alloc_list_tail == NULL) {
83594220b39SElena Agostini rte_errno = EPERM;
83694220b39SElena Agostini return -rte_errno;
83794220b39SElena Agostini }
8381306a73bSElena Agostini
8391306a73bSElena Agostini /* Allocate memory */
8401306a73bSElena Agostini mem_alloc_list_tail->size = size;
8411306a73bSElena Agostini mem_alloc_list_tail->ptr_h = ptr;
8421306a73bSElena Agostini
8431306a73bSElena Agostini res = pfn_cuMemHostRegister(mem_alloc_list_tail->ptr_h,
8441306a73bSElena Agostini mem_alloc_list_tail->size,
8451306a73bSElena Agostini CU_MEMHOSTREGISTER_PORTABLE |
8461306a73bSElena Agostini CU_MEMHOSTREGISTER_DEVICEMAP);
8471306a73bSElena Agostini if (res != 0) {
8481306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
8491306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostRegister failed with %s ptr %p size %zd",
8501306a73bSElena Agostini err_string,
8511306a73bSElena Agostini mem_alloc_list_tail->ptr_h,
8521306a73bSElena Agostini mem_alloc_list_tail->size);
85394220b39SElena Agostini rte_errno = EPERM;
85494220b39SElena Agostini return -rte_errno;
8551306a73bSElena Agostini }
8561306a73bSElena Agostini
8571306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(use_ptr_h),
8581306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM,
8591306a73bSElena Agostini ((struct cuda_info *)(dev->mpshared->dev_private))->cu_dev);
8601306a73bSElena Agostini if (res != 0) {
8611306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
8621306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
8631306a73bSElena Agostini err_string);
86494220b39SElena Agostini rte_errno = EPERM;
86594220b39SElena Agostini return -rte_errno;
8661306a73bSElena Agostini }
8671306a73bSElena Agostini
8681306a73bSElena Agostini if (use_ptr_h == 0) {
8691306a73bSElena Agostini res = pfn_cuMemHostGetDevicePointer(&(mem_alloc_list_tail->ptr_d),
8701306a73bSElena Agostini mem_alloc_list_tail->ptr_h, 0);
8711306a73bSElena Agostini if (res != 0) {
8721306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
8731306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostGetDevicePointer failed with %s",
8741306a73bSElena Agostini err_string);
87594220b39SElena Agostini rte_errno = EPERM;
87694220b39SElena Agostini return -rte_errno;
8771306a73bSElena Agostini }
8781306a73bSElena Agostini
8791306a73bSElena Agostini if ((uintptr_t)mem_alloc_list_tail->ptr_d !=
8801306a73bSElena Agostini (uintptr_t)mem_alloc_list_tail->ptr_h) {
8811306a73bSElena Agostini rte_cuda_log(ERR, "Host input pointer is different wrt GPU registered pointer");
88294220b39SElena Agostini rte_errno = ENOTSUP;
88394220b39SElena Agostini return -rte_errno;
8841306a73bSElena Agostini }
8851306a73bSElena Agostini } else {
8861306a73bSElena Agostini mem_alloc_list_tail->ptr_d = (CUdeviceptr)mem_alloc_list_tail->ptr_h;
8871306a73bSElena Agostini }
8881306a73bSElena Agostini
8891306a73bSElena Agostini /* GPUDirect RDMA attribute required */
8901306a73bSElena Agostini res = pfn_cuPointerSetAttribute(&flag,
8911306a73bSElena Agostini CU_POINTER_ATTRIBUTE_SYNC_MEMOPS,
8921306a73bSElena Agostini mem_alloc_list_tail->ptr_d);
8931306a73bSElena Agostini if (res != 0) {
8941306a73bSElena Agostini rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for GPU memory at %"PRIu32
8951306a73bSElena Agostini ", err %d", (uint32_t)mem_alloc_list_tail->ptr_d, res);
89694220b39SElena Agostini rte_errno = EPERM;
89794220b39SElena Agostini return -rte_errno;
8981306a73bSElena Agostini }
8991306a73bSElena Agostini
9001306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_h);
9011306a73bSElena Agostini mem_alloc_list_tail->size = size;
9021306a73bSElena Agostini mem_alloc_list_tail->dev = dev;
9031306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
9041306a73bSElena Agostini mem_alloc_list_tail->mtype = CPU_REGISTERED;
905c8557ed4SElena Agostini mem_alloc_list_tail->ptr_orig_d = mem_alloc_list_tail->ptr_d;
9061306a73bSElena Agostini
9071306a73bSElena Agostini /* Restore original ctx as current ctx */
9081306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx);
9091306a73bSElena Agostini if (res != 0) {
9101306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
9111306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
9121306a73bSElena Agostini err_string);
91394220b39SElena Agostini rte_errno = EPERM;
91494220b39SElena Agostini return -rte_errno;
9151306a73bSElena Agostini }
9161306a73bSElena Agostini
9171306a73bSElena Agostini return 0;
9181306a73bSElena Agostini }
9191306a73bSElena Agostini
9201306a73bSElena Agostini static int
cuda_mem_cpu_map(struct rte_gpu * dev,__rte_unused size_t size,void * ptr_in,void ** ptr_out)92124c77594SElena Agostini cuda_mem_cpu_map(struct rte_gpu *dev, __rte_unused size_t size, void *ptr_in, void **ptr_out)
92224c77594SElena Agostini {
92324c77594SElena Agostini struct mem_entry *mem_item;
92424c77594SElena Agostini cuda_ptr_key hk;
92524c77594SElena Agostini
92624c77594SElena Agostini if (dev == NULL)
92724c77594SElena Agostini return -ENODEV;
92824c77594SElena Agostini
92924c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in);
93024c77594SElena Agostini
93124c77594SElena Agostini mem_item = mem_list_find_item(hk);
93224c77594SElena Agostini if (mem_item == NULL) {
93324c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in);
93424c77594SElena Agostini rte_errno = EPERM;
93524c77594SElena Agostini return -rte_errno;
93624c77594SElena Agostini }
93724c77594SElena Agostini
93824c77594SElena Agostini if (mem_item->mtype != GPU_MEM) {
93924c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p is not GPU memory type.", ptr_in);
94024c77594SElena Agostini rte_errno = EPERM;
94124c77594SElena Agostini return -rte_errno;
94224c77594SElena Agostini }
94324c77594SElena Agostini
94424c77594SElena Agostini if (mem_item->size != size)
94524c77594SElena Agostini rte_cuda_log(WARNING,
94624c77594SElena Agostini "Can't expose memory area with size (%zd) different from original size (%zd).",
94724c77594SElena Agostini size, mem_item->size);
94824c77594SElena Agostini
94924c77594SElena Agostini if (gdrcopy_pin(&gdrc_h, &(mem_item->mh), (uint64_t)mem_item->ptr_d,
95024c77594SElena Agostini mem_item->size, &(mem_item->ptr_h))) {
95124c77594SElena Agostini rte_cuda_log(ERR, "Error exposing GPU memory address 0x%p.", ptr_in);
95224c77594SElena Agostini rte_errno = EPERM;
95324c77594SElena Agostini return -rte_errno;
95424c77594SElena Agostini }
95524c77594SElena Agostini
9560354e8e8SElena Agostini mem_item->mtype = GPU_REGISTERED;
95724c77594SElena Agostini *ptr_out = mem_item->ptr_h;
95824c77594SElena Agostini
95924c77594SElena Agostini return 0;
96024c77594SElena Agostini }
96124c77594SElena Agostini
96224c77594SElena Agostini static int
cuda_mem_unregister(struct rte_gpu * dev,void * ptr)9631306a73bSElena Agostini cuda_mem_unregister(struct rte_gpu *dev, void *ptr)
9641306a73bSElena Agostini {
9651306a73bSElena Agostini CUresult res;
9661306a73bSElena Agostini struct mem_entry *mem_item;
9671306a73bSElena Agostini const char *err_string;
9681306a73bSElena Agostini cuda_ptr_key hk;
9691306a73bSElena Agostini
9701306a73bSElena Agostini if (dev == NULL)
9711306a73bSElena Agostini return -ENODEV;
9721306a73bSElena Agostini
9731306a73bSElena Agostini hk = get_hash_from_ptr((void *)ptr);
9741306a73bSElena Agostini
9751306a73bSElena Agostini mem_item = mem_list_find_item(hk);
9761306a73bSElena Agostini if (mem_item == NULL) {
9771306a73bSElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr);
97894220b39SElena Agostini rte_errno = EPERM;
97994220b39SElena Agostini return -rte_errno;
9801306a73bSElena Agostini }
9811306a73bSElena Agostini
9821306a73bSElena Agostini if (mem_item->mtype == CPU_REGISTERED) {
9831306a73bSElena Agostini res = pfn_cuMemHostUnregister(ptr);
9841306a73bSElena Agostini if (res != 0) {
9851306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
9861306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostUnregister current failed with %s",
9871306a73bSElena Agostini err_string);
98894220b39SElena Agostini rte_errno = EPERM;
98994220b39SElena Agostini return -rte_errno;
9901306a73bSElena Agostini }
9911306a73bSElena Agostini
9921306a73bSElena Agostini return mem_list_del_item(hk);
9931306a73bSElena Agostini }
9941306a73bSElena Agostini
9951306a73bSElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype);
9961306a73bSElena Agostini
99794220b39SElena Agostini rte_errno = EPERM;
99894220b39SElena Agostini return -rte_errno;
9991306a73bSElena Agostini }
10001306a73bSElena Agostini
10011306a73bSElena Agostini static int
cuda_mem_cpu_unmap(struct rte_gpu * dev,void * ptr_in)100224c77594SElena Agostini cuda_mem_cpu_unmap(struct rte_gpu *dev, void *ptr_in)
100324c77594SElena Agostini {
100424c77594SElena Agostini struct mem_entry *mem_item;
100524c77594SElena Agostini cuda_ptr_key hk;
100624c77594SElena Agostini
100724c77594SElena Agostini if (dev == NULL)
100824c77594SElena Agostini return -ENODEV;
100924c77594SElena Agostini
101024c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in);
101124c77594SElena Agostini
101224c77594SElena Agostini mem_item = mem_list_find_item(hk);
101324c77594SElena Agostini if (mem_item == NULL) {
101424c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in);
101524c77594SElena Agostini rte_errno = EPERM;
101624c77594SElena Agostini return -rte_errno;
101724c77594SElena Agostini }
101824c77594SElena Agostini
10190354e8e8SElena Agostini if (mem_item->mtype == GPU_REGISTERED) {
102024c77594SElena Agostini if (gdrcopy_unpin(gdrc_h, mem_item->mh, (void *)mem_item->ptr_d,
102124c77594SElena Agostini mem_item->size)) {
102224c77594SElena Agostini rte_cuda_log(ERR, "Error unexposing GPU memory address 0x%p.", ptr_in);
102324c77594SElena Agostini rte_errno = EPERM;
102424c77594SElena Agostini return -rte_errno;
102524c77594SElena Agostini }
102624c77594SElena Agostini
10270354e8e8SElena Agostini mem_item->mtype = GPU_MEM;
10280354e8e8SElena Agostini } else {
10290354e8e8SElena Agostini rte_errno = EPERM;
10300354e8e8SElena Agostini return -rte_errno;
10310354e8e8SElena Agostini }
10320354e8e8SElena Agostini
103324c77594SElena Agostini return 0;
103424c77594SElena Agostini }
103524c77594SElena Agostini
103624c77594SElena Agostini static int
cuda_mem_free(struct rte_gpu * dev,void * ptr)10370354e8e8SElena Agostini cuda_mem_free(struct rte_gpu *dev, void *ptr)
10380354e8e8SElena Agostini {
10390354e8e8SElena Agostini CUresult res;
10400354e8e8SElena Agostini struct mem_entry *mem_item;
10410354e8e8SElena Agostini const char *err_string;
10420354e8e8SElena Agostini cuda_ptr_key hk;
10430354e8e8SElena Agostini
10440354e8e8SElena Agostini if (dev == NULL)
10450354e8e8SElena Agostini return -ENODEV;
10460354e8e8SElena Agostini
10470354e8e8SElena Agostini hk = get_hash_from_ptr((void *)ptr);
10480354e8e8SElena Agostini
10490354e8e8SElena Agostini mem_item = mem_list_find_item(hk);
10500354e8e8SElena Agostini if (mem_item == NULL) {
10510354e8e8SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr);
10520354e8e8SElena Agostini rte_errno = EPERM;
10530354e8e8SElena Agostini return -rte_errno;
10540354e8e8SElena Agostini }
10550354e8e8SElena Agostini
10560354e8e8SElena Agostini /*
10570354e8e8SElena Agostini * If a GPU memory area that's CPU mapped is being freed
10580354e8e8SElena Agostini * without calling cpu_unmap, force the unmapping.
10590354e8e8SElena Agostini */
10600354e8e8SElena Agostini if (mem_item->mtype == GPU_REGISTERED)
10610354e8e8SElena Agostini cuda_mem_cpu_unmap(dev, ptr);
10620354e8e8SElena Agostini
10630354e8e8SElena Agostini if (mem_item->mtype == GPU_MEM) {
10640354e8e8SElena Agostini res = pfn_cuMemFree(mem_item->ptr_orig_d);
10650354e8e8SElena Agostini if (res != 0) {
10660354e8e8SElena Agostini pfn_cuGetErrorString(res, &(err_string));
10670354e8e8SElena Agostini rte_cuda_log(ERR, "cuMemFree current failed with %s",
10680354e8e8SElena Agostini err_string);
10690354e8e8SElena Agostini rte_errno = EPERM;
10700354e8e8SElena Agostini return -rte_errno;
10710354e8e8SElena Agostini }
10720354e8e8SElena Agostini
10730354e8e8SElena Agostini return mem_list_del_item(hk);
10740354e8e8SElena Agostini }
10750354e8e8SElena Agostini
10760354e8e8SElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype);
10770354e8e8SElena Agostini
10780354e8e8SElena Agostini return -EPERM;
10790354e8e8SElena Agostini }
10800354e8e8SElena Agostini
10810354e8e8SElena Agostini static int
cuda_dev_close(struct rte_gpu * dev)10821306a73bSElena Agostini cuda_dev_close(struct rte_gpu *dev)
10831306a73bSElena Agostini {
10841306a73bSElena Agostini if (dev == NULL)
10851306a73bSElena Agostini return -EINVAL;
10861306a73bSElena Agostini
10871306a73bSElena Agostini rte_free(dev->mpshared->dev_private);
10881306a73bSElena Agostini
10891306a73bSElena Agostini return 0;
10901306a73bSElena Agostini }
10911306a73bSElena Agostini
10921306a73bSElena Agostini static int
cuda_wmb(struct rte_gpu * dev)10931306a73bSElena Agostini cuda_wmb(struct rte_gpu *dev)
10941306a73bSElena Agostini {
10951306a73bSElena Agostini CUresult res;
10961306a73bSElena Agostini const char *err_string;
10971306a73bSElena Agostini CUcontext current_ctx;
10981306a73bSElena Agostini CUcontext input_ctx;
10991306a73bSElena Agostini struct cuda_info *private;
11001306a73bSElena Agostini
110194220b39SElena Agostini if (dev == NULL) {
110294220b39SElena Agostini rte_errno = ENODEV;
110394220b39SElena Agostini return -rte_errno;
110494220b39SElena Agostini }
11051306a73bSElena Agostini
11061306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private;
11071306a73bSElena Agostini
11081306a73bSElena Agostini if (private->gdr_write_ordering != CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) {
11091306a73bSElena Agostini /*
11101306a73bSElena Agostini * No need to explicitly force the write ordering because
11111306a73bSElena Agostini * the device natively supports it
11121306a73bSElena Agostini */
11131306a73bSElena Agostini return 0;
11141306a73bSElena Agostini }
11151306a73bSElena Agostini
11161306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) {
11171306a73bSElena Agostini /*
11181306a73bSElena Agostini * Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function.
11191306a73bSElena Agostini * Application needs to use alternative methods.
11201306a73bSElena Agostini */
11211306a73bSElena Agostini rte_cuda_log(WARNING, "Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function."
11221306a73bSElena Agostini "Application needs to use alternative methods.");
112394220b39SElena Agostini
112494220b39SElena Agostini rte_errno = ENOTSUP;
112594220b39SElena Agostini return -rte_errno;
11261306a73bSElena Agostini }
11271306a73bSElena Agostini
11281306a73bSElena Agostini /* Store current ctx */
11291306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx);
11301306a73bSElena Agostini if (res != 0) {
11311306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
11321306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s",
11331306a73bSElena Agostini err_string);
113494220b39SElena Agostini rte_errno = EPERM;
113594220b39SElena Agostini return -rte_errno;
11361306a73bSElena Agostini }
11371306a73bSElena Agostini
11381306a73bSElena Agostini /* Set child ctx as current ctx */
11391306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context);
11401306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx);
11411306a73bSElena Agostini if (res != 0) {
11421306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
11431306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s",
11441306a73bSElena Agostini err_string);
114594220b39SElena Agostini rte_errno = EPERM;
114694220b39SElena Agostini return -rte_errno;
11471306a73bSElena Agostini }
11481306a73bSElena Agostini
11491306a73bSElena Agostini res = pfn_cuFlushGPUDirectRDMAWrites(CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TARGET_CURRENT_CTX,
11501306a73bSElena Agostini CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TO_ALL_DEVICES);
11511306a73bSElena Agostini if (res != 0) {
11521306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
11531306a73bSElena Agostini rte_cuda_log(ERR, "cuFlushGPUDirectRDMAWrites current failed with %s",
11541306a73bSElena Agostini err_string);
115594220b39SElena Agostini rte_errno = EPERM;
115694220b39SElena Agostini return -rte_errno;
11571306a73bSElena Agostini }
11581306a73bSElena Agostini
11591306a73bSElena Agostini /* Restore original ctx as current ctx */
11601306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx);
11611306a73bSElena Agostini if (res != 0) {
11621306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
11631306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s",
11641306a73bSElena Agostini err_string);
116594220b39SElena Agostini rte_errno = EPERM;
116694220b39SElena Agostini return -rte_errno;
11671306a73bSElena Agostini }
11681306a73bSElena Agostini
11691306a73bSElena Agostini return 0;
11701306a73bSElena Agostini }
11711306a73bSElena Agostini
11721306a73bSElena Agostini static int
cuda_gpu_probe(__rte_unused struct rte_pci_driver * pci_drv,struct rte_pci_device * pci_dev)11731306a73bSElena Agostini cuda_gpu_probe(__rte_unused struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
11741306a73bSElena Agostini {
11751306a73bSElena Agostini struct rte_gpu *dev = NULL;
11761306a73bSElena Agostini CUresult res;
11771306a73bSElena Agostini CUdevice cu_dev_id;
11781306a73bSElena Agostini CUcontext pctx;
11791306a73bSElena Agostini char dev_name[RTE_DEV_NAME_MAX_LEN];
11801306a73bSElena Agostini const char *err_string;
11811306a73bSElena Agostini int processor_count = 0;
11821306a73bSElena Agostini struct cuda_info *private;
11831306a73bSElena Agostini
11841306a73bSElena Agostini if (pci_dev == NULL) {
11851306a73bSElena Agostini rte_cuda_log(ERR, "NULL PCI device");
118694220b39SElena Agostini rte_errno = ENODEV;
118794220b39SElena Agostini return -rte_errno;
11881306a73bSElena Agostini }
11891306a73bSElena Agostini
11901306a73bSElena Agostini rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
11911306a73bSElena Agostini
11921306a73bSElena Agostini /* Allocate memory to be used privately by drivers */
11931306a73bSElena Agostini dev = rte_gpu_allocate(pci_dev->device.name);
119494220b39SElena Agostini if (dev == NULL) {
119594220b39SElena Agostini rte_errno = ENODEV;
119694220b39SElena Agostini return -rte_errno;
119794220b39SElena Agostini }
11981306a73bSElena Agostini
11991306a73bSElena Agostini /* Initialize values only for the first CUDA driver call */
12001306a73bSElena Agostini if (dev->mpshared->info.dev_id == 0) {
12011306a73bSElena Agostini mem_alloc_list_head = NULL;
12021306a73bSElena Agostini mem_alloc_list_tail = NULL;
12031306a73bSElena Agostini mem_alloc_list_last_elem = 0;
12041306a73bSElena Agostini
12051306a73bSElena Agostini /* Load libcuda.so library */
12061306a73bSElena Agostini if (cuda_loader()) {
12071306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver library not found");
120894220b39SElena Agostini rte_errno = ENOTSUP;
120994220b39SElena Agostini return -rte_errno;
12101306a73bSElena Agostini }
12111306a73bSElena Agostini
12121306a73bSElena Agostini /* Load initial CUDA functions */
12131306a73bSElena Agostini if (cuda_sym_func_loader()) {
12141306a73bSElena Agostini rte_cuda_log(ERR, "CUDA functions not found in library");
121594220b39SElena Agostini rte_errno = ENOTSUP;
121694220b39SElena Agostini return -rte_errno;
12171306a73bSElena Agostini }
12181306a73bSElena Agostini
12191306a73bSElena Agostini /*
12201306a73bSElena Agostini * Required to initialize the CUDA Driver.
12211306a73bSElena Agostini * Multiple calls of cuInit() will return immediately
12221306a73bSElena Agostini * without making any relevant change
12231306a73bSElena Agostini */
12241306a73bSElena Agostini sym_cuInit(0);
12251306a73bSElena Agostini
12261306a73bSElena Agostini res = sym_cuDriverGetVersion(&cuda_driver_version);
12271306a73bSElena Agostini if (res != 0) {
12281306a73bSElena Agostini rte_cuda_log(ERR, "cuDriverGetVersion failed with %d", res);
122994220b39SElena Agostini rte_errno = ENOTSUP;
123094220b39SElena Agostini return -rte_errno;
12311306a73bSElena Agostini }
12321306a73bSElena Agostini
12331306a73bSElena Agostini if (cuda_driver_version < CUDA_DRIVER_MIN_VERSION) {
12341306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver version found is %d. "
12351306a73bSElena Agostini "Minimum requirement is %d",
12361306a73bSElena Agostini cuda_driver_version,
12371306a73bSElena Agostini CUDA_DRIVER_MIN_VERSION);
123894220b39SElena Agostini rte_errno = ENOTSUP;
123994220b39SElena Agostini return -rte_errno;
12401306a73bSElena Agostini }
12411306a73bSElena Agostini
12421306a73bSElena Agostini if (cuda_pfn_func_loader()) {
12431306a73bSElena Agostini rte_cuda_log(ERR, "CUDA PFN functions not found in library");
124494220b39SElena Agostini rte_errno = ENOTSUP;
124594220b39SElena Agostini return -rte_errno;
12461306a73bSElena Agostini }
124724c77594SElena Agostini
124824c77594SElena Agostini gdrc_h = NULL;
12491306a73bSElena Agostini }
12501306a73bSElena Agostini
12511306a73bSElena Agostini /* Fill HW specific part of device structure */
12521306a73bSElena Agostini dev->device = &pci_dev->device;
12531306a73bSElena Agostini dev->mpshared->info.numa_node = pci_dev->device.numa_node;
12541306a73bSElena Agostini
12551306a73bSElena Agostini /* Get NVIDIA GPU Device descriptor */
12561306a73bSElena Agostini res = pfn_cuDeviceGetByPCIBusId(&cu_dev_id, dev->device->name);
12571306a73bSElena Agostini if (res != 0) {
12581306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
12591306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetByPCIBusId name %s failed with %d: %s",
12601306a73bSElena Agostini dev->device->name, res, err_string);
126194220b39SElena Agostini rte_errno = EPERM;
126294220b39SElena Agostini return -rte_errno;
12631306a73bSElena Agostini }
12641306a73bSElena Agostini
12651306a73bSElena Agostini res = pfn_cuDevicePrimaryCtxRetain(&pctx, cu_dev_id);
12661306a73bSElena Agostini if (res != 0) {
12671306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
12681306a73bSElena Agostini rte_cuda_log(ERR, "cuDevicePrimaryCtxRetain name %s failed with %d: %s",
12691306a73bSElena Agostini dev->device->name, res, err_string);
127094220b39SElena Agostini rte_errno = EPERM;
127194220b39SElena Agostini return -rte_errno;
12721306a73bSElena Agostini }
12731306a73bSElena Agostini
12741306a73bSElena Agostini res = pfn_cuCtxGetApiVersion(pctx, &cuda_api_version);
12751306a73bSElena Agostini if (res != 0) {
12761306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetApiVersion failed with %d", res);
127794220b39SElena Agostini rte_errno = ENOTSUP;
127894220b39SElena Agostini return -rte_errno;
12791306a73bSElena Agostini }
12801306a73bSElena Agostini
12811306a73bSElena Agostini if (cuda_api_version < CUDA_API_MIN_VERSION) {
12821306a73bSElena Agostini rte_cuda_log(ERR, "CUDA API version found is %d Minimum requirement is %d",
12831306a73bSElena Agostini cuda_api_version, CUDA_API_MIN_VERSION);
128494220b39SElena Agostini rte_errno = ENOTSUP;
128594220b39SElena Agostini return -rte_errno;
12861306a73bSElena Agostini }
12871306a73bSElena Agostini
12881306a73bSElena Agostini dev->mpshared->info.context = (uint64_t)pctx;
12891306a73bSElena Agostini
12901306a73bSElena Agostini /*
12911306a73bSElena Agostini * GPU Device generic info
12921306a73bSElena Agostini */
12931306a73bSElena Agostini
12941306a73bSElena Agostini /* Processor count */
12951306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(processor_count),
12961306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT,
12971306a73bSElena Agostini cu_dev_id);
12981306a73bSElena Agostini if (res != 0) {
12991306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
13001306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
13011306a73bSElena Agostini err_string);
130294220b39SElena Agostini rte_errno = EPERM;
130394220b39SElena Agostini return -rte_errno;
13041306a73bSElena Agostini }
13051306a73bSElena Agostini dev->mpshared->info.processor_count = (uint32_t)processor_count;
13061306a73bSElena Agostini
13071306a73bSElena Agostini /* Total memory */
13081306a73bSElena Agostini res = pfn_cuDeviceTotalMem(&dev->mpshared->info.total_memory, cu_dev_id);
13091306a73bSElena Agostini if (res != 0) {
13101306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
13111306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceTotalMem failed with %s",
13121306a73bSElena Agostini err_string);
131394220b39SElena Agostini rte_errno = EPERM;
131494220b39SElena Agostini return -rte_errno;
13151306a73bSElena Agostini }
13161306a73bSElena Agostini
13171fd3de64SElena Agostini dev->mpshared->info.page_size = (size_t)GPU_PAGE_SIZE;
13181fd3de64SElena Agostini
13191306a73bSElena Agostini /*
13201306a73bSElena Agostini * GPU Device private info
13211306a73bSElena Agostini */
13221306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL,
13231306a73bSElena Agostini sizeof(struct cuda_info),
13241306a73bSElena Agostini RTE_CACHE_LINE_SIZE);
13251306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) {
13261306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private");
132794220b39SElena Agostini rte_errno = EPERM;
132894220b39SElena Agostini return -rte_errno;
13291306a73bSElena Agostini }
13301306a73bSElena Agostini
13311306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private;
13321306a73bSElena Agostini private->cu_dev = cu_dev_id;
13331306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name,
13341306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN,
13351306a73bSElena Agostini cu_dev_id);
13361306a73bSElena Agostini if (res != 0) {
13371306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
13381306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s",
13391306a73bSElena Agostini err_string);
134094220b39SElena Agostini rte_errno = EPERM;
134194220b39SElena Agostini return -rte_errno;
13421306a73bSElena Agostini }
13431306a73bSElena Agostini
13441306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_supported),
13451306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_SUPPORTED,
13461306a73bSElena Agostini cu_dev_id);
13471306a73bSElena Agostini if (res != 0) {
13481306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
13491306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
13501306a73bSElena Agostini err_string);
135194220b39SElena Agostini rte_errno = EPERM;
135294220b39SElena Agostini return -rte_errno;
13531306a73bSElena Agostini }
13541306a73bSElena Agostini
13551306a73bSElena Agostini if (private->gdr_supported == 0)
13561306a73bSElena Agostini rte_cuda_log(WARNING, "GPU %s doesn't support GPUDirect RDMA",
13571306a73bSElena Agostini pci_dev->device.name);
13581306a73bSElena Agostini
13591306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_write_ordering),
13601306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_WRITES_ORDERING,
13611306a73bSElena Agostini cu_dev_id);
13621306a73bSElena Agostini if (res != 0) {
13631306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
13641306a73bSElena Agostini rte_cuda_log(ERR,
13651306a73bSElena Agostini "cuDeviceGetAttribute failed with %s",
13661306a73bSElena Agostini err_string);
136794220b39SElena Agostini rte_errno = EPERM;
136894220b39SElena Agostini return -rte_errno;
13691306a73bSElena Agostini }
13701306a73bSElena Agostini
13711306a73bSElena Agostini if (private->gdr_write_ordering == CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) {
13721306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_flush_type),
13731306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_FLUSH_WRITES_OPTIONS,
13741306a73bSElena Agostini cu_dev_id);
13751306a73bSElena Agostini if (res != 0) {
13761306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string));
13771306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s",
13781306a73bSElena Agostini err_string);
137994220b39SElena Agostini rte_errno = EPERM;
138094220b39SElena Agostini return -rte_errno;
13811306a73bSElena Agostini }
13821306a73bSElena Agostini
13831306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST)
13841306a73bSElena Agostini rte_cuda_log(ERR, "GPUDirect RDMA flush writes API is not supported");
13851306a73bSElena Agostini }
13861306a73bSElena Agostini
13871306a73bSElena Agostini dev->ops.dev_info_get = cuda_dev_info_get;
13881306a73bSElena Agostini dev->ops.dev_close = cuda_dev_close;
13891306a73bSElena Agostini dev->ops.mem_alloc = cuda_mem_alloc;
13901306a73bSElena Agostini dev->ops.mem_free = cuda_mem_free;
13911306a73bSElena Agostini dev->ops.mem_register = cuda_mem_register;
13921306a73bSElena Agostini dev->ops.mem_unregister = cuda_mem_unregister;
139324c77594SElena Agostini dev->ops.mem_cpu_map = cuda_mem_cpu_map;
139424c77594SElena Agostini dev->ops.mem_cpu_unmap = cuda_mem_cpu_unmap;
13951306a73bSElena Agostini dev->ops.wmb = cuda_wmb;
13961306a73bSElena Agostini
13971306a73bSElena Agostini rte_gpu_complete_new(dev);
13981306a73bSElena Agostini
13991306a73bSElena Agostini rte_cuda_debug("dev id = %u name = %s",
14001306a73bSElena Agostini dev->mpshared->info.dev_id, private->gpu_name);
14011306a73bSElena Agostini
14021306a73bSElena Agostini return 0;
14031306a73bSElena Agostini }
14041306a73bSElena Agostini
14051306a73bSElena Agostini static int
cuda_gpu_remove(struct rte_pci_device * pci_dev)14061306a73bSElena Agostini cuda_gpu_remove(struct rte_pci_device *pci_dev)
14071306a73bSElena Agostini {
14081306a73bSElena Agostini struct rte_gpu *dev;
14091306a73bSElena Agostini int ret;
14101306a73bSElena Agostini uint8_t gpu_id;
14111306a73bSElena Agostini
141294220b39SElena Agostini if (pci_dev == NULL) {
141394220b39SElena Agostini rte_errno = ENODEV;
141494220b39SElena Agostini return -rte_errno;
141594220b39SElena Agostini }
14161306a73bSElena Agostini
14171306a73bSElena Agostini dev = rte_gpu_get_by_name(pci_dev->device.name);
14181306a73bSElena Agostini if (dev == NULL) {
14191306a73bSElena Agostini rte_cuda_log(ERR, "Couldn't find HW dev \"%s\" to uninitialise it",
14201306a73bSElena Agostini pci_dev->device.name);
142194220b39SElena Agostini rte_errno = ENODEV;
142294220b39SElena Agostini return -rte_errno;
14231306a73bSElena Agostini }
14241306a73bSElena Agostini gpu_id = dev->mpshared->info.dev_id;
14251306a73bSElena Agostini
14261306a73bSElena Agostini /* release dev from library */
14271306a73bSElena Agostini ret = rte_gpu_release(dev);
14281306a73bSElena Agostini if (ret)
14291306a73bSElena Agostini rte_cuda_log(ERR, "Device %i failed to uninit: %i", gpu_id, ret);
14301306a73bSElena Agostini
14311306a73bSElena Agostini rte_cuda_debug("Destroyed dev = %u", gpu_id);
14321306a73bSElena Agostini
14331306a73bSElena Agostini return 0;
14341306a73bSElena Agostini }
14351306a73bSElena Agostini
14361306a73bSElena Agostini static struct rte_pci_driver rte_cuda_driver = {
14371306a73bSElena Agostini .id_table = pci_id_cuda_map,
14381306a73bSElena Agostini .drv_flags = RTE_PCI_DRV_WC_ACTIVATE,
14391306a73bSElena Agostini .probe = cuda_gpu_probe,
14401306a73bSElena Agostini .remove = cuda_gpu_remove,
14411306a73bSElena Agostini };
14421306a73bSElena Agostini
14431306a73bSElena Agostini RTE_PMD_REGISTER_PCI(gpu_cuda, rte_cuda_driver);
14441306a73bSElena Agostini RTE_PMD_REGISTER_PCI_TABLE(gpu_cuda, pci_id_cuda_map);
14451306a73bSElena Agostini RTE_PMD_REGISTER_KMOD_DEP(gpu_cuda, "* nvidia & (nv_peer_mem | nvpeer_mem)");
1446