mem: add function to check if memory is contiguous

For now, memory is always contiguous because legacy mem mode is
enabled unconditionally, but this function will be helpful down
the line when we implement support for allocating physically
non-contiguous memory. We can no longer guarantee physically
contiguous memory unless we're in legacy or IOVA_AS_VA mode, but
we can certainly try and see if we succeed.

In addition, this would be useful for e.g. PMD's who may allocate
chunks that are smaller than the pagesize, but they must not cross
the page boundary, in which case we will be able to accommodate
that request. This function will also support non-hugepage memory.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
Tested-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
Tested-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Tested-by: Gowrishankar Muthukrishnan <gowrishankar.m@linux.vnet.ibm.com>
This commit is contained in:
Anatoly Burakov 2018-04-11 13:30:29 +01:00 committed by Thomas Monjalon
parent 2a04139f66
commit c8f73de36e
6 changed files with 105 additions and 37 deletions

View File

@ -41,6 +41,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_launch.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memalloc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_memory.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_tailqs.c
SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_errno.c

View File

@ -0,0 +1,90 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2017-2018 Intel Corporation
*/
#include <rte_lcore.h>
#include <rte_fbarray.h>
#include <rte_memzone.h>
#include <rte_memory.h>
#include <rte_eal_memconfig.h>
#include "eal_private.h"
#include "eal_internal_cfg.h"
#include "eal_memalloc.h"
bool
eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start,
size_t len)
{
void *end, *aligned_start, *aligned_end;
size_t pgsz = (size_t)msl->page_sz;
const struct rte_memseg *ms;
/* for IOVA_VA, it's always contiguous */
if (rte_eal_iova_mode() == RTE_IOVA_VA)
return true;
/* for legacy memory, it's always contiguous */
if (internal_config.legacy_mem)
return true;
end = RTE_PTR_ADD(start, len);
/* for nohuge, we check pagemap, otherwise check memseg */
if (!rte_eal_has_hugepages()) {
rte_iova_t cur, expected;
aligned_start = RTE_PTR_ALIGN_FLOOR(start, pgsz);
aligned_end = RTE_PTR_ALIGN_CEIL(end, pgsz);
/* if start and end are on the same page, bail out early */
if (RTE_PTR_DIFF(aligned_end, aligned_start) == pgsz)
return true;
/* skip first iteration */
cur = rte_mem_virt2iova(aligned_start);
expected = cur + pgsz;
aligned_start = RTE_PTR_ADD(aligned_start, pgsz);
while (aligned_start < aligned_end) {
cur = rte_mem_virt2iova(aligned_start);
if (cur != expected)
return false;
aligned_start = RTE_PTR_ADD(aligned_start, pgsz);
expected += pgsz;
}
} else {
int start_seg, end_seg, cur_seg;
rte_iova_t cur, expected;
aligned_start = RTE_PTR_ALIGN_FLOOR(start, pgsz);
aligned_end = RTE_PTR_ALIGN_CEIL(end, pgsz);
start_seg = RTE_PTR_DIFF(aligned_start, msl->base_va) /
pgsz;
end_seg = RTE_PTR_DIFF(aligned_end, msl->base_va) /
pgsz;
/* if start and end are on the same page, bail out early */
if (RTE_PTR_DIFF(aligned_end, aligned_start) == pgsz)
return true;
/* skip first iteration */
ms = rte_fbarray_get(&msl->memseg_arr, start_seg);
cur = ms->iova;
expected = cur + pgsz;
/* if we can't access IOVA addresses, assume non-contiguous */
if (cur == RTE_BAD_IOVA)
return false;
for (cur_seg = start_seg + 1; cur_seg < end_seg;
cur_seg++, expected += pgsz) {
ms = rte_fbarray_get(&msl->memseg_arr, cur_seg);
if (ms->iova != expected)
return false;
}
}
return true;
}

View File

@ -8,6 +8,7 @@
#include <stdbool.h>
#include <rte_memory.h>
#include <rte_eal_memconfig.h>
/*
* Allocate segment of specified page size.
@ -42,4 +43,12 @@ eal_memalloc_free_seg(struct rte_memseg *ms);
int
eal_memalloc_free_seg_bulk(struct rte_memseg **ms, int n_segs);
/*
* Check if memory pointed to by `start` and of `length` that resides in
* memseg list `msl` is IOVA-contiguous.
*/
bool
eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start,
size_t len);
#endif /* EAL_MEMALLOC_H */

View File

@ -18,6 +18,7 @@
#include <rte_common.h>
#include <rte_spinlock.h>
#include "eal_memalloc.h"
#include "malloc_elem.h"
#include "malloc_heap.h"
@ -100,45 +101,10 @@ malloc_elem_insert(struct malloc_elem *elem)
* so we just check the page addresses.
*/
static bool
elem_check_phys_contig(const struct rte_memseg_list *msl __rte_unused,
elem_check_phys_contig(const struct rte_memseg_list *msl,
void *start, size_t size)
{
rte_iova_t cur, expected;
void *start_page, *end_page, *cur_page;
size_t pagesz;
/* for hugepage memory or IOVA as VA, it's always contiguous */
if (rte_eal_has_hugepages() || rte_eal_iova_mode() == RTE_IOVA_VA)
return true;
/* otherwise, check if start and end are within the same page */
pagesz = getpagesize();
start_page = RTE_PTR_ALIGN_FLOOR(start, pagesz);
end_page = RTE_PTR_ALIGN_FLOOR(RTE_PTR_ADD(start, size - 1), pagesz);
if (start_page == end_page)
return true;
/* if they are from different pages, check if they are contiguous */
/* if we can't access physical addresses, assume non-contiguous */
if (!rte_eal_using_phys_addrs())
return false;
/* skip first iteration */
cur = rte_mem_virt2iova(start_page);
expected = cur + pagesz;
cur_page = RTE_PTR_ADD(start_page, pagesz);
while (cur_page <= end_page) {
cur = rte_mem_virt2iova(cur_page);
if (cur != expected)
return false;
cur_page = RTE_PTR_ADD(cur_page, pagesz);
expected += pagesz;
}
return true;
return eal_memalloc_is_contig(msl, start, size);
}
/*

View File

@ -16,6 +16,7 @@ common_sources = files(
'eal_common_launch.c',
'eal_common_lcore.c',
'eal_common_log.c',
'eal_common_memalloc.c',
'eal_common_memory.c',
'eal_common_memzone.c',
'eal_common_options.c',

View File

@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_timer.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memzone.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_log.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_launch.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memalloc.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_memory.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_tailqs.c
SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_errno.c