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" 19*7850d19fSElena Agostini #include "devices.h" 2024c77594SElena Agostini 211306a73bSElena Agostini #define CUDA_DRIVER_MIN_VERSION 11040 221306a73bSElena Agostini #define CUDA_API_MIN_VERSION 3020 231306a73bSElena Agostini 241306a73bSElena Agostini /* CUDA Driver functions loaded with dlsym() */ 251306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuInit)(unsigned int flags); 261306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuDriverGetVersion)(int *driverVersion); 271306a73bSElena Agostini static CUresult CUDAAPI (*sym_cuGetProcAddress)(const char *symbol, 281306a73bSElena Agostini void **pfn, int cudaVersion, uint64_t flags); 291306a73bSElena Agostini 301306a73bSElena Agostini /* CUDA Driver functions loaded with cuGetProcAddress for versioning */ 311306a73bSElena Agostini static PFN_cuGetErrorString pfn_cuGetErrorString; 321306a73bSElena Agostini static PFN_cuGetErrorName pfn_cuGetErrorName; 331306a73bSElena Agostini static PFN_cuPointerSetAttribute pfn_cuPointerSetAttribute; 341306a73bSElena Agostini static PFN_cuDeviceGetAttribute pfn_cuDeviceGetAttribute; 351306a73bSElena Agostini static PFN_cuDeviceGetByPCIBusId pfn_cuDeviceGetByPCIBusId; 361306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRetain pfn_cuDevicePrimaryCtxRetain; 371306a73bSElena Agostini static PFN_cuDevicePrimaryCtxRelease pfn_cuDevicePrimaryCtxRelease; 381306a73bSElena Agostini static PFN_cuDeviceTotalMem pfn_cuDeviceTotalMem; 391306a73bSElena Agostini static PFN_cuDeviceGetName pfn_cuDeviceGetName; 401306a73bSElena Agostini static PFN_cuCtxGetApiVersion pfn_cuCtxGetApiVersion; 411306a73bSElena Agostini static PFN_cuCtxSetCurrent pfn_cuCtxSetCurrent; 421306a73bSElena Agostini static PFN_cuCtxGetCurrent pfn_cuCtxGetCurrent; 431306a73bSElena Agostini static PFN_cuCtxGetDevice pfn_cuCtxGetDevice; 441306a73bSElena Agostini static PFN_cuCtxGetExecAffinity pfn_cuCtxGetExecAffinity; 451306a73bSElena Agostini static PFN_cuMemAlloc pfn_cuMemAlloc; 461306a73bSElena Agostini static PFN_cuMemFree pfn_cuMemFree; 471306a73bSElena Agostini static PFN_cuMemHostRegister pfn_cuMemHostRegister; 481306a73bSElena Agostini static PFN_cuMemHostUnregister pfn_cuMemHostUnregister; 491306a73bSElena Agostini static PFN_cuMemHostGetDevicePointer pfn_cuMemHostGetDevicePointer; 501306a73bSElena Agostini static PFN_cuFlushGPUDirectRDMAWrites pfn_cuFlushGPUDirectRDMAWrites; 511306a73bSElena Agostini 521306a73bSElena Agostini static void *cudalib; 531306a73bSElena Agostini static unsigned int cuda_api_version; 541306a73bSElena Agostini static int cuda_driver_version; 5524c77594SElena Agostini static gdr_t gdrc_h; 561306a73bSElena Agostini 571306a73bSElena Agostini #define CUDA_MAX_ALLOCATION_NUM 512 581306a73bSElena Agostini 591306a73bSElena Agostini #define GPU_PAGE_SHIFT 16 601306a73bSElena Agostini #define GPU_PAGE_SIZE (1UL << GPU_PAGE_SHIFT) 611306a73bSElena Agostini 6224c77594SElena Agostini RTE_LOG_REGISTER_DEFAULT(cuda_logtype, NOTICE); 631306a73bSElena Agostini 641306a73bSElena Agostini /* NVIDIA GPU address map */ 651306a73bSElena Agostini static const struct rte_pci_id pci_id_cuda_map[] = { 661306a73bSElena Agostini { 671306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 68*7850d19fSElena Agostini NVIDIA_GPU_A40_DEVICE_ID) 6965ac1464SElena Agostini }, 7065ac1464SElena Agostini { 7165ac1464SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 721306a73bSElena Agostini NVIDIA_GPU_A30_24GB_DEVICE_ID) 731306a73bSElena Agostini }, 741306a73bSElena Agostini { 751306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 76*7850d19fSElena Agostini NVIDIA_GPU_A30X_24GB_DPU_DEVICE_ID) 77442876b2SElena Agostini }, 78442876b2SElena Agostini { 79442876b2SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 801306a73bSElena Agostini NVIDIA_GPU_A10_24GB_DEVICE_ID) 811306a73bSElena Agostini }, 821306a73bSElena Agostini { 831306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 84*7850d19fSElena Agostini NVIDIA_GPU_A10G_DEVICE_ID) 85*7850d19fSElena Agostini }, 86*7850d19fSElena Agostini { 87*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 88*7850d19fSElena Agostini NVIDIA_GPU_A10M_DEVICE_ID) 89*7850d19fSElena Agostini }, 90*7850d19fSElena Agostini { 91*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 92*7850d19fSElena Agostini NVIDIA_GPU_A100_40GB_SXM4_DEVICE_ID) 93*7850d19fSElena Agostini }, 94*7850d19fSElena Agostini { 95*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 96*7850d19fSElena Agostini NVIDIA_GPU_A100_40GB_PCIE_DEVICE_ID) 97*7850d19fSElena Agostini }, 98*7850d19fSElena Agostini { 99*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 100*7850d19fSElena Agostini NVIDIA_GPU_A100_80GB_SXM4_DEVICE_ID) 101*7850d19fSElena Agostini }, 102*7850d19fSElena Agostini { 103*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 104*7850d19fSElena Agostini NVIDIA_GPU_A100_80GB_PCIE_DEVICE_ID) 105*7850d19fSElena Agostini }, 106*7850d19fSElena Agostini { 107*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 108*7850d19fSElena Agostini NVIDIA_GPU_A100X_80GB_DPU_DEVICE_ID) 109*7850d19fSElena Agostini }, 110*7850d19fSElena Agostini { 111*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 112*7850d19fSElena Agostini NVIDIA_GPU_GA100_PG506_207) 113*7850d19fSElena Agostini }, 114*7850d19fSElena Agostini { 115*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 116*7850d19fSElena Agostini NVIDIA_GPU_GA100_PCIE) 117*7850d19fSElena Agostini }, 118*7850d19fSElena Agostini { 119*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 120*7850d19fSElena Agostini NVIDIA_GPU_GA100_PG506_217) 121*7850d19fSElena Agostini }, 122*7850d19fSElena Agostini { 123*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 124*7850d19fSElena Agostini NVIDIA_GPU_V100_16GB_SXM2_DEVICE_ID) 125*7850d19fSElena Agostini }, 126*7850d19fSElena Agostini { 127*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 128*7850d19fSElena Agostini NVIDIA_GPU_V100_16GB_DGXS_DEVICE_ID) 129*7850d19fSElena Agostini }, 130*7850d19fSElena Agostini { 131*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 132*7850d19fSElena Agostini NVIDIA_GPU_V100_16GB_FHHL_DEVICE_ID) 133*7850d19fSElena Agostini }, 134*7850d19fSElena Agostini { 135*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 136*7850d19fSElena Agostini NVIDIA_GPU_V100_16GB_PCIE_DEVICE_ID) 137*7850d19fSElena Agostini }, 138*7850d19fSElena Agostini { 139*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 140*7850d19fSElena Agostini NVIDIA_GPU_V100_32GB_SXM2_DEVICE_ID) 14156b5bb50SElena Agostini }, 14256b5bb50SElena Agostini { 14356b5bb50SElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 14456b5bb50SElena Agostini NVIDIA_GPU_V100_32GB_PCIE_DEVICE_ID) 1451306a73bSElena Agostini }, 1461306a73bSElena Agostini { 1471306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 148*7850d19fSElena Agostini NVIDIA_GPU_V100_32GB_DGXS_DEVICE_ID) 1491306a73bSElena Agostini }, 1501306a73bSElena Agostini { 1511306a73bSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 152*7850d19fSElena Agostini NVIDIA_GPU_V100_32GB_SXM3_DEVICE_ID) 153*7850d19fSElena Agostini }, 154*7850d19fSElena Agostini { 155*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 156*7850d19fSElena Agostini NVIDIA_GPU_V100_32GB_SXM3_H_DEVICE_ID) 157*7850d19fSElena Agostini }, 158*7850d19fSElena Agostini { 159*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 160*7850d19fSElena Agostini NVIDIA_GPU_V100_SXM2) 161*7850d19fSElena Agostini }, 162*7850d19fSElena Agostini { 163*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 164*7850d19fSElena Agostini NVIDIA_GPU_V100S_PCIE) 165*7850d19fSElena Agostini }, 166*7850d19fSElena Agostini { 167*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 168*7850d19fSElena Agostini NVIDIA_GPU_TITAN_V_CEO_ED) 169*7850d19fSElena Agostini }, 170*7850d19fSElena Agostini { 171*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 172*7850d19fSElena Agostini NVIDIA_GPU_GV100GL_PG500_216) 173*7850d19fSElena Agostini }, 174*7850d19fSElena Agostini { 175*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 176*7850d19fSElena Agostini NVIDIA_GPU_GV100GL_PG503_216) 177*7850d19fSElena Agostini }, 178*7850d19fSElena Agostini { 179*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 180*7850d19fSElena Agostini NVIDIA_GPU_TU102_TITAN_RTX) 181*7850d19fSElena Agostini }, 182*7850d19fSElena Agostini { 183*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 184*7850d19fSElena Agostini NVIDIA_GPU_TU102GL_QUADRO_RTX) 185*7850d19fSElena Agostini }, 186*7850d19fSElena Agostini { 187*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 188*7850d19fSElena Agostini NVIDIA_GPU_GV100_QUADRO_DEVICE_ID) 189*7850d19fSElena Agostini }, 190*7850d19fSElena Agostini { 191*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 192*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_4000) 193*7850d19fSElena Agostini }, 194*7850d19fSElena Agostini { 195*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 196*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_5000) 197*7850d19fSElena Agostini }, 198*7850d19fSElena Agostini { 199*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 200*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_6000) 201*7850d19fSElena Agostini }, 202*7850d19fSElena Agostini { 203*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 204*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_8000) 205*7850d19fSElena Agostini }, 206*7850d19fSElena Agostini { 207*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 208*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A4000) 209*7850d19fSElena Agostini }, 210*7850d19fSElena Agostini { 211*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 212*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A6000) 213*7850d19fSElena Agostini }, 214*7850d19fSElena Agostini { 215*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 216*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A5000) 217*7850d19fSElena Agostini }, 218*7850d19fSElena Agostini { 219*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 220*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A4500) 221*7850d19fSElena Agostini }, 222*7850d19fSElena Agostini { 223*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 224*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A5500) 225*7850d19fSElena Agostini }, 226*7850d19fSElena Agostini { 227*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 228*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A2000) 229*7850d19fSElena Agostini }, 230*7850d19fSElena Agostini { 231*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 232*7850d19fSElena Agostini NVIDIA_GPU_QUADRO_RTX_A2000_12GB) 233*7850d19fSElena Agostini }, 234*7850d19fSElena Agostini { 235*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 236*7850d19fSElena Agostini NVIDIA_GPU_T4G) 237*7850d19fSElena Agostini }, 238*7850d19fSElena Agostini { 239*7850d19fSElena Agostini RTE_PCI_DEVICE(NVIDIA_GPU_VENDOR_ID, 240*7850d19fSElena Agostini NVIDIA_GPU_T4) 2411306a73bSElena Agostini }, 2421306a73bSElena Agostini { 2431306a73bSElena Agostini .device_id = 0 2441306a73bSElena Agostini } 2451306a73bSElena Agostini }; 2461306a73bSElena Agostini 2471306a73bSElena Agostini /* Device private info */ 2481306a73bSElena Agostini struct cuda_info { 2491306a73bSElena Agostini char gpu_name[RTE_DEV_NAME_MAX_LEN]; 2501306a73bSElena Agostini CUdevice cu_dev; 2511306a73bSElena Agostini int gdr_supported; 2521306a73bSElena Agostini int gdr_write_ordering; 2531306a73bSElena Agostini int gdr_flush_type; 2541306a73bSElena Agostini }; 2551306a73bSElena Agostini 2561306a73bSElena Agostini /* Type of memory allocated by CUDA driver */ 2571306a73bSElena Agostini enum mem_type { 2581306a73bSElena Agostini GPU_MEM = 0, 2591306a73bSElena Agostini CPU_REGISTERED, 2601306a73bSElena Agostini GPU_REGISTERED /* Not used yet */ 2611306a73bSElena Agostini }; 2621306a73bSElena Agostini 2631306a73bSElena Agostini /* key associated to a memory address */ 2641306a73bSElena Agostini typedef uintptr_t cuda_ptr_key; 2651306a73bSElena Agostini 2661306a73bSElena Agostini /* Single entry of the memory list */ 2671306a73bSElena Agostini struct mem_entry { 2681306a73bSElena Agostini CUdeviceptr ptr_d; 269c8557ed4SElena Agostini CUdeviceptr ptr_orig_d; 2701306a73bSElena Agostini void *ptr_h; 2711306a73bSElena Agostini size_t size; 272c8557ed4SElena Agostini size_t size_orig; 2731306a73bSElena Agostini struct rte_gpu *dev; 2741306a73bSElena Agostini CUcontext ctx; 2751306a73bSElena Agostini cuda_ptr_key pkey; 2761306a73bSElena Agostini enum mem_type mtype; 27724c77594SElena Agostini gdr_mh_t mh; 2781306a73bSElena Agostini struct mem_entry *prev; 2791306a73bSElena Agostini struct mem_entry *next; 2801306a73bSElena Agostini }; 2811306a73bSElena Agostini 2821306a73bSElena Agostini static struct mem_entry *mem_alloc_list_head; 2831306a73bSElena Agostini static struct mem_entry *mem_alloc_list_tail; 2841306a73bSElena Agostini static uint32_t mem_alloc_list_last_elem; 2851306a73bSElena Agostini 2861306a73bSElena Agostini /* Load the CUDA symbols */ 2871306a73bSElena Agostini 2881306a73bSElena Agostini static int 2891306a73bSElena Agostini cuda_loader(void) 2901306a73bSElena Agostini { 2911306a73bSElena Agostini char cuda_path[1024]; 2921306a73bSElena Agostini 2931306a73bSElena Agostini if (getenv("CUDA_PATH_L") == NULL) 2941306a73bSElena Agostini snprintf(cuda_path, 1024, "%s", "libcuda.so"); 2951306a73bSElena Agostini else 2960105d49eSElena Agostini snprintf(cuda_path, 1024, "%s/%s", getenv("CUDA_PATH_L"), "libcuda.so"); 2971306a73bSElena Agostini 2981306a73bSElena Agostini cudalib = dlopen(cuda_path, RTLD_LAZY); 2991306a73bSElena Agostini if (cudalib == NULL) { 3001306a73bSElena Agostini rte_cuda_log(ERR, "Failed to find CUDA library in %s (CUDA_PATH_L=%s)", 3011306a73bSElena Agostini cuda_path, getenv("CUDA_PATH_L")); 3021306a73bSElena Agostini return -1; 3031306a73bSElena Agostini } 3041306a73bSElena Agostini 3051306a73bSElena Agostini return 0; 3061306a73bSElena Agostini } 3071306a73bSElena Agostini 3081306a73bSElena Agostini static int 3091306a73bSElena Agostini cuda_sym_func_loader(void) 3101306a73bSElena Agostini { 3111306a73bSElena Agostini if (cudalib == NULL) 3121306a73bSElena Agostini return -1; 3131306a73bSElena Agostini 3141306a73bSElena Agostini sym_cuInit = dlsym(cudalib, "cuInit"); 3151306a73bSElena Agostini if (sym_cuInit == NULL) { 3161306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuInit"); 3171306a73bSElena Agostini return -1; 3181306a73bSElena Agostini } 3191306a73bSElena Agostini 3201306a73bSElena Agostini sym_cuDriverGetVersion = dlsym(cudalib, "cuDriverGetVersion"); 3211306a73bSElena Agostini if (sym_cuDriverGetVersion == NULL) { 3221306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuDriverGetVersion"); 3231306a73bSElena Agostini return -1; 3241306a73bSElena Agostini } 3251306a73bSElena Agostini 3261306a73bSElena Agostini sym_cuGetProcAddress = dlsym(cudalib, "cuGetProcAddress"); 3271306a73bSElena Agostini if (sym_cuGetProcAddress == NULL) { 3281306a73bSElena Agostini rte_cuda_log(ERR, "Failed to load CUDA missing symbol cuGetProcAddress"); 3291306a73bSElena Agostini return -1; 3301306a73bSElena Agostini } 3311306a73bSElena Agostini 3321306a73bSElena Agostini return 0; 3331306a73bSElena Agostini } 3341306a73bSElena Agostini 3351306a73bSElena Agostini static int 3361306a73bSElena Agostini cuda_pfn_func_loader(void) 3371306a73bSElena Agostini { 3381306a73bSElena Agostini CUresult res; 3391306a73bSElena Agostini 3401306a73bSElena Agostini res = sym_cuGetProcAddress("cuGetErrorString", 3411306a73bSElena Agostini (void **) (&pfn_cuGetErrorString), cuda_driver_version, 0); 3421306a73bSElena Agostini if (res != 0) { 3431306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorString failed with %d", res); 3441306a73bSElena Agostini return -1; 3451306a73bSElena Agostini } 3461306a73bSElena Agostini 3471306a73bSElena Agostini res = sym_cuGetProcAddress("cuGetErrorName", 3481306a73bSElena Agostini (void **)(&pfn_cuGetErrorName), cuda_driver_version, 0); 3491306a73bSElena Agostini if (res != 0) { 3501306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuGetErrorName failed with %d", res); 3511306a73bSElena Agostini return -1; 3521306a73bSElena Agostini } 3531306a73bSElena Agostini 3541306a73bSElena Agostini res = sym_cuGetProcAddress("cuPointerSetAttribute", 3551306a73bSElena Agostini (void **)(&pfn_cuPointerSetAttribute), cuda_driver_version, 0); 3561306a73bSElena Agostini if (res != 0) { 3571306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuPointerSetAttribute failed with %d", res); 3581306a73bSElena Agostini return -1; 3591306a73bSElena Agostini } 3601306a73bSElena Agostini 3611306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetAttribute", 3621306a73bSElena Agostini (void **)(&pfn_cuDeviceGetAttribute), cuda_driver_version, 0); 3631306a73bSElena Agostini if (res != 0) { 3641306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetAttribute failed with %d", res); 3651306a73bSElena Agostini return -1; 3661306a73bSElena Agostini } 3671306a73bSElena Agostini 3681306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetByPCIBusId", 3691306a73bSElena Agostini (void **)(&pfn_cuDeviceGetByPCIBusId), cuda_driver_version, 0); 3701306a73bSElena Agostini if (res != 0) { 3711306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetByPCIBusId failed with %d", res); 3721306a73bSElena Agostini return -1; 3731306a73bSElena Agostini } 3741306a73bSElena Agostini 3751306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceGetName", 3761306a73bSElena Agostini (void **)(&pfn_cuDeviceGetName), cuda_driver_version, 0); 3771306a73bSElena Agostini if (res != 0) { 3781306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceGetName failed with %d", res); 3791306a73bSElena Agostini return -1; 3801306a73bSElena Agostini } 3811306a73bSElena Agostini 3821306a73bSElena Agostini res = sym_cuGetProcAddress("cuDevicePrimaryCtxRetain", 3831306a73bSElena Agostini (void **)(&pfn_cuDevicePrimaryCtxRetain), cuda_driver_version, 0); 3841306a73bSElena Agostini if (res != 0) { 3851306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRetain failed with %d", res); 3861306a73bSElena Agostini return -1; 3871306a73bSElena Agostini } 3881306a73bSElena Agostini 3891306a73bSElena Agostini res = sym_cuGetProcAddress("cuDevicePrimaryCtxRelease", 3901306a73bSElena Agostini (void **)(&pfn_cuDevicePrimaryCtxRelease), cuda_driver_version, 0); 3911306a73bSElena Agostini if (res != 0) { 3921306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDevicePrimaryCtxRelease failed with %d", res); 3931306a73bSElena Agostini return -1; 3941306a73bSElena Agostini } 3951306a73bSElena Agostini 3961306a73bSElena Agostini res = sym_cuGetProcAddress("cuDeviceTotalMem", 3971306a73bSElena Agostini (void **)(&pfn_cuDeviceTotalMem), cuda_driver_version, 0); 3981306a73bSElena Agostini if (res != 0) { 3991306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuDeviceTotalMem failed with %d", res); 4001306a73bSElena Agostini return -1; 4011306a73bSElena Agostini } 4021306a73bSElena Agostini 4031306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetApiVersion", 4041306a73bSElena Agostini (void **)(&pfn_cuCtxGetApiVersion), cuda_driver_version, 0); 4051306a73bSElena Agostini if (res != 0) { 4061306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetApiVersion failed with %d", res); 4071306a73bSElena Agostini return -1; 4081306a73bSElena Agostini } 4091306a73bSElena Agostini 4101306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetDevice", 4111306a73bSElena Agostini (void **)(&pfn_cuCtxGetDevice), cuda_driver_version, 0); 4121306a73bSElena Agostini if (res != 0) { 4131306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetDevice failed with %d", res); 4141306a73bSElena Agostini return -1; 4151306a73bSElena Agostini } 4161306a73bSElena Agostini 4171306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxSetCurrent", 4181306a73bSElena Agostini (void **)(&pfn_cuCtxSetCurrent), cuda_driver_version, 0); 4191306a73bSElena Agostini if (res != 0) { 4201306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxSetCurrent failed with %d", res); 4211306a73bSElena Agostini return -1; 4221306a73bSElena Agostini } 4231306a73bSElena Agostini 4241306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetCurrent", 4251306a73bSElena Agostini (void **)(&pfn_cuCtxGetCurrent), cuda_driver_version, 0); 4261306a73bSElena Agostini if (res != 0) { 4271306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetCurrent failed with %d", res); 4281306a73bSElena Agostini return -1; 4291306a73bSElena Agostini } 4301306a73bSElena Agostini 4311306a73bSElena Agostini res = sym_cuGetProcAddress("cuCtxGetExecAffinity", 4321306a73bSElena Agostini (void **)(&pfn_cuCtxGetExecAffinity), cuda_driver_version, 0); 4331306a73bSElena Agostini if (res != 0) { 4341306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuCtxGetExecAffinity failed with %d", res); 4351306a73bSElena Agostini return -1; 4361306a73bSElena Agostini } 4371306a73bSElena Agostini 4381306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemAlloc", 4391306a73bSElena Agostini (void **)(&pfn_cuMemAlloc), cuda_driver_version, 0); 4401306a73bSElena Agostini if (res != 0) { 4411306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemAlloc failed with %d", res); 4421306a73bSElena Agostini return -1; 4431306a73bSElena Agostini } 4441306a73bSElena Agostini 4451306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemFree", 4461306a73bSElena Agostini (void **)(&pfn_cuMemFree), cuda_driver_version, 0); 4471306a73bSElena Agostini if (res != 0) { 4481306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemFree failed with %d", res); 4491306a73bSElena Agostini return -1; 4501306a73bSElena Agostini } 4511306a73bSElena Agostini 4521306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostRegister", 4531306a73bSElena Agostini (void **)(&pfn_cuMemHostRegister), cuda_driver_version, 0); 4541306a73bSElena Agostini if (res != 0) { 4551306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostRegister failed with %d", res); 4561306a73bSElena Agostini return -1; 4571306a73bSElena Agostini } 4581306a73bSElena Agostini 4591306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostUnregister", 4601306a73bSElena Agostini (void **)(&pfn_cuMemHostUnregister), cuda_driver_version, 0); 4611306a73bSElena Agostini if (res != 0) { 4621306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostUnregister failed with %d", res); 4631306a73bSElena Agostini return -1; 4641306a73bSElena Agostini } 4651306a73bSElena Agostini 4661306a73bSElena Agostini res = sym_cuGetProcAddress("cuMemHostGetDevicePointer", 4671306a73bSElena Agostini (void **)(&pfn_cuMemHostGetDevicePointer), cuda_driver_version, 0); 4681306a73bSElena Agostini if (res != 0) { 4691306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve pfn_cuMemHostGetDevicePointer failed with %d", res); 4701306a73bSElena Agostini return -1; 4711306a73bSElena Agostini } 4721306a73bSElena Agostini 4731306a73bSElena Agostini res = sym_cuGetProcAddress("cuFlushGPUDirectRDMAWrites", 4741306a73bSElena Agostini (void **)(&pfn_cuFlushGPUDirectRDMAWrites), cuda_driver_version, 0); 4751306a73bSElena Agostini if (res != 0) { 4761306a73bSElena Agostini rte_cuda_log(ERR, "Retrieve cuFlushGPUDirectRDMAWrites failed with %d", res); 4771306a73bSElena Agostini return -1; 4781306a73bSElena Agostini } 4791306a73bSElena Agostini 4801306a73bSElena Agostini return 0; 4811306a73bSElena Agostini } 4821306a73bSElena Agostini 4831306a73bSElena Agostini /* Generate a key from a memory pointer */ 4841306a73bSElena Agostini static cuda_ptr_key 4851306a73bSElena Agostini get_hash_from_ptr(void *ptr) 4861306a73bSElena Agostini { 4871306a73bSElena Agostini return (uintptr_t)ptr; 4881306a73bSElena Agostini } 4891306a73bSElena Agostini 4901306a73bSElena Agostini static uint32_t 4911306a73bSElena Agostini mem_list_count_item(void) 4921306a73bSElena Agostini { 4931306a73bSElena Agostini return mem_alloc_list_last_elem; 4941306a73bSElena Agostini } 4951306a73bSElena Agostini 4961306a73bSElena Agostini /* Initiate list of memory allocations if not done yet */ 4971306a73bSElena Agostini static struct mem_entry * 4981306a73bSElena Agostini mem_list_add_item(void) 4991306a73bSElena Agostini { 5001306a73bSElena Agostini /* Initiate list of memory allocations if not done yet */ 5011306a73bSElena Agostini if (mem_alloc_list_head == NULL) { 5021306a73bSElena Agostini mem_alloc_list_head = rte_zmalloc(NULL, 5031306a73bSElena Agostini sizeof(struct mem_entry), 5041306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 5051306a73bSElena Agostini if (mem_alloc_list_head == NULL) { 5061306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for memory list"); 5071306a73bSElena Agostini return NULL; 5081306a73bSElena Agostini } 5091306a73bSElena Agostini 5101306a73bSElena Agostini mem_alloc_list_head->next = NULL; 5111306a73bSElena Agostini mem_alloc_list_head->prev = NULL; 5121306a73bSElena Agostini mem_alloc_list_tail = mem_alloc_list_head; 5131306a73bSElena Agostini } else { 5141306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = rte_zmalloc(NULL, 5151306a73bSElena Agostini sizeof(struct mem_entry), 5161306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 5171306a73bSElena Agostini 5181306a73bSElena Agostini if (mem_alloc_list_cur == NULL) { 5191306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for memory list"); 5201306a73bSElena Agostini return NULL; 5211306a73bSElena Agostini } 5221306a73bSElena Agostini 5231306a73bSElena Agostini mem_alloc_list_tail->next = mem_alloc_list_cur; 5241306a73bSElena Agostini mem_alloc_list_cur->prev = mem_alloc_list_tail; 5251306a73bSElena Agostini mem_alloc_list_tail = mem_alloc_list_tail->next; 5261306a73bSElena Agostini mem_alloc_list_tail->next = NULL; 5271306a73bSElena Agostini } 5281306a73bSElena Agostini 5291306a73bSElena Agostini mem_alloc_list_last_elem++; 5301306a73bSElena Agostini 5311306a73bSElena Agostini return mem_alloc_list_tail; 5321306a73bSElena Agostini } 5331306a73bSElena Agostini 5341306a73bSElena Agostini static struct mem_entry * 5351306a73bSElena Agostini mem_list_find_item(cuda_ptr_key pk) 5361306a73bSElena Agostini { 5371306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = NULL; 5381306a73bSElena Agostini 5391306a73bSElena Agostini if (mem_alloc_list_head == NULL) { 5401306a73bSElena Agostini rte_cuda_log(ERR, "Memory list doesn't exist"); 5411306a73bSElena Agostini return NULL; 5421306a73bSElena Agostini } 5431306a73bSElena Agostini 5441306a73bSElena Agostini if (mem_list_count_item() == 0) { 5451306a73bSElena Agostini rte_cuda_log(ERR, "No items in memory list"); 5461306a73bSElena Agostini return NULL; 5471306a73bSElena Agostini } 5481306a73bSElena Agostini 5491306a73bSElena Agostini mem_alloc_list_cur = mem_alloc_list_head; 5501306a73bSElena Agostini 5511306a73bSElena Agostini while (mem_alloc_list_cur != NULL) { 5521306a73bSElena Agostini if (mem_alloc_list_cur->pkey == pk) 5531306a73bSElena Agostini return mem_alloc_list_cur; 5541306a73bSElena Agostini mem_alloc_list_cur = mem_alloc_list_cur->next; 5551306a73bSElena Agostini } 5561306a73bSElena Agostini 5571306a73bSElena Agostini return mem_alloc_list_cur; 5581306a73bSElena Agostini } 5591306a73bSElena Agostini 5601306a73bSElena Agostini static int 5611306a73bSElena Agostini mem_list_del_item(cuda_ptr_key pk) 5621306a73bSElena Agostini { 5631306a73bSElena Agostini struct mem_entry *mem_alloc_list_cur = NULL; 5641306a73bSElena Agostini 5651306a73bSElena Agostini mem_alloc_list_cur = mem_list_find_item(pk); 5661306a73bSElena Agostini if (mem_alloc_list_cur == NULL) 5671306a73bSElena Agostini return -EINVAL; 5681306a73bSElena Agostini 5691306a73bSElena Agostini /* if key is in head */ 57098ddd04cSElena Agostini if (mem_alloc_list_cur->prev == NULL) { 5711306a73bSElena Agostini mem_alloc_list_head = mem_alloc_list_cur->next; 57298ddd04cSElena Agostini if (mem_alloc_list_head != NULL) 57398ddd04cSElena Agostini mem_alloc_list_head->prev = NULL; 57498ddd04cSElena Agostini } else { 5751306a73bSElena Agostini mem_alloc_list_cur->prev->next = mem_alloc_list_cur->next; 5761306a73bSElena Agostini if (mem_alloc_list_cur->next != NULL) 5771306a73bSElena Agostini mem_alloc_list_cur->next->prev = mem_alloc_list_cur->prev; 5781306a73bSElena Agostini } 5791306a73bSElena Agostini 5801306a73bSElena Agostini rte_free(mem_alloc_list_cur); 5811306a73bSElena Agostini 5821306a73bSElena Agostini mem_alloc_list_last_elem--; 5831306a73bSElena Agostini 5841306a73bSElena Agostini return 0; 5851306a73bSElena Agostini } 5861306a73bSElena Agostini 5871306a73bSElena Agostini static int 5881306a73bSElena Agostini cuda_dev_info_get(struct rte_gpu *dev, struct rte_gpu_info *info) 5891306a73bSElena Agostini { 5901306a73bSElena Agostini int ret = 0; 5911306a73bSElena Agostini CUresult res; 5921306a73bSElena Agostini struct rte_gpu_info parent_info; 5931306a73bSElena Agostini CUexecAffinityParam affinityPrm; 5941306a73bSElena Agostini const char *err_string; 5951306a73bSElena Agostini struct cuda_info *private; 5961306a73bSElena Agostini CUcontext current_ctx; 5971306a73bSElena Agostini CUcontext input_ctx; 5981306a73bSElena Agostini 59994220b39SElena Agostini if (dev == NULL) { 60094220b39SElena Agostini rte_errno = ENODEV; 60194220b39SElena Agostini return -rte_errno; 60294220b39SElena Agostini } 6031306a73bSElena Agostini 6041306a73bSElena Agostini /* Child initialization time probably called by rte_gpu_add_child() */ 6051306a73bSElena Agostini if (dev->mpshared->info.parent != RTE_GPU_ID_NONE && 6061306a73bSElena Agostini dev->mpshared->dev_private == NULL) { 6071306a73bSElena Agostini /* Store current ctx */ 6081306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 6091306a73bSElena Agostini if (res != 0) { 6101306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6111306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 6121306a73bSElena Agostini err_string); 61394220b39SElena Agostini rte_errno = EPERM; 61494220b39SElena Agostini return -rte_errno; 6151306a73bSElena Agostini } 6161306a73bSElena Agostini 6171306a73bSElena Agostini /* Set child ctx as current ctx */ 6181306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 6191306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 6201306a73bSElena Agostini if (res != 0) { 6211306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6221306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 6231306a73bSElena Agostini err_string); 62494220b39SElena Agostini rte_errno = EPERM; 62594220b39SElena Agostini return -rte_errno; 6261306a73bSElena Agostini } 6271306a73bSElena Agostini 6281306a73bSElena Agostini /* 6291306a73bSElena Agostini * Ctx capacity info 6301306a73bSElena Agostini */ 6311306a73bSElena Agostini 6321306a73bSElena Agostini /* MPS compatible */ 6331306a73bSElena Agostini res = pfn_cuCtxGetExecAffinity(&affinityPrm, 6341306a73bSElena Agostini CU_EXEC_AFFINITY_TYPE_SM_COUNT); 6351306a73bSElena Agostini if (res != 0) { 6361306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6371306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetExecAffinity failed with %s", 6381306a73bSElena Agostini err_string); 6391306a73bSElena Agostini } 6401306a73bSElena Agostini dev->mpshared->info.processor_count = 6411306a73bSElena Agostini (uint32_t)affinityPrm.param.smCount.val; 6421306a73bSElena Agostini 6431306a73bSElena Agostini ret = rte_gpu_info_get(dev->mpshared->info.parent, &parent_info); 64494220b39SElena Agostini if (ret) { 64594220b39SElena Agostini rte_errno = ENODEV; 64694220b39SElena Agostini return -rte_errno; 64794220b39SElena Agostini } 6481306a73bSElena Agostini dev->mpshared->info.total_memory = parent_info.total_memory; 6491306a73bSElena Agostini 6501fd3de64SElena Agostini dev->mpshared->info.page_size = parent_info.page_size; 6511fd3de64SElena Agostini 6521306a73bSElena Agostini /* 6531306a73bSElena Agostini * GPU Device private info 6541306a73bSElena Agostini */ 6551306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL, 6561306a73bSElena Agostini sizeof(struct cuda_info), 6571306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 6581306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) { 6591306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private"); 66094220b39SElena Agostini rte_errno = EPERM; 66194220b39SElena Agostini return -rte_errno; 6621306a73bSElena Agostini } 6631306a73bSElena Agostini 6641306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 6651306a73bSElena Agostini 6661306a73bSElena Agostini res = pfn_cuCtxGetDevice(&(private->cu_dev)); 6671306a73bSElena Agostini if (res != 0) { 6681306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6691306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetDevice failed with %s", 6701306a73bSElena Agostini err_string); 67194220b39SElena Agostini rte_errno = EPERM; 67294220b39SElena Agostini return -rte_errno; 6731306a73bSElena Agostini } 6741306a73bSElena Agostini 6751306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name, 6761306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN, private->cu_dev); 6771306a73bSElena Agostini if (res != 0) { 6781306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6791306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s", 6801306a73bSElena Agostini err_string); 68194220b39SElena Agostini rte_errno = EPERM; 68294220b39SElena Agostini return -rte_errno; 6831306a73bSElena Agostini } 6841306a73bSElena Agostini 6851306a73bSElena Agostini /* Restore original ctx as current ctx */ 6861306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 6871306a73bSElena Agostini if (res != 0) { 6881306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 6891306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 6901306a73bSElena Agostini err_string); 69194220b39SElena Agostini rte_errno = EPERM; 69294220b39SElena Agostini return -rte_errno; 6931306a73bSElena Agostini } 6941306a73bSElena Agostini } 6951306a73bSElena Agostini 6961306a73bSElena Agostini *info = dev->mpshared->info; 6971306a73bSElena Agostini 6981306a73bSElena Agostini return 0; 6991306a73bSElena Agostini } 7001306a73bSElena Agostini 7011306a73bSElena Agostini /* 7021306a73bSElena Agostini * GPU Memory 7031306a73bSElena Agostini */ 7041306a73bSElena Agostini 7051306a73bSElena Agostini static int 706c8557ed4SElena Agostini cuda_mem_alloc(struct rte_gpu *dev, size_t size, unsigned int align, void **ptr) 7071306a73bSElena Agostini { 7081306a73bSElena Agostini CUresult res; 7091306a73bSElena Agostini const char *err_string; 7101306a73bSElena Agostini CUcontext current_ctx; 7111306a73bSElena Agostini CUcontext input_ctx; 7121306a73bSElena Agostini unsigned int flag = 1; 7131306a73bSElena Agostini 7141306a73bSElena Agostini if (dev == NULL) 7151306a73bSElena Agostini return -ENODEV; 7161306a73bSElena Agostini 7171306a73bSElena Agostini /* Store current ctx */ 7181306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 7191306a73bSElena Agostini if (res != 0) { 7201306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7211306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 7221306a73bSElena Agostini err_string); 72394220b39SElena Agostini rte_errno = EPERM; 72494220b39SElena Agostini return -rte_errno; 7251306a73bSElena Agostini } 7261306a73bSElena Agostini 7271306a73bSElena Agostini /* Set child ctx as current ctx */ 7281306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 7291306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 7301306a73bSElena Agostini if (res != 0) { 7311306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7321306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 7331306a73bSElena Agostini err_string); 73494220b39SElena Agostini rte_errno = EPERM; 73594220b39SElena Agostini return -rte_errno; 7361306a73bSElena Agostini } 7371306a73bSElena Agostini 7381306a73bSElena Agostini /* Get next memory list item */ 7391306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item(); 74094220b39SElena Agostini if (mem_alloc_list_tail == NULL) { 74194220b39SElena Agostini rte_errno = EPERM; 74294220b39SElena Agostini return -rte_errno; 74394220b39SElena Agostini } 7441306a73bSElena Agostini 7451306a73bSElena Agostini /* Allocate memory */ 7461306a73bSElena Agostini mem_alloc_list_tail->size = size; 747c8557ed4SElena Agostini mem_alloc_list_tail->size_orig = size + align; 748c8557ed4SElena Agostini 749c8557ed4SElena Agostini res = pfn_cuMemAlloc(&(mem_alloc_list_tail->ptr_orig_d), 750c8557ed4SElena Agostini mem_alloc_list_tail->size_orig); 7511306a73bSElena Agostini if (res != 0) { 7521306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7531306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 7541306a73bSElena Agostini err_string); 75594220b39SElena Agostini rte_errno = EPERM; 75694220b39SElena Agostini return -rte_errno; 7571306a73bSElena Agostini } 7581306a73bSElena Agostini 759c8557ed4SElena Agostini /* Align memory address */ 760c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d = mem_alloc_list_tail->ptr_orig_d; 761c8557ed4SElena Agostini if (align && ((uintptr_t)mem_alloc_list_tail->ptr_d) % align) 762c8557ed4SElena Agostini mem_alloc_list_tail->ptr_d += (align - 763c8557ed4SElena Agostini (((uintptr_t)mem_alloc_list_tail->ptr_d) % align)); 764c8557ed4SElena Agostini 7651306a73bSElena Agostini /* GPUDirect RDMA attribute required */ 7661306a73bSElena Agostini res = pfn_cuPointerSetAttribute(&flag, 7671306a73bSElena Agostini CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, 7681306a73bSElena Agostini mem_alloc_list_tail->ptr_d); 7691306a73bSElena Agostini if (res != 0) { 7701306a73bSElena Agostini rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for " 7711306a73bSElena Agostini "GPU memory at %"PRIu32", err %d", 7721306a73bSElena Agostini (uint32_t)mem_alloc_list_tail->ptr_d, res); 77394220b39SElena Agostini rte_errno = EPERM; 77494220b39SElena Agostini return -rte_errno; 7751306a73bSElena Agostini } 7761306a73bSElena Agostini 7771306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_d); 7781306a73bSElena Agostini mem_alloc_list_tail->ptr_h = NULL; 7791306a73bSElena Agostini mem_alloc_list_tail->dev = dev; 7801306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 7811306a73bSElena Agostini mem_alloc_list_tail->mtype = GPU_MEM; 7821306a73bSElena Agostini 7831306a73bSElena Agostini /* Restore original ctx as current ctx */ 7841306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 7851306a73bSElena Agostini if (res != 0) { 7861306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 7871306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 7881306a73bSElena Agostini err_string); 78994220b39SElena Agostini rte_errno = EPERM; 79094220b39SElena Agostini return -rte_errno; 7911306a73bSElena Agostini } 7921306a73bSElena Agostini 7931306a73bSElena Agostini *ptr = (void *)mem_alloc_list_tail->ptr_d; 7941306a73bSElena Agostini 7951306a73bSElena Agostini return 0; 7961306a73bSElena Agostini } 7971306a73bSElena Agostini 7981306a73bSElena Agostini static int 7991306a73bSElena Agostini cuda_mem_register(struct rte_gpu *dev, size_t size, void *ptr) 8001306a73bSElena Agostini { 8011306a73bSElena Agostini CUresult res; 8021306a73bSElena Agostini const char *err_string; 8031306a73bSElena Agostini CUcontext current_ctx; 8041306a73bSElena Agostini CUcontext input_ctx; 8051306a73bSElena Agostini unsigned int flag = 1; 8061306a73bSElena Agostini int use_ptr_h = 0; 8071306a73bSElena Agostini 8081306a73bSElena Agostini if (dev == NULL) 8091306a73bSElena Agostini return -ENODEV; 8101306a73bSElena Agostini 8111306a73bSElena Agostini /* Store current ctx */ 8121306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 8131306a73bSElena Agostini if (res != 0) { 8141306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8151306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 8161306a73bSElena Agostini err_string); 81794220b39SElena Agostini rte_errno = EPERM; 81894220b39SElena Agostini return -rte_errno; 8191306a73bSElena Agostini } 8201306a73bSElena Agostini 8211306a73bSElena Agostini /* Set child ctx as current ctx */ 8221306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 8231306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 8241306a73bSElena Agostini if (res != 0) { 8251306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8261306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 8271306a73bSElena Agostini err_string); 82894220b39SElena Agostini rte_errno = EPERM; 82994220b39SElena Agostini return -rte_errno; 8301306a73bSElena Agostini } 8311306a73bSElena Agostini 8321306a73bSElena Agostini /* Get next memory list item */ 8331306a73bSElena Agostini mem_alloc_list_tail = mem_list_add_item(); 83494220b39SElena Agostini if (mem_alloc_list_tail == NULL) { 83594220b39SElena Agostini rte_errno = EPERM; 83694220b39SElena Agostini return -rte_errno; 83794220b39SElena Agostini } 8381306a73bSElena Agostini 8391306a73bSElena Agostini /* Allocate memory */ 8401306a73bSElena Agostini mem_alloc_list_tail->size = size; 8411306a73bSElena Agostini mem_alloc_list_tail->ptr_h = ptr; 8421306a73bSElena Agostini 8431306a73bSElena Agostini res = pfn_cuMemHostRegister(mem_alloc_list_tail->ptr_h, 8441306a73bSElena Agostini mem_alloc_list_tail->size, 8451306a73bSElena Agostini CU_MEMHOSTREGISTER_PORTABLE | 8461306a73bSElena Agostini CU_MEMHOSTREGISTER_DEVICEMAP); 8471306a73bSElena Agostini if (res != 0) { 8481306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8491306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostRegister failed with %s ptr %p size %zd", 8501306a73bSElena Agostini err_string, 8511306a73bSElena Agostini mem_alloc_list_tail->ptr_h, 8521306a73bSElena Agostini mem_alloc_list_tail->size); 85394220b39SElena Agostini rte_errno = EPERM; 85494220b39SElena Agostini return -rte_errno; 8551306a73bSElena Agostini } 8561306a73bSElena Agostini 8571306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(use_ptr_h), 8581306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_CAN_USE_HOST_POINTER_FOR_REGISTERED_MEM, 8591306a73bSElena Agostini ((struct cuda_info *)(dev->mpshared->dev_private))->cu_dev); 8601306a73bSElena Agostini if (res != 0) { 8611306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8621306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 8631306a73bSElena Agostini err_string); 86494220b39SElena Agostini rte_errno = EPERM; 86594220b39SElena Agostini return -rte_errno; 8661306a73bSElena Agostini } 8671306a73bSElena Agostini 8681306a73bSElena Agostini if (use_ptr_h == 0) { 8691306a73bSElena Agostini res = pfn_cuMemHostGetDevicePointer(&(mem_alloc_list_tail->ptr_d), 8701306a73bSElena Agostini mem_alloc_list_tail->ptr_h, 0); 8711306a73bSElena Agostini if (res != 0) { 8721306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 8731306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostGetDevicePointer failed with %s", 8741306a73bSElena Agostini err_string); 87594220b39SElena Agostini rte_errno = EPERM; 87694220b39SElena Agostini return -rte_errno; 8771306a73bSElena Agostini } 8781306a73bSElena Agostini 8791306a73bSElena Agostini if ((uintptr_t)mem_alloc_list_tail->ptr_d != 8801306a73bSElena Agostini (uintptr_t)mem_alloc_list_tail->ptr_h) { 8811306a73bSElena Agostini rte_cuda_log(ERR, "Host input pointer is different wrt GPU registered pointer"); 88294220b39SElena Agostini rte_errno = ENOTSUP; 88394220b39SElena Agostini return -rte_errno; 8841306a73bSElena Agostini } 8851306a73bSElena Agostini } else { 8861306a73bSElena Agostini mem_alloc_list_tail->ptr_d = (CUdeviceptr)mem_alloc_list_tail->ptr_h; 8871306a73bSElena Agostini } 8881306a73bSElena Agostini 8891306a73bSElena Agostini /* GPUDirect RDMA attribute required */ 8901306a73bSElena Agostini res = pfn_cuPointerSetAttribute(&flag, 8911306a73bSElena Agostini CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, 8921306a73bSElena Agostini mem_alloc_list_tail->ptr_d); 8931306a73bSElena Agostini if (res != 0) { 8941306a73bSElena Agostini rte_cuda_log(ERR, "Could not set SYNC MEMOP attribute for GPU memory at %"PRIu32 8951306a73bSElena Agostini ", err %d", (uint32_t)mem_alloc_list_tail->ptr_d, res); 89694220b39SElena Agostini rte_errno = EPERM; 89794220b39SElena Agostini return -rte_errno; 8981306a73bSElena Agostini } 8991306a73bSElena Agostini 9001306a73bSElena Agostini mem_alloc_list_tail->pkey = get_hash_from_ptr((void *)mem_alloc_list_tail->ptr_h); 9011306a73bSElena Agostini mem_alloc_list_tail->size = size; 9021306a73bSElena Agostini mem_alloc_list_tail->dev = dev; 9031306a73bSElena Agostini mem_alloc_list_tail->ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 9041306a73bSElena Agostini mem_alloc_list_tail->mtype = CPU_REGISTERED; 905c8557ed4SElena Agostini mem_alloc_list_tail->ptr_orig_d = mem_alloc_list_tail->ptr_d; 9061306a73bSElena Agostini 9071306a73bSElena Agostini /* Restore original ctx as current ctx */ 9081306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 9091306a73bSElena Agostini if (res != 0) { 9101306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 9111306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 9121306a73bSElena Agostini err_string); 91394220b39SElena Agostini rte_errno = EPERM; 91494220b39SElena Agostini return -rte_errno; 9151306a73bSElena Agostini } 9161306a73bSElena Agostini 9171306a73bSElena Agostini return 0; 9181306a73bSElena Agostini } 9191306a73bSElena Agostini 9201306a73bSElena Agostini static int 92124c77594SElena Agostini cuda_mem_cpu_map(struct rte_gpu *dev, __rte_unused size_t size, void *ptr_in, void **ptr_out) 92224c77594SElena Agostini { 92324c77594SElena Agostini struct mem_entry *mem_item; 92424c77594SElena Agostini cuda_ptr_key hk; 92524c77594SElena Agostini 92624c77594SElena Agostini if (dev == NULL) 92724c77594SElena Agostini return -ENODEV; 92824c77594SElena Agostini 92924c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in); 93024c77594SElena Agostini 93124c77594SElena Agostini mem_item = mem_list_find_item(hk); 93224c77594SElena Agostini if (mem_item == NULL) { 93324c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in); 93424c77594SElena Agostini rte_errno = EPERM; 93524c77594SElena Agostini return -rte_errno; 93624c77594SElena Agostini } 93724c77594SElena Agostini 93824c77594SElena Agostini if (mem_item->mtype != GPU_MEM) { 93924c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p is not GPU memory type.", ptr_in); 94024c77594SElena Agostini rte_errno = EPERM; 94124c77594SElena Agostini return -rte_errno; 94224c77594SElena Agostini } 94324c77594SElena Agostini 94424c77594SElena Agostini if (mem_item->size != size) 94524c77594SElena Agostini rte_cuda_log(WARNING, 94624c77594SElena Agostini "Can't expose memory area with size (%zd) different from original size (%zd).", 94724c77594SElena Agostini size, mem_item->size); 94824c77594SElena Agostini 94924c77594SElena Agostini if (gdrcopy_pin(&gdrc_h, &(mem_item->mh), (uint64_t)mem_item->ptr_d, 95024c77594SElena Agostini mem_item->size, &(mem_item->ptr_h))) { 95124c77594SElena Agostini rte_cuda_log(ERR, "Error exposing GPU memory address 0x%p.", ptr_in); 95224c77594SElena Agostini rte_errno = EPERM; 95324c77594SElena Agostini return -rte_errno; 95424c77594SElena Agostini } 95524c77594SElena Agostini 95624c77594SElena Agostini *ptr_out = mem_item->ptr_h; 95724c77594SElena Agostini 95824c77594SElena Agostini return 0; 95924c77594SElena Agostini } 96024c77594SElena Agostini 96124c77594SElena Agostini static int 9621306a73bSElena Agostini cuda_mem_free(struct rte_gpu *dev, void *ptr) 9631306a73bSElena Agostini { 9641306a73bSElena Agostini CUresult res; 9651306a73bSElena Agostini struct mem_entry *mem_item; 9661306a73bSElena Agostini const char *err_string; 9671306a73bSElena Agostini cuda_ptr_key hk; 9681306a73bSElena Agostini 9691306a73bSElena Agostini if (dev == NULL) 9701306a73bSElena Agostini return -ENODEV; 9711306a73bSElena Agostini 9721306a73bSElena Agostini hk = get_hash_from_ptr((void *)ptr); 9731306a73bSElena Agostini 9741306a73bSElena Agostini mem_item = mem_list_find_item(hk); 9751306a73bSElena Agostini if (mem_item == NULL) { 9761306a73bSElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr); 97794220b39SElena Agostini rte_errno = EPERM; 97894220b39SElena Agostini return -rte_errno; 9791306a73bSElena Agostini } 9801306a73bSElena Agostini 9811306a73bSElena Agostini if (mem_item->mtype == GPU_MEM) { 982c8557ed4SElena Agostini res = pfn_cuMemFree(mem_item->ptr_orig_d); 9831306a73bSElena Agostini if (res != 0) { 9841306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 9851306a73bSElena Agostini rte_cuda_log(ERR, "cuMemFree current failed with %s", 9861306a73bSElena Agostini err_string); 98794220b39SElena Agostini rte_errno = EPERM; 98894220b39SElena Agostini return -rte_errno; 9891306a73bSElena Agostini } 9901306a73bSElena Agostini 9911306a73bSElena Agostini return mem_list_del_item(hk); 9921306a73bSElena Agostini } 9931306a73bSElena Agostini 9941306a73bSElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype); 9951306a73bSElena Agostini 9961306a73bSElena Agostini return -EPERM; 9971306a73bSElena Agostini } 9981306a73bSElena Agostini 9991306a73bSElena Agostini static int 10001306a73bSElena Agostini cuda_mem_unregister(struct rte_gpu *dev, void *ptr) 10011306a73bSElena Agostini { 10021306a73bSElena Agostini CUresult res; 10031306a73bSElena Agostini struct mem_entry *mem_item; 10041306a73bSElena Agostini const char *err_string; 10051306a73bSElena Agostini cuda_ptr_key hk; 10061306a73bSElena Agostini 10071306a73bSElena Agostini if (dev == NULL) 10081306a73bSElena Agostini return -ENODEV; 10091306a73bSElena Agostini 10101306a73bSElena Agostini hk = get_hash_from_ptr((void *)ptr); 10111306a73bSElena Agostini 10121306a73bSElena Agostini mem_item = mem_list_find_item(hk); 10131306a73bSElena Agostini if (mem_item == NULL) { 10141306a73bSElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory", ptr); 101594220b39SElena Agostini rte_errno = EPERM; 101694220b39SElena Agostini return -rte_errno; 10171306a73bSElena Agostini } 10181306a73bSElena Agostini 10191306a73bSElena Agostini if (mem_item->mtype == CPU_REGISTERED) { 10201306a73bSElena Agostini res = pfn_cuMemHostUnregister(ptr); 10211306a73bSElena Agostini if (res != 0) { 10221306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 10231306a73bSElena Agostini rte_cuda_log(ERR, "cuMemHostUnregister current failed with %s", 10241306a73bSElena Agostini err_string); 102594220b39SElena Agostini rte_errno = EPERM; 102694220b39SElena Agostini return -rte_errno; 10271306a73bSElena Agostini } 10281306a73bSElena Agostini 10291306a73bSElena Agostini return mem_list_del_item(hk); 10301306a73bSElena Agostini } 10311306a73bSElena Agostini 10321306a73bSElena Agostini rte_cuda_log(ERR, "Memory type %d not supported", mem_item->mtype); 10331306a73bSElena Agostini 103494220b39SElena Agostini rte_errno = EPERM; 103594220b39SElena Agostini return -rte_errno; 10361306a73bSElena Agostini } 10371306a73bSElena Agostini 10381306a73bSElena Agostini static int 103924c77594SElena Agostini cuda_mem_cpu_unmap(struct rte_gpu *dev, void *ptr_in) 104024c77594SElena Agostini { 104124c77594SElena Agostini struct mem_entry *mem_item; 104224c77594SElena Agostini cuda_ptr_key hk; 104324c77594SElena Agostini 104424c77594SElena Agostini if (dev == NULL) 104524c77594SElena Agostini return -ENODEV; 104624c77594SElena Agostini 104724c77594SElena Agostini hk = get_hash_from_ptr((void *)ptr_in); 104824c77594SElena Agostini 104924c77594SElena Agostini mem_item = mem_list_find_item(hk); 105024c77594SElena Agostini if (mem_item == NULL) { 105124c77594SElena Agostini rte_cuda_log(ERR, "Memory address 0x%p not found in driver memory.", ptr_in); 105224c77594SElena Agostini rte_errno = EPERM; 105324c77594SElena Agostini return -rte_errno; 105424c77594SElena Agostini } 105524c77594SElena Agostini 105624c77594SElena Agostini if (gdrcopy_unpin(gdrc_h, mem_item->mh, (void *)mem_item->ptr_d, 105724c77594SElena Agostini mem_item->size)) { 105824c77594SElena Agostini rte_cuda_log(ERR, "Error unexposing GPU memory address 0x%p.", ptr_in); 105924c77594SElena Agostini rte_errno = EPERM; 106024c77594SElena Agostini return -rte_errno; 106124c77594SElena Agostini } 106224c77594SElena Agostini 106324c77594SElena Agostini return 0; 106424c77594SElena Agostini } 106524c77594SElena Agostini 106624c77594SElena Agostini static int 10671306a73bSElena Agostini cuda_dev_close(struct rte_gpu *dev) 10681306a73bSElena Agostini { 10691306a73bSElena Agostini if (dev == NULL) 10701306a73bSElena Agostini return -EINVAL; 10711306a73bSElena Agostini 10721306a73bSElena Agostini rte_free(dev->mpshared->dev_private); 10731306a73bSElena Agostini 10741306a73bSElena Agostini return 0; 10751306a73bSElena Agostini } 10761306a73bSElena Agostini 10771306a73bSElena Agostini static int 10781306a73bSElena Agostini cuda_wmb(struct rte_gpu *dev) 10791306a73bSElena Agostini { 10801306a73bSElena Agostini CUresult res; 10811306a73bSElena Agostini const char *err_string; 10821306a73bSElena Agostini CUcontext current_ctx; 10831306a73bSElena Agostini CUcontext input_ctx; 10841306a73bSElena Agostini struct cuda_info *private; 10851306a73bSElena Agostini 108694220b39SElena Agostini if (dev == NULL) { 108794220b39SElena Agostini rte_errno = ENODEV; 108894220b39SElena Agostini return -rte_errno; 108994220b39SElena Agostini } 10901306a73bSElena Agostini 10911306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 10921306a73bSElena Agostini 10931306a73bSElena Agostini if (private->gdr_write_ordering != CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) { 10941306a73bSElena Agostini /* 10951306a73bSElena Agostini * No need to explicitly force the write ordering because 10961306a73bSElena Agostini * the device natively supports it 10971306a73bSElena Agostini */ 10981306a73bSElena Agostini return 0; 10991306a73bSElena Agostini } 11001306a73bSElena Agostini 11011306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) { 11021306a73bSElena Agostini /* 11031306a73bSElena Agostini * Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function. 11041306a73bSElena Agostini * Application needs to use alternative methods. 11051306a73bSElena Agostini */ 11061306a73bSElena Agostini rte_cuda_log(WARNING, "Can't flush GDR writes with cuFlushGPUDirectRDMAWrites CUDA function." 11071306a73bSElena Agostini "Application needs to use alternative methods."); 110894220b39SElena Agostini 110994220b39SElena Agostini rte_errno = ENOTSUP; 111094220b39SElena Agostini return -rte_errno; 11111306a73bSElena Agostini } 11121306a73bSElena Agostini 11131306a73bSElena Agostini /* Store current ctx */ 11141306a73bSElena Agostini res = pfn_cuCtxGetCurrent(¤t_ctx); 11151306a73bSElena Agostini if (res != 0) { 11161306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11171306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetCurrent failed with %s", 11181306a73bSElena Agostini err_string); 111994220b39SElena Agostini rte_errno = EPERM; 112094220b39SElena Agostini return -rte_errno; 11211306a73bSElena Agostini } 11221306a73bSElena Agostini 11231306a73bSElena Agostini /* Set child ctx as current ctx */ 11241306a73bSElena Agostini input_ctx = (CUcontext)((uintptr_t)dev->mpshared->info.context); 11251306a73bSElena Agostini res = pfn_cuCtxSetCurrent(input_ctx); 11261306a73bSElena Agostini if (res != 0) { 11271306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11281306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent input failed with %s", 11291306a73bSElena Agostini err_string); 113094220b39SElena Agostini rte_errno = EPERM; 113194220b39SElena Agostini return -rte_errno; 11321306a73bSElena Agostini } 11331306a73bSElena Agostini 11341306a73bSElena Agostini res = pfn_cuFlushGPUDirectRDMAWrites(CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TARGET_CURRENT_CTX, 11351306a73bSElena Agostini CU_FLUSH_GPU_DIRECT_RDMA_WRITES_TO_ALL_DEVICES); 11361306a73bSElena Agostini if (res != 0) { 11371306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11381306a73bSElena Agostini rte_cuda_log(ERR, "cuFlushGPUDirectRDMAWrites current failed with %s", 11391306a73bSElena Agostini err_string); 114094220b39SElena Agostini rte_errno = EPERM; 114194220b39SElena Agostini return -rte_errno; 11421306a73bSElena Agostini } 11431306a73bSElena Agostini 11441306a73bSElena Agostini /* Restore original ctx as current ctx */ 11451306a73bSElena Agostini res = pfn_cuCtxSetCurrent(current_ctx); 11461306a73bSElena Agostini if (res != 0) { 11471306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 11481306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxSetCurrent current failed with %s", 11491306a73bSElena Agostini err_string); 115094220b39SElena Agostini rte_errno = EPERM; 115194220b39SElena Agostini return -rte_errno; 11521306a73bSElena Agostini } 11531306a73bSElena Agostini 11541306a73bSElena Agostini return 0; 11551306a73bSElena Agostini } 11561306a73bSElena Agostini 11571306a73bSElena Agostini static int 11581306a73bSElena Agostini cuda_gpu_probe(__rte_unused struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 11591306a73bSElena Agostini { 11601306a73bSElena Agostini struct rte_gpu *dev = NULL; 11611306a73bSElena Agostini CUresult res; 11621306a73bSElena Agostini CUdevice cu_dev_id; 11631306a73bSElena Agostini CUcontext pctx; 11641306a73bSElena Agostini char dev_name[RTE_DEV_NAME_MAX_LEN]; 11651306a73bSElena Agostini const char *err_string; 11661306a73bSElena Agostini int processor_count = 0; 11671306a73bSElena Agostini struct cuda_info *private; 11681306a73bSElena Agostini 11691306a73bSElena Agostini if (pci_dev == NULL) { 11701306a73bSElena Agostini rte_cuda_log(ERR, "NULL PCI device"); 117194220b39SElena Agostini rte_errno = ENODEV; 117294220b39SElena Agostini return -rte_errno; 11731306a73bSElena Agostini } 11741306a73bSElena Agostini 11751306a73bSElena Agostini rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name)); 11761306a73bSElena Agostini 11771306a73bSElena Agostini /* Allocate memory to be used privately by drivers */ 11781306a73bSElena Agostini dev = rte_gpu_allocate(pci_dev->device.name); 117994220b39SElena Agostini if (dev == NULL) { 118094220b39SElena Agostini rte_errno = ENODEV; 118194220b39SElena Agostini return -rte_errno; 118294220b39SElena Agostini } 11831306a73bSElena Agostini 11841306a73bSElena Agostini /* Initialize values only for the first CUDA driver call */ 11851306a73bSElena Agostini if (dev->mpshared->info.dev_id == 0) { 11861306a73bSElena Agostini mem_alloc_list_head = NULL; 11871306a73bSElena Agostini mem_alloc_list_tail = NULL; 11881306a73bSElena Agostini mem_alloc_list_last_elem = 0; 11891306a73bSElena Agostini 11901306a73bSElena Agostini /* Load libcuda.so library */ 11911306a73bSElena Agostini if (cuda_loader()) { 11921306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver library not found"); 119394220b39SElena Agostini rte_errno = ENOTSUP; 119494220b39SElena Agostini return -rte_errno; 11951306a73bSElena Agostini } 11961306a73bSElena Agostini 11971306a73bSElena Agostini /* Load initial CUDA functions */ 11981306a73bSElena Agostini if (cuda_sym_func_loader()) { 11991306a73bSElena Agostini rte_cuda_log(ERR, "CUDA functions not found in library"); 120094220b39SElena Agostini rte_errno = ENOTSUP; 120194220b39SElena Agostini return -rte_errno; 12021306a73bSElena Agostini } 12031306a73bSElena Agostini 12041306a73bSElena Agostini /* 12051306a73bSElena Agostini * Required to initialize the CUDA Driver. 12061306a73bSElena Agostini * Multiple calls of cuInit() will return immediately 12071306a73bSElena Agostini * without making any relevant change 12081306a73bSElena Agostini */ 12091306a73bSElena Agostini sym_cuInit(0); 12101306a73bSElena Agostini 12111306a73bSElena Agostini res = sym_cuDriverGetVersion(&cuda_driver_version); 12121306a73bSElena Agostini if (res != 0) { 12131306a73bSElena Agostini rte_cuda_log(ERR, "cuDriverGetVersion failed with %d", res); 121494220b39SElena Agostini rte_errno = ENOTSUP; 121594220b39SElena Agostini return -rte_errno; 12161306a73bSElena Agostini } 12171306a73bSElena Agostini 12181306a73bSElena Agostini if (cuda_driver_version < CUDA_DRIVER_MIN_VERSION) { 12191306a73bSElena Agostini rte_cuda_log(ERR, "CUDA Driver version found is %d. " 12201306a73bSElena Agostini "Minimum requirement is %d", 12211306a73bSElena Agostini cuda_driver_version, 12221306a73bSElena Agostini CUDA_DRIVER_MIN_VERSION); 122394220b39SElena Agostini rte_errno = ENOTSUP; 122494220b39SElena Agostini return -rte_errno; 12251306a73bSElena Agostini } 12261306a73bSElena Agostini 12271306a73bSElena Agostini if (cuda_pfn_func_loader()) { 12281306a73bSElena Agostini rte_cuda_log(ERR, "CUDA PFN functions not found in library"); 122994220b39SElena Agostini rte_errno = ENOTSUP; 123094220b39SElena Agostini return -rte_errno; 12311306a73bSElena Agostini } 123224c77594SElena Agostini 123324c77594SElena Agostini gdrc_h = NULL; 12341306a73bSElena Agostini } 12351306a73bSElena Agostini 12361306a73bSElena Agostini /* Fill HW specific part of device structure */ 12371306a73bSElena Agostini dev->device = &pci_dev->device; 12381306a73bSElena Agostini dev->mpshared->info.numa_node = pci_dev->device.numa_node; 12391306a73bSElena Agostini 12401306a73bSElena Agostini /* Get NVIDIA GPU Device descriptor */ 12411306a73bSElena Agostini res = pfn_cuDeviceGetByPCIBusId(&cu_dev_id, dev->device->name); 12421306a73bSElena Agostini if (res != 0) { 12431306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12441306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetByPCIBusId name %s failed with %d: %s", 12451306a73bSElena Agostini dev->device->name, res, err_string); 124694220b39SElena Agostini rte_errno = EPERM; 124794220b39SElena Agostini return -rte_errno; 12481306a73bSElena Agostini } 12491306a73bSElena Agostini 12501306a73bSElena Agostini res = pfn_cuDevicePrimaryCtxRetain(&pctx, cu_dev_id); 12511306a73bSElena Agostini if (res != 0) { 12521306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12531306a73bSElena Agostini rte_cuda_log(ERR, "cuDevicePrimaryCtxRetain name %s failed with %d: %s", 12541306a73bSElena Agostini dev->device->name, res, err_string); 125594220b39SElena Agostini rte_errno = EPERM; 125694220b39SElena Agostini return -rte_errno; 12571306a73bSElena Agostini } 12581306a73bSElena Agostini 12591306a73bSElena Agostini res = pfn_cuCtxGetApiVersion(pctx, &cuda_api_version); 12601306a73bSElena Agostini if (res != 0) { 12611306a73bSElena Agostini rte_cuda_log(ERR, "cuCtxGetApiVersion failed with %d", res); 126294220b39SElena Agostini rte_errno = ENOTSUP; 126394220b39SElena Agostini return -rte_errno; 12641306a73bSElena Agostini } 12651306a73bSElena Agostini 12661306a73bSElena Agostini if (cuda_api_version < CUDA_API_MIN_VERSION) { 12671306a73bSElena Agostini rte_cuda_log(ERR, "CUDA API version found is %d Minimum requirement is %d", 12681306a73bSElena Agostini cuda_api_version, CUDA_API_MIN_VERSION); 126994220b39SElena Agostini rte_errno = ENOTSUP; 127094220b39SElena Agostini return -rte_errno; 12711306a73bSElena Agostini } 12721306a73bSElena Agostini 12731306a73bSElena Agostini dev->mpshared->info.context = (uint64_t)pctx; 12741306a73bSElena Agostini 12751306a73bSElena Agostini /* 12761306a73bSElena Agostini * GPU Device generic info 12771306a73bSElena Agostini */ 12781306a73bSElena Agostini 12791306a73bSElena Agostini /* Processor count */ 12801306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(processor_count), 12811306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_MULTIPROCESSOR_COUNT, 12821306a73bSElena Agostini cu_dev_id); 12831306a73bSElena Agostini if (res != 0) { 12841306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12851306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 12861306a73bSElena Agostini err_string); 128794220b39SElena Agostini rte_errno = EPERM; 128894220b39SElena Agostini return -rte_errno; 12891306a73bSElena Agostini } 12901306a73bSElena Agostini dev->mpshared->info.processor_count = (uint32_t)processor_count; 12911306a73bSElena Agostini 12921306a73bSElena Agostini /* Total memory */ 12931306a73bSElena Agostini res = pfn_cuDeviceTotalMem(&dev->mpshared->info.total_memory, cu_dev_id); 12941306a73bSElena Agostini if (res != 0) { 12951306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 12961306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceTotalMem failed with %s", 12971306a73bSElena Agostini err_string); 129894220b39SElena Agostini rte_errno = EPERM; 129994220b39SElena Agostini return -rte_errno; 13001306a73bSElena Agostini } 13011306a73bSElena Agostini 13021fd3de64SElena Agostini dev->mpshared->info.page_size = (size_t)GPU_PAGE_SIZE; 13031fd3de64SElena Agostini 13041306a73bSElena Agostini /* 13051306a73bSElena Agostini * GPU Device private info 13061306a73bSElena Agostini */ 13071306a73bSElena Agostini dev->mpshared->dev_private = rte_zmalloc(NULL, 13081306a73bSElena Agostini sizeof(struct cuda_info), 13091306a73bSElena Agostini RTE_CACHE_LINE_SIZE); 13101306a73bSElena Agostini if (dev->mpshared->dev_private == NULL) { 13111306a73bSElena Agostini rte_cuda_log(ERR, "Failed to allocate memory for GPU process private"); 131294220b39SElena Agostini rte_errno = EPERM; 131394220b39SElena Agostini return -rte_errno; 13141306a73bSElena Agostini } 13151306a73bSElena Agostini 13161306a73bSElena Agostini private = (struct cuda_info *)dev->mpshared->dev_private; 13171306a73bSElena Agostini private->cu_dev = cu_dev_id; 13181306a73bSElena Agostini res = pfn_cuDeviceGetName(private->gpu_name, 13191306a73bSElena Agostini RTE_DEV_NAME_MAX_LEN, 13201306a73bSElena Agostini cu_dev_id); 13211306a73bSElena Agostini if (res != 0) { 13221306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 13231306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetName failed with %s", 13241306a73bSElena Agostini err_string); 132594220b39SElena Agostini rte_errno = EPERM; 132694220b39SElena Agostini return -rte_errno; 13271306a73bSElena Agostini } 13281306a73bSElena Agostini 13291306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_supported), 13301306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_SUPPORTED, 13311306a73bSElena Agostini cu_dev_id); 13321306a73bSElena Agostini if (res != 0) { 13331306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 13341306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 13351306a73bSElena Agostini err_string); 133694220b39SElena Agostini rte_errno = EPERM; 133794220b39SElena Agostini return -rte_errno; 13381306a73bSElena Agostini } 13391306a73bSElena Agostini 13401306a73bSElena Agostini if (private->gdr_supported == 0) 13411306a73bSElena Agostini rte_cuda_log(WARNING, "GPU %s doesn't support GPUDirect RDMA", 13421306a73bSElena Agostini pci_dev->device.name); 13431306a73bSElena Agostini 13441306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_write_ordering), 13451306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_WRITES_ORDERING, 13461306a73bSElena Agostini cu_dev_id); 13471306a73bSElena Agostini if (res != 0) { 13481306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 13491306a73bSElena Agostini rte_cuda_log(ERR, 13501306a73bSElena Agostini "cuDeviceGetAttribute failed with %s", 13511306a73bSElena Agostini err_string); 135294220b39SElena Agostini rte_errno = EPERM; 135394220b39SElena Agostini return -rte_errno; 13541306a73bSElena Agostini } 13551306a73bSElena Agostini 13561306a73bSElena Agostini if (private->gdr_write_ordering == CU_GPU_DIRECT_RDMA_WRITES_ORDERING_NONE) { 13571306a73bSElena Agostini res = pfn_cuDeviceGetAttribute(&(private->gdr_flush_type), 13581306a73bSElena Agostini CU_DEVICE_ATTRIBUTE_GPU_DIRECT_RDMA_FLUSH_WRITES_OPTIONS, 13591306a73bSElena Agostini cu_dev_id); 13601306a73bSElena Agostini if (res != 0) { 13611306a73bSElena Agostini pfn_cuGetErrorString(res, &(err_string)); 13621306a73bSElena Agostini rte_cuda_log(ERR, "cuDeviceGetAttribute failed with %s", 13631306a73bSElena Agostini err_string); 136494220b39SElena Agostini rte_errno = EPERM; 136594220b39SElena Agostini return -rte_errno; 13661306a73bSElena Agostini } 13671306a73bSElena Agostini 13681306a73bSElena Agostini if (private->gdr_flush_type != CU_FLUSH_GPU_DIRECT_RDMA_WRITES_OPTION_HOST) 13691306a73bSElena Agostini rte_cuda_log(ERR, "GPUDirect RDMA flush writes API is not supported"); 13701306a73bSElena Agostini } 13711306a73bSElena Agostini 13721306a73bSElena Agostini dev->ops.dev_info_get = cuda_dev_info_get; 13731306a73bSElena Agostini dev->ops.dev_close = cuda_dev_close; 13741306a73bSElena Agostini dev->ops.mem_alloc = cuda_mem_alloc; 13751306a73bSElena Agostini dev->ops.mem_free = cuda_mem_free; 13761306a73bSElena Agostini dev->ops.mem_register = cuda_mem_register; 13771306a73bSElena Agostini dev->ops.mem_unregister = cuda_mem_unregister; 137824c77594SElena Agostini dev->ops.mem_cpu_map = cuda_mem_cpu_map; 137924c77594SElena Agostini dev->ops.mem_cpu_unmap = cuda_mem_cpu_unmap; 13801306a73bSElena Agostini dev->ops.wmb = cuda_wmb; 13811306a73bSElena Agostini 13821306a73bSElena Agostini rte_gpu_complete_new(dev); 13831306a73bSElena Agostini 13841306a73bSElena Agostini rte_cuda_debug("dev id = %u name = %s", 13851306a73bSElena Agostini dev->mpshared->info.dev_id, private->gpu_name); 13861306a73bSElena Agostini 13871306a73bSElena Agostini return 0; 13881306a73bSElena Agostini } 13891306a73bSElena Agostini 13901306a73bSElena Agostini static int 13911306a73bSElena Agostini cuda_gpu_remove(struct rte_pci_device *pci_dev) 13921306a73bSElena Agostini { 13931306a73bSElena Agostini struct rte_gpu *dev; 13941306a73bSElena Agostini int ret; 13951306a73bSElena Agostini uint8_t gpu_id; 13961306a73bSElena Agostini 139794220b39SElena Agostini if (pci_dev == NULL) { 139894220b39SElena Agostini rte_errno = ENODEV; 139994220b39SElena Agostini return -rte_errno; 140094220b39SElena Agostini } 14011306a73bSElena Agostini 14021306a73bSElena Agostini dev = rte_gpu_get_by_name(pci_dev->device.name); 14031306a73bSElena Agostini if (dev == NULL) { 14041306a73bSElena Agostini rte_cuda_log(ERR, "Couldn't find HW dev \"%s\" to uninitialise it", 14051306a73bSElena Agostini pci_dev->device.name); 140694220b39SElena Agostini rte_errno = ENODEV; 140794220b39SElena Agostini return -rte_errno; 14081306a73bSElena Agostini } 14091306a73bSElena Agostini gpu_id = dev->mpshared->info.dev_id; 14101306a73bSElena Agostini 14111306a73bSElena Agostini /* release dev from library */ 14121306a73bSElena Agostini ret = rte_gpu_release(dev); 14131306a73bSElena Agostini if (ret) 14141306a73bSElena Agostini rte_cuda_log(ERR, "Device %i failed to uninit: %i", gpu_id, ret); 14151306a73bSElena Agostini 14161306a73bSElena Agostini rte_cuda_debug("Destroyed dev = %u", gpu_id); 14171306a73bSElena Agostini 14181306a73bSElena Agostini return 0; 14191306a73bSElena Agostini } 14201306a73bSElena Agostini 14211306a73bSElena Agostini static struct rte_pci_driver rte_cuda_driver = { 14221306a73bSElena Agostini .id_table = pci_id_cuda_map, 14231306a73bSElena Agostini .drv_flags = RTE_PCI_DRV_WC_ACTIVATE, 14241306a73bSElena Agostini .probe = cuda_gpu_probe, 14251306a73bSElena Agostini .remove = cuda_gpu_remove, 14261306a73bSElena Agostini }; 14271306a73bSElena Agostini 14281306a73bSElena Agostini RTE_PMD_REGISTER_PCI(gpu_cuda, rte_cuda_driver); 14291306a73bSElena Agostini RTE_PMD_REGISTER_PCI_TABLE(gpu_cuda, pci_id_cuda_map); 14301306a73bSElena Agostini RTE_PMD_REGISTER_KMOD_DEP(gpu_cuda, "* nvidia & (nv_peer_mem | nvpeer_mem)"); 1431