Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2016 Intel Corporation.
3 : * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES.
4 : * All rights reserved.
5 : */
6 :
7 : #include "spdk/stdinc.h"
8 : #include "spdk/util.h"
9 : #include "spdk/env_dpdk.h"
10 : #include "spdk/log.h"
11 : #include "spdk/assert.h"
12 :
13 : #include "env_internal.h"
14 :
15 : #include <rte_config.h>
16 : #include <rte_cycles.h>
17 : #include <rte_malloc.h>
18 : #include <rte_mempool.h>
19 : #include <rte_memzone.h>
20 : #include <rte_version.h>
21 : #include <rte_eal.h>
22 :
23 : static __thread bool g_is_thread_unaffinitized;
24 : static bool g_enforce_numa;
25 :
26 : SPDK_STATIC_ASSERT(SOCKET_ID_ANY == SPDK_ENV_NUMA_ID_ANY, "SOCKET_ID_ANY mismatch");
27 :
28 : void *
29 0 : spdk_malloc(size_t size, size_t align, uint64_t *unused, int numa_id, uint32_t flags)
30 : {
31 : void *buf;
32 :
33 0 : if (flags == 0 || unused != NULL) {
34 0 : return NULL;
35 : }
36 :
37 0 : align = spdk_max(align, RTE_CACHE_LINE_SIZE);
38 0 : buf = rte_malloc_socket(NULL, size, align, numa_id);
39 0 : if (buf == NULL && !g_enforce_numa && numa_id != SOCKET_ID_ANY) {
40 0 : buf = rte_malloc_socket(NULL, size, align, SOCKET_ID_ANY);
41 0 : }
42 0 : return buf;
43 0 : }
44 :
45 : void *
46 0 : spdk_zmalloc(size_t size, size_t align, uint64_t *unused, int numa_id, uint32_t flags)
47 : {
48 : void *buf;
49 :
50 0 : if (flags == 0 || unused != NULL) {
51 0 : return NULL;
52 : }
53 :
54 0 : align = spdk_max(align, RTE_CACHE_LINE_SIZE);
55 0 : buf = rte_zmalloc_socket(NULL, size, align, numa_id);
56 0 : if (buf == NULL && !g_enforce_numa && numa_id != SOCKET_ID_ANY) {
57 0 : buf = rte_zmalloc_socket(NULL, size, align, SOCKET_ID_ANY);
58 0 : }
59 0 : return buf;
60 0 : }
61 :
62 : void *
63 0 : spdk_realloc(void *buf, size_t size, size_t align)
64 : {
65 0 : align = spdk_max(align, RTE_CACHE_LINE_SIZE);
66 0 : return rte_realloc(buf, size, align);
67 : }
68 :
69 : void
70 0 : spdk_free(void *buf)
71 : {
72 0 : rte_free(buf);
73 0 : }
74 :
75 : void *
76 0 : spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *unused, int numa_id)
77 : {
78 0 : return spdk_malloc(size, align, unused, numa_id, (SPDK_MALLOC_DMA | SPDK_MALLOC_SHARE));
79 : }
80 :
81 : void *
82 0 : spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *unused, int numa_id)
83 : {
84 0 : return spdk_zmalloc(size, align, unused, numa_id, (SPDK_MALLOC_DMA | SPDK_MALLOC_SHARE));
85 : }
86 :
87 : void *
88 0 : spdk_dma_malloc(size_t size, size_t align, uint64_t *unused)
89 : {
90 0 : return spdk_dma_malloc_socket(size, align, unused, SPDK_ENV_NUMA_ID_ANY);
91 : }
92 :
93 : void *
94 0 : spdk_dma_zmalloc(size_t size, size_t align, uint64_t *unused)
95 : {
96 0 : return spdk_dma_zmalloc_socket(size, align, unused, SPDK_ENV_NUMA_ID_ANY);
97 : }
98 :
99 : void *
100 0 : spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *unused)
101 : {
102 0 : if (unused != NULL) {
103 0 : return NULL;
104 : }
105 0 : align = spdk_max(align, RTE_CACHE_LINE_SIZE);
106 0 : return rte_realloc(buf, size, align);
107 0 : }
108 :
109 : void
110 0 : spdk_dma_free(void *buf)
111 : {
112 0 : spdk_free(buf);
113 0 : }
114 :
115 : void *
116 0 : spdk_memzone_reserve_aligned(const char *name, size_t len, int numa_id,
117 : unsigned flags, unsigned align)
118 : {
119 : const struct rte_memzone *mz;
120 0 : unsigned dpdk_flags = 0;
121 :
122 0 : if ((flags & SPDK_MEMZONE_NO_IOVA_CONTIG) == 0) {
123 0 : dpdk_flags |= RTE_MEMZONE_IOVA_CONTIG;
124 0 : }
125 :
126 0 : if (numa_id == SPDK_ENV_NUMA_ID_ANY) {
127 0 : numa_id = SOCKET_ID_ANY;
128 0 : }
129 :
130 0 : mz = rte_memzone_reserve_aligned(name, len, numa_id, dpdk_flags, align);
131 0 : if (mz == NULL && !g_enforce_numa && numa_id != SOCKET_ID_ANY) {
132 0 : mz = rte_memzone_reserve_aligned(name, len, SOCKET_ID_ANY, dpdk_flags, align);
133 0 : }
134 :
135 0 : if (mz != NULL) {
136 0 : memset(mz->addr, 0, len);
137 0 : return mz->addr;
138 : } else {
139 0 : return NULL;
140 : }
141 0 : }
142 :
143 : void *
144 0 : spdk_memzone_reserve(const char *name, size_t len, int numa_id, unsigned flags)
145 : {
146 0 : return spdk_memzone_reserve_aligned(name, len, numa_id, flags,
147 : RTE_CACHE_LINE_SIZE);
148 : }
149 :
150 : void *
151 0 : spdk_memzone_lookup(const char *name)
152 : {
153 0 : const struct rte_memzone *mz = rte_memzone_lookup(name);
154 :
155 0 : if (mz != NULL) {
156 0 : return mz->addr;
157 : } else {
158 0 : return NULL;
159 : }
160 0 : }
161 :
162 : int
163 0 : spdk_memzone_free(const char *name)
164 : {
165 0 : const struct rte_memzone *mz = rte_memzone_lookup(name);
166 :
167 0 : if (mz != NULL) {
168 0 : return rte_memzone_free(mz);
169 : }
170 :
171 0 : return -1;
172 0 : }
173 :
174 : void
175 0 : spdk_memzone_dump(FILE *f)
176 : {
177 0 : rte_memzone_dump(f);
178 0 : }
179 :
180 : struct spdk_mempool *
181 0 : spdk_mempool_create_ctor(const char *name, size_t count,
182 : size_t ele_size, size_t cache_size, int numa_id,
183 : spdk_mempool_obj_cb_t *obj_init, void *obj_init_arg)
184 : {
185 : struct rte_mempool *mp;
186 : size_t tmp;
187 :
188 0 : if (numa_id == SPDK_ENV_NUMA_ID_ANY) {
189 0 : numa_id = SOCKET_ID_ANY;
190 0 : }
191 :
192 : /* No more than half of all elements can be in cache */
193 0 : tmp = (count / 2) / rte_lcore_count();
194 0 : if (cache_size > tmp) {
195 0 : cache_size = tmp;
196 0 : }
197 :
198 0 : if (cache_size > RTE_MEMPOOL_CACHE_MAX_SIZE) {
199 0 : cache_size = RTE_MEMPOOL_CACHE_MAX_SIZE;
200 0 : }
201 :
202 0 : mp = rte_mempool_create(name, count, ele_size, cache_size,
203 0 : 0, NULL, NULL, (rte_mempool_obj_cb_t *)obj_init, obj_init_arg,
204 0 : numa_id, 0);
205 0 : if (mp == NULL && !g_enforce_numa && numa_id != SOCKET_ID_ANY) {
206 0 : mp = rte_mempool_create(name, count, ele_size, cache_size,
207 0 : 0, NULL, NULL, (rte_mempool_obj_cb_t *)obj_init, obj_init_arg,
208 : SOCKET_ID_ANY, 0);
209 0 : }
210 :
211 0 : return (struct spdk_mempool *)mp;
212 : }
213 :
214 :
215 : struct spdk_mempool *
216 0 : spdk_mempool_create(const char *name, size_t count,
217 : size_t ele_size, size_t cache_size, int numa_id)
218 : {
219 0 : return spdk_mempool_create_ctor(name, count, ele_size, cache_size, numa_id,
220 : NULL, NULL);
221 : }
222 :
223 : char *
224 0 : spdk_mempool_get_name(struct spdk_mempool *mp)
225 : {
226 0 : return ((struct rte_mempool *)mp)->name;
227 : }
228 :
229 : void
230 0 : spdk_mempool_free(struct spdk_mempool *mp)
231 : {
232 0 : rte_mempool_free((struct rte_mempool *)mp);
233 0 : }
234 :
235 : void *
236 0 : spdk_mempool_get(struct spdk_mempool *mp)
237 : {
238 0 : void *ele = NULL;
239 : int rc;
240 :
241 0 : rc = rte_mempool_get((struct rte_mempool *)mp, &ele);
242 0 : if (rc != 0) {
243 0 : return NULL;
244 : }
245 0 : return ele;
246 0 : }
247 :
248 : int
249 0 : spdk_mempool_get_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
250 : {
251 0 : return rte_mempool_get_bulk((struct rte_mempool *)mp, ele_arr, count);
252 : }
253 :
254 : void
255 0 : spdk_mempool_put(struct spdk_mempool *mp, void *ele)
256 : {
257 0 : rte_mempool_put((struct rte_mempool *)mp, ele);
258 0 : }
259 :
260 : void
261 0 : spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
262 : {
263 0 : rte_mempool_put_bulk((struct rte_mempool *)mp, ele_arr, count);
264 0 : }
265 :
266 : size_t
267 0 : spdk_mempool_count(const struct spdk_mempool *pool)
268 : {
269 0 : return rte_mempool_avail_count((struct rte_mempool *)pool);
270 : }
271 :
272 : uint32_t
273 0 : spdk_mempool_obj_iter(struct spdk_mempool *mp, spdk_mempool_obj_cb_t obj_cb,
274 : void *obj_cb_arg)
275 : {
276 0 : return rte_mempool_obj_iter((struct rte_mempool *)mp, (rte_mempool_obj_cb_t *)obj_cb,
277 0 : obj_cb_arg);
278 : }
279 :
280 : struct env_mempool_mem_iter_ctx {
281 : spdk_mempool_mem_cb_t *user_cb;
282 : void *user_arg;
283 : };
284 :
285 : static void
286 0 : mempool_mem_iter_remap(struct rte_mempool *mp, void *opaque, struct rte_mempool_memhdr *memhdr,
287 : unsigned mem_idx)
288 : {
289 0 : struct env_mempool_mem_iter_ctx *ctx = opaque;
290 :
291 0 : ctx->user_cb((struct spdk_mempool *)mp, ctx->user_arg, memhdr->addr, memhdr->iova, memhdr->len,
292 0 : mem_idx);
293 0 : }
294 :
295 : uint32_t
296 0 : spdk_mempool_mem_iter(struct spdk_mempool *mp, spdk_mempool_mem_cb_t mem_cb,
297 : void *mem_cb_arg)
298 : {
299 0 : struct env_mempool_mem_iter_ctx ctx = {
300 0 : .user_cb = mem_cb,
301 0 : .user_arg = mem_cb_arg
302 : };
303 :
304 0 : return rte_mempool_mem_iter((struct rte_mempool *)mp, mempool_mem_iter_remap, &ctx);
305 : }
306 :
307 : struct spdk_mempool *
308 0 : spdk_mempool_lookup(const char *name)
309 : {
310 0 : return (struct spdk_mempool *)rte_mempool_lookup(name);
311 : }
312 :
313 : bool
314 0 : spdk_process_is_primary(void)
315 : {
316 0 : return (rte_eal_process_type() == RTE_PROC_PRIMARY);
317 : }
318 :
319 : uint64_t
320 0 : spdk_get_ticks(void)
321 : {
322 0 : return rte_get_timer_cycles();
323 : }
324 :
325 : uint64_t
326 0 : spdk_get_ticks_hz(void)
327 : {
328 0 : return rte_get_timer_hz();
329 : }
330 :
331 : void
332 0 : spdk_delay_us(unsigned int us)
333 : {
334 0 : rte_delay_us(us);
335 0 : }
336 :
337 : void
338 0 : spdk_pause(void)
339 : {
340 0 : rte_pause();
341 0 : }
342 :
343 : void
344 0 : spdk_unaffinitize_thread(void)
345 : {
346 : rte_cpuset_t new_cpuset;
347 : long num_cores, i;
348 :
349 0 : if (g_is_thread_unaffinitized) {
350 0 : return;
351 : }
352 :
353 0 : CPU_ZERO(&new_cpuset);
354 :
355 0 : num_cores = sysconf(_SC_NPROCESSORS_CONF);
356 :
357 : /* Create a mask containing all CPUs */
358 0 : for (i = 0; i < num_cores; i++) {
359 0 : CPU_SET(i, &new_cpuset);
360 0 : }
361 :
362 0 : rte_thread_set_affinity(&new_cpuset);
363 0 : g_is_thread_unaffinitized = true;
364 0 : }
365 :
366 : void *
367 0 : spdk_call_unaffinitized(void *cb(void *arg), void *arg)
368 : {
369 : rte_cpuset_t orig_cpuset;
370 : void *ret;
371 :
372 0 : if (cb == NULL) {
373 0 : return NULL;
374 : }
375 :
376 0 : if (g_is_thread_unaffinitized) {
377 0 : ret = cb(arg);
378 0 : } else {
379 0 : rte_thread_get_affinity(&orig_cpuset);
380 0 : spdk_unaffinitize_thread();
381 :
382 0 : ret = cb(arg);
383 :
384 0 : rte_thread_set_affinity(&orig_cpuset);
385 0 : g_is_thread_unaffinitized = false;
386 : }
387 :
388 0 : return ret;
389 0 : }
390 :
391 : struct spdk_ring *
392 0 : spdk_ring_create(enum spdk_ring_type type, size_t count, int numa_id)
393 : {
394 : char ring_name[64];
395 : static uint32_t ring_num = 0;
396 0 : unsigned flags = RING_F_EXACT_SZ;
397 : struct rte_ring *ring;
398 :
399 0 : switch (type) {
400 : case SPDK_RING_TYPE_SP_SC:
401 0 : flags |= RING_F_SP_ENQ | RING_F_SC_DEQ;
402 0 : break;
403 : case SPDK_RING_TYPE_MP_SC:
404 0 : flags |= RING_F_SC_DEQ;
405 0 : break;
406 : case SPDK_RING_TYPE_MP_MC:
407 0 : flags |= 0;
408 0 : break;
409 : default:
410 0 : return NULL;
411 : }
412 :
413 0 : snprintf(ring_name, sizeof(ring_name), "ring_%u_%d",
414 0 : __atomic_fetch_add(&ring_num, 1, __ATOMIC_RELAXED), getpid());
415 :
416 0 : ring = rte_ring_create(ring_name, count, numa_id, flags);
417 0 : if (ring == NULL && !g_enforce_numa && numa_id != SOCKET_ID_ANY) {
418 0 : ring = rte_ring_create(ring_name, count, SOCKET_ID_ANY, flags);
419 0 : }
420 0 : return (struct spdk_ring *)ring;
421 0 : }
422 :
423 : void
424 0 : spdk_ring_free(struct spdk_ring *ring)
425 : {
426 0 : rte_ring_free((struct rte_ring *)ring);
427 0 : }
428 :
429 : size_t
430 0 : spdk_ring_count(struct spdk_ring *ring)
431 : {
432 0 : return rte_ring_count((struct rte_ring *)ring);
433 : }
434 :
435 : size_t
436 0 : spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count,
437 : size_t *free_space)
438 : {
439 0 : return rte_ring_enqueue_bulk((struct rte_ring *)ring, objs, count,
440 0 : (unsigned int *)free_space);
441 : }
442 :
443 : size_t
444 0 : spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count)
445 : {
446 0 : return rte_ring_dequeue_burst((struct rte_ring *)ring, objs, count, NULL);
447 : }
448 :
449 : void
450 0 : spdk_env_dpdk_dump_mem_stats(FILE *file)
451 : {
452 0 : fprintf(file, "DPDK memory size %" PRIu64 "\n", rte_eal_get_physmem_size());
453 0 : fprintf(file, "DPDK memory layout\n");
454 0 : rte_dump_physmem_layout(file);
455 0 : fprintf(file, "DPDK memzones.\n");
456 0 : rte_memzone_dump(file);
457 0 : fprintf(file, "DPDK mempools.\n");
458 0 : rte_mempool_list_dump(file);
459 0 : fprintf(file, "DPDK malloc stats.\n");
460 0 : rte_malloc_dump_stats(file, NULL);
461 0 : fprintf(file, "DPDK malloc heaps.\n");
462 0 : rte_malloc_dump_heaps(file);
463 0 : }
464 :
465 : int
466 0 : spdk_get_tid(void)
467 : {
468 0 : return rte_sys_gettid();
469 : }
470 :
471 : void
472 0 : mem_enforce_numa(void)
473 : {
474 0 : g_enforce_numa = true;
475 0 : }
|