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 1720105d49eSElena 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 526*1fd3de64SElena Agostini dev->mpshared->info.page_size = parent_info.page_size; 527*1fd3de64SElena Agostini 5281306a73bSElena Agostini /* 5291306a73bSElena Agostini * GPU Device private info 5301306a73bSElena Agostini */ 5311306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL, 5321306a73bSElena Agostini sizeof(struct cuda_info), 5331306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 5341306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) { 5351306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private"); 53694220b39SElena Agostini rte_errno = EPERM; 53794220b39SElena Agostini return -rte_errno; 5381306a73bSElena Agostini } 5391306a73bSElena Agostini 5401306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 5411306a73bSElena Agostini 5421306a73bSElena Agostini res = pfn_cuCtxGetDevice(&(private->cu_dev)); 5431306a73bSElena Agostini if (res != 0) { 5441306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5451306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetDevice failed with %s", 5461306a73bSElena Agostini err_string); 54794220b39SElena Agostini rte_errno = EPERM; 54894220b39SElena Agostini return -rte_errno; 5491306a73bSElena Agostini } 5501306a73bSElena Agostini 5511306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name, 5521306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN, private->cu_dev); 5531306a73bSElena Agostini if (res != 0) { 5541306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5551306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s", 5561306a73bSElena Agostini err_string); 55794220b39SElena Agostini rte_errno = EPERM; 55894220b39SElena Agostini return -rte_errno; 5591306a73bSElena Agostini } 5601306a73bSElena Agostini 5611306a73bSElena Agostini /* Restore original ctx as current ctx */ 5621306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 5631306a73bSElena Agostini if (res != 0) { 5641306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5651306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 5661306a73bSElena Agostini err_string); 56794220b39SElena Agostini rte_errno = EPERM; 56894220b39SElena Agostini return -rte_errno; 5691306a73bSElena Agostini } 5701306a73bSElena Agostini } 5711306a73bSElena Agostini 5721306a73bSElena Agostini *info = dev->mpshared->info; 5731306a73bSElena Agostini 5741306a73bSElena Agostini return 0; 5751306a73bSElena Agostini } 5761306a73bSElena Agostini 5771306a73bSElena Agostini /* 5781306a73bSElena Agostini * GPU Memory 5791306a73bSElena Agostini */ 5801306a73bSElena Agostini 5811306a73bSElena Agostini static int 582c8557ed4SElena Agostini cuda_mem_alloc(struct rte_gpu *dev, size_t size, unsigned int align, void **ptr) 5831306a73bSElena Agostini { 5841306a73bSElena Agostini CUresult res; 5851306a73bSElena Agostini const char *err_string; 5861306a73bSElena Agostini CUcontext current_ctx; 5871306a73bSElena Agostini CUcontext input_ctx; 5881306a73bSElena Agostini unsigned int flag = 1; 5891306a73bSElena Agostini 5901306a73bSElena Agostini if (dev == NULL) 5911306a73bSElena Agostini return -ENODEV; 5921306a73bSElena Agostini 5931306a73bSElena Agostini /* Store current ctx */ 5941306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 5951306a73bSElena Agostini if (res != 0) { 5961306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 5971306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 5981306a73bSElena Agostini err_string); 59994220b39SElena Agostini rte_errno = EPERM; 60094220b39SElena Agostini return -rte_errno; 6011306a73bSElena Agostini } 6021306a73bSElena Agostini 6031306a73bSElena Agostini /* Set child ctx as current ctx */ 6041306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 6051306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 6061306a73bSElena Agostini if (res != 0) { 6071306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6081306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 6091306a73bSElena Agostini err_string); 61094220b39SElena Agostini rte_errno = EPERM; 61194220b39SElena Agostini return -rte_errno; 6121306a73bSElena Agostini } 6131306a73bSElena Agostini 6141306a73bSElena Agostini /* Get next memory list item */ 6151306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item(); 61694220b39SElena Agostini if (mem_alloc_list_tail == NULL) { 61794220b39SElena Agostini rte_errno = EPERM; 61894220b39SElena Agostini return -rte_errno; 61994220b39SElena Agostini } 6201306a73bSElena Agostini 6211306a73bSElena Agostini /* Allocate memory */ 6221306a73bSElena Agostini mem_alloc_list_tail->size = size; 623c8557ed4SElena Agostini mem_alloc_list_tail->size_orig = size + align; 624c8557ed4SElena Agostini 625c8557ed4SElena Agostini res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d), 626c8557ed4SElena Agostini mem_alloc_list_tail->size_orig); 6271306a73bSElena Agostini if (res != 0) { 6281306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6291306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 6301306a73bSElena Agostini err_string); 63194220b39SElena Agostini rte_errno = EPERM; 63294220b39SElena Agostini return -rte_errno; 6331306a73bSElena Agostini } 6341306a73bSElena Agostini 635c8557ed4SElena Agostini /* Align memory address */ 636c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d; 637c8557ed4SElena Agostini if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align) 638c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d += (align - 639c8557ed4SElena Agostini (((uintptr_t)mem_alloc_list_tail->ptr_d) % align)); 640c8557ed4SElena Agostini 6411306a73bSElena Agostini /* GPUDirect RDMA attribute required */ 6421306a73bSElena Agostini res = pfn_cuPointerSetAttribute(&flag, 6431306a73bSElena Agostini CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, 6441306a73bSElena Agostini mem_alloc_list_tail->ptr_d); 6451306a73bSElena Agostini if (res != 0) { 6461306a73bSElena Agostini rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for " 6471306a73bSElena Agostini "GPU memory at %"PRIu32", err %d", 6481306a73bSElena Agostini (uint32_t)mem_alloc_list_tail->ptr_d, res); 64994220b39SElena Agostini rte_errno = EPERM; 65094220b39SElena Agostini return -rte_errno; 6511306a73bSElena Agostini } 6521306a73bSElena Agostini 6531306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_d); 6541306a73bSElena Agostini mem_alloc_list_tail->ptr_h = NULL; 6551306a73bSElena Agostini mem_alloc_list_tail->dev = dev; 6561306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 6571306a73bSElena Agostini mem_alloc_list_tail->mtype = GPU_MEM; 6581306a73bSElena Agostini 6591306a73bSElena Agostini /* Restore original ctx as current ctx */ 6601306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 6611306a73bSElena Agostini if (res != 0) { 6621306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6631306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 6641306a73bSElena Agostini err_string); 66594220b39SElena Agostini rte_errno = EPERM; 66694220b39SElena Agostini return -rte_errno; 6671306a73bSElena Agostini } 6681306a73bSElena Agostini 6691306a73bSElena Agostini *ptr = (void *)mem_alloc_list_tail->ptr_d; 6701306a73bSElena Agostini 6711306a73bSElena Agostini return 0; 6721306a73bSElena Agostini } 6731306a73bSElena Agostini 6741306a73bSElena Agostini static int 6751306a73bSElena Agostini cuda_mem_register(struct rte_gpu *dev, size_t size, void *ptr) 6761306a73bSElena Agostini { 6771306a73bSElena Agostini CUresult res; 6781306a73bSElena Agostini const char *err_string; 6791306a73bSElena Agostini CUcontext current_ctx; 6801306a73bSElena Agostini CUcontext input_ctx; 6811306a73bSElena Agostini unsigned int flag = 1; 6821306a73bSElena Agostini int use_ptr_h = 0; 6831306a73bSElena Agostini 6841306a73bSElena Agostini if (dev == NULL) 6851306a73bSElena Agostini return -ENODEV; 6861306a73bSElena Agostini 6871306a73bSElena Agostini /* Store current ctx */ 6881306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 6891306a73bSElena Agostini if (res != 0) { 6901306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6911306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 6921306a73bSElena Agostini err_string); 69394220b39SElena Agostini rte_errno = EPERM; 69494220b39SElena Agostini return -rte_errno; 6951306a73bSElena Agostini } 6961306a73bSElena Agostini 6971306a73bSElena Agostini /* Set child ctx as current ctx */ 6981306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 6991306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 7001306a73bSElena Agostini if (res != 0) { 7011306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7021306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 7031306a73bSElena Agostini err_string); 70494220b39SElena Agostini rte_errno = EPERM; 70594220b39SElena Agostini return -rte_errno; 7061306a73bSElena Agostini } 7071306a73bSElena Agostini 7081306a73bSElena Agostini /* Get next memory list item */ 7091306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item(); 71094220b39SElena Agostini if (mem_alloc_list_tail == NULL) { 71194220b39SElena Agostini rte_errno = EPERM; 71294220b39SElena Agostini return -rte_errno; 71394220b39SElena Agostini } 7141306a73bSElena Agostini 7151306a73bSElena Agostini /* Allocate memory */ 7161306a73bSElena Agostini mem_alloc_list_tail->size = size; 7171306a73bSElena Agostini mem_alloc_list_tail->ptr_h = ptr; 7181306a73bSElena Agostini 7191306a73bSElena Agostini res = pfn_cuMemHostRegister(mem_alloc_list_tail->ptr_h, 7201306a73bSElena Agostini mem_alloc_list_tail->size, 7211306a73bSElena Agostini CU_MEMHOSTREGISTER_PORTABLE | 7221306a73bSElena Agostini CU_MEMHOSTREGISTER_DEVICEMAP); 7231306a73bSElena Agostini if (res != 0) { 7241306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7251306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostRegister failed with %s ptr %p size %zd", 7261306a73bSElena Agostini err_string, 7271306a73bSElena Agostini mem_alloc_list_tail->ptr_h, 7281306a73bSElena Agostini mem_alloc_list_tail->size); 72994220b39SElena Agostini rte_errno = EPERM; 73094220b39SElena Agostini return -rte_errno; 7311306a73bSElena Agostini } 7321306a73bSElena Agostini 7331306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(use_ptr_h), 7341306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM, 7351306a73bSElena Agostini ((struct cuda_info *)(dev->mpshared->dev_private))->cu_dev); 7361306a73bSElena Agostini if (res != 0) { 7371306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7381306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 7391306a73bSElena Agostini err_string); 74094220b39SElena Agostini rte_errno = EPERM; 74194220b39SElena Agostini return -rte_errno; 7421306a73bSElena Agostini } 7431306a73bSElena Agostini 7441306a73bSElena Agostini if (use_ptr_h == 0) { 7451306a73bSElena Agostini res = pfn_cuMemHostGetDevicePointer(&(mem_alloc_list_tail->ptr_d), 7461306a73bSElena Agostini mem_alloc_list_tail->ptr_h, 0); 7471306a73bSElena Agostini if (res != 0) { 7481306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7491306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostGetDevicePointer failed with %s", 7501306a73bSElena Agostini err_string); 75194220b39SElena Agostini rte_errno = EPERM; 75294220b39SElena Agostini return -rte_errno; 7531306a73bSElena Agostini } 7541306a73bSElena Agostini 7551306a73bSElena Agostini if ((uintptr_t)mem_alloc_list_tail->ptr_d != 7561306a73bSElena Agostini (uintptr_t)mem_alloc_list_tail->ptr_h) { 7571306a73bSElena Agostini rte_cuda_log(ERR, "Host input pointer is different wrt GPU registered pointer"); 75894220b39SElena Agostini rte_errno = ENOTSUP; 75994220b39SElena Agostini return -rte_errno; 7601306a73bSElena Agostini } 7611306a73bSElena Agostini } else { 7621306a73bSElena Agostini mem_alloc_list_tail->ptr_d = (CUdeviceptr)mem_alloc_list_tail->ptr_h; 7631306a73bSElena Agostini } 7641306a73bSElena 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 GPU memory at %"PRIu32 7711306a73bSElena Agostini ", err %d", (uint32_t)mem_alloc_list_tail->ptr_d, res); 77294220b39SElena Agostini rte_errno = EPERM; 77394220b39SElena Agostini return -rte_errno; 7741306a73bSElena Agostini } 7751306a73bSElena Agostini 7761306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_h); 7771306a73bSElena Agostini mem_alloc_list_tail->size = size; 7781306a73bSElena Agostini mem_alloc_list_tail->dev = dev; 7791306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 7801306a73bSElena Agostini mem_alloc_list_tail->mtype = CPU_REGISTERED; 781c8557ed4SElena Agostini mem_alloc_list_tail->ptr_orig_d = mem_alloc_list_tail->ptr_d; 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 return 0; 7941306a73bSElena Agostini } 7951306a73bSElena Agostini 7961306a73bSElena Agostini static int 79724c77594SElena Agostini cuda_mem_cpu_map(struct rte_gpu *dev, __rte_unused size_t size, void *ptr_in, void **ptr_out) 79824c77594SElena Agostini { 79924c77594SElena Agostini struct mem_entry *mem_item; 80024c77594SElena Agostini cuda_ptr_key hk; 80124c77594SElena Agostini 80224c77594SElena Agostini if (dev == NULL) 80324c77594SElena Agostini return -ENODEV; 80424c77594SElena Agostini 80524c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in); 80624c77594SElena Agostini 80724c77594SElena Agostini mem_item = mem_list_find_item(hk); 80824c77594SElena Agostini if (mem_item == NULL) { 80924c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in); 81024c77594SElena Agostini rte_errno = EPERM; 81124c77594SElena Agostini return -rte_errno; 81224c77594SElena Agostini } 81324c77594SElena Agostini 81424c77594SElena Agostini if (mem_item->mtype != GPU_MEM) { 81524c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p is not GPU memory type.", ptr_in); 81624c77594SElena Agostini rte_errno = EPERM; 81724c77594SElena Agostini return -rte_errno; 81824c77594SElena Agostini } 81924c77594SElena Agostini 82024c77594SElena Agostini if (mem_item->size != size) 82124c77594SElena Agostini rte_cuda_log(WARNING, 82224c77594SElena Agostini "Can't expose memory area with size (%zd) different from original size (%zd).", 82324c77594SElena Agostini size, mem_item->size); 82424c77594SElena Agostini 82524c77594SElena Agostini if (gdrcopy_pin(&gdrc_h, &(mem_item->mh), (uint64_t)mem_item->ptr_d, 82624c77594SElena Agostini mem_item->size, &(mem_item->ptr_h))) { 82724c77594SElena Agostini rte_cuda_log(ERR, "Error exposing GPU memory address 0x%p.", ptr_in); 82824c77594SElena Agostini rte_errno = EPERM; 82924c77594SElena Agostini return -rte_errno; 83024c77594SElena Agostini } 83124c77594SElena Agostini 83224c77594SElena Agostini *ptr_out = mem_item->ptr_h; 83324c77594SElena Agostini 83424c77594SElena Agostini return 0; 83524c77594SElena Agostini } 83624c77594SElena Agostini 83724c77594SElena Agostini static int 8381306a73bSElena Agostini cuda_mem_free(struct rte_gpu *dev, void *ptr) 8391306a73bSElena Agostini { 8401306a73bSElena Agostini CUresult res; 8411306a73bSElena Agostini struct mem_entry *mem_item; 8421306a73bSElena Agostini const char *err_string; 8431306a73bSElena Agostini cuda_ptr_key hk; 8441306a73bSElena Agostini 8451306a73bSElena Agostini if (dev == NULL) 8461306a73bSElena Agostini return -ENODEV; 8471306a73bSElena Agostini 8481306a73bSElena Agostini hk = get_hash_from_ptr((void *)ptr); 8491306a73bSElena Agostini 8501306a73bSElena Agostini mem_item = mem_list_find_item(hk); 8511306a73bSElena Agostini if (mem_item == NULL) { 8521306a73bSElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr); 85394220b39SElena Agostini rte_errno = EPERM; 85494220b39SElena Agostini return -rte_errno; 8551306a73bSElena Agostini } 8561306a73bSElena Agostini 8571306a73bSElena Agostini if (mem_item->mtype == GPU_MEM) { 858c8557ed4SElena Agostini res = pfn_cuMemFree(mem_item->ptr_orig_d); 8591306a73bSElena Agostini if (res != 0) { 8601306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8611306a73bSElena Agostini rte_cuda_log(ERR, "cuMemFree current failed with %s", 8621306a73bSElena Agostini err_string); 86394220b39SElena Agostini rte_errno = EPERM; 86494220b39SElena Agostini return -rte_errno; 8651306a73bSElena Agostini } 8661306a73bSElena Agostini 8671306a73bSElena Agostini return mem_list_del_item(hk); 8681306a73bSElena Agostini } 8691306a73bSElena Agostini 8701306a73bSElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype); 8711306a73bSElena Agostini 8721306a73bSElena Agostini return -EPERM; 8731306a73bSElena Agostini } 8741306a73bSElena Agostini 8751306a73bSElena Agostini static int 8761306a73bSElena Agostini cuda_mem_unregister(struct rte_gpu *dev, void *ptr) 8771306a73bSElena Agostini { 8781306a73bSElena Agostini CUresult res; 8791306a73bSElena Agostini struct mem_entry *mem_item; 8801306a73bSElena Agostini const char *err_string; 8811306a73bSElena Agostini cuda_ptr_key hk; 8821306a73bSElena Agostini 8831306a73bSElena Agostini if (dev == NULL) 8841306a73bSElena Agostini return -ENODEV; 8851306a73bSElena Agostini 8861306a73bSElena Agostini hk = get_hash_from_ptr((void *)ptr); 8871306a73bSElena Agostini 8881306a73bSElena Agostini mem_item = mem_list_find_item(hk); 8891306a73bSElena Agostini if (mem_item == NULL) { 8901306a73bSElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr); 89194220b39SElena Agostini rte_errno = EPERM; 89294220b39SElena Agostini return -rte_errno; 8931306a73bSElena Agostini } 8941306a73bSElena Agostini 8951306a73bSElena Agostini if (mem_item->mtype == CPU_REGISTERED) { 8961306a73bSElena Agostini res = pfn_cuMemHostUnregister(ptr); 8971306a73bSElena Agostini if (res != 0) { 8981306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8991306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostUnregister current failed with %s", 9001306a73bSElena Agostini err_string); 90194220b39SElena Agostini rte_errno = EPERM; 90294220b39SElena Agostini return -rte_errno; 9031306a73bSElena Agostini } 9041306a73bSElena Agostini 9051306a73bSElena Agostini return mem_list_del_item(hk); 9061306a73bSElena Agostini } 9071306a73bSElena Agostini 9081306a73bSElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype); 9091306a73bSElena Agostini 91094220b39SElena Agostini rte_errno = EPERM; 91194220b39SElena Agostini return -rte_errno; 9121306a73bSElena Agostini } 9131306a73bSElena Agostini 9141306a73bSElena Agostini static int 91524c77594SElena Agostini cuda_mem_cpu_unmap(struct rte_gpu *dev, void *ptr_in) 91624c77594SElena Agostini { 91724c77594SElena Agostini struct mem_entry *mem_item; 91824c77594SElena Agostini cuda_ptr_key hk; 91924c77594SElena Agostini 92024c77594SElena Agostini if (dev == NULL) 92124c77594SElena Agostini return -ENODEV; 92224c77594SElena Agostini 92324c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in); 92424c77594SElena Agostini 92524c77594SElena Agostini mem_item = mem_list_find_item(hk); 92624c77594SElena Agostini if (mem_item == NULL) { 92724c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in); 92824c77594SElena Agostini rte_errno = EPERM; 92924c77594SElena Agostini return -rte_errno; 93024c77594SElena Agostini } 93124c77594SElena Agostini 93224c77594SElena Agostini if (gdrcopy_unpin(gdrc_h, mem_item->mh, (void *)mem_item->ptr_d, 93324c77594SElena Agostini mem_item->size)) { 93424c77594SElena Agostini rte_cuda_log(ERR, "Error unexposing GPU memory address 0x%p.", ptr_in); 93524c77594SElena Agostini rte_errno = EPERM; 93624c77594SElena Agostini return -rte_errno; 93724c77594SElena Agostini } 93824c77594SElena Agostini 93924c77594SElena Agostini return 0; 94024c77594SElena Agostini } 94124c77594SElena Agostini 94224c77594SElena Agostini static int 9431306a73bSElena Agostini cuda_dev_close(struct rte_gpu *dev) 9441306a73bSElena Agostini { 9451306a73bSElena Agostini if (dev == NULL) 9461306a73bSElena Agostini return -EINVAL; 9471306a73bSElena Agostini 9481306a73bSElena Agostini rte_free(dev->mpshared->dev_private); 9491306a73bSElena Agostini 9501306a73bSElena Agostini return 0; 9511306a73bSElena Agostini } 9521306a73bSElena Agostini 9531306a73bSElena Agostini static int 9541306a73bSElena Agostini cuda_wmb(struct rte_gpu *dev) 9551306a73bSElena Agostini { 9561306a73bSElena Agostini CUresult res; 9571306a73bSElena Agostini const char *err_string; 9581306a73bSElena Agostini CUcontext current_ctx; 9591306a73bSElena Agostini CUcontext input_ctx; 9601306a73bSElena Agostini struct cuda_info *private; 9611306a73bSElena Agostini 96294220b39SElena Agostini if (dev == NULL) { 96394220b39SElena Agostini rte_errno = ENODEV; 96494220b39SElena Agostini return -rte_errno; 96594220b39SElena Agostini } 9661306a73bSElena Agostini 9671306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 9681306a73bSElena Agostini 9691306a73bSElena Agostini if (private->gdr_write_ordering != CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) { 9701306a73bSElena Agostini /* 9711306a73bSElena Agostini * No need to explicitly force the write ordering because 9721306a73bSElena Agostini * the device natively supports it 9731306a73bSElena Agostini */ 9741306a73bSElena Agostini return 0; 9751306a73bSElena Agostini } 9761306a73bSElena Agostini 9771306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) { 9781306a73bSElena Agostini /* 9791306a73bSElena Agostini * Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function. 9801306a73bSElena Agostini * Application needs to use alternative methods. 9811306a73bSElena Agostini */ 9821306a73bSElena Agostini rte_cuda_log(WARNING, "Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function." 9831306a73bSElena Agostini "Application needs to use alternative methods."); 98494220b39SElena Agostini 98594220b39SElena Agostini rte_errno = ENOTSUP; 98694220b39SElena Agostini return -rte_errno; 9871306a73bSElena Agostini } 9881306a73bSElena Agostini 9891306a73bSElena Agostini /* Store current ctx */ 9901306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 9911306a73bSElena Agostini if (res != 0) { 9921306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 9931306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 9941306a73bSElena Agostini err_string); 99594220b39SElena Agostini rte_errno = EPERM; 99694220b39SElena Agostini return -rte_errno; 9971306a73bSElena Agostini } 9981306a73bSElena Agostini 9991306a73bSElena Agostini /* Set child ctx as current ctx */ 10001306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 10011306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 10021306a73bSElena Agostini if (res != 0) { 10031306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 10041306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 10051306a73bSElena Agostini err_string); 100694220b39SElena Agostini rte_errno = EPERM; 100794220b39SElena Agostini return -rte_errno; 10081306a73bSElena Agostini } 10091306a73bSElena Agostini 10101306a73bSElena Agostini res = pfn_cuFlushGPUDirectRDMAWrites(CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TARGET_CURRENT_CTX, 10111306a73bSElena Agostini CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TO_ALL_DEVICES); 10121306a73bSElena Agostini if (res != 0) { 10131306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 10141306a73bSElena Agostini rte_cuda_log(ERR, "cuFlushGPUDirectRDMAWrites current failed with %s", 10151306a73bSElena Agostini err_string); 101694220b39SElena Agostini rte_errno = EPERM; 101794220b39SElena Agostini return -rte_errno; 10181306a73bSElena Agostini } 10191306a73bSElena Agostini 10201306a73bSElena Agostini /* Restore original ctx as current ctx */ 10211306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 10221306a73bSElena Agostini if (res != 0) { 10231306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 10241306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 10251306a73bSElena Agostini err_string); 102694220b39SElena Agostini rte_errno = EPERM; 102794220b39SElena Agostini return -rte_errno; 10281306a73bSElena Agostini } 10291306a73bSElena Agostini 10301306a73bSElena Agostini return 0; 10311306a73bSElena Agostini } 10321306a73bSElena Agostini 10331306a73bSElena Agostini static int 10341306a73bSElena Agostini cuda_gpu_probe(__rte_unused struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 10351306a73bSElena Agostini { 10361306a73bSElena Agostini struct rte_gpu *dev = NULL; 10371306a73bSElena Agostini CUresult res; 10381306a73bSElena Agostini CUdevice cu_dev_id; 10391306a73bSElena Agostini CUcontext pctx; 10401306a73bSElena Agostini char dev_name[RTE_DEV_NAME_MAX_LEN]; 10411306a73bSElena Agostini const char *err_string; 10421306a73bSElena Agostini int processor_count = 0; 10431306a73bSElena Agostini struct cuda_info *private; 10441306a73bSElena Agostini 10451306a73bSElena Agostini if (pci_dev == NULL) { 10461306a73bSElena Agostini rte_cuda_log(ERR, "NULL PCI device"); 104794220b39SElena Agostini rte_errno = ENODEV; 104894220b39SElena Agostini return -rte_errno; 10491306a73bSElena Agostini } 10501306a73bSElena Agostini 10511306a73bSElena Agostini rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name)); 10521306a73bSElena Agostini 10531306a73bSElena Agostini /* Allocate memory to be used privately by drivers */ 10541306a73bSElena Agostini dev = rte_gpu_allocate(pci_dev->device.name); 105594220b39SElena Agostini if (dev == NULL) { 105694220b39SElena Agostini rte_errno = ENODEV; 105794220b39SElena Agostini return -rte_errno; 105894220b39SElena Agostini } 10591306a73bSElena Agostini 10601306a73bSElena Agostini /* Initialize values only for the first CUDA driver call */ 10611306a73bSElena Agostini if (dev->mpshared->info.dev_id == 0) { 10621306a73bSElena Agostini mem_alloc_list_head = NULL; 10631306a73bSElena Agostini mem_alloc_list_tail = NULL; 10641306a73bSElena Agostini mem_alloc_list_last_elem = 0; 10651306a73bSElena Agostini 10661306a73bSElena Agostini /* Load libcuda.so library */ 10671306a73bSElena Agostini if (cuda_loader()) { 10681306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver library not found"); 106994220b39SElena Agostini rte_errno = ENOTSUP; 107094220b39SElena Agostini return -rte_errno; 10711306a73bSElena Agostini } 10721306a73bSElena Agostini 10731306a73bSElena Agostini /* Load initial CUDA functions */ 10741306a73bSElena Agostini if (cuda_sym_func_loader()) { 10751306a73bSElena Agostini rte_cuda_log(ERR, "CUDA functions not found in library"); 107694220b39SElena Agostini rte_errno = ENOTSUP; 107794220b39SElena Agostini return -rte_errno; 10781306a73bSElena Agostini } 10791306a73bSElena Agostini 10801306a73bSElena Agostini /* 10811306a73bSElena Agostini * Required to initialize the CUDA Driver. 10821306a73bSElena Agostini * Multiple calls of cuInit() will return immediately 10831306a73bSElena Agostini * without making any relevant change 10841306a73bSElena Agostini */ 10851306a73bSElena Agostini sym_cuInit(0); 10861306a73bSElena Agostini 10871306a73bSElena Agostini res = sym_cuDriverGetVersion(&cuda_driver_version); 10881306a73bSElena Agostini if (res != 0) { 10891306a73bSElena Agostini rte_cuda_log(ERR, "cuDriverGetVersion failed with %d", res); 109094220b39SElena Agostini rte_errno = ENOTSUP; 109194220b39SElena Agostini return -rte_errno; 10921306a73bSElena Agostini } 10931306a73bSElena Agostini 10941306a73bSElena Agostini if (cuda_driver_version < CUDA_DRIVER_MIN_VERSION) { 10951306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver version found is %d. " 10961306a73bSElena Agostini "Minimum requirement is %d", 10971306a73bSElena Agostini cuda_driver_version, 10981306a73bSElena Agostini CUDA_DRIVER_MIN_VERSION); 109994220b39SElena Agostini rte_errno = ENOTSUP; 110094220b39SElena Agostini return -rte_errno; 11011306a73bSElena Agostini } 11021306a73bSElena Agostini 11031306a73bSElena Agostini if (cuda_pfn_func_loader()) { 11041306a73bSElena Agostini rte_cuda_log(ERR, "CUDA PFN functions not found in library"); 110594220b39SElena Agostini rte_errno = ENOTSUP; 110694220b39SElena Agostini return -rte_errno; 11071306a73bSElena Agostini } 110824c77594SElena Agostini 110924c77594SElena Agostini gdrc_h = NULL; 11101306a73bSElena Agostini } 11111306a73bSElena Agostini 11121306a73bSElena Agostini /* Fill HW specific part of device structure */ 11131306a73bSElena Agostini dev->device = &pci_dev->device; 11141306a73bSElena Agostini dev->mpshared->info.numa_node = pci_dev->device.numa_node; 11151306a73bSElena Agostini 11161306a73bSElena Agostini /* Get NVIDIA GPU Device descriptor */ 11171306a73bSElena Agostini res = pfn_cuDeviceGetByPCIBusId(&cu_dev_id, dev->device->name); 11181306a73bSElena Agostini if (res != 0) { 11191306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11201306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetByPCIBusId name %s failed with %d: %s", 11211306a73bSElena Agostini dev->device->name, res, err_string); 112294220b39SElena Agostini rte_errno = EPERM; 112394220b39SElena Agostini return -rte_errno; 11241306a73bSElena Agostini } 11251306a73bSElena Agostini 11261306a73bSElena Agostini res = pfn_cuDevicePrimaryCtxRetain(&pctx, cu_dev_id); 11271306a73bSElena Agostini if (res != 0) { 11281306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11291306a73bSElena Agostini rte_cuda_log(ERR, "cuDevicePrimaryCtxRetain name %s failed with %d: %s", 11301306a73bSElena Agostini dev->device->name, res, err_string); 113194220b39SElena Agostini rte_errno = EPERM; 113294220b39SElena Agostini return -rte_errno; 11331306a73bSElena Agostini } 11341306a73bSElena Agostini 11351306a73bSElena Agostini res = pfn_cuCtxGetApiVersion(pctx, &cuda_api_version); 11361306a73bSElena Agostini if (res != 0) { 11371306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetApiVersion failed with %d", res); 113894220b39SElena Agostini rte_errno = ENOTSUP; 113994220b39SElena Agostini return -rte_errno; 11401306a73bSElena Agostini } 11411306a73bSElena Agostini 11421306a73bSElena Agostini if (cuda_api_version < CUDA_API_MIN_VERSION) { 11431306a73bSElena Agostini rte_cuda_log(ERR, "CUDA API version found is %d Minimum requirement is %d", 11441306a73bSElena Agostini cuda_api_version, CUDA_API_MIN_VERSION); 114594220b39SElena Agostini rte_errno = ENOTSUP; 114694220b39SElena Agostini return -rte_errno; 11471306a73bSElena Agostini } 11481306a73bSElena Agostini 11491306a73bSElena Agostini dev->mpshared->info.context = (uint64_t)pctx; 11501306a73bSElena Agostini 11511306a73bSElena Agostini /* 11521306a73bSElena Agostini * GPU Device generic info 11531306a73bSElena Agostini */ 11541306a73bSElena Agostini 11551306a73bSElena Agostini /* Processor count */ 11561306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(processor_count), 11571306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT, 11581306a73bSElena Agostini cu_dev_id); 11591306a73bSElena Agostini if (res != 0) { 11601306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11611306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 11621306a73bSElena Agostini err_string); 116394220b39SElena Agostini rte_errno = EPERM; 116494220b39SElena Agostini return -rte_errno; 11651306a73bSElena Agostini } 11661306a73bSElena Agostini dev->mpshared->info.processor_count = (uint32_t)processor_count; 11671306a73bSElena Agostini 11681306a73bSElena Agostini /* Total memory */ 11691306a73bSElena Agostini res = pfn_cuDeviceTotalMem(&dev->mpshared->info.total_memory, cu_dev_id); 11701306a73bSElena Agostini if (res != 0) { 11711306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11721306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceTotalMem failed with %s", 11731306a73bSElena Agostini err_string); 117494220b39SElena Agostini rte_errno = EPERM; 117594220b39SElena Agostini return -rte_errno; 11761306a73bSElena Agostini } 11771306a73bSElena Agostini 1178*1fd3de64SElena Agostini dev->mpshared->info.page_size = (size_t)GPU_PAGE_SIZE; 1179*1fd3de64SElena Agostini 11801306a73bSElena Agostini /* 11811306a73bSElena Agostini * GPU Device private info 11821306a73bSElena Agostini */ 11831306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL, 11841306a73bSElena Agostini sizeof(struct cuda_info), 11851306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 11861306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) { 11871306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private"); 118894220b39SElena Agostini rte_errno = EPERM; 118994220b39SElena Agostini return -rte_errno; 11901306a73bSElena Agostini } 11911306a73bSElena Agostini 11921306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 11931306a73bSElena Agostini private->cu_dev = cu_dev_id; 11941306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name, 11951306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN, 11961306a73bSElena Agostini cu_dev_id); 11971306a73bSElena Agostini if (res != 0) { 11981306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11991306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s", 12001306a73bSElena Agostini err_string); 120194220b39SElena Agostini rte_errno = EPERM; 120294220b39SElena Agostini return -rte_errno; 12031306a73bSElena Agostini } 12041306a73bSElena Agostini 12051306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_supported), 12061306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_SUPPORTED, 12071306a73bSElena Agostini cu_dev_id); 12081306a73bSElena Agostini if (res != 0) { 12091306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12101306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 12111306a73bSElena Agostini err_string); 121294220b39SElena Agostini rte_errno = EPERM; 121394220b39SElena Agostini return -rte_errno; 12141306a73bSElena Agostini } 12151306a73bSElena Agostini 12161306a73bSElena Agostini if (private->gdr_supported == 0) 12171306a73bSElena Agostini rte_cuda_log(WARNING, "GPU %s doesn't support GPUDirect RDMA", 12181306a73bSElena Agostini pci_dev->device.name); 12191306a73bSElena Agostini 12201306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_write_ordering), 12211306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_WRITES_ORDERING, 12221306a73bSElena Agostini cu_dev_id); 12231306a73bSElena Agostini if (res != 0) { 12241306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12251306a73bSElena Agostini rte_cuda_log(ERR, 12261306a73bSElena Agostini "cuDeviceGetAttribute failed with %s", 12271306a73bSElena Agostini err_string); 122894220b39SElena Agostini rte_errno = EPERM; 122994220b39SElena Agostini return -rte_errno; 12301306a73bSElena Agostini } 12311306a73bSElena Agostini 12321306a73bSElena Agostini if (private->gdr_write_ordering == CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) { 12331306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_flush_type), 12341306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_FLUSH_WRITES_OPTIONS, 12351306a73bSElena Agostini cu_dev_id); 12361306a73bSElena Agostini if (res != 0) { 12371306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12381306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 12391306a73bSElena Agostini err_string); 124094220b39SElena Agostini rte_errno = EPERM; 124194220b39SElena Agostini return -rte_errno; 12421306a73bSElena Agostini } 12431306a73bSElena Agostini 12441306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) 12451306a73bSElena Agostini rte_cuda_log(ERR, "GPUDirect RDMA flush writes API is not supported"); 12461306a73bSElena Agostini } 12471306a73bSElena Agostini 12481306a73bSElena Agostini dev->ops.dev_info_get = cuda_dev_info_get; 12491306a73bSElena Agostini dev->ops.dev_close = cuda_dev_close; 12501306a73bSElena Agostini dev->ops.mem_alloc = cuda_mem_alloc; 12511306a73bSElena Agostini dev->ops.mem_free = cuda_mem_free; 12521306a73bSElena Agostini dev->ops.mem_register = cuda_mem_register; 12531306a73bSElena Agostini dev->ops.mem_unregister = cuda_mem_unregister; 125424c77594SElena Agostini dev->ops.mem_cpu_map = cuda_mem_cpu_map; 125524c77594SElena Agostini dev->ops.mem_cpu_unmap = cuda_mem_cpu_unmap; 12561306a73bSElena Agostini dev->ops.wmb = cuda_wmb; 12571306a73bSElena Agostini 12581306a73bSElena Agostini rte_gpu_complete_new(dev); 12591306a73bSElena Agostini 12601306a73bSElena Agostini rte_cuda_debug("dev id = %u name = %s", 12611306a73bSElena Agostini dev->mpshared->info.dev_id, private->gpu_name); 12621306a73bSElena Agostini 12631306a73bSElena Agostini return 0; 12641306a73bSElena Agostini } 12651306a73bSElena Agostini 12661306a73bSElena Agostini static int 12671306a73bSElena Agostini cuda_gpu_remove(struct rte_pci_device *pci_dev) 12681306a73bSElena Agostini { 12691306a73bSElena Agostini struct rte_gpu *dev; 12701306a73bSElena Agostini int ret; 12711306a73bSElena Agostini uint8_t gpu_id; 12721306a73bSElena Agostini 127394220b39SElena Agostini if (pci_dev == NULL) { 127494220b39SElena Agostini rte_errno = ENODEV; 127594220b39SElena Agostini return -rte_errno; 127694220b39SElena Agostini } 12771306a73bSElena Agostini 12781306a73bSElena Agostini dev = rte_gpu_get_by_name(pci_dev->device.name); 12791306a73bSElena Agostini if (dev == NULL) { 12801306a73bSElena Agostini rte_cuda_log(ERR, "Couldn't find HW dev \"%s\" to uninitialise it", 12811306a73bSElena Agostini pci_dev->device.name); 128294220b39SElena Agostini rte_errno = ENODEV; 128394220b39SElena Agostini return -rte_errno; 12841306a73bSElena Agostini } 12851306a73bSElena Agostini gpu_id = dev->mpshared->info.dev_id; 12861306a73bSElena Agostini 12871306a73bSElena Agostini /* release dev from library */ 12881306a73bSElena Agostini ret = rte_gpu_release(dev); 12891306a73bSElena Agostini if (ret) 12901306a73bSElena Agostini rte_cuda_log(ERR, "Device %i failed to uninit: %i", gpu_id, ret); 12911306a73bSElena Agostini 12921306a73bSElena Agostini rte_cuda_debug("Destroyed dev = %u", gpu_id); 12931306a73bSElena Agostini 12941306a73bSElena Agostini return 0; 12951306a73bSElena Agostini } 12961306a73bSElena Agostini 12971306a73bSElena Agostini static struct rte_pci_driver rte_cuda_driver = { 12981306a73bSElena Agostini .id_table = pci_id_cuda_map, 12991306a73bSElena Agostini .drv_flags = RTE_PCI_DRV_WC_ACTIVATE, 13001306a73bSElena Agostini .probe = cuda_gpu_probe, 13011306a73bSElena Agostini .remove = cuda_gpu_remove, 13021306a73bSElena Agostini }; 13031306a73bSElena Agostini 13041306a73bSElena Agostini RTE_PMD_REGISTER_PCI(gpu_cuda, rte_cuda_driver); 13051306a73bSElena Agostini RTE_PMD_REGISTER_PCI_TABLE(gpu_cuda, pci_id_cuda_map); 13061306a73bSElena Agostini RTE_PMD_REGISTER_KMOD_DEP(gpu_cuda, "* nvidia & (nv_peer_mem | nvpeer_mem)"); 1307