/*- * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "eal_private.h" #include "eal_internal_cfg.h" /* * Return a pointer to a read-only table of struct rte_physmem_desc * elements, containing the layout of all addressable physical * memory. The last element of the table contains a NULL address. */ const struct rte_memseg * rte_eal_get_physmem_layout(void) { return rte_eal_get_configuration()->mem_config->memseg; } /* get the total size of memory */ uint64_t rte_eal_get_physmem_size(void) { const struct rte_mem_config *mcfg; unsigned i = 0; uint64_t total_len = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; for (i = 0; i < RTE_MAX_MEMSEG; i++) { if (mcfg->memseg[i].addr == NULL) break; total_len += mcfg->memseg[i].len; } return total_len; } /* Dump the physical memory layout on console */ void rte_dump_physmem_layout(FILE *f) { const struct rte_mem_config *mcfg; unsigned i = 0; /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; for (i = 0; i < RTE_MAX_MEMSEG; i++) { if (mcfg->memseg[i].addr == NULL) break; fprintf(f, "Segment %u: IOVA:0x%"PRIx64", len:%zu, " "virt:%p, socket_id:%"PRId32", " "hugepage_sz:%"PRIu64", nchannel:%"PRIx32", " "nrank:%"PRIx32"\n", i, mcfg->memseg[i].iova, mcfg->memseg[i].len, mcfg->memseg[i].addr, mcfg->memseg[i].socket_id, mcfg->memseg[i].hugepage_sz, mcfg->memseg[i].nchannel, mcfg->memseg[i].nrank); } } /* 63 bits is good enough for a sanity check */ #define MAX_DMA_MASK_BITS 63 /* check memseg iovas are within the required range based on dma mask */ int rte_eal_check_dma_mask(uint8_t maskbits) { const struct rte_mem_config *mcfg; uint64_t mask; int i; /* sanity check */ if (maskbits > MAX_DMA_MASK_BITS) { RTE_LOG(INFO, EAL, "wrong dma mask size %u (Max: %u)\n", maskbits, MAX_DMA_MASK_BITS); return -1; } /* create dma mask */ mask = ~((1ULL << maskbits) - 1); /* get pointer to global configuration */ mcfg = rte_eal_get_configuration()->mem_config; for (i = 0; i < RTE_MAX_MEMSEG; i++) { if (mcfg->memseg[i].addr == NULL) break; if (mcfg->memseg[i].iova & mask) { RTE_LOG(INFO, EAL, "memseg[%d] iova %"PRIx64" out of range:\n", i, mcfg->memseg[i].iova); RTE_LOG(INFO, EAL, "\tusing dma mask %"PRIx64"\n", mask); return -1; } } return 0; } /* return the number of memory channels */ unsigned rte_memory_get_nchannel(void) { return rte_eal_get_configuration()->mem_config->nchannel; } /* return the number of memory rank */ unsigned rte_memory_get_nrank(void) { return rte_eal_get_configuration()->mem_config->nrank; } static int rte_eal_memdevice_init(void) { struct rte_config *config; if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; config = rte_eal_get_configuration(); config->mem_config->nchannel = internal_config.force_nchannel; config->mem_config->nrank = internal_config.force_nrank; return 0; } /* Lock page in physical memory and prevent from swapping. */ int rte_mem_lock_page(const void *virt) { unsigned long virtual = (unsigned long)virt; int page_size = getpagesize(); unsigned long aligned = (virtual & ~(page_size - 1)); return mlock((void *)aligned, page_size); } /* init memory subsystem */ int rte_eal_memory_init(void) { RTE_LOG(DEBUG, EAL, "Setting up physically contiguous memory...\n"); const int retval = rte_eal_process_type() == RTE_PROC_PRIMARY ? rte_eal_hugepage_init() : rte_eal_hugepage_attach(); if (retval < 0) return -1; if (internal_config.no_shconf == 0 && rte_eal_memdevice_init() < 0) return -1; return 0; }