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> 91306a73bSElena Agostini #include <rte_bus_pci.h> 101306a73bSElena Agostini #include <rte_byteorder.h> 111306a73bSElena Agostini #include <rte_dev.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" 1924c77594SElena Agostini 201306a73bSElena Agostini #define CUDA_DRIVER_MIN_VERSION 11040 211306a73bSElena Agostini #define CUDA_API_MIN_VERSION 3020 221306a73bSElena Agostini 231306a73bSElena Agostini /* CUDA Driver functions loaded with dlsym() */ 241306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuInit)(unsigned int flags); 251306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuDriverGetVersion)(int *driverVersion); 261306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuGetProcAddress)(const char *symbol, 271306a73bSElena Agostini void **pfn, int cudaVersion, uint64_t flags); 281306a73bSElena Agostini 291306a73bSElena Agostini /* CUDA Driver functions loaded with cuGetProcAddress for versioning */ 301306a73bSElena Agostini static PFN_cuGetErrorString pfn_cuGetErrorString; 311306a73bSElena Agostini static PFN_cuGetErrorName pfn_cuGetErrorName; 321306a73bSElena Agostini static PFN_cuPointerSetAttribute pfn_cuPointerSetAttribute; 331306a73bSElena Agostini static PFN_cuDeviceGetAttribute pfn_cuDeviceGetAttribute; 341306a73bSElena Agostini static PFN_cuDeviceGetByPCIBusId pfn_cuDeviceGetByPCIBusId; 351306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRetain pfn_cuDevicePrimaryCtxRetain; 361306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRelease pfn_cuDevicePrimaryCtxRelease; 371306a73bSElena Agostini static PFN_cuDeviceTotalMem pfn_cuDeviceTotalMem; 381306a73bSElena Agostini static PFN_cuDeviceGetName pfn_cuDeviceGetName; 391306a73bSElena Agostini static PFN_cuCtxGetApiVersion pfn_cuCtxGetApiVersion; 401306a73bSElena Agostini static PFN_cuCtxSetCurrent pfn_cuCtxSetCurrent; 411306a73bSElena Agostini static PFN_cuCtxGetCurrent pfn_cuCtxGetCurrent; 421306a73bSElena Agostini static PFN_cuCtxGetDevice pfn_cuCtxGetDevice; 431306a73bSElena Agostini static PFN_cuCtxGetExecAffinity pfn_cuCtxGetExecAffinity; 441306a73bSElena Agostini static PFN_cuMemAlloc pfn_cuMemAlloc; 451306a73bSElena Agostini static PFN_cuMemFree pfn_cuMemFree; 461306a73bSElena Agostini static PFN_cuMemHostRegister pfn_cuMemHostRegister; 471306a73bSElena Agostini static PFN_cuMemHostUnregister pfn_cuMemHostUnregister; 481306a73bSElena Agostini static PFN_cuMemHostGetDevicePointer pfn_cuMemHostGetDevicePointer; 491306a73bSElena Agostini static PFN_cuFlushGPUDirectRDMAWrites pfn_cuFlushGPUDirectRDMAWrites; 501306a73bSElena Agostini 511306a73bSElena Agostini static void *cudalib; 521306a73bSElena Agostini static unsigned int cuda_api_version; 531306a73bSElena Agostini static int cuda_driver_version; 5424c77594SElena Agostini static gdr_t gdrc_h; 551306a73bSElena Agostini 561306a73bSElena Agostini /* NVIDIA GPU vendor */ 571306a73bSElena Agostini #define NVIDIA_GPU_VENDOR_ID (0x10de) 581306a73bSElena Agostini 591306a73bSElena Agostini /* NVIDIA GPU device IDs */ 601306a73bSElena Agostini #define NVIDIA_GPU_A100_40GB_DEVICE_ID (0x20f1) 611306a73bSElena Agostini #define NVIDIA_GPU_A100_80GB_DEVICE_ID (0x20b5) 6265ac1464SElena Agostini #define NVIDIA_GPU_A100_80GB_DPU_DEVICE_ID (0x20b8) 631306a73bSElena Agostini 641306a73bSElena Agostini #define NVIDIA_GPU_A30_24GB_DEVICE_ID (0x20b7) 651306a73bSElena Agostini #define NVIDIA_GPU_A10_24GB_DEVICE_ID (0x2236) 661306a73bSElena Agostini 6756b5bb50SElena Agostini #define NVIDIA_GPU_V100_32GB_SXM_DEVICE_ID (0x1db5) 6856b5bb50SElena Agostini #define NVIDIA_GPU_V100_32GB_PCIE_DEVICE_ID (0x1db6) 691306a73bSElena Agostini #define NVIDIA_GPU_V100_16GB_DEVICE_ID (0x1db4) 701306a73bSElena Agostini 711306a73bSElena Agostini #define NVIDIA_GPU_T4_16GB_DEVICE_ID (0x1eb8) 721306a73bSElena Agostini 731306a73bSElena Agostini #define CUDA_MAX_ALLOCATION_NUM 512 741306a73bSElena Agostini 751306a73bSElena Agostini #define GPU_PAGE_SHIFT 16 761306a73bSElena Agostini #define GPU_PAGE_SIZE (1UL << GPU_PAGE_SHIFT) 771306a73bSElena Agostini 7824c77594SElena Agostini RTE_LOG_REGISTER_DEFAULT(cuda_logtype, NOTICE); 791306a73bSElena Agostini 801306a73bSElena Agostini /* NVIDIA GPU address map */ 811306a73bSElena Agostini static const struct rte_pci_id pci_id_cuda_map[] = { 821306a73bSElena Agostini { 831306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 841306a73bSElena Agostini NVIDIA_GPU_A100_40GB_DEVICE_ID) 851306a73bSElena Agostini }, 861306a73bSElena Agostini { 871306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 881306a73bSElena Agostini NVIDIA_GPU_A100_80GB_DEVICE_ID) 891306a73bSElena Agostini }, 901306a73bSElena Agostini { 911306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 9265ac1464SElena Agostini NVIDIA_GPU_A100_80GB_DPU_DEVICE_ID) 9365ac1464SElena Agostini }, 9465ac1464SElena Agostini { 9565ac1464SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 961306a73bSElena Agostini NVIDIA_GPU_A30_24GB_DEVICE_ID) 971306a73bSElena Agostini }, 981306a73bSElena Agostini { 991306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 1001306a73bSElena Agostini NVIDIA_GPU_A10_24GB_DEVICE_ID) 1011306a73bSElena Agostini }, 1021306a73bSElena Agostini { 1031306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 10456b5bb50SElena Agostini NVIDIA_GPU_V100_32GB_SXM_DEVICE_ID) 10556b5bb50SElena Agostini }, 10656b5bb50SElena Agostini { 10756b5bb50SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 10856b5bb50SElena Agostini NVIDIA_GPU_V100_32GB_PCIE_DEVICE_ID) 1091306a73bSElena Agostini }, 1101306a73bSElena Agostini { 1111306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 1121306a73bSElena Agostini NVIDIA_GPU_V100_16GB_DEVICE_ID) 1131306a73bSElena Agostini }, 1141306a73bSElena Agostini { 1151306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 1161306a73bSElena Agostini NVIDIA_GPU_T4_16GB_DEVICE_ID) 1171306a73bSElena Agostini }, 1181306a73bSElena Agostini { 1191306a73bSElena Agostini .device_id = 0 1201306a73bSElena Agostini } 1211306a73bSElena Agostini }; 1221306a73bSElena Agostini 1231306a73bSElena Agostini /* Device private info */ 1241306a73bSElena Agostini struct cuda_info { 1251306a73bSElena Agostini char gpu_name[RTE_DEV_NAME_MAX_LEN]; 1261306a73bSElena Agostini CUdevice cu_dev; 1271306a73bSElena Agostini int gdr_supported; 1281306a73bSElena Agostini int gdr_write_ordering; 1291306a73bSElena Agostini int gdr_flush_type; 1301306a73bSElena Agostini }; 1311306a73bSElena Agostini 1321306a73bSElena Agostini /* Type of memory allocated by CUDA driver */ 1331306a73bSElena Agostini enum mem_type { 1341306a73bSElena Agostini GPU_MEM = 0, 1351306a73bSElena Agostini CPU_REGISTERED, 1361306a73bSElena Agostini GPU_REGISTERED /* Not used yet */ 1371306a73bSElena Agostini }; 1381306a73bSElena Agostini 1391306a73bSElena Agostini /* key associated to a memory address */ 1401306a73bSElena Agostini typedef uintptr_t cuda_ptr_key; 1411306a73bSElena Agostini 1421306a73bSElena Agostini /* Single entry of the memory list */ 1431306a73bSElena Agostini struct mem_entry { 1441306a73bSElena Agostini CUdeviceptr ptr_d; 145c8557ed4SElena Agostini CUdeviceptr ptr_orig_d; 1461306a73bSElena Agostini void *ptr_h; 1471306a73bSElena Agostini size_t size; 148c8557ed4SElena Agostini size_t size_orig; 1491306a73bSElena Agostini struct rte_gpu *dev; 1501306a73bSElena Agostini CUcontext ctx; 1511306a73bSElena Agostini cuda_ptr_key pkey; 1521306a73bSElena Agostini enum mem_type mtype; 15324c77594SElena Agostini gdr_mh_t mh; 1541306a73bSElena Agostini struct mem_entry *prev; 1551306a73bSElena Agostini struct mem_entry *next; 1561306a73bSElena Agostini }; 1571306a73bSElena Agostini 1581306a73bSElena Agostini static struct mem_entry *mem_alloc_list_head; 1591306a73bSElena Agostini static struct mem_entry *mem_alloc_list_tail; 1601306a73bSElena Agostini static uint32_t mem_alloc_list_last_elem; 1611306a73bSElena Agostini 1621306a73bSElena Agostini /* Load the CUDA symbols */ 1631306a73bSElena Agostini 1641306a73bSElena Agostini static int 1651306a73bSElena Agostini cuda_loader(void) 1661306a73bSElena Agostini { 1671306a73bSElena Agostini char cuda_path[1024]; 1681306a73bSElena Agostini 1691306a73bSElena Agostini if (getenv("CUDA_PATH_L") == NULL) 1701306a73bSElena Agostini snprintf(cuda_path, 1024, "%s", "libcuda.so"); 1711306a73bSElena Agostini else 172*0105d49eSElena Agostini snprintf(cuda_path, 1024, "%s/%s", getenv("CUDA_PATH_L"), "libcuda.so"); 1731306a73bSElena Agostini 1741306a73bSElena Agostini cudalib = dlopen(cuda_path, RTLD_LAZY); 1751306a73bSElena Agostini if (cudalib == NULL) { 1761306a73bSElena Agostini rte_cuda_log(ERR, "Failed to find CUDA library in %s (CUDA_PATH_L=%s)", 1771306a73bSElena Agostini cuda_path, getenv("CUDA_PATH_L")); 1781306a73bSElena Agostini return -1; 1791306a73bSElena Agostini } 1801306a73bSElena Agostini 1811306a73bSElena Agostini return 0; 1821306a73bSElena Agostini } 1831306a73bSElena Agostini 1841306a73bSElena Agostini static int 1851306a73bSElena Agostini cuda_sym_func_loader(void) 1861306a73bSElena Agostini { 1871306a73bSElena Agostini if (cudalib == NULL) 1881306a73bSElena Agostini return -1; 1891306a73bSElena Agostini 1901306a73bSElena Agostini sym_cuInit = dlsym(cudalib, "cuInit"); 1911306a73bSElena Agostini if (sym_cuInit == NULL) { 1921306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuInit"); 1931306a73bSElena Agostini return -1; 1941306a73bSElena Agostini } 1951306a73bSElena Agostini 1961306a73bSElena Agostini sym_cuDriverGetVersion = dlsym(cudalib, "cuDriverGetVersion"); 1971306a73bSElena Agostini if (sym_cuDriverGetVersion == NULL) { 1981306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuDriverGetVersion"); 1991306a73bSElena Agostini return -1; 2001306a73bSElena Agostini } 2011306a73bSElena Agostini 2021306a73bSElena Agostini sym_cuGetProcAddress = dlsym(cudalib, "cuGetProcAddress"); 2031306a73bSElena Agostini if (sym_cuGetProcAddress == NULL) { 2041306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuGetProcAddress"); 2051306a73bSElena Agostini return -1; 2061306a73bSElena Agostini } 2071306a73bSElena Agostini 2081306a73bSElena Agostini return 0; 2091306a73bSElena Agostini } 2101306a73bSElena Agostini 2111306a73bSElena Agostini static int 2121306a73bSElena Agostini cuda_pfn_func_loader(void) 2131306a73bSElena Agostini { 2141306a73bSElena Agostini CUresult res; 2151306a73bSElena Agostini 2161306a73bSElena Agostini res = sym_cuGetProcAddress("cuGetErrorString", 2171306a73bSElena Agostini (void **) (&pfn_cuGetErrorString), cuda_driver_version, 0); 2181306a73bSElena Agostini if (res != 0) { 2191306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorString failed with %d", res); 2201306a73bSElena Agostini return -1; 2211306a73bSElena Agostini } 2221306a73bSElena Agostini 2231306a73bSElena Agostini res = sym_cuGetProcAddress("cuGetErrorName", 2241306a73bSElena Agostini (void **)(&pfn_cuGetErrorName), cuda_driver_version, 0); 2251306a73bSElena Agostini if (res != 0) { 2261306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorName failed with %d", res); 2271306a73bSElena Agostini return -1; 2281306a73bSElena Agostini } 2291306a73bSElena Agostini 2301306a73bSElena Agostini res = sym_cuGetProcAddress("cuPointerSetAttribute", 2311306a73bSElena Agostini (void **)(&pfn_cuPointerSetAttribute), cuda_driver_version, 0); 2321306a73bSElena Agostini if (res != 0) { 2331306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuPointerSetAttribute failed with %d", res); 2341306a73bSElena Agostini return -1; 2351306a73bSElena Agostini } 2361306a73bSElena Agostini 2371306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetAttribute", 2381306a73bSElena Agostini (void **)(&pfn_cuDeviceGetAttribute), cuda_driver_version, 0); 2391306a73bSElena Agostini if (res != 0) { 2401306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetAttribute failed with %d", res); 2411306a73bSElena Agostini return -1; 2421306a73bSElena Agostini } 2431306a73bSElena Agostini 2441306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetByPCIBusId", 2451306a73bSElena Agostini (void **)(&pfn_cuDeviceGetByPCIBusId), cuda_driver_version, 0); 2461306a73bSElena Agostini if (res != 0) { 2471306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetByPCIBusId failed with %d", res); 2481306a73bSElena Agostini return -1; 2491306a73bSElena Agostini } 2501306a73bSElena Agostini 2511306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetName", 2521306a73bSElena Agostini (void **)(&pfn_cuDeviceGetName), cuda_driver_version, 0); 2531306a73bSElena Agostini if (res != 0) { 2541306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetName failed with %d", res); 2551306a73bSElena Agostini return -1; 2561306a73bSElena Agostini } 2571306a73bSElena Agostini 2581306a73bSElena Agostini res = sym_cuGetProcAddress("cuDevicePrimaryCtxRetain", 2591306a73bSElena Agostini (void **)(&pfn_cuDevicePrimaryCtxRetain), cuda_driver_version, 0); 2601306a73bSElena Agostini if (res != 0) { 2611306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRetain failed with %d", res); 2621306a73bSElena Agostini return -1; 2631306a73bSElena Agostini } 2641306a73bSElena Agostini 2651306a73bSElena Agostini res = sym_cuGetProcAddress("cuDevicePrimaryCtxRelease", 2661306a73bSElena Agostini (void **)(&pfn_cuDevicePrimaryCtxRelease), cuda_driver_version, 0); 2671306a73bSElena Agostini if (res != 0) { 2681306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRelease failed with %d", res); 2691306a73bSElena Agostini return -1; 2701306a73bSElena Agostini } 2711306a73bSElena Agostini 2721306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceTotalMem", 2731306a73bSElena Agostini (void **)(&pfn_cuDeviceTotalMem), cuda_driver_version, 0); 2741306a73bSElena Agostini if (res != 0) { 2751306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceTotalMem failed with %d", res); 2761306a73bSElena Agostini return -1; 2771306a73bSElena Agostini } 2781306a73bSElena Agostini 2791306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetApiVersion", 2801306a73bSElena Agostini (void **)(&pfn_cuCtxGetApiVersion), cuda_driver_version, 0); 2811306a73bSElena Agostini if (res != 0) { 2821306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetApiVersion failed with %d", res); 2831306a73bSElena Agostini return -1; 2841306a73bSElena Agostini } 2851306a73bSElena Agostini 2861306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetDevice", 2871306a73bSElena Agostini (void **)(&pfn_cuCtxGetDevice), cuda_driver_version, 0); 2881306a73bSElena Agostini if (res != 0) { 2891306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetDevice failed with %d", res); 2901306a73bSElena Agostini return -1; 2911306a73bSElena Agostini } 2921306a73bSElena Agostini 2931306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxSetCurrent", 2941306a73bSElena Agostini (void **)(&pfn_cuCtxSetCurrent), cuda_driver_version, 0); 2951306a73bSElena Agostini if (res != 0) { 2961306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxSetCurrent failed with %d", res); 2971306a73bSElena Agostini return -1; 2981306a73bSElena Agostini } 2991306a73bSElena Agostini 3001306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetCurrent", 3011306a73bSElena Agostini (void **)(&pfn_cuCtxGetCurrent), cuda_driver_version, 0); 3021306a73bSElena Agostini if (res != 0) { 3031306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetCurrent failed with %d", res); 3041306a73bSElena Agostini return -1; 3051306a73bSElena Agostini } 3061306a73bSElena Agostini 3071306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetExecAffinity", 3081306a73bSElena Agostini (void **)(&pfn_cuCtxGetExecAffinity), cuda_driver_version, 0); 3091306a73bSElena Agostini if (res != 0) { 3101306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetExecAffinity failed with %d", res); 3111306a73bSElena Agostini return -1; 3121306a73bSElena Agostini } 3131306a73bSElena Agostini 3141306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemAlloc", 3151306a73bSElena Agostini (void **)(&pfn_cuMemAlloc), cuda_driver_version, 0); 3161306a73bSElena Agostini if (res != 0) { 3171306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemAlloc failed with %d", res); 3181306a73bSElena Agostini return -1; 3191306a73bSElena Agostini } 3201306a73bSElena Agostini 3211306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemFree", 3221306a73bSElena Agostini (void **)(&pfn_cuMemFree), cuda_driver_version, 0); 3231306a73bSElena Agostini if (res != 0) { 3241306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemFree failed with %d", res); 3251306a73bSElena Agostini return -1; 3261306a73bSElena Agostini } 3271306a73bSElena Agostini 3281306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostRegister", 3291306a73bSElena Agostini (void **)(&pfn_cuMemHostRegister), cuda_driver_version, 0); 3301306a73bSElena Agostini if (res != 0) { 3311306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostRegister failed with %d", res); 3321306a73bSElena Agostini return -1; 3331306a73bSElena Agostini } 3341306a73bSElena Agostini 3351306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostUnregister", 3361306a73bSElena Agostini (void **)(&pfn_cuMemHostUnregister), cuda_driver_version, 0); 3371306a73bSElena Agostini if (res != 0) { 3381306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostUnregister failed with %d", res); 3391306a73bSElena Agostini return -1; 3401306a73bSElena Agostini } 3411306a73bSElena Agostini 3421306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostGetDevicePointer", 3431306a73bSElena Agostini (void **)(&pfn_cuMemHostGetDevicePointer), cuda_driver_version, 0); 3441306a73bSElena Agostini if (res != 0) { 3451306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostGetDevicePointer failed with %d", res); 3461306a73bSElena Agostini return -1; 3471306a73bSElena Agostini } 3481306a73bSElena Agostini 3491306a73bSElena Agostini res = sym_cuGetProcAddress("cuFlushGPUDirectRDMAWrites", 3501306a73bSElena Agostini (void **)(&pfn_cuFlushGPUDirectRDMAWrites), cuda_driver_version, 0); 3511306a73bSElena Agostini if (res != 0) { 3521306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve cuFlushGPUDirectRDMAWrites failed with %d", res); 3531306a73bSElena Agostini return -1; 3541306a73bSElena Agostini } 3551306a73bSElena Agostini 3561306a73bSElena Agostini return 0; 3571306a73bSElena Agostini } 3581306a73bSElena Agostini 3591306a73bSElena Agostini /* Generate a key from a memory pointer */ 3601306a73bSElena Agostini static cuda_ptr_key 3611306a73bSElena Agostini get_hash_from_ptr(void *ptr) 3621306a73bSElena Agostini { 3631306a73bSElena Agostini return (uintptr_t)ptr; 3641306a73bSElena Agostini } 3651306a73bSElena Agostini 3661306a73bSElena Agostini static uint32_t 3671306a73bSElena Agostini mem_list_count_item(void) 3681306a73bSElena Agostini { 3691306a73bSElena Agostini return mem_alloc_list_last_elem; 3701306a73bSElena Agostini } 3711306a73bSElena Agostini 3721306a73bSElena Agostini /* Initiate list of memory allocations if not done yet */ 3731306a73bSElena Agostini static struct mem_entry * 3741306a73bSElena Agostini mem_list_add_item(void) 3751306a73bSElena Agostini { 3761306a73bSElena Agostini /* Initiate list of memory allocations if not done yet */ 3771306a73bSElena Agostini if (mem_alloc_list_head == NULL) { 3781306a73bSElena Agostini mem_alloc_list_head = rte_zmalloc(NULL, 3791306a73bSElena Agostini sizeof(struct mem_entry), 3801306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 3811306a73bSElena Agostini if (mem_alloc_list_head == NULL) { 3821306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for memory list"); 3831306a73bSElena Agostini return NULL; 3841306a73bSElena Agostini } 3851306a73bSElena Agostini 3861306a73bSElena Agostini mem_alloc_list_head->next = NULL; 3871306a73bSElena Agostini mem_alloc_list_head->prev = NULL; 3881306a73bSElena Agostini mem_alloc_list_tail = mem_alloc_list_head; 3891306a73bSElena Agostini } else { 3901306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = rte_zmalloc(NULL, 3911306a73bSElena Agostini sizeof(struct mem_entry), 3921306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 3931306a73bSElena Agostini 3941306a73bSElena Agostini if (mem_alloc_list_cur == NULL) { 3951306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for memory list"); 3961306a73bSElena Agostini return NULL; 3971306a73bSElena Agostini } 3981306a73bSElena Agostini 3991306a73bSElena Agostini mem_alloc_list_tail->next = mem_alloc_list_cur; 4001306a73bSElena Agostini mem_alloc_list_cur->prev = mem_alloc_list_tail; 4011306a73bSElena Agostini mem_alloc_list_tail = mem_alloc_list_tail->next; 4021306a73bSElena Agostini mem_alloc_list_tail->next = NULL; 4031306a73bSElena Agostini } 4041306a73bSElena Agostini 4051306a73bSElena Agostini mem_alloc_list_last_elem++; 4061306a73bSElena Agostini 4071306a73bSElena Agostini return mem_alloc_list_tail; 4081306a73bSElena Agostini } 4091306a73bSElena Agostini 4101306a73bSElena Agostini static struct mem_entry * 4111306a73bSElena Agostini mem_list_find_item(cuda_ptr_key pk) 4121306a73bSElena Agostini { 4131306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = NULL; 4141306a73bSElena Agostini 4151306a73bSElena Agostini if (mem_alloc_list_head == NULL) { 4161306a73bSElena Agostini rte_cuda_log(ERR, "Memory list doesn't exist"); 4171306a73bSElena Agostini return NULL; 4181306a73bSElena Agostini } 4191306a73bSElena Agostini 4201306a73bSElena Agostini if (mem_list_count_item() == 0) { 4211306a73bSElena Agostini rte_cuda_log(ERR, "No items in memory list"); 4221306a73bSElena Agostini return NULL; 4231306a73bSElena Agostini } 4241306a73bSElena Agostini 4251306a73bSElena Agostini mem_alloc_list_cur = mem_alloc_list_head; 4261306a73bSElena Agostini 4271306a73bSElena Agostini while (mem_alloc_list_cur != NULL) { 4281306a73bSElena Agostini if (mem_alloc_list_cur->pkey == pk) 4291306a73bSElena Agostini return mem_alloc_list_cur; 4301306a73bSElena Agostini mem_alloc_list_cur = mem_alloc_list_cur->next; 4311306a73bSElena Agostini } 4321306a73bSElena Agostini 4331306a73bSElena Agostini return mem_alloc_list_cur; 4341306a73bSElena Agostini } 4351306a73bSElena Agostini 4361306a73bSElena Agostini static int 4371306a73bSElena Agostini mem_list_del_item(cuda_ptr_key pk) 4381306a73bSElena Agostini { 4391306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = NULL; 4401306a73bSElena Agostini 4411306a73bSElena Agostini mem_alloc_list_cur = mem_list_find_item(pk); 4421306a73bSElena Agostini if (mem_alloc_list_cur == NULL) 4431306a73bSElena Agostini return -EINVAL; 4441306a73bSElena Agostini 4451306a73bSElena Agostini /* if key is in head */ 44698ddd04cSElena Agostini if (mem_alloc_list_cur->prev == NULL) { 4471306a73bSElena Agostini mem_alloc_list_head = mem_alloc_list_cur->next; 44898ddd04cSElena Agostini if (mem_alloc_list_head != NULL) 44998ddd04cSElena Agostini mem_alloc_list_head->prev = NULL; 45098ddd04cSElena Agostini } else { 4511306a73bSElena Agostini mem_alloc_list_cur->prev->next = mem_alloc_list_cur->next; 4521306a73bSElena Agostini if (mem_alloc_list_cur->next != NULL) 4531306a73bSElena Agostini mem_alloc_list_cur->next->prev = mem_alloc_list_cur->prev; 4541306a73bSElena Agostini } 4551306a73bSElena Agostini 4561306a73bSElena Agostini rte_free(mem_alloc_list_cur); 4571306a73bSElena Agostini 4581306a73bSElena Agostini mem_alloc_list_last_elem--; 4591306a73bSElena Agostini 4601306a73bSElena Agostini return 0; 4611306a73bSElena Agostini } 4621306a73bSElena Agostini 4631306a73bSElena Agostini static int 4641306a73bSElena Agostini cuda_dev_info_get(struct rte_gpu *dev, struct rte_gpu_info *info) 4651306a73bSElena Agostini { 4661306a73bSElena Agostini int ret = 0; 4671306a73bSElena Agostini CUresult res; 4681306a73bSElena Agostini struct rte_gpu_info parent_info; 4691306a73bSElena Agostini CUexecAffinityParam affinityPrm; 4701306a73bSElena Agostini const char *err_string; 4711306a73bSElena Agostini struct cuda_info *private; 4721306a73bSElena Agostini CUcontext current_ctx; 4731306a73bSElena Agostini CUcontext input_ctx; 4741306a73bSElena Agostini 47594220b39SElena Agostini if (dev == NULL) { 47694220b39SElena Agostini rte_errno = ENODEV; 47794220b39SElena Agostini return -rte_errno; 47894220b39SElena Agostini } 4791306a73bSElena Agostini 4801306a73bSElena Agostini /* Child initialization time probably called by rte_gpu_add_child() */ 4811306a73bSElena Agostini if (dev->mpshared->info.parent != RTE_GPU_ID_NONE && 4821306a73bSElena Agostini dev->mpshared->dev_private == NULL) { 4831306a73bSElena Agostini /* Store current ctx */ 4841306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 4851306a73bSElena Agostini if (res != 0) { 4861306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 4871306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 4881306a73bSElena Agostini err_string); 48994220b39SElena Agostini rte_errno = EPERM; 49094220b39SElena Agostini return -rte_errno; 4911306a73bSElena Agostini } 4921306a73bSElena Agostini 4931306a73bSElena Agostini /* Set child ctx as current ctx */ 4941306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 4951306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 4961306a73bSElena Agostini if (res != 0) { 4971306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 4981306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 4991306a73bSElena Agostini err_string); 50094220b39SElena Agostini rte_errno = EPERM; 50194220b39SElena Agostini return -rte_errno; 5021306a73bSElena Agostini } 5031306a73bSElena Agostini 5041306a73bSElena Agostini /* 5051306a73bSElena Agostini * Ctx capacity info 5061306a73bSElena Agostini */ 5071306a73bSElena Agostini 5081306a73bSElena Agostini /* MPS compatible */ 5091306a73bSElena Agostini res = pfn_cuCtxGetExecAffinity(&affinityPrm, 5101306a73bSElena Agostini CU_EXEC_AFFINITY_TYPE_SM_COUNT); 5111306a73bSElena Agostini if (res != 0) { 5121306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5131306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetExecAffinity failed with %s", 5141306a73bSElena Agostini err_string); 5151306a73bSElena Agostini } 5161306a73bSElena Agostini dev->mpshared->info.processor_count = 5171306a73bSElena Agostini (uint32_t)affinityPrm.param.smCount.val; 5181306a73bSElena Agostini 5191306a73bSElena Agostini ret = rte_gpu_info_get(dev->mpshared->info.parent, &parent_info); 52094220b39SElena Agostini if (ret) { 52194220b39SElena Agostini rte_errno = ENODEV; 52294220b39SElena Agostini return -rte_errno; 52394220b39SElena Agostini } 5241306a73bSElena Agostini dev->mpshared->info.total_memory = parent_info.total_memory; 5251306a73bSElena Agostini 5261306a73bSElena Agostini /* 5271306a73bSElena Agostini * GPU Device private info 5281306a73bSElena Agostini */ 5291306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL, 5301306a73bSElena Agostini sizeof(struct cuda_info), 5311306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 5321306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) { 5331306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private"); 53494220b39SElena Agostini rte_errno = EPERM; 53594220b39SElena Agostini return -rte_errno; 5361306a73bSElena Agostini } 5371306a73bSElena Agostini 5381306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 5391306a73bSElena Agostini 5401306a73bSElena Agostini res = pfn_cuCtxGetDevice(&(private->cu_dev)); 5411306a73bSElena Agostini if (res != 0) { 5421306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5431306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetDevice failed with %s", 5441306a73bSElena Agostini err_string); 54594220b39SElena Agostini rte_errno = EPERM; 54694220b39SElena Agostini return -rte_errno; 5471306a73bSElena Agostini } 5481306a73bSElena Agostini 5491306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name, 5501306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN, private->cu_dev); 5511306a73bSElena Agostini if (res != 0) { 5521306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5531306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s", 5541306a73bSElena Agostini err_string); 55594220b39SElena Agostini rte_errno = EPERM; 55694220b39SElena Agostini return -rte_errno; 5571306a73bSElena Agostini } 5581306a73bSElena Agostini 5591306a73bSElena Agostini /* Restore original ctx as current ctx */ 5601306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 5611306a73bSElena Agostini if (res != 0) { 5621306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5631306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 5641306a73bSElena Agostini err_string); 56594220b39SElena Agostini rte_errno = EPERM; 56694220b39SElena Agostini return -rte_errno; 5671306a73bSElena Agostini } 5681306a73bSElena Agostini } 5691306a73bSElena Agostini 5701306a73bSElena Agostini *info = dev->mpshared->info; 5711306a73bSElena Agostini 5721306a73bSElena Agostini return 0; 5731306a73bSElena Agostini } 5741306a73bSElena Agostini 5751306a73bSElena Agostini /* 5761306a73bSElena Agostini * GPU Memory 5771306a73bSElena Agostini */ 5781306a73bSElena Agostini 5791306a73bSElena Agostini static int 580c8557ed4SElena Agostini cuda_mem_alloc(struct rte_gpu *dev, size_t size, unsigned int align, void **ptr) 5811306a73bSElena Agostini { 5821306a73bSElena Agostini CUresult res; 5831306a73bSElena Agostini const char *err_string; 5841306a73bSElena Agostini CUcontext current_ctx; 5851306a73bSElena Agostini CUcontext input_ctx; 5861306a73bSElena Agostini unsigned int flag = 1; 5871306a73bSElena Agostini 5881306a73bSElena Agostini if (dev == NULL) 5891306a73bSElena Agostini return -ENODEV; 5901306a73bSElena Agostini 5911306a73bSElena Agostini /* Store current ctx */ 5921306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 5931306a73bSElena Agostini if (res != 0) { 5941306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5951306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 5961306a73bSElena Agostini err_string); 59794220b39SElena Agostini rte_errno = EPERM; 59894220b39SElena Agostini return -rte_errno; 5991306a73bSElena Agostini } 6001306a73bSElena Agostini 6011306a73bSElena Agostini /* Set child ctx as current ctx */ 6021306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 6031306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 6041306a73bSElena Agostini if (res != 0) { 6051306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6061306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 6071306a73bSElena Agostini err_string); 60894220b39SElena Agostini rte_errno = EPERM; 60994220b39SElena Agostini return -rte_errno; 6101306a73bSElena Agostini } 6111306a73bSElena Agostini 6121306a73bSElena Agostini /* Get next memory list item */ 6131306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item(); 61494220b39SElena Agostini if (mem_alloc_list_tail == NULL) { 61594220b39SElena Agostini rte_errno = EPERM; 61694220b39SElena Agostini return -rte_errno; 61794220b39SElena Agostini } 6181306a73bSElena Agostini 6191306a73bSElena Agostini /* Allocate memory */ 6201306a73bSElena Agostini mem_alloc_list_tail->size = size; 621c8557ed4SElena Agostini mem_alloc_list_tail->size_orig = size + align; 622c8557ed4SElena Agostini 623c8557ed4SElena Agostini res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d), 624c8557ed4SElena Agostini mem_alloc_list_tail->size_orig); 6251306a73bSElena Agostini if (res != 0) { 6261306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6271306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 6281306a73bSElena Agostini err_string); 62994220b39SElena Agostini rte_errno = EPERM; 63094220b39SElena Agostini return -rte_errno; 6311306a73bSElena Agostini } 6321306a73bSElena Agostini 633c8557ed4SElena Agostini /* Align memory address */ 634c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d; 635c8557ed4SElena Agostini if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align) 636c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d += (align - 637c8557ed4SElena Agostini (((uintptr_t)mem_alloc_list_tail->ptr_d) % align)); 638c8557ed4SElena Agostini 6391306a73bSElena Agostini /* GPUDirect RDMA attribute required */ 6401306a73bSElena Agostini res = pfn_cuPointerSetAttribute(&flag, 6411306a73bSElena Agostini CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, 6421306a73bSElena Agostini mem_alloc_list_tail->ptr_d); 6431306a73bSElena Agostini if (res != 0) { 6441306a73bSElena Agostini rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for " 6451306a73bSElena Agostini "GPU memory at %"PRIu32", err %d", 6461306a73bSElena Agostini (uint32_t)mem_alloc_list_tail->ptr_d, res); 64794220b39SElena Agostini rte_errno = EPERM; 64894220b39SElena Agostini return -rte_errno; 6491306a73bSElena Agostini } 6501306a73bSElena Agostini 6511306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_d); 6521306a73bSElena Agostini mem_alloc_list_tail->ptr_h = NULL; 6531306a73bSElena Agostini mem_alloc_list_tail->dev = dev; 6541306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 6551306a73bSElena Agostini mem_alloc_list_tail->mtype = GPU_MEM; 6561306a73bSElena Agostini 6571306a73bSElena Agostini /* Restore original ctx as current ctx */ 6581306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 6591306a73bSElena Agostini if (res != 0) { 6601306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6611306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 6621306a73bSElena Agostini err_string); 66394220b39SElena Agostini rte_errno = EPERM; 66494220b39SElena Agostini return -rte_errno; 6651306a73bSElena Agostini } 6661306a73bSElena Agostini 6671306a73bSElena Agostini *ptr = (void *)mem_alloc_list_tail->ptr_d; 6681306a73bSElena Agostini 6691306a73bSElena Agostini return 0; 6701306a73bSElena Agostini } 6711306a73bSElena Agostini 6721306a73bSElena Agostini static int 6731306a73bSElena Agostini cuda_mem_register(struct rte_gpu *dev, size_t size, void *ptr) 6741306a73bSElena Agostini { 6751306a73bSElena Agostini CUresult res; 6761306a73bSElena Agostini const char *err_string; 6771306a73bSElena Agostini CUcontext current_ctx; 6781306a73bSElena Agostini CUcontext input_ctx; 6791306a73bSElena Agostini unsigned int flag = 1; 6801306a73bSElena Agostini int use_ptr_h = 0; 6811306a73bSElena Agostini 6821306a73bSElena Agostini if (dev == NULL) 6831306a73bSElena Agostini return -ENODEV; 6841306a73bSElena Agostini 6851306a73bSElena Agostini /* Store current ctx */ 6861306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 6871306a73bSElena Agostini if (res != 0) { 6881306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6891306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 6901306a73bSElena Agostini err_string); 69194220b39SElena Agostini rte_errno = EPERM; 69294220b39SElena Agostini return -rte_errno; 6931306a73bSElena Agostini } 6941306a73bSElena Agostini 6951306a73bSElena Agostini /* Set child ctx as current ctx */ 6961306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 6971306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 6981306a73bSElena Agostini if (res != 0) { 6991306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7001306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 7011306a73bSElena Agostini err_string); 70294220b39SElena Agostini rte_errno = EPERM; 70394220b39SElena Agostini return -rte_errno; 7041306a73bSElena Agostini } 7051306a73bSElena Agostini 7061306a73bSElena Agostini /* Get next memory list item */ 7071306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item(); 70894220b39SElena Agostini if (mem_alloc_list_tail == NULL) { 70994220b39SElena Agostini rte_errno = EPERM; 71094220b39SElena Agostini return -rte_errno; 71194220b39SElena Agostini } 7121306a73bSElena Agostini 7131306a73bSElena Agostini /* Allocate memory */ 7141306a73bSElena Agostini mem_alloc_list_tail->size = size; 7151306a73bSElena Agostini mem_alloc_list_tail->ptr_h = ptr; 7161306a73bSElena Agostini 7171306a73bSElena Agostini res = pfn_cuMemHostRegister(mem_alloc_list_tail->ptr_h, 7181306a73bSElena Agostini mem_alloc_list_tail->size, 7191306a73bSElena Agostini CU_MEMHOSTREGISTER_PORTABLE | 7201306a73bSElena Agostini CU_MEMHOSTREGISTER_DEVICEMAP); 7211306a73bSElena Agostini if (res != 0) { 7221306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7231306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostRegister failed with %s ptr %p size %zd", 7241306a73bSElena Agostini err_string, 7251306a73bSElena Agostini mem_alloc_list_tail->ptr_h, 7261306a73bSElena Agostini mem_alloc_list_tail->size); 72794220b39SElena Agostini rte_errno = EPERM; 72894220b39SElena Agostini return -rte_errno; 7291306a73bSElena Agostini } 7301306a73bSElena Agostini 7311306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(use_ptr_h), 7321306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM, 7331306a73bSElena Agostini ((struct cuda_info *)(dev->mpshared->dev_private))->cu_dev); 7341306a73bSElena Agostini if (res != 0) { 7351306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7361306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 7371306a73bSElena Agostini err_string); 73894220b39SElena Agostini rte_errno = EPERM; 73994220b39SElena Agostini return -rte_errno; 7401306a73bSElena Agostini } 7411306a73bSElena Agostini 7421306a73bSElena Agostini if (use_ptr_h == 0) { 7431306a73bSElena Agostini res = pfn_cuMemHostGetDevicePointer(&(mem_alloc_list_tail->ptr_d), 7441306a73bSElena Agostini mem_alloc_list_tail->ptr_h, 0); 7451306a73bSElena Agostini if (res != 0) { 7461306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7471306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostGetDevicePointer failed with %s", 7481306a73bSElena Agostini err_string); 74994220b39SElena Agostini rte_errno = EPERM; 75094220b39SElena Agostini return -rte_errno; 7511306a73bSElena Agostini } 7521306a73bSElena Agostini 7531306a73bSElena Agostini if ((uintptr_t)mem_alloc_list_tail->ptr_d != 7541306a73bSElena Agostini (uintptr_t)mem_alloc_list_tail->ptr_h) { 7551306a73bSElena Agostini rte_cuda_log(ERR, "Host input pointer is different wrt GPU registered pointer"); 75694220b39SElena Agostini rte_errno = ENOTSUP; 75794220b39SElena Agostini return -rte_errno; 7581306a73bSElena Agostini } 7591306a73bSElena Agostini } else { 7601306a73bSElena Agostini mem_alloc_list_tail->ptr_d = (CUdeviceptr)mem_alloc_list_tail->ptr_h; 7611306a73bSElena Agostini } 7621306a73bSElena Agostini 7631306a73bSElena Agostini /* GPUDirect RDMA attribute required */ 7641306a73bSElena Agostini res = pfn_cuPointerSetAttribute(&flag, 7651306a73bSElena Agostini CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, 7661306a73bSElena Agostini mem_alloc_list_tail->ptr_d); 7671306a73bSElena Agostini if (res != 0) { 7681306a73bSElena Agostini rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for GPU memory at %"PRIu32 7691306a73bSElena Agostini ", err %d", (uint32_t)mem_alloc_list_tail->ptr_d, res); 77094220b39SElena Agostini rte_errno = EPERM; 77194220b39SElena Agostini return -rte_errno; 7721306a73bSElena Agostini } 7731306a73bSElena Agostini 7741306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_h); 7751306a73bSElena Agostini mem_alloc_list_tail->size = size; 7761306a73bSElena Agostini mem_alloc_list_tail->dev = dev; 7771306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 7781306a73bSElena Agostini mem_alloc_list_tail->mtype = CPU_REGISTERED; 779c8557ed4SElena Agostini mem_alloc_list_tail->ptr_orig_d = mem_alloc_list_tail->ptr_d; 7801306a73bSElena Agostini 7811306a73bSElena Agostini /* Restore original ctx as current ctx */ 7821306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 7831306a73bSElena Agostini if (res != 0) { 7841306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7851306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 7861306a73bSElena Agostini err_string); 78794220b39SElena Agostini rte_errno = EPERM; 78894220b39SElena Agostini return -rte_errno; 7891306a73bSElena Agostini } 7901306a73bSElena Agostini 7911306a73bSElena Agostini return 0; 7921306a73bSElena Agostini } 7931306a73bSElena Agostini 7941306a73bSElena Agostini static int 79524c77594SElena Agostini cuda_mem_cpu_map(struct rte_gpu *dev, __rte_unused size_t size, void *ptr_in, void **ptr_out) 79624c77594SElena Agostini { 79724c77594SElena Agostini struct mem_entry *mem_item; 79824c77594SElena Agostini cuda_ptr_key hk; 79924c77594SElena Agostini 80024c77594SElena Agostini if (dev == NULL) 80124c77594SElena Agostini return -ENODEV; 80224c77594SElena Agostini 80324c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in); 80424c77594SElena Agostini 80524c77594SElena Agostini mem_item = mem_list_find_item(hk); 80624c77594SElena Agostini if (mem_item == NULL) { 80724c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in); 80824c77594SElena Agostini rte_errno = EPERM; 80924c77594SElena Agostini return -rte_errno; 81024c77594SElena Agostini } 81124c77594SElena Agostini 81224c77594SElena Agostini if (mem_item->mtype != GPU_MEM) { 81324c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p is not GPU memory type.", ptr_in); 81424c77594SElena Agostini rte_errno = EPERM; 81524c77594SElena Agostini return -rte_errno; 81624c77594SElena Agostini } 81724c77594SElena Agostini 81824c77594SElena Agostini if (mem_item->size != size) 81924c77594SElena Agostini rte_cuda_log(WARNING, 82024c77594SElena Agostini "Can't expose memory area with size (%zd) different from original size (%zd).", 82124c77594SElena Agostini size, mem_item->size); 82224c77594SElena Agostini 82324c77594SElena Agostini if (gdrcopy_pin(&gdrc_h, &(mem_item->mh), (uint64_t)mem_item->ptr_d, 82424c77594SElena Agostini mem_item->size, &(mem_item->ptr_h))) { 82524c77594SElena Agostini rte_cuda_log(ERR, "Error exposing GPU memory address 0x%p.", ptr_in); 82624c77594SElena Agostini rte_errno = EPERM; 82724c77594SElena Agostini return -rte_errno; 82824c77594SElena Agostini } 82924c77594SElena Agostini 83024c77594SElena Agostini *ptr_out = mem_item->ptr_h; 83124c77594SElena Agostini 83224c77594SElena Agostini return 0; 83324c77594SElena Agostini } 83424c77594SElena Agostini 83524c77594SElena Agostini static int 8361306a73bSElena Agostini cuda_mem_free(struct rte_gpu *dev, void *ptr) 8371306a73bSElena Agostini { 8381306a73bSElena Agostini CUresult res; 8391306a73bSElena Agostini struct mem_entry *mem_item; 8401306a73bSElena Agostini const char *err_string; 8411306a73bSElena Agostini cuda_ptr_key hk; 8421306a73bSElena Agostini 8431306a73bSElena Agostini if (dev == NULL) 8441306a73bSElena Agostini return -ENODEV; 8451306a73bSElena Agostini 8461306a73bSElena Agostini hk = get_hash_from_ptr((void *)ptr); 8471306a73bSElena Agostini 8481306a73bSElena Agostini mem_item = mem_list_find_item(hk); 8491306a73bSElena Agostini if (mem_item == NULL) { 8501306a73bSElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr); 85194220b39SElena Agostini rte_errno = EPERM; 85294220b39SElena Agostini return -rte_errno; 8531306a73bSElena Agostini } 8541306a73bSElena Agostini 8551306a73bSElena Agostini if (mem_item->mtype == GPU_MEM) { 856c8557ed4SElena Agostini res = pfn_cuMemFree(mem_item->ptr_orig_d); 8571306a73bSElena Agostini if (res != 0) { 8581306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8591306a73bSElena Agostini rte_cuda_log(ERR, "cuMemFree current failed with %s", 8601306a73bSElena Agostini err_string); 86194220b39SElena Agostini rte_errno = EPERM; 86294220b39SElena Agostini return -rte_errno; 8631306a73bSElena Agostini } 8641306a73bSElena Agostini 8651306a73bSElena Agostini return mem_list_del_item(hk); 8661306a73bSElena Agostini } 8671306a73bSElena Agostini 8681306a73bSElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype); 8691306a73bSElena Agostini 8701306a73bSElena Agostini return -EPERM; 8711306a73bSElena Agostini } 8721306a73bSElena Agostini 8731306a73bSElena Agostini static int 8741306a73bSElena Agostini cuda_mem_unregister(struct rte_gpu *dev, void *ptr) 8751306a73bSElena Agostini { 8761306a73bSElena Agostini CUresult res; 8771306a73bSElena Agostini struct mem_entry *mem_item; 8781306a73bSElena Agostini const char *err_string; 8791306a73bSElena Agostini cuda_ptr_key hk; 8801306a73bSElena Agostini 8811306a73bSElena Agostini if (dev == NULL) 8821306a73bSElena Agostini return -ENODEV; 8831306a73bSElena Agostini 8841306a73bSElena Agostini hk = get_hash_from_ptr((void *)ptr); 8851306a73bSElena Agostini 8861306a73bSElena Agostini mem_item = mem_list_find_item(hk); 8871306a73bSElena Agostini if (mem_item == NULL) { 8881306a73bSElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr); 88994220b39SElena Agostini rte_errno = EPERM; 89094220b39SElena Agostini return -rte_errno; 8911306a73bSElena Agostini } 8921306a73bSElena Agostini 8931306a73bSElena Agostini if (mem_item->mtype == CPU_REGISTERED) { 8941306a73bSElena Agostini res = pfn_cuMemHostUnregister(ptr); 8951306a73bSElena Agostini if (res != 0) { 8961306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8971306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostUnregister current failed with %s", 8981306a73bSElena Agostini err_string); 89994220b39SElena Agostini rte_errno = EPERM; 90094220b39SElena Agostini return -rte_errno; 9011306a73bSElena Agostini } 9021306a73bSElena Agostini 9031306a73bSElena Agostini return mem_list_del_item(hk); 9041306a73bSElena Agostini } 9051306a73bSElena Agostini 9061306a73bSElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype); 9071306a73bSElena Agostini 90894220b39SElena Agostini rte_errno = EPERM; 90994220b39SElena Agostini return -rte_errno; 9101306a73bSElena Agostini } 9111306a73bSElena Agostini 9121306a73bSElena Agostini static int 91324c77594SElena Agostini cuda_mem_cpu_unmap(struct rte_gpu *dev, void *ptr_in) 91424c77594SElena Agostini { 91524c77594SElena Agostini struct mem_entry *mem_item; 91624c77594SElena Agostini cuda_ptr_key hk; 91724c77594SElena Agostini 91824c77594SElena Agostini if (dev == NULL) 91924c77594SElena Agostini return -ENODEV; 92024c77594SElena Agostini 92124c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in); 92224c77594SElena Agostini 92324c77594SElena Agostini mem_item = mem_list_find_item(hk); 92424c77594SElena Agostini if (mem_item == NULL) { 92524c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in); 92624c77594SElena Agostini rte_errno = EPERM; 92724c77594SElena Agostini return -rte_errno; 92824c77594SElena Agostini } 92924c77594SElena Agostini 93024c77594SElena Agostini if (gdrcopy_unpin(gdrc_h, mem_item->mh, (void *)mem_item->ptr_d, 93124c77594SElena Agostini mem_item->size)) { 93224c77594SElena Agostini rte_cuda_log(ERR, "Error unexposing GPU memory address 0x%p.", ptr_in); 93324c77594SElena Agostini rte_errno = EPERM; 93424c77594SElena Agostini return -rte_errno; 93524c77594SElena Agostini } 93624c77594SElena Agostini 93724c77594SElena Agostini return 0; 93824c77594SElena Agostini } 93924c77594SElena Agostini 94024c77594SElena Agostini static int 9411306a73bSElena Agostini cuda_dev_close(struct rte_gpu *dev) 9421306a73bSElena Agostini { 9431306a73bSElena Agostini if (dev == NULL) 9441306a73bSElena Agostini return -EINVAL; 9451306a73bSElena Agostini 9461306a73bSElena Agostini rte_free(dev->mpshared->dev_private); 9471306a73bSElena Agostini 9481306a73bSElena Agostini return 0; 9491306a73bSElena Agostini } 9501306a73bSElena Agostini 9511306a73bSElena Agostini static int 9521306a73bSElena Agostini cuda_wmb(struct rte_gpu *dev) 9531306a73bSElena Agostini { 9541306a73bSElena Agostini CUresult res; 9551306a73bSElena Agostini const char *err_string; 9561306a73bSElena Agostini CUcontext current_ctx; 9571306a73bSElena Agostini CUcontext input_ctx; 9581306a73bSElena Agostini struct cuda_info *private; 9591306a73bSElena Agostini 96094220b39SElena Agostini if (dev == NULL) { 96194220b39SElena Agostini rte_errno = ENODEV; 96294220b39SElena Agostini return -rte_errno; 96394220b39SElena Agostini } 9641306a73bSElena Agostini 9651306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 9661306a73bSElena Agostini 9671306a73bSElena Agostini if (private->gdr_write_ordering != CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) { 9681306a73bSElena Agostini /* 9691306a73bSElena Agostini * No need to explicitly force the write ordering because 9701306a73bSElena Agostini * the device natively supports it 9711306a73bSElena Agostini */ 9721306a73bSElena Agostini return 0; 9731306a73bSElena Agostini } 9741306a73bSElena Agostini 9751306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) { 9761306a73bSElena Agostini /* 9771306a73bSElena Agostini * Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function. 9781306a73bSElena Agostini * Application needs to use alternative methods. 9791306a73bSElena Agostini */ 9801306a73bSElena Agostini rte_cuda_log(WARNING, "Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function." 9811306a73bSElena Agostini "Application needs to use alternative methods."); 98294220b39SElena Agostini 98394220b39SElena Agostini rte_errno = ENOTSUP; 98494220b39SElena Agostini return -rte_errno; 9851306a73bSElena Agostini } 9861306a73bSElena Agostini 9871306a73bSElena Agostini /* Store current ctx */ 9881306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 9891306a73bSElena Agostini if (res != 0) { 9901306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 9911306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 9921306a73bSElena Agostini err_string); 99394220b39SElena Agostini rte_errno = EPERM; 99494220b39SElena Agostini return -rte_errno; 9951306a73bSElena Agostini } 9961306a73bSElena Agostini 9971306a73bSElena Agostini /* Set child ctx as current ctx */ 9981306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 9991306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 10001306a73bSElena Agostini if (res != 0) { 10011306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 10021306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 10031306a73bSElena Agostini err_string); 100494220b39SElena Agostini rte_errno = EPERM; 100594220b39SElena Agostini return -rte_errno; 10061306a73bSElena Agostini } 10071306a73bSElena Agostini 10081306a73bSElena Agostini res = pfn_cuFlushGPUDirectRDMAWrites(CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TARGET_CURRENT_CTX, 10091306a73bSElena Agostini CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TO_ALL_DEVICES); 10101306a73bSElena Agostini if (res != 0) { 10111306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 10121306a73bSElena Agostini rte_cuda_log(ERR, "cuFlushGPUDirectRDMAWrites current failed with %s", 10131306a73bSElena Agostini err_string); 101494220b39SElena Agostini rte_errno = EPERM; 101594220b39SElena Agostini return -rte_errno; 10161306a73bSElena Agostini } 10171306a73bSElena Agostini 10181306a73bSElena Agostini /* Restore original ctx as current ctx */ 10191306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 10201306a73bSElena Agostini if (res != 0) { 10211306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 10221306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 10231306a73bSElena Agostini err_string); 102494220b39SElena Agostini rte_errno = EPERM; 102594220b39SElena Agostini return -rte_errno; 10261306a73bSElena Agostini } 10271306a73bSElena Agostini 10281306a73bSElena Agostini return 0; 10291306a73bSElena Agostini } 10301306a73bSElena Agostini 10311306a73bSElena Agostini static int 10321306a73bSElena Agostini cuda_gpu_probe(__rte_unused struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 10331306a73bSElena Agostini { 10341306a73bSElena Agostini struct rte_gpu *dev = NULL; 10351306a73bSElena Agostini CUresult res; 10361306a73bSElena Agostini CUdevice cu_dev_id; 10371306a73bSElena Agostini CUcontext pctx; 10381306a73bSElena Agostini char dev_name[RTE_DEV_NAME_MAX_LEN]; 10391306a73bSElena Agostini const char *err_string; 10401306a73bSElena Agostini int processor_count = 0; 10411306a73bSElena Agostini struct cuda_info *private; 10421306a73bSElena Agostini 10431306a73bSElena Agostini if (pci_dev == NULL) { 10441306a73bSElena Agostini rte_cuda_log(ERR, "NULL PCI device"); 104594220b39SElena Agostini rte_errno = ENODEV; 104694220b39SElena Agostini return -rte_errno; 10471306a73bSElena Agostini } 10481306a73bSElena Agostini 10491306a73bSElena Agostini rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name)); 10501306a73bSElena Agostini 10511306a73bSElena Agostini /* Allocate memory to be used privately by drivers */ 10521306a73bSElena Agostini dev = rte_gpu_allocate(pci_dev->device.name); 105394220b39SElena Agostini if (dev == NULL) { 105494220b39SElena Agostini rte_errno = ENODEV; 105594220b39SElena Agostini return -rte_errno; 105694220b39SElena Agostini } 10571306a73bSElena Agostini 10581306a73bSElena Agostini /* Initialize values only for the first CUDA driver call */ 10591306a73bSElena Agostini if (dev->mpshared->info.dev_id == 0) { 10601306a73bSElena Agostini mem_alloc_list_head = NULL; 10611306a73bSElena Agostini mem_alloc_list_tail = NULL; 10621306a73bSElena Agostini mem_alloc_list_last_elem = 0; 10631306a73bSElena Agostini 10641306a73bSElena Agostini /* Load libcuda.so library */ 10651306a73bSElena Agostini if (cuda_loader()) { 10661306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver library not found"); 106794220b39SElena Agostini rte_errno = ENOTSUP; 106894220b39SElena Agostini return -rte_errno; 10691306a73bSElena Agostini } 10701306a73bSElena Agostini 10711306a73bSElena Agostini /* Load initial CUDA functions */ 10721306a73bSElena Agostini if (cuda_sym_func_loader()) { 10731306a73bSElena Agostini rte_cuda_log(ERR, "CUDA functions not found in library"); 107494220b39SElena Agostini rte_errno = ENOTSUP; 107594220b39SElena Agostini return -rte_errno; 10761306a73bSElena Agostini } 10771306a73bSElena Agostini 10781306a73bSElena Agostini /* 10791306a73bSElena Agostini * Required to initialize the CUDA Driver. 10801306a73bSElena Agostini * Multiple calls of cuInit() will return immediately 10811306a73bSElena Agostini * without making any relevant change 10821306a73bSElena Agostini */ 10831306a73bSElena Agostini sym_cuInit(0); 10841306a73bSElena Agostini 10851306a73bSElena Agostini res = sym_cuDriverGetVersion(&cuda_driver_version); 10861306a73bSElena Agostini if (res != 0) { 10871306a73bSElena Agostini rte_cuda_log(ERR, "cuDriverGetVersion failed with %d", res); 108894220b39SElena Agostini rte_errno = ENOTSUP; 108994220b39SElena Agostini return -rte_errno; 10901306a73bSElena Agostini } 10911306a73bSElena Agostini 10921306a73bSElena Agostini if (cuda_driver_version < CUDA_DRIVER_MIN_VERSION) { 10931306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver version found is %d. " 10941306a73bSElena Agostini "Minimum requirement is %d", 10951306a73bSElena Agostini cuda_driver_version, 10961306a73bSElena Agostini CUDA_DRIVER_MIN_VERSION); 109794220b39SElena Agostini rte_errno = ENOTSUP; 109894220b39SElena Agostini return -rte_errno; 10991306a73bSElena Agostini } 11001306a73bSElena Agostini 11011306a73bSElena Agostini if (cuda_pfn_func_loader()) { 11021306a73bSElena Agostini rte_cuda_log(ERR, "CUDA PFN functions not found in library"); 110394220b39SElena Agostini rte_errno = ENOTSUP; 110494220b39SElena Agostini return -rte_errno; 11051306a73bSElena Agostini } 110624c77594SElena Agostini 110724c77594SElena Agostini gdrc_h = NULL; 11081306a73bSElena Agostini } 11091306a73bSElena Agostini 11101306a73bSElena Agostini /* Fill HW specific part of device structure */ 11111306a73bSElena Agostini dev->device = &pci_dev->device; 11121306a73bSElena Agostini dev->mpshared->info.numa_node = pci_dev->device.numa_node; 11131306a73bSElena Agostini 11141306a73bSElena Agostini /* Get NVIDIA GPU Device descriptor */ 11151306a73bSElena Agostini res = pfn_cuDeviceGetByPCIBusId(&cu_dev_id, dev->device->name); 11161306a73bSElena Agostini if (res != 0) { 11171306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11181306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetByPCIBusId name %s failed with %d: %s", 11191306a73bSElena Agostini dev->device->name, res, err_string); 112094220b39SElena Agostini rte_errno = EPERM; 112194220b39SElena Agostini return -rte_errno; 11221306a73bSElena Agostini } 11231306a73bSElena Agostini 11241306a73bSElena Agostini res = pfn_cuDevicePrimaryCtxRetain(&pctx, cu_dev_id); 11251306a73bSElena Agostini if (res != 0) { 11261306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11271306a73bSElena Agostini rte_cuda_log(ERR, "cuDevicePrimaryCtxRetain name %s failed with %d: %s", 11281306a73bSElena Agostini dev->device->name, res, err_string); 112994220b39SElena Agostini rte_errno = EPERM; 113094220b39SElena Agostini return -rte_errno; 11311306a73bSElena Agostini } 11321306a73bSElena Agostini 11331306a73bSElena Agostini res = pfn_cuCtxGetApiVersion(pctx, &cuda_api_version); 11341306a73bSElena Agostini if (res != 0) { 11351306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetApiVersion failed with %d", res); 113694220b39SElena Agostini rte_errno = ENOTSUP; 113794220b39SElena Agostini return -rte_errno; 11381306a73bSElena Agostini } 11391306a73bSElena Agostini 11401306a73bSElena Agostini if (cuda_api_version < CUDA_API_MIN_VERSION) { 11411306a73bSElena Agostini rte_cuda_log(ERR, "CUDA API version found is %d Minimum requirement is %d", 11421306a73bSElena Agostini cuda_api_version, CUDA_API_MIN_VERSION); 114394220b39SElena Agostini rte_errno = ENOTSUP; 114494220b39SElena Agostini return -rte_errno; 11451306a73bSElena Agostini } 11461306a73bSElena Agostini 11471306a73bSElena Agostini dev->mpshared->info.context = (uint64_t)pctx; 11481306a73bSElena Agostini 11491306a73bSElena Agostini /* 11501306a73bSElena Agostini * GPU Device generic info 11511306a73bSElena Agostini */ 11521306a73bSElena Agostini 11531306a73bSElena Agostini /* Processor count */ 11541306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(processor_count), 11551306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT, 11561306a73bSElena Agostini cu_dev_id); 11571306a73bSElena Agostini if (res != 0) { 11581306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11591306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 11601306a73bSElena Agostini err_string); 116194220b39SElena Agostini rte_errno = EPERM; 116294220b39SElena Agostini return -rte_errno; 11631306a73bSElena Agostini } 11641306a73bSElena Agostini dev->mpshared->info.processor_count = (uint32_t)processor_count; 11651306a73bSElena Agostini 11661306a73bSElena Agostini /* Total memory */ 11671306a73bSElena Agostini res = pfn_cuDeviceTotalMem(&dev->mpshared->info.total_memory, cu_dev_id); 11681306a73bSElena Agostini if (res != 0) { 11691306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11701306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceTotalMem failed with %s", 11711306a73bSElena Agostini err_string); 117294220b39SElena Agostini rte_errno = EPERM; 117394220b39SElena Agostini return -rte_errno; 11741306a73bSElena Agostini } 11751306a73bSElena Agostini 11761306a73bSElena Agostini /* 11771306a73bSElena Agostini * GPU Device private info 11781306a73bSElena Agostini */ 11791306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL, 11801306a73bSElena Agostini sizeof(struct cuda_info), 11811306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 11821306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) { 11831306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private"); 118494220b39SElena Agostini rte_errno = EPERM; 118594220b39SElena Agostini return -rte_errno; 11861306a73bSElena Agostini } 11871306a73bSElena Agostini 11881306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 11891306a73bSElena Agostini private->cu_dev = cu_dev_id; 11901306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name, 11911306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN, 11921306a73bSElena Agostini cu_dev_id); 11931306a73bSElena Agostini if (res != 0) { 11941306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11951306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s", 11961306a73bSElena Agostini err_string); 119794220b39SElena Agostini rte_errno = EPERM; 119894220b39SElena Agostini return -rte_errno; 11991306a73bSElena Agostini } 12001306a73bSElena Agostini 12011306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_supported), 12021306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_SUPPORTED, 12031306a73bSElena Agostini cu_dev_id); 12041306a73bSElena Agostini if (res != 0) { 12051306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12061306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 12071306a73bSElena Agostini err_string); 120894220b39SElena Agostini rte_errno = EPERM; 120994220b39SElena Agostini return -rte_errno; 12101306a73bSElena Agostini } 12111306a73bSElena Agostini 12121306a73bSElena Agostini if (private->gdr_supported == 0) 12131306a73bSElena Agostini rte_cuda_log(WARNING, "GPU %s doesn't support GPUDirect RDMA", 12141306a73bSElena Agostini pci_dev->device.name); 12151306a73bSElena Agostini 12161306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_write_ordering), 12171306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_WRITES_ORDERING, 12181306a73bSElena Agostini cu_dev_id); 12191306a73bSElena Agostini if (res != 0) { 12201306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12211306a73bSElena Agostini rte_cuda_log(ERR, 12221306a73bSElena Agostini "cuDeviceGetAttribute failed with %s", 12231306a73bSElena Agostini err_string); 122494220b39SElena Agostini rte_errno = EPERM; 122594220b39SElena Agostini return -rte_errno; 12261306a73bSElena Agostini } 12271306a73bSElena Agostini 12281306a73bSElena Agostini if (private->gdr_write_ordering == CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) { 12291306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_flush_type), 12301306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_FLUSH_WRITES_OPTIONS, 12311306a73bSElena Agostini cu_dev_id); 12321306a73bSElena Agostini if (res != 0) { 12331306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12341306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 12351306a73bSElena Agostini err_string); 123694220b39SElena Agostini rte_errno = EPERM; 123794220b39SElena Agostini return -rte_errno; 12381306a73bSElena Agostini } 12391306a73bSElena Agostini 12401306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) 12411306a73bSElena Agostini rte_cuda_log(ERR, "GPUDirect RDMA flush writes API is not supported"); 12421306a73bSElena Agostini } 12431306a73bSElena Agostini 12441306a73bSElena Agostini dev->ops.dev_info_get = cuda_dev_info_get; 12451306a73bSElena Agostini dev->ops.dev_close = cuda_dev_close; 12461306a73bSElena Agostini dev->ops.mem_alloc = cuda_mem_alloc; 12471306a73bSElena Agostini dev->ops.mem_free = cuda_mem_free; 12481306a73bSElena Agostini dev->ops.mem_register = cuda_mem_register; 12491306a73bSElena Agostini dev->ops.mem_unregister = cuda_mem_unregister; 125024c77594SElena Agostini dev->ops.mem_cpu_map = cuda_mem_cpu_map; 125124c77594SElena Agostini dev->ops.mem_cpu_unmap = cuda_mem_cpu_unmap; 12521306a73bSElena Agostini dev->ops.wmb = cuda_wmb; 12531306a73bSElena Agostini 12541306a73bSElena Agostini rte_gpu_complete_new(dev); 12551306a73bSElena Agostini 12561306a73bSElena Agostini rte_cuda_debug("dev id = %u name = %s", 12571306a73bSElena Agostini dev->mpshared->info.dev_id, private->gpu_name); 12581306a73bSElena Agostini 12591306a73bSElena Agostini return 0; 12601306a73bSElena Agostini } 12611306a73bSElena Agostini 12621306a73bSElena Agostini static int 12631306a73bSElena Agostini cuda_gpu_remove(struct rte_pci_device *pci_dev) 12641306a73bSElena Agostini { 12651306a73bSElena Agostini struct rte_gpu *dev; 12661306a73bSElena Agostini int ret; 12671306a73bSElena Agostini uint8_t gpu_id; 12681306a73bSElena Agostini 126994220b39SElena Agostini if (pci_dev == NULL) { 127094220b39SElena Agostini rte_errno = ENODEV; 127194220b39SElena Agostini return -rte_errno; 127294220b39SElena Agostini } 12731306a73bSElena Agostini 12741306a73bSElena Agostini dev = rte_gpu_get_by_name(pci_dev->device.name); 12751306a73bSElena Agostini if (dev == NULL) { 12761306a73bSElena Agostini rte_cuda_log(ERR, "Couldn't find HW dev \"%s\" to uninitialise it", 12771306a73bSElena Agostini pci_dev->device.name); 127894220b39SElena Agostini rte_errno = ENODEV; 127994220b39SElena Agostini return -rte_errno; 12801306a73bSElena Agostini } 12811306a73bSElena Agostini gpu_id = dev->mpshared->info.dev_id; 12821306a73bSElena Agostini 12831306a73bSElena Agostini /* release dev from library */ 12841306a73bSElena Agostini ret = rte_gpu_release(dev); 12851306a73bSElena Agostini if (ret) 12861306a73bSElena Agostini rte_cuda_log(ERR, "Device %i failed to uninit: %i", gpu_id, ret); 12871306a73bSElena Agostini 12881306a73bSElena Agostini rte_cuda_debug("Destroyed dev = %u", gpu_id); 12891306a73bSElena Agostini 12901306a73bSElena Agostini return 0; 12911306a73bSElena Agostini } 12921306a73bSElena Agostini 12931306a73bSElena Agostini static struct rte_pci_driver rte_cuda_driver = { 12941306a73bSElena Agostini .id_table = pci_id_cuda_map, 12951306a73bSElena Agostini .drv_flags = RTE_PCI_DRV_WC_ACTIVATE, 12961306a73bSElena Agostini .probe = cuda_gpu_probe, 12971306a73bSElena Agostini .remove = cuda_gpu_remove, 12981306a73bSElena Agostini }; 12991306a73bSElena Agostini 13001306a73bSElena Agostini RTE_PMD_REGISTER_PCI(gpu_cuda, rte_cuda_driver); 13011306a73bSElena Agostini RTE_PMD_REGISTER_PCI_TABLE(gpu_cuda, pci_id_cuda_map); 13021306a73bSElena Agostini RTE_PMD_REGISTER_KMOD_DEP(gpu_cuda, "* nvidia & (nv_peer_mem | nvpeer_mem)"); 1303