xref: /dpdk/drivers/gpu/cuda/gdrcopy.c (revision 592ab76f9f0f41993bebb44da85c37750a93ece9)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3  */
4 
5 #include "common.h"
6 
7 #ifdef DRIVERS_GPU_CUDA_GDRCOPY_H
8 
9 static void *gdrclib;
10 static gdr_t (*sym_gdr_open)(void);
11 static int (*sym_gdr_pin_buffer)(gdr_t g, unsigned long addr, size_t size,
12 		uint64_t p2p_token, uint32_t va_space, gdr_mh_t *handle);
13 static int (*sym_gdr_unpin_buffer)(gdr_t g, gdr_mh_t handle);
14 static int (*sym_gdr_map)(gdr_t g, gdr_mh_t handle, void **va, size_t size);
15 static int (*sym_gdr_unmap)(gdr_t g, gdr_mh_t handle, void *va, size_t size);
16 
17 static int
18 gdrcopy_loader(void)
19 {
20 	char gdrcopy_path[1024];
21 
22 	if (getenv("GDRCOPY_PATH_L") == NULL)
23 		snprintf(gdrcopy_path, 1024, "%s", "libgdrapi.so");
24 	else
25 		snprintf(gdrcopy_path, 1024, "%s/%s", getenv("GDRCOPY_PATH_L"), "libgdrapi.so");
26 
27 	gdrclib = dlopen(gdrcopy_path, RTLD_LAZY);
28 	if (gdrclib == NULL) {
29 		rte_cuda_log(ERR, "Failed to find GDRCopy library %s (GDRCOPY_PATH_L=%s)\n",
30 				gdrcopy_path, getenv("GDRCOPY_PATH_L"));
31 		return -1;
32 	}
33 
34 	sym_gdr_open = dlsym(gdrclib, "gdr_open");
35 	if (sym_gdr_open == NULL) {
36 		rte_cuda_log(ERR, "Failed to load GDRCopy symbols\n");
37 		return -1;
38 	}
39 
40 	sym_gdr_pin_buffer = dlsym(gdrclib, "gdr_pin_buffer");
41 	if (sym_gdr_pin_buffer == NULL) {
42 		rte_cuda_log(ERR, "Failed to load GDRCopy symbols\n");
43 		return -1;
44 	}
45 
46 	sym_gdr_unpin_buffer = dlsym(gdrclib, "gdr_unpin_buffer");
47 	if (sym_gdr_unpin_buffer == NULL) {
48 		rte_cuda_log(ERR, "Failed to load GDRCopy symbols\n");
49 		return -1;
50 	}
51 
52 	sym_gdr_map = dlsym(gdrclib, "gdr_map");
53 	if (sym_gdr_map == NULL) {
54 		rte_cuda_log(ERR, "Failed to load GDRCopy symbols\n");
55 		return -1;
56 	}
57 
58 	sym_gdr_unmap = dlsym(gdrclib, "gdr_unmap");
59 	if (sym_gdr_unmap == NULL) {
60 		rte_cuda_log(ERR, "Failed to load GDRCopy symbols\n");
61 		return -1;
62 	}
63 
64 	return 0;
65 }
66 
67 static int
68 gdrcopy_open(gdr_t *g)
69 {
70 	gdr_t g_;
71 
72 	g_ = sym_gdr_open();
73 	if (!g_)
74 		return -1;
75 	*g = g_;
76 
77 	return 0;
78 }
79 
80 #endif
81 
82 int
83 gdrcopy_pin(__rte_unused gdr_t *gdrc_h, __rte_unused gdr_mh_t *mh,
84 		__rte_unused uint64_t d_addr, __rte_unused size_t size,
85 		__rte_unused void **h_addr)
86 {
87 #ifdef DRIVERS_GPU_CUDA_GDRCOPY_H
88 	if (*gdrc_h == NULL) {
89 		if (gdrcopy_loader())
90 			return -ENOTSUP;
91 
92 		if (gdrcopy_open(gdrc_h)) {
93 			rte_cuda_log(ERR,
94 					"GDRCopy gdrdrv kernel module not found. Can't CPU map GPU memory.");
95 			return -EPERM;
96 		}
97 	}
98 
99 	/* Pin the device buffer */
100 	if (sym_gdr_pin_buffer(*gdrc_h, d_addr, size, 0, 0, mh) != 0) {
101 		rte_cuda_log(ERR, "GDRCopy pin buffer error.");
102 		return -1;
103 	}
104 
105 	/* Map the buffer to user space */
106 	if (sym_gdr_map(*gdrc_h, *mh, h_addr, size) != 0) {
107 		rte_cuda_log(ERR, "GDRCopy map buffer error.");
108 		sym_gdr_unpin_buffer(*gdrc_h, *mh);
109 		return -1;
110 	}
111 
112 	return 0;
113 #else
114 	rte_cuda_log(ERR,
115 			"GDRCopy headers not provided at DPDK building time. Can't CPU map GPU memory.");
116 	return -ENOTSUP;
117 #endif
118 }
119 
120 int
121 gdrcopy_unpin(gdr_t gdrc_h, __rte_unused gdr_mh_t mh,
122 		__rte_unused void *d_addr, __rte_unused size_t size)
123 {
124 	if (gdrc_h == NULL)
125 		return -EINVAL;
126 
127 #ifdef DRIVERS_GPU_CUDA_GDRCOPY_H
128 	/* Unmap the buffer from user space */
129 	if (sym_gdr_unmap(gdrc_h, mh, d_addr, size) != 0) {
130 		rte_cuda_log(ERR, "GDRCopy unmap buffer error.");
131 		return -1;
132 	}
133 	/* Unpin the device buffer */
134 	if (sym_gdr_unpin_buffer(gdrc_h, mh) != 0) {
135 		rte_cuda_log(ERR, "GDRCopy unpin buffer error.");
136 		return -1;
137 	}
138 #endif
139 
140 	return 0;
141 }
142