LCOV - code coverage report
Current view: top level - app/test - test_external_mem.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 1 219 0.5 %
Date: 2025-01-02 22:41:34 Functions: 1 7 14.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 216 0.0 %

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

Generated by: LCOV version 1.14