LCOV - code coverage report
Current view: top level - drivers/common/mlx5 - mlx5_malloc.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 68 0.0 %
Date: 2025-05-01 17:49:45 Functions: 0 8 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 54 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2020 Mellanox Technologies, Ltd
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <errno.h>
       6                 :            : #include <eal_export.h>
       7                 :            : #include <rte_malloc.h>
       8                 :            : #include <malloc.h>
       9                 :            : #include <stdbool.h>
      10                 :            : #include <string.h>
      11                 :            : 
      12                 :            : #include "mlx5_common_log.h"
      13                 :            : #include "mlx5_common_os.h"
      14                 :            : #include "mlx5_malloc.h"
      15                 :            : 
      16                 :            : struct mlx5_sys_mem {
      17                 :            :         uint32_t init:1; /* Memory allocator initialized. */
      18                 :            :         uint32_t enable:1; /* System memory select. */
      19                 :            :         uint32_t reserve:30; /* Reserve. */
      20                 :            :         RTE_ATOMIC(struct rte_memseg_list *) last_msl;
      21                 :            :         /* last allocated rte memory memseg list. */
      22                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
      23                 :            :         uint64_t malloc_sys;
      24                 :            :         /* Memory allocated from system count. */
      25                 :            :         uint64_t malloc_rte;
      26                 :            :         /* Memory allocated from hugepage count. */
      27                 :            :         uint64_t realloc_sys;
      28                 :            :         /* Memory reallocate from system count. */
      29                 :            :         uint64_t realloc_rte;
      30                 :            :         /* Memory reallocate from hugepage count. */
      31                 :            :         uint64_t free_sys;
      32                 :            :         /* Memory free to system count. */
      33                 :            :         uint64_t free_rte;
      34                 :            :         /* Memory free to hugepage count. */
      35                 :            :         uint64_t msl_miss;
      36                 :            :         /* MSL miss count. */
      37                 :            :         uint64_t msl_update;
      38                 :            :         /* MSL update count. */
      39                 :            : #endif
      40                 :            : };
      41                 :            : 
      42                 :            : /* Initialize default as not */
      43                 :            : static struct mlx5_sys_mem mlx5_sys_mem = {
      44                 :            :         .init = 0,
      45                 :            :         .enable = 0,
      46                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
      47                 :            :         .malloc_sys = 0,
      48                 :            :         .malloc_rte = 0,
      49                 :            :         .realloc_sys = 0,
      50                 :            :         .realloc_rte = 0,
      51                 :            :         .free_sys = 0,
      52                 :            :         .free_rte = 0,
      53                 :            :         .msl_miss = 0,
      54                 :            :         .msl_update = 0,
      55                 :            : #endif
      56                 :            : };
      57                 :            : 
      58                 :            : /**
      59                 :            :  * Check if the address belongs to memory seg list.
      60                 :            :  *
      61                 :            :  * @param addr
      62                 :            :  *   Memory address to be checked.
      63                 :            :  * @param msl
      64                 :            :  *   Memory seg list.
      65                 :            :  *
      66                 :            :  * @return
      67                 :            :  *   True if it belongs, false otherwise.
      68                 :            :  */
      69                 :            : static bool
      70                 :            : mlx5_mem_check_msl(void *addr, struct rte_memseg_list *msl)
      71                 :            : {
      72                 :            :         void *start, *end;
      73                 :            : 
      74                 :          0 :         if (!msl)
      75                 :            :                 return false;
      76                 :          0 :         start = msl->base_va;
      77                 :          0 :         end = RTE_PTR_ADD(start, msl->len);
      78   [ #  #  #  # ]:          0 :         if (addr >= start && addr < end)
      79                 :            :                 return true;
      80                 :            :         return false;
      81                 :            : }
      82                 :            : 
      83                 :            : /**
      84                 :            :  * Update the msl if memory belongs to new msl.
      85                 :            :  *
      86                 :            :  * @param addr
      87                 :            :  *   Memory address.
      88                 :            :  */
      89                 :            : static void
      90                 :          0 : mlx5_mem_update_msl(void *addr)
      91                 :            : {
      92                 :            :         /*
      93                 :            :          * Update the cache msl if the new addr comes from the new msl
      94                 :            :          * different with the cached msl.
      95                 :            :          */
      96         [ #  # ]:          0 :         if (addr && !mlx5_mem_check_msl(addr,
      97         [ #  # ]:          0 :             (struct rte_memseg_list *)rte_atomic_load_explicit
      98                 :            :             (&mlx5_sys_mem.last_msl, rte_memory_order_relaxed))) {
      99                 :          0 :                 rte_atomic_store_explicit(&mlx5_sys_mem.last_msl,
     100                 :            :                         rte_mem_virt2memseg_list(addr),
     101                 :            :                         rte_memory_order_relaxed);
     102                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     103                 :            :                 rte_atomic_fetch_add_explicit(&mlx5_sys_mem.msl_update, 1,
     104                 :            :                                    rte_memory_order_relaxed);
     105                 :            : #endif
     106                 :            :         }
     107                 :          0 : }
     108                 :            : 
     109                 :            : /**
     110                 :            :  * Check if the address belongs to rte memory.
     111                 :            :  *
     112                 :            :  * @param addr
     113                 :            :  *   Memory address to be checked.
     114                 :            :  *
     115                 :            :  * @return
     116                 :            :  *   True if it belongs, false otherwise.
     117                 :            :  */
     118                 :            : static bool
     119                 :          0 : mlx5_mem_is_rte(void *addr)
     120                 :            : {
     121                 :            :         /*
     122                 :            :          * Check if the last cache msl matches. Drop to slow path
     123                 :            :          * to check if the memory belongs to rte memory.
     124                 :            :          */
     125                 :          0 :         if (!mlx5_mem_check_msl(addr, (struct rte_memseg_list *)
     126         [ #  # ]:          0 :             rte_atomic_load_explicit(&mlx5_sys_mem.last_msl, rte_memory_order_relaxed))) {
     127         [ #  # ]:          0 :                 if (!rte_mem_virt2memseg_list(addr))
     128                 :          0 :                         return false;
     129                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     130                 :            :                 rte_atomic_fetch_add_explicit(&mlx5_sys_mem.msl_miss, 1, rte_memory_order_relaxed);
     131                 :            : #endif
     132                 :            :         }
     133                 :            :         return true;
     134                 :            : }
     135                 :            : 
     136                 :            : /**
     137                 :            :  * Allocate memory with alignment.
     138                 :            :  *
     139                 :            :  * @param size
     140                 :            :  *   Memory size to be allocated.
     141                 :            :  * @param align
     142                 :            :  *   Memory alignment.
     143                 :            :  * @param zero
     144                 :            :  *   Clear the allocated memory or not.
     145                 :            :  *
     146                 :            :  * @return
     147                 :            :  *   Pointer of the allocated memory, NULL otherwise.
     148                 :            :  */
     149                 :            : static void *
     150                 :          0 : mlx5_alloc_align(size_t size, unsigned int align, unsigned int zero)
     151                 :            : {
     152                 :            :         void *buf;
     153                 :            : 
     154                 :          0 :         buf = mlx5_os_malloc(align, size);
     155         [ #  # ]:          0 :         if (!buf) {
     156                 :          0 :                 DRV_LOG(ERR, "Couldn't allocate buf size=%zu align=%u.",
     157                 :            :                         size, align);
     158                 :          0 :                 return NULL;
     159                 :            :         }
     160         [ #  # ]:          0 :         if (zero)
     161                 :            :                 memset(buf, 0, size);
     162                 :            :         return buf;
     163                 :            : }
     164                 :            : 
     165                 :            : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_malloc)
     166                 :            : void *
     167                 :          0 : mlx5_malloc(uint32_t flags, size_t size, unsigned int align, int socket)
     168                 :            : {
     169                 :            :         void *addr;
     170                 :            :         bool rte_mem;
     171                 :            : 
     172                 :            :         /*
     173                 :            :          * If neither system memory nor rte memory is required, allocate
     174                 :            :          * memory according to mlx5_sys_mem.enable.
     175                 :            :          */
     176         [ #  # ]:          0 :         if (flags & MLX5_MEM_RTE)
     177                 :            :                 rte_mem = true;
     178         [ #  # ]:          0 :         else if (flags & MLX5_MEM_SYS)
     179                 :            :                 rte_mem = false;
     180                 :            :         else
     181                 :          0 :                 rte_mem = mlx5_sys_mem.enable ? false : true;
     182         [ #  # ]:          0 :         if (rte_mem) {
     183         [ #  # ]:          0 :                 if (flags & MLX5_MEM_ZERO)
     184                 :          0 :                         addr = rte_zmalloc_socket(NULL, size, align, socket);
     185                 :            :                 else
     186                 :          0 :                         addr = rte_malloc_socket(NULL, size, align, socket);
     187                 :          0 :                 mlx5_mem_update_msl(addr);
     188                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     189                 :            :                 if (addr)
     190                 :            :                         rte_atomic_fetch_add_explicit(&mlx5_sys_mem.malloc_rte, 1,
     191                 :            :                                            rte_memory_order_relaxed);
     192                 :            : #endif
     193                 :          0 :                 return addr;
     194                 :            :         }
     195                 :            :         /* The memory will be allocated from system. */
     196         [ #  # ]:          0 :         if (align > MLX5_MALLOC_ALIGNMENT)
     197                 :          0 :                 addr = mlx5_alloc_align(size, align, !!(flags & MLX5_MEM_ZERO));
     198         [ #  # ]:          0 :         else if (flags & MLX5_MEM_ZERO)
     199                 :          0 :                 addr = calloc(1, size);
     200                 :            :         else
     201                 :          0 :                 addr = malloc(size);
     202                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     203                 :            :         if (addr)
     204                 :            :                 rte_atomic_fetch_add_explicit(&mlx5_sys_mem.malloc_sys, 1,
     205                 :            :                                    rte_memory_order_relaxed);
     206                 :            : #endif
     207                 :            :         return addr;
     208                 :            : }
     209                 :            : 
     210                 :            : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_realloc)
     211                 :            : void *
     212                 :          0 : mlx5_realloc(void *addr, uint32_t flags, size_t size, unsigned int align,
     213                 :            :              int socket)
     214                 :            : {
     215                 :            :         void *new_addr;
     216                 :            :         bool rte_mem;
     217                 :            : 
     218                 :            :         /* Allocate directly if old memory address is NULL. */
     219         [ #  # ]:          0 :         if (!addr)
     220                 :          0 :                 return mlx5_malloc(flags, size, align, socket);
     221                 :            :         /* Get the memory type. */
     222         [ #  # ]:          0 :         if (flags & MLX5_MEM_RTE)
     223                 :            :                 rte_mem = true;
     224         [ #  # ]:          0 :         else if (flags & MLX5_MEM_SYS)
     225                 :            :                 rte_mem = false;
     226                 :            :         else
     227                 :          0 :                 rte_mem = mlx5_sys_mem.enable ? false : true;
     228                 :            :         /* Check if old memory and to be allocated memory are the same type. */
     229         [ #  # ]:          0 :         if (rte_mem != mlx5_mem_is_rte(addr)) {
     230                 :          0 :                 DRV_LOG(ERR, "Couldn't reallocate to different memory type.");
     231                 :          0 :                 return NULL;
     232                 :            :         }
     233                 :            :         /* Allocate memory from rte memory. */
     234         [ #  # ]:          0 :         if (rte_mem) {
     235                 :          0 :                 new_addr = rte_realloc_socket(addr, size, align, socket);
     236                 :          0 :                 mlx5_mem_update_msl(new_addr);
     237                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     238                 :            :                 if (new_addr)
     239                 :            :                         rte_atomic_fetch_add_explicit(&mlx5_sys_mem.realloc_rte, 1,
     240                 :            :                                            rte_memory_order_relaxed);
     241                 :            : #endif
     242                 :          0 :                 return new_addr;
     243                 :            :         }
     244                 :            :         /* Align is not supported for system memory. */
     245         [ #  # ]:          0 :         if (align) {
     246                 :          0 :                 DRV_LOG(ERR, "Couldn't reallocate with alignment");
     247                 :          0 :                 return NULL;
     248                 :            :         }
     249                 :          0 :         new_addr = realloc(addr, size);
     250                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     251                 :            :         if (new_addr)
     252                 :            :                 rte_atomic_fetch_add_explicit(&mlx5_sys_mem.realloc_sys, 1,
     253                 :            :                                    rte_memory_order_relaxed);
     254                 :            : #endif
     255                 :          0 :         return new_addr;
     256                 :            : }
     257                 :            : 
     258                 :            : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_free)
     259                 :            : void
     260                 :          0 : mlx5_free(void *addr)
     261                 :            : {
     262         [ #  # ]:          0 :         if (addr == NULL)
     263                 :            :                 return;
     264         [ #  # ]:          0 :         if (!mlx5_mem_is_rte(addr)) {
     265                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     266                 :            :                 rte_atomic_fetch_add_explicit(&mlx5_sys_mem.free_sys, 1,
     267                 :            :                                    rte_memory_order_relaxed);
     268                 :            : #endif
     269                 :            :                 mlx5_os_free(addr);
     270                 :            :         } else {
     271                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     272                 :            :                 rte_atomic_fetch_add_explicit(&mlx5_sys_mem.free_rte, 1,
     273                 :            :                                    rte_memory_order_relaxed);
     274                 :            : #endif
     275                 :          0 :                 rte_free(addr);
     276                 :            :         }
     277                 :            : }
     278                 :            : 
     279                 :            : RTE_EXPORT_INTERNAL_SYMBOL(mlx5_memory_stat_dump)
     280                 :            : void
     281                 :          0 : mlx5_memory_stat_dump(void)
     282                 :            : {
     283                 :            : #ifdef RTE_LIBRTE_MLX5_DEBUG
     284                 :            :         DRV_LOG(INFO, "System memory malloc:%"PRIi64", realloc:%"PRIi64","
     285                 :            :                 " free:%"PRIi64"\nRTE memory malloc:%"PRIi64","
     286                 :            :                 " realloc:%"PRIi64", free:%"PRIi64"\nMSL miss:%"PRIi64","
     287                 :            :                 " update:%"PRIi64"",
     288                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.malloc_sys, rte_memory_order_relaxed),
     289                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.realloc_sys, rte_memory_order_relaxed),
     290                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.free_sys, rte_memory_order_relaxed),
     291                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.malloc_rte, rte_memory_order_relaxed),
     292                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.realloc_rte, rte_memory_order_relaxed),
     293                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.free_rte, rte_memory_order_relaxed),
     294                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.msl_miss, rte_memory_order_relaxed),
     295                 :            :                 rte_atomic_load_explicit(&mlx5_sys_mem.msl_update, rte_memory_order_relaxed));
     296                 :            : #endif
     297                 :          0 : }
     298                 :            : 
     299                 :            : void
     300                 :          0 : mlx5_malloc_mem_select(uint32_t sys_mem_en)
     301                 :            : {
     302                 :            :         /*
     303                 :            :          * The initialization should be called only once and all devices
     304                 :            :          * should use the same memory type. Otherwise, when new device is
     305                 :            :          * being attached with some different memory allocation configuration,
     306                 :            :          * the memory will get wrong behavior or a failure will be raised.
     307                 :            :          */
     308         [ #  # ]:          0 :         if (!mlx5_sys_mem.init) {
     309         [ #  # ]:          0 :                 if (sys_mem_en)
     310                 :          0 :                         mlx5_sys_mem.enable = 1;
     311                 :          0 :                 mlx5_sys_mem.init = 1;
     312         [ #  # ]:          0 :                 DRV_LOG(INFO, "%s is selected.", sys_mem_en ? "SYS_MEM" : "RTE_MEM");
     313         [ #  # ]:          0 :         } else if (mlx5_sys_mem.enable != sys_mem_en) {
     314         [ #  # ]:          0 :                 DRV_LOG(WARNING, "%s is already selected.",
     315                 :            :                         mlx5_sys_mem.enable ? "SYS_MEM" : "RTE_MEM");
     316                 :            :         }
     317                 :          0 : }

Generated by: LCOV version 1.14