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

Generated by: LCOV version 1.14