LCOV - code coverage report
Current view: top level - app/test - test_external_mem.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 145 219 66.2 %
Date: 2026-10-01 18:19:24 Functions: 7 7 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 114 216 52.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #define ALLOW_INTERNAL_API
       6                 :            : 
       7                 :            : #include "test.h"
       8                 :            : 
       9                 :            : #include <errno.h>
      10                 :            : #include <stdio.h>
      11                 :            : #include <stdlib.h>
      12                 :            : #include <string.h>
      13                 :            : #include <fcntl.h>
      14                 :            : 
      15                 :            : #ifndef RTE_EXEC_ENV_LINUX
      16                 :            : static int
      17                 :            : test_external_mem(void)
      18                 :            : {
      19                 :            :         printf("external_mem only supported on Linux, skipping test\n");
      20                 :            :         return TEST_SKIPPED;
      21                 :            : }
      22                 :            : 
      23                 :            : #else
      24                 :            : 
      25                 :            : #include <sys/mman.h>
      26                 :            : #include <sys/wait.h>
      27                 :            : 
      28                 :            : #include <rte_common.h>
      29                 :            : #include <rte_debug.h>
      30                 :            : #include <rte_eal.h>
      31                 :            : #include <rte_eal_paging.h>
      32                 :            : #include <rte_errno.h>
      33                 :            : #include <rte_malloc.h>
      34                 :            : #include <rte_ring.h>
      35                 :            : #include <rte_string_fns.h>
      36                 :            : 
      37                 :            : #define EXTERNAL_MEM_SZ (RTE_PGSIZE_4K << 10) /* 4M of data */
      38                 :            : 
      39                 :            : static int
      40                 :          4 : check_mem(void *addr, rte_iova_t *iova, size_t pgsz, int n_pages)
      41                 :            : {
      42                 :            :         int i;
      43                 :            : 
      44                 :            :         /* check that we can get this memory from EAL now */
      45         [ +  + ]:       4100 :         for (i = 0; i < n_pages; i++) {
      46                 :            :                 const struct rte_memseg_list *msl;
      47                 :            :                 const struct rte_memseg *ms;
      48                 :       4096 :                 void *cur = RTE_PTR_ADD(addr, pgsz * i);
      49                 :            :                 rte_iova_t expected_iova;
      50                 :            : 
      51                 :       4096 :                 msl = rte_mem_virt2memseg_list(cur);
      52         [ -  + ]:       4096 :                 if (!msl->external) {
      53                 :            :                         printf("%s():%i: Memseg list is not marked as external\n",
      54                 :            :                                 __func__, __LINE__);
      55                 :          0 :                         return -1;
      56                 :            :                 }
      57                 :            : 
      58                 :       4096 :                 ms = rte_mem_virt2memseg(cur, msl);
      59         [ -  + ]:       4096 :                 if (ms == NULL) {
      60                 :            :                         printf("%s():%i: Failed to retrieve memseg for external mem\n",
      61                 :            :                                 __func__, __LINE__);
      62                 :          0 :                         return -1;
      63                 :            :                 }
      64         [ -  + ]:       4096 :                 if (ms->addr != cur) {
      65                 :            :                         printf("%s():%i: VA mismatch\n", __func__, __LINE__);
      66                 :          0 :                         return -1;
      67                 :            :                 }
      68         [ +  + ]:       4096 :                 expected_iova = (iova == NULL) ? RTE_BAD_IOVA : iova[i];
      69         [ -  + ]:       4096 :                 if (ms->iova != expected_iova) {
      70                 :            :                         printf("%s():%i: IOVA mismatch\n", __func__, __LINE__);
      71                 :          0 :                         return -1;
      72                 :            :                 }
      73                 :            :         }
      74                 :            :         return 0;
      75                 :            : }
      76                 :            : 
      77                 :            : static int
      78                 :          2 : test_malloc_invalid_param(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
      79                 :            :                 int n_pages)
      80                 :            : {
      81                 :            :         static const char * const names[] = {
      82                 :            :                 NULL, /* NULL name */
      83                 :            :                 "",   /* empty name */
      84                 :            :                 "this heap name is definitely way too long to be valid"
      85                 :            :         };
      86                 :            :         const char *valid_name = "valid heap name";
      87                 :            :         unsigned int i;
      88                 :            : 
      89                 :            :         /* check invalid name handling */
      90         [ +  + ]:          8 :         for (i = 0; i < RTE_DIM(names); i++) {
      91                 :          6 :                 const char *name = names[i];
      92                 :            : 
      93                 :            :                 /* these calls may fail for other reasons, so check errno */
      94   [ +  -  -  + ]:          6 :                 if (rte_malloc_heap_create(name) >= 0 || rte_errno != EINVAL) {
      95                 :            :                         printf("%s():%i: Created heap with invalid name\n",
      96                 :            :                                         __func__, __LINE__);
      97                 :          0 :                         goto fail;
      98                 :            :                 }
      99                 :            : 
     100   [ +  -  -  + ]:          6 :                 if (rte_malloc_heap_destroy(name) >= 0 || rte_errno != EINVAL) {
     101                 :            :                         printf("%s():%i: Destroyed heap with invalid name\n",
     102                 :            :                                         __func__, __LINE__);
     103                 :          0 :                         goto fail;
     104                 :            :                 }
     105                 :            : 
     106         [ +  - ]:          6 :                 if (rte_malloc_heap_get_socket(name) >= 0 ||
     107         [ -  + ]:          6 :                                 rte_errno != EINVAL) {
     108                 :            :                         printf("%s():%i: Found socket for heap with invalid name\n",
     109                 :            :                                         __func__, __LINE__);
     110                 :          0 :                         goto fail;
     111                 :            :                 }
     112                 :            : 
     113         [ +  - ]:          6 :                 if (rte_malloc_heap_memory_add(name, addr, len,
     114         [ -  + ]:          6 :                                 NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
     115                 :            :                         printf("%s():%i: Added memory to heap with invalid name\n",
     116                 :            :                                         __func__, __LINE__);
     117                 :          0 :                         goto fail;
     118                 :            :                 }
     119         [ +  - ]:          6 :                 if (rte_malloc_heap_memory_remove(name, addr, len) >= 0 ||
     120         [ -  + ]:          6 :                                 rte_errno != EINVAL) {
     121                 :            :                         printf("%s():%i: Removed memory from heap with invalid name\n",
     122                 :            :                                         __func__, __LINE__);
     123                 :          0 :                         goto fail;
     124                 :            :                 }
     125                 :            : 
     126         [ +  - ]:          6 :                 if (rte_malloc_heap_memory_attach(name, addr, len) >= 0 ||
     127         [ -  + ]:          6 :                                 rte_errno != EINVAL) {
     128                 :            :                         printf("%s():%i: Attached memory to heap with invalid name\n",
     129                 :            :                                 __func__, __LINE__);
     130                 :          0 :                         goto fail;
     131                 :            :                 }
     132         [ +  - ]:          6 :                 if (rte_malloc_heap_memory_detach(name, addr, len) >= 0 ||
     133         [ -  + ]:          6 :                                 rte_errno != EINVAL) {
     134                 :            :                         printf("%s():%i: Detached memory from heap with invalid name\n",
     135                 :            :                                 __func__, __LINE__);
     136                 :          0 :                         goto fail;
     137                 :            :                 }
     138                 :            :         }
     139                 :            : 
     140                 :            :         /* do same as above, but with a valid heap name */
     141                 :            : 
     142                 :            :         /* skip create call */
     143   [ +  -  -  + ]:          2 :         if (rte_malloc_heap_destroy(valid_name) >= 0 || rte_errno != ENOENT) {
     144                 :            :                 printf("%s():%i: Destroyed heap with invalid name\n",
     145                 :            :                         __func__, __LINE__);
     146                 :          0 :                 goto fail;
     147                 :            :         }
     148         [ +  - ]:          2 :         if (rte_malloc_heap_get_socket(valid_name) >= 0 ||
     149         [ -  + ]:          2 :                         rte_errno != ENOENT) {
     150                 :            :                 printf("%s():%i: Found socket for heap with invalid name\n",
     151                 :            :                                 __func__, __LINE__);
     152                 :          0 :                 goto fail;
     153                 :            :         }
     154                 :            : 
     155                 :            :         /* these calls may fail for other reasons, so check errno */
     156         [ +  - ]:          2 :         if (rte_malloc_heap_memory_add(valid_name, addr, len,
     157         [ -  + ]:          2 :                         NULL, 0, pgsz) >= 0 || rte_errno != ENOENT) {
     158                 :            :                 printf("%s():%i: Added memory to non-existent heap\n",
     159                 :            :                         __func__, __LINE__);
     160                 :          0 :                 goto fail;
     161                 :            :         }
     162         [ +  - ]:          2 :         if (rte_malloc_heap_memory_remove(valid_name, addr, len) >= 0 ||
     163         [ -  + ]:          2 :                         rte_errno != ENOENT) {
     164                 :            :                 printf("%s():%i: Removed memory from non-existent heap\n",
     165                 :            :                         __func__, __LINE__);
     166                 :          0 :                 goto fail;
     167                 :            :         }
     168                 :            : 
     169         [ +  - ]:          2 :         if (rte_malloc_heap_memory_attach(valid_name, addr, len) >= 0 ||
     170         [ -  + ]:          2 :                         rte_errno != ENOENT) {
     171                 :            :                 printf("%s():%i: Attached memory to non-existent heap\n",
     172                 :            :                         __func__, __LINE__);
     173                 :          0 :                 goto fail;
     174                 :            :         }
     175         [ +  - ]:          2 :         if (rte_malloc_heap_memory_detach(valid_name, addr, len) >= 0 ||
     176         [ -  + ]:          2 :                         rte_errno != ENOENT) {
     177                 :            :                 printf("%s():%i: Detached memory from non-existent heap\n",
     178                 :            :                         __func__, __LINE__);
     179                 :          0 :                 goto fail;
     180                 :            :         }
     181                 :            : 
     182                 :            :         /* create a valid heap but test other invalid parameters */
     183         [ -  + ]:          2 :         if (rte_malloc_heap_create(valid_name) != 0) {
     184                 :            :                 printf("%s():%i: Failed to create valid heap\n",
     185                 :            :                         __func__, __LINE__);
     186                 :          0 :                 goto fail;
     187                 :            :         }
     188                 :            : 
     189                 :            :         /* zero length */
     190         [ +  - ]:          2 :         if (rte_malloc_heap_memory_add(valid_name, addr, 0,
     191         [ -  + ]:          2 :                         NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
     192                 :            :                 printf("%s():%i: Added memory with invalid parameters\n",
     193                 :            :                         __func__, __LINE__);
     194                 :          0 :                 goto fail;
     195                 :            :         }
     196                 :            : 
     197         [ +  - ]:          2 :         if (rte_malloc_heap_memory_remove(valid_name, addr, 0) >= 0 ||
     198         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     199                 :            :                 printf("%s():%i: Removed memory with invalid parameters\n",
     200                 :            :                         __func__, __LINE__);
     201                 :          0 :                 goto fail;
     202                 :            :         }
     203                 :            : 
     204         [ +  - ]:          2 :         if (rte_malloc_heap_memory_attach(valid_name, addr, 0) >= 0 ||
     205         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     206                 :            :                 printf("%s():%i: Attached memory with invalid parameters\n",
     207                 :            :                         __func__, __LINE__);
     208                 :          0 :                 goto fail;
     209                 :            :         }
     210         [ +  - ]:          2 :         if (rte_malloc_heap_memory_detach(valid_name, addr, 0) >= 0 ||
     211         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     212                 :            :                 printf("%s():%i: Detached memory with invalid parameters\n",
     213                 :            :                         __func__, __LINE__);
     214                 :          0 :                 goto fail;
     215                 :            :         }
     216                 :            : 
     217                 :            :         /* zero address */
     218         [ +  - ]:          2 :         if (rte_malloc_heap_memory_add(valid_name, NULL, len,
     219         [ -  + ]:          2 :                         NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
     220                 :            :                 printf("%s():%i: Added memory with invalid parameters\n",
     221                 :            :                         __func__, __LINE__);
     222                 :          0 :                 goto fail;
     223                 :            :         }
     224                 :            : 
     225         [ +  - ]:          2 :         if (rte_malloc_heap_memory_remove(valid_name, NULL, len) >= 0 ||
     226         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     227                 :            :                 printf("%s():%i: Removed memory with invalid parameters\n",
     228                 :            :                         __func__, __LINE__);
     229                 :          0 :                 goto fail;
     230                 :            :         }
     231                 :            : 
     232         [ +  - ]:          2 :         if (rte_malloc_heap_memory_attach(valid_name, NULL, len) >= 0 ||
     233         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     234                 :            :                 printf("%s():%i: Attached memory with invalid parameters\n",
     235                 :            :                         __func__, __LINE__);
     236                 :          0 :                 goto fail;
     237                 :            :         }
     238         [ +  - ]:          2 :         if (rte_malloc_heap_memory_detach(valid_name, NULL, len) >= 0 ||
     239         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     240                 :            :                 printf("%s():%i: Detached memory with invalid parameters\n",
     241                 :            :                         __func__, __LINE__);
     242                 :          0 :                 goto fail;
     243                 :            :         }
     244                 :            : 
     245                 :            :         /* the following tests are only valid if IOVA table is not NULL */
     246         [ +  + ]:          2 :         if (iova != NULL) {
     247                 :            :                 /* wrong page count */
     248         [ +  - ]:          1 :                 if (rte_malloc_heap_memory_add(valid_name, addr, len,
     249         [ -  + ]:          1 :                                 iova, 0, pgsz) >= 0 || rte_errno != EINVAL) {
     250                 :            :                         printf("%s():%i: Added memory with invalid parameters\n",
     251                 :            :                                 __func__, __LINE__);
     252                 :          0 :                         goto fail;
     253                 :            :                 }
     254         [ +  - ]:          1 :                 if (rte_malloc_heap_memory_add(valid_name, addr, len,
     255                 :          1 :                                 iova, n_pages - 1, pgsz) >= 0 ||
     256         [ -  + ]:          1 :                                 rte_errno != EINVAL) {
     257                 :            :                         printf("%s():%i: Added memory with invalid parameters\n",
     258                 :            :                                 __func__, __LINE__);
     259                 :          0 :                         goto fail;
     260                 :            :                 }
     261         [ +  - ]:          1 :                 if (rte_malloc_heap_memory_add(valid_name, addr, len,
     262                 :          1 :                                 iova, n_pages + 1, pgsz) >= 0 ||
     263         [ -  + ]:          1 :                                 rte_errno != EINVAL) {
     264                 :            :                         printf("%s():%i: Added memory with invalid parameters\n",
     265                 :            :                                 __func__, __LINE__);
     266                 :          0 :                         goto fail;
     267                 :            :                 }
     268                 :            :         }
     269                 :            : 
     270                 :            :         /* tests passed, destroy heap */
     271         [ -  + ]:          2 :         if (rte_malloc_heap_destroy(valid_name) != 0) {
     272                 :            :                 printf("%s():%i: Failed to destroy valid heap\n",
     273                 :            :                         __func__, __LINE__);
     274                 :          0 :                 goto fail;
     275                 :            :         }
     276                 :            :         return 0;
     277                 :          0 : fail:
     278                 :          0 :         rte_malloc_heap_destroy(valid_name);
     279                 :          0 :         return -1;
     280                 :            : }
     281                 :            : 
     282                 :            : static int
     283                 :          2 : test_malloc_basic(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
     284                 :            :                 int n_pages)
     285                 :            : {
     286                 :            :         const char *heap_name = "heap";
     287                 :            :         void *ptr = NULL;
     288                 :            :         int socket_id;
     289                 :            :         const struct rte_memzone *mz = NULL, *contig_mz = NULL;
     290                 :            : 
     291                 :            :         /* create heap */
     292         [ -  + ]:          2 :         if (rte_malloc_heap_create(heap_name) != 0) {
     293                 :            :                 printf("%s():%i: Failed to create malloc heap\n",
     294                 :            :                         __func__, __LINE__);
     295                 :          0 :                 goto fail;
     296                 :            :         }
     297                 :            : 
     298                 :            :         /* get socket ID corresponding to this heap */
     299                 :          2 :         socket_id = rte_malloc_heap_get_socket(heap_name);
     300         [ -  + ]:          2 :         if (socket_id < 0) {
     301                 :            :                 printf("%s():%i: cannot find socket for external heap\n",
     302                 :            :                         __func__, __LINE__);
     303                 :          0 :                 goto fail;
     304                 :            :         }
     305                 :            : 
     306                 :            :         /* heap is empty, so any allocation should fail */
     307                 :          2 :         ptr = rte_malloc_socket("EXTMEM", 64, 0, socket_id);
     308         [ -  + ]:          2 :         if (ptr != NULL) {
     309                 :            :                 printf("%s():%i: Allocated from empty heap\n", __func__,
     310                 :            :                         __LINE__);
     311                 :          0 :                 goto fail;
     312                 :            :         }
     313                 :            : 
     314                 :            :         /* add memory to heap */
     315         [ -  + ]:          2 :         if (rte_malloc_heap_memory_add(heap_name, addr, len,
     316                 :            :                         iova, n_pages, pgsz) != 0) {
     317                 :            :                 printf("%s():%i: Failed to add memory to heap\n",
     318                 :            :                         __func__, __LINE__);
     319                 :          0 :                 goto fail;
     320                 :            :         }
     321                 :            : 
     322                 :            :         /* check if memory is accessible from EAL */
     323         [ -  + ]:          2 :         if (check_mem(addr, iova, pgsz, n_pages) < 0)
     324                 :          0 :                 goto fail;
     325                 :            : 
     326                 :            :         /* allocate - this now should succeed */
     327                 :          2 :         ptr = rte_malloc_socket("EXTMEM", 64, 0, socket_id);
     328         [ -  + ]:          2 :         if (ptr == NULL) {
     329                 :            :                 printf("%s():%i: Failed to allocate from external heap\n",
     330                 :            :                         __func__, __LINE__);
     331                 :          0 :                 goto fail;
     332                 :            :         }
     333                 :            : 
     334                 :            :         /* check if address is in expected range */
     335   [ +  -  -  + ]:          2 :         if (ptr < addr || ptr >= RTE_PTR_ADD(addr, len)) {
     336                 :            :                 printf("%s():%i: Allocated from unexpected address space\n",
     337                 :            :                         __func__, __LINE__);
     338                 :          0 :                 goto fail;
     339                 :            :         }
     340                 :            : 
     341                 :            :         /* we've allocated something - removing memory should fail */
     342         [ +  - ]:          2 :         if (rte_malloc_heap_memory_remove(heap_name, addr, len) >= 0 ||
     343         [ -  + ]:          2 :                         rte_errno != EBUSY) {
     344                 :            :                 printf("%s():%i: Removing memory succeeded when memory is not free\n",
     345                 :            :                         __func__, __LINE__);
     346                 :          0 :                 goto fail;
     347                 :            :         }
     348   [ +  -  -  + ]:          2 :         if (rte_malloc_heap_destroy(heap_name) >= 0 || rte_errno != EBUSY) {
     349                 :            :                 printf("%s():%i: Destroying heap succeeded when memory is not free\n",
     350                 :            :                         __func__, __LINE__);
     351                 :          0 :                 goto fail;
     352                 :            :         }
     353                 :            : 
     354                 :            :         /* try allocating a memzone */
     355                 :          2 :         mz = rte_memzone_reserve("heap_test", pgsz * 2, socket_id, 0);
     356         [ -  + ]:          2 :         if (mz == NULL) {
     357                 :            :                 printf("%s():%i: Failed to reserve memzone\n",
     358                 :            :                         __func__, __LINE__);
     359                 :          0 :                 goto fail;
     360                 :            :         }
     361                 :            :         /* try allocating an IOVA-contiguous memzone - this should succeed
     362                 :            :          * if we've set up a contiguous IOVA table, and fail if we haven't.
     363                 :            :          */
     364                 :          2 :         contig_mz = rte_memzone_reserve("heap_test_contig", pgsz * 2, socket_id,
     365                 :            :                         RTE_MEMZONE_IOVA_CONTIG);
     366         [ -  + ]:          2 :         if ((iova == NULL) != (contig_mz == NULL)) {
     367                 :            :                 printf("%s():%i: Failed to reserve memzone\n",
     368                 :            :                         __func__, __LINE__);
     369                 :          0 :                 goto fail;
     370                 :            :         }
     371                 :            : 
     372                 :          2 :         rte_malloc_dump_stats(stdout, NULL);
     373                 :          2 :         rte_malloc_dump_heaps(stdout);
     374                 :            : 
     375                 :            :         /* free memory - removing it should now succeed */
     376                 :          2 :         rte_free(ptr);
     377                 :            :         ptr = NULL;
     378                 :            : 
     379                 :          2 :         rte_memzone_free(mz);
     380                 :            :         mz = NULL;
     381                 :          2 :         rte_memzone_free(contig_mz);
     382                 :            :         contig_mz = NULL;
     383                 :            : 
     384         [ -  + ]:          2 :         if (rte_malloc_heap_memory_remove(heap_name, addr, len) != 0) {
     385                 :            :                 printf("%s():%i: Removing memory from heap failed\n",
     386                 :            :                         __func__, __LINE__);
     387                 :          0 :                 goto fail;
     388                 :            :         }
     389         [ -  + ]:          2 :         if (rte_malloc_heap_destroy(heap_name) != 0) {
     390                 :            :                 printf("%s():%i: Destroying heap failed\n",
     391                 :            :                         __func__, __LINE__);
     392                 :          0 :                 goto fail;
     393                 :            :         }
     394                 :            : 
     395                 :            :         return 0;
     396                 :          0 : fail:
     397                 :          0 :         rte_memzone_free(contig_mz);
     398                 :          0 :         rte_memzone_free(mz);
     399                 :          0 :         rte_free(ptr);
     400                 :            :         /* even if something failed, attempt to clean up */
     401                 :          0 :         rte_malloc_heap_memory_remove(heap_name, addr, len);
     402                 :          0 :         rte_malloc_heap_destroy(heap_name);
     403                 :            : 
     404                 :          0 :         return -1;
     405                 :            : }
     406                 :            : 
     407                 :            : static int
     408                 :          2 : test_extmem_invalid_param(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
     409                 :            :                 int n_pages)
     410                 :            : {
     411                 :            :         /* these calls may fail for other reasons, so check errno */
     412         [ +  - ]:          2 :         if (rte_extmem_unregister(addr, len) >= 0 ||
     413         [ -  + ]:          2 :                         rte_errno != ENOENT) {
     414                 :            :                 printf("%s():%i: Unregistered non-existent memory\n",
     415                 :            :                         __func__, __LINE__);
     416                 :          0 :                 return -1;
     417                 :            :         }
     418                 :            : 
     419         [ +  - ]:          2 :         if (rte_extmem_attach(addr, len) >= 0 ||
     420         [ -  + ]:          2 :                         rte_errno != ENOENT) {
     421                 :            :                 printf("%s():%i: Attached to non-existent memory\n",
     422                 :            :                         __func__, __LINE__);
     423                 :          0 :                 return -1;
     424                 :            :         }
     425         [ +  - ]:          2 :         if (rte_extmem_attach(addr, len) >= 0 ||
     426         [ -  + ]:          2 :                         rte_errno != ENOENT) {
     427                 :            :                 printf("%s():%i: Detached from non-existent memory\n",
     428                 :            :                         __func__, __LINE__);
     429                 :          0 :                 return -1;
     430                 :            :         }
     431                 :            : 
     432                 :            :         /* zero length */
     433         [ +  - ]:          2 :         if (rte_extmem_register(addr, 0, NULL, 0, pgsz) >= 0 ||
     434         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     435                 :            :                 printf("%s():%i: Registered memory with invalid parameters\n",
     436                 :            :                         __func__, __LINE__);
     437                 :          0 :                 return -1;
     438                 :            :         }
     439                 :            : 
     440         [ +  - ]:          2 :         if (rte_extmem_unregister(addr, 0) >= 0 ||
     441         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     442                 :            :                 printf("%s():%i: Unregistered memory with invalid parameters\n",
     443                 :            :                         __func__, __LINE__);
     444                 :          0 :                 return -1;
     445                 :            :         }
     446                 :            : 
     447         [ +  - ]:          2 :         if (rte_extmem_attach(addr, 0) >= 0 ||
     448         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     449                 :            :                 printf("%s():%i: Attached memory with invalid parameters\n",
     450                 :            :                         __func__, __LINE__);
     451                 :          0 :                 return -1;
     452                 :            :         }
     453         [ +  - ]:          2 :         if (rte_extmem_attach(addr, 0) >= 0 ||
     454         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     455                 :            :                 printf("%s():%i: Detached memory with invalid parameters\n",
     456                 :            :                         __func__, __LINE__);
     457                 :          0 :                 return -1;
     458                 :            :         }
     459                 :            : 
     460                 :            :         /* zero address */
     461         [ +  - ]:          2 :         if (rte_extmem_register(NULL, len, NULL, 0, pgsz) >= 0 ||
     462         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     463                 :            :                 printf("%s():%i: Registered memory with invalid parameters\n",
     464                 :            :                         __func__, __LINE__);
     465                 :          0 :                 return -1;
     466                 :            :         }
     467                 :            : 
     468         [ +  - ]:          2 :         if (rte_extmem_unregister(NULL, len) >= 0 ||
     469         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     470                 :            :                 printf("%s():%i: Unregistered memory with invalid parameters\n",
     471                 :            :                         __func__, __LINE__);
     472                 :          0 :                 return -1;
     473                 :            :         }
     474                 :            : 
     475         [ +  - ]:          2 :         if (rte_extmem_attach(NULL, len) >= 0 ||
     476         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     477                 :            :                 printf("%s():%i: Attached memory with invalid parameters\n",
     478                 :            :                         __func__, __LINE__);
     479                 :          0 :                 return -1;
     480                 :            :         }
     481         [ +  - ]:          2 :         if (rte_extmem_attach(NULL, len) >= 0 ||
     482         [ -  + ]:          2 :                         rte_errno != EINVAL) {
     483                 :            :                 printf("%s():%i: Detached memory with invalid parameters\n",
     484                 :            :                         __func__, __LINE__);
     485                 :          0 :                 return -1;
     486                 :            :         }
     487                 :            : 
     488                 :            :         /* the following tests are only valid if IOVA table is not NULL */
     489         [ +  + ]:          2 :         if (iova != NULL) {
     490                 :            :                 /* wrong page count */
     491         [ +  - ]:          1 :                 if (rte_extmem_register(addr, len,
     492         [ -  + ]:          1 :                                 iova, 0, pgsz) >= 0 || rte_errno != EINVAL) {
     493                 :            :                         printf("%s():%i: Registered memory with invalid parameters\n",
     494                 :            :                                 __func__, __LINE__);
     495                 :          0 :                         return -1;
     496                 :            :                 }
     497         [ +  - ]:          1 :                 if (rte_extmem_register(addr, len,
     498                 :          1 :                                 iova, n_pages - 1, pgsz) >= 0 ||
     499         [ -  + ]:          1 :                                 rte_errno != EINVAL) {
     500                 :            :                         printf("%s():%i: Registered memory with invalid parameters\n",
     501                 :            :                                 __func__, __LINE__);
     502                 :          0 :                         return -1;
     503                 :            :                 }
     504         [ +  - ]:          1 :                 if (rte_extmem_register(addr, len,
     505                 :          1 :                                 iova, n_pages + 1, pgsz) >= 0 ||
     506         [ -  + ]:          1 :                                 rte_errno != EINVAL) {
     507                 :            :                         printf("%s():%i: Registered memory with invalid parameters\n",
     508                 :            :                                 __func__, __LINE__);
     509                 :          0 :                         return -1;
     510                 :            :                 }
     511                 :            :         }
     512                 :            : 
     513                 :            :         return 0;
     514                 :            : }
     515                 :            : 
     516                 :            : static int
     517                 :          2 : test_extmem_basic(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
     518                 :            :                 int n_pages)
     519                 :            : {
     520                 :            :         /* register memory */
     521         [ -  + ]:          2 :         if (rte_extmem_register(addr, len, iova, n_pages, pgsz) != 0) {
     522                 :            :                 printf("%s():%i: Failed to register memory\n",
     523                 :            :                         __func__, __LINE__);
     524                 :          0 :                 goto fail;
     525                 :            :         }
     526                 :            : 
     527                 :            :         /* check if memory is accessible from EAL */
     528         [ -  + ]:          2 :         if (check_mem(addr, iova, pgsz, n_pages) < 0)
     529                 :          0 :                 goto fail;
     530                 :            : 
     531         [ -  + ]:          2 :         if (rte_extmem_unregister(addr, len) != 0) {
     532                 :            :                 printf("%s():%i: Removing memory from heap failed\n",
     533                 :            :                         __func__, __LINE__);
     534                 :          0 :                 goto fail;
     535                 :            :         }
     536                 :            : 
     537                 :            :         return 0;
     538                 :          0 : fail:
     539                 :            :         /* even if something failed, attempt to clean up */
     540                 :          0 :         rte_extmem_unregister(addr, len);
     541                 :            : 
     542                 :          0 :         return -1;
     543                 :            : }
     544                 :            : 
     545                 :            : /* we need to test attach/detach in secondary processes. */
     546                 :            : static int
     547                 :          1 : test_external_mem(void)
     548                 :          1 : {
     549                 :          1 :         size_t pgsz = rte_mem_page_size();
     550                 :            :         size_t len = EXTERNAL_MEM_SZ;
     551                 :          1 :         rte_iova_t iova[len / pgsz];
     552                 :            :         void *addr;
     553                 :            :         int ret, n_pages;
     554                 :            :         int i;
     555                 :            : 
     556                 :            :         /* create external memory area */
     557                 :          1 :         n_pages = RTE_DIM(iova);
     558                 :          1 :         addr = mmap(NULL, len, PROT_WRITE | PROT_READ,
     559                 :            :                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
     560         [ -  + ]:          1 :         if (addr == MAP_FAILED) {
     561                 :            :                 printf("%s():%i: Failed to create dummy memory area\n",
     562                 :            :                         __func__, __LINE__);
     563                 :          0 :                 return -1;
     564                 :            :         }
     565         [ +  + ]:       1025 :         for (i = 0; i < n_pages; i++) {
     566                 :            :                 /* arbitrary IOVA */
     567                 :       1024 :                 rte_iova_t tmp = 0x100000000 + i * pgsz;
     568                 :       1024 :                 iova[i] = tmp;
     569                 :            :         }
     570                 :            : 
     571                 :            :         /* test external heap memory */
     572                 :          1 :         ret = test_malloc_invalid_param(addr, len, pgsz, iova, n_pages);
     573                 :          1 :         ret |= test_malloc_basic(addr, len, pgsz, iova, n_pages);
     574                 :            :         /* when iova table is NULL, everything should still work */
     575                 :          1 :         ret |= test_malloc_invalid_param(addr, len, pgsz, NULL, n_pages);
     576                 :          1 :         ret |= test_malloc_basic(addr, len, pgsz, NULL, n_pages);
     577                 :            : 
     578                 :            :         /* test non-heap memory */
     579                 :          1 :         ret |= test_extmem_invalid_param(addr, len, pgsz, iova, n_pages);
     580                 :          1 :         ret |= test_extmem_basic(addr, len, pgsz, iova, n_pages);
     581                 :            :         /* when iova table is NULL, everything should still work */
     582                 :          1 :         ret |= test_extmem_invalid_param(addr, len, pgsz, NULL, n_pages);
     583                 :          1 :         ret |= test_extmem_basic(addr, len, pgsz, NULL, n_pages);
     584                 :            : 
     585                 :          1 :         munmap(addr, len);
     586                 :            : 
     587                 :          1 :         return ret;
     588                 :            : }
     589                 :            : 
     590                 :            : #endif /* !RTE_EXEC_ENV_WINDOWS */
     591                 :            : 
     592                 :        302 : REGISTER_FAST_TEST(external_mem_autotest, NOHUGE_SKIP, ASAN_OK, test_external_mem);

Generated by: LCOV version 1.14