199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <stdio.h> 699a2dd95SBruce Richardson #include <stdint.h> 799a2dd95SBruce Richardson #include <inttypes.h> 899a2dd95SBruce Richardson #include <string.h> 999a2dd95SBruce Richardson #include <errno.h> 1099a2dd95SBruce Richardson 1145a685caSAnkur Dwivedi #include <eal_trace_internal.h> 1299a2dd95SBruce Richardson #include <rte_log.h> 1399a2dd95SBruce Richardson #include <rte_memory.h> 1499a2dd95SBruce Richardson #include <rte_memzone.h> 1599a2dd95SBruce Richardson #include <rte_eal.h> 1699a2dd95SBruce Richardson #include <rte_errno.h> 1799a2dd95SBruce Richardson #include <rte_string_fns.h> 1899a2dd95SBruce Richardson #include <rte_common.h> 1999a2dd95SBruce Richardson 2099a2dd95SBruce Richardson #include "malloc_heap.h" 2199a2dd95SBruce Richardson #include "malloc_elem.h" 2299a2dd95SBruce Richardson #include "eal_private.h" 2399a2dd95SBruce Richardson #include "eal_memcfg.h" 2499a2dd95SBruce Richardson 2538689022SOphir Munk /* Default count used until rte_memzone_max_set() is called */ 2638689022SOphir Munk #define DEFAULT_MAX_MEMZONE_COUNT 2560 2738689022SOphir Munk 2838689022SOphir Munk int 2938689022SOphir Munk rte_memzone_max_set(size_t max) 3038689022SOphir Munk { 3138689022SOphir Munk struct rte_mem_config *mcfg; 3238689022SOphir Munk 3338689022SOphir Munk if (eal_get_internal_configuration()->init_complete > 0) { 34ae67895bSDavid Marchand EAL_LOG(ERR, "Max memzone cannot be set after EAL init"); 3538689022SOphir Munk return -1; 3638689022SOphir Munk } 3738689022SOphir Munk 3838689022SOphir Munk mcfg = rte_eal_get_configuration()->mem_config; 3938689022SOphir Munk if (mcfg == NULL) { 40ae67895bSDavid Marchand EAL_LOG(ERR, "Failed to set max memzone count"); 4138689022SOphir Munk return -1; 4238689022SOphir Munk } 4338689022SOphir Munk 4438689022SOphir Munk mcfg->max_memzone = max; 4538689022SOphir Munk 4638689022SOphir Munk return 0; 4738689022SOphir Munk } 4838689022SOphir Munk 4938689022SOphir Munk size_t 5038689022SOphir Munk rte_memzone_max_get(void) 5138689022SOphir Munk { 5238689022SOphir Munk struct rte_mem_config *mcfg; 5338689022SOphir Munk 5438689022SOphir Munk mcfg = rte_eal_get_configuration()->mem_config; 5538689022SOphir Munk if (mcfg == NULL || mcfg->max_memzone == 0) 5638689022SOphir Munk return DEFAULT_MAX_MEMZONE_COUNT; 5738689022SOphir Munk 5838689022SOphir Munk return mcfg->max_memzone; 5938689022SOphir Munk } 6038689022SOphir Munk 6199a2dd95SBruce Richardson static inline const struct rte_memzone * 6299a2dd95SBruce Richardson memzone_lookup_thread_unsafe(const char *name) 6399a2dd95SBruce Richardson { 6499a2dd95SBruce Richardson struct rte_mem_config *mcfg; 6599a2dd95SBruce Richardson struct rte_fbarray *arr; 6699a2dd95SBruce Richardson const struct rte_memzone *mz; 6799a2dd95SBruce Richardson int i = 0; 6899a2dd95SBruce Richardson 6999a2dd95SBruce Richardson /* get pointer to global configuration */ 7099a2dd95SBruce Richardson mcfg = rte_eal_get_configuration()->mem_config; 7199a2dd95SBruce Richardson arr = &mcfg->memzones; 7299a2dd95SBruce Richardson 7399a2dd95SBruce Richardson /* 7499a2dd95SBruce Richardson * the algorithm is not optimal (linear), but there are few 7599a2dd95SBruce Richardson * zones and this function should be called at init only 7699a2dd95SBruce Richardson */ 7799a2dd95SBruce Richardson i = rte_fbarray_find_next_used(arr, 0); 7899a2dd95SBruce Richardson while (i >= 0) { 7999a2dd95SBruce Richardson mz = rte_fbarray_get(arr, i); 8099a2dd95SBruce Richardson if (mz->addr != NULL && 8199a2dd95SBruce Richardson !strncmp(name, mz->name, RTE_MEMZONE_NAMESIZE)) 8299a2dd95SBruce Richardson return mz; 8399a2dd95SBruce Richardson i = rte_fbarray_find_next_used(arr, i + 1); 8499a2dd95SBruce Richardson } 8599a2dd95SBruce Richardson return NULL; 8699a2dd95SBruce Richardson } 8799a2dd95SBruce Richardson 88bc1a35fbSDavid Marchand #define MEMZONE_KNOWN_FLAGS (RTE_MEMZONE_2MB \ 89bc1a35fbSDavid Marchand | RTE_MEMZONE_1GB \ 90bc1a35fbSDavid Marchand | RTE_MEMZONE_16MB \ 91bc1a35fbSDavid Marchand | RTE_MEMZONE_16GB \ 92bc1a35fbSDavid Marchand | RTE_MEMZONE_256KB \ 93bc1a35fbSDavid Marchand | RTE_MEMZONE_256MB \ 94bc1a35fbSDavid Marchand | RTE_MEMZONE_512MB \ 95bc1a35fbSDavid Marchand | RTE_MEMZONE_4GB \ 96bc1a35fbSDavid Marchand | RTE_MEMZONE_SIZE_HINT_ONLY \ 97bc1a35fbSDavid Marchand | RTE_MEMZONE_IOVA_CONTIG \ 98bc1a35fbSDavid Marchand ) 99bc1a35fbSDavid Marchand 10099a2dd95SBruce Richardson static const struct rte_memzone * 10199a2dd95SBruce Richardson memzone_reserve_aligned_thread_unsafe(const char *name, size_t len, 10299a2dd95SBruce Richardson int socket_id, unsigned int flags, unsigned int align, 10399a2dd95SBruce Richardson unsigned int bound) 10499a2dd95SBruce Richardson { 10599a2dd95SBruce Richardson struct rte_memzone *mz; 10699a2dd95SBruce Richardson struct rte_mem_config *mcfg; 10799a2dd95SBruce Richardson struct rte_fbarray *arr; 10899a2dd95SBruce Richardson void *mz_addr; 10999a2dd95SBruce Richardson size_t requested_len; 11099a2dd95SBruce Richardson int mz_idx; 11199a2dd95SBruce Richardson bool contig; 11299a2dd95SBruce Richardson 11399a2dd95SBruce Richardson /* get pointer to global configuration */ 11499a2dd95SBruce Richardson mcfg = rte_eal_get_configuration()->mem_config; 11599a2dd95SBruce Richardson arr = &mcfg->memzones; 11699a2dd95SBruce Richardson 11799a2dd95SBruce Richardson /* no more room in config */ 11899a2dd95SBruce Richardson if (arr->count >= arr->len) { 119ae67895bSDavid Marchand EAL_LOG(ERR, 12038689022SOphir Munk "%s(): Number of requested memzone segments exceeds maximum " 121ae67895bSDavid Marchand "%u", __func__, arr->len); 12238689022SOphir Munk 12399a2dd95SBruce Richardson rte_errno = ENOSPC; 12499a2dd95SBruce Richardson return NULL; 12599a2dd95SBruce Richardson } 12699a2dd95SBruce Richardson 12799a2dd95SBruce Richardson if (strlen(name) > sizeof(mz->name) - 1) { 128ae67895bSDavid Marchand EAL_LOG(DEBUG, "%s(): memzone <%s>: name too long", 12999a2dd95SBruce Richardson __func__, name); 13099a2dd95SBruce Richardson rte_errno = ENAMETOOLONG; 13199a2dd95SBruce Richardson return NULL; 13299a2dd95SBruce Richardson } 13399a2dd95SBruce Richardson 13499a2dd95SBruce Richardson /* zone already exist */ 13599a2dd95SBruce Richardson if ((memzone_lookup_thread_unsafe(name)) != NULL) { 136ae67895bSDavid Marchand EAL_LOG(DEBUG, "%s(): memzone <%s> already exists", 13799a2dd95SBruce Richardson __func__, name); 13899a2dd95SBruce Richardson rte_errno = EEXIST; 13999a2dd95SBruce Richardson return NULL; 14099a2dd95SBruce Richardson } 14199a2dd95SBruce Richardson 14299a2dd95SBruce Richardson /* if alignment is not a power of two */ 14399a2dd95SBruce Richardson if (align && !rte_is_power_of_2(align)) { 144ae67895bSDavid Marchand EAL_LOG(ERR, "%s(): Invalid alignment: %u", __func__, 14599a2dd95SBruce Richardson align); 14699a2dd95SBruce Richardson rte_errno = EINVAL; 14799a2dd95SBruce Richardson return NULL; 14899a2dd95SBruce Richardson } 14999a2dd95SBruce Richardson 15099a2dd95SBruce Richardson /* alignment less than cache size is not allowed */ 15199a2dd95SBruce Richardson if (align < RTE_CACHE_LINE_SIZE) 15299a2dd95SBruce Richardson align = RTE_CACHE_LINE_SIZE; 15399a2dd95SBruce Richardson 15499a2dd95SBruce Richardson /* align length on cache boundary. Check for overflow before doing so */ 15599a2dd95SBruce Richardson if (len > SIZE_MAX - RTE_CACHE_LINE_MASK) { 15699a2dd95SBruce Richardson rte_errno = EINVAL; /* requested size too big */ 15799a2dd95SBruce Richardson return NULL; 15899a2dd95SBruce Richardson } 15999a2dd95SBruce Richardson 16099a2dd95SBruce Richardson len = RTE_ALIGN_CEIL(len, RTE_CACHE_LINE_SIZE); 16199a2dd95SBruce Richardson 16299a2dd95SBruce Richardson /* save minimal requested length */ 16399a2dd95SBruce Richardson requested_len = RTE_MAX((size_t)RTE_CACHE_LINE_SIZE, len); 16499a2dd95SBruce Richardson 16599a2dd95SBruce Richardson /* check that boundary condition is valid */ 16699a2dd95SBruce Richardson if (bound != 0 && (requested_len > bound || !rte_is_power_of_2(bound))) { 16799a2dd95SBruce Richardson rte_errno = EINVAL; 16899a2dd95SBruce Richardson return NULL; 16999a2dd95SBruce Richardson } 17099a2dd95SBruce Richardson 17199a2dd95SBruce Richardson if ((socket_id != SOCKET_ID_ANY) && socket_id < 0) { 17299a2dd95SBruce Richardson rte_errno = EINVAL; 17399a2dd95SBruce Richardson return NULL; 17499a2dd95SBruce Richardson } 17599a2dd95SBruce Richardson 176bc1a35fbSDavid Marchand if ((flags & ~MEMZONE_KNOWN_FLAGS) != 0) { 177bc1a35fbSDavid Marchand rte_errno = EINVAL; 178bc1a35fbSDavid Marchand return NULL; 179bc1a35fbSDavid Marchand } 180bc1a35fbSDavid Marchand 18199a2dd95SBruce Richardson /* only set socket to SOCKET_ID_ANY if we aren't allocating for an 18299a2dd95SBruce Richardson * external heap. 18399a2dd95SBruce Richardson */ 18499a2dd95SBruce Richardson if (!rte_eal_has_hugepages() && socket_id < RTE_MAX_NUMA_NODES) 18599a2dd95SBruce Richardson socket_id = SOCKET_ID_ANY; 18699a2dd95SBruce Richardson 18799a2dd95SBruce Richardson contig = (flags & RTE_MEMZONE_IOVA_CONTIG) != 0; 18899a2dd95SBruce Richardson /* malloc only cares about size flags, remove contig flag from flags */ 18999a2dd95SBruce Richardson flags &= ~RTE_MEMZONE_IOVA_CONTIG; 19099a2dd95SBruce Richardson 19199a2dd95SBruce Richardson if (len == 0 && bound == 0) { 19299a2dd95SBruce Richardson /* no size constraints were placed, so use malloc elem len */ 19399a2dd95SBruce Richardson requested_len = 0; 19462ea63a6SStephen Hemminger mz_addr = malloc_heap_alloc_biggest(socket_id, flags, align, contig); 19599a2dd95SBruce Richardson } else { 19699a2dd95SBruce Richardson if (len == 0) 19799a2dd95SBruce Richardson requested_len = bound; 19899a2dd95SBruce Richardson /* allocate memory on heap */ 19962ea63a6SStephen Hemminger mz_addr = malloc_heap_alloc(requested_len, socket_id, flags, align, bound, contig); 20099a2dd95SBruce Richardson } 20199a2dd95SBruce Richardson if (mz_addr == NULL) { 20299a2dd95SBruce Richardson rte_errno = ENOMEM; 20399a2dd95SBruce Richardson return NULL; 20499a2dd95SBruce Richardson } 20599a2dd95SBruce Richardson 20699a2dd95SBruce Richardson struct malloc_elem *elem = malloc_elem_from_data(mz_addr); 20799a2dd95SBruce Richardson 20899a2dd95SBruce Richardson /* fill the zone in config */ 20999a2dd95SBruce Richardson mz_idx = rte_fbarray_find_next_free(arr, 0); 21099a2dd95SBruce Richardson 21199a2dd95SBruce Richardson if (mz_idx < 0) { 21299a2dd95SBruce Richardson mz = NULL; 21399a2dd95SBruce Richardson } else { 21499a2dd95SBruce Richardson rte_fbarray_set_used(arr, mz_idx); 21599a2dd95SBruce Richardson mz = rte_fbarray_get(arr, mz_idx); 21699a2dd95SBruce Richardson } 21799a2dd95SBruce Richardson 21899a2dd95SBruce Richardson if (mz == NULL) { 219ae67895bSDavid Marchand EAL_LOG(ERR, "%s(): Cannot find free memzone", __func__); 22099a2dd95SBruce Richardson malloc_heap_free(elem); 22199a2dd95SBruce Richardson rte_errno = ENOSPC; 22299a2dd95SBruce Richardson return NULL; 22399a2dd95SBruce Richardson } 22499a2dd95SBruce Richardson 22599a2dd95SBruce Richardson strlcpy(mz->name, name, sizeof(mz->name)); 22699a2dd95SBruce Richardson mz->iova = rte_malloc_virt2iova(mz_addr); 22799a2dd95SBruce Richardson mz->addr = mz_addr; 22899a2dd95SBruce Richardson mz->len = requested_len == 0 ? 22999a2dd95SBruce Richardson elem->size - elem->pad - MALLOC_ELEM_OVERHEAD : 23099a2dd95SBruce Richardson requested_len; 23199a2dd95SBruce Richardson mz->hugepage_sz = elem->msl->page_sz; 23299a2dd95SBruce Richardson mz->socket_id = elem->msl->socket_id; 23399a2dd95SBruce Richardson mz->flags = 0; 23499a2dd95SBruce Richardson 23599a2dd95SBruce Richardson return mz; 23699a2dd95SBruce Richardson } 23799a2dd95SBruce Richardson 23899a2dd95SBruce Richardson static const struct rte_memzone * 23999a2dd95SBruce Richardson rte_memzone_reserve_thread_safe(const char *name, size_t len, int socket_id, 24099a2dd95SBruce Richardson unsigned int flags, unsigned int align, unsigned int bound) 24199a2dd95SBruce Richardson { 24299a2dd95SBruce Richardson struct rte_mem_config *mcfg; 24399a2dd95SBruce Richardson const struct rte_memzone *mz = NULL; 24499a2dd95SBruce Richardson 24599a2dd95SBruce Richardson /* get pointer to global configuration */ 24699a2dd95SBruce Richardson mcfg = rte_eal_get_configuration()->mem_config; 24799a2dd95SBruce Richardson 24899a2dd95SBruce Richardson rte_rwlock_write_lock(&mcfg->mlock); 24999a2dd95SBruce Richardson 25099a2dd95SBruce Richardson mz = memzone_reserve_aligned_thread_unsafe( 25199a2dd95SBruce Richardson name, len, socket_id, flags, align, bound); 25299a2dd95SBruce Richardson 25399a2dd95SBruce Richardson rte_eal_trace_memzone_reserve(name, len, socket_id, flags, align, 25499a2dd95SBruce Richardson bound, mz); 25599a2dd95SBruce Richardson 25699a2dd95SBruce Richardson rte_rwlock_write_unlock(&mcfg->mlock); 25799a2dd95SBruce Richardson 25899a2dd95SBruce Richardson return mz; 25999a2dd95SBruce Richardson } 26099a2dd95SBruce Richardson 26199a2dd95SBruce Richardson /* 26299a2dd95SBruce Richardson * Return a pointer to a correctly filled memzone descriptor (with a 26399a2dd95SBruce Richardson * specified alignment and boundary). If the allocation cannot be done, 26499a2dd95SBruce Richardson * return NULL. 26599a2dd95SBruce Richardson */ 26699a2dd95SBruce Richardson const struct rte_memzone * 26799a2dd95SBruce Richardson rte_memzone_reserve_bounded(const char *name, size_t len, int socket_id, 26899a2dd95SBruce Richardson unsigned flags, unsigned align, unsigned bound) 26999a2dd95SBruce Richardson { 27099a2dd95SBruce Richardson return rte_memzone_reserve_thread_safe(name, len, socket_id, flags, 27199a2dd95SBruce Richardson align, bound); 27299a2dd95SBruce Richardson } 27399a2dd95SBruce Richardson 27499a2dd95SBruce Richardson /* 27599a2dd95SBruce Richardson * Return a pointer to a correctly filled memzone descriptor (with a 27699a2dd95SBruce Richardson * specified alignment). If the allocation cannot be done, return NULL. 27799a2dd95SBruce Richardson */ 27899a2dd95SBruce Richardson const struct rte_memzone * 27999a2dd95SBruce Richardson rte_memzone_reserve_aligned(const char *name, size_t len, int socket_id, 28099a2dd95SBruce Richardson unsigned flags, unsigned align) 28199a2dd95SBruce Richardson { 28299a2dd95SBruce Richardson return rte_memzone_reserve_thread_safe(name, len, socket_id, flags, 28399a2dd95SBruce Richardson align, 0); 28499a2dd95SBruce Richardson } 28599a2dd95SBruce Richardson 28699a2dd95SBruce Richardson /* 28799a2dd95SBruce Richardson * Return a pointer to a correctly filled memzone descriptor. If the 28899a2dd95SBruce Richardson * allocation cannot be done, return NULL. 28999a2dd95SBruce Richardson */ 29099a2dd95SBruce Richardson const struct rte_memzone * 29199a2dd95SBruce Richardson rte_memzone_reserve(const char *name, size_t len, int socket_id, 29299a2dd95SBruce Richardson unsigned flags) 29399a2dd95SBruce Richardson { 29499a2dd95SBruce Richardson return rte_memzone_reserve_thread_safe(name, len, socket_id, 29599a2dd95SBruce Richardson flags, RTE_CACHE_LINE_SIZE, 0); 29699a2dd95SBruce Richardson } 29799a2dd95SBruce Richardson 29899a2dd95SBruce Richardson int 29999a2dd95SBruce Richardson rte_memzone_free(const struct rte_memzone *mz) 30099a2dd95SBruce Richardson { 30199a2dd95SBruce Richardson char name[RTE_MEMZONE_NAMESIZE]; 30299a2dd95SBruce Richardson struct rte_mem_config *mcfg; 30399a2dd95SBruce Richardson struct rte_fbarray *arr; 30499a2dd95SBruce Richardson struct rte_memzone *found_mz; 30599a2dd95SBruce Richardson int ret = 0; 30699a2dd95SBruce Richardson void *addr = NULL; 30799a2dd95SBruce Richardson unsigned idx; 30899a2dd95SBruce Richardson 30999a2dd95SBruce Richardson if (mz == NULL) 31099a2dd95SBruce Richardson return -EINVAL; 31199a2dd95SBruce Richardson 31299a2dd95SBruce Richardson rte_strlcpy(name, mz->name, RTE_MEMZONE_NAMESIZE); 31399a2dd95SBruce Richardson mcfg = rte_eal_get_configuration()->mem_config; 31499a2dd95SBruce Richardson arr = &mcfg->memzones; 31599a2dd95SBruce Richardson 31699a2dd95SBruce Richardson rte_rwlock_write_lock(&mcfg->mlock); 31799a2dd95SBruce Richardson 31899a2dd95SBruce Richardson idx = rte_fbarray_find_idx(arr, mz); 31999a2dd95SBruce Richardson found_mz = rte_fbarray_get(arr, idx); 32099a2dd95SBruce Richardson 32199a2dd95SBruce Richardson if (found_mz == NULL) { 32299a2dd95SBruce Richardson ret = -EINVAL; 32399a2dd95SBruce Richardson } else if (found_mz->addr == NULL) { 324ae67895bSDavid Marchand EAL_LOG(ERR, "Memzone is not allocated"); 32599a2dd95SBruce Richardson ret = -EINVAL; 32699a2dd95SBruce Richardson } else { 32799a2dd95SBruce Richardson addr = found_mz->addr; 32899a2dd95SBruce Richardson memset(found_mz, 0, sizeof(*found_mz)); 32999a2dd95SBruce Richardson rte_fbarray_set_free(arr, idx); 33099a2dd95SBruce Richardson } 33199a2dd95SBruce Richardson 33299a2dd95SBruce Richardson rte_rwlock_write_unlock(&mcfg->mlock); 33399a2dd95SBruce Richardson 334a306620eSStephen Hemminger rte_eal_trace_memzone_free(name, addr, ret); 335a306620eSStephen Hemminger 33699a2dd95SBruce Richardson rte_free(addr); 33799a2dd95SBruce Richardson 33899a2dd95SBruce Richardson return ret; 33999a2dd95SBruce Richardson } 34099a2dd95SBruce Richardson 34199a2dd95SBruce Richardson /* 34299a2dd95SBruce Richardson * Lookup for the memzone identified by the given name 34399a2dd95SBruce Richardson */ 34499a2dd95SBruce Richardson const struct rte_memzone * 34599a2dd95SBruce Richardson rte_memzone_lookup(const char *name) 34699a2dd95SBruce Richardson { 34799a2dd95SBruce Richardson struct rte_mem_config *mcfg; 34899a2dd95SBruce Richardson const struct rte_memzone *memzone = NULL; 34999a2dd95SBruce Richardson 35099a2dd95SBruce Richardson mcfg = rte_eal_get_configuration()->mem_config; 35199a2dd95SBruce Richardson 35299a2dd95SBruce Richardson rte_rwlock_read_lock(&mcfg->mlock); 35399a2dd95SBruce Richardson 35499a2dd95SBruce Richardson memzone = memzone_lookup_thread_unsafe(name); 35599a2dd95SBruce Richardson 35699a2dd95SBruce Richardson rte_rwlock_read_unlock(&mcfg->mlock); 35799a2dd95SBruce Richardson 35899a2dd95SBruce Richardson rte_eal_trace_memzone_lookup(name, memzone); 35999a2dd95SBruce Richardson return memzone; 36099a2dd95SBruce Richardson } 36199a2dd95SBruce Richardson 362*17bb6004SGagandeep Singh struct memzone_info { 363*17bb6004SGagandeep Singh FILE *f; 364*17bb6004SGagandeep Singh uint64_t total_size; 365*17bb6004SGagandeep Singh }; 366*17bb6004SGagandeep Singh 36799a2dd95SBruce Richardson static void 36899a2dd95SBruce Richardson dump_memzone(const struct rte_memzone *mz, void *arg) 36999a2dd95SBruce Richardson { 37099a2dd95SBruce Richardson struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; 37199a2dd95SBruce Richardson struct rte_memseg_list *msl = NULL; 372*17bb6004SGagandeep Singh struct memzone_info *info = arg; 37399a2dd95SBruce Richardson void *cur_addr, *mz_end; 37499a2dd95SBruce Richardson struct rte_memseg *ms; 37599a2dd95SBruce Richardson int mz_idx, ms_idx; 376*17bb6004SGagandeep Singh FILE *f = info->f; 37799a2dd95SBruce Richardson size_t page_sz; 37899a2dd95SBruce Richardson 37999a2dd95SBruce Richardson mz_idx = rte_fbarray_find_idx(&mcfg->memzones, mz); 380*17bb6004SGagandeep Singh info->total_size += mz->len; 38199a2dd95SBruce Richardson 38299a2dd95SBruce Richardson fprintf(f, "Zone %u: name:<%s>, len:0x%zx, virt:%p, " 38399a2dd95SBruce Richardson "socket_id:%"PRId32", flags:%"PRIx32"\n", 38499a2dd95SBruce Richardson mz_idx, 38599a2dd95SBruce Richardson mz->name, 38699a2dd95SBruce Richardson mz->len, 38799a2dd95SBruce Richardson mz->addr, 38899a2dd95SBruce Richardson mz->socket_id, 38999a2dd95SBruce Richardson mz->flags); 39099a2dd95SBruce Richardson 39199a2dd95SBruce Richardson /* go through each page occupied by this memzone */ 39299a2dd95SBruce Richardson msl = rte_mem_virt2memseg_list(mz->addr); 39399a2dd95SBruce Richardson if (!msl) { 394ae67895bSDavid Marchand EAL_LOG(DEBUG, "Skipping bad memzone"); 39599a2dd95SBruce Richardson return; 39699a2dd95SBruce Richardson } 39799a2dd95SBruce Richardson page_sz = (size_t)mz->hugepage_sz; 39899a2dd95SBruce Richardson cur_addr = RTE_PTR_ALIGN_FLOOR(mz->addr, page_sz); 39999a2dd95SBruce Richardson mz_end = RTE_PTR_ADD(cur_addr, mz->len); 40099a2dd95SBruce Richardson 40199a2dd95SBruce Richardson fprintf(f, "physical segments used:\n"); 40299a2dd95SBruce Richardson ms_idx = RTE_PTR_DIFF(mz->addr, msl->base_va) / page_sz; 40399a2dd95SBruce Richardson ms = rte_fbarray_get(&msl->memseg_arr, ms_idx); 40499a2dd95SBruce Richardson 40599a2dd95SBruce Richardson do { 40699a2dd95SBruce Richardson fprintf(f, " addr: %p iova: 0x%" PRIx64 " " 40799a2dd95SBruce Richardson "len: 0x%zx " 40899a2dd95SBruce Richardson "pagesz: 0x%zx\n", 40999a2dd95SBruce Richardson cur_addr, ms->iova, ms->len, page_sz); 41099a2dd95SBruce Richardson 41199a2dd95SBruce Richardson /* advance VA to next page */ 41299a2dd95SBruce Richardson cur_addr = RTE_PTR_ADD(cur_addr, page_sz); 41399a2dd95SBruce Richardson 41499a2dd95SBruce Richardson /* memzones occupy contiguous segments */ 41599a2dd95SBruce Richardson ++ms; 41699a2dd95SBruce Richardson } while (cur_addr < mz_end); 41799a2dd95SBruce Richardson } 41899a2dd95SBruce Richardson 41999a2dd95SBruce Richardson /* Dump all reserved memory zones on console */ 42099a2dd95SBruce Richardson void 42199a2dd95SBruce Richardson rte_memzone_dump(FILE *f) 42299a2dd95SBruce Richardson { 423*17bb6004SGagandeep Singh struct memzone_info info = { .f = f }; 424*17bb6004SGagandeep Singh 425*17bb6004SGagandeep Singh rte_memzone_walk(dump_memzone, &info); 426*17bb6004SGagandeep Singh fprintf(f, "Total Memory Zones size = %"PRIu64"M\n", 427*17bb6004SGagandeep Singh info.total_size / (1024 * 1024)); 42899a2dd95SBruce Richardson } 42999a2dd95SBruce Richardson 43099a2dd95SBruce Richardson /* 43199a2dd95SBruce Richardson * Init the memzone subsystem 43299a2dd95SBruce Richardson */ 43399a2dd95SBruce Richardson int 43499a2dd95SBruce Richardson rte_eal_memzone_init(void) 43599a2dd95SBruce Richardson { 43699a2dd95SBruce Richardson struct rte_mem_config *mcfg; 43799a2dd95SBruce Richardson int ret = 0; 43899a2dd95SBruce Richardson 43999a2dd95SBruce Richardson /* get pointer to global configuration */ 44099a2dd95SBruce Richardson mcfg = rte_eal_get_configuration()->mem_config; 44199a2dd95SBruce Richardson 44299a2dd95SBruce Richardson rte_rwlock_write_lock(&mcfg->mlock); 44399a2dd95SBruce Richardson 44499a2dd95SBruce Richardson if (rte_eal_process_type() == RTE_PROC_PRIMARY && 44599a2dd95SBruce Richardson rte_fbarray_init(&mcfg->memzones, "memzone", 44638689022SOphir Munk rte_memzone_max_get(), sizeof(struct rte_memzone))) { 447ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot allocate memzone list"); 44899a2dd95SBruce Richardson ret = -1; 44999a2dd95SBruce Richardson } else if (rte_eal_process_type() == RTE_PROC_SECONDARY && 45099a2dd95SBruce Richardson rte_fbarray_attach(&mcfg->memzones)) { 451ae67895bSDavid Marchand EAL_LOG(ERR, "Cannot attach to memzone list"); 45299a2dd95SBruce Richardson ret = -1; 45399a2dd95SBruce Richardson } 45499a2dd95SBruce Richardson 45599a2dd95SBruce Richardson rte_rwlock_write_unlock(&mcfg->mlock); 45699a2dd95SBruce Richardson 45799a2dd95SBruce Richardson return ret; 45899a2dd95SBruce Richardson } 45999a2dd95SBruce Richardson 46099a2dd95SBruce Richardson /* Walk all reserved memory zones */ 46199a2dd95SBruce Richardson void rte_memzone_walk(void (*func)(const struct rte_memzone *, void *), 46299a2dd95SBruce Richardson void *arg) 46399a2dd95SBruce Richardson { 46499a2dd95SBruce Richardson struct rte_mem_config *mcfg; 46599a2dd95SBruce Richardson struct rte_fbarray *arr; 46699a2dd95SBruce Richardson int i; 46799a2dd95SBruce Richardson 46899a2dd95SBruce Richardson mcfg = rte_eal_get_configuration()->mem_config; 46999a2dd95SBruce Richardson arr = &mcfg->memzones; 47099a2dd95SBruce Richardson 47199a2dd95SBruce Richardson rte_rwlock_read_lock(&mcfg->mlock); 47299a2dd95SBruce Richardson i = rte_fbarray_find_next_used(arr, 0); 47399a2dd95SBruce Richardson while (i >= 0) { 47499a2dd95SBruce Richardson struct rte_memzone *mz = rte_fbarray_get(arr, i); 47599a2dd95SBruce Richardson (*func)(mz, arg); 47699a2dd95SBruce Richardson i = rte_fbarray_find_next_used(arr, i + 1); 47799a2dd95SBruce Richardson } 47899a2dd95SBruce Richardson rte_rwlock_read_unlock(&mcfg->mlock); 47999a2dd95SBruce Richardson } 480