]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <stdio.h> | |
35 | #include <stdint.h> | |
36 | #include <inttypes.h> | |
37 | #include <sys/queue.h> | |
38 | ||
39 | #include <rte_random.h> | |
40 | #include <rte_cycles.h> | |
41 | #include <rte_memory.h> | |
42 | #include <rte_memzone.h> | |
43 | #include <rte_eal.h> | |
44 | #include <rte_eal_memconfig.h> | |
45 | #include <rte_common.h> | |
46 | #include <rte_string_fns.h> | |
47 | #include <rte_errno.h> | |
48 | #include <rte_malloc.h> | |
49 | #include "../../lib/librte_eal/common/malloc_elem.h" | |
50 | ||
51 | #include "test.h" | |
52 | ||
53 | /* | |
54 | * Memzone | |
55 | * ======= | |
56 | * | |
57 | * - Search for three reserved zones or reserve them if they do not exist: | |
58 | * | |
59 | * - One is on any socket id. | |
60 | * - The second is on socket 0. | |
61 | * - The last one is on socket 1 (if socket 1 exists). | |
62 | * | |
63 | * - Check that the zones exist. | |
64 | * | |
65 | * - Check that the zones are cache-aligned. | |
66 | * | |
67 | * - Check that zones do not overlap. | |
68 | * | |
69 | * - Check that the zones are on the correct socket id. | |
70 | * | |
71 | * - Check that a lookup of the first zone returns the same pointer. | |
72 | * | |
73 | * - Check that it is not possible to create another zone with the | |
74 | * same name as an existing zone. | |
75 | * | |
76 | * - Check flags for specific huge page size reservation | |
77 | */ | |
78 | ||
79 | /* Test if memory overlaps: return 1 if true, or 0 if false. */ | |
80 | static int | |
81 | is_memory_overlap(phys_addr_t ptr1, size_t len1, phys_addr_t ptr2, size_t len2) | |
82 | { | |
83 | if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1) | |
84 | return 1; | |
85 | else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2) | |
86 | return 1; | |
87 | return 0; | |
88 | } | |
89 | ||
90 | static int | |
91 | test_memzone_invalid_alignment(void) | |
92 | { | |
93 | const struct rte_memzone * mz; | |
94 | ||
95 | mz = rte_memzone_lookup("invalid_alignment"); | |
96 | if (mz != NULL) { | |
97 | printf("Zone with invalid alignment has been reserved\n"); | |
98 | return -1; | |
99 | } | |
100 | ||
101 | mz = rte_memzone_reserve_aligned("invalid_alignment", 100, | |
102 | SOCKET_ID_ANY, 0, 100); | |
103 | if (mz != NULL) { | |
104 | printf("Zone with invalid alignment has been reserved\n"); | |
105 | return -1; | |
106 | } | |
107 | return 0; | |
108 | } | |
109 | ||
110 | static int | |
111 | test_memzone_reserving_zone_size_bigger_than_the_maximum(void) | |
112 | { | |
113 | const struct rte_memzone * mz; | |
114 | ||
115 | mz = rte_memzone_lookup("zone_size_bigger_than_the_maximum"); | |
116 | if (mz != NULL) { | |
117 | printf("zone_size_bigger_than_the_maximum has been reserved\n"); | |
118 | return -1; | |
119 | } | |
120 | ||
121 | mz = rte_memzone_reserve("zone_size_bigger_than_the_maximum", (size_t)-1, | |
122 | SOCKET_ID_ANY, 0); | |
123 | if (mz != NULL) { | |
124 | printf("It is impossible to reserve such big a memzone\n"); | |
125 | return -1; | |
126 | } | |
127 | ||
128 | return 0; | |
129 | } | |
130 | ||
131 | static int | |
132 | test_memzone_reserve_flags(void) | |
133 | { | |
134 | const struct rte_memzone *mz; | |
135 | const struct rte_memseg *ms; | |
136 | int hugepage_2MB_avail = 0; | |
137 | int hugepage_1GB_avail = 0; | |
138 | int hugepage_16MB_avail = 0; | |
139 | int hugepage_16GB_avail = 0; | |
140 | const size_t size = 100; | |
141 | int i = 0; | |
142 | ms = rte_eal_get_physmem_layout(); | |
143 | for (i = 0; i < RTE_MAX_MEMSEG; i++) { | |
144 | if (ms[i].hugepage_sz == RTE_PGSIZE_2M) | |
145 | hugepage_2MB_avail = 1; | |
146 | if (ms[i].hugepage_sz == RTE_PGSIZE_1G) | |
147 | hugepage_1GB_avail = 1; | |
148 | if (ms[i].hugepage_sz == RTE_PGSIZE_16M) | |
149 | hugepage_16MB_avail = 1; | |
150 | if (ms[i].hugepage_sz == RTE_PGSIZE_16G) | |
151 | hugepage_16GB_avail = 1; | |
152 | } | |
153 | /* Display the availability of 2MB ,1GB, 16MB, 16GB pages */ | |
154 | if (hugepage_2MB_avail) | |
155 | printf("2MB Huge pages available\n"); | |
156 | if (hugepage_1GB_avail) | |
157 | printf("1GB Huge pages available\n"); | |
158 | if (hugepage_16MB_avail) | |
159 | printf("16MB Huge pages available\n"); | |
160 | if (hugepage_16GB_avail) | |
161 | printf("16GB Huge pages available\n"); | |
162 | /* | |
163 | * If 2MB pages available, check that a small memzone is correctly | |
164 | * reserved from 2MB huge pages when requested by the RTE_MEMZONE_2MB flag. | |
165 | * Also check that RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an | |
166 | * available page size (i.e 1GB ) when 2MB pages are unavailable. | |
167 | */ | |
168 | if (hugepage_2MB_avail) { | |
169 | mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY, | |
170 | RTE_MEMZONE_2MB); | |
171 | if (mz == NULL) { | |
172 | printf("MEMZONE FLAG 2MB\n"); | |
173 | return -1; | |
174 | } | |
175 | if (mz->hugepage_sz != RTE_PGSIZE_2M) { | |
176 | printf("hugepage_sz not equal 2M\n"); | |
177 | return -1; | |
178 | } | |
179 | ||
180 | mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, | |
181 | RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
182 | if (mz == NULL) { | |
183 | printf("MEMZONE FLAG 2MB\n"); | |
184 | return -1; | |
185 | } | |
186 | if (mz->hugepage_sz != RTE_PGSIZE_2M) { | |
187 | printf("hugepage_sz not equal 2M\n"); | |
188 | return -1; | |
189 | } | |
190 | ||
191 | /* Check if 1GB huge pages are unavailable, that function fails unless | |
192 | * HINT flag is indicated | |
193 | */ | |
194 | if (!hugepage_1GB_avail) { | |
195 | mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY, | |
196 | RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
197 | if (mz == NULL) { | |
198 | printf("MEMZONE FLAG 1GB & HINT\n"); | |
199 | return -1; | |
200 | } | |
201 | if (mz->hugepage_sz != RTE_PGSIZE_2M) { | |
202 | printf("hugepage_sz not equal 2M\n"); | |
203 | return -1; | |
204 | } | |
205 | ||
206 | mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY, | |
207 | RTE_MEMZONE_1GB); | |
208 | if (mz != NULL) { | |
209 | printf("MEMZONE FLAG 1GB\n"); | |
210 | return -1; | |
211 | } | |
212 | } | |
213 | } | |
214 | ||
215 | /*As with 2MB tests above for 1GB huge page requests*/ | |
216 | if (hugepage_1GB_avail) { | |
217 | mz = rte_memzone_reserve("flag_zone_1G", size, SOCKET_ID_ANY, | |
218 | RTE_MEMZONE_1GB); | |
219 | if (mz == NULL) { | |
220 | printf("MEMZONE FLAG 1GB\n"); | |
221 | return -1; | |
222 | } | |
223 | if (mz->hugepage_sz != RTE_PGSIZE_1G) { | |
224 | printf("hugepage_sz not equal 1G\n"); | |
225 | return -1; | |
226 | } | |
227 | ||
228 | mz = rte_memzone_reserve("flag_zone_1G_HINT", size, SOCKET_ID_ANY, | |
229 | RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
230 | if (mz == NULL) { | |
231 | printf("MEMZONE FLAG 1GB\n"); | |
232 | return -1; | |
233 | } | |
234 | if (mz->hugepage_sz != RTE_PGSIZE_1G) { | |
235 | printf("hugepage_sz not equal 1G\n"); | |
236 | return -1; | |
237 | } | |
238 | ||
239 | /* Check if 1GB huge pages are unavailable, that function fails unless | |
240 | * HINT flag is indicated | |
241 | */ | |
242 | if (!hugepage_2MB_avail) { | |
243 | mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, | |
244 | RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
245 | if (mz == NULL){ | |
246 | printf("MEMZONE FLAG 2MB & HINT\n"); | |
247 | return -1; | |
248 | } | |
249 | if (mz->hugepage_sz != RTE_PGSIZE_1G) { | |
250 | printf("hugepage_sz not equal 1G\n"); | |
251 | return -1; | |
252 | } | |
253 | mz = rte_memzone_reserve("flag_zone_2M", size, SOCKET_ID_ANY, | |
254 | RTE_MEMZONE_2MB); | |
255 | if (mz != NULL) { | |
256 | printf("MEMZONE FLAG 2MB\n"); | |
257 | return -1; | |
258 | } | |
259 | } | |
260 | ||
261 | if (hugepage_2MB_avail && hugepage_1GB_avail) { | |
262 | mz = rte_memzone_reserve("flag_zone_2M_HINT", size, SOCKET_ID_ANY, | |
263 | RTE_MEMZONE_2MB|RTE_MEMZONE_1GB); | |
264 | if (mz != NULL) { | |
265 | printf("BOTH SIZES SET\n"); | |
266 | return -1; | |
267 | } | |
268 | } | |
269 | } | |
270 | /* | |
271 | * This option is for IBM Power. If 16MB pages available, check | |
272 | * that a small memzone is correctly reserved from 16MB huge pages | |
273 | * when requested by the RTE_MEMZONE_16MB flag. Also check that | |
274 | * RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an available | |
275 | * page size (i.e 16GB ) when 16MB pages are unavailable. | |
276 | */ | |
277 | if (hugepage_16MB_avail) { | |
278 | mz = rte_memzone_reserve("flag_zone_16M", size, SOCKET_ID_ANY, | |
279 | RTE_MEMZONE_16MB); | |
280 | if (mz == NULL) { | |
281 | printf("MEMZONE FLAG 16MB\n"); | |
282 | return -1; | |
283 | } | |
284 | if (mz->hugepage_sz != RTE_PGSIZE_16M) { | |
285 | printf("hugepage_sz not equal 16M\n"); | |
286 | return -1; | |
287 | } | |
288 | ||
289 | mz = rte_memzone_reserve("flag_zone_16M_HINT", size, | |
290 | SOCKET_ID_ANY, RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
291 | if (mz == NULL) { | |
292 | printf("MEMZONE FLAG 2MB\n"); | |
293 | return -1; | |
294 | } | |
295 | if (mz->hugepage_sz != RTE_PGSIZE_16M) { | |
296 | printf("hugepage_sz not equal 16M\n"); | |
297 | return -1; | |
298 | } | |
299 | ||
300 | /* Check if 1GB huge pages are unavailable, that function fails | |
301 | * unless HINT flag is indicated | |
302 | */ | |
303 | if (!hugepage_16GB_avail) { | |
304 | mz = rte_memzone_reserve("flag_zone_16G_HINT", size, | |
305 | SOCKET_ID_ANY, | |
306 | RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
307 | if (mz == NULL) { | |
308 | printf("MEMZONE FLAG 16GB & HINT\n"); | |
309 | return -1; | |
310 | } | |
311 | if (mz->hugepage_sz != RTE_PGSIZE_16M) { | |
312 | printf("hugepage_sz not equal 16M\n"); | |
313 | return -1; | |
314 | } | |
315 | ||
316 | mz = rte_memzone_reserve("flag_zone_16G", size, | |
317 | SOCKET_ID_ANY, RTE_MEMZONE_16GB); | |
318 | if (mz != NULL) { | |
319 | printf("MEMZONE FLAG 16GB\n"); | |
320 | return -1; | |
321 | } | |
322 | } | |
323 | } | |
324 | /*As with 16MB tests above for 16GB huge page requests*/ | |
325 | if (hugepage_16GB_avail) { | |
326 | mz = rte_memzone_reserve("flag_zone_16G", size, SOCKET_ID_ANY, | |
327 | RTE_MEMZONE_16GB); | |
328 | if (mz == NULL) { | |
329 | printf("MEMZONE FLAG 16GB\n"); | |
330 | return -1; | |
331 | } | |
332 | if (mz->hugepage_sz != RTE_PGSIZE_16G) { | |
333 | printf("hugepage_sz not equal 16G\n"); | |
334 | return -1; | |
335 | } | |
336 | ||
337 | mz = rte_memzone_reserve("flag_zone_16G_HINT", size, | |
338 | SOCKET_ID_ANY, RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
339 | if (mz == NULL) { | |
340 | printf("MEMZONE FLAG 16GB\n"); | |
341 | return -1; | |
342 | } | |
343 | if (mz->hugepage_sz != RTE_PGSIZE_16G) { | |
344 | printf("hugepage_sz not equal 16G\n"); | |
345 | return -1; | |
346 | } | |
347 | ||
348 | /* Check if 1GB huge pages are unavailable, that function fails | |
349 | * unless HINT flag is indicated | |
350 | */ | |
351 | if (!hugepage_16MB_avail) { | |
352 | mz = rte_memzone_reserve("flag_zone_16M_HINT", size, | |
353 | SOCKET_ID_ANY, | |
354 | RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY); | |
355 | if (mz == NULL) { | |
356 | printf("MEMZONE FLAG 16MB & HINT\n"); | |
357 | return -1; | |
358 | } | |
359 | if (mz->hugepage_sz != RTE_PGSIZE_16G) { | |
360 | printf("hugepage_sz not equal 16G\n"); | |
361 | return -1; | |
362 | } | |
363 | mz = rte_memzone_reserve("flag_zone_16M", size, | |
364 | SOCKET_ID_ANY, RTE_MEMZONE_16MB); | |
365 | if (mz != NULL) { | |
366 | printf("MEMZONE FLAG 16MB\n"); | |
367 | return -1; | |
368 | } | |
369 | } | |
370 | ||
371 | if (hugepage_16MB_avail && hugepage_16GB_avail) { | |
372 | mz = rte_memzone_reserve("flag_zone_16M_HINT", size, | |
373 | SOCKET_ID_ANY, | |
374 | RTE_MEMZONE_16MB|RTE_MEMZONE_16GB); | |
375 | if (mz != NULL) { | |
376 | printf("BOTH SIZES SET\n"); | |
377 | return -1; | |
378 | } | |
379 | } | |
380 | } | |
381 | return 0; | |
382 | } | |
383 | ||
384 | ||
385 | /* Find the heap with the greatest free block size */ | |
386 | static size_t | |
387 | find_max_block_free_size(const unsigned _align) | |
388 | { | |
389 | struct rte_malloc_socket_stats stats; | |
390 | unsigned i, align = _align; | |
391 | size_t len = 0; | |
392 | ||
393 | for (i = 0; i < RTE_MAX_NUMA_NODES; i++) { | |
394 | rte_malloc_get_socket_stats(i, &stats); | |
395 | if (stats.greatest_free_size > len) | |
396 | len = stats.greatest_free_size; | |
397 | } | |
398 | ||
399 | if (align < RTE_CACHE_LINE_SIZE) | |
400 | align = RTE_CACHE_LINE_ROUNDUP(align+1); | |
401 | ||
402 | if (len <= MALLOC_ELEM_OVERHEAD + align) | |
403 | return 0; | |
404 | ||
405 | return len - MALLOC_ELEM_OVERHEAD - align; | |
406 | } | |
407 | ||
408 | static int | |
409 | test_memzone_reserve_max(void) | |
410 | { | |
411 | const struct rte_memzone *mz; | |
412 | size_t maxlen; | |
413 | ||
414 | maxlen = find_max_block_free_size(0); | |
415 | ||
416 | if (maxlen == 0) { | |
417 | printf("There is no space left!\n"); | |
418 | return 0; | |
419 | } | |
420 | ||
421 | mz = rte_memzone_reserve("max_zone", 0, SOCKET_ID_ANY, 0); | |
422 | if (mz == NULL){ | |
423 | printf("Failed to reserve a big chunk of memory - %s\n", | |
424 | rte_strerror(rte_errno)); | |
425 | rte_dump_physmem_layout(stdout); | |
426 | rte_memzone_dump(stdout); | |
427 | return -1; | |
428 | } | |
429 | ||
430 | if (mz->len != maxlen) { | |
431 | printf("Memzone reserve with 0 size did not return bigest block\n"); | |
432 | printf("Expected size = %zu, actual size = %zu\n", maxlen, mz->len); | |
433 | rte_dump_physmem_layout(stdout); | |
434 | rte_memzone_dump(stdout); | |
435 | return -1; | |
436 | } | |
437 | return 0; | |
438 | } | |
439 | ||
440 | static int | |
441 | test_memzone_reserve_max_aligned(void) | |
442 | { | |
443 | const struct rte_memzone *mz; | |
444 | size_t maxlen = 0; | |
445 | ||
446 | /* random alignment */ | |
447 | rte_srand((unsigned)rte_rdtsc()); | |
448 | const unsigned align = 1 << ((rte_rand() % 8) + 5); /* from 128 up to 4k alignment */ | |
449 | ||
450 | maxlen = find_max_block_free_size(align); | |
451 | ||
452 | if (maxlen == 0) { | |
453 | printf("There is no space left for biggest %u-aligned memzone!\n", align); | |
454 | return 0; | |
455 | } | |
456 | ||
457 | mz = rte_memzone_reserve_aligned("max_zone_aligned", 0, | |
458 | SOCKET_ID_ANY, 0, align); | |
459 | if (mz == NULL){ | |
460 | printf("Failed to reserve a big chunk of memory - %s\n", | |
461 | rte_strerror(rte_errno)); | |
462 | rte_dump_physmem_layout(stdout); | |
463 | rte_memzone_dump(stdout); | |
464 | return -1; | |
465 | } | |
466 | ||
467 | if (mz->len != maxlen) { | |
468 | printf("Memzone reserve with 0 size and alignment %u did not return" | |
469 | " bigest block\n", align); | |
470 | printf("Expected size = %zu, actual size = %zu\n", | |
471 | maxlen, mz->len); | |
472 | rte_dump_physmem_layout(stdout); | |
473 | rte_memzone_dump(stdout); | |
474 | return -1; | |
475 | } | |
476 | return 0; | |
477 | } | |
478 | ||
479 | static int | |
480 | test_memzone_aligned(void) | |
481 | { | |
482 | const struct rte_memzone *memzone_aligned_32; | |
483 | const struct rte_memzone *memzone_aligned_128; | |
484 | const struct rte_memzone *memzone_aligned_256; | |
485 | const struct rte_memzone *memzone_aligned_512; | |
486 | const struct rte_memzone *memzone_aligned_1024; | |
487 | ||
488 | /* memzone that should automatically be adjusted to align on 64 bytes */ | |
489 | memzone_aligned_32 = rte_memzone_reserve_aligned("aligned_32", 100, | |
490 | SOCKET_ID_ANY, 0, 32); | |
491 | ||
492 | /* memzone that is supposed to be aligned on a 128 byte boundary */ | |
493 | memzone_aligned_128 = rte_memzone_reserve_aligned("aligned_128", 100, | |
494 | SOCKET_ID_ANY, 0, 128); | |
495 | ||
496 | /* memzone that is supposed to be aligned on a 256 byte boundary */ | |
497 | memzone_aligned_256 = rte_memzone_reserve_aligned("aligned_256", 100, | |
498 | SOCKET_ID_ANY, 0, 256); | |
499 | ||
500 | /* memzone that is supposed to be aligned on a 512 byte boundary */ | |
501 | memzone_aligned_512 = rte_memzone_reserve_aligned("aligned_512", 100, | |
502 | SOCKET_ID_ANY, 0, 512); | |
503 | ||
504 | /* memzone that is supposed to be aligned on a 1024 byte boundary */ | |
505 | memzone_aligned_1024 = rte_memzone_reserve_aligned("aligned_1024", 100, | |
506 | SOCKET_ID_ANY, 0, 1024); | |
507 | ||
508 | printf("check alignments and lengths\n"); | |
509 | if (memzone_aligned_32 == NULL) { | |
510 | printf("Unable to reserve 64-byte aligned memzone!\n"); | |
511 | return -1; | |
512 | } | |
513 | if ((memzone_aligned_32->phys_addr & RTE_CACHE_LINE_MASK) != 0) | |
514 | return -1; | |
515 | if (((uintptr_t) memzone_aligned_32->addr & RTE_CACHE_LINE_MASK) != 0) | |
516 | return -1; | |
517 | if ((memzone_aligned_32->len & RTE_CACHE_LINE_MASK) != 0) | |
518 | return -1; | |
519 | ||
520 | if (memzone_aligned_128 == NULL) { | |
521 | printf("Unable to reserve 128-byte aligned memzone!\n"); | |
522 | return -1; | |
523 | } | |
524 | if ((memzone_aligned_128->phys_addr & 127) != 0) | |
525 | return -1; | |
526 | if (((uintptr_t) memzone_aligned_128->addr & 127) != 0) | |
527 | return -1; | |
528 | if ((memzone_aligned_128->len & RTE_CACHE_LINE_MASK) != 0) | |
529 | return -1; | |
530 | ||
531 | if (memzone_aligned_256 == NULL) { | |
532 | printf("Unable to reserve 256-byte aligned memzone!\n"); | |
533 | return -1; | |
534 | } | |
535 | if ((memzone_aligned_256->phys_addr & 255) != 0) | |
536 | return -1; | |
537 | if (((uintptr_t) memzone_aligned_256->addr & 255) != 0) | |
538 | return -1; | |
539 | if ((memzone_aligned_256->len & RTE_CACHE_LINE_MASK) != 0) | |
540 | return -1; | |
541 | ||
542 | if (memzone_aligned_512 == NULL) { | |
543 | printf("Unable to reserve 512-byte aligned memzone!\n"); | |
544 | return -1; | |
545 | } | |
546 | if ((memzone_aligned_512->phys_addr & 511) != 0) | |
547 | return -1; | |
548 | if (((uintptr_t) memzone_aligned_512->addr & 511) != 0) | |
549 | return -1; | |
550 | if ((memzone_aligned_512->len & RTE_CACHE_LINE_MASK) != 0) | |
551 | return -1; | |
552 | ||
553 | if (memzone_aligned_1024 == NULL) { | |
554 | printf("Unable to reserve 1024-byte aligned memzone!\n"); | |
555 | return -1; | |
556 | } | |
557 | if ((memzone_aligned_1024->phys_addr & 1023) != 0) | |
558 | return -1; | |
559 | if (((uintptr_t) memzone_aligned_1024->addr & 1023) != 0) | |
560 | return -1; | |
561 | if ((memzone_aligned_1024->len & RTE_CACHE_LINE_MASK) != 0) | |
562 | return -1; | |
563 | ||
564 | /* check that zones don't overlap */ | |
565 | printf("check overlapping\n"); | |
566 | if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, | |
567 | memzone_aligned_128->phys_addr, memzone_aligned_128->len)) | |
568 | return -1; | |
569 | if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, | |
570 | memzone_aligned_256->phys_addr, memzone_aligned_256->len)) | |
571 | return -1; | |
572 | if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, | |
573 | memzone_aligned_512->phys_addr, memzone_aligned_512->len)) | |
574 | return -1; | |
575 | if (is_memory_overlap(memzone_aligned_32->phys_addr, memzone_aligned_32->len, | |
576 | memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) | |
577 | return -1; | |
578 | if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, | |
579 | memzone_aligned_256->phys_addr, memzone_aligned_256->len)) | |
580 | return -1; | |
581 | if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, | |
582 | memzone_aligned_512->phys_addr, memzone_aligned_512->len)) | |
583 | return -1; | |
584 | if (is_memory_overlap(memzone_aligned_128->phys_addr, memzone_aligned_128->len, | |
585 | memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) | |
586 | return -1; | |
587 | if (is_memory_overlap(memzone_aligned_256->phys_addr, memzone_aligned_256->len, | |
588 | memzone_aligned_512->phys_addr, memzone_aligned_512->len)) | |
589 | return -1; | |
590 | if (is_memory_overlap(memzone_aligned_256->phys_addr, memzone_aligned_256->len, | |
591 | memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) | |
592 | return -1; | |
593 | if (is_memory_overlap(memzone_aligned_512->phys_addr, memzone_aligned_512->len, | |
594 | memzone_aligned_1024->phys_addr, memzone_aligned_1024->len)) | |
595 | return -1; | |
596 | return 0; | |
597 | } | |
598 | ||
599 | static int | |
600 | check_memzone_bounded(const char *name, uint32_t len, uint32_t align, | |
601 | uint32_t bound) | |
602 | { | |
603 | const struct rte_memzone *mz; | |
604 | phys_addr_t bmask; | |
605 | ||
606 | bmask = ~((phys_addr_t)bound - 1); | |
607 | ||
608 | if ((mz = rte_memzone_reserve_bounded(name, len, SOCKET_ID_ANY, 0, | |
609 | align, bound)) == NULL) { | |
610 | printf("%s(%s): memzone creation failed\n", | |
611 | __func__, name); | |
612 | return -1; | |
613 | } | |
614 | ||
615 | if ((mz->phys_addr & ((phys_addr_t)align - 1)) != 0) { | |
616 | printf("%s(%s): invalid phys addr alignment\n", | |
617 | __func__, mz->name); | |
618 | return -1; | |
619 | } | |
620 | ||
621 | if (((uintptr_t) mz->addr & ((uintptr_t)align - 1)) != 0) { | |
622 | printf("%s(%s): invalid virtual addr alignment\n", | |
623 | __func__, mz->name); | |
624 | return -1; | |
625 | } | |
626 | ||
627 | if ((mz->len & RTE_CACHE_LINE_MASK) != 0 || mz->len < len || | |
628 | mz->len < RTE_CACHE_LINE_SIZE) { | |
629 | printf("%s(%s): invalid length\n", | |
630 | __func__, mz->name); | |
631 | return -1; | |
632 | } | |
633 | ||
634 | if ((mz->phys_addr & bmask) != | |
635 | ((mz->phys_addr + mz->len - 1) & bmask)) { | |
636 | printf("%s(%s): invalid memzone boundary %u crossed\n", | |
637 | __func__, mz->name, bound); | |
638 | return -1; | |
639 | } | |
640 | ||
641 | return 0; | |
642 | } | |
643 | ||
644 | static int | |
645 | test_memzone_bounded(void) | |
646 | { | |
647 | const struct rte_memzone *memzone_err; | |
648 | const char *name; | |
649 | int rc; | |
650 | ||
651 | /* should fail as boundary is not power of two */ | |
652 | name = "bounded_error_31"; | |
653 | if ((memzone_err = rte_memzone_reserve_bounded(name, | |
654 | 100, SOCKET_ID_ANY, 0, 32, UINT32_MAX)) != NULL) { | |
655 | printf("%s(%s)created a memzone with invalid boundary " | |
656 | "conditions\n", __func__, memzone_err->name); | |
657 | return -1; | |
658 | } | |
659 | ||
660 | /* should fail as len is greater then boundary */ | |
661 | name = "bounded_error_32"; | |
662 | if ((memzone_err = rte_memzone_reserve_bounded(name, | |
663 | 100, SOCKET_ID_ANY, 0, 32, 32)) != NULL) { | |
664 | printf("%s(%s)created a memzone with invalid boundary " | |
665 | "conditions\n", __func__, memzone_err->name); | |
666 | return -1; | |
667 | } | |
668 | ||
669 | if ((rc = check_memzone_bounded("bounded_128", 100, 128, 128)) != 0) | |
670 | return rc; | |
671 | ||
672 | if ((rc = check_memzone_bounded("bounded_256", 100, 256, 128)) != 0) | |
673 | return rc; | |
674 | ||
675 | if ((rc = check_memzone_bounded("bounded_1K", 100, 64, 1024)) != 0) | |
676 | return rc; | |
677 | ||
678 | if ((rc = check_memzone_bounded("bounded_1K_MAX", 0, 64, 1024)) != 0) | |
679 | return rc; | |
680 | ||
681 | return 0; | |
682 | } | |
683 | ||
684 | static int | |
685 | test_memzone_free(void) | |
686 | { | |
687 | const struct rte_memzone *mz[RTE_MAX_MEMZONE]; | |
688 | int i; | |
689 | char name[20]; | |
690 | ||
691 | mz[0] = rte_memzone_reserve("tempzone0", 2000, SOCKET_ID_ANY, 0); | |
692 | mz[1] = rte_memzone_reserve("tempzone1", 4000, SOCKET_ID_ANY, 0); | |
693 | ||
694 | if (mz[0] > mz[1]) | |
695 | return -1; | |
696 | if (!rte_memzone_lookup("tempzone0")) | |
697 | return -1; | |
698 | if (!rte_memzone_lookup("tempzone1")) | |
699 | return -1; | |
700 | ||
701 | if (rte_memzone_free(mz[0])) { | |
702 | printf("Fail memzone free - tempzone0\n"); | |
703 | return -1; | |
704 | } | |
705 | if (rte_memzone_lookup("tempzone0")) { | |
706 | printf("Found previously free memzone - tempzone0\n"); | |
707 | return -1; | |
708 | } | |
709 | mz[2] = rte_memzone_reserve("tempzone2", 2000, SOCKET_ID_ANY, 0); | |
710 | ||
711 | if (mz[2] > mz[1]) { | |
712 | printf("tempzone2 should have gotten the free entry from tempzone0\n"); | |
713 | return -1; | |
714 | } | |
715 | if (rte_memzone_free(mz[2])) { | |
716 | printf("Fail memzone free - tempzone2\n"); | |
717 | return -1; | |
718 | } | |
719 | if (rte_memzone_lookup("tempzone2")) { | |
720 | printf("Found previously free memzone - tempzone2\n"); | |
721 | return -1; | |
722 | } | |
723 | if (rte_memzone_free(mz[1])) { | |
724 | printf("Fail memzone free - tempzone1\n"); | |
725 | return -1; | |
726 | } | |
727 | if (rte_memzone_lookup("tempzone1")) { | |
728 | printf("Found previously free memzone - tempzone1\n"); | |
729 | return -1; | |
730 | } | |
731 | ||
732 | i = 0; | |
733 | do { | |
734 | snprintf(name, sizeof(name), "tempzone%u", i); | |
735 | mz[i] = rte_memzone_reserve(name, 1, SOCKET_ID_ANY, 0); | |
736 | } while (mz[i++] != NULL); | |
737 | ||
738 | if (rte_memzone_free(mz[0])) { | |
739 | printf("Fail memzone free - tempzone0\n"); | |
740 | return -1; | |
741 | } | |
742 | mz[0] = rte_memzone_reserve("tempzone0new", 0, SOCKET_ID_ANY, 0); | |
743 | ||
744 | if (mz[0] == NULL) { | |
745 | printf("Fail to create memzone - tempzone0new - when MAX memzones were " | |
746 | "created and one was free\n"); | |
747 | return -1; | |
748 | } | |
749 | ||
750 | for (i = i - 2; i >= 0; i--) { | |
751 | if (rte_memzone_free(mz[i])) { | |
752 | printf("Fail memzone free - tempzone%d\n", i); | |
753 | return -1; | |
754 | } | |
755 | } | |
756 | ||
757 | return 0; | |
758 | } | |
759 | ||
760 | static int | |
761 | test_memzone(void) | |
762 | { | |
763 | const struct rte_memzone *memzone1; | |
764 | const struct rte_memzone *memzone2; | |
765 | const struct rte_memzone *memzone3; | |
766 | const struct rte_memzone *memzone4; | |
767 | const struct rte_memzone *mz; | |
768 | ||
769 | memzone1 = rte_memzone_reserve("testzone1", 100, | |
770 | SOCKET_ID_ANY, 0); | |
771 | ||
772 | memzone2 = rte_memzone_reserve("testzone2", 1000, | |
773 | 0, 0); | |
774 | ||
775 | memzone3 = rte_memzone_reserve("testzone3", 1000, | |
776 | 1, 0); | |
777 | ||
778 | memzone4 = rte_memzone_reserve("testzone4", 1024, | |
779 | SOCKET_ID_ANY, 0); | |
780 | ||
781 | /* memzone3 may be NULL if we don't have NUMA */ | |
782 | if (memzone1 == NULL || memzone2 == NULL || memzone4 == NULL) | |
783 | return -1; | |
784 | ||
785 | rte_memzone_dump(stdout); | |
786 | ||
787 | /* check cache-line alignments */ | |
788 | printf("check alignments and lengths\n"); | |
789 | ||
790 | if ((memzone1->phys_addr & RTE_CACHE_LINE_MASK) != 0) | |
791 | return -1; | |
792 | if ((memzone2->phys_addr & RTE_CACHE_LINE_MASK) != 0) | |
793 | return -1; | |
794 | if (memzone3 != NULL && (memzone3->phys_addr & RTE_CACHE_LINE_MASK) != 0) | |
795 | return -1; | |
796 | if ((memzone1->len & RTE_CACHE_LINE_MASK) != 0 || memzone1->len == 0) | |
797 | return -1; | |
798 | if ((memzone2->len & RTE_CACHE_LINE_MASK) != 0 || memzone2->len == 0) | |
799 | return -1; | |
800 | if (memzone3 != NULL && ((memzone3->len & RTE_CACHE_LINE_MASK) != 0 || | |
801 | memzone3->len == 0)) | |
802 | return -1; | |
803 | if (memzone4->len != 1024) | |
804 | return -1; | |
805 | ||
806 | /* check that zones don't overlap */ | |
807 | printf("check overlapping\n"); | |
808 | ||
809 | if (is_memory_overlap(memzone1->phys_addr, memzone1->len, | |
810 | memzone2->phys_addr, memzone2->len)) | |
811 | return -1; | |
812 | if (memzone3 != NULL && | |
813 | is_memory_overlap(memzone1->phys_addr, memzone1->len, | |
814 | memzone3->phys_addr, memzone3->len)) | |
815 | return -1; | |
816 | if (memzone3 != NULL && | |
817 | is_memory_overlap(memzone2->phys_addr, memzone2->len, | |
818 | memzone3->phys_addr, memzone3->len)) | |
819 | return -1; | |
820 | ||
821 | printf("check socket ID\n"); | |
822 | ||
823 | /* memzone2 must be on socket id 0 and memzone3 on socket 1 */ | |
824 | if (memzone2->socket_id != 0) | |
825 | return -1; | |
826 | if (memzone3 != NULL && memzone3->socket_id != 1) | |
827 | return -1; | |
828 | ||
829 | printf("test zone lookup\n"); | |
830 | mz = rte_memzone_lookup("testzone1"); | |
831 | if (mz != memzone1) | |
832 | return -1; | |
833 | ||
834 | printf("test duplcate zone name\n"); | |
835 | mz = rte_memzone_reserve("testzone1", 100, | |
836 | SOCKET_ID_ANY, 0); | |
837 | if (mz != NULL) | |
838 | return -1; | |
839 | ||
840 | printf("test free memzone\n"); | |
841 | if (test_memzone_free() < 0) | |
842 | return -1; | |
843 | ||
844 | printf("test reserving memzone with bigger size than the maximum\n"); | |
845 | if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0) | |
846 | return -1; | |
847 | ||
848 | printf("test memzone_reserve flags\n"); | |
849 | if (test_memzone_reserve_flags() < 0) | |
850 | return -1; | |
851 | ||
852 | printf("test alignment for memzone_reserve\n"); | |
853 | if (test_memzone_aligned() < 0) | |
854 | return -1; | |
855 | ||
856 | printf("test boundary alignment for memzone_reserve\n"); | |
857 | if (test_memzone_bounded() < 0) | |
858 | return -1; | |
859 | ||
860 | printf("test invalid alignment for memzone_reserve\n"); | |
861 | if (test_memzone_invalid_alignment() < 0) | |
862 | return -1; | |
863 | ||
864 | printf("test reserving the largest size memzone possible\n"); | |
865 | if (test_memzone_reserve_max() < 0) | |
866 | return -1; | |
867 | ||
868 | printf("test reserving the largest size aligned memzone possible\n"); | |
869 | if (test_memzone_reserve_max_aligned() < 0) | |
870 | return -1; | |
871 | ||
872 | return 0; | |
873 | } | |
874 | ||
875 | REGISTER_TEST_COMMAND(memzone_autotest, test_memzone); |