mempool: support no hugepage mode

Introduce a new function rte_mempool_populate_virt() that is now called
by default when hugepages are not supported. This function populate the
mempool with several physically contiguous chunks whose minimum size is
the page size of the system.

Thanks to this, rte_mempool_create() will work properly in without
hugepages (if the object size is smaller than a page size), and 2
specific workarouds can be removed:

- trailer_size was artificially extended to a page size
- rte_mempool_virt2phy() did not rely on object physical address

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
This commit is contained in:
Olivier Matz 2016-05-18 13:04:43 +02:00 committed by Thomas Monjalon
parent 593a084afc
commit aab4f62d6c
2 changed files with 86 additions and 38 deletions

View File

@ -223,23 +223,6 @@ rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags,
sz->trailer_size = new_size - sz->header_size - sz->elt_size;
}
if (! rte_eal_has_hugepages()) {
/*
* compute trailer size so that pool elements fit exactly in
* a standard page
*/
int page_size = getpagesize();
int new_size = page_size - sz->header_size - sz->elt_size;
if (new_size < 0 || (unsigned int)new_size < sz->trailer_size) {
printf("When hugepages are disabled, pool objects "
"can't exceed PAGE_SIZE: %d + %d + %d > %d\n",
sz->header_size, sz->elt_size, sz->trailer_size,
page_size);
return 0;
}
sz->trailer_size = new_size;
}
/* this is the size of an object, including header and trailer */
sz->total_size = sz->header_size + sz->elt_size + sz->trailer_size;
@ -511,16 +494,74 @@ rte_mempool_populate_phys_tab(struct rte_mempool *mp, char *vaddr,
return cnt;
}
/* Default function to populate the mempool: allocate memory in mezones,
/* Populate the mempool with a virtual area. Return the number of
* objects added, or a negative value on error.
*/
static int
rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
size_t len, size_t pg_sz, rte_mempool_memchunk_free_cb_t *free_cb,
void *opaque)
{
phys_addr_t paddr;
size_t off, phys_len;
int ret, cnt = 0;
/* mempool must not be populated */
if (mp->nb_mem_chunks != 0)
return -EEXIST;
/* address and len must be page-aligned */
if (RTE_PTR_ALIGN_CEIL(addr, pg_sz) != addr)
return -EINVAL;
if (RTE_ALIGN_CEIL(len, pg_sz) != len)
return -EINVAL;
for (off = 0; off + pg_sz <= len &&
mp->populated_size < mp->size; off += phys_len) {
paddr = rte_mem_virt2phy(addr + off);
if (paddr == RTE_BAD_PHYS_ADDR) {
ret = -EINVAL;
goto fail;
}
/* populate with the largest group of contiguous pages */
for (phys_len = pg_sz; off + phys_len < len; phys_len += pg_sz) {
phys_addr_t paddr_tmp;
paddr_tmp = rte_mem_virt2phy(addr + off + phys_len);
paddr_tmp = rte_mem_phy2mch(-1, paddr_tmp);
if (paddr_tmp != paddr + phys_len)
break;
}
ret = rte_mempool_populate_phys(mp, addr + off, paddr,
phys_len, free_cb, opaque);
if (ret < 0)
goto fail;
/* no need to call the free callback for next chunks */
free_cb = NULL;
cnt += ret;
}
return cnt;
fail:
rte_mempool_free_memchunks(mp);
return ret;
}
/* Default function to populate the mempool: allocate memory in memzones,
* and populate them. Return the number of objects added, or a negative
* value on error.
*/
static int rte_mempool_populate_default(struct rte_mempool *mp)
static int
rte_mempool_populate_default(struct rte_mempool *mp)
{
int mz_flags = RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY;
char mz_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
size_t size, total_elt_sz, align;
size_t size, total_elt_sz, align, pg_sz, pg_shift;
unsigned mz_id, n;
int ret;
@ -528,10 +569,19 @@ static int rte_mempool_populate_default(struct rte_mempool *mp)
if (mp->nb_mem_chunks != 0)
return -EEXIST;
align = RTE_CACHE_LINE_SIZE;
if (rte_eal_has_hugepages()) {
pg_shift = 0; /* not needed, zone is physically contiguous */
pg_sz = 0;
align = RTE_CACHE_LINE_SIZE;
} else {
pg_sz = getpagesize();
pg_shift = rte_bsf32(pg_sz);
align = pg_sz;
}
total_elt_sz = mp->header_size + mp->elt_size + mp->trailer_size;
for (mz_id = 0, n = mp->size; n > 0; mz_id++, n -= ret) {
size = rte_mempool_xmem_size(n, total_elt_sz, 0);
size = rte_mempool_xmem_size(n, total_elt_sz, pg_shift);
ret = snprintf(mz_name, sizeof(mz_name),
RTE_MEMPOOL_MZ_FORMAT "_%d", mp->name, mz_id);
@ -551,9 +601,16 @@ static int rte_mempool_populate_default(struct rte_mempool *mp)
goto fail;
}
ret = rte_mempool_populate_phys(mp, mz->addr, mz->phys_addr,
mz->len, rte_mempool_memchunk_mz_free,
(void *)(uintptr_t)mz);
if (rte_eal_has_hugepages())
ret = rte_mempool_populate_phys(mp, mz->addr,
mz->phys_addr, mz->len,
rte_mempool_memchunk_mz_free,
(void *)(uintptr_t)mz);
else
ret = rte_mempool_populate_virt(mp, mz->addr,
mz->len, pg_sz,
rte_mempool_memchunk_mz_free,
(void *)(uintptr_t)mz);
if (ret < 0)
goto fail;
}

View File

@ -1150,19 +1150,10 @@ rte_mempool_empty(const struct rte_mempool *mp)
static inline phys_addr_t
rte_mempool_virt2phy(__rte_unused const struct rte_mempool *mp, const void *elt)
{
if (rte_eal_has_hugepages()) {
const struct rte_mempool_objhdr *hdr;
hdr = (const struct rte_mempool_objhdr *)RTE_PTR_SUB(elt,
sizeof(*hdr));
return hdr->physaddr;
} else {
/*
* If huge pages are disabled, we cannot assume the
* memory region to be physically contiguous.
* Lookup for each element.
*/
return rte_mem_virt2phy(elt);
}
const struct rte_mempool_objhdr *hdr;
hdr = (const struct rte_mempool_objhdr *)RTE_PTR_SUB(elt,
sizeof(*hdr));
return hdr->physaddr;
}
/**