Memory Hotplug for DPDK
Subsystems (4)
PATCH v2 36/41 net/ena: use contiguous allocation for DMA memory
In reply to Anatoly Burakov--- drivers/net/ena/base/ena_plat_dpdk.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ena/base/ena_plat_dpdk.h +4 -3
@@ -188,7 +188,8 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (handle); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size,SOCKET_ID_ANY ,0 ); \ + mz =rte_memzone_reserve_contig (z_name, \ + size,SOCKET_ID_ANY ,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ phys = mz->iova; \
@@ -206,7 +207,7 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (dev_node); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size, node,0 ); \ + mz =rte_memzone_reserve_contig (z_name, size, node,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ phys = mz->iova; \
@@ -219,7 +220,7 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (dev_node); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size, node,0 ); \ + mz =rte_memzone_reserve_contig (z_name, size, node,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ }while (0 )
Signature · 1 line
2.7.4
Re: [PATCH v2 36/41] net/ena: use contiguous allocation for DMA memory
2018-03-07 17:57 GMT+01:00 Anatoly Burakov <[email protected]>:
Quoted 1 line
Signed-off-by Anatoly Burakov <[email protected]>
Quoted 38 lines
--- drivers/net/ena/base/ena_plat_dpdk.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)drivers/net/ena/base/ena_plat_dpdk.h +4
-4@@ -188,7 +188,8 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (handle); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size,SOCKET_ID_ANY ,0 ); \ + mz =rte_memzone_reserve_contig (z_name, \ + size,SOCKET_ID_ANY ,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ phys = mz->iova; \@@ -206,7 +207,7 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (dev_node); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size, node,0 ); \ + mz =rte_memzone_reserve_contig (z_name, size, node,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ phys = mz->iova; \@@ -219,7 +220,7 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (dev_node); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size, node,0 ); \ + mz =rte_memzone_reserve_contig (z_name, size, node,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ }while (0 ) --2.7.4
PATCH v2 37/41 net/enic: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
It is not 100% clear that second call to memzone_reserve is allocating DMA memory. Corrections welcome.
drivers/net/enic/enic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/enic/enic_main.c +2 -2
@@ -319,7 +319,7 @@ enic_alloc_consistent(void *priv, size_t size,struct enic *enic = (struct enic *)priv;struct enic_memzone_entry *mze; - rz =rte_memzone_reserve_aligned ((const char *)name, + rz =rte_memzone_reserve_aligned_contig ((const char *)name, size,SOCKET_ID_ANY ,0 ,ENIC_ALIGN );if (!rz) { pr_err("%s : Failed to allocate memory requested for %s\n",
@@ -787,7 +787,7 @@ int enic_alloc_wq(struct enic *enic, uint16_t queue_idx,"vnic_cqmsg-%s-%d-%d" , enic->bdf_name, queue_idx, instance++); - wq->cqmsg_rz =rte_memzone_reserve_aligned ((const char *)name, + wq->cqmsg_rz =rte_memzone_reserve_aligned_contig ((const char *)name,sizeof (uint32_t ),SOCKET_ID_ANY ,0 ,ENIC_ALIGN );
Signature · 1 line
2.7.4
PATCH v2 38/41 net/i40e: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
It is not 100% clear that all users of this function need to allocate DMA memory. Corrections welcome.
drivers/net/i40e/i40e_ethdev.c | 2 +- drivers/net/i40e/i40e_rxtx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/i40e/i40e_ethdev.c +1 -1
@@ -4010,7 +4010,7 @@ i40e_allocate_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw,return I40E_ERR_PARAM ;snprintf (z_name,sizeof (z_name),"i40e_dma_%" PRIu64,rte_rand ()); - mz =rte_memzone_reserve_bounded (z_name, size,SOCKET_ID_ANY ,0 , + mz =rte_memzone_reserve_bounded_contig (z_name, size,SOCKET_ID_ANY ,0 , alignment,RTE_PGSIZE_2M );if (!mz)return I40E_ERR_NO_MEMORY ;
drivers/net/i40e/i40e_rxtx.c +1 -1
@@ -2189,7 +2189,7 @@ i40e_memzone_reserve(const char *name, uint32_t len, int socket_id)if (mz)return mz; - mz =rte_memzone_reserve_aligned (name, len, + mz =rte_memzone_reserve_aligned_contig (name, len, socket_id,0 ,I40E_RING_BASE_ALIGN );return mz; }
Signature · 1 line
2.7.4
PATCH v2 39/41 net/qede: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
Doing "grep -R rte_memzone_reserve drivers/net/qede" returns the following:
drivers/net/qede/qede_fdir.c: mz = rte_memzone_reserve_aligned(mz_name, QEDE_MAX_FDIR_PKT_LEN,
drivers/net/qede/base/bcm_osal.c: mz = rte_memzone_reserve_aligned_contig(mz_name, size, drivers/net/qede/base/bcm_osal.c: mz = rte_memzone_reserve_aligned_contig(mz_name, size, socket_id, 0,
I took a brief look at memzone in qede_fdir and it didn't look like memzone was used for DMA, so i left it alone. Corrections welcome.
drivers/net/qede/base/bcm_osal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/qede/base/bcm_osal.c +3 -2
@@ -135,7 +135,7 @@ void *osal_dma_alloc_coherent(struct ecore_dev *p_dev,if (core_id == (unsigned int )LCORE_ID_ANY ) core_id =0 ; socket_id =rte_lcore_to_socket_id (core_id); - mz =rte_memzone_reserve_aligned (mz_name, size, + mz =rte_memzone_reserve_aligned_contig (mz_name, size, socket_id,0 ,RTE_CACHE_LINE_SIZE );if (!mz) { DP_ERR(p_dev, "Unable to allocate DMA memory "
@@ -174,7 +174,8 @@ void *osal_dma_alloc_coherent_aligned(struct ecore_dev *p_dev,if (core_id == (unsigned int )LCORE_ID_ANY ) core_id =0 ; socket_id =rte_lcore_to_socket_id (core_id); - mz =rte_memzone_reserve_aligned (mz_name, size, socket_id,0 , align); + mz =rte_memzone_reserve_aligned_contig (mz_name, size, socket_id,0 , + align);if (!mz) { DP_ERR(p_dev, "Unable to allocate DMA memory " "of size %zu bytes - %s\n",
Signature · 1 line
2.7.4
Re: [PATCH v2 39/41] net/qede: use contiguous allocation for DMA memory
-----Original Message-----
From: Anatoly Burakov <[email protected]>
Date: Wednesday, March 7, 2018 at 8:57 AM
To: "[email protected]" <[email protected]>
Cc: "Mody, Rasesh" <[email protected]>, Harish Patil <[email protected]>, "Shaikh, Shahed" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>, "Jacob, Jerin" <[email protected]>, "[email protected]" <[email protected]>, "[email protected]" <[email protected]>
Subject: [PATCH v2 39/41] net/qede: use contiguous allocation for DMA memory
Quoted 14 lines
Signed-off-by Anatoly Burakov <[email protected]>---
Notes:
Doing "grep -Rrte_memzone_reservedrivers/net/qede" returns the
following:
drivers/net/qede/qede_fdir.c: mz =
rte_memzone_reserve_aligned(mz_name,QEDE_MAX_FDIR_PKT_LEN,
drivers/net/qede/base/bcm_osal.c: mz =
rte_memzone_reserve_aligned_contig(mz_name, size,
drivers/net/qede/base/bcm_osal.c: mz =
rte_memzone_reserve_aligned_contig(mz_name, size,socket_id, 0,
Quoted 3 lines
I took a brief look at memzone in
qede_fdirand it didn't look like
memzone
was used for DMA, so i left it alone. Corrections welcome.
That’s right.
Quoted 28 lines
drivers/net/qede/base/bcm_osal.c| 5 +++--1 file changed, 3 insertions(+), 2 deletions(-)drivers/net/qede/base/bcm_osal.c +3
-2@@ -135,7 +135,7 @@ void *osal_dma_alloc_coherent(struct ecore_dev *p_dev,if (core_id == (unsigned int )LCORE_ID_ANY ) core_id =0 ; socket_id =rte_lcore_to_socket_id (core_id); - mz =rte_memzone_reserve_aligned (mz_name, size, + mz =rte_memzone_reserve_aligned_contig (mz_name, size, socket_id,0 ,RTE_CACHE_LINE_SIZE );if (!mz) { DP_ERR(p_dev, "Unable to allocate DMA memory "@@ -174,7 +174,8 @@ void *osal_dma_alloc_coherent_aligned(struct ecore_dev *p_dev, if (core_id == (unsigned int)LCORE_ID_ANY) core_id = 0; socket_id =rte_lcore_to_socket_id (core_id); - mz =rte_memzone_reserve_aligned (mz_name, size, socket_id,0 , align); + mz =rte_memzone_reserve_aligned_contig (mz_name, size, socket_id,0 , + align);if (!mz) { DP_ERR(p_dev, "Unable to allocate DMA memory "
Quoted 3 lines
"of size %zu bytes - %s\n",Signature · 1 line
2.7.4
Quoted 1 line
PATCH v2 40/41 net/virtio: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
Not sure if virtio needs to allocate DMA-capable memory, being a software driver and all. Corrections welcome.
drivers/net/virtio/virtio_ethdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/virtio/virtio_ethdev.c +4 -4
@@ -391,7 +391,7 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)PMD_INIT_LOG (DEBUG ,"vring_size: %d, rounded_vring_size: %d" , size, vq->vq_ring_size); - mz =rte_memzone_reserve_aligned (vq_name, vq->vq_ring_size, + mz =rte_memzone_reserve_aligned_contig (vq_name, vq->vq_ring_size,SOCKET_ID_ANY ,0 ,VIRTIO_PCI_VRING_ALIGN );if (mz ==NULL ) {
@@ -417,9 +417,9 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)if (sz_hdr_mz) {snprintf (vq_hdr_name,sizeof (vq_hdr_name),"port%d_vq%d_hdr" , dev->data->port_id, vtpci_queue_idx); - hdr_mz =rte_memzone_reserve_aligned (vq_hdr_name, sz_hdr_mz, -SOCKET_ID_ANY ,0 , -RTE_CACHE_LINE_SIZE ); + hdr_mz =rte_memzone_reserve_aligned_contig (vq_hdr_name, + sz_hdr_mz,SOCKET_ID_ANY ,0 , +RTE_CACHE_LINE_SIZE );if (hdr_mz ==NULL ) {if (rte_errno ==EEXIST ) hdr_mz =rte_memzone_lookup (vq_hdr_name);
Signature · 1 line
2.7.4
Re: [PATCH v2 40/41] net/virtio: use contiguous allocation for DMA memory
Hi Anatoly,
Quoted 7 lines · Anatoly Burakov
Signed-off-by Anatoly Burakov <[email protected]>Reviewed-by Venkatesh Srinivas <[email protected]>---
Notes:
Not sure if virtio needs to allocate DMA-capable memory, being a software driver and all. Corrections welcome.
Yes, we need the ring memory to be contiguous in physical address space.
Quoted 2 lines
drivers/net/virtio/virtio_ethdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
So:
Thanks,
Maxime
PATCH v2 41/41 net/vmxnet3: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
Not sure if DMA-capable memzones are needed for vmxnet3. Corrections welcome.
drivers/net/vmxnet3/vmxnet3_ethdev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/vmxnet3/vmxnet3_ethdev.c +4 -3
@@ -150,14 +150,15 @@ gpa_zone_reserve(struct rte_eth_dev *dev, uint32_t size,if (!reuse) {if (mz)rte_memzone_free (mz); -return rte_memzone_reserve_aligned (z_name, size, socket_id, -0 , align); +return rte_memzone_reserve_aligned_contig (z_name, size, + socket_id,0 , align); }if (mz)return mz; -return rte_memzone_reserve_aligned (z_name, size, socket_id,0 , align); +return rte_memzone_reserve_aligned_contig (z_name, size, socket_id,0 , + align); }/**
Signature · 1 line
2.7.4
Hi Anatoly,
I am trying to verify this patchset and have encountered few issues.
Few -Werror=maybe-uninitialized errors in eal_memalloc.c/eal_memory.c/ eal_common_memzone.c files.
lib/librte_eal/common/eal_common_memzone.c +1 -1
@@ -321,7 +321,7 @@ rte_memzone_free(const struct rte_memzone *mz)struct rte_fbarray *arr;struct rte_memzone *found_mz;int ret =0 ; -void *addr; +void *addr =NULL ;unsigned idx;if (mz ==NULL )
lib/librte_eal/linuxapp/eal/eal_memalloc.c +1 -1
@@ -570,7 +570,7 @@ eal_memalloc_alloc_page_bulk(struct rte_memseg **ms, int n,unsigned int msl_idx;int cur_idx, start_idx, end_idx, i, j, ret =-1 ;#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES -bool have_numa; +bool have_numa = false;int oldpolicy;struct bitmask *oldmask =numa_allocate_nodemask ();#endif
lib/librte_eal/linuxapp/eal/eal_memory.c +2 -2
@@ -1386,9 +1386,9 @@ eal_legacy_hugepage_attach(void)struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;struct hugepage_file *hp =NULL ;unsigned int num_hp =0 ; -unsigned int i; +unsigned int i =0 ;int ms_idx, msl_idx; -unsigned int cur_seg, max_seg; +unsigned int cur_seg, max_seg =0 ;off_t size =0 ;int fd, fd_hugepage =-1 ;
@Hemanth
Also, this patchset breaks dpaa/dpaa2 bus drivers (they rely on rte_eal_get_physmem_layout that is depricated
http://dpdk.org/dev/patchwork/patch/34002/)
So, generic arm64 linuxapp build is broken.
Regards,
Pavan.
Quoted 9 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Dependencies (to be applied in specified order):
- IPC bugfixes patchset [2]
- IPC improvements patchset [3]
- IPC asynchronous request API patch [4]
- Function to return number of sockets [5]
<snip>
--
Quoted 1 line
2.7.4
Quoted 6 lines · Pavan Nikhilesh
Hi Anatoly,
I am trying to verify this patchset and have encountered few issues.
Few -Werror=maybe-uninitialized errors in eal_memalloc.c/eal_memory.c/
eal_common_memzone.cfiles.
Thanks for the heads up, i'll fix those in the next revision. Out of curiousity, which compiler version are you using?
Quoted 45 lines
lib/librte_eal/common/eal_common_memzone.c +1
-1@@ -321,7 +321,7 @@ rte_memzone_free(const struct rte_memzone *mz)struct rte_fbarray *arr;struct rte_memzone *found_mz;int ret =0 ; -void *addr; +void *addr =NULL ;unsigned idx;if (mz ==NULL )lib/librte_eal/linuxapp/eal/eal_memalloc.c +1
-1@@ -570,7 +570,7 @@ eal_memalloc_alloc_page_bulk(struct rte_memseg **ms, int n,unsigned int msl_idx;int cur_idx, start_idx, end_idx, i, j, ret =-1 ;#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES -bool have_numa; +bool have_numa = false;int oldpolicy;struct bitmask *oldmask =numa_allocate_nodemask ();#endif lib/librte_eal/linuxapp/eal/eal_memory.c +2
-2@@ -1386,9 +1386,9 @@ eal_legacy_hugepage_attach(void)struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;struct hugepage_file *hp =NULL ;unsigned int num_hp =0 ; -unsigned int i; +unsigned int i =0 ;int ms_idx, msl_idx; -unsigned int cur_seg, max_seg; +unsigned int cur_seg, max_seg =0 ;off_t size =0 ;int fd, fd_hugepage =-1 ;
Quoted 5 lines
@Hemanth
Also, this patchset breaks dpaa/dpaa2 bus drivers (they rely onrte_eal_get_physmem_layoutthat is depricated
http://dpdk.org/dev/patchwork/patch/34002/)
So, generic arm64 linuxapp build is broken.
Should the deprecation notice have been accompanied with marking that function as __rte_deprecated?
Quoted 18 lines
Regards,
Pavan.Quoted 9 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Dependencies (to be applied in specified order):
- IPC bugfixes patchset [2]
- IPC improvements patchset [3]
- IPC asynchronous request API patch [4]
- Function to return number of sockets [5]<snip>
--Quoted 1 line
2.7.4
Signature · 2 lines
Thanks, Anatoly
Quoted 10 lines · Anatoly
Quoted 6 lines · Pavan Nikhilesh
Hi Anatoly,
I am trying to verify this patchset and have encountered few issues.
Few -Werror=maybe-uninitialized errors in eal_memalloc.c/eal_memory.c/
eal_common_memzone.cfiles.Thanks for the heads up, i'll fix those in the next revision. Out of curiousity, which compiler version are you using?
I'm using gcc 5.3.0.
Quoted 46 lines
Quoted 46 lines
lib/librte_eal/common/eal_common_memzone.c +1
-1@@ -321,7 +321,7 @@ rte_memzone_free(const struct rte_memzone *mz)struct rte_fbarray *arr;struct rte_memzone *found_mz;int ret =0 ; -void *addr; +void *addr =NULL ;unsigned idx;if (mz ==NULL )lib/librte_eal/linuxapp/eal/eal_memalloc.c +1
-1@@ -570,7 +570,7 @@ eal_memalloc_alloc_page_bulk(struct rte_memseg **ms, int n,unsigned int msl_idx;int cur_idx, start_idx, end_idx, i, j, ret =-1 ;#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES -bool have_numa; +bool have_numa = false;int oldpolicy;struct bitmask *oldmask =numa_allocate_nodemask ();#endif lib/librte_eal/linuxapp/eal/eal_memory.c +2
-2@@ -1386,9 +1386,9 @@ eal_legacy_hugepage_attach(void)struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;struct hugepage_file *hp =NULL ;unsigned int num_hp =0 ; -unsigned int i; +unsigned int i =0 ;int ms_idx, msl_idx; -unsigned int cur_seg, max_seg; +unsigned int cur_seg, max_seg =0 ;off_t size =0 ;int fd, fd_hugepage =-1 ;
Quoted 8 lines
Quoted 5 lines
@Hemanth
Also, this patchset breaks dpaa/dpaa2 bus drivers (they rely onrte_eal_get_physmem_layoutthat is depricated
http://dpdk.org/dev/patchwork/patch/34002/)
So, generic arm64 linuxapp build is broken.Should the deprecation notice have been accompanied with marking that function as
__rte_deprecated?
Yup that's the general sequence.
Quoted 24 lines
Quoted 9 lines
Regards,
Pavan.Quoted 3 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Quoted 10 lines
Quoted 6 lines
Dependencies (to be applied in specified order):
- IPC bugfixes patchset [2]
- IPC improvements patchset [3]
- IPC asynchronous request API patch [4]
- Function to return number of sockets [5]<snip>
--Quoted 1 line
2.7.4
--
Thanks,
Anatoly
Hi Anatoly,
We are currently facing issues with running testpmd on thunderx platform. The issue seems to be with vfio
EAL: Detected 24 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: No free hugepages reported in hugepages-2048kB
EAL: Multi-process socket /var/run/.rte_unix
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: VFIO support not initialized
<snip>
EAL: probe driver: 177d:a053 octeontx_fpavf EAL: PCI device 0001:01:00.1 on NUMA socket 0 EAL: probe driver: 177d:a034 net_thunderx EAL: using IOMMU type 1 (Type 1) EAL: cannot set up DMA remapping, error 22 (Invalid argument) EAL: 0001:01:00.1 DMA remapping failed, error 22 (Invalid argument) EAL: Requested device 0001:01:00.1 cannot be used EAL: PCI device 0001:01:00.2 on NUMA socket 0 <snip> testpmd: No probed ethernet devices testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=251456, size=2176, socket=0 testpmd: preferred mempool ops selected: ring_mp_mc EAL: VFIO support not initialized EAL: VFIO support not initialized EAL: VFIO support not initialized
Done
This is because rte_service_init() calls rte_calloc() before rte_bus_probe() and vfio_dma_mem_map fails because iommu type is not set.
Call stack:
gdb) bt
#0 vfio_dma_mem_map (vaddr=281439006359552, iova=11274289152, len=536870912, do_map=1) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:967 #1 0x00000000004fd974 in rte_vfio_dma_map (vaddr=281439006359552, iova=11274289152, len=536870912) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:988 #2 0x00000000004fbe78 in vfio_mem_event_callback (type=RTE_MEM_EVENT_ALLOC, addr=0xfff7a0000000, len=536870912) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:240 #3 0x00000000005070ac in eal_memalloc_notify (event=RTE_MEM_EVENT_ALLOC, start=0xfff7a0000000, len=536870912) at /root/clean/dpdk/lib/librte_eal/common/eal_common_memalloc.c:177 #4 0x0000000000515c98 in try_expand_heap_primary (heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:247 #5 0x0000000000515e94 in try_expand_heap (heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:327 #6 0x00000000005163a0 in alloc_more_mem_on_socket (heap=0xffffb7fb167c, size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:455 #7 0x0000000000516514 in heap_alloc_on_socket (type=0x85bf90 "rte_services", size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:491 #8 0x0000000000516664 in malloc_heap_alloc (type=0x85bf90 "rte_services", size=8192, socket_arg=-1, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:527 #9 0x0000000000513b54 in rte_malloc_socket (type=0x85bf90 "rte_services", size=8192, align=128, socket_arg=-1) at /root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:54
#10 0x0000000000513bc8 in rte_zmalloc_socket (type=0x85bf90 "rte_services", size=8192, align=128, socket=-1) at /root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:72 #11 0x0000000000513c00 in rte_zmalloc (type=0x85bf90 "rte_services", size=8192, align=128) at /root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:81 #12 0x0000000000513c90 in rte_calloc (type=0x85bf90 "rte_services", num=64, size=128, align=128) at /root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:99 #13 0x0000000000518cec in rte_service_init () at /root/clean/dpdk/lib/librte_eal/common/rte_service.c:81
#14 0x00000000004f55f4 in rte_eal_init (argc=3, argv=0xfffffffff488) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:959
#15 0x000000000045af5c in main (argc=3, argv=0xfffffffff488) at /root/clean/dpdk/app/test-pmd/testpmd.c:2483
Also, I have tried running with --legacy-mem but I'm stuck in pci_find_max_end_va loop because rte_fbarray_find_next_used always return 0.
HugePages_Total: 15 HugePages_Free: 11 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 524288 kB
Call Stack:
(gdb) bt
#0 find_next (arr=0xffffb7fb009c, start=0, used=true) at /root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:248 #1 0x00000000005132a8 in rte_fbarray_find_next_used (arr=0xffffb7fb009c, start=0) at /root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:700 #2 0x000000000052d030 in pci_find_max_end_va () at /root/clean/dpdk/drivers/bus/pci/linux/pci.c:138 #3 0x0000000000530ab8 in pci_vfio_map_resource_primary (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:499 #4 0x0000000000530ffc in pci_vfio_map_resource (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:601 #5 0x000000000052ce90 in rte_pci_map_device (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/linux/pci.c:75 #6 0x0000000000531a20 in rte_pci_probe_one_driver (dr=0x997e20 <rte_nicvf_pmd>, dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/pci_common.c:164 #7 0x0000000000531c68 in pci_probe_all_drivers (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/pci_common.c:249 #8 0x0000000000531f68 in rte_pci_probe () at /root/clean/dpdk/drivers/bus/pci/pci_common.c:359 #9 0x000000000050a140 in rte_bus_probe () at /root/clean/dpdk/lib/librte_eal/common/eal_common_bus.c:98
#10 0x00000000004f55f4 in rte_eal_init (argc=1, argv=0xfffffffff498) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:967 #11 0x000000000045af5c in main (argc=1, argv=0xfffffffff498) at /root/clean/dpdk/app/test-pmd/testpmd.c:2483
Am I missing something here?
Thanks,
Pavan.
Quoted 95 lines · Pavan Nikhilesh
Quoted 10 lines · Anatoly
Quoted 6 lines · Pavan Nikhilesh
Hi Anatoly,
I am trying to verify this patchset and have encountered few issues.
Few -Werror=maybe-uninitialized errors in eal_memalloc.c/eal_memory.c/
eal_common_memzone.cfiles.Thanks for the heads up, i'll fix those in the next revision. Out of curiousity, which compiler version are you using?
I'm using gcc 5.3.0.
Quoted 46 lines
Quoted 46 lines
lib/librte_eal/common/eal_common_memzone.c +1
-1@@ -321,7 +321,7 @@ rte_memzone_free(const struct rte_memzone *mz)struct rte_fbarray *arr;struct rte_memzone *found_mz;int ret =0 ; -void *addr; +void *addr =NULL ;unsigned idx;if (mz ==NULL )lib/librte_eal/linuxapp/eal/eal_memalloc.c +1
-1@@ -570,7 +570,7 @@ eal_memalloc_alloc_page_bulk(struct rte_memseg **ms, int n,unsigned int msl_idx;int cur_idx, start_idx, end_idx, i, j, ret =-1 ;#ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES -bool have_numa; +bool have_numa = false;int oldpolicy;struct bitmask *oldmask =numa_allocate_nodemask ();#endif lib/librte_eal/linuxapp/eal/eal_memory.c +2
-2@@ -1386,9 +1386,9 @@ eal_legacy_hugepage_attach(void)struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;struct hugepage_file *hp =NULL ;unsigned int num_hp =0 ; -unsigned int i; +unsigned int i =0 ;int ms_idx, msl_idx; -unsigned int cur_seg, max_seg; +unsigned int cur_seg, max_seg =0 ;off_t size =0 ;int fd, fd_hugepage =-1 ;Quoted 8 lines
Quoted 5 lines
@Hemanth
Also, this patchset breaks dpaa/dpaa2 bus drivers (they rely onrte_eal_get_physmem_layoutthat is depricated
http://dpdk.org/dev/patchwork/patch/34002/)
So, generic arm64 linuxapp build is broken.Should the deprecation notice have been accompanied with marking that function as
__rte_deprecated?Yup that's the general sequence.
Quoted 24 lines
Quoted 9 lines
Regards,
Pavan.Quoted 3 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Quoted 10 lines
Quoted 6 lines
Dependencies (to be applied in specified order):
- IPC bugfixes patchset [2]
- IPC improvements patchset [3]
- IPC asynchronous request API patch [4]
- Function to return number of sockets [5]<snip>
--Quoted 1 line
2.7.4
--
Thanks,
Anatoly
Quoted 77 lines · Pavan Nikhilesh
Hi Anatoly,
We are currently facing issues with running testpmd on thunderx platform. The issue seems to be with vfio
EAL: Detected 24 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: No free hugepages reported in hugepages-2048kB
EAL: Multi-process socket/var/run/.rte_unix
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: VFIO support not initialized<snip>
EAL: probe driver: 177d:a053 octeontx_fpavf EAL: PCI device 0001:01:00.1 on NUMA socket 0 EAL: probe driver: 177d:a034 net_thunderx EAL: using IOMMU type 1 (Type 1) EAL: cannot set up DMA remapping, error 22 (Invalid argument) EAL: 0001:01:00.1 DMA remapping failed, error 22 (Invalid argument) EAL: Requested device 0001:01:00.1 cannot be used EAL: PCI device 0001:01:00.2 on NUMA socket 0 <snip> testpmd: No probed ethernet devices testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=251456, size=2176, socket=0 testpmd: preferred mempool ops selected: ring_mp_mc EAL: VFIO support not initialized EAL: VFIO support not initialized EAL: VFIO support not initializedDone
This is because
rte_service_init()callsrte_calloc()beforerte_bus_probe()andvfio_dma_mem_mapfails because iommu type is not set.Call stack:
gdb) bt#0 vfio_dma_mem_map (vaddr=281439006359552, iova=11274289152, len=536870912, do_map=1) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:967 #1 0x00000000004fd974 in rte_vfio_dma_map (vaddr=281439006359552, iova=11274289152, len=536870912) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:988 #2 0x00000000004fbe78 in vfio_mem_event_callback (type=RTE_MEM_EVENT_ALLOC, addr=0xfff7a0000000, len=536870912) at /root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:240 #3 0x00000000005070ac in eal_memalloc_notify (event=RTE_MEM_EVENT_ALLOC, start=0xfff7a0000000, len=536870912) at /root/clean/dpdk/lib/librte_eal/common/eal_common_memalloc.c:177 #4 0x0000000000515c98 in try_expand_heap_primary (heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:247 #5 0x0000000000515e94 in try_expand_heap (heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:327 #6 0x00000000005163a0 in alloc_more_mem_on_socket (heap=0xffffb7fb167c, size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:455 #7 0x0000000000516514 in heap_alloc_on_socket (type=0x85bf90 "rte_services", size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:491 #8 0x0000000000516664 in malloc_heap_alloc (type=0x85bf90 "rte_services", size=8192, socket_arg=-1, flags=0, align=128, bound=0, contig=false) at /root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:527 #9 0x0000000000513b54 in rte_malloc_socket (type=0x85bf90 "rte_services", size=8192, align=128, socket_arg=-1) at /root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:54#10
0x0000000000513bc8inrte_zmalloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:72#110x0000000000513c00inrte_zmalloc(type=0x85bf90 "rte_services", size=8192, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:81#120x0000000000513c90inrte_calloc(type=0x85bf90 "rte_services", num=64, size=128, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:99#130x0000000000518cecinrte_service_init() at/root/clean/dpdk/lib/librte_eal/common/rte_service.c:81
#140x00000000004f55f4inrte_eal_init(argc=3, argv=0xfffffffff488) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:959
#150x000000000045af5cin main (argc=3, argv=0xfffffffff488) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Also, I have tried running with --legacy-mem but I'm stuck in
pci_find_max_end_valoop becauserte_fbarray_find_next_usedalways return
0. >HugePages_Total: 15 HugePages_Free: 11 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 524288 kBCall Stack:
(gdb) bt#0 find_next (arr=0xffffb7fb009c, start=0, used=true) at /root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:248 #1 0x00000000005132a8 in rte_fbarray_find_next_used (arr=0xffffb7fb009c, start=0) at /root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:700 #2 0x000000000052d030 in pci_find_max_end_va () at /root/clean/dpdk/drivers/bus/pci/linux/pci.c:138 #3 0x0000000000530ab8 in pci_vfio_map_resource_primary (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:499 #4 0x0000000000530ffc in pci_vfio_map_resource (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:601 #5 0x000000000052ce90 in rte_pci_map_device (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/linux/pci.c:75 #6 0x0000000000531a20 in rte_pci_probe_one_driver (dr=0x997e20 <rte_nicvf_pmd>, dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/pci_common.c:164 #7 0x0000000000531c68 in pci_probe_all_drivers (dev=0xeae700) at /root/clean/dpdk/drivers/bus/pci/pci_common.c:249 #8 0x0000000000531f68 in rte_pci_probe () at /root/clean/dpdk/drivers/bus/pci/pci_common.c:359 #9 0x000000000050a140 in rte_bus_probe () at /root/clean/dpdk/lib/librte_eal/common/eal_common_bus.c:98
Quoted 4 lines
#10
0x00000000004f55f4inrte_eal_init(argc=1, argv=0xfffffffff498) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:967#110x000000000045af5cin main (argc=1, argv=0xfffffffff498) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Am I missing something here?
I'll look into those, thanks!
Btw, i've now set up a github repo with the patchset applied:
https://github.com/anatolyburakov/dpdk
I will be pushing quick fixes there before spinning new revisions, so we can discover and fix bugs more rapidly. I'll fix compile issues reported earlier, then i'll take a look at your issues. The latter one seems like a typo, the former is probably a matter of moving things around a bit.
(also, pull requests welcome if you find it easier to fix things yourself and submit patches against my tree!)
Thanks for testing.
Signature · 2 lines
Thanks, Anatoly
Quoted 87 lines · Anatoly
Quoted 80 lines · Pavan Nikhilesh
Hi Anatoly,
We are currently facing issues with running testpmd on thunderx platform. The issue seems to be with vfio
EAL: Detected 24 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: No free hugepages reported in hugepages-2048kB
EAL: Multi-process socket/var/run/.rte_unix
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: VFIO support not initialized<snip>
EAL: probe driver: 177d:a053
octeontx_fpavf
EAL: PCI device 0001:01:00.1 on NUMA socket 0
EAL: probe driver: 177d:a034net_thunderx
EAL: using IOMMU type 1 (Type 1)
EAL: cannot set up DMA remapping, error 22 (Invalid argument)
EAL: 0001:01:00.1 DMA remapping failed, error 22 (Invalid argument)
EAL: Requested device 0001:01:00.1 cannot be used
EAL: PCI device 0001:01:00.2 on NUMA socket 0
<snip>
testpmd: No probed ethernet devices
testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=251456, size=2176, socket=0
testpmd: preferred mempool ops selected:ring_mp_mc
EAL: VFIO support not initialized
EAL: VFIO support not initialized
EAL: VFIO support not initialized
DoneThis is because
rte_service_init()callsrte_calloc()beforerte_bus_probe()andvfio_dma_mem_mapfails because iommu type is not set.Call stack:
gdb) bt
#0vfio_dma_mem_map(vaddr=281439006359552, iova=11274289152, len=536870912, do_map=1) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:967
#10x00000000004fd974inrte_vfio_dma_map(vaddr=281439006359552, iova=11274289152, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:988
#20x00000000004fbe78invfio_mem_event_callback(type=RTE_MEM_EVENT_ALLOC, addr=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:240
#30x00000000005070acineal_memalloc_notify(event=RTE_MEM_EVENT_ALLOC, start=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/common/eal_common_memalloc.c:177#40x0000000000515c98intry_expand_heap_primary(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:247#50x0000000000515e94intry_expand_heap(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:327#60x00000000005163a0inalloc_more_mem_on_socket(heap=0xffffb7fb167c, size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:455#70x0000000000516514inheap_alloc_on_socket(type=0x85bf90 "rte_services", size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:491#80x0000000000516664inmalloc_heap_alloc(type=0x85bf90 "rte_services", size=8192, socket_arg=-1, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:527#90x0000000000513b54inrte_malloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket_arg=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:54
#100x0000000000513bc8inrte_zmalloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:72
#110x0000000000513c00inrte_zmalloc(type=0x85bf90 "rte_services", size=8192, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:81
#120x0000000000513c90inrte_calloc(type=0x85bf90 "rte_services", num=64, size=128, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:99
#130x0000000000518cecinrte_service_init() at/root/clean/dpdk/lib/librte_eal/common/rte_service.c:81
#140x00000000004f55f4inrte_eal_init(argc=3, argv=0xfffffffff488) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:959
#150x000000000045af5cin main (argc=3, argv=0xfffffffff488) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Also, I have tried running with --legacy-mem but I'm stuck in
pci_find_max_end_valoop becauserte_fbarray_find_next_usedalways return
0. >
HugePages_Total: 15
HugePages_Free: 11
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 524288 kBCall Stack:
(gdb) bt
#0find_next(arr=0xffffb7fb009c, start=0, used=true) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:248
#10x00000000005132a8inrte_fbarray_find_next_used(arr=0xffffb7fb009c, start=0) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:700#20x000000000052d030inpci_find_max_end_va() at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:138
#30x0000000000530ab8inpci_vfio_map_resource_primary(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:499#40x0000000000530ffcinpci_vfio_map_resource(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:601
#50x000000000052ce90inrte_pci_map_device(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:75
#60x0000000000531a20inrte_pci_probe_one_driver(dr=0x997e20 <rte_nicvf_pmd>, dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:164#70x0000000000531c68inpci_probe_all_drivers(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:249
#80x0000000000531f68inrte_pci_probe() at/root/clean/dpdk/drivers/bus/pci/pci_common.c:359
#90x000000000050a140inrte_bus_probe() at/root/clean/dpdk/lib/librte_eal/common/eal_common_bus.c:98
#100x00000000004f55f4inrte_eal_init(argc=1, argv=0xfffffffff498) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:967#110x000000000045af5cin main (argc=1, argv=0xfffffffff498) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Quoted 1 line
Am I missing something here?
I'll look into those, thanks!
Btw, i've now set up a github repo with the patchset applied:
Quoted 8 lines
https://github.com/anatolyburakov/dpdk
I will be pushing quick fixes there before spinning new revisions, so we can discover and fix bugs more rapidly. I'll fix compile issues reported earlier, then i'll take a look at your issues. The latter one seems like a typo, the former is probably a matter of moving things around a bit.
(also, pull requests welcome if you find it easier to fix things yourself and submit patches against my tree!)
Thanks for testing.
I've looked into the failures.
The VFIO one is not actually a failure. It only prints out errors because rte_malloc is called before VFIO is initialized. However, once VFIO *is* initialized, all of that memory would be added to VFIO, so these error messages are harmless. Regardless, i've added a check to see if init is finished before printing out those errors, so they won't be printed out any more.
Second one is a typo on my part that got lost in one of the rebases.
I've pushed fixes for both into the github repo.
Signature · 2 lines
Thanks, Anatoly
Quoted 97 lines · Anatoly
Quoted 87 lines · Anatoly
Quoted 80 lines · Pavan Nikhilesh
Hi Anatoly,
We are currently facing issues with running testpmd on thunderx platform. The issue seems to be with vfio
EAL: Detected 24 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: No free hugepages reported in hugepages-2048kB
EAL: Multi-process socket/var/run/.rte_unix
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: VFIO support not initialized<snip>
EAL: probe driver: 177d:a053
octeontx_fpavf
EAL: PCI device 0001:01:00.1 on NUMA socket 0
EAL: probe driver: 177d:a034net_thunderx
EAL: using IOMMU type 1 (Type 1)
EAL: cannot set up DMA remapping, error 22 (Invalid argument)
EAL: 0001:01:00.1 DMA remapping failed, error 22 (Invalid argument)
EAL: Requested device 0001:01:00.1 cannot be used
EAL: PCI device 0001:01:00.2 on NUMA socket 0
<snip>
testpmd: No probed ethernet devices
testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=251456, size=2176, socket=0
testpmd: preferred mempool ops selected:ring_mp_mc
EAL: VFIO support not initialized
EAL: VFIO support not initialized
EAL: VFIO support not initialized
DoneThis is because
rte_service_init()callsrte_calloc()beforerte_bus_probe()andvfio_dma_mem_mapfails because iommu type is not set.Call stack:
gdb) bt
#0vfio_dma_mem_map(vaddr=281439006359552, iova=11274289152, len=536870912, do_map=1) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:967
#10x00000000004fd974inrte_vfio_dma_map(vaddr=281439006359552, iova=11274289152, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:988
#20x00000000004fbe78invfio_mem_event_callback(type=RTE_MEM_EVENT_ALLOC, addr=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:240
#30x00000000005070acineal_memalloc_notify(event=RTE_MEM_EVENT_ALLOC, start=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/common/eal_common_memalloc.c:177#40x0000000000515c98intry_expand_heap_primary(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:247#50x0000000000515e94intry_expand_heap(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:327#60x00000000005163a0inalloc_more_mem_on_socket(heap=0xffffb7fb167c, size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:455#70x0000000000516514inheap_alloc_on_socket(type=0x85bf90 "rte_services", size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:491#80x0000000000516664inmalloc_heap_alloc(type=0x85bf90 "rte_services", size=8192, socket_arg=-1, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:527#90x0000000000513b54inrte_malloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket_arg=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:54
#100x0000000000513bc8inrte_zmalloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:72
#110x0000000000513c00inrte_zmalloc(type=0x85bf90 "rte_services", size=8192, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:81
#120x0000000000513c90inrte_calloc(type=0x85bf90 "rte_services", num=64, size=128, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:99
#130x0000000000518cecinrte_service_init() at/root/clean/dpdk/lib/librte_eal/common/rte_service.c:81
#140x00000000004f55f4inrte_eal_init(argc=3, argv=0xfffffffff488) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:959
#150x000000000045af5cin main (argc=3, argv=0xfffffffff488) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Also, I have tried running with --legacy-mem but I'm stuck in
pci_find_max_end_valoop becauserte_fbarray_find_next_usedalways return
0. >
HugePages_Total: 15
HugePages_Free: 11
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 524288 kBCall Stack:
(gdb) bt
#0find_next(arr=0xffffb7fb009c, start=0, used=true) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:248
#10x00000000005132a8inrte_fbarray_find_next_used(arr=0xffffb7fb009c, start=0) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:700#20x000000000052d030inpci_find_max_end_va() at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:138
#30x0000000000530ab8inpci_vfio_map_resource_primary(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:499#40x0000000000530ffcinpci_vfio_map_resource(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:601
#50x000000000052ce90inrte_pci_map_device(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:75
#60x0000000000531a20inrte_pci_probe_one_driver(dr=0x997e20 <rte_nicvf_pmd>, dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:164#70x0000000000531c68inpci_probe_all_drivers(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:249
#80x0000000000531f68inrte_pci_probe() at/root/clean/dpdk/drivers/bus/pci/pci_common.c:359
#90x000000000050a140inrte_bus_probe() at/root/clean/dpdk/lib/librte_eal/common/eal_common_bus.c:98
#100x00000000004f55f4inrte_eal_init(argc=1, argv=0xfffffffff498) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:967#110x000000000045af5cin main (argc=1, argv=0xfffffffff498) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Quoted 1 line
Am I missing something here?
I'll look into those, thanks!
Btw, i've now set up a github repo with the patchset applied:
Quoted 8 lines
https://github.com/anatolyburakov/dpdk
I will be pushing quick fixes there before spinning new revisions, so we can discover and fix bugs more rapidly. I'll fix compile issues reported earlier, then i'll take a look at your issues. The latter one seems like a typo, the former is probably a matter of moving things around a bit.
(also, pull requests welcome if you find it easier to fix things yourself and submit patches against my tree!)
Thanks for testing.
Quoted 8 lines
I've looked into the failures.
The VFIO one is not actually a failure. It only prints out errors because
rte_mallocis called before VFIO is initialized. However, once VFIO *is* initialized, all of that memory would be added to VFIO, so these error messages are harmless. Regardless, i've added a check to see if init is finished before printing out those errors, so they won't be printed out any more.Second one is a typo on my part that got lost in one of the rebases.
I've pushed fixes for both into the github repo.
Although i do wonder where do the DMA remapping errors come from. The error message says "invalid argument", so that doesn't come from rte_service or anything to do with rte_malloc - this is us not providing valid arguments to VFIO. I'm not seeing these errors on my system. I'll check on others to be sure.
Signature · 2 lines
Thanks, Anatoly
Quoted 170 lines · Anatoly
Quoted 169 lines · Anatoly
Quoted 151 lines · Anatoly
Quoted 136 lines · Pavan Nikhilesh
Hi Anatoly,
We are currently facing issues with running testpmd on thunderx platform.
The issue seems to be with vfioEAL: Detected 24 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: No free hugepages reported in hugepages-2048kB
EAL: Multi-process socket/var/run/.rte_unix
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: VFIO support not initialized<snip>
EAL: probe driver: 177d:a053
octeontx_fpavf
EAL: PCI device 0001:01:00.1 on NUMA socket 0
EAL: probe driver: 177d:a034net_thunderx
EAL: using IOMMU type 1 (Type 1)
EAL: cannot set up DMA remapping, error 22 (Invalid argument) EAL: 0001:01:00.1 DMA remapping failed, error 22 (Invalid argument)
EAL: Requested device 0001:01:00.1 cannot be used
EAL: PCI device 0001:01:00.2 on NUMA socket 0
<snip>
testpmd: No probed ethernet devices
testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=251456, size=2176, socket=0
testpmd: preferred mempool ops selected:ring_mp_mc
EAL: VFIO support not initialized
EAL: VFIO support not initialized
EAL: VFIO support not initialized
DoneThis is because
rte_service_init()callsrte_calloc()beforerte_bus_probe()andvfio_dma_mem_mapfails because iommu type is not set.Call stack:
gdb) bt
#0vfio_dma_mem_map(vaddr=281439006359552, iova=11274289152, len=536870912, do_map=1) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:967#10x00000000004fd974inrte_vfio_dma_map(vaddr=281439006359552, iova=11274289152, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:988#20x00000000004fbe78invfio_mem_event_callback(type=RTE_MEM_EVENT_ALLOC, addr=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:240#30x00000000005070acineal_memalloc_notify(event=RTE_MEM_EVENT_ALLOC, start=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/common/eal_common_memalloc.c:177#40x0000000000515c98intry_expand_heap_primary(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:247#50x0000000000515e94intry_expand_heap(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:327#60x00000000005163a0inalloc_more_mem_on_socket(heap=0xffffb7fb167c, size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:455#70x0000000000516514inheap_alloc_on_socket(type=0x85bf90 "rte_services", size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:491#80x0000000000516664inmalloc_heap_alloc(type=0x85bf90 "rte_services", size=8192, socket_arg=-1, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:527#90x0000000000513b54inrte_malloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket_arg=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:54#100x0000000000513bc8inrte_zmalloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:72#110x0000000000513c00inrte_zmalloc(type=0x85bf90 "rte_services", size=8192, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:81#120x0000000000513c90inrte_calloc(type=0x85bf90 "rte_services", num=64, size=128, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:99#130x0000000000518cecinrte_service_init() at/root/clean/dpdk/lib/librte_eal/common/rte_service.c:81#140x00000000004f55f4inrte_eal_init(argc=3, argv=0xfffffffff488) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:959#150x000000000045af5cin main (argc=3, argv=0xfffffffff488) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Also, I have tried running with --legacy-mem but I'm stuck in
pci_find_max_end_valoop becauserte_fbarray_find_next_usedalways return
0. >
HugePages_Total: 15
HugePages_Free: 11
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 524288 kBCall Stack:
(gdb) bt
#0find_next(arr=0xffffb7fb009c, start=0, used=true) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:248#10x00000000005132a8inrte_fbarray_find_next_used(arr=0xffffb7fb009c, start=0) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:700#20x000000000052d030inpci_find_max_end_va() at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:138
#30x0000000000530ab8inpci_vfio_map_resource_primary(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:499#40x0000000000530ffcinpci_vfio_map_resource(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:601#50x000000000052ce90inrte_pci_map_device(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:75
#60x0000000000531a20inrte_pci_probe_one_driver(dr=0x997e20 <rte_nicvf_pmd>, dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:164
#70x0000000000531c68inpci_probe_all_drivers(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:249#80x0000000000531f68inrte_pci_probe() at/root/clean/dpdk/drivers/bus/pci/pci_common.c:359
#90x000000000050a140inrte_bus_probe() at/root/clean/dpdk/lib/librte_eal/common/eal_common_bus.c:98#100x00000000004f55f4inrte_eal_init(argc=1, argv=0xfffffffff498) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:967#110x000000000045af5cin main (argc=1, argv=0xfffffffff498) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Quoted 1 line
Am I missing something here?
I'll look into those, thanks!
Btw, i've now set up a github repo with the patchset applied:
https://github.com/anatolyburakov/dpdk
I will be pushing quick fixes there before spinning new revisions, so we can discover and fix bugs more rapidly. I'll fix compile issues reported earlier, then i'll take a look at your issues. The latter one seems like a typo, the former is probably a matter of moving things around a bit.
Quoted 5 lines
(also, pull requests welcome if you find it easier to fix things yourself and submit patches against my tree!)
Thanks for testing.
I've looked into the failures.
The VFIO one is not actually a failure. It only prints out errors because
rte_mallocis called before VFIO is initialized. However, once VFIO *is* initialized, all of that memory would be added to VFIO, so these error messages are harmless. Regardless, i've added a check to see if init is finished before printing out those errors, so they won't be printed out any more.Second one is a typo on my part that got lost in one of the rebases.
Quoted 8 lines
Quoted 2 lines
I've pushed fixes for both into the github repo.
Although i do wonder where do the DMA remapping errors come from. The error message says "invalid argument", so that doesn't come from
rte_serviceor anything to do withrte_malloc- this is us not providing valid arguments to VFIO. I'm not seeing these errors on my system. I'll check on others to be sure.
I have taken a look at the github tree the issues with VFIO are gone, Although compilation issues with dpaa/dpaa2 are still present due to their dependency on rte_eal_get_physmem_layout.
Quoted 4 lines
--
Thanks,
Anatoly
Thanks,
Pavan
Quoted 180 lines · Pavan Nikhilesh
Quoted 170 lines · Anatoly
Quoted 169 lines · Anatoly
Quoted 151 lines · Anatoly
Quoted 136 lines · Pavan Nikhilesh
Hi Anatoly,
We are currently facing issues with running testpmd on thunderx platform.
The issue seems to be with vfioEAL: Detected 24 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: No free hugepages reported in hugepages-2048kB
EAL: Multi-process socket/var/run/.rte_unix
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: VFIO support not initialized<snip>
EAL: probe driver: 177d:a053
octeontx_fpavf
EAL: PCI device 0001:01:00.1 on NUMA socket 0
EAL: probe driver: 177d:a034net_thunderx
EAL: using IOMMU type 1 (Type 1)
EAL: cannot set up DMA remapping, error 22 (Invalid argument) EAL: 0001:01:00.1 DMA remapping failed, error 22 (Invalid argument)
EAL: Requested device 0001:01:00.1 cannot be used
EAL: PCI device 0001:01:00.2 on NUMA socket 0
<snip>
testpmd: No probed ethernet devices
testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=251456, size=2176, socket=0
testpmd: preferred mempool ops selected:ring_mp_mc
EAL: VFIO support not initialized
EAL: VFIO support not initialized
EAL: VFIO support not initialized
DoneThis is because
rte_service_init()callsrte_calloc()beforerte_bus_probe()andvfio_dma_mem_mapfails because iommu type is not set.Call stack:
gdb) bt
#0vfio_dma_mem_map(vaddr=281439006359552, iova=11274289152, len=536870912, do_map=1) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:967#10x00000000004fd974inrte_vfio_dma_map(vaddr=281439006359552, iova=11274289152, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:988#20x00000000004fbe78invfio_mem_event_callback(type=RTE_MEM_EVENT_ALLOC, addr=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:240#30x00000000005070acineal_memalloc_notify(event=RTE_MEM_EVENT_ALLOC, start=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/common/eal_common_memalloc.c:177#40x0000000000515c98intry_expand_heap_primary(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:247#50x0000000000515e94intry_expand_heap(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:327#60x00000000005163a0inalloc_more_mem_on_socket(heap=0xffffb7fb167c, size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:455#70x0000000000516514inheap_alloc_on_socket(type=0x85bf90 "rte_services", size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:491#80x0000000000516664inmalloc_heap_alloc(type=0x85bf90 "rte_services", size=8192, socket_arg=-1, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:527#90x0000000000513b54inrte_malloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket_arg=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:54#100x0000000000513bc8inrte_zmalloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:72#110x0000000000513c00inrte_zmalloc(type=0x85bf90 "rte_services", size=8192, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:81#120x0000000000513c90inrte_calloc(type=0x85bf90 "rte_services", num=64, size=128, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:99#130x0000000000518cecinrte_service_init() at/root/clean/dpdk/lib/librte_eal/common/rte_service.c:81#140x00000000004f55f4inrte_eal_init(argc=3, argv=0xfffffffff488) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:959#150x000000000045af5cin main (argc=3, argv=0xfffffffff488) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Also, I have tried running with --legacy-mem but I'm stuck in
pci_find_max_end_valoop becauserte_fbarray_find_next_usedalways return
0. >
HugePages_Total: 15
HugePages_Free: 11
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 524288 kBCall Stack:
(gdb) bt
#0find_next(arr=0xffffb7fb009c, start=0, used=true) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:248#10x00000000005132a8inrte_fbarray_find_next_used(arr=0xffffb7fb009c, start=0) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:700#20x000000000052d030inpci_find_max_end_va() at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:138
#30x0000000000530ab8inpci_vfio_map_resource_primary(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:499#40x0000000000530ffcinpci_vfio_map_resource(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:601#50x000000000052ce90inrte_pci_map_device(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:75
#60x0000000000531a20inrte_pci_probe_one_driver(dr=0x997e20 <rte_nicvf_pmd>, dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:164
#70x0000000000531c68inpci_probe_all_drivers(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:249#80x0000000000531f68inrte_pci_probe() at/root/clean/dpdk/drivers/bus/pci/pci_common.c:359
#90x000000000050a140inrte_bus_probe() at/root/clean/dpdk/lib/librte_eal/common/eal_common_bus.c:98#100x00000000004f55f4inrte_eal_init(argc=1, argv=0xfffffffff498) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:967#110x000000000045af5cin main (argc=1, argv=0xfffffffff498) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Quoted 1 line
Am I missing something here?
I'll look into those, thanks!
Btw, i've now set up a github repo with the patchset applied:
https://github.com/anatolyburakov/dpdk
I will be pushing quick fixes there before spinning new revisions, so we can discover and fix bugs more rapidly. I'll fix compile issues reported earlier, then i'll take a look at your issues. The latter one seems like a typo, the former is probably a matter of moving things around a bit.
Quoted 5 lines
(also, pull requests welcome if you find it easier to fix things yourself and submit patches against my tree!)
Thanks for testing.
I've looked into the failures.
The VFIO one is not actually a failure. It only prints out errors because
rte_mallocis called before VFIO is initialized. However, once VFIO *is* initialized, all of that memory would be added to VFIO, so these error messages are harmless. Regardless, i've added a check to see if init is finished before printing out those errors, so they won't be printed out any more.Second one is a typo on my part that got lost in one of the rebases.
Quoted 8 lines
Quoted 2 lines
I've pushed fixes for both into the github repo.
Although i do wonder where do the DMA remapping errors come from. The error message says "invalid argument", so that doesn't come from
rte_serviceor anything to do withrte_malloc- this is us not providing valid arguments to VFIO. I'm not seeing these errors on my system. I'll check on others to be sure.
Quoted 3 lines
I have taken a look at the github tree the issues with VFIO are gone, Although compilation issues with dpaa/dpaa2 are still present due to their dependency on
rte_eal_get_physmem_layout.
I've fixed the dpaa compile issue and pushed it to github. I've tried to keep the semantics the same as before, but i can't compile-test (let alone test-test) them as i don't have access to a system with dpaa bus.
Also, you might want to know that dpaa bus driver references RTE_LIBRTE_DPAA_MAX_CRYPTODEV which is only found in config/common_armv8a_linuxapp but is not present in base config. Not sure if that's an issue.
Quoted 9 lines
Quoted 5 lines
--
Thanks,
AnatolyThanks,
Pavan
Signature · 2 lines
Thanks, Anatoly
Quoted 185 lines · Anatoly
Quoted 180 lines · Pavan Nikhilesh
Quoted 170 lines · Anatoly
Quoted 169 lines · Anatoly
Quoted 151 lines · Anatoly
Quoted 136 lines · Pavan Nikhilesh
Hi Anatoly,
We are currently facing issues with running testpmd on thunderx platform.
The issue seems to be with vfioEAL: Detected 24 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: No free hugepages reported in hugepages-2048kB
EAL: Multi-process socket/var/run/.rte_unix
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: VFIO support not initialized<snip>
EAL: probe driver: 177d:a053
octeontx_fpavf
EAL: PCI device 0001:01:00.1 on NUMA socket 0
EAL: probe driver: 177d:a034net_thunderx
EAL: using IOMMU type 1 (Type 1)
EAL: cannot set up DMA remapping, error 22 (Invalid argument) EAL: 0001:01:00.1 DMA remapping failed, error 22 (Invalid argument)
EAL: Requested device 0001:01:00.1 cannot be used
EAL: PCI device 0001:01:00.2 on NUMA socket 0
<snip>
testpmd: No probed ethernet devices
testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=251456, size=2176, socket=0
testpmd: preferred mempool ops selected:ring_mp_mc
EAL: VFIO support not initialized
EAL: VFIO support not initialized
EAL: VFIO support not initialized
DoneThis is because
rte_service_init()callsrte_calloc()beforerte_bus_probe()andvfio_dma_mem_mapfails because iommu type is not set.Call stack:
gdb) bt
#0vfio_dma_mem_map(vaddr=281439006359552, iova=11274289152, len=536870912, do_map=1) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:967#10x00000000004fd974inrte_vfio_dma_map(vaddr=281439006359552, iova=11274289152, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:988#20x00000000004fbe78invfio_mem_event_callback(type=RTE_MEM_EVENT_ALLOC, addr=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal_vfio.c:240#30x00000000005070acineal_memalloc_notify(event=RTE_MEM_EVENT_ALLOC, start=0xfff7a0000000, len=536870912) at/root/clean/dpdk/lib/librte_eal/common/eal_common_memalloc.c:177#40x0000000000515c98intry_expand_heap_primary(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:247#50x0000000000515e94intry_expand_heap(heap=0xffffb7fb167c, pg_sz=536870912, elt_size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:327#60x00000000005163a0inalloc_more_mem_on_socket(heap=0xffffb7fb167c, size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:455#70x0000000000516514inheap_alloc_on_socket(type=0x85bf90 "rte_services", size=8192, socket=0, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:491#80x0000000000516664inmalloc_heap_alloc(type=0x85bf90 "rte_services", size=8192, socket_arg=-1, flags=0, align=128, bound=0, contig=false) at/root/clean/dpdk/lib/librte_eal/common/malloc_heap.c:527#90x0000000000513b54inrte_malloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket_arg=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:54#100x0000000000513bc8inrte_zmalloc_socket(type=0x85bf90 "rte_services", size=8192, align=128, socket=-1) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:72#110x0000000000513c00inrte_zmalloc(type=0x85bf90 "rte_services", size=8192, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:81#120x0000000000513c90inrte_calloc(type=0x85bf90 "rte_services", num=64, size=128, align=128) at/root/clean/dpdk/lib/librte_eal/common/rte_malloc.c:99#130x0000000000518cecinrte_service_init() at/root/clean/dpdk/lib/librte_eal/common/rte_service.c:81#140x00000000004f55f4inrte_eal_init(argc=3, argv=0xfffffffff488) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:959#150x000000000045af5cin main (argc=3, argv=0xfffffffff488) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Also, I have tried running with --legacy-mem but I'm stuck in
pci_find_max_end_valoop becauserte_fbarray_find_next_usedalways return
0. >
HugePages_Total: 15
HugePages_Free: 11
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 524288 kBCall Stack:
(gdb) bt
#0find_next(arr=0xffffb7fb009c, start=0, used=true) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:248#10x00000000005132a8inrte_fbarray_find_next_used(arr=0xffffb7fb009c, start=0) at/root/clean/dpdk/lib/librte_eal/common/eal_common_fbarray.c:700#20x000000000052d030inpci_find_max_end_va() at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:138
#30x0000000000530ab8inpci_vfio_map_resource_primary(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:499#40x0000000000530ffcinpci_vfio_map_resource(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci_vfio.c:601#50x000000000052ce90inrte_pci_map_device(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/linux/pci.c:75
#60x0000000000531a20inrte_pci_probe_one_driver(dr=0x997e20 <rte_nicvf_pmd>, dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:164
#70x0000000000531c68inpci_probe_all_drivers(dev=0xeae700) at/root/clean/dpdk/drivers/bus/pci/pci_common.c:249#80x0000000000531f68inrte_pci_probe() at/root/clean/dpdk/drivers/bus/pci/pci_common.c:359
#90x000000000050a140inrte_bus_probe() at/root/clean/dpdk/lib/librte_eal/common/eal_common_bus.c:98#100x00000000004f55f4inrte_eal_init(argc=1, argv=0xfffffffff498) at/root/clean/dpdk/lib/librte_eal/linuxapp/eal/eal.c:967#110x000000000045af5cin main (argc=1, argv=0xfffffffff498) at/root/clean/dpdk/app/test-pmd/testpmd.c:2483Quoted 1 line
Am I missing something here?
I'll look into those, thanks!
Btw, i've now set up a github repo with the patchset applied:
https://github.com/anatolyburakov/dpdk
I will be pushing quick fixes there before spinning new revisions, so we can discover and fix bugs more rapidly. I'll fix compile issues reported earlier, then i'll take a look at your issues. The latter one seems like a typo, the former is probably a matter of moving things around a bit.
Quoted 5 lines
(also, pull requests welcome if you find it easier to fix things yourself and submit patches against my tree!)
Thanks for testing.
I've looked into the failures.
The VFIO one is not actually a failure. It only prints out errors because
rte_mallocis called before VFIO is initialized. However, once VFIO *is* initialized, all of that memory would be added to VFIO, so these error messages are harmless. Regardless, i've added a check to see if init is finished before printing out those errors, so they won't be printed out any more.Second one is a typo on my part that got lost in one of the rebases.
Quoted 8 lines
Quoted 2 lines
I've pushed fixes for both into the github repo.
Although i do wonder where do the DMA remapping errors come from. The error message says "invalid argument", so that doesn't come from
rte_serviceor anything to do withrte_malloc- this is us not providing valid arguments to VFIO. I'm not seeing these errors on my system. I'll check on others to be sure.Quoted 3 lines
I have taken a look at the github tree the issues with VFIO are gone, Although compilation issues with dpaa/dpaa2 are still present due to their dependency on
rte_eal_get_physmem_layout.
Quoted 8 lines
I've fixed the dpaa compile issue and pushed it to github. I've tried to keep the semantics the same as before, but i can't compile-test (let alone test-test) them as i don't have access to a system with dpaa bus.
Also, you might want to know that dpaa bus driver references
RTE_LIBRTE_DPAA_MAX_CRYPTODEVwhich is only found in config/common_armv8a_linuxapp but is not present in base config. Not sure if that's an issue.
Hi anatoly,
I've checkout your branch on github
commit 61e6876fd1d2 ("remove panic from memalloc")
I am compiling it with clang:
clang version 3.8.1-24 (tags/RELEASE_381/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
There are a lot of compilation errors not present on DPDK branch. They need to be fixed.
Thanks,
Signature · 2 lines
Nélio Laranjeiro 6WIND
Hello Anatoly,
Quoted 1 line · Anatoly
On 09-Mar-18 9:15 AM, Pavan Nikhilesh wrote:
[...]
Quoted 9 lines
Quoted 7 lines
I have taken a look at the github tree the issues with VFIO are gone, Although
compilation issues with dpaa/dpaa2 are still present due to their dependency onrte_eal_get_physmem_layout.
Quoted 3 lines
I've fixed the dpaa compile issue and pushed it to github. I've tried to keep the semantics the same as before, but i can't compile-test (let alone test-test) them as i don't have access to a system with dpaa bus.
Thanks. I will have a look at this.
Quoted 6 lines
Also, you might want to know that dpaa bus driver references
RTE_LIBRTE_DPAA_MAX_CRYPTODEVwhich is only found in config/common_armv8a_linuxapp but is not present in base config. Not sure if that's an issue.
This might be an issue as very recently some patches updated the base config. I will cross check this as well.
-
Shreyansh
Hello Anatoly,
Quoted 17 lines · Shreyansh Jain
Hello Anatoly,
Quoted 1 line · Anatoly
On 09-Mar-18 9:15 AM, Pavan Nikhilesh wrote:
[...]
Quoted 9 lines
Quoted 7 lines
I have taken a look at the github tree the issues with VFIO are gone, Although
compilation issues with dpaa/dpaa2 are still present due to their dependency onrte_eal_get_physmem_layout.
Quoted 5 lines
Quoted 3 lines
I've fixed the dpaa compile issue and pushed it to github. I've tried to keep the semantics the same as before, but i can't compile-test (let alone test-test) them as i don't have access to a system with dpaa bus.
Thanks. I will have a look at this.
Just a heads-up, DPAA2 is broken on top-of-tree (github:784e041f6b520) as of now:
--->8---
root@ls2088ardb:~/shreyansh/07_dpdk_memory# ./arm64-dpaa2-linuxapp-gcc/app/testpmd -c 0xE -n 1 --log-level=eal,8 --log-level=mem,8 -- -i --portmask=0x3
EAL: Detected lcore 0 as core 0 on socket 0 EAL: Detected lcore 1 as core 1 on socket 0 EAL: Detected lcore 2 as core 0 on socket 0 EAL: Detected lcore 3 as core 1 on socket 0 EAL: Detected lcore 4 as core 0 on socket 0 EAL: Detected lcore 5 as core 1 on socket 0 EAL: Detected lcore 6 as core 0 on socket 0 EAL: Detected lcore 7 as core 1 on socket 0 EAL: Support maximum 16 logical core(s) by configuration. EAL: Detected 8 lcore(s) EAL: Detected 1 NUMA nodes EAL: VFIO PCI modules not loaded EAL: DPAA Bus not present. Skipping. EAL: Container: dprc.2 has VFIO iommu group id = 4 EAL: fslmc: Bus scan completed EAL: Module /sys/module/rte_kni not found! error 2 (No such file or directory) EAL: Multi-process socket /var/run/.rte_unix EAL: Probing VFIO support... EAL: IOMMU type 1 (Type 1) is supported EAL: IOMMU type 7 (sPAPR) is not supported EAL: IOMMU type 8 (No-IOMMU) is not supported EAL: VFIO support initialized EAL: Mem event callback 'vfio_mem_event_clb' registered EAL: Ask a virtual area of 0x2e000 bytes EAL: Virtual area found at 0xffff86cae000 (size = 0x2e000) EAL: Setting up physically contiguous memory... EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873f000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xfff780000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873e000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffef40000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873d000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffe700000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873c000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffdec0000000 (size = 0x800000000) EAL: TSC frequency is ~25000 KHz EAL: Master lcore 1 is ready (tid=88742110;cpuset=[1]) EAL: lcore 3 is ready (tid=85cab910;cpuset=[3]) EAL: lcore 2 is ready (tid=864ab910;cpuset=[2]) EAL: eal_memalloc_alloc_page_bulk(): couldn't find suitable memseg_list
error allocating rte services array
EAL: FATAL: rte_service_init() failed
EAL: rte_service_init() failed
PANIC in main():
Cannot init EAL
1: [./arm64-dpaa2-linuxapp-gcc/app/testpmd(rte_dump_stack+0x38) [0x4f37a8]] Aborted
--->8--
Above is an initial output - still investigating. I will keep you posted.
Quoted 6 lines
Quoted 6 lines
Also, you might want to know that dpaa bus driver references
RTE_LIBRTE_DPAA_MAX_CRYPTODEVwhich is only found in config/common_armv8a_linuxapp but is not present in base config. Not sure if that's an issue.
A recent patch from Hemant has fixed this (yet to be merged in master).
[...]
-
Shreyansh
Hello Anatoly,
This is not necessarily right chain to reply to, but reusing this email for another issue in DPAA2 so that all issues can be at a single place.
Quoted 89 lines · Shreyansh Jain
Hello Anatoly,
Quoted 17 lines · Shreyansh Jain
Hello Anatoly,
Quoted 1 line · Anatoly
On 09-Mar-18 9:15 AM, Pavan Nikhilesh wrote:
[...]
Quoted 9 lines
Quoted 7 lines
I have taken a look at the github tree the issues with VFIO are gone, Although
compilation issues with dpaa/dpaa2 are still present due to their dependency onrte_eal_get_physmem_layout.Quoted 5 lines
Quoted 3 lines
I've fixed the dpaa compile issue and pushed it to github. I've tried to keep the semantics the same as before, but i can't compile-test (let alone test-test) them as i don't have access to a system with dpaa bus.
Thanks. I will have a look at this.
Just a heads-up, DPAA2 is broken on top-of-tree (github:
784e041f6b520) as of now:--->8---
root@ls2088ardb:~/shreyansh/07_dpdk_memory# ./arm64-dpaa2-linuxapp-gcc/app/testpmd -c0xE-n 1 --log-level=eal,8 --log-level=mem,8 -- -i --portmask=0x3EAL: Detected lcore 0 as core 0 on socket 0 EAL: Detected lcore 1 as core 1 on socket 0 EAL: Detected lcore 2 as core 0 on socket 0 EAL: Detected lcore 3 as core 1 on socket 0 EAL: Detected lcore 4 as core 0 on socket 0 EAL: Detected lcore 5 as core 1 on socket 0 EAL: Detected lcore 6 as core 0 on socket 0 EAL: Detected lcore 7 as core 1 on socket 0 EAL: Support maximum 16 logical core(s) by configuration. EAL: Detected 8 lcore(s) EAL: Detected 1 NUMA nodes EAL: VFIO PCI modules not loaded EAL: DPAA Bus not present. Skipping. EAL: Container: dprc.2 has VFIO iommu group id = 4 EAL: fslmc: Bus scan completed EAL: Module /sys/module/rte_kni not found! error 2 (No such file or directory) EAL: Multi-process socket /var/run/.rte_unix EAL: Probing VFIO support... EAL: IOMMU type 1 (Type 1) is supported EAL: IOMMU type 7 (sPAPR) is not supported EAL: IOMMU type 8 (No-IOMMU) is not supported EAL: VFIO support initialized EAL: Mem event callback 'vfio_mem_event_clb' registered EAL: Ask a virtual area of 0x2e000 bytes EAL: Virtual area found at 0xffff86cae000 (size = 0x2e000) EAL: Setting up physically contiguous memory... EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873f000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xfff780000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873e000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffef40000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873d000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffe700000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873c000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffdec0000000 (size = 0x800000000) EAL: TSC frequency is ~25000 KHz EAL: Master lcore 1 is ready (tid=88742110;cpuset=[1]) EAL: lcore 3 is ready (tid=85cab910;cpuset=[3]) EAL: lcore 2 is ready (tid=864ab910;cpuset=[2]) EAL: eal_memalloc_alloc_page_bulk(): couldn't find suitable memseg_listerror allocating rte services array
EAL: FATAL:rte_service_init()failedEAL:
rte_service_init()failed
Quoted 8 lines
PANIC in
main():
Cannot init EAL
1: [./arm64-dpaa2-linuxapp-gcc/app/testpmd(rte_dump_stack+0x38) [0x4f37a8]] Aborted
--->8--Above is an initial output - still investigating. I will keep you posted.
While working on issue reported in [1], I have found another issue which I might need you help.
[1] http://dpdk.org/ml/archives/dev/2018-March/093202.html
For [1], I bypassed by changing the mempool_add_elem code for time being - it now allows non-contiguous (not explicitly demanded contiguous) allocations to go through rte_mempool_populate_iova. With that, I was able to get DPAA2 working.
Problem is:
1. When I am working with 1GB pages, I/O is working fine.
2. When using 2MB pages (1024 num), the initialization somewhere after VFIO layer fails.
All with IOVA=VA mode.
Some logs:
This is the output of the virtual memory layout demanded by DPDK:
--->8---
EAL: Ask a virtual area of 0x2e000 bytes
EAL: Virtual area found at 0xffffb6561000 (size = 0x2e000)
EAL: Setting up physically contiguous memory...
EAL: Ask a virtual area of 0x59000 bytes
EAL: Virtual area found at 0xffffb6508000 (size = 0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of 0x400000000 bytes
EAL: Virtual area found at 0xfffbb6400000 (size = 0x400000000)
EAL: Ask a virtual area of 0x59000 bytes
EAL: Virtual area found at 0xfffbb62af000 (size = 0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of 0x400000000 bytes
EAL: Virtual area found at 0xfff7b6200000 (size = 0x400000000)
EAL: Ask a virtual area of 0x59000 bytes
EAL: Virtual area found at 0xfff7b6056000 (size = 0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of 0x400000000 bytes
EAL: Virtual area found at 0xfff3b6000000 (size = 0x400000000)
EAL: Ask a virtual area of 0x59000 bytes
EAL: Virtual area found at 0xfff3b5dfd000 (size = 0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of 0x400000000 bytes
EAL: Virtual area found at 0xffefb5c00000 (size = 0x400000000) --->8---
Then, somehow VFIO mapping is able to find only a single page to map
--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size 0x200000
EAL: Total 1 segments found.
--->8---
Then, these logs appear probably when DPAA2 code requests for memory. I am not sure why it repeats the same '...expanded by 10MB'.
--->8---
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 2MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callback vfio_mem_event_clbEAL: request: mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
LPM or EM none selected, default LPM on
Initializing port 0 ...
--->8---
l3fwd is stuck at this point. What I observe is that DPAA2 driver has gone ahead to register the queues (queue_setup) with hardware and the memory has either overrun (smaller than requested size mapped) or the addresses are corrupt (that is, not dma-able). (I get SMMU faults, indicating one of these cases)
There is some change from you in the fslmc/fslmc_vfio.c file (rte_fslmc_vfio_dmamap()). Ideally, that code should have walked over all the available pages for mapping but that didn't happen and only a single virtual area got dma-mapped.
--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size 0x200000
EAL: Total 1 segments found.
--->8---
I am looking into this but if there is some hint which come to your mind, it might help.
Regards,
Shreyansh
Quoted 205 lines · Shreyansh Jain
Hello Anatoly,
This is not necessarily right chain to reply to, but reusing this email for another issue in DPAA2 so that all issues can be at a single place.
Quoted 89 lines · Shreyansh Jain
Hello Anatoly,
Quoted 17 lines · Shreyansh Jain
Hello Anatoly,
Quoted 1 line · Anatoly
On 09-Mar-18 9:15 AM, Pavan Nikhilesh wrote:
[...]
Quoted 9 lines
Quoted 7 lines
I have taken a look at the github tree the issues with VFIO are gone, Although
compilation issues with dpaa/dpaa2 are still present due to their dependency onrte_eal_get_physmem_layout.Quoted 5 lines
Quoted 3 lines
I've fixed the dpaa compile issue and pushed it to github. I've tried to keep the semantics the same as before, but i can't compile-test (let alone test-test) them as i don't have access to a system with dpaa bus.
Thanks. I will have a look at this.
Just a heads-up, DPAA2 is broken on top-of-tree (github:
784e041f6b520) as of now:--->8---
root@ls2088ardb:~/shreyansh/07_dpdk_memory# ./arm64-dpaa2-linuxapp-gcc/app/testpmd -c0xE-n 1 --log-level=eal,8 --log-level=mem,8 -- -i --portmask=0x3EAL: Detected lcore 0 as core 0 on socket 0 EAL: Detected lcore 1 as core 1 on socket 0 EAL: Detected lcore 2 as core 0 on socket 0 EAL: Detected lcore 3 as core 1 on socket 0 EAL: Detected lcore 4 as core 0 on socket 0 EAL: Detected lcore 5 as core 1 on socket 0 EAL: Detected lcore 6 as core 0 on socket 0 EAL: Detected lcore 7 as core 1 on socket 0 EAL: Support maximum 16 logical core(s) by configuration. EAL: Detected 8 lcore(s) EAL: Detected 1 NUMA nodes EAL: VFIO PCI modules not loaded EAL: DPAA Bus not present. Skipping. EAL: Container: dprc.2 has VFIO iommu group id = 4 EAL: fslmc: Bus scan completed EAL: Module /sys/module/rte_kni not found! error 2 (No such file or directory) EAL: Multi-process socket /var/run/.rte_unix EAL: Probing VFIO support... EAL: IOMMU type 1 (Type 1) is supported EAL: IOMMU type 7 (sPAPR) is not supported EAL: IOMMU type 8 (No-IOMMU) is not supported EAL: VFIO support initialized EAL: Mem event callback 'vfio_mem_event_clb' registered EAL: Ask a virtual area of 0x2e000 bytes EAL: Virtual area found at 0xffff86cae000 (size = 0x2e000) EAL: Setting up physically contiguous memory... EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873f000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xfff780000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873e000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffef40000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873d000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffe700000000 (size = 0x800000000) EAL: Ask a virtual area of 0x1000 bytes EAL: Virtual area found at 0xffff8873c000 (size = 0x1000) EAL: Memseg list allocated: 0x100000kB at socket 0 EAL: Ask a virtual area of 0x800000000 bytes EAL: Virtual area found at 0xffdec0000000 (size = 0x800000000) EAL: TSC frequency is ~25000 KHz EAL: Master lcore 1 is ready (tid=88742110;cpuset=[1]) EAL: lcore 3 is ready (tid=85cab910;cpuset=[3]) EAL: lcore 2 is ready (tid=864ab910;cpuset=[2]) EAL: eal_memalloc_alloc_page_bulk(): couldn't find suitable memseg_listerror allocating rte services array
EAL: FATAL:rte_service_init()failedEAL:
rte_service_init()failedQuoted 8 lines
PANIC in
main():
Cannot init EAL
1: [./arm64-dpaa2-linuxapp-gcc/app/testpmd(rte_dump_stack+0x38) [0x4f37a8]] Aborted
--->8--Above is an initial output - still investigating. I will keep you posted.
While working on issue reported in [1], I have found another issue which I might need you help.
[1] http://dpdk.org/ml/archives/dev/2018-March/093202.html
For [1], I bypassed by changing the
mempool_add_elemcode for time being - it now allows non-contiguous (not explicitly demanded contiguous) allocations to go throughrte_mempool_populate_iova. With that, I was able to get DPAA2 working.Problem is:
1. When I am working with 1GB pages, I/O is working fine.
2. When using 2MB pages (1024 num), the initialization somewhere after VFIO layer fails.All with IOVA=VA mode.
Some logs:
This is the output of the virtual memory layout demanded by DPDK:
--->8---
EAL: Ask a virtual area of0x2e000bytes
EAL: Virtual area found at0xffffb6561000(size =0x2e000)
EAL: Setting up physically contiguous memory...
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xffffb6508000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfffbb6400000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfffbb62af000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfff7b6200000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfff7b6056000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfff3b6000000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfff3b5dfd000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xffefb5c00000(size =0x400000000) --->8---Then, somehow VFIO mapping is able to find only a single page to map
--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size0x200000
EAL: Total 1 segments found.
--->8---Then, these logs appear probably when DPAA2 code requests for memory. I am not sure why it repeats the same '...expanded by 10MB'.
--->8---
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 2MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:mp_malloc_sync
EAL: Heap on socket 0 was expanded by 10MB
LPM or EM none selected, default LPM on
Initializing port 0 ...
--->8---l3fwd is stuck at this point. What I observe is that DPAA2 driver has gone ahead to register the queues (
queue_setup) with hardware and the memory has either overrun (smaller than requested size mapped) or the addresses are corrupt (that is, not dma-able). (I get SMMU faults, indicating one of these cases)There is some change from you in the
fslmc/fslmc_vfio.cfile (rte_fslmc_vfio_dmamap()). Ideally, that code should have walked over all the available pages for mapping but that didn't happen and only a single virtual area got dma-mapped.--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size0x200000
EAL: Total 1 segments found.
--->8---
Quoted 6 lines
I am looking into this but if there is some hint which come to your mind, it might help.
Regards,
Shreyansh
Hi Shreyansh,
Thanks for the feedback.
The "heap on socket 0 was expanded by 10MB" has to do with synchronization requests in primary/secondary processes. I can see you're allocating LPM tables - that's most likely what these allocations are about (it's hotplugging memory).
I think i might have an idea what is going on. I am assuming that you are starting up your DPDK application without any -m or --socket-mem flags, which means you are starting with empty heap.
During initialization, certain DPDK features (such as service cores, PMD's) allocate memory. Most likely you have essentially started up with 1 2M page, which is what you see in fslmc logs: this page gets mapped for VFIO.
Then, you allocate a bunch of LPM tables, which trigger more memory allocation, and trigger memory allocation callbacks registered through rte_mem_event_register_callback(). One of these callbacks is a VFIO callback, which is registered in eal_vfio.c:rte_vfio_enable(). However, since fslmc bus has its own VFIO implementation that is independent of what happens in EAL VFIO code, what probably happens is that the fslmc bus misses the necessary messages from the memory hotplug to map additional resources for DMA.
Try adding a rte_mem_event_register_callback() somewhere in fslmc init so that it calls necessary map function. eal_vfio.c:vfio_mem_event_callback() should provide a good template on how to approach creating such a callback. Let me know if this works!
(as a side note, how can we extend VFIO to move this stuff back into EAL and expose it as an API?)
Signature · 2 lines
Thanks, Anatoly
Hello Anatoly,
Quoted 7 lines
-----Original Message-----
From: Burakov, Anatoly [mailto:[email protected]]
Sent: Wednesday, March 21, 2018 8:18 PM
To: Shreyansh Jain <[email protected]>
Cc: [email protected]; Hemant Agrawal <[email protected]>
Subject: Re: [dpdk-dev] [PATCH v2 00/41] Memory Hotplug for DPDK
[...]
Quoted 124 lines
Quoted 6 lines
Quoted 1 line
While working on issue reported in [1], I have found another issue which I might need you help.
[1]
https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdpdk.o
rg%2Fml%2Farchives%2Fdev%2F2018- March%2F093202.html&data=02%7C01%7Cshreyansh.jain%40nxp.com%7C5faee716e6 fc4908bdb608d58f3ad1e5%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6365 72405182868376&sdata=WohDdktHHAuNDnss1atuixSa%2FqC7HRMSDVCtFC9Vnto%3D&re served=0Quoted 52 lines
For [1], I bypassed by changing the
mempool_add_elemcode for time being - it now allows non-contiguous (not explicitly demanded contiguous) allocations to go throughrte_mempool_populate_iova. With that, I was able to get DPAA2 working.Problem is:
1. When I am working with 1GB pages, I/O is working fine.
2. When using 2MB pages (1024 num), the initialization somewhere after VFIO layer fails.All with IOVA=VA mode.
Some logs:
This is the output of the virtual memory layout demanded by DPDK:
--->8---
EAL: Ask a virtual area of0x2e000bytes
EAL: Virtual area found at0xffffb6561000(size =0x2e000)
EAL: Setting up physically contiguous memory...
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xffffb6508000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfffbb6400000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfffbb62af000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfff7b6200000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfff7b6056000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfff3b6000000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfff3b5dfd000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xffefb5c00000(size =0x400000000) --->8---Then, somehow VFIO mapping is able to find only a single page to map
--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size0x200000
EAL: Total 1 segments found.
--->8---Quoted 5 lines
Then, these logs appear probably when DPAA2 code requests for memory. I am not sure why it repeats the same '...expanded by 10MB'.
--->8---
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 2MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 23 lines
EAL: Heap on socket 0 was expanded by 10MB
LPM or EM none selected, default LPM on
Initializing port 0 ...
--->8---l3fwd is stuck at this point. What I observe is that DPAA2 driver has gone ahead to register the queues (
queue_setup) with hardware and the memory has either overrun (smaller than requested size mapped) or the addresses are corrupt (that is, not dma-able). (I get SMMU faults, indicating one of these cases)There is some change from you in the
fslmc/fslmc_vfio.cfile (rte_fslmc_vfio_dmamap()). Ideally, that code should have walked over all the available pages for mapping but that didn't happen and only a single virtual area got dma-mapped.--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size0x200000
EAL: Total 1 segments found.
--->8---Quoted 6 lines
I am looking into this but if there is some hint which come to your mind, it might help.
Regards,
Shreyansh
Quoted 8 lines
Hi Shreyansh,
Thanks for the feedback.
The "heap on socket 0 was expanded by 10MB" has to do with synchronization requests in primary/secondary processes. I can see you're allocating LPM tables - that's most likely what these allocations are about (it's hotplugging memory).
I get that but why same message multiple times without any change in the expansion. Further, I don't have multiple process - in fact, I'm working with a single datapath thread. Anyways, I will look through the code for this.
Quoted 4 lines
I think i might have an idea what is going on. I am assuming that you are starting up your DPDK application without any -m or --socket-mem flags, which means you are starting with empty heap.
Yes, no specific --socket-mem passed as argument.
Quoted 5 lines
During initialization, certain DPDK features (such as service cores, PMD's) allocate memory. Most likely you have essentially started up with 1 2M page, which is what you see in fslmc logs: this page gets mapped for VFIO.
Agree.
Quoted 9 lines
Then, you allocate a bunch of LPM tables, which trigger more memory allocation, and trigger memory allocation callbacks registered through
rte_mem_event_register_callback(). One of these callbacks is a VFIO callback, which is registered in eal_vfio.c:rte_vfio_enable(). However, since fslmc bus has its own VFIO implementation that is independent of what happens in EAL VFIO code, what probably happens is that the fslmc bus misses the necessary messages from the memory hotplug to map additional resources for DMA.
Makes sense
Quoted 5 lines
Try adding a
rte_mem_event_register_callback()somewhere in fslmc init so that it calls necessary map function. eal_vfio.c:vfio_mem_event_callback() should provide a good template on how to approach creating such a callback. Let me know if this works!
OK. I will give this a try and update you.
Quoted 3 lines
(as a side note, how can we extend VFIO to move this stuff back into EAL and expose it as an API?)
The problem is that FSLMC VFIO driver is slightly different from generic VFIO layer in the sense that device in a VFIO container is actually another level of container. Anyways, I will have a look how much generalization is possible. Or else, I will work with the vfio_mem_event_callback() as suggested above.
Thanks for suggestions.
Quoted 4 lines
--
Thanks,
Anatoly
Quoted 140 lines · Shreyansh Jain
Hello Anatoly,
Quoted 7 lines
-----Original Message-----
From: Burakov, Anatoly [mailto:[email protected]]
Sent: Wednesday, March 21, 2018 8:18 PM
To: Shreyansh Jain <[email protected]>
Cc: [email protected]; Hemant Agrawal <[email protected]>
Subject: Re: [dpdk-dev] [PATCH v2 00/41] Memory Hotplug for DPDK[...]
Quoted 128 lines
Quoted 6 lines
Quoted 1 line
While working on issue reported in [1], I have found another issue which I might need you help.
[1]
https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdpdk.o
rg%2Fml%2Farchives%2Fdev%2F2018- March%2F093202.html&data=02%7C01%7Cshreyansh.jain%40nxp.com%7C5faee716e6 fc4908bdb608d58f3ad1e5%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6365 72405182868376&sdata=WohDdktHHAuNDnss1atuixSa%2FqC7HRMSDVCtFC9Vnto%3D&re served=0Quoted 52 lines
For [1], I bypassed by changing the
mempool_add_elemcode for time being - it now allows non-contiguous (not explicitly demanded contiguous) allocations to go throughrte_mempool_populate_iova. With that, I was able to get DPAA2 working.Problem is:
1. When I am working with 1GB pages, I/O is working fine.
2. When using 2MB pages (1024 num), the initialization somewhere after VFIO layer fails.All with IOVA=VA mode.
Some logs:
This is the output of the virtual memory layout demanded by DPDK:
--->8---
EAL: Ask a virtual area of0x2e000bytes
EAL: Virtual area found at0xffffb6561000(size =0x2e000)
EAL: Setting up physically contiguous memory...
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xffffb6508000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfffbb6400000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfffbb62af000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfff7b6200000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfff7b6056000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xfff3b6000000(size =0x400000000)
EAL: Ask a virtual area of0x59000bytes
EAL: Virtual area found at0xfff3b5dfd000(size =0x59000)
EAL: Memseg list allocated: 0x800kB at socket 0
EAL: Ask a virtual area of0x400000000bytes
EAL: Virtual area found at0xffefb5c00000(size =0x400000000) --->8---Then, somehow VFIO mapping is able to find only a single page to map
--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size0x200000
EAL: Total 1 segments found.
--->8---Quoted 5 lines
Then, these logs appear probably when DPAA2 code requests for memory. I am not sure why it repeats the same '...expanded by 10MB'.
--->8---
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 2MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 2 lines
EAL: Heap on socket 0 was expanded by 10MB
EAL: Calling mem event callbackvfio_mem_event_clbEAL: request:
mp_malloc_syncQuoted 23 lines
EAL: Heap on socket 0 was expanded by 10MB
LPM or EM none selected, default LPM on
Initializing port 0 ...
--->8---l3fwd is stuck at this point. What I observe is that DPAA2 driver has gone ahead to register the queues (
queue_setup) with hardware and the memory has either overrun (smaller than requested size mapped) or the addresses are corrupt (that is, not dma-able). (I get SMMU faults, indicating one of these cases)There is some change from you in the
fslmc/fslmc_vfio.cfile (rte_fslmc_vfio_dmamap()). Ideally, that code should have walked over all the available pages for mapping but that didn't happen and only a single virtual area got dma-mapped.--->8---
EAL: Device (dpci.1) abstracted from VFIO
EAL: -->Initial SHM Virtual ADDR FFFBB6400000
EAL: -----> DMA size0x200000
EAL: Total 1 segments found.
--->8---Quoted 6 lines
I am looking into this but if there is some hint which come to your mind, it might help.
Regards,
ShreyanshHi Shreyansh,
Thanks for the feedback.
Quoted 8 lines
Quoted 4 lines
The "heap on socket 0 was expanded by 10MB" has to do with synchronization requests in primary/secondary processes. I can see you're allocating LPM tables - that's most likely what these allocations are about (it's hotplugging memory).
I get that but why same message multiple times without any change in the expansion. Further, I don't have multiple process - in fact, I'm working with a single datapath thread. Anyways, I will look through the code for this.
Hi Shreyansh,
I've misspoke - this has nothing to do with multiprocess. The "request: mp_malloc_sync" does, but it's an attempt to notify other processes of the allocation - if there are no processes, nothing happens.
However, multiple heap expansions do correspond to multiple allocations. If you allocate an LPM table that takes up 10M of hugepage memory - you expand heap by 10M. If you do it multiple times (e.g. per-NIC?), you do multiple heap expansions. This message will be triggered on every heap expansion.
Quoted 33 lines
Quoted 4 lines
I think i might have an idea what is going on. I am assuming that you are starting up your DPDK application without any -m or --socket-mem flags, which means you are starting with empty heap.
Yes, no specific --socket-mem passed as argument.
Quoted 5 lines
During initialization, certain DPDK features (such as service cores, PMD's) allocate memory. Most likely you have essentially started up with 1 2M page, which is what you see in fslmc logs: this page gets mapped for VFIO.
Agree.
Quoted 9 lines
Then, you allocate a bunch of LPM tables, which trigger more memory allocation, and trigger memory allocation callbacks registered through
rte_mem_event_register_callback(). One of these callbacks is a VFIO callback, which is registered in eal_vfio.c:rte_vfio_enable(). However, since fslmc bus has its own VFIO implementation that is independent of what happens in EAL VFIO code, what probably happens is that the fslmc bus misses the necessary messages from the memory hotplug to map additional resources for DMA.Makes sense
Quoted 5 lines
Try adding a
rte_mem_event_register_callback()somewhere in fslmc init so that it calls necessary map function. eal_vfio.c:vfio_mem_event_callback() should provide a good template on how to approach creating such a callback. Let me know if this works!
Quoted 7 lines
OK. I will give this a try and update you.
Quoted 3 lines
(as a side note, how can we extend VFIO to move this stuff back into EAL and expose it as an API?)
The problem is that FSLMC VFIO driver is slightly different from generic VFIO layer in the sense that device in a VFIO container is actually another level of container. Anyways, I will have a look how much generalization is possible. Or else, I will work with the
vfio_mem_event_callback()as suggested above.
This can wait :) The callback is probably the proper way to do it right now.
Quoted 7 lines
Thanks for suggestions.
Quoted 4 lines
--
Thanks,
Anatoly
Signature · 2 lines
Thanks, Anatoly
Hi Anatoly,
Quoted 46 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Dependencies (to be applied in specified order):
- IPC bugfixes patchset [2]
- IPC improvements patchset [3]
- IPC asynchronous request API patch [4]
- Function to return number of sockets [5]Deprecation notices relevant to this patchset:
- General outline of memory hotplug changes [6]
- EAL NUMA node count changes [7]The vast majority of changes are in the EAL and malloc, the external API disruption is minimal: a new set of API's are added for contiguous memory allocation for
rte_memzone, and a few API additions inrte_memorydue to switch tomemseg_listsas opposed to memsegs. Every other API change is internal to EAL, and all of the memory allocation/freeing is handled throughrte_malloc, with no externally visible API changes.Quick outline of all changes done as part of this patchset:
* Malloc heap adjusted to handle holes in address space
* Single memseg list replaced by multiple memseg lists
* VA space for hugepages is preallocated in advance
* Added alloc/free for pages happening as needed on rte_malloc/rte_free
* Added contiguous memory allocation API's forrte_memzone
* Integrated Pawel Wodkowski's patch for registering/unregistering memory with VFIO [8]
* Callbacks for registering memory allocations
* Multiprocess support done via DPDK IPC introduced in 18.02The biggest difference is a "memseg" now represents a single page (as opposed to being a big contiguous block of pages). As a consequence, both memzones and malloc elements are no longer guaranteed to be physically contiguous, unless the user asks for it at reserve time. To preserve whatever functionality that was dependent on previous behavior, a legacy memory option is also provided, however it is expected (or perhaps vainly hoped) to be temporary solution.
Why multiple memseg lists instead of one? Since memseg is a single page now, the list of memsegs will get quite big, and we need to locate pages somehow when we allocate and free them. We could of course just walk the list and allocate one contiguous chunk of VA space for memsegs, but this implementation uses separate lists instead in order to speed up many operations with memseg lists.
Quoted 3 lines
For v1 and v2, the following limitations are present:
- FreeBSD does not even compile, let alone run
- No 32-bit support
I just read on [email protected] [1] that an early merge to this series is expected. So, would this limitation be fixed before merge? Or, has it already been fixed in github repo?
[1] http://dpdk.org/ml/archives/announce/2018-March/000182.html
[...]
-
Shreyansh
Quoted 58 lines · Shreyansh Jain
Hi Anatoly,
Quoted 46 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Dependencies (to be applied in specified order):
- IPC bugfixes patchset [2]
- IPC improvements patchset [3]
- IPC asynchronous request API patch [4]
- Function to return number of sockets [5]Deprecation notices relevant to this patchset:
- General outline of memory hotplug changes [6]
- EAL NUMA node count changes [7]The vast majority of changes are in the EAL and malloc, the external API disruption is minimal: a new set of API's are added for contiguous memory allocation for
rte_memzone, and a few API additions inrte_memorydue to switch tomemseg_listsas opposed to memsegs. Every other API change is internal to EAL, and all of the memory allocation/freeing is handled throughrte_malloc, with no externally visible API changes.Quick outline of all changes done as part of this patchset:
* Malloc heap adjusted to handle holes in address space
* Single memseg list replaced by multiple memseg lists
* VA space for hugepages is preallocated in advance
* Added alloc/free for pages happening as needed on rte_malloc/rte_free
* Added contiguous memory allocation API's forrte_memzone
* Integrated Pawel Wodkowski's patch for registering/unregistering memory with VFIO [8]
* Callbacks for registering memory allocations
* Multiprocess support done via DPDK IPC introduced in 18.02The biggest difference is a "memseg" now represents a single page (as opposed to being a big contiguous block of pages). As a consequence, both memzones and malloc elements are no longer guaranteed to be physically contiguous, unless the user asks for it at reserve time. To preserve whatever functionality that was dependent on previous behavior, a legacy memory option is also provided, however it is expected (or perhaps vainly hoped) to be temporary solution.
Why multiple memseg lists instead of one? Since memseg is a single page now, the list of memsegs will get quite big, and we need to locate pages somehow when we allocate and free them. We could of course just walk the list and allocate one contiguous chunk of VA space for memsegs, but this implementation uses separate lists instead in order to speed up many operations with memseg lists.
Quoted 3 lines
For v1 and v2, the following limitations are present:
- FreeBSD does not even compile, let alone run
- No 32-bit supportI just read on [email protected] [1] that an early merge to this series is expected. So, would this limitation be fixed before merge? Or, has it already been fixed in github repo?
Quoted 7 lines
[1] http://dpdk.org/ml/archives/announce/2018-March/000182.html
[...]
-
Shreyansh
Hi Shreyansh,
It will be fixed before merge, yes. I would expect this code to arrive in Github in the next few days.
Signature · 2 lines
Thanks, Anatoly
Hello Anatoly,
Quoted 10 lines
-----Original Message-----
From: Burakov, Anatoly [mailto:[email protected]]
Sent: Tuesday, March 20, 2018 3:38 PM
To: Shreyansh Jain <[email protected]>
Cc: [email protected]; Thomas Monjalon <[email protected]>
Subject: Re: [dpdk-dev] [PATCH v2 00/41] Memory Hotplug for DPDKQuoted 2 lines · Shreyansh Jain
Hi Anatoly,
[...]
Quoted 11 lines
Quoted 6 lines
[...]
-
ShreyanshHi Shreyansh,
It will be fixed before merge, yes. I would expect this code to arrive in Github in the next few days.
I have been integrating with this patchset for considerable time now - attempting to get it working on dpaa2 and dpaa.
Thanks to your quick responses on IRC, at least the VA part of DPAA2 is functional now.
Unfortunately, I am observing a degradation in performance with the patches.
Compared to | % Impact
master (20526313ba4) |
----------------------------------------------
DPAA2 IOVA=VA (hotplug patch) | ~ -4.0% DPAA2 IOVA=VA --legacy-mem | ~ -4.5% DPAA2 (Physical) | Pending DPAA (Physical) | Pending
Theoretically, I agree with the discussion on a similar observation in [1] - but, at least as of writing this, I have no idea why the drop is occurring.
[1] http://dpdk.org/ml/archives/dev/2018-March/093685.html
As a side note - the base for hotplug memory patches and master has some differences (since c06ddf9698e0) - though, I don't see any patch in there which might impact performance. But, it might be good idea to rebase - just to remove that doubt.
I noticed that you have already fixed the issues related to IOVA==PA mapping in your recent code. I haven't had the chance to completely integrate my code against those. I will look through the patches in coming days.
Regards,
Shreyansh
v3 cover Memory Hotplug for DPDK
In reply to Anatoly BurakovThis patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Dependencies (to be applied in specified order):
- IPC asynchronous request API patch [2]
- Function to return number of sockets [3]
- EAL IOVA fix [4]
Deprecation notices relevant to this patchset:
- General outline of memory hotplug changes [5]
- EAL NUMA node count changes [6]
The vast majority of changes are in the EAL and malloc, the external API disruption is minimal: a new set of API's are added for contiguous memory allocation for rte_memzone, and a few API additions in rte_memory due to switch to memseg_lists as opposed to memsegs. Every other API change is internal to EAL, and all of the memory allocation/freeing is handled through rte_malloc, with no externally visible API changes.
Quick outline of all changes done as part of this patchset:
* Malloc heap adjusted to handle holes in address space
* Single memseg list replaced by multiple memseg lists
* VA space for hugepages is preallocated in advance
* Added alloc/free for pages happening as needed on rte_malloc/rte_free
* Added contiguous memory allocation API's for rte_memzone
* Added convenience API calls to walk over memsegs
* Integrated Pawel Wodkowski's patch for registering/unregistering memory with VFIO [7]
* Callbacks for registering memory allocations
* Callbacks for allowing/disallowing allocations above specified limit
* Multiprocess support done via DPDK IPC introduced in 18.02
The biggest difference is a "memseg" now represents a single page (as opposed to being a big contiguous block of pages). As a consequence, both memzones and malloc elements are no longer guaranteed to be physically contiguous, unless the user asks for it at reserve time. To preserve whatever functionality that was dependent on previous behavior, a legacy memory option is also provided, however it is expected (or perhaps vainly hoped) to be temporary solution.
Why multiple memseg lists instead of one? Since memseg is a single page now, the list of memsegs will get quite big, and we need to locate pages somehow when we allocate and free them. We could of course just walk the list and allocate one contiguous chunk of VA space for memsegs, but this implementation uses separate lists instead in order to speed up many operations with memseg lists.
For v3, the following limitations are present:
- VFIO support is only smoke-tested (but is expected to work), VFIO support with secondary processes is not tested; work is ongoing to validate VFIO for all use cases
- FSLMC bus VFIO code is not yet integrated, work is in progress
For testing, it is recommended to use the GitHub repository [8], as it will have all of the dependencies already integrated.
v3:
- Lots of compile fixes
- Fixes for multiprocess synchronization
- Introduced support for sPAPR IOMMU, courtesy of Gowrishankar @ IBM
- Fixes for mempool size calculation
- Added convenience memseg walk() API's
- Added alloc validation callback
v2: - fixed deadlock at init
- reverted rte_panic changes at init, this is now handled inside IPC
[1] http://dpdk.org/dev/patchwork/bundle/aburakov/Memory_RFC/
[2] http://dpdk.org/dev/patchwork/bundle/aburakov/IPC_Async_Request/
[3] http://dpdk.org/dev/patchwork/bundle/aburakov/Num_Sockets/
[4] http://dpdk.org/dev/patchwork/bundle/aburakov/IOVA_mode_fixes/
[5] http://dpdk.org/dev/patchwork/patch/34002/
[6] http://dpdk.org/dev/patchwork/patch/33853/
[7] http://dpdk.org/dev/patchwork/patch/24484/
[8] https://github.com/anatolyburakov/dpdk
Anatoly Burakov (68):
eal: move get_virtual_area out of linuxapp eal_memory.c
eal: move all locking to heap
eal: make malloc heap a doubly-linked list
eal: add function to dump malloc heap contents
test: add command to dump malloc heap contents
eal: make malloc_elem_join_adjacent_free public
eal: make malloc free list remove public
eal: make malloc free return resulting malloc element
eal: replace panics with error messages in malloc
eal: add backend support for contiguous allocation
eal: enable reserving physically contiguous memzones
ethdev: use contiguous allocation for DMA memory crypto/qat: use contiguous allocation for DMA memory net/avf: use contiguous allocation for DMA memory net/bnx2x: use contiguous allocation for DMA memory net/cxgbe: use contiguous allocation for DMA memory net/ena: use contiguous allocation for DMA memory net/enic: use contiguous allocation for DMA memory net/i40e: use contiguous allocation for DMA memory net/qede: use contiguous allocation for DMA memory net/virtio: use contiguous allocation for DMA memory net/vmxnet3: use contiguous allocation for DMA memory net/bnxt: use contiguous allocation for DMA memory
mempool: add support for the new allocation methods
eal: add function to walk all memsegs
bus/fslmc: use memseg walk instead of iteration bus/pci: use memseg walk instead of iteration net/mlx5: use memseg walk instead of iteration
eal: use memseg walk instead of iteration
mempool: use memseg walk instead of iteration
test: use memseg walk instead of iteration vfio/type1: use memseg walk instead of iteration vfio/spapr: use memseg walk instead of iteration
eal: add contig walk function
virtio: use memseg contig walk instead of iteration
eal: add iova2virt function
bus/dpaa: use iova2virt instead of memseg iteration bus/fslmc: use iova2virt instead of memseg iteration crypto/dpaa_sec: use iova2virt instead of memseg iteration
eal: add virt2memseg function
bus/fslmc: use virt2memseg instead of iteration net/mlx4: use virt2memseg instead of iteration net/mlx5: use virt2memseg instead of iteration crypto/dpaa_sec: use virt2memseg instead of iteration
eal: use memzone walk instead of iteration
vfio: allow to map other memory regions
eal: add "legacy memory" option
eal: add rte_fbarray
eal: replace memseg with memseg lists
eal: replace memzone array with fbarray
eal: add support for mapping hugepages at runtime
eal: add support for unmapping pages at runtime
eal: add "single file segments" command-line option
eal: add API to check if memory is contiguous
eal: prepare memseg lists for multiprocess sync
eal: read hugepage counts from node-specific sysfs path
eal: make use of memory hotplug for init
eal: share hugepage info primary and secondary
eal: add secondary process init with memory hotplug
eal: enable memory hotplug support in rte_malloc
eal: add support for multiprocess memory hotplug
eal: add support for callbacks on memory hotplug
eal: enable callbacks on malloc/free and mp sync
vfio: enable support for mem event callbacks
eal: enable non-legacy memory mode
eal: add memory validator callback
eal: enable validation before new page allocation
eal: prevent preallocated pages from being freed
config/common_base | 15 +- config/defconfig_i686-native-linuxapp-gcc | 3 + config/defconfig_i686-native-linuxapp-icc | 3 + config/defconfig_x86_x32-native-linuxapp-gcc | 3 + config/rte_config.h | 7 +- doc/guides/rel_notes/deprecation.rst | 9 - drivers/bus/dpaa/rte_dpaa_bus.h | 12 +- drivers/bus/fslmc/fslmc_vfio.c | 80 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 27 +- drivers/bus/pci/Makefile | 3 + drivers/bus/pci/linux/pci.c | 28 +- drivers/bus/pci/meson.build | 3 + drivers/crypto/dpaa_sec/dpaa_sec.c | 30 +- drivers/crypto/qat/Makefile | 3 + drivers/crypto/qat/meson.build | 3 + drivers/crypto/qat/qat_qp.c | 23 +- drivers/event/dpaa/Makefile | 3 + drivers/event/dpaa2/Makefile | 3 + drivers/mempool/dpaa/Makefile | 3 + drivers/mempool/dpaa2/Makefile | 3 + drivers/net/avf/Makefile | 3 + drivers/net/avf/avf_ethdev.c | 2 +- drivers/net/bnx2x/Makefile | 3 + drivers/net/bnx2x/bnx2x.c | 2 +- drivers/net/bnx2x/bnx2x_rxtx.c | 3 +- drivers/net/bnxt/Makefile | 3 + drivers/net/bnxt/bnxt_ethdev.c | 6 +- drivers/net/bnxt/bnxt_ring.c | 3 +- drivers/net/bnxt/bnxt_vnic.c | 2 +- drivers/net/cxgbe/Makefile | 3 + drivers/net/cxgbe/sge.c | 3 +- drivers/net/dpaa/Makefile | 3 + drivers/net/dpaa2/Makefile | 3 + drivers/net/dpaa2/meson.build | 3 + drivers/net/ena/Makefile | 3 + drivers/net/ena/base/ena_plat_dpdk.h | 7 +- drivers/net/ena/ena_ethdev.c | 10 +- drivers/net/enic/Makefile | 3 + drivers/net/enic/enic_main.c | 4 +- drivers/net/i40e/Makefile | 3 + drivers/net/i40e/i40e_ethdev.c | 2 +- drivers/net/i40e/i40e_rxtx.c | 2 +- drivers/net/i40e/meson.build | 3 + drivers/net/mlx4/mlx4_mr.c | 17 +- drivers/net/mlx5/Makefile | 3 + drivers/net/mlx5/mlx5.c | 25 +- drivers/net/mlx5/mlx5_mr.c | 18 +- drivers/net/octeontx/Makefile | 3 + drivers/net/qede/Makefile | 3 + drivers/net/qede/base/bcm_osal.c | 5 +- drivers/net/virtio/virtio_ethdev.c | 8 +- drivers/net/virtio/virtio_user/vhost_kernel.c | 83 +- drivers/net/vmxnet3/Makefile | 3 + drivers/net/vmxnet3/vmxnet3_ethdev.c | 7 +- lib/librte_eal/bsdapp/eal/Makefile | 4 + lib/librte_eal/bsdapp/eal/eal.c | 83 +- lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 65 +- lib/librte_eal/bsdapp/eal/eal_memalloc.c | 48 + lib/librte_eal/bsdapp/eal/eal_memory.c | 222 +++- lib/librte_eal/bsdapp/eal/meson.build | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_fbarray.c | 859 ++++++++++++++++ lib/librte_eal/common/eal_common_memalloc.c | 359 +++++++ lib/librte_eal/common/eal_common_memory.c | 804 ++++++++++++++- lib/librte_eal/common/eal_common_memzone.c | 274 +++-- lib/librte_eal/common/eal_common_options.c | 13 +- lib/librte_eal/common/eal_filesystem.h | 30 + lib/librte_eal/common/eal_hugepages.h | 11 +- lib/librte_eal/common/eal_internal_cfg.h | 12 +- lib/librte_eal/common/eal_memalloc.h | 80 ++ lib/librte_eal/common/eal_options.h | 4 + lib/librte_eal/common/eal_private.h | 33 + lib/librte_eal/common/include/rte_eal_memconfig.h | 28 +- lib/librte_eal/common/include/rte_fbarray.h | 353 +++++++ lib/librte_eal/common/include/rte_malloc.h | 10 + lib/librte_eal/common/include/rte_malloc_heap.h | 6 + lib/librte_eal/common/include/rte_memory.h | 232 ++++- lib/librte_eal/common/include/rte_memzone.h | 159 ++- lib/librte_eal/common/include/rte_vfio.h | 39 + lib/librte_eal/common/malloc_elem.c | 433 ++++++-- lib/librte_eal/common/malloc_elem.h | 43 +- lib/librte_eal/common/malloc_heap.c | 704 ++++++++++++- lib/librte_eal/common/malloc_heap.h | 15 +- lib/librte_eal/common/malloc_mp.c | 744 ++++++++++++++ lib/librte_eal/common/malloc_mp.h | 86 ++ lib/librte_eal/common/meson.build | 4 + lib/librte_eal/common/rte_malloc.c | 85 +- lib/librte_eal/linuxapp/eal/Makefile | 5 + lib/librte_eal/linuxapp/eal/eal.c | 62 +- lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 218 +++- lib/librte_eal/linuxapp/eal/eal_memalloc.c | 1124 +++++++++++++++++++++ lib/librte_eal/linuxapp/eal/eal_memory.c | 1119 ++++++++++++-------- lib/librte_eal/linuxapp/eal/eal_vfio.c | 491 +++++++-- lib/librte_eal/linuxapp/eal/eal_vfio.h | 12 + lib/librte_eal/linuxapp/eal/meson.build | 1 + lib/librte_eal/rte_eal_version.map | 33 +- lib/librte_ether/rte_ethdev.c | 3 +- lib/librte_mempool/Makefile | 3 + lib/librte_mempool/meson.build | 3 + lib/librte_mempool/rte_mempool.c | 138 ++- test/test/commands.c | 3 + test/test/test_malloc.c | 30 +- test/test/test_memory.c | 27 +- test/test/test_memzone.c | 62 +- 104 files changed, 8434 insertions(+), 1263 deletions(-) create mode 100644 lib/librte_eal/bsdapp/eal/eal_memalloc.c create mode 100644 lib/librte_eal/common/eal_common_fbarray.c create mode 100644 lib/librte_eal/common/eal_common_memalloc.c create mode 100644 lib/librte_eal/common/eal_memalloc.h create mode 100644 lib/librte_eal/common/include/rte_fbarray.h create mode 100644 lib/librte_eal/common/malloc_mp.c create mode 100644 lib/librte_eal/common/malloc_mp.h create mode 100644 lib/librte_eal/linuxapp/eal/eal_memalloc.c
Signature · 1 line
2.7.4
PATCH v3 1/68 eal: move get_virtual_area out of linuxapp eal_memory.c
Move get_virtual_area out of linuxapp EAL memory and make it common to EAL, so that other code could reserve virtual areas as well.
---
Notes:
v3: replace uint64_t with size_t for size variables
lib/librte_eal/common/eal_common_memory.c | 101 ++++++++++++++++++++++ lib/librte_eal/common/eal_private.h | 33 +++++++ lib/librte_eal/linuxapp/eal/eal_memory.c | 137 ++++++------------------------ 3 files changed, 161 insertions(+), 110 deletions(-)
lib/librte_eal/common/eal_common_memory.c +101 -0
@@ -2,10 +2,12 @@* Copyright(c) 2010-2014 Intel Corporation */ +#include <errno.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <stdarg.h> +#include <string.h> #include <unistd.h> #include <inttypes.h> #include <sys/mman.h>
@@ -14,12 +16,111 @@#include <rte_memory.h> #include <rte_eal.h> #include <rte_eal_memconfig.h> +#include <rte_errno.h> #include <rte_log.h> #include "eal_private.h" #include "eal_internal_cfg.h" /* +* Try to mmap *size bytes in /dev/zero. If it is successful, return the +* pointer to the mmap'd area and keep *size unmodified. Else, retry +* with a smaller zone: decrease *size by hugepage_sz until it reaches +* 0. In this case, return NULL. Note: this function returns an address +* which is a multiple of hugepage size. +*/ + +static uint64_t baseaddr_offset; +static uint64_t system_page_sz; + +void * +eal_get_virtual_area (void *requested_addr,size_t *size, +size_t page_sz,int flags,int mmap_flags) +{ +bool addr_is_hint, allow_shrink, unmap, no_align; +uint64_t map_sz; +void *mapped_addr, *aligned_addr; + +if (system_page_sz ==0 ) + system_page_sz =sysconf (_SC_PAGESIZE); + + mmap_flags |=MAP_PRIVATE |MAP_ANONYMOUS ; + +RTE_LOG (DEBUG ,EAL ,"Ask a virtual area of 0x%zx bytes\n" , *size); + + addr_is_hint = (flags &EAL_VIRTUAL_AREA_ADDR_IS_HINT ) >0 ; + allow_shrink = (flags &EAL_VIRTUAL_AREA_ALLOW_SHRINK ) >0 ; + unmap = (flags &EAL_VIRTUAL_AREA_UNMAP ) >0 ; + +if (requested_addr ==NULL && internal_config.base_virtaddr !=0 ) { + requested_addr = (void *) (internal_config.base_virtaddr + + (size_t )baseaddr_offset); + requested_addr =RTE_PTR_ALIGN (requested_addr, page_sz); + addr_is_hint = true; + } + +/* if requested address is not aligned by page size, or if requested +* address is NULL, add page size to requested length as we may get an +* address that's aligned by system page size, which can be smaller than +* our requested page size. additionally, we shouldn't try to align if +* system page size is the same as requested page size. +*/ + no_align = (requested_addr !=NULL && + ((uintptr_t )requested_addr & (page_sz -1 )) ==0 ) || + page_sz == system_page_sz; + +do { + map_sz = no_align ? *size : *size + page_sz; + + mapped_addr =mmap (requested_addr, map_sz,PROT_READ , + mmap_flags,-1 ,0 ); +if (mapped_addr ==MAP_FAILED && allow_shrink) + *size -= page_sz; + }while (allow_shrink && mapped_addr ==MAP_FAILED && *size >0 ); + +/* align resulting address - if map failed, we will ignore the value +* anyway, so no need to add additional checks. +*/ + aligned_addr = no_align ? mapped_addr : +RTE_PTR_ALIGN (mapped_addr, page_sz); + +if (*size ==0 ) { +RTE_LOG (ERR ,EAL ,"Cannot get a virtual area of any size: %s\n" , +strerror (errno)); + rte_errno = errno; +return NULL ; + }else if (mapped_addr ==MAP_FAILED ) { +RTE_LOG (ERR ,EAL ,"Cannot get a virtual area: %s\n" , +strerror (errno)); +/* pass errno up the call chain */ + rte_errno = errno; +return NULL ; + }else if (requested_addr !=NULL && !addr_is_hint && + aligned_addr != requested_addr) { +RTE_LOG (ERR ,EAL ,"Cannot get a virtual area at requested address: %p (got %p)\n" , + requested_addr, aligned_addr); +munmap (mapped_addr, map_sz); + rte_errno =EADDRNOTAVAIL ; +return NULL ; + }else if (requested_addr !=NULL && addr_is_hint && + aligned_addr != requested_addr) { +RTE_LOG (WARNING ,EAL ,"WARNING! Base virtual address hint (%p != %p) not respected!\n" , + requested_addr, aligned_addr); +RTE_LOG (WARNING ,EAL ," This may cause issues with mapping memory into secondary processes\n" ); + } + +if (unmap) +munmap (mapped_addr, map_sz); + +RTE_LOG (DEBUG ,EAL ,"Virtual area found at %p (size = 0x%zx)\n" , + aligned_addr, *size); + + baseaddr_offset += *size; + +return aligned_addr; +} + +/* * 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.
lib/librte_eal/common/eal_private.h +33 -0
@@ -127,6 +127,39 @@ int rte_eal_alarm_init(void);int rte_eal_check_module (const char *module_name);/** +* Get virtual area of specified size from the OS. +* +* This function is private to the EAL. +* +* @param requested_addr +* Address where to request address space. +* @param size +* Size of requested area. +* @param page_sz +* Page size on which to align requested virtual area. +* @param flags +* EAL_VIRTUAL_AREA_* flags. +* @param mmap_flags +* Extra flags passed directly to mmap(). +* +* @return +* Virtual area address if successful. +* NULL if unsuccessful. +*/ + +#define EAL_VIRTUAL_AREA_ADDR_IS_HINT (1 << 0) +/**< don't fail if cannot get exact requested address. */ +#define EAL_VIRTUAL_AREA_ALLOW_SHRINK (1 << 1) +/**< try getting smaller sized (decrement by page size) virtual areas if cannot +* get area of requested size. +*/ +#define EAL_VIRTUAL_AREA_UNMAP (1 << 2) +/**< immediately unmap reserved virtual area. */ +void * +eal_get_virtual_area (void *requested_addr,size_t *size, +size_t page_sz,int flags,int mmap_flags); + +/** * Get cpu core_id. * * This function is private to the EAL.
lib/librte_eal/linuxapp/eal/eal_memory.c +27 -110
204 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v3 2/68 eal: move all locking to heap
In reply to Anatoly BurakovDown the line, we will need to do everything from the heap as any alloc or free may trigger alloc/free OS memory, which would involve growing/shrinking heap.
--- lib/librte_eal/common/malloc_elem.c | 16 ++-------------- lib/librte_eal/common/malloc_heap.c | 38 +++++++++++++++++++++++++++++++++++++ lib/librte_eal/common/malloc_heap.h | 6 ++++++ lib/librte_eal/common/rte_malloc.c | 4 ++-- 4 files changed, 48 insertions(+), 16 deletions(-)
lib/librte_eal/common/malloc_elem.c +2 -14
@@ -243,10 +243,6 @@ join_elem(struct malloc_elem *elem1, struct malloc_elem *elem2)int malloc_elem_free (struct malloc_elem *elem) { -if (!malloc_elem_cookies_ok (elem) || elem->state !=ELEM_BUSY ) -return -1 ; - -rte_spinlock_lock (&(elem->heap->lock));size_t sz = elem->size -sizeof (*elem) -MALLOC_ELEM_TRAILER_LEN ;uint8_t *ptr = (uint8_t *)&elem[1 ];struct malloc_elem *next =RTE_PTR_ADD (elem, elem->size);
@@ -274,8 +270,6 @@ malloc_elem_free(struct malloc_elem *elem)memset (ptr,0 , sz); -rte_spinlock_unlock (&(elem->heap->lock)); -return 0 ; }
@@ -292,11 +286,10 @@ malloc_elem_resize(struct malloc_elem *elem, size_t size)return 0 ;struct malloc_elem *next =RTE_PTR_ADD (elem, elem->size); -rte_spinlock_lock (&elem->heap->lock);if (next ->state !=ELEM_FREE ) - goto err_return; +return -1 ;if (elem->size + next->size < new_size) - goto err_return; +return -1 ;/* we now know the element fits, so remove from free list, * join the two
@@ -311,10 +304,5 @@ malloc_elem_resize(struct malloc_elem *elem, size_t size)split_elem (elem, split_pt);malloc_elem_free_list_insert (split_pt); } -rte_spinlock_unlock (&elem->heap->lock);return 0 ; - -err_return: -rte_spinlock_unlock (&elem->heap->lock); -return -1 ; }
lib/librte_eal/common/malloc_heap.c +38 -0
@@ -145,6 +145,44 @@ malloc_heap_alloc(struct malloc_heap *heap,return elem ==NULL ?NULL : (void *)(&elem[1 ]); } +int +malloc_heap_free (struct malloc_elem *elem) +{ +struct malloc_heap *heap; +int ret; + +if (!malloc_elem_cookies_ok (elem) || elem->state !=ELEM_BUSY ) +return -1 ; + +/* elem may be merged with previous element, so keep heap address */ + heap = elem->heap; + +rte_spinlock_lock (&(heap->lock)); + + ret =malloc_elem_free (elem); + +rte_spinlock_unlock (&(heap->lock)); + +return ret; +} + +int +malloc_heap_resize (struct malloc_elem *elem,size_t size) +{ +int ret; + +if (!malloc_elem_cookies_ok (elem) || elem->state !=ELEM_BUSY ) +return -1 ; + +rte_spinlock_lock (&(elem->heap->lock)); + + ret =malloc_elem_resize (elem, size); + +rte_spinlock_unlock (&(elem->heap->lock)); + +return ret; +} +/* * Function to retrieve data for heap on given socket */
lib/librte_eal/common/malloc_heap.h +6 -0
@@ -28,6 +28,12 @@ malloc_heap_alloc(struct malloc_heap *heap, const char *type, size_t size, unsigned flags, size_t align, size_t bound);int +malloc_heap_free (struct malloc_elem *elem); + +int +malloc_heap_resize (struct malloc_elem *elem,size_t size); + +int malloc_heap_get_stats (struct malloc_heap *heap,struct rte_malloc_socket_stats *socket_stats);
lib/librte_eal/common/rte_malloc.c +2 -2
@@ -29,7 +29,7 @@void rte_free (void *addr) {if (addr ==NULL )return ; -if (malloc_elem_free (malloc_elem_from_data (addr)) <0 ) +if (malloc_heap_free (malloc_elem_from_data (addr)) <0 )rte_panic ("Fatal error: Invalid memory\n" ); }
@@ -140,7 +140,7 @@ rte_realloc(void *ptr, size_t size, unsigned align) size =RTE_CACHE_LINE_ROUNDUP (size), align =RTE_CACHE_LINE_ROUNDUP (align);/* check alignment matches first, and if ok, see if we can resize block */ if (RTE_PTR_ALIGN (ptr,align) == ptr && -malloc_elem_resize (elem, size) ==0 ) +malloc_heap_resize (elem, size) ==0 )return ptr;/* either alignment is off, or we have no room to expand,
Signature · 1 line
2.7.4
PATCH v3 3/68 eal: make malloc heap a doubly-linked list
In reply to Anatoly BurakovAs we are preparing for dynamic memory allocation, we need to be able to handle holes in our malloc heap, hence we're switching to doubly linked list, and prepare infrastructure to support it.
Since our heap is now aware where are our first and last elements, there is no longer any need to have a dummy element at the end of each heap, so get rid of that as well. Instead, let insert/remove/ join/split operations handle end-of-list conditions automatically.
--- lib/librte_eal/common/include/rte_malloc_heap.h | 6 + lib/librte_eal/common/malloc_elem.c | 200 +++++++++++++++++++----- lib/librte_eal/common/malloc_elem.h | 14 +- lib/librte_eal/common/malloc_heap.c | 8 +- 4 files changed, 179 insertions(+), 49 deletions(-)
lib/librte_eal/common/include/rte_malloc_heap.h +6 -0
@@ -13,12 +13,18 @@/* Number of free lists per heap, grouped by size. */ #define RTE_HEAP_NUM_FREELISTS 13 +/* dummy definition, for pointers */ +struct malloc_elem ; +/** * Structure to hold malloc heap */ struct malloc_heap {rte_spinlock_t lock; LIST_HEAD(, malloc_elem) free_head[RTE_HEAP_NUM_FREELISTS]; +struct malloc_elem *volatile first; +struct malloc_elem *volatile last; +unsigned alloc_count;size_t total_size; } __rte_cache_aligned;
lib/librte_eal/common/malloc_elem.c +164 -36
271 lines not on this page · raw message
lib/librte_eal/common/malloc_elem.h +7 -7
@@ -18,8 +18,12 @@ enum elem_state {struct malloc_elem {struct malloc_heap *heap; -struct malloc_elem *volatile prev;/* points to prev elem in memseg */ -LIST_ENTRY (malloc_elem) free_list;/* list of free elements in heap */ +struct malloc_elem *volatile prev; +/**< points to prev elem in memseg */ +struct malloc_elem *volatile next; +/**< points to next elem in memseg */ +LIST_ENTRY (malloc_elem) free_list; +/**< list of free elements in heap */ const struct rte_memseg *ms;volatile enum elem_state state;uint32_t pad;
@@ -110,12 +114,8 @@ malloc_elem_init(struct malloc_elem *elem,const struct rte_memseg *ms, size_t size); -/* -* initialise a dummy malloc_elem header for the end-of-memseg marker -*/ void -malloc_elem_mkend (struct malloc_elem *elem, -struct malloc_elem *prev_free); +malloc_elem_insert (struct malloc_elem *elem);/* * return true if the current malloc_elem can hold a block of data
lib/librte_eal/common/malloc_heap.c +2 -6
@@ -70,15 +70,11 @@ check_hugepage_sz(unsigned flags, uint64_t hugepage_sz)static void malloc_heap_add_memseg (struct malloc_heap *heap,struct rte_memseg *ms) { -/* allocate the memory block headers, one at end, one at start */ struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr; -struct malloc_elem *end_elem =RTE_PTR_ADD (ms->addr, - ms->len -MALLOC_ELEM_OVERHEAD ); - end_elem =RTE_PTR_ALIGN_FLOOR (end_elem,RTE_CACHE_LINE_SIZE ); -const size_t elem_size = (uintptr_t )end_elem - (uintptr_t )start_elem; +const size_t elem_size = ms->len -MALLOC_ELEM_OVERHEAD ;malloc_elem_init (start_elem, heap, ms, elem_size); -malloc_elem_mkend (end_elem, start_elem); +malloc_elem_insert (start_elem);malloc_elem_free_list_insert (start_elem); heap->total_size += elem_size;
Signature · 1 line
2.7.4
Re: [PATCH v3 03/68] eal: make malloc heap a doubly-linked list
Quoted 10 lines · On Wed, 4 Apr 2018 00:21:15 +0100 Anatoly Burakov <[email protected]>…
As we are preparing for dynamic memory allocation, we need to be able to handle holes in our malloc heap, hence we're switching to doubly linked list, and prepare infrastructure to support it.
Since our heap is now aware where are our first and last elements, there is no longer any need to have a dummy element at the end of each heap, so get rid of that as well. Instead, let insert/remove/ join/split operations handle end-of-list conditions automatically.
Signed-off-by Anatoly Burakov <[email protected]>
Dummy element at end of heap could be helpful for purify/valgrind style verification that code does not exceed allocation.
Re: [PATCH v3 03/68] eal: make malloc heap a doubly-linked list
Quoted 12 lines · Stephen Hemminger
Quoted 9 lines · On Wed, 4 Apr 2018 00:21:15 +0100 Anatoly Burakov <[email protected]>…
As we are preparing for dynamic memory allocation, we need to be able to handle holes in our malloc heap, hence we're switching to doubly linked list, and prepare infrastructure to support it.
Since our heap is now aware where are our first and last elements, there is no longer any need to have a dummy element at the end of each heap, so get rid of that as well. Instead, let insert/remove/ join/split operations handle end-of-list conditions automatically.
Quoted 5 lines
Quoted 1 line
Signed-off-by Anatoly Burakov <[email protected]>Dummy element at end of heap could be helpful for purify/valgrind style verification that code does not exceed allocation.
It would interfere with removing pages from memory :) Dummy element needs to be stored somewhere - if it's stored in a page, that means that page cannot be freed. Moreover, with pages being added/removed dynamically, the dummy element will have to be moved back and forth, so "at the end of the heap" is not a fixed location.
Signature · 2 lines
Thanks, Anatoly
PATCH v3 4/68 eal: add function to dump malloc heap contents
In reply to Anatoly BurakovMalloc heap is now a doubly linked list, so it's now possible to iterate over each malloc element regardless of its state.
---
Notes:
v3: mark function as experimental
lib/librte_eal/common/include/rte_malloc.h | 10 ++++++++++ lib/librte_eal/common/malloc_elem.c | 24 ++++++++++++++++++++++++ lib/librte_eal/common/malloc_elem.h | 6 ++++++ lib/librte_eal/common/malloc_heap.c | 22 ++++++++++++++++++++++ lib/librte_eal/common/malloc_heap.h | 3 +++ lib/librte_eal/common/rte_malloc.c | 17 +++++++++++++++++ lib/librte_eal/rte_eal_version.map | 1 + 7 files changed, 83 insertions(+)
lib/librte_eal/common/include/rte_malloc.h +10 -0
@@ -13,6 +13,7 @@#include <stdio.h> #include <stddef.h> +#include <rte_compat.h> #include <rte_memory.h> #ifdef __cplusplus
@@ -278,6 +279,15 @@ void rte_malloc_dump_stats(FILE *f, const char *type);/** +* Dump contents of all malloc heaps to a file. +* +* @param f +* A pointer to a file for output +*/ +void __rte_experimental +rte_malloc_dump_heaps (FILE *f); + +/** * Set the maximum amount of allocated memory for this type. * * This is not yet implemented
lib/librte_eal/common/malloc_elem.c +24 -0
@@ -1,6 +1,7 @@/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2014 Intel Corporation */ +#include <inttypes.h> #include <stdint.h> #include <stddef.h> #include <stdio.h>
@@ -434,3 +435,26 @@ malloc_elem_resize(struct malloc_elem *elem, size_t size) }return 0 ; } + +static inline const char * +elem_state_to_str (enum elem_state state) +{ +switch (state) { +case ELEM_PAD : +return "PAD" ; +case ELEM_BUSY : +return "BUSY" ; +case ELEM_FREE : +return "FREE" ; + } +return "ERROR" ; +} + +void +malloc_elem_dump (const struct malloc_elem *elem,FILE *f) +{ +fprintf (f,"Malloc element at %p (%s)\n" , elem, +elem_state_to_str (elem->state)); +fprintf (f," len: 0x%zx pad: 0x%" PRIx32"\n" , elem->size, elem->pad); +fprintf (f," prev: %p next: %p\n" , elem->prev, elem->next); +}
lib/librte_eal/common/malloc_elem.h +6 -0
@@ -149,6 +149,12 @@ int malloc_elem_resize(struct malloc_elem *elem, size_t size);/* +* dump contents of malloc elem to a file. +*/ +void +malloc_elem_dump (const struct malloc_elem *elem,FILE *f); + +/* * Given an element size, compute its freelist index. */ size_t
lib/librte_eal/common/malloc_heap.c +22 -0
@@ -217,6 +217,28 @@ malloc_heap_get_stats(struct malloc_heap *heap,return 0 ; } +/* +* Function to retrieve data for heap on given socket +*/ +void +malloc_heap_dump (struct malloc_heap *heap,FILE *f) +{ +struct malloc_elem *elem; + +rte_spinlock_lock (&heap->lock); + +fprintf (f,"Heap size: 0x%zx\n" , heap->total_size); +fprintf (f,"Heap alloc count: %u\n" , heap->alloc_count); + + elem = heap->first; +while (elem) { +malloc_elem_dump (elem, f); + elem = elem->next; + } + +rte_spinlock_unlock (&heap->lock); +} +int rte_eal_malloc_heap_init (void ) {
lib/librte_eal/common/malloc_heap.h +3 -0
@@ -37,6 +37,9 @@ int malloc_heap_get_stats(struct malloc_heap *heap, struct rte_malloc_socket_stats *socket_stats); +void +malloc_heap_dump (struct malloc_heap *heap,FILE *f); +int rte_eal_malloc_heap_init (void );
lib/librte_eal/common/rte_malloc.c +17 -0
@@ -182,6 +182,23 @@ rte_malloc_get_socket_stats(int socket, }/* +* Function to dump contents of all heaps +*/ +void __rte_experimental +rte_malloc_dump_heaps (FILE *f) +{ +struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; +unsigned int idx; + +for (idx =0 ; idx <rte_socket_count (); idx++) { +unsigned int socket =rte_socket_id_by_idx (idx); +fprintf (f,"Heap on socket %i:\n" , socket); +malloc_heap_dump (&mcfg->malloc_heaps[socket], f); + } + +} + +/* * Print stats on memory type. If type is NULL, info on all types is printed */ void
lib/librte_eal/rte_eal_version.map +1 -0
@@ -222,6 +222,7 @@ EXPERIMENTAL { rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops; rte_log_register_type_and_pick_level; + rte_malloc_dump_heaps; rte_mp_action_register; rte_mp_action_unregister; rte_mp_reply;
Signature · 1 line
2.7.4
PATCH v3 5/68 test: add command to dump malloc heap contents
In reply to Anatoly Burakov--- test/test/commands.c | 3 +++ 1 file changed, 3 insertions(+)
test/test/commands.c +3 -0
@@ -137,6 +137,8 @@ static void cmd_dump_parsed(void *parsed_result,rte_log_dump (stdout); else if (!strcmp(res->dump, "dump_malloc_stats"))rte_malloc_dump_stats (stdout,NULL ); + else if (!strcmp(res->dump, "dump_malloc_heaps")) +rte_malloc_dump_heaps (stdout); } cmdline_parse_token_string_t cmd_dump_dump =
@@ -147,6 +149,7 @@ cmdline_parse_token_string_t cmd_dump_dump ="dump_ring#" "dump_mempool#" "dump_malloc_stats#" +"dump_malloc_heaps#" "dump_devargs#" "dump_log_types");
Signature · 1 line
2.7.4
PATCH v3 6/68 eal: make malloc_elem_join_adjacent_free public
In reply to Anatoly BurakovWe need this function to join newly allocated segments with the heap.
--- lib/librte_eal/common/malloc_elem.c | 6 +++--- lib/librte_eal/common/malloc_elem.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-)
lib/librte_eal/common/malloc_elem.c +3 -3
@@ -325,8 +325,8 @@ join_elem(struct malloc_elem *elem1, struct malloc_elem *elem2) elem1->next = next; } -static struct malloc_elem * -elem_join_adjacent_free (struct malloc_elem *elem) +struct malloc_elem * +malloc_elem_join_adjacent_free (struct malloc_elem *elem) {/* * check if next element exists, is adjacent and is free, if so join
@@ -388,7 +388,7 @@ malloc_elem_free(struct malloc_elem *elem) ptr =RTE_PTR_ADD (elem,sizeof (*elem)); data_len = elem->size -MALLOC_ELEM_OVERHEAD ; - elem =elem_join_adjacent_free (elem); + elem =malloc_elem_join_adjacent_free (elem);malloc_elem_free_list_insert (elem);
lib/librte_eal/common/malloc_elem.h +3 -0
@@ -141,6 +141,9 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size,int malloc_elem_free (struct malloc_elem *elem); +struct malloc_elem * +malloc_elem_join_adjacent_free (struct malloc_elem *elem); +/* * attempt to resize a malloc_elem by expanding into any free space * immediately after it in memory.
Signature · 1 line
2.7.4
PATCH v3 7/68 eal: make malloc free list remove public
In reply to Anatoly Burakov--- lib/librte_eal/common/malloc_elem.c | 12 ++++++------ lib/librte_eal/common/malloc_elem.h | 3 +++ 2 files changed, 9 insertions(+), 6 deletions(-)
lib/librte_eal/common/malloc_elem.c +6 -6
@@ -245,8 +245,8 @@ malloc_elem_free_list_insert(struct malloc_elem *elem)/* * Remove the specified element from its heap's free list. */ -static void -elem_free_list_remove (struct malloc_elem *elem) +void +malloc_elem_free_list_remove (struct malloc_elem *elem) {LIST_REMOVE (elem, free_list); }
@@ -266,7 +266,7 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size, unsigned align,const size_t trailer_size = elem->size - old_elem_size - size -MALLOC_ELEM_OVERHEAD ; -elem_free_list_remove (elem); +malloc_elem_free_list_remove (elem);if (trailer_size >MALLOC_ELEM_OVERHEAD +MIN_DATA_SIZE ) {/* split it, too much free space after elem */
@@ -340,7 +340,7 @@ malloc_elem_join_adjacent_free(struct malloc_elem *elem) erase =RTE_PTR_SUB (elem->next,MALLOC_ELEM_TRAILER_LEN );/* remove from free list, join to this one */ -elem_free_list_remove (elem->next); +malloc_elem_free_list_remove (elem->next);join_elem (elem, elem->next);/* erase header and trailer */
@@ -360,7 +360,7 @@ malloc_elem_join_adjacent_free(struct malloc_elem *elem) erase =RTE_PTR_SUB (elem,MALLOC_ELEM_TRAILER_LEN );/* remove from free list, join to this one */ -elem_free_list_remove (elem->prev); +malloc_elem_free_list_remove (elem->prev); new_elem = elem->prev;join_elem (new_elem, elem);
@@ -423,7 +423,7 @@ malloc_elem_resize(struct malloc_elem *elem, size_t size)/* we now know the element fits, so remove from free list, * join the two */ -elem_free_list_remove (elem->next); +malloc_elem_free_list_remove (elem->next);join_elem (elem, elem->next);if (elem->size - new_size >=MIN_DATA_SIZE +MALLOC_ELEM_OVERHEAD ) {
lib/librte_eal/common/malloc_elem.h +3 -0
@@ -151,6 +151,9 @@ malloc_elem_join_adjacent_free(struct malloc_elem *elem);int malloc_elem_resize (struct malloc_elem *elem,size_t size); +void +malloc_elem_free_list_remove (struct malloc_elem *elem); +/* * dump contents of malloc elem to a file. */
Signature · 1 line
2.7.4
PATCH v3 8/68 eal: make malloc free return resulting malloc element
In reply to Anatoly BurakovThis will be needed because we need to know how big is the new empty space, to check whether we can free some pages as a result.
---
Notes:
v3: clarified commit message
lib/librte_eal/common/malloc_elem.c | 4 ++-- lib/librte_eal/common/malloc_elem.h | 2 +- lib/librte_eal/common/malloc_heap.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-)
lib/librte_eal/common/malloc_elem.c +2 -2
@@ -379,7 +379,7 @@ malloc_elem_join_adjacent_free(struct malloc_elem *elem)* blocks either immediately before or immediately after newly freed block * are also free, the blocks are merged together. */ -int +struct malloc_elem *malloc_elem_free (struct malloc_elem *elem) {void *ptr;
@@ -397,7 +397,7 @@ malloc_elem_free(struct malloc_elem *elem)memset (ptr,0 , data_len); -return 0 ; +return elem; }/*
lib/librte_eal/common/malloc_elem.h +1 -1
@@ -138,7 +138,7 @@ malloc_elem_alloc(struct malloc_elem *elem, size_t size,* blocks either immediately before or immediately after newly freed block * are also free, the blocks are merged together. */ -int +struct malloc_elem *malloc_elem_free (struct malloc_elem *elem); struct malloc_elem *
lib/librte_eal/common/malloc_heap.c +2 -2
@@ -145,7 +145,7 @@ int malloc_heap_free(struct malloc_elem *elem) {struct malloc_heap *heap; -int ret; +struct malloc_elem *ret;if (!malloc_elem_cookies_ok (elem) || elem->state !=ELEM_BUSY )return -1 ;
@@ -159,7 +159,7 @@ malloc_heap_free(struct malloc_elem *elem)rte_spinlock_unlock (&(heap->lock)); -return ret; +return ret !=NULL ?0 :-1 ; }int
Signature · 1 line
2.7.4
PATCH v3 9/68 eal: replace panics with error messages in malloc
In reply to Anatoly Burakov--- lib/librte_eal/common/rte_malloc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
lib/librte_eal/common/rte_malloc.c +5 -3
@@ -30,7 +30,7 @@ void rte_free(void *addr) {if (addr ==NULL )return ;if (malloc_heap_free (malloc_elem_from_data (addr)) <0 ) -rte_panic ("Fatal error: Invalid memory\n" ); +RTE_LOG (ERR ,EAL ,"Error: Invalid memory\n" ); }/*
@@ -134,8 +134,10 @@ rte_realloc(void *ptr, size_t size, unsigned align)return rte_malloc (NULL , size, align);struct malloc_elem *elem =malloc_elem_from_data (ptr); -if (elem ==NULL ) -rte_panic ("Fatal error: memory corruption detected\n" ); +if (elem ==NULL ) { +RTE_LOG (ERR ,EAL ,"Error: memory corruption detected\n" ); +return NULL ; + } size =RTE_CACHE_LINE_ROUNDUP (size), align =RTE_CACHE_LINE_ROUNDUP (align);/* check alignment matches first, and if ok, see if we can resize block */
Signature · 1 line
2.7.4
PATCH v3 10/68 eal: add backend support for contiguous allocation
In reply to Anatoly BurakovNo major changes, just add some checks in a few key places, and a new parameter to pass around.
Also, add a dummy function to check malloc element for physical contiguousness. For now, assume hugepage memory is always contiguous, while non-hugepage memory will be checked.
---
Notes:
v3:
- Moved this patch earlier
- Added physical contiguousness checking function
lib/librte_eal/common/eal_common_memzone.c | 23 +++--- lib/librte_eal/common/malloc_elem.c | 125 ++++++++++++++++++++++++----- lib/librte_eal/common/malloc_elem.h | 6 +- lib/librte_eal/common/malloc_heap.c | 11 +-- lib/librte_eal/common/malloc_heap.h | 4 +- lib/librte_eal/common/rte_malloc.c | 7 +- 6 files changed, 133 insertions(+), 43 deletions(-)
lib/librte_eal/common/eal_common_memzone.c +13 -10
@@ -98,7 +98,8 @@ find_heap_max_free_elem(int *s, unsigned align)static const struct rte_memzone *memzone_reserve_aligned_thread_unsafe (const char *name,size_t len, -int socket_id,unsigned flags,unsigned align,unsigned bound) +int socket_id,unsigned int flags,unsigned int align, +unsigned int bound,bool contig) {struct rte_memzone *mz;struct rte_mem_config *mcfg;
@@ -188,7 +189,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,/* allocate memory on heap */ void *mz_addr =malloc_heap_alloc (&mcfg->malloc_heaps[socket],NULL , - requested_len, flags, align, bound); + requested_len, flags, align, bound, contig);if ((mz_addr ==NULL ) && (socket_id ==SOCKET_ID_ANY )) {/* try other heaps */
@@ -197,7 +198,8 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,continue ; mz_addr =malloc_heap_alloc (&mcfg->malloc_heaps[i], -NULL , requested_len, flags, align, bound); +NULL , requested_len, flags, align, + bound, contig);if (mz_addr !=NULL )break ; }
@@ -235,9 +237,9 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len, }static const struct rte_memzone * -rte_memzone_reserve_thread_safe (const char *name,size_t len, -int socket_id,unsigned flags,unsigned align, -unsigned bound) +rte_memzone_reserve_thread_safe (const char *name,size_t len,int socket_id, +unsigned int flags,unsigned int align,unsigned int bound, +bool contig) {struct rte_mem_config *mcfg;const struct rte_memzone *mz =NULL ;
@@ -248,7 +250,7 @@ rte_memzone_reserve_thread_safe(const char *name, size_t len,rte_rwlock_write_lock (&mcfg->mlock); mz =memzone_reserve_aligned_thread_unsafe ( - name, len, socket_id, flags, align, bound); + name, len, socket_id, flags, align, bound, contig);rte_rwlock_write_unlock (&mcfg->mlock);
@@ -265,7 +267,7 @@ rte_memzone_reserve_bounded(const char *name, size_t len, int socket_id, unsigned flags, unsigned align, unsigned bound) { return rte_memzone_reserve_thread_safe(name, len, socket_id, flags, -align ,bound ); +align ,bound ,false ); }/*
@@ -277,7 +279,7 @@ rte_memzone_reserve_aligned(const char *name, size_t len, int socket_id, unsigned flags, unsigned align) {return rte_memzone_reserve_thread_safe (name, len, socket_id, flags, - align,0 ); + align,0 , false); }/*
@@ -289,7 +291,8 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) {return rte_memzone_reserve_thread_safe (name, len, socket_id, - flags,RTE_CACHE_LINE_SIZE ,0 ); + flags,RTE_CACHE_LINE_SIZE ,0 , + false); }int
lib/librte_eal/common/malloc_elem.c +103 -22
160 lines not on this page · raw message
lib/librte_eal/common/malloc_elem.h +4 -2
@@ -5,6 +5,8 @@#ifndef MALLOC_ELEM_H_ #define MALLOC_ELEM_H_ +#include <stdbool.h> +#include <rte_memory.h> /* dummy definition of struct so we can use pointers to it in malloc_elem struct */
@@ -123,7 +125,7 @@ malloc_elem_insert(struct malloc_elem *elem);*/ int malloc_elem_can_hold (struct malloc_elem *elem,size_t size, -unsigned align,size_t bound); +unsigned int align,size_t bound,bool contig);/* * reserve a block of data in an existing malloc_elem. If the malloc_elem
@@ -131,7 +133,7 @@ malloc_elem_can_hold(struct malloc_elem *elem, size_t size,*/ struct malloc_elem *malloc_elem_alloc (struct malloc_elem *elem,size_t size, -unsigned align,size_t bound); +unsigned int align,size_t bound,bool contig);/* * free a malloc_elem block by adding it to the free list. If the
lib/librte_eal/common/malloc_heap.c +6 -5
@@ -88,7 +88,7 @@ malloc_heap_add_memseg(struct malloc_heap *heap, struct rte_memseg *ms)*/ static struct malloc_elem *find_suitable_element (struct malloc_heap *heap,size_t size, -unsigned flags,size_t align,size_t bound) +unsigned int flags,size_t align,size_t bound,bool contig) {size_t idx;struct malloc_elem *elem, *alt_elem =NULL ;
@@ -97,7 +97,8 @@ find_suitable_element(struct malloc_heap *heap, size_t size, idx < RTE_HEAP_NUM_FREELISTS; idx++) {for (elem =LIST_FIRST (&heap->free_head[idx]); !!elem; elem =LIST_NEXT (elem, free_list)) { -if (malloc_elem_can_hold (elem, size, align, bound)) { +if (malloc_elem_can_hold (elem, size, align, bound, + contig)) {if (check_hugepage_sz (flags, elem->ms->hugepage_sz))return elem;if (alt_elem ==NULL )
@@ -121,7 +122,7 @@ find_suitable_element(struct malloc_heap *heap, size_t size,void *malloc_heap_alloc (struct malloc_heap *heap,const char *type __attribute__((unused)),size_t size,unsigned flags, -size_t align,size_t bound) +size_t align,size_t bound,bool contig) {struct malloc_elem *elem;
@@ -130,9 +131,9 @@ malloc_heap_alloc(struct malloc_heap *heap,rte_spinlock_lock (&heap->lock); - elem =find_suitable_element (heap, size, flags, align, bound); + elem =find_suitable_element (heap, size, flags, align, bound, contig);if (elem !=NULL ) { - elem =malloc_elem_alloc (elem, size, align, bound); + elem =malloc_elem_alloc (elem, size, align, bound, contig);/* increase heap's count of allocated elements */ heap->alloc_count++; }
lib/librte_eal/common/malloc_heap.h +3 -1
@@ -5,6 +5,8 @@#ifndef MALLOC_HEAP_H_ #define MALLOC_HEAP_H_ +#include <stdbool.h> +#include <rte_malloc.h> #include <rte_malloc_heap.h>
@@ -25,7 +27,7 @@ malloc_get_numa_socket(void)void *malloc_heap_alloc (struct malloc_heap *heap,const char *type,size_t size, -unsigned flags,size_t align,size_t bound); +unsigned int flags,size_t align,size_t bound,bool contig);int malloc_heap_free (struct malloc_elem *elem);
lib/librte_eal/common/rte_malloc.c +4 -3
@@ -37,7 +37,8 @@ void rte_free(void *addr)* Allocate memory on specified heap. */ void * -rte_malloc_socket (const char *type,size_t size,unsigned align,int socket_arg) +rte_malloc_socket (const char *type,size_t size,unsigned int align, +int socket_arg) {struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;int socket, i;
@@ -60,7 +61,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)return NULL ; ret =malloc_heap_alloc (&mcfg->malloc_heaps[socket], type, - size,0 , align ==0 ?1 : align,0 ); + size,0 , align ==0 ?1 : align,0 , false);if (ret !=NULL || socket_arg !=SOCKET_ID_ANY )return ret;
@@ -71,7 +72,7 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket_arg)continue ; ret =malloc_heap_alloc (&mcfg->malloc_heaps[i], type, - size,0 , align ==0 ?1 : align,0 ); + size,0 , align ==0 ?1 : align,0 , false);if (ret !=NULL )return ret; }
Signature · 1 line
2.7.4
PATCH v3 11/68 eal: enable reserving physically contiguous memzones
In reply to Anatoly BurakovThis adds a new set of _contig API's to rte_memzone. For now, hugepage memory is always contiguous, but we need to prepare the drivers for the switch.
---
Notes:
v3:
- Moved this patch earlier
lib/librte_eal/common/eal_common_memzone.c | 44 ++++++++ lib/librte_eal/common/include/rte_memzone.h | 158 ++++++++++++++++++++++++++++ lib/librte_eal/rte_eal_version.map | 3 + 3 files changed, 205 insertions(+)
lib/librte_eal/common/eal_common_memzone.c +44 -0
@@ -171,6 +171,12 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len, socket_id =SOCKET_ID_ANY ;if (len ==0 ) { +/* len == 0 is only allowed for non-contiguous zones */ +if (contig) { +RTE_LOG (DEBUG ,EAL ,"Reserving zero-length contiguous memzones is not supported\n" ); + rte_errno =EINVAL ; +return NULL ; + }if (bound !=0 ) requested_len = bound;else {
@@ -272,6 +278,19 @@ rte_memzone_reserve_bounded(const char *name, size_t len, int socket_id,/* * Return a pointer to a correctly filled memzone descriptor (with a +* specified alignment and boundary). If the allocation cannot be done, +* return NULL. +*/ +__rte_experimental const struct rte_memzone * +rte_memzone_reserve_bounded_contig (const char *name,size_t len,int socket_id, +unsigned int flags,unsigned int align,unsigned int bound) +{ +return rte_memzone_reserve_thread_safe (name, len, socket_id, flags, + align, bound, true); +} + +/* +* Return a pointer to a correctly filled memzone descriptor (with a * specified alignment). If the allocation cannot be done, return NULL. */ const struct rte_memzone *
@@ -283,6 +302,18 @@ rte_memzone_reserve_aligned(const char *name, size_t len, int socket_id, }/* +* Return a pointer to a correctly filled memzone descriptor (with a +* specified alignment). If the allocation cannot be done, return NULL. +*/ +__rte_experimental const struct rte_memzone * +rte_memzone_reserve_aligned_contig (const char *name,size_t len,int socket_id, +unsigned int flags,unsigned int align) +{ +return rte_memzone_reserve_thread_safe (name, len, socket_id, flags, + align,0 , true); +} + +/* * Return a pointer to a correctly filled memzone descriptor. If the * allocation cannot be done, return NULL. */
@@ -295,6 +326,19 @@ rte_memzone_reserve(const char *name, size_t len, int socket_id, false); } +/* +* Return a pointer to a correctly filled memzone descriptor. If the +* allocation cannot be done, return NULL. +*/ +__rte_experimental const struct rte_memzone * +rte_memzone_reserve_contig (const char *name,size_t len,int socket_id, +unsigned int flags) +{ +return rte_memzone_reserve_thread_safe (name, len, socket_id, + flags,RTE_CACHE_LINE_SIZE ,0 , + true); +} +int rte_memzone_free (const struct rte_memzone *mz) {
lib/librte_eal/common/include/rte_memzone.h +158 -0
170 lines not on this page · raw message
lib/librte_eal/rte_eal_version.map +3 -0
@@ -223,6 +223,9 @@ EXPERIMENTAL { rte_eal_mbuf_user_pool_ops; rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; + rte_memzone_reserve_contig; + rte_memzone_reserve_aligned_contig; + rte_memzone_reserve_bounded_contig; rte_mp_action_register; rte_mp_action_unregister; rte_mp_reply;
Signature · 1 line
2.7.4
Re: [PATCH v3 11/68] eal: enable reserving physically contiguous memzones
Quoted 5 lines · On Wed, 4 Apr 2018 00:21:23 +0100 Anatoly Burakov <[email protected]>…
This adds a new set of
_contigAPI's torte_memzone. For now, hugepage memory is always contiguous, but we need to prepare the drivers for the switch.Signed-off-by Anatoly Burakov <[email protected]>
Why not make fragmentation an optional flag to the memzone_reserved rather than a new API. That way less drivers need to be changed.
#define RTE_MEMZONE_SPARSE 0x00100000 /* Allow zone to be non-contiguous */
Re: [PATCH v3 11/68] eal: enable reserving physically contiguous memzones
Quoted 7 lines · Stephen Hemminger
Quoted 4 lines · On Wed, 4 Apr 2018 00:21:23 +0100 Anatoly Burakov <[email protected]>…
This adds a new set of
_contigAPI's torte_memzone. For now, hugepage memory is always contiguous, but we need to prepare the drivers for the switch.
Quoted 7 lines
Quoted 1 line
Signed-off-by Anatoly Burakov <[email protected]>Why not make fragmentation an optional flag to the
memzone_reservedrather than a new API. That way less drivers need to be changed.#define
RTE_MEMZONE_SPARSE0x00100000/* Allow zone to be non-contiguous */
That is a good idea, however, i would perhaps do it the other way around. Most of the time we are reserving memzones, we do not need those to be IOVA-contiguous (i.e. creating rings, hashtables etc.). So it would rather be a RTE_MEMZONE_CONTIG (or some such) flag.
Signature · 2 lines
Thanks, Anatoly
PATCH v3 12/68 ethdev: use contiguous allocation for DMA memory
In reply to Anatoly BurakovThis fixes the following drivers in one go:
grep -Rl rte_eth_dma_zone_reserve drivers/
drivers/net/avf/avf_rxtx.cdrivers/net/thunderx/nicvf_ethdev.cdrivers/net/e1000/igb_rxtx.cdrivers/net/e1000/em_rxtx.cdrivers/net/fm10k/fm10k_ethdev.cdrivers/net/vmxnet3/vmxnet3_rxtx.cdrivers/net/liquidio/lio_rxtx.cdrivers/net/i40e/i40e_rxtx.cdrivers/net/sfc/sfc.cdrivers/net/ixgbe/ixgbe_rxtx.cdrivers/net/nfp/nfp_net.c
---
Notes:
v3: moved this patch earlier in the patchset
lib/librte_ether/rte_ethdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
lib/librte_ether/rte_ethdev.c +2 -1
@@ -3403,7 +3403,8 @@ rte_eth_dma_zone_reserve(const struct rte_eth_dev *dev, const char *ring_name,if (mz)return mz; -return rte_memzone_reserve_aligned (z_name, size, socket_id,0 , align); +return rte_memzone_reserve_aligned_contig (z_name, size, socket_id,0 , + align); }int
Signature · 1 line
2.7.4
PATCH v3 13/68 crypto/qat: use contiguous allocation for DMA memory
In reply to Anatoly BurakovAlso, remove the weird page alignment code.
---
Notes:
v3:
- Move the patch earlier in the patchset
- Fix build system files to allow experimental API's
- Removed non-sensical memzone flags code
drivers/crypto/qat/Makefile | 3 +++ drivers/crypto/qat/meson.build | 3 +++ drivers/crypto/qat/qat_qp.c | 23 ++--------------------- 3 files changed, 8 insertions(+), 21 deletions(-)
drivers/crypto/qat/Makefile +3 -0
@@ -13,6 +13,9 @@ LIBABIVER := 1 CFLAGS += $(WERROR_FLAGS) CFLAGS += -O3 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + # external library include paths CFLAGS += -I$(SRCDIR)/qat_adf LDLIBS += -lcrypto
drivers/crypto/qat/meson.build +3 -0
@@ -12,3 +12,6 @@ includes += include_directories('qat_adf') deps += ['bus_pci'] ext_deps += dep pkgconfig_extra_libs += '-lcrypto' + +# contig memzone allocation is not yet part of stable API +allow_experimental_apis = true
drivers/crypto/qat/qat_qp.c +2 -21
@@ -54,8 +54,6 @@ queue_dma_zone_reserve(const char *queue_name, uint32_t queue_size, int socket_id) {const struct rte_memzone *mz; -unsigned memzone_flags =0 ; -const struct rte_memseg *ms;PMD_INIT_FUNC_TRACE (); mz =rte_memzone_lookup (queue_name);
@@ -78,25 +76,8 @@ queue_dma_zone_reserve(const char *queue_name, uint32_t queue_size,PMD_DRV_LOG (DEBUG ,"Allocate memzone for %s, size %u on socket %u" , queue_name, queue_size, socket_id); - ms =rte_eal_get_physmem_layout (); -switch (ms[0 ].hugepage_sz) { -case (RTE_PGSIZE_2M ): - memzone_flags =RTE_MEMZONE_2MB ; -break ; -case (RTE_PGSIZE_1G ): - memzone_flags =RTE_MEMZONE_1GB ; -break ; -case (RTE_PGSIZE_16M ): - memzone_flags =RTE_MEMZONE_16MB ; -break ; -case (RTE_PGSIZE_16G ): - memzone_flags =RTE_MEMZONE_16GB ; -break ; -default : - memzone_flags =RTE_MEMZONE_SIZE_HINT_ONLY ; - } -return rte_memzone_reserve_aligned (queue_name, queue_size, socket_id, - memzone_flags, queue_size); +return rte_memzone_reserve_aligned_contig (queue_name, queue_size, + socket_id,0 , queue_size); } int qat_crypto_sym_qp_setup(struct rte_cryptodev *dev, uint16_t queue_pair_id,
Signature · 1 line
2.7.4
PATCH v3 14/68 net/avf: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
- Allowed experimental API's in the makefile
drivers/net/avf/Makefile | 3 +++ drivers/net/avf/avf_ethdev.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/net/avf/Makefile +3 -0
@@ -20,6 +20,9 @@ EXPORT_MAP := rte_pmd_avf_version.map LIBABIVER := 1 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + # # Add extra flags for base driver files (also known as shared code) # to disable warnings
drivers/net/avf/avf_ethdev.c +1 -1
@@ -1365,7 +1365,7 @@ avf_allocate_dma_mem_d(__rte_unused struct avf_hw *hw,return AVF_ERR_PARAM ;snprintf (z_name,sizeof (z_name),"avf_dma_%" PRIu64,rte_rand ()); - mz =rte_memzone_reserve_bounded (z_name, size,SOCKET_ID_ANY ,0 , + mz =rte_memzone_reserve_bounded_contig (z_name, size,SOCKET_ID_ANY ,0 , alignment,RTE_PGSIZE_2M );if (!mz)return AVF_ERR_NO_MEMORY ;
Signature · 1 line
2.7.4
PATCH v3 15/68 net/bnx2x: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
- Allowed experimental API's in the makefile
drivers/net/bnx2x/Makefile | 3 +++ drivers/net/bnx2x/bnx2x.c | 2 +- drivers/net/bnx2x/bnx2x_rxtx.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-)
drivers/net/bnx2x/Makefile +3 -0
@@ -17,6 +17,9 @@ EXPORT_MAP := rte_pmd_bnx2x_version.map LIBABIVER := 1 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + ifeq ($(CONFIG_RTE_TOOLCHAIN_ICC),y) CFLAGS += -wd188 #188: enumerated type mixed with another type endif
drivers/net/bnx2x/bnx2x.c +1 -1
@@ -177,7 +177,7 @@ bnx2x_dma_alloc(struct bnx2x_softc *sc, size_t size, struct bnx2x_dma *dma, rte_get_timer_cycles());/* Caller must take care that strlen(mz_name) < RTE_MEMZONE_NAMESIZE */ - z =rte_memzone_reserve_aligned (mz_name, (uint64_t ) (size), + z =rte_memzone_reserve_aligned_contig (mz_name, (uint64_t )size,SOCKET_ID_ANY ,0 , align);if (z ==NULL ) {
drivers/net/bnx2x/bnx2x_rxtx.c +2 -1
@@ -26,7 +26,8 @@ ring_dma_zone_reserve(struct rte_eth_dev *dev, const char *ring_name,if (mz)return mz; -return rte_memzone_reserve_aligned (z_name, ring_size, socket_id,0 ,BNX2X_PAGE_SIZE ); +return rte_memzone_reserve_aligned_contig (z_name, ring_size, socket_id, +0 ,BNX2X_PAGE_SIZE ); } static void
Signature · 1 line
2.7.4
PATCH v3 16/68 net/cxgbe: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
- Allowed experimental API's in the makefile
drivers/net/cxgbe/Makefile | 3 +++ drivers/net/cxgbe/sge.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-)
drivers/net/cxgbe/Makefile +3 -0
@@ -18,6 +18,9 @@ EXPORT_MAP := rte_pmd_cxgbe_version.map LIBABIVER := 1 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + ifeq ($(CONFIG_RTE_TOOLCHAIN_ICC),y) # # CFLAGS for icc
drivers/net/cxgbe/sge.c +2 -1
@@ -1344,7 +1344,8 @@ static void *alloc_ring(size_t nelem, size_t elem_size,* handle the maximum ring size is allocated in order to allow for * resizing in later calls to the queue setup function. */ - tz =rte_memzone_reserve_aligned (z_name, len, socket_id,0 ,4096 ); + tz =rte_memzone_reserve_aligned_contig (z_name, len, socket_id,0 , +4096 );if (!tz)return NULL ;
Signature · 1 line
2.7.4
PATCH v3 17/68 net/ena: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
- Allowed experimental API's in the Makefile
drivers/net/ena/Makefile | 3 +++ drivers/net/ena/base/ena_plat_dpdk.h | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-)
drivers/net/ena/Makefile +3 -0
@@ -43,6 +43,9 @@ INCLUDES :=-I$(SRCDIR) -I$(SRCDIR)/base/ena_defs -I$(SRCDIR)/base EXPORT_MAP := rte_pmd_ena_version.map LIBABIVER := 1 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + VPATH += $(SRCDIR)/base # # all source are stored in SRCS-y
drivers/net/ena/base/ena_plat_dpdk.h +4 -3
@@ -188,7 +188,8 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (handle); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size,SOCKET_ID_ANY ,0 ); \ + mz =rte_memzone_reserve_contig (z_name, \ + size,SOCKET_ID_ANY ,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ phys = mz->iova; \
@@ -206,7 +207,7 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (dev_node); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size, node,0 ); \ + mz =rte_memzone_reserve_contig (z_name, size, node,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ phys = mz->iova; \
@@ -219,7 +220,7 @@ typedef uint64_t dma_addr_t;ENA_TOUCH (dmadev);ENA_TOUCH (dev_node); \snprintf (z_name,sizeof (z_name), \"ena_alloc_%d" , ena_alloc_cnt++); \ - mz =rte_memzone_reserve (z_name, size, node,0 ); \ + mz =rte_memzone_reserve_contig (z_name, size, node,0 ); \memset (mz->addr,0 , size); \ virt = mz->addr; \ }while (0 )
Signature · 1 line
2.7.4
PATCH v3 18/68 net/enic: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
- Allowed experimental API in Makefile
v3:
- Moved patch earlier in the patchset
- Allowed experimental API in the build system
drivers/net/enic/Makefile | 3 +++ drivers/net/enic/enic_main.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-)
drivers/net/enic/Makefile +3 -0
@@ -13,6 +13,9 @@ EXPORT_MAP := rte_pmd_enic_version.map LIBABIVER := 1 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + CFLAGS += -I$(SRCDIR)/base/ CFLAGS += -I$(SRCDIR) CFLAGS += -O3
drivers/net/enic/enic_main.c +2 -2
@@ -343,7 +343,7 @@ enic_alloc_consistent(void *priv, size_t size,struct enic *enic = (struct enic *)priv;struct enic_memzone_entry *mze; - rz =rte_memzone_reserve_aligned ((const char *)name, + rz =rte_memzone_reserve_aligned_contig ((const char *)name, size,SOCKET_ID_ANY ,0 ,ENIC_ALIGN );if (!rz) { pr_err("%s : Failed to allocate memory requested for %s\n",
@@ -887,7 +887,7 @@ int enic_alloc_wq(struct enic *enic, uint16_t queue_idx,"vnic_cqmsg-%s-%d-%d" , enic->bdf_name, queue_idx, instance++); - wq->cqmsg_rz =rte_memzone_reserve_aligned ((const char *)name, + wq->cqmsg_rz =rte_memzone_reserve_aligned_contig ((const char *)name,sizeof (uint32_t ),SOCKET_ID_ANY ,0 ,ENIC_ALIGN );
Signature · 1 line
2.7.4
PATCH v3 19/68 net/i40e: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
- Allowed experimental API in the build system
drivers/net/i40e/Makefile | 3 +++ drivers/net/i40e/i40e_ethdev.c | 2 +- drivers/net/i40e/i40e_rxtx.c | 2 +- drivers/net/i40e/meson.build | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-)
drivers/net/i40e/Makefile +3 -0
@@ -19,6 +19,9 @@ EXPORT_MAP := rte_pmd_i40e_version.map LIBABIVER := 2 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + # # Add extra flags for base driver files (also known as shared code) # to disable warnings
drivers/net/i40e/i40e_ethdev.c +1 -1
@@ -4053,7 +4053,7 @@ i40e_allocate_dma_mem_d(__attribute__((unused)) struct i40e_hw *hw,return I40E_ERR_PARAM ;snprintf (z_name,sizeof (z_name),"i40e_dma_%" PRIu64,rte_rand ()); - mz =rte_memzone_reserve_bounded (z_name, size,SOCKET_ID_ANY ,0 , + mz =rte_memzone_reserve_bounded_contig (z_name, size,SOCKET_ID_ANY ,0 , alignment,RTE_PGSIZE_2M );if (!mz)return I40E_ERR_NO_MEMORY ;
drivers/net/i40e/i40e_rxtx.c +1 -1
@@ -2189,7 +2189,7 @@ i40e_memzone_reserve(const char *name, uint32_t len, int socket_id)if (mz)return mz; - mz =rte_memzone_reserve_aligned (name, len, + mz =rte_memzone_reserve_aligned_contig (name, len, socket_id,0 ,I40E_RING_BASE_ALIGN );return mz; }
drivers/net/i40e/meson.build +3 -0
@@ -46,3 +46,6 @@ endif includes += include_directories('base') install_headers('rte_pmd_i40e.h') + +# contig memzone allocation is not yet part of stable API +allow_experimental_apis = true
Signature · 1 line
2.7.4
PATCH v3 20/68 net/qede: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved the patch earlier in the patchset
- Allowed experimental API in Makefile
drivers/net/qede/Makefile | 3 +++ drivers/net/qede/base/bcm_osal.c | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/net/qede/Makefile +3 -0
@@ -21,6 +21,9 @@ EXPORT_MAP := rte_pmd_qede_version.map LIBABIVER := 1 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + # # OS #
drivers/net/qede/base/bcm_osal.c +3 -2
@@ -135,7 +135,7 @@ void *osal_dma_alloc_coherent(struct ecore_dev *p_dev,if (core_id == (unsigned int )LCORE_ID_ANY ) core_id =rte_get_master_lcore (); socket_id =rte_lcore_to_socket_id (core_id); - mz =rte_memzone_reserve_aligned (mz_name, size, + mz =rte_memzone_reserve_aligned_contig (mz_name, size, socket_id,0 ,RTE_CACHE_LINE_SIZE );if (!mz) { DP_ERR(p_dev, "Unable to allocate DMA memory "
@@ -174,7 +174,8 @@ void *osal_dma_alloc_coherent_aligned(struct ecore_dev *p_dev,if (core_id == (unsigned int )LCORE_ID_ANY ) core_id =rte_get_master_lcore (); socket_id =rte_lcore_to_socket_id (core_id); - mz =rte_memzone_reserve_aligned (mz_name, size, socket_id,0 , align); + mz =rte_memzone_reserve_aligned_contig (mz_name, size, socket_id,0 , + align);if (!mz) { DP_ERR(p_dev, "Unable to allocate DMA memory " "of size %zu bytes - %s\n",
Signature · 1 line
2.7.4
PATCH v3 21/68 net/virtio: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
drivers/net/virtio/virtio_ethdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/virtio/virtio_ethdev.c +4 -4
@@ -390,7 +390,7 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)PMD_INIT_LOG (DEBUG ,"vring_size: %d, rounded_vring_size: %d" , size, vq->vq_ring_size); - mz =rte_memzone_reserve_aligned (vq_name, vq->vq_ring_size, + mz =rte_memzone_reserve_aligned_contig (vq_name, vq->vq_ring_size,SOCKET_ID_ANY ,0 ,VIRTIO_PCI_VRING_ALIGN );if (mz ==NULL ) {
@@ -416,9 +416,9 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)if (sz_hdr_mz) {snprintf (vq_hdr_name,sizeof (vq_hdr_name),"port%d_vq%d_hdr" , dev->data->port_id, vtpci_queue_idx); - hdr_mz =rte_memzone_reserve_aligned (vq_hdr_name, sz_hdr_mz, -SOCKET_ID_ANY ,0 , -RTE_CACHE_LINE_SIZE ); + hdr_mz =rte_memzone_reserve_aligned_contig (vq_hdr_name, + sz_hdr_mz,SOCKET_ID_ANY ,0 , +RTE_CACHE_LINE_SIZE );if (hdr_mz ==NULL ) {if (rte_errno ==EEXIST ) hdr_mz =rte_memzone_lookup (vq_hdr_name);
Signature · 1 line
2.7.4
PATCH v3 22/68 net/vmxnet3: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Moved patch earlier in the patchset
- Allowed experimental API in Makefile
drivers/net/vmxnet3/Makefile | 3 +++ drivers/net/vmxnet3/vmxnet3_ethdev.c | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-)
drivers/net/vmxnet3/Makefile +3 -0
@@ -45,6 +45,9 @@ EXPORT_MAP := rte_pmd_vmxnet3_version.map LIBABIVER := 1 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + # # all source are stored in SRCS-y #
drivers/net/vmxnet3/vmxnet3_ethdev.c +4 -3
@@ -149,14 +149,15 @@ gpa_zone_reserve(struct rte_eth_dev *dev, uint32_t size,if (!reuse) {if (mz)rte_memzone_free (mz); -return rte_memzone_reserve_aligned (z_name, size, socket_id, -0 , align); +return rte_memzone_reserve_aligned_contig (z_name, size, + socket_id,0 , align); }if (mz)return mz; -return rte_memzone_reserve_aligned (z_name, size, socket_id,0 , align); +return rte_memzone_reserve_aligned_contig (z_name, size, socket_id,0 , + align); }/*
Signature · 1 line
2.7.4
PATCH v3 23/68 net/bnxt: use contiguous allocation for DMA memory
In reply to Anatoly Burakov---
Notes:
v3:
- Added this patch
All memzone reserve calls then check physical addresses, so this looks like they're reserving DMA memory. Corrections welcome.
drivers/net/bnxt/Makefile | 3 +++ drivers/net/bnxt/bnxt_ethdev.c | 6 ++++-- drivers/net/bnxt/bnxt_ring.c | 3 ++- drivers/net/bnxt/bnxt_vnic.c | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-)
drivers/net/bnxt/Makefile +3 -0
@@ -42,6 +42,9 @@ EXPORT_MAP := rte_pmd_bnxt_version.map LIBABIVER := 2 +# contiguous memzone reserve API are not yet stable +CFLAGS += -DALLOW_EXPERIMENTAL_API + CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
drivers/net/bnxt/bnxt_ethdev.c +4 -2
@@ -3146,7 +3146,8 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev) total_alloc_len =RTE_CACHE_LINE_ROUNDUP (sizeof (struct rx_port_stats ) +512 );if (!mz) { - mz =rte_memzone_reserve (mz_name, total_alloc_len, + mz =rte_memzone_reserve_contig (mz_name, + total_alloc_len,SOCKET_ID_ANY ,RTE_MEMZONE_2MB |RTE_MEMZONE_SIZE_HINT_ONLY );
@@ -3181,7 +3182,8 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev) total_alloc_len =RTE_CACHE_LINE_ROUNDUP (sizeof (struct tx_port_stats ) +512 );if (!mz) { - mz =rte_memzone_reserve (mz_name, total_alloc_len, + mz =rte_memzone_reserve_contig (mz_name, + total_alloc_len,SOCKET_ID_ANY ,RTE_MEMZONE_2MB |RTE_MEMZONE_SIZE_HINT_ONLY );
drivers/net/bnxt/bnxt_ring.c +2 -1
@@ -165,7 +165,8 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx, mz_name[RTE_MEMZONE_NAMESIZE -1 ] =0 ; mz =rte_memzone_lookup (mz_name);if (!mz) { - mz = rte_memzone_reserve_aligned(mz_name, total_alloc_len, + mz = rte_memzone_reserve_aligned_contig(mz_name, + total_alloc_len, SOCKET_ID_ANY, RTE_MEMZONE_2MB | RTE_MEMZONE_SIZE_HINT_ONLY,
drivers/net/bnxt/bnxt_vnic.c +1 -1
@@ -184,7 +184,7 @@ int bnxt_alloc_vnic_attributes(struct bnxt *bp) mz_name[RTE_MEMZONE_NAMESIZE -1 ] =0 ; mz =rte_memzone_lookup (mz_name);if (!mz) { - mz = rte_memzone_reserve(mz_name, + mz = rte_memzone_reserve_contig(mz_name, entry_length * max_vnics, SOCKET_ID_ANY, RTE_MEMZONE_2MB |
Signature · 1 line
2.7.4
PATCH v3 24/68 mempool: add support for the new allocation methods
In reply to Anatoly BurakovIf a user has specified that the zone should have contiguous memory, use the new _contig allocation API's instead of normal ones. Otherwise, account for the fact that unless we're in IOVA_AS_VA mode, we cannot guarantee that the pages would be physically contiguous, so we calculate the memzone size and alignments as if we were getting the smallest page size available.
Existing mempool size calculation function also doesn't give us expected results, because it will return memzone sizes aligned to page size (e.g. a 1MB mempool will reserve the entire 1GB page if all user has are 1GB pages), so add a new one that will give us results more in line with what we would expect.
---
Notes:
v3:
- Fixed mempool size calculation
- Fixed handling of contiguous memzones
- Moved earlier in the patchset
lib/librte_mempool/Makefile | 3 + lib/librte_mempool/meson.build | 3 + lib/librte_mempool/rte_mempool.c | 137 ++++++++++++++++++++++++++++++++------- 3 files changed, 121 insertions(+), 22 deletions(-)
lib/librte_mempool/Makefile +3 -0
@@ -13,6 +13,9 @@ EXPORT_MAP := rte_mempool_version.map LIBABIVER := 3 +# uses new contiguous memzone allocation that isn't yet in stable ABI +CFLAGS += -DALLOW_EXPERIMENTAL_API + # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool.c SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool_ops.c
lib/librte_mempool/meson.build +3 -0
@@ -5,3 +5,6 @@ version = 3 sources = files('rte_mempool.c', 'rte_mempool_ops.c') headers = files('rte_mempool.h') deps += ['ring'] + +# contig memzone allocation is not yet part of stable API +allow_experimental_apis = true
lib/librte_mempool/rte_mempool.c +115 -22
196 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v3 25/68 eal: add function to walk all memsegs
In reply to Anatoly BurakovFor code that might need to iterate over list of allocated segments, using this API will make it more resilient to internal API changes and will prevent copying the same iteration code over and over again.
Additionally, down the line there will be locking implemented, so users of this API will not need to care about locking either.
--- lib/librte_eal/common/eal_common_memory.c | 21 +++++++++++++++++++++ lib/librte_eal/common/include/rte_memory.h | 25 +++++++++++++++++++++++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 47 insertions(+)
lib/librte_eal/common/eal_common_memory.c +21 -0
@@ -218,6 +218,27 @@ rte_mem_lock_page(const void *virt)return mlock ((void *)aligned, page_size); } +int __rte_experimental +rte_memseg_walk (rte_memseg_walk_t func,void *arg) +{ +struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; +int i, ret; + +for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { +const struct rte_memseg *ms = &mcfg->memseg[i]; + +if (ms->addr ==NULL ) +continue ; + + ret =func (ms, arg); +if (ret <0 ) +return -1 ; +if (ret >0 ) +return 1 ; + } +return 0 ; +} +/* init memory subsystem */ int rte_eal_memory_init (void )
lib/librte_eal/common/include/rte_memory.h +25 -0
@@ -20,6 +20,7 @@ extern "C" {#endif #include <rte_common.h> +#include <rte_compat.h> #include <rte_config.h> __extension__
@@ -130,6 +131,30 @@ phys_addr_t rte_mem_virt2phy(const void *virt);rte_iova_t rte_mem_virt2iova (const void *virt);/** +* Memseg walk function prototype. +* +* Returning 0 will continue walk +* Returning 1 will stop the walk +* Returning -1 will stop the walk and report error +*/ +typedef int (*rte_memseg_walk_t )(const struct rte_memseg *ms,void *arg); + +/** +* Walk list of all memsegs. +* +* @param func +* Iterator function +* @param arg +* Argument passed to iterator +* @return +* 0 if walked over the entire list +* 1 if stopped by the user +* -1 if user function reported error +*/ +int __rte_experimental +rte_memseg_walk (rte_memseg_walk_t func,void *arg); + +/** * Get the layout of the available physical memory. * * It can be useful for an application to have the full physical
lib/librte_eal/rte_eal_version.map +1 -0
@@ -223,6 +223,7 @@ EXPERIMENTAL { rte_eal_mbuf_user_pool_ops; rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; + rte_memseg_walk; rte_memzone_reserve_contig; rte_memzone_reserve_aligned_contig; rte_memzone_reserve_bounded_contig;
Signature · 1 line
2.7.4
PATCH v3 26/68 bus/fslmc: use memseg walk instead of iteration
In reply to Anatoly Burakov--- drivers/bus/fslmc/fslmc_vfio.c | 78 ++++++++++++++++++++++-------------------- drivers/event/dpaa2/Makefile | 3 ++ drivers/mempool/dpaa2/Makefile | 3 ++ drivers/net/dpaa2/Makefile | 3 ++ drivers/net/dpaa2/meson.build | 3 ++ drivers/net/octeontx/Makefile | 3 ++ 6 files changed, 56 insertions(+), 37 deletions(-)
drivers/bus/fslmc/fslmc_vfio.c +41 -37
@@ -193,17 +193,51 @@ static int vfio_map_irq_region(struct fslmc_vfio_group *group)return -errno; } -int rte_fslmc_vfio_dmamap (void ) +static int +fslmc_vfio_map (const struct rte_memseg *ms,void *arg) { -int ret; +int *n_segs = arg;struct fslmc_vfio_group *group;struct vfio_iommu_type1_dma_map dma_map = { .argsz =sizeof (struct vfio_iommu_type1_dma_map ), .flags =VFIO_DMA_MAP_FLAG_READ |VFIO_DMA_MAP_FLAG_WRITE , }; +int ret; + + dma_map.size = ms->len; + dma_map.vaddr = ms->addr_64; +#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA + dma_map.iova = ms->iova; +#else + dma_map.iova = dma_map.vaddr; +#endif + +/* SET DMA MAP for IOMMU */ + group = &vfio_group; + +if (!group->container) { +FSLMC_VFIO_LOG (ERR ,"Container is not connected " ); +return -1 ; + } + +FSLMC_VFIO_LOG (DEBUG ,"-->Initial SHM Virtual ADDR %llX" , + dma_map.vaddr); +FSLMC_VFIO_LOG (DEBUG ,"-----> DMA size 0x%llX" , dma_map.size); + ret =ioctl (group->container->fd,VFIO_IOMMU_MAP_DMA , + &dma_map); +if (ret) { +FSLMC_VFIO_LOG (ERR ,"VFIO_IOMMU_MAP_DMA API(errno = %d)" , + errno); +return -1 ; + } + (*n_segs)++; +return 0 ; +} -int i; +int rte_fslmc_vfio_dmamap (void ) +{const struct rte_memseg *memseg; +int i =0 ;if (is_dma_done)return 0 ;
@@ -214,51 +248,21 @@ int rte_fslmc_vfio_dmamap(void)return -ENODEV ; } -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { -if (memseg[i].addr ==NULL && memseg[i].len ==0 ) { -FSLMC_VFIO_LOG (DEBUG ,"Total %d segments found." , i); -break ; - } - - dma_map.size = memseg[i].len; - dma_map.vaddr = memseg[i].addr_64; -#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA - dma_map.iova = memseg[i].iova; -#else - dma_map.iova = dma_map.vaddr; -#endif - -/* SET DMA MAP for IOMMU */ - group = &vfio_group; - -if (!group->container) { -FSLMC_VFIO_LOG (ERR ,"Container is not connected " ); -return -1 ; - } - -FSLMC_VFIO_LOG (DEBUG ,"-->Initial SHM Virtual ADDR %llX" , - dma_map.vaddr); -FSLMC_VFIO_LOG (DEBUG ,"-----> DMA size 0x%llX" , dma_map.size); - ret =ioctl (group->container->fd,VFIO_IOMMU_MAP_DMA , - &dma_map); -if (ret) { -FSLMC_VFIO_LOG (ERR ,"VFIO_IOMMU_MAP_DMA API(errno = %d)" , - errno); -return ret; - } - } +if (rte_memseg_walk (fslmc_vfio_map, &i) <0 ) +return -1 ;/* Verifying that at least single segment is available */ if (i <=0 ) {FSLMC_VFIO_LOG (ERR ,"No Segments found for VFIO Mapping" );return -1 ; } +FSLMC_VFIO_LOG (DEBUG ,"Total %d segments found." , i);/* TODO - This is a W.A. as VFIO currently does not add the mapping of * the interrupt region to SMMU. This should be removed once the * support is added in the Kernel. */ -vfio_map_irq_region (group); +vfio_map_irq_region (&vfio_group); is_dma_done =1 ;
drivers/event/dpaa2/Makefile +3 -0
@@ -28,6 +28,9 @@ EXPORT_MAP := rte_pmd_dpaa2_event_version.map LIBABIVER := 1 +# depends on fslmc bus which uses experimental API +CFLAGS += -DALLOW_EXPERIMENTAL_API + # # all source are stored in SRCS-y #
drivers/mempool/dpaa2/Makefile +3 -0
@@ -27,6 +27,9 @@ EXPORT_MAP := rte_mempool_dpaa2_version.map # Lbrary version LIBABIVER := 1 +# depends on fslmc bus which uses experimental API +CFLAGS += -DALLOW_EXPERIMENTAL_API + # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_MEMPOOL) += dpaa2_hw_mempool.c
drivers/net/dpaa2/Makefile +3 -0
@@ -33,6 +33,9 @@ EXPORT_MAP := rte_pmd_dpaa2_version.map # library version LIBABIVER := 1 +# depends on fslmc bus which uses experimental API +CFLAGS += -DALLOW_EXPERIMENTAL_API + SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += base/dpaa2_hw_dpni.c SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2_ethdev.c
drivers/net/dpaa2/meson.build +3 -0
@@ -13,3 +13,6 @@ sources = files('base/dpaa2_hw_dpni.c', 'mc/dpni.c') includes += include_directories('base', 'mc') + +# depends on fslmc bus which uses experimental API +allow_experimental_apis = true
drivers/net/octeontx/Makefile +3 -0
@@ -16,6 +16,9 @@ EXPORT_MAP := rte_pmd_octeontx_version.map LIBABIVER := 1 +# depends on fslmc bus which uses experimental API +CFLAGS += -DALLOW_EXPERIMENTAL_API + OBJS_BASE_DRIVER=$(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c))) $(foreach obj, $(OBJS_BASE_DRIVER), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER)))
Signature · 1 line
2.7.4
Re: [PATCH v3 26/68] bus/fslmc: use memseg walk instead of iteration
Hello Anatoly,
Quoted 15 lines · Anatoly Burakov
Signed-off-by Anatoly Burakov <[email protected]>--- drivers/bus/fslmc/fslmc_vfio.c | 78 ++++++++++++++++++++++-------------------- drivers/event/dpaa2/Makefile | 3 ++ drivers/mempool/dpaa2/Makefile | 3 ++ drivers/net/dpaa2/Makefile | 3 ++ drivers/net/dpaa2/meson.build | 3 ++ drivers/net/octeontx/Makefile | 3 ++ 6 files changed, 56 insertions(+), 37 deletions(-)drivers/bus/fslmc/fslmc_vfio.c +0
-0
drivers/bus/fslmc/fslmc_vfio.c static int vfio_map_irq_region(struct fslmc_vfio_group *group) · line 193
Quoted 1 line
drivers/bus/fslmc/fslmc_vfio.c +0
-0@@ -193,17 +193,51 @@ static int vfio_map_irq_region(struct fslmc_vfio_group *group)return -errno;
[...]
I will send an incremental patch, in reply to this, which fixes dpaa2 for va cases.
Though, I think this patch can be completely replaced by that - if you prefer that, let me know and I will send it non-incremental (master based).
Quoted 16 lines
drivers/net/dpaa2/meson.build +3
-0@@ -13,3 +13,6 @@ sources = files('base/dpaa2_hw_dpni.c', 'mc/dpni.c') includes += include_directories('base', 'mc') + +# depends on fslmc bus which uses experimental API +allow_experimental_apis = truedrivers/net/octeontx/Makefile +0
-0
drivers/net/octeontx/Makefile EXPORT_MAP := rte_pmd_octeontx_version.map · line 19
Quoted 4 lines
drivers/net/octeontx/Makefile +1
-0@@ -16,6 +16,9 @@ EXPORT_MAP := rte_pmd_octeontx_version.map LIBABIVER := 1 +# depends on fslmc bus which uses experimental API
I think you wanted to say "octeontx" rather than fslmc here. Also, this is not part of 'bus/fslmc' patch.
drivers/net/octeontx/Makefile EXPORT_MAP := rte_pmd_octeontx_version.map · line 24
Quoted 6 lines
drivers/net/octeontx/Makefile +2
-0+CFLAGS += -DALLOW_EXPERIMENTAL_API + OBJS_BASE_DRIVER=$(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c))) $(foreach obj, $(OBJS_BASE_DRIVER), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER)))
If the Octeon part is removed from above, and incremental patch is merged here, please use my Ack:
PATCH 1/1 bus/fslmc: support for hotplugging of memory
In reply to Anatoly BurakovRestructure VFIO DMA code for handling hotplug memory events (callbacks) and --legacy case.
---
###
This is based on the 16fbfef04a3 github repository. This is assuming that changes already exists as done in patch 26/68.
Though, this can be a standalone, replacing 26/88. Though, the Makefile changes don't exist in this.
Also, this just a first draft. I will push any review changes after this incrementally over v4.
###
drivers/bus/fslmc/fslmc_bus.c | 15 ++++ drivers/bus/fslmc/fslmc_vfio.c | 161 +++++++++++++++++++++++++++++++++++---- drivers/bus/fslmc/fslmc_vfio.h | 1 + drivers/net/dpaa2/dpaa2_ethdev.c | 1 - 4 files changed, 163 insertions(+), 15 deletions(-)
drivers/bus/fslmc/fslmc_bus.c +15 -0
@@ -266,6 +266,21 @@ rte_fslmc_probe(void)return 0 ; } +if (rte_log_get_global_level () >=RTE_LOG_DEBUG ) +rte_dump_physmem_layout (stdout); + +/* Map existing segments as well as, in case of hotpluggable memory, +* install callback handler. +*/ + ret =rte_fslmc_vfio_dmamap (); +if (ret) { +FSLMC_BUS_LOG (ERR ,"Unable to DMA map existing VAs: (%d)" , + ret); +/* Not continuing ahead */ +FSLMC_BUS_LOG (ERR ,"FSLMC VFIO Mapping failed" ); +return 0 ; + } + ret =fslmc_vfio_process_group ();if (ret) {FSLMC_BUS_LOG (ERR ,"Unable to setup devices %d" , ret);
drivers/bus/fslmc/fslmc_vfio.c +147 -14
213 lines not on this page · raw message
drivers/bus/fslmc/fslmc_vfio.h +1 -0
@@ -9,6 +9,7 @@#define _FSLMC_VFIO_H_#include <rte_vfio.h> +#include <rte_memory.h> #include "eal_vfio.h"
drivers/net/dpaa2/dpaa2_ethdev.c +0 -1
@@ -1850,7 +1850,6 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev) eth_dev->rx_pkt_burst = dpaa2_dev_prefetch_rx; eth_dev->tx_pkt_burst = dpaa2_dev_tx; -rte_fslmc_vfio_dmamap ();RTE_LOG (INFO ,PMD ,"%s: netdev created\n" , eth_dev->data->name);return 0 ;
Signature · 1 line
2.14.1
Re: [PATCH] bus/fslmc: support for hotplugging of memory
Quoted 6 lines · Shreyansh Jain
Restructure VFIO DMA code for handling hotplug memory events (callbacks) and --legacy case.
Signed-off-by Shreyansh Jain <[email protected]>---
Quoted 8 lines
###
This is based on the16fbfef04a3github repository. This is assuming that changes already exists as done in patch 26/68.
Though, this can be a standalone, replacing 26/88. Though, theMakefilechanges don't exist in this.
Also, this just a first draft. I will push any review changes after this incrementally over v4.
###
Hi Shreyansh,
I think we can keep the 26/68 as it still works within the context of the patchset. I would like to add these changes closer to the end, where we enable support for callbacks in VFIO (this could/should come as the next patch).
That said, i took some liberties when integrating this patch, hopefully for the better. I know you mentioned it's a draft, so you can post any comments for the inevitable v4 :)
Quoted 12 lines
drivers/bus/fslmc/fslmc_bus.c | 15 ++++ drivers/bus/fslmc/fslmc_vfio.c | 161 +++++++++++++++++++++++++++++++++++---- drivers/bus/fslmc/fslmc_vfio.h | 1 + drivers/net/dpaa2/dpaa2_ethdev.c | 1 - 4 files changed, 163 insertions(+), 15 deletions(-)drivers/bus/fslmc/fslmc_bus.c +0
-0
drivers/bus/fslmc/fslmc_bus.c rte_fslmc_probe(void) · line 270
Quoted 5 lines
drivers/bus/fslmc/fslmc_bus.c +2
-0@@ -266,6 +266,21 @@ rte_fslmc_probe(void)return 0 ; } +if (rte_log_get_global_level () >=RTE_LOG_DEBUG ) +rte_dump_physmem_layout (stdout);
Presumably, this is not needed - just debug leftovers?
drivers/bus/fslmc/fslmc_bus.c rte_fslmc_probe(void) · line 283
Quoted 13 lines
drivers/bus/fslmc/fslmc_bus.c +13
-0+ +/* Map existing segments as well as, in case of hotpluggable memory, +* install callback handler. +*/ + ret =rte_fslmc_vfio_dmamap (); +if (ret) { +FSLMC_BUS_LOG (ERR ,"Unable to DMA map existing VAs: (%d)" , + ret); +/* Not continuing ahead */ +FSLMC_BUS_LOG (ERR ,"FSLMC VFIO Mapping failed" ); +return 0 ; + } +
What happens if there are no devices on the bus that can be used by DPDK? As far as i can tell, it would return error, which may or may not be desirable (failing to map anything because there aren't any fslmc devices is not an error?).
For "regular" VFIO, the container is an empty shell unless you add groups into it - does fslmc VFIO support work differently, and container is already working/initialized by the time we reach this point?
Anyway, i'll leave this as is.
Quoted 12 lines
drivers/bus/fslmc/fslmc_bus.c +0
-0ret =fslmc_vfio_process_group ();if (ret) {FSLMC_BUS_LOG (ERR ,"Unable to setup devices %d" , ret);drivers/bus/fslmc/fslmc_vfio.c +1
-0@@ -30,6 +30,7 @@#include <rte_kvargs.h> #include <rte_dev.h> #include <rte_bus.h> +#include <rte_eal_memconfig.h>
<...>
drivers/bus/fslmc/fslmc_vfio.c static int vfio_map_irq_region(struct fslmc_vfio_group *group) · line 257
Quoted 10 lines
drivers/bus/fslmc/fslmc_vfio.c +7
-2+} + static int -fslmc_vfio_map(const struct rte_memseg_list *msl __rte_unused, -const struct rte_memseg *ms,void *arg) +#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA +fslmc_map_dma(uint64_t vaddr, rte_iova_t iovaddr, size_t len) +#else +fslmc_map_dma(uint64_t vaddr, rte_iova_t iovaddr __rte_unused, size_t len) +#endif
I think i'll leave this as just "rte_iova_t iovaaddr __rte_unused" :)
Quoted 13 lines
{drivers/bus/fslmc/fslmc_vfio.c +2
-3-int *n_segs = arg;struct fslmc_vfio_group *group;struct vfio_iommu_type1_dma_map dma_map = { .argsz =sizeof (struct vfio_iommu_type1_dma_map ),@@ -205,10 +263,11 @@ fslmc_vfio_map(const struct rte_memseg_list *msl __rte_unused, };int ret; - dma_map.size = ms->len; - dma_map.vaddr = ms->addr_64; + dma_map.size = len; + dma_map.vaddr = vaddr;
<...>
Quoted 4 lines
if (
is_dma_done)
return 0;
I suspect this check was needed because you've done VFIO mapping on device probe as opposed to bus probe, so VFIO mapping function could've been called multiple times. Is that still the case, or is this check no longer needed? I took the liberty to remove it.
Quoted 4 lines
drivers/bus/fslmc/fslmc_vfio.c +3
-1-if (rte_memseg_walk (fslmc_vfio_map, &i) <0 ) +/* Lock before parsing and registering callback to memory subsystem */ +rte_rwlock_read_lock (mem_lock); +
<...>
drivers/bus/fslmc/fslmc_vfio.h line 15
Quoted 13 lines
return 0;
drivers/bus/fslmc/fslmc_vfio.h +1
-0@@ -9,6 +9,7 @@#define _FSLMC_VFIO_H_#include <rte_vfio.h> +#include <rte_memory.h> #include "eal_vfio.h"
I suspect this change is not needed? I took the liberty to remove it.
Signature · 2 lines
Thanks, Anatoly
Re: [PATCH] bus/fslmc: support for hotplugging of memory
Hello Anatoly,
Quoted 16 lines · Anatoly
Quoted 6 lines · Shreyansh Jain
Restructure VFIO DMA code for handling hotplug memory events (callbacks) and --legacy case.
Signed-off-by Shreyansh Jain <[email protected]>---
Quoted 8 lines
###
This is based on the16fbfef04a3github repository. This is assuming that changes already exists as done in patch 26/68.
Though, this can be a standalone, replacing 26/88. Though, theMakefilechanges don't exist in this.
Also, this just a first draft. I will push any review changes after this incrementally over v4.
###
Quoted 3 lines
Hi Shreyansh,
I think we can keep the 26/68 as it still works within the context of the patchset. I would like to add these changes closer to the end, where we enable support for callbacks in VFIO (this could/should come as the next patch).
But then it would also mean that dpaa2 would be broken within the memory hotplug patches? I think it would be broken once the memseg ceases to be continuous physical sets.
Quoted 11 lines
That said, i took some liberties when integrating this patch, hopefully for the better. I know you mentioned it's a draft, so you can post any comments for the inevitable v4 :)
Quoted 8 lines
drivers/bus/fslmc/fslmc_bus.c | 15 ++++
drivers/bus/fslmc/fslmc_vfio.c | 161
+++++++++++++++++++++++++++++++++++----
drivers/bus/fslmc/fslmc_vfio.h | 1 +
drivers/net/dpaa2/dpaa2_ethdev.c| 1 -4 files changed, 163 insertions(+), 15 deletions(-)
Quoted 11 lines
drivers/bus/fslmc/fslmc_bus.c rte_fslmc_probe(void) · line 269
Quoted 9 lines
drivers/bus/fslmc/fslmc_bus.c +2
-0@@ -266,6 +266,21 @@ rte_fslmc_probe(void) return 0; } + if (rte_log_get_global_level() >= RTE_LOG_DEBUG) + rte_dump_physmem_layout(stdout);Presumably, this is not needed - just debug leftovers?
Yes, and can be removed.
Quoted 16 lines
Quoted 4 lines
drivers/bus/fslmc/fslmc_bus.c +3
-0+ + /* Map existing segments as well as, in case of hotpluggable memory, +* install callback handler. drivers/bus/fslmc/fslmc_bus.c rte_fslmc_probe(void) · line 283
Quoted 10 lines
drivers/bus/fslmc/fslmc_bus.c +10
-0+*/ + ret = rte_fslmc_vfio_dmamap(); + if (ret) { + FSLMC_BUS_LOG(ERR, "Unable to DMA map existing VAs: (%d)", + ret); + /* Not continuing ahead */ + FSLMC_BUS_LOG(ERR, "FSLMC VFIO Mapping failed"); + return 0; + } +What happens if there are no devices on the bus that can be used by DPDK? As far as i can tell, it would return error, which may or may not be desirable (failing to map anything because there aren't any fslmc devices is not an error?).
## If no devices found on the bus:
Call wouldn't have reached here. There is a jump out in rte_fslmc_probe in case no devices were scanned on the bus.
--->8--- rte_fslmc_probe() ---
...
if (TAILQ_EMPTY(&rte_fslmc_bus.device_list))
return 0;...
--->8---
## Assuming you are pointing to 'return 0':
So, the rte_eal_scan/probe doesn't expect to be interrupted just because one of the buses had issues (whether no devices found, not a real issue). It would continue ahead with scan/probe.
But, I think error should be returned so that rte_eal_probe can dump to logs the error and continue ahead normally. I will fix this.
Quoted 2 lines
For "regular" VFIO, the container is an empty shell unless you add groups into it - does fslmc VFIO support work differently, and container is already working/initialized by the time we reach this point?
FSLMC VFIO Container is not much different from generic container. But, at this point in code, the container is already initialized (group is connected to it, and relevant device fds extracted). Only thing pending beyond this point is to look into the container and initialize various fslmc specific devices contained *within* the group. And, dma mapping of regions which is done using the newly introduced code.
Quoted 2 lines
Anyway, i'll leave this as is.
OK.
Quoted 16 lines
Quoted 13 lines
drivers/bus/fslmc/fslmc_bus.c +0
-0ret = fslmc_vfio_process_group(); if (ret) { FSLMC_BUS_LOG(ERR, "Unable to setup devices %d", ret);drivers/bus/fslmc/fslmc_vfio.c +1
-0@@ -30,6 +30,7 @@ #include <rte_kvargs.h> #include <rte_dev.h> #include <rte_bus.h> +#include <rte_eal_memconfig.h> <...>
Quoted 13 lines
Quoted 11 lines
drivers/bus/fslmc/fslmc_vfio.c +2
-0+} +static int
drivers/bus/fslmc/fslmc_vfio.c +4
-2-fslmc_vfio_map(const struct rte_memseg_list *msl __rte_unused, - const struct rte_memseg *ms, void *arg) +#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA +fslmc_map_dma(uint64_t vaddr, rte_iova_t iovaddr, size_t len) +#else +fslmc_map_dma(uint64_t vaddr, rte_iova_t iovaddr __rte_unused, size_tlen)
+#endifI think i'll leave this as just "
rte_iova_tiovaaddr__rte_unused" :)
Hmm, it is harmless if used without the enclosing #defines.
But, i don't know if any compiler has any side-effects attached to this - for example, clang reporting this as error, etc.
Quoted 17 lines
Quoted 14 lines
{
- int*n_segs= arg;
structfslmc_vfio_group*group;
structvfio_iommu_type1_dma_mapdma_map= { .argsz =sizeof(struct vfio_iommu_type1_dma_map),drivers/bus/fslmc/fslmc_vfio.c +2
-2@@ -205,10 +263,11 @@ fslmc_vfio_map(const struct rte_memseg_list *msl __rte_unused, }; int ret; - dma_map.size = ms->len; - dma_map.vaddr = ms->addr_64; + dma_map.size = len; + dma_map.vaddr = vaddr;<...>
Quoted 4 lines
Quoted 2 lines
if (
is_dma_done)
return 0;I suspect this check was needed because you've done VFIO mapping on device probe as opposed to bus probe, so VFIO mapping function could've been called multiple times. Is that still the case, or is this check no longer needed? I took the liberty to remove it.
Yes, that is correct. Now that device probe vfio is disabled, it is safe to remove this check.
Quoted 9 lines
Quoted 6 lines
- if (
rte_memseg_walk(fslmc_vfio_map, &i)< 0)
+ /* Lock before parsing and registering callback to memory subsystem */
+rte_rwlock_read_lock(mem_lock);
+<...>
Quoted 13 lines
drivers/bus/fslmc/fslmc_vfio.h line 12
Quoted 10 lines
return 0;
drivers/bus/fslmc/fslmc_vfio.h +1
-0@@ -9,6 +9,7 @@ #define _FSLMC_VFIO_H_ #include <rte_vfio.h> +#include <rte_memory.h> #include "eal_vfio.h"I suspect this change is not needed? I took the liberty to remove it.
I remember when I was using your initial patch, this I added based on structures being unresolved. It is possible that is not longer the case (and that I too have moved a lot of code beyond the first internal draft). If it compiles OK, no need for this.
-
Shreyansh
Re: [PATCH] bus/fslmc: support for hotplugging of memory
Quoted 19 lines · Shreyansh Jain
Hello Anatoly,
Quoted 16 lines · Anatoly
Quoted 14 lines · Shreyansh Jain
Restructure VFIO DMA code for handling hotplug memory events (callbacks) and --legacy case.
Signed-off-by Shreyansh Jain <[email protected]>---
###
This is based on the16fbfef04a3github repository. This is assuming that changes already exists as done in patch 26/68.
Though, this can be a standalone, replacing 26/88. Though, theMakefilechanges don't exist in this.
Also, this just a first draft. I will push any review changes after this incrementally over v4.
###
Quoted 7 lines
Quoted 3 lines
Hi Shreyansh,
I think we can keep the 26/68 as it still works within the context of the patchset. I would like to add these changes closer to the end, where we enable support for callbacks in VFIO (this could/should come as the next patch).
But then it would also mean that dpaa2 would be broken within the memory hotplug patches? I think it would be broken once the memseg ceases to be continuous physical sets.
Hi Shreyansh,
Why would it be broken? Even when memseg change comes into effect, legacy mem is not enabled until much later in the patchset, when all of the callback/multiprocess business is in place. For all intents and purposes, this stays valid for legacy mode, hence not broken.
We later enable callbacks etc. on VFIO, but technically they still aren't enabled until 65 (67 in v4), when it becomes possible to actually run DPDK in non-legacy mode.
So, for the duration of this patchset, dpaa2 is not broken, as far as i can tell. Keeping in mind that only legacy mode will be available until patch 65/67, what exactly is being broken here?
Signature · 2 lines
Thanks, Anatoly
Re: [PATCH] bus/fslmc: support for hotplugging of memory
Quoted 44 lines
-----Original Message-----
From: Burakov, Anatoly [mailto:[email protected]]
Sent: Monday, April 9, 2018 9:20 PM
To: Shreyansh Jain <[email protected]>
Cc: [email protected]
Subject: Re: [dpdk-dev] [PATCH] bus/fslmc: support for hotplugging of memoryQuoted 14 lines · Shreyansh Jain
Hello Anatoly,
Quoted 11 lines · Anatoly
Quoted 10 lines · Shreyansh Jain
Restructure VFIO DMA code for handling hotplug memory events (callbacks) and --legacy case.
Signed-off-by Shreyansh Jain <[email protected]>---
###
This is based on the16fbfef04a3github repository. This is assuming that changes already exists as done in patch 26/68. Though, this can be a standalone, replacing 26/88. Though, the
MakefileQuoted 2 lines
Quoted 2 lines
Quoted 2 lines
changes don't exist in this.
Also, this just a first draft. I will push any review changes afterthis
Quoted 11 lines
Quoted 9 lines
Quoted 2 lines
incrementally over v4.
###Hi Shreyansh,
I think we can keep the 26/68 as it still works within the context of the patchset. I would like to add these changes closer to the end, where we enable support for callbacks in VFIO (this could/should come as the next patch).
But then it would also mean that dpaa2 would be broken within the
memory
Quoted 4 lines
hotplug patches?
I think it would be broken once the memseg ceases to be continuous physical sets.
Quoted 6 lines
Hi Shreyansh,
Why would it be broken? Even when memseg change comes into effect, legacy mem is not enabled until much later in the patchset, when all of the callback/multiprocess business is in place. For all intents and purposes, this stays valid for legacy mode, hence not broken.
Ok. Then, I am mistaken. I was under the impression that as soon as memseg lists are introduced, when memseg stop being contiguous blocks, DPAA2 would have stopped working. I just didn't put an effort to check this.
Quoted 4 lines
We later enable callbacks etc. on VFIO, but technically they still aren't enabled until 65 (67 in v4), when it becomes possible to actually run DPDK in non-legacy mode.
Got it. Thanks.
Quoted 5 lines
So, for the duration of this patchset, dpaa2 is not broken, as far as i can tell. Keeping in mind that only legacy mode will be available until patch 65/67, what exactly is being broken here?
Nothing, just a misunderstanding.
Quoted 3 lines
--
Thanks,
Anatoly
PATCH v3 27/68 bus/pci: use memseg walk instead of iteration
In reply to Anatoly Burakov--- drivers/bus/pci/Makefile | 3 +++ drivers/bus/pci/linux/pci.c | 26 ++++++++++++++------------ drivers/bus/pci/meson.build | 3 +++ 3 files changed, 20 insertions(+), 12 deletions(-)
drivers/bus/pci/Makefile +3 -0
@@ -49,6 +49,9 @@ CFLAGS += -I$(RTE_SDK)/drivers/bus/pci/$(SYSTEM) CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common CFLAGS += -I$(RTE_SDK)/lib/librte_eal/$(SYSTEM)app/eal +# memseg walk is not part of stable API yet +CFLAGS += -DALLOW_EXPERIMENTAL_API + LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring LDLIBS += -lrte_ethdev -lrte_pci
drivers/bus/pci/linux/pci.c +14 -12
@@ -116,22 +116,24 @@ rte_pci_unmap_device(struct rte_pci_device *dev) } } -void * -pci_find_max_end_va (void ) +static int +find_max_end_va (const struct rte_memseg *ms,void *arg) { -const struct rte_memseg *seg =rte_eal_get_physmem_layout (); -const struct rte_memseg *last = seg; -unsigned i =0 ; +void *end_va =RTE_PTR_ADD (ms->addr, ms->len); +void **max_va = arg; -for (i =0 ; i <RTE_MAX_MEMSEG ; i++, seg++) { -if (seg->addr ==NULL ) -break ; +if (*max_va < end_va) + *max_va = end_va; +return 0 ; +} -if (seg->addr > last->addr) - last = seg; +void * +pci_find_max_end_va (void ) +{ +void *va =NULL ; - } -return RTE_PTR_ADD (last->addr, last->len); +rte_memseg_walk (find_max_end_va, &va); +return va; }/* parse one line of the "resource" sysfs file (note that the 'line'
drivers/bus/pci/meson.build +3 -0
@@ -14,3 +14,6 @@ else sources += files('bsd/pci.c') includes += include_directories('bsd') endif + +# memseg walk is not part of stable API yet +allow_experimental_apis = true
Signature · 1 line
2.7.4
PATCH v3 28/68 net/mlx5: use memseg walk instead of iteration
In reply to Anatoly Burakov--- drivers/net/mlx5/Makefile | 3 +++ drivers/net/mlx5/mlx5.c | 24 +++++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-)
drivers/net/mlx5/Makefile +3 -0
@@ -92,6 +92,9 @@ CFLAGS += -Wno-error=cast-qual EXPORT_MAP := rte_pmd_mlx5_version.map LIBABIVER := 1 +# memseg walk is not part of stable API +CFLAGS += -DALLOW_EXPERIMENTAL_API + # DEBUG which is usually provided on the command-line may enable # CONFIG_RTE_LIBRTE_MLX5_DEBUG. ifeq ($(DEBUG),1)
drivers/net/mlx5/mlx5.c +15 -9
@@ -477,6 +477,19 @@ static struct rte_pci_driver mlx5_driver;*/ static void *uar_base; +static int +find_lower_va_bound (const struct rte_memseg *ms,void *arg) +{ +void **addr = arg; + +if (*addr ==NULL ) + *addr = ms->addr; +else + *addr =RTE_MIN (*addr, ms->addr); + +return 0 ; +} +/** * Reserve UAR address space for primary process. *
@@ -491,21 +504,14 @@ mlx5_uar_init_primary(struct rte_eth_dev *dev) {struct priv *priv = dev->data->dev_private;void *addr = (void *)0 ; -int i; -const struct rte_mem_config *mcfg;if (uar_base) {/* UAR address space mapped. */ priv->uar_base = uar_base;return 0 ; }/* find out lower bound of hugepage segments */ - mcfg =rte_eal_get_configuration ()->mem_config; -for (i =0 ; i <RTE_MAX_MEMSEG && mcfg->memseg[i].addr; i++) { -if (addr) - addr =RTE_MIN (addr, mcfg->memseg[i].addr); -else - addr = mcfg->memseg[i].addr; - } +rte_memseg_walk (find_lower_va_bound, &addr); +/* keep distance to hugepages to minimize potential conflicts. */ addr =RTE_PTR_SUB (addr,MLX5_UAR_OFFSET +MLX5_UAR_SIZE );/* anonymous mmap, no real memory consumption. */
Signature · 1 line
2.7.4
PATCH v3 29/68 eal: use memseg walk instead of iteration
In reply to Anatoly Burakov--- lib/librte_eal/bsdapp/eal/eal.c | 25 +++++++----- lib/librte_eal/common/eal_common_memory.c | 67 ++++++++++++++++--------------- lib/librte_eal/common/malloc_heap.c | 33 +++++++++------ lib/librte_eal/linuxapp/eal/eal.c | 22 +++++----- 4 files changed, 81 insertions(+), 66 deletions(-)
lib/librte_eal/bsdapp/eal/eal.c +14 -11
@@ -429,23 +429,26 @@ eal_parse_args(int argc, char **argv)return ret; } +static int +check_socket (const struct rte_memseg *ms,void *arg) +{ +int *socket_id = arg; + +if (ms->socket_id == *socket_id) +return 1 ; + +return 0 ; +} +static void eal_check_mem_on_local_socket (void ) { -const struct rte_memseg *ms; -int i, socket_id; +int socket_id; socket_id =rte_lcore_to_socket_id (rte_config.master_lcore); - ms =rte_eal_get_physmem_layout (); - -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) -if (ms[i].socket_id == socket_id && - ms[i].len >0 ) -return ; - -RTE_LOG (WARNING ,EAL ,"WARNING: Master core has no " -"memory on local socket!\n" ); +if (rte_memseg_walk (check_socket, &socket_id) ==0 ) +RTE_LOG (WARNING ,EAL ,"WARNING: Master core has no memory on local socket!\n" ); } static int
lib/librte_eal/common/eal_common_memory.c +35 -32
89 lines not on this page · raw message
lib/librte_eal/common/malloc_heap.c +21 -12
@@ -67,17 +67,32 @@ check_hugepage_sz(unsigned flags, uint64_t hugepage_sz)* to prevent overflow. The rest of the zone is added to free list as a single * large free block */ -static void -malloc_heap_add_memseg (struct malloc_heap *heap,struct rte_memseg *ms) +static int +malloc_heap_add_memseg(const struct rte_memseg *ms, void *arg __rte_unused) { -struct malloc_elem *start_elem = (struct malloc_elem *)ms->addr; -const size_t elem_size = ms->len -MALLOC_ELEM_OVERHEAD ; +struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; +struct malloc_elem *start_elem; +struct rte_memseg *found_ms; +struct malloc_heap *heap; +size_t elem_size; +int ms_idx; + + heap = &mcfg->malloc_heaps[ms->socket_id]; + +/* ms is const, so find it */ + ms_idx = ms - mcfg->memseg; + found_ms = &mcfg->memseg[ms_idx]; -malloc_elem_init (start_elem, heap, ms, elem_size); + start_elem = (struct malloc_elem *)found_ms->addr; + elem_size = ms->len -MALLOC_ELEM_OVERHEAD ; + +malloc_elem_init (start_elem, heap, found_ms, elem_size);malloc_elem_insert (start_elem);malloc_elem_free_list_insert (start_elem); heap->total_size += elem_size; + +return 0 ; }/*
@@ -244,17 +259,11 @@ intrte_eal_malloc_heap_init (void) {struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; -unsigned ms_cnt; -struct rte_memseg *ms;if (mcfg ==NULL )return -1 ; -for (ms = &mcfg->memseg[0 ], ms_cnt =0 ; - (ms_cnt <RTE_MAX_MEMSEG ) && (ms->len >0 ); - ms_cnt++, ms++) { -malloc_heap_add_memseg (&mcfg->malloc_heaps[ms->socket_id], ms); - } +rte_memseg_walk (malloc_heap_add_memseg,NULL );return 0 ; }
lib/librte_eal/linuxapp/eal/eal.c +11 -11
@@ -638,23 +638,23 @@ eal_parse_args(int argc, char **argv)return ret; } +static int +check_mem (const struct rte_memseg *ms,void *arg) +{ +int *socket = arg; + +return ms->socket_id == *socket; +} +static void eal_check_mem_on_local_socket (void ) { -const struct rte_memseg *ms; -int i, socket_id; +int socket_id; socket_id =rte_lcore_to_socket_id (rte_config.master_lcore); - ms =rte_eal_get_physmem_layout (); - -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) -if (ms[i].socket_id == socket_id && - ms[i].len >0 ) -return ; - -RTE_LOG (WARNING ,EAL ,"WARNING: Master core has no " -"memory on local socket!\n" ); +if (rte_memseg_walk (check_mem, &socket_id) ==0 ) +RTE_LOG (WARNING ,EAL ,"WARNING: Master core has no memory on local socket!\n" ); } static int
Signature · 1 line
2.7.4
PATCH v3 30/68 mempool: use memseg walk instead of iteration
In reply to Anatoly Burakov--- lib/librte_mempool/rte_mempool.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
lib/librte_mempool/rte_mempool.c +12 -12
@@ -99,23 +99,23 @@ static unsigned optimize_object_size(unsigned obj_size)return new_obj_size *RTE_MEMPOOL_ALIGN ; } +static int +find_min_pagesz (const struct rte_memseg *ms,void *arg) +{ +size_t *min = arg; + +if (ms->hugepage_sz < *min) + *min = ms->hugepage_sz; + +return 0 ; +} +static size_t get_min_page_size (void ) { -const struct rte_mem_config *mcfg = -rte_eal_get_configuration ()->mem_config; -int i;size_t min_pagesz =SIZE_MAX ; -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { -const struct rte_memseg *ms = &mcfg->memseg[i]; - -if (ms->addr ==NULL ) -continue ; - -if (ms->hugepage_sz < min_pagesz) - min_pagesz = ms->hugepage_sz; - } +rte_memseg_walk (find_min_pagesz, &min_pagesz);return min_pagesz ==SIZE_MAX ? (size_t )getpagesize () : min_pagesz; }
Signature · 1 line
2.7.4
PATCH v3 31/68 test: use memseg walk instead of iteration
In reply to Anatoly Burakov--- test/test/test_malloc.c | 40 +++++++++++++++++++++++------------- test/test/test_memory.c | 23 +++++++++++---------- test/test/test_memzone.c | 53 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 74 insertions(+), 42 deletions(-)
test/test/test_malloc.c +26 -14
@@ -705,16 +705,34 @@ test_malloc_bad_params(void)return -1 ; } +static int +check_socket_mem (const struct rte_memseg *ms,void *arg) +{ +int32_t *socket = arg; + +return *socket == ms->socket_id; +} +/* Check if memory is available on a specific socket */ static int is_mem_on_socket (int32_t socket) { -const struct rte_memseg *ms =rte_eal_get_physmem_layout (); -unsigned i; +return rte_memseg_walk (check_socket_mem, &socket); +} -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { -if (socket == ms[i].socket_id) -return 1 ; +struct walk_param { +void *addr; +int32_t socket; +}; +static int +find_socket (const struct rte_memseg *ms,void *arg) +{ +struct walk_param *param = arg; + +if (param->addr >= ms->addr && + param->addr <RTE_PTR_ADD (ms->addr, ms->len)) { + param->socket = ms->socket_id; +return 1 ; }return 0 ; }
@@ -726,15 +744,9 @@ is_mem_on_socket(int32_t socket)static int32_t addr_to_socket (void * addr) { -const struct rte_memseg *ms =rte_eal_get_physmem_layout (); -unsigned i; - -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { -if ((ms[i].addr <= addr) && - ((uintptr_t )addr < - ((uintptr_t )ms[i].addr + (uintptr_t )ms[i].len))) -return ms[i].socket_id; - } +struct walk_param param = {.addr = addr, .socket =0 }; +if (rte_memseg_walk (find_socket, ¶m) >0 ) +return param.socket;return -1 ; }
test/test/test_memory.c +12 -11
@@ -23,12 +23,20 @@*/ static int +check_mem(const struct rte_memseg *ms, void *arg __rte_unused) +{ +volatile uint8_t *mem = (volatile uint8_t *) ms->addr; +size_t i; + +for (i =0 ; i < ms->len; i++, mem++) + *mem; +return 0 ; +} + +static int test_memory (void ) {uint64_t s; -unsigned i; -size_t j; -const struct rte_memseg *mem;/* * dump the mapped memory: the python-expect script checks
@@ -45,14 +53,7 @@ test_memory(void) }/* try to read memory (should not segfault) */ - mem =rte_eal_get_physmem_layout (); -for (i =0 ; i <RTE_MAX_MEMSEG && mem[i].addr !=NULL ; i++) { - -/* check memory */ -for (j =0 ; j<mem[i].len; j++) { - *((volatile uint8_t *) mem[i].addr + j); - } - } +rte_memseg_walk (check_mem,NULL );return 0 ; }
test/test/test_memzone.c +36 -17
64 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v3 32/68 vfio/type1: use memseg walk instead of iteration
In reply to Anatoly Burakov--- lib/librte_eal/linuxapp/eal/eal_vfio.c | 45 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 24 deletions(-)
lib/librte_eal/linuxapp/eal/eal_vfio.c +21 -24
@@ -665,39 +665,36 @@ vfio_get_group_no(const char *sysfs_base, }static int -vfio_type1_dma_map (int vfio_container_fd) +type1_map (const struct rte_memseg *ms,void *arg) { -const struct rte_memseg *ms =rte_eal_get_physmem_layout (); -int i, ret; +int *vfio_container_fd = arg; +struct vfio_iommu_type1_dma_map dma_map; +int ret; -/* map all DPDK segments for DMA. use 1:1 PA to IOVA mapping */ -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { -struct vfio_iommu_type1_dma_map dma_map; +memset (&dma_map,0 ,sizeof (dma_map)); + dma_map.argsz =sizeof (struct vfio_iommu_type1_dma_map ); + dma_map.vaddr = ms->addr_64; + dma_map.size = ms->len; + dma_map.iova = ms->iova; + dma_map.flags =VFIO_DMA_MAP_FLAG_READ |VFIO_DMA_MAP_FLAG_WRITE ; -if (ms[i].addr ==NULL ) -break ; - -memset (&dma_map,0 ,sizeof (dma_map)); - dma_map.argsz =sizeof (struct vfio_iommu_type1_dma_map ); - dma_map.vaddr = ms[i].addr_64; - dma_map.size = ms[i].len; - dma_map.iova = ms[i].iova; - dma_map.flags =VFIO_DMA_MAP_FLAG_READ |VFIO_DMA_MAP_FLAG_WRITE ; + ret =ioctl (*vfio_container_fd,VFIO_IOMMU_MAP_DMA , &dma_map); - ret =ioctl (vfio_container_fd,VFIO_IOMMU_MAP_DMA , &dma_map); - -if (ret) { -RTE_LOG (ERR ,EAL ," cannot set up DMA remapping, " -"error %i (%s)\n" , errno, -strerror (errno)); -return -1 ; - } +if (ret) { +RTE_LOG (ERR ,EAL ," cannot set up DMA remapping, error %i (%s)\n" , + errno,strerror (errno)); +return -1 ; } -return 0 ; }static int +vfio_type1_dma_map (int vfio_container_fd) +{ +return rte_memseg_walk (type1_map, &vfio_container_fd); +} + +static int vfio_spapr_dma_map (int vfio_container_fd) {const struct rte_memseg *ms =rte_eal_get_physmem_layout ();
Signature · 1 line
2.7.4
PATCH v3 33/68 vfio/spapr: use memseg walk instead of iteration
In reply to Anatoly Burakov--- lib/librte_eal/linuxapp/eal/eal_vfio.c | 108 +++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 45 deletions(-)
lib/librte_eal/linuxapp/eal/eal_vfio.c +63 -45
@@ -694,16 +694,69 @@ vfio_type1_dma_map(int vfio_container_fd)return rte_memseg_walk (type1_map, &vfio_container_fd); } +struct spapr_walk_param { +uint64_t window_size; +uint64_t hugepage_sz; +};static int -vfio_spapr_dma_map (int vfio_container_fd) +spapr_window_size (const struct rte_memseg *ms,void *arg) { -const struct rte_memseg *ms =rte_eal_get_physmem_layout (); -int i, ret; +struct spapr_walk_param *param = arg; +uint64_t max = ms->iova + ms->len; + +if (max > param->window_size) { + param->hugepage_sz = ms->hugepage_sz; + param->window_size = max; + } +return 0 ; +} + +static int +spapr_map (const struct rte_memseg *ms,void *arg) +{ +struct vfio_iommu_type1_dma_map dma_map;struct vfio_iommu_spapr_register_memory reg = { .argsz =sizeof (reg), .flags =0 }; +int *vfio_container_fd = arg; +int ret; + + reg.vaddr = (uintptr_t ) ms->addr; + reg.size = ms->len; + ret =ioctl (*vfio_container_fd, +VFIO_IOMMU_SPAPR_REGISTER_MEMORY , ®); +if (ret) { +RTE_LOG (ERR ,EAL ," cannot register vaddr for IOMMU, error %i (%s)\n" , + errno,strerror (errno)); +return -1 ; + } + +memset (&dma_map,0 ,sizeof (dma_map)); + dma_map.argsz =sizeof (struct vfio_iommu_type1_dma_map ); + dma_map.vaddr = ms->addr_64; + dma_map.size = ms->len; + dma_map.iova = ms->iova; + dma_map.flags =VFIO_DMA_MAP_FLAG_READ | +VFIO_DMA_MAP_FLAG_WRITE ; + + ret =ioctl (*vfio_container_fd,VFIO_IOMMU_MAP_DMA , &dma_map); + +if (ret) { +RTE_LOG (ERR ,EAL ," cannot set up DMA remapping, error %i (%s)\n" , + errno,strerror (errno)); +return -1 ; + } + +return 0 ; +} + +static int +vfio_spapr_dma_map (int vfio_container_fd) +{ +struct spapr_walk_param param; +int ret;struct vfio_iommu_spapr_tce_info info = { .argsz =sizeof (info), };
@@ -714,6 +767,8 @@ vfio_spapr_dma_map(int vfio_container_fd) .argsz = sizeof(remove), }; +memset (¶m,0 ,sizeof (param)); +/* query spapr iommu info */ ret =ioctl (vfio_container_fd,VFIO_IOMMU_SPAPR_TCE_GET_INFO , &info);if (ret) {
@@ -732,17 +787,11 @@ vfio_spapr_dma_map(int vfio_container_fd) }/* create DMA window from 0 to max(phys_addr + len) */ -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { -if (ms[i].addr ==NULL ) -break ; - - create.window_size =RTE_MAX (create.window_size, - ms[i].iova + ms[i].len); - } +rte_memseg_walk (spapr_window_size, ¶m);/* sPAPR requires window size to be a power of 2 */ - create.window_size =rte_align64pow2 (create.window_size); - create.page_shift =__builtin_ctzll (ms->hugepage_sz); + create.window_size =rte_align64pow2 (param.window_size); + create.page_shift =__builtin_ctzll (param.hugepage_sz); create.levels =1 ; ret =ioctl (vfio_container_fd,VFIO_IOMMU_SPAPR_TCE_CREATE , &create);
@@ -758,39 +807,8 @@ vfio_spapr_dma_map(int vfio_container_fd) }/* map all DPDK segments for DMA. use 1:1 PA to IOVA mapping */ -for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { -struct vfio_iommu_type1_dma_map dma_map; - -if (ms[i].addr ==NULL ) -break ; - - reg.vaddr = (uintptr_t ) ms[i].addr; - reg.size = ms[i].len; - ret =ioctl (vfio_container_fd, -VFIO_IOMMU_SPAPR_REGISTER_MEMORY , ®); -if (ret) { -RTE_LOG (ERR ,EAL ," cannot register vaddr for IOMMU, " -"error %i (%s)\n" , errno,strerror (errno)); -return -1 ; - } - -memset (&dma_map,0 ,sizeof (dma_map)); - dma_map.argsz =sizeof (struct vfio_iommu_type1_dma_map ); - dma_map.vaddr = ms[i].addr_64; - dma_map.size = ms[i].len; - dma_map.iova = ms[i].iova; - dma_map.flags =VFIO_DMA_MAP_FLAG_READ | -VFIO_DMA_MAP_FLAG_WRITE ; - - ret =ioctl (vfio_container_fd,VFIO_IOMMU_MAP_DMA , &dma_map); - -if (ret) { -RTE_LOG (ERR ,EAL ," cannot set up DMA remapping, " -"error %i (%s)\n" , errno,strerror (errno)); -return -1 ; - } - - } +if (rte_memseg_walk (spapr_map, &vfio_container_fd) <0 ) +return -1 ;return 0 ; }
Signature · 1 line
2.7.4
PATCH v3 34/68 eal: add contig walk function
In reply to Anatoly BurakovFor now, this function is identical to memseg walk function, but it is meant to walk over first segment of each VA contiguous group of memsegs. The difference will become apparent when memseg lists will come into play.
Again, this is done so that there is less dependency on internals of mem API and less noise later change sets.
--- lib/librte_eal/common/eal_common_memory.c | 37 ++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_memory.h | 27 ++++++++++++++++++++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 65 insertions(+)
lib/librte_eal/common/eal_common_memory.c +37 -0
@@ -242,6 +242,43 @@ rte_memseg_walk(rte_memseg_walk_t func, void *arg)return 0 ; } +int __rte_experimental +rte_memseg_contig_walk (rte_memseg_contig_walk_t func,void *arg) +{ +struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; +int i, j, ret; + +for (i =0 ; i <RTE_MAX_MEMSEG ; i++) { +const struct rte_memseg *ms = &mcfg->memseg[i]; +size_t total_len; +void *end_addr; + +if (ms->addr ==NULL ) +continue ; + + end_addr =RTE_PTR_ADD (ms->addr, ms->len); + +/* check how many more segments are contiguous to this one */ +for (j = i +1 ; j <RTE_MAX_MEMSEG ; j++) { +const struct rte_memseg *next = &mcfg->memseg[j]; + +if (next->addr != end_addr) +break ; + + end_addr =RTE_PTR_ADD (next->addr, next->len); + i++; + } + total_len =RTE_PTR_DIFF (end_addr, ms->addr); + + ret =func (ms, total_len, arg); +if (ret <0 ) +return -1 ; +if (ret >0 ) +return 1 ; + } +return 0 ; +} +/* init memory subsystem */ int rte_eal_memory_init (void )
lib/librte_eal/common/include/rte_memory.h +27 -0
@@ -140,6 +140,18 @@ rte_iova_t rte_mem_virt2iova(const void *virt);typedef int (*rte_memseg_walk_t )(const struct rte_memseg *ms,void *arg);/** +* Memseg contig walk function prototype. This will trigger a callback on every +* VA-contiguous are starting at memseg ``ms``, so total valid VA space at each +* callback call will be [``ms->addr``, ``ms->addr + len``). +* +* Returning 0 will continue walk +* Returning 1 will stop the walk +* Returning -1 will stop the walk and report error +*/ +typedef int (*rte_memseg_contig_walk_t )(const struct rte_memseg *ms, +size_t len,void *arg); + +/** * Walk list of all memsegs. * * @param func
@@ -155,6 +167,21 @@ int __rte_experimental rte_memseg_walk(rte_memseg_walk_t func, void *arg);/** +* Walk each VA-contiguous area. +* +* @param func +* Iterator function +* @param arg +* Argument passed to iterator +* @return +* 0 if walked over the entire list +* 1 if stopped by the user +* -1 if user function reported error +*/ +int __rte_experimental +rte_memseg_contig_walk (rte_memseg_contig_walk_t func,void *arg); + +/** * Get the layout of the available physical memory. * * It can be useful for an application to have the full physical
lib/librte_eal/rte_eal_version.map +1 -0
@@ -223,6 +223,7 @@ EXPERIMENTAL { rte_eal_mbuf_user_pool_ops; rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; + rte_memseg_contig_walk; rte_memseg_walk; rte_memzone_reserve_contig; rte_memzone_reserve_aligned_contig;
Signature · 1 line
2.7.4
PATCH v3 35/68 virtio: use memseg contig walk instead of iteration
In reply to Anatoly Burakov--- drivers/net/virtio/virtio_user/vhost_kernel.c | 83 +++++++++++---------------- 1 file changed, 35 insertions(+), 48 deletions(-)
drivers/net/virtio/virtio_user/vhost_kernel.c +35 -48
@@ -70,6 +70,32 @@ static uint64_t vhost_req_user_to_kernel[] = { [VHOST_USER_SET_MEM_TABLE] = VHOST_SET_MEM_TABLE, }; +struct walk_arg { +struct vhost_memory_kernel *vm; +uint32_t region_nr; +}; +static int +add_memory_region (const struct rte_memseg *ms,size_t len,void *arg) +{ +struct walk_arg *wa = arg; +struct vhost_memory_region *mr; +void *start_addr; + +if (wa->region_nr >= max_regions) +return -1 ; + + mr = &wa->vm->regions[wa->region_nr++]; + start_addr = ms->addr; + + mr->guest_phys_addr = (uint64_t )(uintptr_t )start_addr; + mr->userspace_addr = (uint64_t )(uintptr_t )start_addr; + mr->memory_size = len; + mr->mmap_offset =0 ; + +return 0 ; +} + +/* By default, vhost kernel module allows 64 regions, but DPDK allows * 256 segments. As a relief, below function merges those virtually * adjacent memsegs into one region.
@@ -77,63 +103,24 @@ static uint64_t vhost_req_user_to_kernel[] = {static struct vhost_memory_kernel *prepare_vhost_memory_kernel (void ) { -uint32_t i, j, k =0 ; -struct rte_memseg *seg; -struct vhost_memory_region *mr;struct vhost_memory_kernel *vm; +struct walk_arg wa; vm =malloc (sizeof (struct vhost_memory_kernel ) + - max_regions * -sizeof (struct vhost_memory_region )); + max_regions * +sizeof (struct vhost_memory_region ));if (!vm)return NULL ; -for (i =0 ; i <RTE_MAX_MEMSEG ; ++i) { - seg = &rte_eal_get_configuration ()->mem_config->memseg[i]; -if (!seg->addr) -break ; - -int new_region =1 ; - -for (j =0 ; j < k; ++j) { - mr = &vm->regions[j]; + wa.region_nr =0 ; + wa.vm = vm; -if (mr->userspace_addr + mr->memory_size == - (uint64_t )(uintptr_t )seg->addr) { - mr->memory_size += seg->len; - new_region =0 ; -break ; - } - -if ((uint64_t )(uintptr_t )seg->addr + seg->len == - mr->userspace_addr) { - mr->guest_phys_addr = - (uint64_t )(uintptr_t )seg->addr; - mr->userspace_addr = - (uint64_t )(uintptr_t )seg->addr; - mr->memory_size += seg->len; - new_region =0 ; -break ; - } - } - -if (new_region ==0 ) -continue ; - - mr = &vm->regions[k++]; -/* use vaddr here! */ - mr->guest_phys_addr = (uint64_t )(uintptr_t )seg->addr; - mr->userspace_addr = (uint64_t )(uintptr_t )seg->addr; - mr->memory_size = seg->len; - mr->mmap_offset =0 ; - -if (k >= max_regions) { -free (vm); -return NULL ; - } +if (rte_memseg_contig_walk (add_memory_region, &wa) <0 ) { +free (vm); +return NULL ; } - vm->nregions = k; + vm->nregions = wa.region_nr; vm->padding =0 ;return vm; }
Signature · 1 line
2.7.4
PATCH v3 36/68 eal: add iova2virt function
In reply to Anatoly BurakovThis is reverse lookup of PA to VA. Using this will make other code less dependent on internals of mem API.
--- lib/librte_eal/common/eal_common_memory.c | 30 ++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_memory.h | 12 ++++++++++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 43 insertions(+)
lib/librte_eal/common/eal_common_memory.c +30 -0
@@ -131,6 +131,36 @@ rte_eal_get_physmem_layout(void)return rte_eal_get_configuration ()->mem_config->memseg; } +struct virtiova { +rte_iova_t iova; +void *virt; +}; +static int +find_virt (const struct rte_memseg *ms,void *arg) +{ +struct virtiova *vi = arg; +if (vi->iova >= ms->iova && vi->iova < (ms->iova + ms->len)) { +size_t offset = vi->iova - ms->iova; + vi->virt =RTE_PTR_ADD (ms->addr, offset); +/* stop the walk */ +return 1 ; + } +return 0 ; +} + +__rte_experimental void * +rte_mem_iova2virt (rte_iova_t iova) +{ +struct virtiova vi; + +memset (&vi,0 ,sizeof (vi)); + + vi.iova = iova; +rte_memseg_walk (find_virt, &vi); + +return vi.virt; +} +static int physmem_size (const struct rte_memseg *ms,void *arg) {
lib/librte_eal/common/include/rte_memory.h +12 -0
@@ -131,6 +131,18 @@ phys_addr_t rte_mem_virt2phy(const void *virt);rte_iova_t rte_mem_virt2iova (const void *virt);/** +* Get virtual memory address corresponding to iova address. +* +* @param iova +* The iova address. +* @return +* Virtual address corresponding to iova address (or NULL if address does not +* exist within DPDK memory map). +*/ +__rte_experimental void * +rte_mem_iova2virt (rte_iova_t iova); + +/** * Memseg walk function prototype. * * Returning 0 will continue walk
lib/librte_eal/rte_eal_version.map +1 -0
@@ -223,6 +223,7 @@ EXPERIMENTAL { rte_eal_mbuf_user_pool_ops; rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; + rte_mem_iova2virt; rte_memseg_contig_walk; rte_memseg_walk; rte_memzone_reserve_contig;
Signature · 1 line
2.7.4
PATCH v3 37/68 bus/dpaa: use iova2virt instead of memseg iteration
In reply to Anatoly Burakov--- drivers/bus/dpaa/rte_dpaa_bus.h | 12 +----------- drivers/event/dpaa/Makefile | 3 +++ drivers/mempool/dpaa/Makefile | 3 +++ drivers/net/dpaa/Makefile | 3 +++ 4 files changed, 10 insertions(+), 11 deletions(-)
drivers/bus/dpaa/rte_dpaa_bus.h +1 -11
@@ -98,17 +98,7 @@ struct dpaa_portal {/* TODO - this is costly, need to write a fast coversion routine */ static inline void *rte_dpaa_mem_ptov (phys_addr_t paddr) { -const struct rte_memseg *memseg =rte_eal_get_physmem_layout (); -int i; - -for (i =0 ; i <RTE_MAX_MEMSEG && memseg[i].addr !=NULL ; i++) { -if (paddr >= memseg[i].iova && paddr < - memseg[i].iova + memseg[i].len) -return (uint8_t *)(memseg[i].addr) + - (paddr - memseg[i].iova); - } - -return NULL ; +return rte_mem_iova2virt (paddr); }/**
drivers/event/dpaa/Makefile +3 -0
@@ -26,6 +26,9 @@ EXPORT_MAP := rte_pmd_dpaa_event_version.map LIBABIVER := 1 +# depends on dpaa bus which uses experimental API +CFLAGS += -DALLOW_EXPERIMENTAL_API + # Interfaces with DPDK SRCS-$(CONFIG_RTE_LIBRTE_PMD_DPAA_EVENTDEV) += dpaa_eventdev.c
drivers/mempool/dpaa/Makefile +3 -0
@@ -22,6 +22,9 @@ EXPORT_MAP := rte_mempool_dpaa_version.map # Lbrary version LIBABIVER := 1 +# depends on dpaa bus which uses experimental API +CFLAGS += -DALLOW_EXPERIMENTAL_API + # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_DPAA_MEMPOOL) += dpaa_mempool.c
drivers/net/dpaa/Makefile +3 -0
@@ -27,6 +27,9 @@ EXPORT_MAP := rte_pmd_dpaa_version.map LIBABIVER := 1 +# depends on dpaa bus which uses experimental API +CFLAGS += -DALLOW_EXPERIMENTAL_API + # Interfaces with DPDK SRCS-$(CONFIG_RTE_LIBRTE_DPAA_PMD) += dpaa_ethdev.c SRCS-$(CONFIG_RTE_LIBRTE_DPAA_PMD) += dpaa_rxtx.c
Signature · 1 line
2.7.4
PATCH v3 38/68 bus/fslmc: use iova2virt instead of memseg iteration
In reply to Anatoly Burakov--- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-)
drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +1 -12
@@ -260,21 +260,10 @@ static void *dpaa2_mem_ptov(phys_addr_t paddr) __attribute__((unused));/* todo - this is costly, need to write a fast coversion routine */ static void *dpaa2_mem_ptov (phys_addr_t paddr) { -const struct rte_memseg *memseg; -int i; -if (dpaa2_virt_mode)return (void *)(size_t )paddr; - memseg =rte_eal_get_physmem_layout (); - -for (i =0 ; i <RTE_MAX_MEMSEG && memseg[i].addr_64 !=0 ; i++) { -if (paddr >= memseg[i].iova && - paddr < memseg[i].iova + memseg[i].len) -return (void *)(size_t )(memseg[i].addr_64 - + (paddr - memseg[i].iova)); - } -return NULL ; +return rte_mem_iova2virt (paddr); }static phys_addr_t dpaa2_mem_vtop (uint64_t vaddr) __attribute__((unused));
Signature · 1 line
2.7.4
PATCH v3 39/68 crypto/dpaa_sec: use iova2virt instead of memseg iteration
In reply to Anatoly Burakov--- drivers/crypto/dpaa_sec/dpaa_sec.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
drivers/crypto/dpaa_sec/dpaa_sec.c +1 -10
@@ -120,16 +120,7 @@ dpaa_mem_vtop_ctx(struct dpaa_sec_op_ctx *ctx, void *vaddr)static inline void *dpaa_mem_ptov (rte_iova_t paddr) { -const struct rte_memseg *memseg =rte_eal_get_physmem_layout (); -int i; - -for (i =0 ; i <RTE_MAX_MEMSEG && memseg[i].addr_64 !=0 ; i++) { -if (paddr >= memseg[i].iova && - paddr < memseg[i].iova + memseg[i].len) -return (void *)(size_t )(memseg[i].addr_64 + - (paddr - memseg[i].iova)); - } -return NULL ; +return rte_mem_iova2virt (paddr); } static void
Signature · 1 line
2.7.4
PATCH v3 40/68 eal: add virt2memseg function
In reply to Anatoly BurakovThis can be used as a virt2iova function that only looks up memory that is owned by DPDK (as opposed to doing pagemap walks). Using this will result in less dependency on internals of mem API.
--- lib/librte_eal/common/eal_common_memory.c | 37 ++++++++++++++++++++++++++++++ lib/librte_eal/common/include/rte_memory.h | 11 +++++++++ lib/librte_eal/rte_eal_version.map | 1 + 3 files changed, 49 insertions(+)
lib/librte_eal/common/eal_common_memory.c +37 -0
@@ -161,6 +161,43 @@ rte_mem_iova2virt(rte_iova_t iova)return vi.virt; } +struct virtms { +const void *virt; +struct rte_memseg *ms; +}; +static int +find_memseg (const struct rte_memseg *ms,void *arg) +{ +struct virtms *vm = arg; + +if (arg >= ms->addr && arg <RTE_PTR_ADD (ms->addr, ms->len)) { +struct rte_memseg *memseg, *found_ms; +int idx; + + memseg =rte_eal_get_configuration ()->mem_config->memseg; + idx = ms - memseg; + found_ms = &memseg[idx]; + + vm->ms = found_ms; +return 1 ; + } +return 0 ; +} + +__rte_experimental struct rte_memseg * +rte_mem_virt2memseg (const void *addr) +{ +struct virtms vm; + +memset (&vm,0 ,sizeof (vm)); + + vm.virt = addr; + +rte_memseg_walk (find_memseg, &vm); + +return vm.ms; +} +static int physmem_size (const struct rte_memseg *ms,void *arg) {
lib/librte_eal/common/include/rte_memory.h +11 -0
@@ -143,6 +143,17 @@ __rte_experimental void * rte_mem_iova2virt(rte_iova_t iova);/** +* Get memseg to which a particular virtual address belongs. +* +* @param virt +* The virtual address. +* @return +* Memseg pointer on success, or NULL on error. +*/ +__rte_experimental struct rte_memseg * +rte_mem_virt2memseg (const void *virt); + +/** * Memseg walk function prototype. * * Returning 0 will continue walk
lib/librte_eal/rte_eal_version.map +1 -0
@@ -224,6 +224,7 @@ EXPERIMENTAL { rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; rte_mem_iova2virt; + rte_mem_virt2memseg; rte_memseg_contig_walk; rte_memseg_walk; rte_memzone_reserve_contig;
Signature · 1 line
2.7.4
PATCH v3 41/68 bus/fslmc: use virt2memseg instead of iteration
In reply to Anatoly Burakov--- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-)
drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +4 -10
@@ -270,20 +270,14 @@ static phys_addr_t dpaa2_mem_vtop(uint64_t vaddr) __attribute__((unused));static phys_addr_t dpaa2_mem_vtop (uint64_t vaddr) {const struct rte_memseg *memseg; -int i;if (dpaa2_virt_mode)return vaddr; - memseg =rte_eal_get_physmem_layout (); - -for (i =0 ; i <RTE_MAX_MEMSEG && memseg[i].addr_64 !=0 ; i++) { -if (vaddr >= memseg[i].addr_64 && - vaddr < memseg[i].addr_64 + memseg[i].len) -return memseg[i].iova - + (vaddr - memseg[i].addr_64); - } -return (size_t )(NULL ); + memseg =rte_mem_virt2memseg ((void *)(uintptr_t )vaddr); +if (memseg) +return memseg->phys_addr +RTE_PTR_DIFF (vaddr, memseg->addr); +return (size_t )NULL ; }/**
Signature · 1 line
2.7.4
PATCH v3 42/68 net/mlx4: use virt2memseg instead of iteration
In reply to Anatoly Burakov--- drivers/net/mlx4/mlx4_mr.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
drivers/net/mlx4/mlx4_mr.c +7 -10
@@ -126,7 +126,7 @@ mlx4_check_mempool(struct rte_mempool *mp, uintptr_t *start, uintptr_t *end)struct mlx4_mr *mlx4_mr_get (struct priv *priv,struct rte_mempool *mp) { -const struct rte_memseg *ms =rte_eal_get_physmem_layout (); +const struct rte_memseg *ms;uintptr_t start;uintptr_t end;unsigned int i;
@@ -142,16 +142,13 @@ mlx4_mr_get(struct priv *priv, struct rte_mempool *mp) (void *)mp, (void *)start, (void *)end, (size_t)(end - start));/* Round start and end to page boundary if found in memory segments. */ -for (i =0 ; (i <RTE_MAX_MEMSEG ) && (ms[i].addr !=NULL ); ++i) { -uintptr_t addr = (uintptr_t )ms[i].addr; -size_t len = ms[i].len; -unsigned int align = ms[i].hugepage_sz; + ms =rte_mem_virt2memseg ((void *)start); +if (ms !=NULL ) + start =RTE_ALIGN_FLOOR (start, ms->hugepage_sz); + ms =rte_mem_virt2memseg ((void *)end); +if (ms !=NULL ) + end =RTE_ALIGN_CEIL (end, ms->hugepage_sz); -if ((start > addr) && (start < addr + len)) - start =RTE_ALIGN_FLOOR (start, align); -if ((end > addr) && (end < addr + len)) - end =RTE_ALIGN_CEIL (end, align); - }DEBUG ("mempool %p using start=%p end=%p size=%zu for MR" , (void *)mp, (void *)start, (void *)end, (size_t )(end - start));
Signature · 1 line
2.7.4
PATCH v3 43/68 net/mlx5: use virt2memseg instead of iteration
In reply to Anatoly Burakov--- drivers/net/mlx5/mlx5_mr.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
drivers/net/mlx5/mlx5_mr.c +8 -10
@@ -234,7 +234,7 @@ struct mlx5_mr * mlx5_mr_new(struct rte_eth_dev *dev, struct rte_mempool *mp) { struct priv *priv = dev->data->dev_private; -const struct rte_memseg *ms =rte_eal_get_physmem_layout (); +const struct rte_memseg *ms;uintptr_t start;uintptr_t end;unsigned int i;
@@ -261,17 +261,15 @@ mlx5_mr_new(struct rte_eth_dev *dev, struct rte_mempool *mp)/* Save original addresses for exact MR lookup. */ mr->start = start; mr->end = end; +/* Round start and end to page boundary if found in memory segments. */ -for (i =0 ; (i <RTE_MAX_MEMSEG ) && (ms[i].addr !=NULL ); ++i) { -uintptr_t addr = (uintptr_t )ms[i].addr; -size_t len = ms[i].len; -unsigned int align = ms[i].hugepage_sz; + ms =rte_mem_virt2memseg ((void *)start); +if (ms !=NULL ) + start =RTE_ALIGN_FLOOR (start, ms->hugepage_sz); + ms =rte_mem_virt2memseg ((void *)end); +if (ms !=NULL ) + end =RTE_ALIGN_CEIL (end, ms->hugepage_sz); -if ((start > addr) && (start < addr + len)) - start =RTE_ALIGN_FLOOR (start, align); -if ((end > addr) && (end < addr + len)) - end =RTE_ALIGN_CEIL (end, align); - } DRV_LOG(DEBUG, "port %u mempool %p using start=%p end=%p size=%zu for memory" " region",
Signature · 1 line
2.7.4
PATCH v3 44/68 crypto/dpaa_sec: use virt2memseg instead of iteration
In reply to Anatoly Burakov--- drivers/crypto/dpaa_sec/dpaa_sec.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-)
drivers/crypto/dpaa_sec/dpaa_sec.c +5 -14
@@ -93,20 +93,11 @@ dpaa_sec_alloc_ctx(dpaa_sec_session *ses)static inline rte_iova_t dpaa_mem_vtop (void *vaddr) { -const struct rte_memseg *memseg =rte_eal_get_physmem_layout (); -uint64_t vaddr_64, paddr; -int i; - - vaddr_64 = (size_t )vaddr; -for (i =0 ; i <RTE_MAX_MEMSEG && memseg[i].addr_64 !=0 ; i++) { -if (vaddr_64 >= memseg[i].addr_64 && - vaddr_64 < memseg[i].addr_64 + memseg[i].len) { - paddr = memseg[i].iova + - (vaddr_64 - memseg[i].addr_64); - -return (rte_iova_t )paddr; - } - } +const struct rte_memseg *ms; + + ms =rte_mem_virt2memseg (vaddr); +if (ms) +return ms->iova +RTE_PTR_DIFF (vaddr, ms->addr);return (size_t )NULL ; }
Signature · 1 line
2.7.4
PATCH v3 45/68 eal: use memzone walk instead of iteration
In reply to Anatoly Burakov--- lib/librte_eal/common/eal_common_memzone.c | 42 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-)
lib/librte_eal/common/eal_common_memzone.c +21 -21
@@ -395,31 +395,31 @@ rte_memzone_lookup(const char *name)return memzone; } +static void +dump_memzone (const struct rte_memzone *mz,void *arg) +{ +struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; +FILE *f = arg; +int mz_idx; + + mz_idx = mz - mcfg->memzone; + +fprintf (f,"Zone %u: name:<%s>, IO:0x%" PRIx64", len:0x%zx, virt:%p, " +"socket_id:%" PRId32", flags:%" PRIx32"\n" , + mz_idx, + mz->name, + mz->iova, + mz->len, + mz->addr, + mz->socket_id, + mz->flags); +} +/* Dump all reserved memory zones on console */ void rte_memzone_dump (FILE *f) { -struct rte_mem_config *mcfg; -unsigned i =0 ; - -/* get pointer to global configuration */ - mcfg =rte_eal_get_configuration ()->mem_config; - -rte_rwlock_read_lock (&mcfg->mlock); -/* dump all zones */ -for (i=0 ; i<RTE_MAX_MEMZONE ; i++) { -if (mcfg->memzone[i].addr ==NULL ) -break ; -fprintf (f,"Zone %u: name:<%s>, IO:0x%" PRIx64", len:0x%zx" -", virt:%p, socket_id:%" PRId32", flags:%" PRIx32"\n" , i, - mcfg->memzone[i].name, - mcfg->memzone[i].iova, - mcfg->memzone[i].len, - mcfg->memzone[i].addr, - mcfg->memzone[i].socket_id, - mcfg->memzone[i].flags); - } -rte_rwlock_read_unlock (&mcfg->mlock); +rte_memzone_walk (dump_memzone, f); }/*
Signature · 1 line
2.7.4
PATCH v3 46/68 vfio: allow to map other memory regions
In reply to Anatoly BurakovCurrently it is not possible to use memory that is not owned by DPDK to perform DMA. This scenarion might be used in vhost applications (like SPDK) where guest send its own memory table. To fill this gap provide API to allow registering arbitrary address in VFIO container.
---
Notes:
v3:
- Added PPC64, courtesy of Gowrishankar
v3:
- Moved to earlier in the patchset
- Made API experimental
- Do not print out error message if init isn't finished
- SPAPR code provided by Gowrishankar
lib/librte_eal/bsdapp/eal/eal.c | 16 ++ lib/librte_eal/common/include/rte_vfio.h | 39 ++++ lib/librte_eal/linuxapp/eal/eal_vfio.c | 347 ++++++++++++++++++++++++------- lib/librte_eal/linuxapp/eal/eal_vfio.h | 12 ++ lib/librte_eal/rte_eal_version.map | 2 + 5 files changed, 341 insertions(+), 75 deletions(-)
lib/librte_eal/bsdapp/eal/eal.c +16 -0
@@ -749,6 +749,8 @@ int rte_vfio_enable(const char *modname);int rte_vfio_is_enabled (const char *modname);int rte_vfio_noiommu_is_enabled (void );int rte_vfio_clear_group (int vfio_group_fd); +int rte_vfio_dma_map (uint64_t vaddr,uint64_t iova,uint64_t len); +int rte_vfio_dma_unmap (uint64_t vaddr,uint64_t iova,uint64_t len); int rte_vfio_setup_device(__rte_unused const char *sysfs_base, __rte_unused const char *dev_addr,
@@ -784,3 +786,17 @@ int rte_vfio_clear_group(__rte_unused int vfio_group_fd) {return 0 ; } + +int __rte_experimental +rte_vfio_dma_map(uint64_t __rte_unused vaddr, __rte_unused uint64_t iova, + __rte_unused uint64_t len) +{ +return -1 ; +} + +int __rte_experimental +rte_vfio_dma_unmap(uint64_t __rte_unused vaddr, uint64_t __rte_unused iova, + __rte_unused uint64_t len) +{ +return -1 ; +}
lib/librte_eal/common/include/rte_vfio.h +39 -0
@@ -127,6 +127,45 @@ int rte_vfio_noiommu_is_enabled(void);int rte_vfio_clear_group (int vfio_group_fd); +/** +* Map memory region for use with VFIO. +* +* @param vaddr +* Starting virtual address of memory to be mapped. +* +* @param iova +* Starting IOVA address of memory to be mapped. +* +* @param len +* Length of memory segment being mapped. +* +* @return +* 0 if success. +* -1 on error. +*/ +int __rte_experimental +rte_vfio_dma_map (uint64_t vaddr,uint64_t iova,uint64_t len); + + +/** +* Unmap memory region from VFIO. +* +* @param vaddr +* Starting virtual address of memory to be unmapped. +* +* @param iova +* Starting IOVA address of memory to be unmapped. +* +* @param len +* Length of memory segment being unmapped. +* +* @return +* 0 if success. +* -1 on error. +*/ +int __rte_experimental +rte_vfio_dma_unmap (uint64_t vaddr,uint64_t iova,uint64_t len); + #ifdef __cplusplus }#endif
lib/librte_eal/linuxapp/eal/eal_vfio.c +272 -75
449 lines not on this page · raw message
lib/librte_eal/linuxapp/eal/eal_vfio.h +12 -0
@@ -19,6 +19,7 @@#ifdef VFIO_PRESENT +#include <stdint.h> #include <linux/vfio.h> #define RTE_VFIO_TYPE1 VFIO_TYPE1_IOMMU
@@ -26,6 +27,7 @@#ifndef VFIO_SPAPR_TCE_v2_IOMMU#define RTE_VFIO_SPAPR 7#define VFIO_IOMMU_SPAPR_REGISTER_MEMORY _IO(VFIO_TYPE, VFIO_BASE + 17) +#define VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY _IO(VFIO_TYPE, VFIO_BASE + 18)#define VFIO_IOMMU_SPAPR_TCE_CREATE _IO(VFIO_TYPE, VFIO_BASE + 19)#define VFIO_IOMMU_SPAPR_TCE_REMOVE _IO(VFIO_TYPE, VFIO_BASE + 20)
@@ -110,6 +112,7 @@ struct vfio_config {int vfio_enabled;int vfio_container_fd;int vfio_active_groups; +const struct vfio_iommu_type *vfio_iommu_type;struct vfio_group vfio_groups[VFIO_MAX_GROUPS ]; };
@@ -119,9 +122,18 @@ struct vfio_config {* */ typedef int (*vfio_dma_func_t )(int ); +/* Custom memory region DMA mapping function prototype. +* Takes VFIO container fd, virtual address, phisical address, length and +* operation type (0 to unmap 1 for map) as a parameters. +* Returns 0 on success, -1 on error. +**/ +typedef int (*vfio_dma_user_func_t )(int fd,uint64_t vaddr,uint64_t iova, +uint64_t len,int do_map); +struct vfio_iommu_type {int type_id;const char *name; +vfio_dma_user_func_t dma_user_map_func;vfio_dma_func_t dma_map_func; };
lib/librte_eal/rte_eal_version.map +2 -0
@@ -266,5 +266,7 @@ EXPERIMENTAL { rte_service_start_with_defaults; rte_socket_count; rte_socket_id_by_idx; + rte_vfio_dma_map; + rte_vfio_dma_unmap; } DPDK_18.02;
Signature · 1 line
2.7.4
Re: [PATCH v3 46/68] vfio: allow to map other memory regions
Quoted 10 lines · Anatoly Burakov
Currently it is not possible to use memory that is not owned by DPDK to perform DMA. This scenarion might be used in vhost applications (like SPDK) where guest send its own memory table. To fill this gap provide API to allow registering arbitrary address in VFIO container.
Signed-off-by Pawel Wodkowski <[email protected]>Signed-off-by Anatoly Burakov <[email protected]>Signed-off-by Gowrishankar Muthukrishnan <[email protected]>---
There's a larger issue raised by this patch. We do support hotplug for VFIO devices, and VFIO will drop all maps whenever last device used by VFIO is unplugged. Since primary use case for this API is mapping non-DPDK-owned memory for DMA, this presents a problem, because we're not tracking the mapped areas anywhere, which means that on last device hot-unplug followed by first device hotplug event, whatever DMA maps user has set up, will be gone - only DPDK-owned memory will be remapped.
One way we could solve it is to store user maps in a local tailq and remap those on hotplug. Another way would be to not solve it and just document this limitation - that using this API in conjunction with hotplug will result in undefined behavior. I would tend to favor the first way.
Signature · 2 lines
Thanks, Anatoly
Re: [PATCH v3 46/68] vfio: allow to map other memory regions
In reply to Anatoly BurakovQuoted 9 lines · Anatoly Burakov
Currently it is not possible to use memory that is not owned by DPDK to perform DMA. This scenarion might be used in vhost applications (like SPDK) where guest send its own memory table. To fill this gap provide API to allow registering arbitrary address in VFIO container.
Signed-off-by Pawel Wodkowski <[email protected]>Signed-off-by Anatoly Burakov <[email protected]>Signed-off-by Gowrishankar Muthukrishnan <[email protected]>---
@Gowrishankar,
We've discussed this privately already, but just to make sure it is publicly stated: as it is, parts of this patchset for PPC64 have potential issues with them.
Unmapping and remapping the entire segment list on alloc introduces a race condition - what if a DMA request comes in while we're in the middle of remapping? We cannot realistically stop NICs from doing DMA while some other thread is allocating memory.
There is also a larger issue that i've raised in a previous response to this patch [1], and PPC64 will will have this problem worse, because not only the described issue will happen on hot-unplug/hotplug, but it may also happen during regular allocations, because PPC64 IOMMU will drop all mappings on window resize.
[1] http://dpdk.org/ml/archives/dev/2018-April/095182.html
Signature · 2 lines
Thanks, Anatoly
PATCH v3 47/68 eal: add "legacy memory" option
In reply to Anatoly BurakovThis adds a "--legacy-mem" command-line switch. It will be used to go back to the old memory behavior, one where we can't dynamically allocate/free memory (the downside), but one where the user can get physically contiguous memory, like before (the upside).
For now, nothing but the legacy behavior exists, non-legacy memory init sequence will be added later. For FreeBSD, non-legacy memory init will never be enabled, while for Linux, it is disabled in this patch to avoid breaking bisect, but will be enabled once non-legacy mode will be fully operational.
---
Notes:
v3:
- Move to earlier in the patchset
- Make Linuxapp always load in legacy mode
lib/librte_eal/bsdapp/eal/eal.c | 3 +++ lib/librte_eal/common/eal_common_options.c | 4 ++++ lib/librte_eal/common/eal_internal_cfg.h | 4 ++++ lib/librte_eal/common/eal_options.h | 2 ++ lib/librte_eal/linuxapp/eal/eal.c | 3 +++ lib/librte_eal/linuxapp/eal/eal_memory.c | 24 ++++++++++++++++++++---- 6 files changed, 36 insertions(+), 4 deletions(-)
lib/librte_eal/bsdapp/eal/eal.c +3 -0
@@ -534,6 +534,9 @@ rte_eal_init(int argc, char **argv)return -1 ; } +/* FreeBSD always uses legacy memory model */ + internal_config.legacy_mem = true; +if (eal_plugins_init () <0 ) {rte_eal_init_alert ("Cannot init plugins\n" ); rte_errno =EINVAL ;
lib/librte_eal/common/eal_common_options.c +4 -0
@@ -73,6 +73,7 @@ eal_long_options[] = { {OPT_VDEV, 1, NULL, OPT_VDEV_NUM }, {OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM }, {OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM }, + {OPT_LEGACY_MEM, 0, NULL, OPT_LEGACY_MEM_NUM }, {0, 0, NULL, 0 } };
@@ -1184,6 +1185,9 @@ eal_parse_common_option(int opt, const char *optarg, core_parsed =LCORE_OPT_MAP ;break ; +case OPT_LEGACY_MEM_NUM : + conf->legacy_mem =1 ; +break ;/* don't know what to do, leave this to caller */ default :
lib/librte_eal/common/eal_internal_cfg.h +4 -0
@@ -47,6 +47,10 @@ struct internal_config {volatile unsigned force_sockets;volatile uint64_t socket_mem[RTE_MAX_NUMA_NODES ];/**< amount of memory per socket */ uintptr_t base_virtaddr;/**< base address to try and reserve memory from */ +volatile unsigned legacy_mem; +/**< true to enable legacy memory behavior (no dynamic allocation, +* IOVA-contiguous segments). +*/ volatile int syslog_facility;/**< facility passed to openlog() */ /** default interrupt mode for VFIO */ volatile enum rte_intr_mode vfio_intr_mode;
lib/librte_eal/common/eal_options.h +2 -0
@@ -55,6 +55,8 @@ enum {OPT_VFIO_INTR_NUM , #define OPT_VMWARE_TSC_MAP "vmware-tsc-map"OPT_VMWARE_TSC_MAP_NUM , +#define OPT_LEGACY_MEM "legacy-mem" +OPT_LEGACY_MEM_NUM , OPT_LONG_MAX_NUM };
lib/librte_eal/linuxapp/eal/eal.c +3 -0
@@ -348,6 +348,7 @@ eal_usage(const char *prgname)" --" OPT_BASE_VIRTADDR " Base virtual address\n" " --" OPT_CREATE_UIO_DEV " Create /dev/uioX (usually done by hotplug)\n" " --" OPT_VFIO_INTR " Interrupt mode for VFIO (legacy|msi|msix)\n" +" --" OPT_LEGACY_MEM " Legacy memory mode (no dynamic allocation, contiguous segments)\n" "\n");/* Allow the application to print its usage message too if hook is set */ if ( rte_application_usage_hook ) {
@@ -767,6 +768,8 @@ rte_eal_init(int argc, char **argv)rte_atomic32_clear (&run_once);return -1 ; } +/* for now, always set legacy mem */ + internal_config.legacy_mem =1 ;if (eal_plugins_init () <0 ) {rte_eal_init_alert ("Cannot init plugins\n" );
lib/librte_eal/linuxapp/eal/eal_memory.c +20 -4
@@ -922,8 +922,8 @@ huge_recover_sigbus(void)* 6. unmap the first mapping * 7. fill memsegs in configuration with contiguous zones */ -int -rte_eal_hugepage_init (void ) +static int +eal_legacy_hugepage_init (void ) {struct rte_mem_config *mcfg;struct hugepage_file *hugepage =NULL , *tmp_hp =NULL ;
@@ -1266,8 +1266,8 @@ getFileSize(int fd)* configuration and finds the hugepages which form that segment, mapping them * in order to form a contiguous block in the virtual memory space */ -int -rte_eal_hugepage_attach (void ) +static int +eal_legacy_hugepage_attach (void ) {const struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config;struct hugepage_file *hp =NULL ;
@@ -1403,6 +1403,22 @@ rte_eal_hugepage_attach(void) }int +rte_eal_hugepage_init (void ) +{ +if (internal_config.legacy_mem) +return eal_legacy_hugepage_init (); +return -1 ; +} + +int +rte_eal_hugepage_attach (void ) +{ +if (internal_config.legacy_mem) +return eal_legacy_hugepage_attach (); +return -1 ; +} + +int rte_eal_using_phys_addrs (void ) {return phys_addrs_available;
Signature · 1 line
2.7.4
PATCH v3 48/68 eal: add rte_fbarray
In reply to Anatoly Burakovrte_fbarray is a simple indexed array stored in shared memory via mapping files into memory. Rationale for its existence is the
following: since we are going to map memory page-by-page, there could be quite a lot of memory segments to keep track of (for smaller page sizes, page count can easily reach thousands). We can't really make page lists truly dynamic and infinitely expandable, because that involves reallocating memory (which is a big no-no in multiprocess). What we can do instead is have a maximum capacity as something really, really large, and decide at allocation time how big the array is going to be. We map the entire file into memory, which makes it possible to use fbarray as shared memory, provided the structure itself is allocated in shared memory. Per-fbarray locking is also used to avoid index data races (but not contents data races - that is up to user application to synchronize).
In addition, in understanding that we will frequently need to scan this array for free space and iterating over array linearly can become slow, rte_fbarray provides facilities to index array's usage. The following use cases are covered:
- find next free/used slot (useful either for adding new elements to fbarray, or walking the list)
- find starting index for next N free/used slots (useful for when we want to allocate chunk of VA-contiguous memory composed of several pages)
- find how many contiguous free/used slots there are, starting from specified index (useful for when we want to figure out how many pages we have until next hole in allocated memory, to speed up some bulk operations where we would otherwise have to walk the array and add pages one by one)
This is accomplished by storing a usage mask in-memory, right after the data section of the array, and using some bit-level magic to figure out the info we need.
---
Notes:
v3:
- Fixed index alignment bug
- Fixed compile issues
v3:
- MAP_POPULATE not supported on FreeBSD, removed it
- Bugfix for index size when it is unaligned
- Replace uint64_t with size_t for mapping sizes
- Make API experimental
Initial version of this had resizing capability, however it was removed due to the fact that in multiprocess scenario, each fbarray would have its own view of mapped memory, which might not correspond with others due to some other process performing a resize that current process didn't know about.
It was therefore decided that to avoid cost of synchronization on each and every operation (to make sure the array wasn't resized), resizing feature should be dropped.
lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/eal_common_fbarray.c | 859 ++++++++++++++++++++++++++++ lib/librte_eal/common/eal_filesystem.h | 13 + lib/librte_eal/common/include/rte_fbarray.h | 353 ++++++++++++ lib/librte_eal/common/meson.build | 2 + lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/rte_eal_version.map | 16 + 8 files changed, 1246 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/eal_common_fbarray.c create mode 100644 lib/librte_eal/common/include/rte_fbarray.h
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -53,6 +53,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_thread.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_proc.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_fbarray.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_heap.c
lib/librte_eal/common/Makefile +1 -1
@@ -16,7 +16,7 @@ INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h INC += rte_bitmap.h rte_vfio.h rte_hypervisor.h rte_test.h -INC += rte_reciprocal.h +INC += rte_reciprocal.h rte_fbarray.h GENERIC_INC := rte_atomic.h rte_byteorder.h rte_cycles.h rte_prefetch.h GENERIC_INC += rte_spinlock.h rte_memcpy.h rte_cpuflags.h rte_rwlock.h
lib/librte_eal/common/eal_common_fbarray.c new file +859 -0
859 lines not on this page · raw message
lib/librte_eal/common/eal_filesystem.h +13 -0
@@ -13,6 +13,7 @@/** Path of rte config file. */ #define RUNTIME_CONFIG_FMT "%s/.%s_config" +#define FBARRAY_FMT "%s/%s_%s"#include <stdint.h> #include <limits.h>
@@ -55,6 +56,18 @@ eal_mp_socket_path(void)return buffer; } +static inline const char * +eal_get_fbarray_path (char *buffer,size_t buflen,const char *name) { +const char *directory ="/tmp" ; +const char *home_dir =getenv ("HOME" ); + +if (getuid () !=0 && home_dir !=NULL ) + directory = home_dir; +snprintf (buffer, buflen -1 ,FBARRAY_FMT , directory, + internal_config.hugefile_prefix, name); +return buffer; +} +/** Path of hugepage info file. */ #define HUGEPAGE_INFO_FMT "%s/.%s_hugepage_info"
lib/librte_eal/common/include/rte_fbarray.h new file +353 -0
353 lines not on this page · raw message
lib/librte_eal/common/meson.build +2 -0
@@ -11,6 +11,7 @@ common_sources = files( 'eal_common_devargs.c', 'eal_common_dev.c', 'eal_common_errno.c', + 'eal_common_fbarray.c', 'eal_common_hexdump.c', 'eal_common_launch.c', 'eal_common_lcore.c',
@@ -51,6 +52,7 @@ common_headers = files( 'include/rte_eal_memconfig.h', 'include/rte_eal_interrupts.h', 'include/rte_errno.h', + 'include/rte_fbarray.h', 'include/rte_hexdump.h', 'include/rte_interrupts.h', 'include/rte_keepalive.h',
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -61,6 +61,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_proc.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_fbarray.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_heap.c
lib/librte_eal/rte_eal_version.map +16 -0
@@ -221,6 +221,22 @@ EXPERIMENTAL { rte_eal_hotplug_add; rte_eal_hotplug_remove; rte_eal_mbuf_user_pool_ops; + rte_fbarray_attach; + rte_fbarray_destroy; + rte_fbarray_detach; + rte_fbarray_dump_metadata; + rte_fbarray_find_idx; + rte_fbarray_find_next_free; + rte_fbarray_find_next_used; + rte_fbarray_find_next_n_free; + rte_fbarray_find_next_n_used; + rte_fbarray_find_contig_free; + rte_fbarray_find_contig_used; + rte_fbarray_get; + rte_fbarray_init; + rte_fbarray_is_used; + rte_fbarray_set_free; + rte_fbarray_set_used; rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; rte_mem_iova2virt;
Signature · 1 line
2.7.4
PATCH v3 49/68 eal: replace memseg with memseg lists
In reply to Anatoly BurakovBefore, we were aggregating multiple pages into one memseg, so the number of memsegs was small. Now, each page gets its own memseg, so the list of memsegs is huge. To accommodate the new memseg list size and to keep the under-the-hood workings sane, the memseg list is now not just a single list, but multiple lists. To be precise, each hugepage size available on the system gets one or more memseg lists, per socket.
In order to support dynamic memory allocation, we reserve all memory in advance (unless we're in 32-bit legacy mode, in which case we do not preallocate memory). As in, we do an anonymous mmap() of the entire maximum size of memory per hugepage size, per socket (which is limited to either RTE_MAX_MEMSEG_PER_TYPE pages or RTE_MAX_MEM_MB_PER_TYPE megabytes worth of memory, whichever is the smaller one), split over multiple lists (which are limited to either RTE_MAX_MEMSEG_PER_LIST memsegs or RTE_MAX_MEM_MB_PER_LIST megabytes per list, whichever is the smaller one). There is also a global limit of CONFIG_RTE_MAX_MEM_MB megabytes, which is mainly used for 32-bit targets to limit amounts of preallocated memory, but can be used to place an upper limit on total amount of VA memory that can be allocated by DPDK application.
So, for each hugepage size, we get (by default) up to 128G worth of memory, per socket, split into chunks of up to 32G in size. The address space is claimed at the start, in eal_common_memory.c. The actual page allocation code is in eal_memalloc.c (Linux-only), and largely consists of copied EAL memory init code.
Pages in the list are also indexed by address. That is, in order to figure out where the page belongs, one can simply look at base address for a memseg list. Similarly, figuring out IOVA address of a memzone is a matter of finding the right memseg list, getting offset and dividing by page size to get the appropriate memseg.
This commit also removes rte_eal_dump_physmem_layout() call, according to deprecation notice [1], and removes that deprecation notice as well.
On 32-bit targets due to limited VA space, DPDK will no longer spread memory to different sockets like before. Instead, it will (by default) allocate all of the memory on socket where master lcore is. To override this behavior, --socket-mem must be used.
The rest of the changes are really ripple effects from the memseg change - heap changes, compile fixes, and rewrites to support fbarray-backed memseg lists. Due to earlier switch to _walk() functions, most of the changes are simple fixes, however some of the _walk() calls were switched to memseg list walk, where it made sense to do so.
Additionally, we are also switching locks from flock() to fcntl(). Down the line, we will be introducing single-file segments option, and we cannot use flock() locks to lock parts of the file. Therefore, we will use fcntl() locks for legacy mem as well, in case someone is unfortunate enough to accidentally start legacy mem primary process alongside an already working non-legacy mem-based primary process.
[1] http://dpdk.org/dev/patchwork/patch/34002/
---
Notes:
v3:
- New and improved legacy mode, without (too much) crazy hacks
- 32-bit support
- FreeBSD support
- Compile fixes for all platforms
config/common_base | 15 +- config/defconfig_i686-native-linuxapp-gcc | 3 + config/defconfig_i686-native-linuxapp-icc | 3 + config/defconfig_x86_x32-native-linuxapp-gcc | 3 + config/rte_config.h | 7 +- doc/guides/rel_notes/deprecation.rst | 9 - drivers/bus/fslmc/fslmc_vfio.c | 10 +- drivers/bus/fslmc/portal/dpaa2_hw_pvt.h | 2 +- drivers/bus/pci/linux/pci.c | 8 +- drivers/crypto/dpaa_sec/dpaa_sec.c | 2 +- drivers/net/mlx4/mlx4_mr.c | 4 +- drivers/net/mlx5/mlx5.c | 3 +- drivers/net/mlx5/mlx5_mr.c | 4 +- drivers/net/virtio/virtio_user/vhost_kernel.c | 4 +- lib/librte_eal/bsdapp/eal/eal.c | 12 +- lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 17 +- lib/librte_eal/bsdapp/eal/eal_memory.c | 207 ++++- lib/librte_eal/common/eal_common_memory.c | 581 ++++++++++++-- lib/librte_eal/common/eal_common_memzone.c | 48 +- lib/librte_eal/common/eal_hugepages.h | 1 - lib/librte_eal/common/eal_internal_cfg.h | 2 +- lib/librte_eal/common/include/rte_eal_memconfig.h | 22 +- lib/librte_eal/common/include/rte_memory.h | 56 +- lib/librte_eal/common/include/rte_memzone.h | 1 - lib/librte_eal/common/malloc_elem.c | 12 +- lib/librte_eal/common/malloc_elem.h | 6 +- lib/librte_eal/common/malloc_heap.c | 62 +- lib/librte_eal/common/rte_malloc.c | 22 +- lib/librte_eal/linuxapp/eal/eal.c | 15 +- lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 25 +- lib/librte_eal/linuxapp/eal/eal_memory.c | 913 +++++++++++++++------- lib/librte_eal/linuxapp/eal/eal_vfio.c | 9 +- lib/librte_eal/rte_eal_version.map | 3 +- lib/librte_mempool/rte_mempool.c | 9 +- test/test/test_malloc.c | 30 +- test/test/test_memory.c | 10 +- test/test/test_memzone.c | 12 +- 37 files changed, 1563 insertions(+), 589 deletions(-)
config/common_base +14 -1
@@ -61,7 +61,20 @@ CONFIG_RTE_CACHE_LINE_SIZE=64 CONFIG_RTE_LIBRTE_EAL=y CONFIG_RTE_MAX_LCORE=128 CONFIG_RTE_MAX_NUMA_NODES=8 -CONFIG_RTE_MAX_MEMSEG=256 +CONFIG_RTE_MAX_MEMSEG_LISTS=64 +# each memseg list will be limited to either RTE_MAX_MEMSEG_PER_LIST pages +# or RTE_MAX_MEM_MB_PER_LIST megabytes worth of memory, whichever is smaller +CONFIG_RTE_MAX_MEMSEG_PER_LIST=8192 +CONFIG_RTE_MAX_MEM_MB_PER_LIST=32768 +# a "type" is a combination of page size and NUMA node. total number of memseg +# lists per type will be limited to either RTE_MAX_MEMSEG_PER_TYPE pages (split +# over multiple lists of RTE_MAX_MEMSEG_PER_LIST pages), or +# RTE_MAX_MEM_MB_PER_TYPE megabytes of memory (split over multiple lists of +# RTE_MAX_MEM_MB_PER_LIST), whichever is smaller +CONFIG_RTE_MAX_MEMSEG_PER_TYPE=32768 +CONFIG_RTE_MAX_MEM_MB_PER_TYPE=131072 +# global maximum usable amount of VA, in megabytes +CONFIG_RTE_MAX_MEM_MB=524288 CONFIG_RTE_MAX_MEMZONE=2560 CONFIG_RTE_MAX_TAILQ=32 CONFIG_RTE_ENABLE_ASSERT=n
config/defconfig_i686-native-linuxapp-gcc +3 -0
@@ -46,3 +46,6 @@ CONFIG_RTE_LIBRTE_PMD_ZUC=n # AVP PMD is not supported on 32-bit # CONFIG_RTE_LIBRTE_AVP_PMD=n + +# 32-bit doesn't break up memory in lists, but does have VA allocation limit +CONFIG_RTE_MAX_MEM_MB=2048
config/defconfig_i686-native-linuxapp-icc +3 -0
@@ -51,3 +51,6 @@ CONFIG_RTE_LIBRTE_PMD_ZUC=n # AVP PMD is not supported on 32-bit # CONFIG_RTE_LIBRTE_AVP_PMD=n + +# 32-bit doesn't break up memory in lists, but does have VA allocation limit +CONFIG_RTE_MAX_MEM_MB=2048
config/defconfig_x86_x32-native-linuxapp-gcc +3 -0
@@ -26,3 +26,6 @@ CONFIG_RTE_LIBRTE_SFC_EFX_PMD=n # AVP PMD is not supported on 32-bit # CONFIG_RTE_LIBRTE_AVP_PMD=n + +# 32-bit doesn't break up memory in lists, but does have VA allocation limit +CONFIG_RTE_MAX_MEM_MB=2048
config/rte_config.h +6 -1
@@ -21,7 +21,12 @@/****** library defines ********/ /* EAL defines */ -#define RTE_MAX_MEMSEG 512 +#define RTE_MAX_MEMSEG_LISTS 128 +#define RTE_MAX_MEMSEG_PER_LIST 8192 +#define RTE_MAX_MEM_MB_PER_LIST 32768 +#define RTE_MAX_MEMSEG_PER_TYPE 32768 +#define RTE_MAX_MEM_MB_PER_TYPE 65536 +#define RTE_MAX_MEM_MB 524288#define RTE_MAX_MEMZONE 2560#define RTE_MAX_TAILQ 32#define RTE_LOG_LEVEL RTE_LOG_INFO
doc/guides/rel_notes/deprecation.rst +0 -9
@@ -38,15 +38,6 @@ Deprecation Notices success and failure, respectively. This will change to 1 and 0 for true and false, respectively, to make use of the function more intuitive. -* eal: due to internal data layout reorganization, there will be changes to - several structures and functions as a result of coming changes to support - memory hotplug in v18.05. - ``rte_eal_get_physmem_layout`` will be deprecated and removed in subsequent - releases. - ``rte_mem_config`` contents will change due to switch to memseg lists. - ``rte_memzone`` member ``memseg_id`` will no longer serve any useful purpose - and will be removed. - * eal: a new set of mbuf mempool ops name APIs for user, platform and best mempool names have been defined in ``rte_mbuf`` in v18.02. The uses of ``rte_eal_mbuf_default_mempool_ops`` shall be replaced by
drivers/bus/fslmc/fslmc_vfio.c +2 -8
@@ -194,7 +194,8 @@ static int vfio_map_irq_region(struct fslmc_vfio_group *group) }static int -fslmc_vfio_map (const struct rte_memseg *ms,void *arg) +fslmc_vfio_map(const struct rte_memseg_list *msl __rte_unused, +const struct rte_memseg *ms,void *arg) {int *n_segs = arg;struct fslmc_vfio_group *group;
@@ -236,18 +237,11 @@ fslmc_vfio_map(const struct rte_memseg *ms, void *arg)int rte_fslmc_vfio_dmamap (void ) { -const struct rte_memseg *memseg;int i =0 ;if (is_dma_done)return 0 ; - memseg =rte_eal_get_physmem_layout (); -if (memseg ==NULL ) { -FSLMC_VFIO_LOG (ERR ,"Cannot get physical layout." ); -return -ENODEV ; - } -if (rte_memseg_walk (fslmc_vfio_map, &i) <0 )return -1 ;
drivers/bus/fslmc/portal/dpaa2_hw_pvt.h +1 -1
@@ -274,7 +274,7 @@ static phys_addr_t dpaa2_mem_vtop(uint64_t vaddr)if (dpaa2_virt_mode)return vaddr; - memseg =rte_mem_virt2memseg ((void *)(uintptr_t )vaddr); + memseg =rte_mem_virt2memseg ((void *)(uintptr_t )vaddr,NULL );if (memseg)return memseg->phys_addr +RTE_PTR_DIFF (vaddr, memseg->addr);return (size_t )NULL ;
drivers/bus/pci/linux/pci.c +5 -3
@@ -117,9 +117,10 @@ rte_pci_unmap_device(struct rte_pci_device *dev) }static int -find_max_end_va (const struct rte_memseg *ms,void *arg) +find_max_end_va (const struct rte_memseg_list *msl,void *arg) { -void *end_va =RTE_PTR_ADD (ms->addr, ms->len); +size_t sz = msl->memseg_arr.len * msl->page_sz; +void *end_va =RTE_PTR_ADD (msl->base_va, sz);void **max_va = arg;if (*max_va < end_va)
@@ -132,10 +133,11 @@ pci_find_max_end_va(void) {void *va =NULL ; -rte_memseg_walk (find_max_end_va, &va); +rte_memseg_list_walk (find_max_end_va, &va);return va; } +/* parse one line of the "resource" sysfs file (note that the 'line' * string is modified) */
drivers/crypto/dpaa_sec/dpaa_sec.c +1 -1
@@ -95,7 +95,7 @@ dpaa_mem_vtop(void *vaddr) {const struct rte_memseg *ms; - ms =rte_mem_virt2memseg (vaddr); + ms =rte_mem_virt2memseg (vaddr,NULL );if (ms)return ms->iova +RTE_PTR_DIFF (vaddr, ms->addr);return (size_t )NULL ;
drivers/net/mlx4/mlx4_mr.c +2 -2
@@ -142,10 +142,10 @@ mlx4_mr_get(struct priv *priv, struct rte_mempool *mp) (void *)mp, (void *)start, (void *)end, (size_t)(end - start));/* Round start and end to page boundary if found in memory segments. */ - ms =rte_mem_virt2memseg ((void *)start); + ms =rte_mem_virt2memseg ((void *)start,NULL );if (ms !=NULL ) start =RTE_ALIGN_FLOOR (start, ms->hugepage_sz); - ms =rte_mem_virt2memseg ((void *)end); + ms =rte_mem_virt2memseg ((void *)end,NULL );if (ms !=NULL ) end =RTE_ALIGN_CEIL (end, ms->hugepage_sz);
drivers/net/mlx5/mlx5.c +2 -1
@@ -478,7 +478,8 @@ static struct rte_pci_driver mlx5_driver;static void *uar_base;static int -find_lower_va_bound (const struct rte_memseg *ms,void *arg) +find_lower_va_bound(const struct rte_memseg_list *msl __rte_unused, +const struct rte_memseg *ms,void *arg) {void **addr = arg;
drivers/net/mlx5/mlx5_mr.c +2 -2
@@ -263,10 +263,10 @@ mlx5_mr_new(struct rte_eth_dev *dev, struct rte_mempool *mp) mr->end = end;/* Round start and end to page boundary if found in memory segments. */ - ms =rte_mem_virt2memseg ((void *)start); + ms =rte_mem_virt2memseg ((void *)start,NULL );if (ms !=NULL ) start =RTE_ALIGN_FLOOR (start, ms->hugepage_sz); - ms =rte_mem_virt2memseg ((void *)end); + ms =rte_mem_virt2memseg ((void *)end,NULL );if (ms !=NULL ) end =RTE_ALIGN_CEIL (end, ms->hugepage_sz);
drivers/net/virtio/virtio_user/vhost_kernel.c +2 -2
@@ -75,7 +75,8 @@ struct walk_arg {uint32_t region_nr; };static int -add_memory_region (const struct rte_memseg *ms,size_t len,void *arg) +add_memory_region(const struct rte_memseg_list *msl __rte_unused, +const struct rte_memseg *ms,size_t len,void *arg) {struct walk_arg *wa = arg;struct vhost_memory_region *mr;
@@ -95,7 +96,6 @@ add_memory_region(const struct rte_memseg *ms, size_t len, void *arg)return 0 ; } -/* By default, vhost kernel module allows 64 regions, but DPDK allows * 256 segments. As a relief, below function merges those virtually * adjacent memsegs into one region.
lib/librte_eal/bsdapp/eal/eal.c +6 -6
@@ -64,8 +64,8 @@ static int mem_cfg_fd = -1;static struct flock wr_lock = { .l_type =F_WRLCK , .l_whence =SEEK_SET , - .l_start = offsetof(struct rte_mem_config , memseg), - .l_len =sizeof (early_mem_config.memseg), + .l_start = offsetof(struct rte_mem_config , memsegs), + .l_len =sizeof (early_mem_config.memsegs), };/* Address of global and public configuration */
@@ -430,11 +430,11 @@ eal_parse_args(int argc, char **argv) }static int -check_socket (const struct rte_memseg *ms,void *arg) +check_socket (const struct rte_memseg_list *msl,void *arg) {int *socket_id = arg; -if (ms->socket_id == *socket_id) +if (msl->socket_id == *socket_id && msl->memseg_arr.count !=0 )return 1 ;return 0 ;
@@ -447,10 +447,11 @@ eal_check_mem_on_local_socket(void) socket_id =rte_lcore_to_socket_id (rte_config.master_lcore); -if (rte_memseg_walk (check_socket, &socket_id) ==0 ) +if (rte_memseg_list_walk (check_socket, &socket_id) ==0 )RTE_LOG (WARNING ,EAL ,"WARNING: Master core has no memory on local socket!\n" ); } +static int sync_func (__attribute__((unused))void *arg) {
@@ -561,7 +562,6 @@ rte_eal_init(int argc, char **argv)rte_eal_get_configuration ()->iova_mode =rte_bus_get_iommu_class ();if (internal_config.no_hugetlbfs ==0 && - internal_config.process_type !=RTE_PROC_SECONDARY &&eal_hugepage_info_init () <0 ) {rte_eal_init_alert ("Cannot get hugepage information." ); rte_errno =EACCES ;
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c +11 -6
@@ -47,12 +47,18 @@ eal_hugepage_info_init(void)struct hugepage_info *hpi = &internal_config.hugepage_info[0 ];struct hugepage_info *tmp_hpi; + internal_config.num_hugepage_sizes =1 ; + +/* nothing more to be done for secondary */ +if (rte_eal_process_type () ==RTE_PROC_SECONDARY ) +return 0 ; + sysctl_size =sizeof (num_buffers); error =sysctlbyname ("hw.contigmem.num_buffers" , &num_buffers, &sysctl_size,NULL ,0 );if (error !=0 ) { -RTE_LOG (ERR ,EAL ,"could not read sysctl hw.contigmem.num_buffers" ); +RTE_LOG (ERR ,EAL ,"could not read sysctl hw.contigmem.num_buffers\n" );return -1 ; }
@@ -61,7 +67,7 @@ eal_hugepage_info_init(void) &sysctl_size, NULL, 0);if (error !=0 ) { -RTE_LOG (ERR ,EAL ,"could not read sysctl hw.contigmem.buffer_size" ); +RTE_LOG (ERR ,EAL ,"could not read sysctl hw.contigmem.buffer_size\n" );return -1 ; }
@@ -81,22 +87,21 @@ eal_hugepage_info_init(void)RTE_LOG (INFO ,EAL ,"Contigmem driver has %d buffers, each of size %dKB\n" , num_buffers, (int )(buffer_size>>10 )); - internal_config.num_hugepage_sizes =1 ; hpi->hugedir =CONTIGMEM_DEV ; hpi->hugepage_sz = buffer_size; hpi->num_pages[0 ] = num_buffers; hpi->lock_descriptor = fd; tmp_hpi =create_shared_memory (eal_hugepage_info_path (), -sizeof (struct hugepage_info )); +sizeof (internal_config.hugepage_info));if (tmp_hpi ==NULL ) {RTE_LOG (ERR ,EAL ,"Failed to create shared memory!\n" );return -1 ; } -memcpy (tmp_hpi, hpi,sizeof (struct hugepage_info )); +memcpy (tmp_hpi, hpi,sizeof (internal_config.hugepage_info)); -if (munmap (tmp_hpi,sizeof (struct hugepage_info )) <0 ) { +if (munmap (tmp_hpi,sizeof (internal_config.hugepage_info)) <0 ) {RTE_LOG (ERR ,EAL ,"Failed to unmap shared memory!\n" );return -1 ; }
lib/librte_eal/bsdapp/eal/eal_memory.c +168 -39
285 lines not on this page · raw message
lib/librte_eal/common/eal_common_memory.c +495 -86
674 lines not on this page · raw message
lib/librte_eal/common/eal_common_memzone.c +35 -13
84 lines not on this page · raw message
lib/librte_eal/common/eal_hugepages.h +0 -1
@@ -22,7 +22,6 @@ struct hugepage_file {size_t size;/**< the page size */ int socket_id;/**< NUMA socket ID */ int file_id;/**< the '%d' in HUGEFILE_FMT */ -int memseg_id;/**< the memory segment to which page belongs */ char filepath[MAX_HUGEPAGE_PATH ];/**< path to backing file on filesystem */ };
lib/librte_eal/common/eal_internal_cfg.h +1 -1
@@ -23,7 +23,7 @@ struct hugepage_info {uint64_t hugepage_sz;/**< size of a huge page */ const char *hugedir;/**< dir where hugetlbfs is mounted */ uint32_t num_pages[RTE_MAX_NUMA_NODES ]; -/**< number of hugepages of that size on each socket */ +/**< number of hugepages of that size on each socket */ int lock_descriptor;/**< file descriptor for hugepage dir */ };
lib/librte_eal/common/include/rte_eal_memconfig.h +21 -1
@@ -12,12 +12,30 @@#include <rte_malloc_heap.h> #include <rte_rwlock.h> #include <rte_pause.h> +#include <rte_fbarray.h> #ifdef __cplusplus extern "C" { #endif /** + * memseg list is a special case as we need to store a bunch of other data + * together with the array itself. + */ +struct rte_memseg_list { + RTE_STD_C11 + union { + void *base_va; + /**< Base virtual address for this memseg list. */ + uint64_t addr_64; + /**< Makes sure addr is always 64-bits */ + }; + int socket_id; /**< Socket ID for all memsegs in this list. */ + uint64_t page_sz; /**< Page size for all memsegs in this list. */ + struct rte_fbarray memseg_arr; +}; + +/** * the structure for the memory configuration for the RTE. * Used by the rte_config structure. It is separated out, as for multi-process * support, the memory details should be shared across instances
@@ -43,9 +61,11 @@ struct rte_mem_config {uint32_t memzone_cnt;/**< Number of allocated memzones */ /* memory segments and zones */ -struct rte_memseg memseg[RTE_MAX_MEMSEG ];/**< Physmem descriptors. */ struct rte_memzone memzone[RTE_MAX_MEMZONE ];/**< Memzone descriptors. */ +struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS ]; +/**< list of dynamic arrays holding memsegs */ +struct rte_tailq_head tailq_head[RTE_MAX_TAILQ ];/**< Tailqs for objects */ /* Heaps of Malloc per socket */
lib/librte_eal/common/include/rte_memory.h +40 -16
89 lines not on this page · raw message
lib/librte_eal/common/include/rte_memzone.h +0 -1
@@ -67,7 +67,6 @@ struct rte_memzone {int32_t socket_id;/**< NUMA socket ID. */ uint32_t flags;/**< Characteristics of this memzone. */ -uint32_t memseg_id;/**< Memseg it belongs. */ } __attribute__((__packed__));/**
lib/librte_eal/common/malloc_elem.c +6 -6
@@ -27,11 +27,11 @@* Initialize a general malloc_elem header structure */ void -malloc_elem_init (struct malloc_elem *elem, -struct malloc_heap *heap,const struct rte_memseg *ms,size_t size) +malloc_elem_init (struct malloc_elem *elem,struct malloc_heap *heap, +struct rte_memseg_list *msl,size_t size) { elem->heap = heap; - elem->ms = ms; + elem->msl = msl; elem->prev =NULL ; elem->next =NULL ;memset (&elem->free_list,0 ,sizeof (elem->free_list));
@@ -100,7 +100,7 @@ malloc_elem_insert(struct malloc_elem *elem)* so we just check the page addresses. */ static bool -elem_check_phys_contig(const struct rte_memseg *ms __rte_unused, +elem_check_phys_contig(const struct rte_memseg_list *msl __rte_unused,void *start,size_t size) {rte_iova_t cur, expected;
@@ -191,7 +191,7 @@ elem_start_pt(struct malloc_elem *elem, size_t size, unsigned align,* couldn't fit all data into one physically contiguous * block, try again with lower addresses. */ -if (!elem_check_phys_contig (elem->ms, +if (!elem_check_phys_contig (elem->msl, (void *)new_data_start, new_data_size)) { elem_size -= align;
@@ -225,7 +225,7 @@ split_elem(struct malloc_elem *elem, struct malloc_elem *split_pt)const size_t old_elem_size = (uintptr_t )split_pt - (uintptr_t )elem;const size_t new_elem_size = elem->size - old_elem_size; -malloc_elem_init (split_pt, elem->heap, elem->ms, new_elem_size); +malloc_elem_init (split_pt, elem->heap, elem->msl, new_elem_size); split_pt->prev = elem; split_pt->next = next_elem;if (next_elem)
lib/librte_eal/common/malloc_elem.h +3 -3
@@ -7,7 +7,7 @@#include <stdbool.h> -#include <rte_memory.h> +#include <rte_eal_memconfig.h> /* dummy definition of struct so we can use pointers to it in malloc_elem struct */ struct malloc_heap ;
@@ -26,7 +26,7 @@ struct malloc_elem {/**< points to next elem in memseg */ LIST_ENTRY (malloc_elem) free_list;/**< list of free elements in heap */ -const struct rte_memseg *ms; +struct rte_memseg_list *msl;volatile enum elem_state state;uint32_t pad;size_t size;
@@ -113,7 +113,7 @@ malloc_elem_from_data(const void *data)void malloc_elem_init (struct malloc_elem *elem,struct malloc_heap *heap, -const struct rte_memseg *ms, +struct rte_memseg_list *msl,size_t size);void
lib/librte_eal/common/malloc_heap.c +38 -24
94 lines not on this page · raw message
lib/librte_eal/common/rte_malloc.c +13 -9
@@ -242,17 +242,21 @@ rte_malloc_set_limit(__rte_unused const char *type,rte_iova_t rte_malloc_virt2iova (const void *addr) { -rte_iova_t iova; -const struct malloc_elem *elem =malloc_elem_from_data (addr); +const struct rte_memseg *ms; +struct malloc_elem *elem =malloc_elem_from_data (addr); +if (elem ==NULL )return RTE_BAD_IOVA ; -if (elem->ms->iova ==RTE_BAD_IOVA ) -return RTE_BAD_IOVA ;if (rte_eal_iova_mode () ==RTE_IOVA_VA ) - iova = (uintptr_t )addr; -else - iova = elem->ms->iova + -RTE_PTR_DIFF (addr, elem->ms->addr); -return iova; +return (uintptr_t ) addr; + + ms =rte_mem_virt2memseg (addr, elem->msl); +if (ms ==NULL ) +return RTE_BAD_IOVA ; + +if (ms->iova ==RTE_BAD_IOVA ) +return RTE_BAD_IOVA ; + +return ms->iova +RTE_PTR_DIFF (addr, ms->addr); }
lib/librte_eal/linuxapp/eal/eal.c +9 -6
@@ -74,8 +74,8 @@ static int mem_cfg_fd = -1;static struct flock wr_lock = { .l_type =F_WRLCK , .l_whence =SEEK_SET , - .l_start = offsetof(struct rte_mem_config , memseg), - .l_len =sizeof (early_mem_config.memseg), + .l_start = offsetof(struct rte_mem_config , memsegs), + .l_len =sizeof (early_mem_config.memsegs), };/* Address of global and public configuration */
@@ -640,11 +640,14 @@ eal_parse_args(int argc, char **argv) }static int -check_mem (const struct rte_memseg *ms,void *arg) +check_socket (const struct rte_memseg_list *msl,void *arg) { -int *socket = arg; +int *socket_id = arg; -return ms->socket_id == *socket; +if (msl->socket_id == *socket_id && msl->memseg_arr.count !=0 ) +return 1 ; + +return 0 ; } static void
@@ -654,7 +657,7 @@ eal_check_mem_on_local_socket(void) socket_id =rte_lcore_to_socket_id (rte_config.master_lcore); -if (rte_memseg_walk (check_mem, &socket_id) ==0 ) +if (rte_memseg_list_walk (check_socket, &socket_id) ==0 )RTE_LOG (WARNING ,EAL ,"WARNING: Master core has no memory on local socket!\n" ); }
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +23 -2
@@ -15,6 +15,7 @@#include <unistd.h> #include <errno.h> #include <sys/queue.h> +#include <sys/stat.h> #include <rte_memory.h> #include <rte_eal.h>
@@ -160,6 +161,18 @@ get_hugepage_dir(uint64_t hugepage_sz) }/* +* uses fstat to report the size of a file on disk +*/ +static off_t +get_file_size (int fd) +{ +struct stat st; +if (fstat (fd, &st) <0 ) +return 0 ; +return st.st_size; +} + +/* * Clear the hugepage directory of whatever hugepage files * there are. Checks if the file is locked (i.e. * if it's in use by another DPDK process).
@@ -189,6 +202,8 @@ clear_hugedir(const char * hugedir) }while (dirent !=NULL ){ +struct flock lck = {0 }; +/* skip files that don't match the hugepage pattern */ if (fnmatch (filter, dirent->d_name,0 ) >0 ) { dirent =readdir (dir);
@@ -205,11 +220,17 @@ clear_hugedir(const char * hugedir) }/* non-blocking lock */ - lck_result =flock (fd,LOCK_EX |LOCK_NB ); + lck.l_type =F_RDLCK ; + lck.l_whence =SEEK_SET ; + lck.l_start =0 ; + lck.l_len =get_file_size (fd); + + lck_result =fcntl (fd,F_SETLK , &lck);/* if lock succeeds, unlock and remove the file */ if (lck_result !=-1 ) { -flock (fd,LOCK_UN ); + lck.l_type =F_UNLCK ; +fcntl (fd,F_SETLK , &lck);unlinkat (dir_fd, dirent->d_name,0 ); }close (fd);
lib/librte_eal/linuxapp/eal/eal_memory.c +615 -298
1,111 lines not on this page · raw message
lib/librte_eal/linuxapp/eal/eal_vfio.c +6 -3
@@ -686,7 +686,8 @@ vfio_get_group_no(const char *sysfs_base, }static int -type1_map (const struct rte_memseg *ms,void *arg) +type1_map(const struct rte_memseg_list *msl __rte_unused, +const struct rte_memseg *ms,void *arg) {int *vfio_container_fd = arg;
@@ -799,7 +800,8 @@ vfio_spapr_dma_do_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova, }static int -vfio_spapr_map_walk (const struct rte_memseg *ms,void *arg) +vfio_spapr_map_walk(const struct rte_memseg_list *msl __rte_unused, +const struct rte_memseg *ms,void *arg) {int *vfio_container_fd = arg;
@@ -812,7 +814,8 @@ struct spapr_walk_param {uint64_t hugepage_sz; };static int -vfio_spapr_window_size_walk (const struct rte_memseg *ms,void *arg) +vfio_spapr_window_size_walk(const struct rte_memseg_list *msl __rte_unused, +const struct rte_memseg *ms,void *arg) {struct spapr_walk_param *param = arg;uint64_t max = ms->iova + ms->len;
lib/librte_eal/rte_eal_version.map +2 -1
@@ -25,7 +25,6 @@ DPDK_2.0 { rte_eal_devargs_type_count; rte_eal_get_configuration; rte_eal_get_lcore_state; - rte_eal_get_physmem_layout; rte_eal_get_physmem_size; rte_eal_has_hugepages; rte_eal_hpet_init;
@@ -241,7 +240,9 @@ EXPERIMENTAL { rte_malloc_dump_heaps; rte_mem_iova2virt; rte_mem_virt2memseg; + rte_mem_virt2memseg_list; rte_memseg_contig_walk; + rte_memseg_list_walk; rte_memseg_walk; rte_memzone_reserve_contig; rte_memzone_reserve_aligned_contig;
lib/librte_mempool/rte_mempool.c +5 -4
@@ -100,12 +100,12 @@ static unsigned optimize_object_size(unsigned obj_size) }static int -find_min_pagesz (const struct rte_memseg *ms,void *arg) +find_min_pagesz (const struct rte_memseg_list *msl,void *arg) {size_t *min = arg; -if (ms->hugepage_sz < *min) - *min = ms->hugepage_sz; +if (msl->page_sz < *min) + *min = msl->page_sz;return 0 ; }
@@ -115,11 +115,12 @@ get_min_page_size(void) {size_t min_pagesz =SIZE_MAX ; -rte_memseg_walk (find_min_pagesz, &min_pagesz); +rte_memseg_list_walk (find_min_pagesz, &min_pagesz);return min_pagesz ==SIZE_MAX ? (size_t )getpagesize () : min_pagesz; } +static void mempool_add_elem (struct rte_mempool *mp,void *obj,rte_iova_t iova) {
test/test/test_malloc.c +7 -23
@@ -12,6 +12,7 @@#include <rte_common.h> #include <rte_memory.h> +#include <rte_eal_memconfig.h> #include <rte_per_lcore.h> #include <rte_launch.h> #include <rte_eal.h>
@@ -706,36 +707,20 @@ test_malloc_bad_params(void) }static int -check_socket_mem (const struct rte_memseg *ms,void *arg) +check_socket_mem (const struct rte_memseg_list *msl,void *arg) {int32_t *socket = arg; -return *socket == ms->socket_id; +return *socket == msl->socket_id; }/* Check if memory is available on a specific socket */ static int is_mem_on_socket (int32_t socket) { -return rte_memseg_walk (check_socket_mem, &socket); +return rte_memseg_list_walk (check_socket_mem, &socket); } -struct walk_param { -void *addr; -int32_t socket; -}; -static int -find_socket (const struct rte_memseg *ms,void *arg) -{ -struct walk_param *param = arg; - -if (param->addr >= ms->addr && - param->addr <RTE_PTR_ADD (ms->addr, ms->len)) { - param->socket = ms->socket_id; -return 1 ; - } -return 0 ; -}/* * Find what socket a memory address is on. Only works for addresses within
@@ -744,10 +729,9 @@ find_socket(const struct rte_memseg *ms, void *arg)static int32_t addr_to_socket (void * addr) { -struct walk_param param = {.addr = addr, .socket =0 }; -if (rte_memseg_walk (find_socket, ¶m) >0 ) -return param.socket; -return -1 ; +const struct rte_memseg *ms =rte_mem_virt2memseg (addr,NULL ); +return ms ==NULL ?-1 : ms->socket_id; + }/* Test using rte_[c|m|zm]alloc_socket() on a specific socket */
test/test/test_memory.c +7 -3
@@ -5,8 +5,11 @@#include <stdio.h> #include <stdint.h> +#include <rte_eal.h> +#include <rte_eal_memconfig.h> #include <rte_memory.h> #include <rte_common.h> +#include <rte_memzone.h> #include "test.h"
@@ -23,12 +26,13 @@*/
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.7.4
Part of the diff is not shown here. View the raw message.
PATCH v3 50/68 eal: replace memzone array with fbarray
In reply to Anatoly BurakovIt's there, so we might as well use it. Some operations will be sped up by that.
Since we have to allocate an fbarray for memzones, we have to do it before we initialize memory subsystem, because that, in secondary processes, will (later) allocate more fbarrays than the primary process, which will result in inability to attach to memzone fbarray if we do it after the fact.
---
Notes:
v3:
- Moved earlier in patchset
- Fixed compiled issues
- Removed rte_panic() calls
drivers/net/ena/ena_ethdev.c | 10 +- lib/librte_eal/bsdapp/eal/eal.c | 14 ++- lib/librte_eal/common/eal_common_memzone.c | 109 ++++++++++++---------- lib/librte_eal/common/include/rte_eal_memconfig.h | 4 +- lib/librte_eal/common/malloc_heap.c | 4 + lib/librte_eal/linuxapp/eal/eal.c | 13 ++- test/test/test_memzone.c | 9 +- 7 files changed, 99 insertions(+), 64 deletions(-)
drivers/net/ena/ena_ethdev.c +7 -3
@@ -264,11 +264,15 @@ static const struct eth_dev_ops ena_dev_ops = {static inline int ena_cpu_to_node (int cpu) {struct rte_config *config =rte_eal_get_configuration (); +struct rte_fbarray *arr = &config->mem_config->memzones; +const struct rte_memzone *mz; -if (likely (cpu <RTE_MAX_MEMZONE )) -return config->mem_config->memzone[cpu].socket_id; +if (unlikely (cpu >=RTE_MAX_MEMZONE )) +return NUMA_NO_NODE ; -return NUMA_NO_NODE ; + mz =rte_fbarray_get (arr, cpu); + +return mz->socket_id; } static inline void ena_rx_mbuf_prepare(struct rte_mbuf *mbuf,
lib/librte_eal/bsdapp/eal/eal.c +12 -2
@@ -599,14 +599,24 @@ rte_eal_init(int argc, char **argv) } } +/* in secondary processes, memory init may allocate additional fbarrays +* not present in primary processes, so to avoid any potential issues, +* initialize memzones first. +*/ +if (rte_eal_memzone_init () <0 ) { +rte_eal_init_alert ("Cannot init memzone\n" ); + rte_errno =ENODEV ; +return -1 ; + } +if (rte_eal_memory_init () <0 ) {rte_eal_init_alert ("Cannot init memory\n" ); rte_errno =ENOMEM ;return -1 ; } -if (rte_eal_memzone_init () <0 ) { -rte_eal_init_alert ("Cannot init memzone\n" ); +if (rte_eal_malloc_heap_init () <0 ) { +rte_eal_init_alert ("Cannot init malloc heap\n" ); rte_errno =ENODEV ;return -1 ; }
lib/librte_eal/common/eal_common_memzone.c +59 -50
203 lines not on this page · raw message
lib/librte_eal/common/include/rte_eal_memconfig.h +1 -3
@@ -58,10 +58,8 @@ struct rte_mem_config {rte_rwlock_t qlock;/**< used for tailq operation for thread safe. */ rte_rwlock_t mplock;/**< only used by mempool LIB for thread-safe. */ -uint32_t memzone_cnt;/**< Number of allocated memzones */ -/* memory segments and zones */ -struct rte_memzone memzone[RTE_MAX_MEMZONE ];/**< Memzone descriptors. */ +struct rte_fbarray memzones;/**< Memzone descriptors. */ struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS ];/**< list of dynamic arrays holding memsegs */
lib/librte_eal/common/malloc_heap.c +4 -0
@@ -278,6 +278,10 @@ rte_eal_malloc_heap_init(void)if (mcfg ==NULL )return -1 ; +/* secondary process does not need to initialize anything */ +if (rte_eal_process_type () !=RTE_PROC_PRIMARY ) +return 0 ; +/* add all IOVA-contiguous areas to the heap */ return rte_memseg_contig_walk (malloc_add_seg,NULL ); }
lib/librte_eal/linuxapp/eal/eal.c +11 -2
@@ -858,6 +858,15 @@ rte_eal_init(int argc, char **argv) return -1; }#endif +/* in secondary processes, memory init may allocate additional fbarrays +* not present in primary processes, so to avoid any potential issues, +* initialize memzones first. +*/ +if (rte_eal_memzone_init () <0 ) { +rte_eal_init_alert ("Cannot init memzone\n" ); + rte_errno =ENODEV ; +return -1 ; + }if (rte_eal_memory_init () <0 ) {rte_eal_init_alert ("Cannot init memory\n" );
@@ -868,8 +877,8 @@ rte_eal_init(int argc, char **argv)/* the directories are locked during eal_hugepage_info_init */ eal_hugedirs_unlock (); -if (rte_eal_memzone_init () <0 ) { -rte_eal_init_alert ("Cannot init memzone\n" ); +if (rte_eal_malloc_heap_init () <0 ) { +rte_eal_init_alert ("Cannot init malloc heap\n" ); rte_errno =ENODEV ;return -1 ; }
test/test/test_memzone.c +5 -4
@@ -909,7 +909,7 @@ test_memzone_basic(void)const struct rte_memzone *mz;int memzone_cnt_after, memzone_cnt_expected;int memzone_cnt_before = -rte_eal_get_configuration ()->mem_config->memzone_cnt; +rte_eal_get_configuration ()->mem_config->memzones.count; memzone1 =rte_memzone_reserve (TEST_MEMZONE_NAME ("testzone1" ),100 ,SOCKET_ID_ANY ,0 );
@@ -933,7 +933,7 @@ test_memzone_basic(void) (memzone3 !=NULL ) + (memzone4 !=NULL ); memzone_cnt_after = -rte_eal_get_configuration ()->mem_config->memzone_cnt; +rte_eal_get_configuration ()->mem_config->memzones.count;if (memzone_cnt_after != memzone_cnt_expected)return -1 ;
@@ -1012,7 +1012,7 @@ test_memzone_basic(void) } memzone_cnt_after = -rte_eal_get_configuration ()->mem_config->memzone_cnt; +rte_eal_get_configuration ()->mem_config->memzones.count;if (memzone_cnt_after != memzone_cnt_before)return -1 ;
@@ -1033,7 +1033,8 @@ static inttest_memzone (void) {/* take note of how many memzones were allocated before running */ -int memzone_cnt =rte_eal_get_configuration ()->mem_config->memzone_cnt; +int memzone_cnt = +rte_eal_get_configuration ()->mem_config->memzones.count;printf ("test basic memzone API\n" );if (test_memzone_basic () <0 )
Signature · 1 line
2.7.4
Re: [PATCH v3 50/68] eal: replace memzone array with fbarray
Quoted 18 lines · Anatoly Burakov
It's there, so we might as well use it. Some operations will be sped up by that.
Since we have to allocate an fbarray for memzones, we have to do it before we initialize memory subsystem, because that, in secondary processes, will (later) allocate more fbarrays than the primary process, which will result in inability to attach to memzone fbarray if we do it after the fact.
Signed-off-by Anatoly Burakov <[email protected]>---
Notes:
v3:
- Moved earlier in patchset
- Fixed compiled issues
- Removedrte_panic()calls
[...]
Quoted 20 lines
lib/librte_eal/common/eal_common_memzone.c +4
-2@@ -28,42 +28,31 @@static inline const struct rte_memzone *memzone_lookup_thread_unsafe (const char *name) { -const struct rte_mem_config *mcfg; +struct rte_mem_config *mcfg; +struct rte_fbarray *arr;const struct rte_memzone *mz; -unsigned i =0 ; +int i =0 ;/* get pointer to global configuration */ mcfg =rte_eal_get_configuration ()->mem_config; + arr = &mcfg->memzones;/*
lib/librte_eal/common/eal_common_memzone.c line 46
Quoted 10 lines
lib/librte_eal/common/eal_common_memzone.c +3
-4* the algorithm is not optimal (linear), but there are few * zones and this function should be called at init only */ -for (i =0 ; i <RTE_MAX_MEMZONE ; i++) { - mz = &mcfg->memzone[i]; -if (mz->addr !=NULL && !strncmp (name, mz->name,RTE_MEMZONE_NAMESIZE )) -return &mcfg->memzone[i]; + i =rte_fbarray_find_next_used (arr,0 ); +while (i >=0 ) { + mz =rte_fbarray_get (arr, i++);
^^^^^^^^
As discussed offline, this needs to be changed. Double increment of 'i' leading to skips over lookup.
lib/librte_eal/common/eal_common_memzone.c line 55
Quoted 9 lines
lib/librte_eal/common/eal_common_memzone.c +4
-0+if (mz->addr !=NULL && + !strncmp (name, mz->name,RTE_MEMZONE_NAMESIZE )) +return mz; + i =rte_fbarray_find_next_used (arr, i +1 ); }return NULL ; }
[..]
-
Shreyansh
PATCH v3 51/68 eal: add support for mapping hugepages at runtime
In reply to Anatoly BurakovNothing uses this code yet. The bulk of it is copied from old memory allocation code (linuxapp eal_memory.c). We provide an EAL-internal API to allocate either one page or multiple pages, guaranteeing that we'll get contiguous VA for all of the pages that we requested.
Not supported on FreeBSD.
Locking is done via fcntl() because that way, when it comes to taking out write locks or unlocking on deallocation, we don't have to keep original fd's around. Plus, using fcntl() gives us ability to lock parts of a file, which is useful for single-file segments, which are coming down the line.
---
Notes:
v3:
- Compile fixes for various platforms
- Split single file segments stuff into separate commit
v3:
- Split single file segments into separate patch
- Added missing FreeBSD implementation
- Removed rte_panic when unable to free page
v3:
- Added single file segments functionality in this commit, instead of later commits
lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/bsdapp/eal/eal_memalloc.c | 26 ++ lib/librte_eal/bsdapp/eal/meson.build | 1 + lib/librte_eal/common/eal_memalloc.h | 31 +++ lib/librte_eal/linuxapp/eal/Makefile | 2 + lib/librte_eal/linuxapp/eal/eal_memalloc.c | 429 +++++++++++++++++++++++++++++ lib/librte_eal/linuxapp/eal/meson.build | 1 + 7 files changed, 491 insertions(+) create mode 100644 lib/librte_eal/bsdapp/eal/eal_memalloc.c create mode 100644 lib/librte_eal/common/eal_memalloc.h create mode 100644 lib/librte_eal/linuxapp/eal/eal_memalloc.c
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -29,6 +29,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_memory.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_hugepage_info.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_thread.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_debug.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_memalloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_lcore.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_timer.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_interrupts.c
lib/librte_eal/bsdapp/eal/eal_memalloc.c new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2017-2018 Intel Corporation +*/ + +#include <inttypes.h> + +#include <rte_log.h> +#include <rte_memory.h> + +#include "eal_memalloc.h" + +int +eal_memalloc_alloc_seg_bulk(struct rte_memseg **ms __rte_unused, + int __rte_unused n_segs, size_t __rte_unused page_sz, + int __rte_unused socket, bool __rte_unused exact) +{ +RTE_LOG (ERR ,EAL ,"Memory hotplug not supported on FreeBSD\n" ); +return -1 ; +} + +struct rte_memseg * +eal_memalloc_alloc_seg(size_t __rte_unused page_sz, int __rte_unused socket) +{ +RTE_LOG (ERR ,EAL ,"Memory hotplug not supported on FreeBSD\n" ); +return NULL ; +}
lib/librte_eal/bsdapp/eal/meson.build +1 -0
@@ -8,6 +8,7 @@ env_sources = files('eal_alarm.c', 'eal_hugepage_info.c', 'eal_interrupts.c', 'eal_lcore.c', + 'eal_memalloc.c', 'eal_thread.c', 'eal_timer.c', 'eal.c',
lib/librte_eal/common/eal_memalloc.h new file +31 -0
@@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause +* Copyright(c) 2017-2018 Intel Corporation +*/ + +#ifndef EAL_MEMALLOC_H +#define EAL_MEMALLOC_H + +#include <stdbool.h> + +#include <rte_memory.h> + +/* +* Allocate segment of specified page size. +*/ +struct rte_memseg * +eal_memalloc_alloc_seg (size_t page_sz,int socket); + +/* +* Allocate `n_segs` segments. +* +* Note: `ms` can be NULL. +* +* Note: it is possible to request best-effort allocation by setting `exact` to +* `false`, in which case allocator will return however many pages it managed to +* allocate successfully. +*/ +int +eal_memalloc_alloc_seg_bulk (struct rte_memseg **ms,int n_segs,size_t page_sz, +int socket,bool exact); + +#endif // EAL_MEMALLOC_H
lib/librte_eal/linuxapp/eal/Makefile +2 -0
@@ -36,6 +36,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_thread.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_log.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio_mp_sync.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_memalloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_debug.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c
@@ -82,6 +83,7 @@ CFLAGS_eal_interrupts.o := -D_GNU_SOURCE CFLAGS_eal_vfio_mp_sync.o := -D_GNU_SOURCE CFLAGS_eal_timer.o := -D_GNU_SOURCE CFLAGS_eal_lcore.o := -D_GNU_SOURCE +CFLAGS_eal_memalloc.o := -D_GNU_SOURCE CFLAGS_eal_thread.o := -D_GNU_SOURCE CFLAGS_eal_log.o := -D_GNU_SOURCE CFLAGS_eal_common_log.o := -D_GNU_SOURCE
lib/librte_eal/linuxapp/eal/eal_memalloc.c new file +429 -0
429 lines not on this page · raw message
lib/librte_eal/linuxapp/eal/meson.build +1 -0
@@ -10,6 +10,7 @@ env_sources = files('eal_alarm.c', 'eal_debug.c', 'eal_hugepage_info.c', 'eal_interrupts.c', + 'eal_memalloc.c', 'eal_lcore.c', 'eal_log.c', 'eal_thread.c',
Signature · 1 line
2.7.4
PATCH v3 52/68 eal: add support for unmapping pages at runtime
In reply to Anatoly BurakovThis isn't used anywhere yet, but the support is now there. Also, adding cleanup to allocation procedures, so that if we fail to allocate everything we asked for, we can free all of it back.
--- lib/librte_eal/bsdapp/eal/eal_memalloc.c | 15 +++ lib/librte_eal/common/eal_memalloc.h | 14 +++ lib/librte_eal/linuxapp/eal/eal_memalloc.c | 149 ++++++++++++++++++++++++++++- 3 files changed, 177 insertions(+), 1 deletion(-)
lib/librte_eal/bsdapp/eal/eal_memalloc.c +15 -0
@@ -24,3 +24,18 @@ eal_memalloc_alloc_seg(size_t __rte_unused page_sz, int __rte_unused socket)RTE_LOG (ERR ,EAL ,"Memory hotplug not supported on FreeBSD\n" );return NULL ; } + +int +eal_memalloc_free_seg(struct rte_memseg *ms __rte_unused) +{ +RTE_LOG (ERR ,EAL ,"Memory hotplug not supported on FreeBSD\n" ); +return -1 ; +} + +int +eal_memalloc_free_seg_bulk(struct rte_memseg **ms __rte_unused, + int n_segs __rte_unused) +{ +RTE_LOG (ERR ,EAL ,"Memory hotplug not supported on FreeBSD\n" ); +return -1 ; +}
lib/librte_eal/common/eal_memalloc.h +14 -0
@@ -28,4 +28,18 @@ int eal_memalloc_alloc_seg_bulk(struct rte_memseg **ms, int n_segs, size_t page_sz, int socket, bool exact); +/* +* Deallocate segment +*/ +int +eal_memalloc_free_seg (struct rte_memseg *ms); + +/* +* Deallocate `n_segs` segments. Returns 0 on successful deallocation of all +* segments, returns -1 on error. Any segments that could have been deallocated, +* will be deallocated even in case of error. +*/ +int +eal_memalloc_free_seg_bulk (struct rte_memseg **ms,int n_segs); +#endif // EAL_MEMALLOC_H
lib/librte_eal/linuxapp/eal/eal_memalloc.c +148 -1
183 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v3 53/68 eal: add "single file segments" command-line option
In reply to Anatoly BurakovCurrently, DPDK stores all pages as separate files in hugetlbfs. This option will allow storing all pages in one file (one file per memseg list).
We do this by using fallocate() calls on FreeBSD, however this is only supported on fairly recent (4.3+) kernels, so ftruncate() fallback is provided to grow (but not shrink) hugepage files. Naming scheme is deterministic, so both primary and secondary processes will be able to easily map needed files and offsets.
For multi-file segments, we can close fd's right away. For single-file segments, we can reuse the same fd and reduce the amount of fd's needed to map/use hugepages. However, we need to store the fd's somewhere, so we add a tailq.
---
Notes:
v3:
- Split this change into a separate patch
- Provide more explanation as to how it works
lib/librte_eal/common/eal_common_options.c | 4 + lib/librte_eal/common/eal_internal_cfg.h | 4 + lib/librte_eal/common/eal_options.h | 2 + lib/librte_eal/linuxapp/eal/eal.c | 1 + lib/librte_eal/linuxapp/eal/eal_memalloc.c | 337 ++++++++++++++++++++++++----- 5 files changed, 297 insertions(+), 51 deletions(-)
lib/librte_eal/common/eal_common_options.c +4 -0
@@ -74,6 +74,7 @@ eal_long_options[] = { {OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM }, {OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM }, {OPT_LEGACY_MEM, 0, NULL, OPT_LEGACY_MEM_NUM }, + {OPT_SINGLE_FILE_SEGMENTS, 0, NULL, OPT_SINGLE_FILE_SEGMENTS_NUM}, {0, 0, NULL, 0 } };
@@ -1188,6 +1189,9 @@ eal_parse_common_option(int opt, const char *optarg,case OPT_LEGACY_MEM_NUM : conf->legacy_mem =1 ;break ; +case OPT_SINGLE_FILE_SEGMENTS_NUM : + conf->single_file_segments =1 ; +break ;/* don't know what to do, leave this to caller */ default :
lib/librte_eal/common/eal_internal_cfg.h +4 -0
@@ -51,6 +51,10 @@ struct internal_config {/**< true to enable legacy memory behavior (no dynamic allocation, * IOVA-contiguous segments). */ +volatile unsigned single_file_segments; +/**< true if storing all pages within single files (per-page-size, +* per-node) non-legacy mode only. +*/ volatile int syslog_facility;/**< facility passed to openlog() */ /** default interrupt mode for VFIO */ volatile enum rte_intr_mode vfio_intr_mode;
lib/librte_eal/common/eal_options.h +2 -0
@@ -57,6 +57,8 @@ enum {OPT_VMWARE_TSC_MAP_NUM , #define OPT_LEGACY_MEM "legacy-mem"OPT_LEGACY_MEM_NUM , +#define OPT_SINGLE_FILE_SEGMENTS "single-file-segments" +OPT_SINGLE_FILE_SEGMENTS_NUM , OPT_LONG_MAX_NUM };
lib/librte_eal/linuxapp/eal/eal.c +1 -0
@@ -349,6 +349,7 @@ eal_usage(const char *prgname)" --" OPT_CREATE_UIO_DEV " Create /dev/uioX (usually done by hotplug)\n" " --" OPT_VFIO_INTR " Interrupt mode for VFIO (legacy|msi|msix)\n" " --" OPT_LEGACY_MEM " Legacy memory mode (no dynamic allocation, contiguous segments)\n" +" --" OPT_SINGLE_FILE_SEGMENTS " Put all hugepage memory in single files\n" "\n");/* Allow the application to print its usage message too if hook is set */ if ( rte_application_usage_hook ) {
lib/librte_eal/linuxapp/eal/eal_memalloc.c +286 -51
392 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v3 54/68 eal: add API to check if memory is contiguous
In reply to Anatoly BurakovFor 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.
---
Notes:
v3:
- Moved this earlier in the patchset
- Add support for non-hugepage memory
- Fix handling of IOVA as VA mode
v3:
- Add support for non-hugepage memory
- Support non-page-sized segments
lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/eal_common_memalloc.c | 90 +++++++++++++++++++++++++++++ lib/librte_eal/common/eal_memalloc.h | 10 ++++ lib/librte_eal/common/malloc_elem.c | 40 +------------ lib/librte_eal/common/meson.build | 1 + lib/librte_eal/linuxapp/eal/Makefile | 1 + 6 files changed, 106 insertions(+), 37 deletions(-) create mode 100644 lib/librte_eal/common/eal_common_memalloc.c
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -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
lib/librte_eal/common/eal_common_memalloc.c new file +90 -0
90 lines not on this page · raw message
lib/librte_eal/common/eal_memalloc.h +10 -0
@@ -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,13 @@ 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
lib/librte_eal/common/malloc_elem.c +3 -37
@@ -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); }/*
lib/librte_eal/common/meson.build +1 -0
@@ -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',
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -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
Signature · 1 line
2.7.4
PATCH v3 55/68 eal: prepare memseg lists for multiprocess sync
In reply to Anatoly BurakovIn preparation for implementing multiprocess support, we are adding a version number to memseg lists. We will not need any locks, because memory hotplug will have a global lock (so any time memory map and thus version number might change, we will already be holding a lock).
There are two ways of implementing multiprocess support for memory
hotplug: either all information about mapped memory is shared between processes, and secondary processes simply attempt to map/unmap memory based on requests from the primary, or secondary processes store their own maps and only check if they are in sync with the primary process' maps.
This implementation will opt for the latter option: primary process shared mappings will be authoritative, and each secondary process will use its own interal view of mapped memory, and will attempt to synchronize on these mappings using versioning.
Under this model, only primary process will decide which pages get mapped, and secondary processes will only copy primary's page maps and get notified of the changes via IPC mechanism (coming in later commits).
---
Notes:
v3:
- Removed per-list locks as we're using global hotplug lock
lib/librte_eal/bsdapp/eal/eal_memalloc.c | 7 + lib/librte_eal/common/eal_memalloc.h | 4 + lib/librte_eal/common/include/rte_eal_memconfig.h | 1 + lib/librte_eal/linuxapp/eal/eal_memalloc.c | 250 ++++++++++++++++++++++ 4 files changed, 262 insertions(+)
lib/librte_eal/bsdapp/eal/eal_memalloc.c +7 -0
@@ -39,3 +39,10 @@ eal_memalloc_free_seg_bulk(struct rte_memseg **ms __rte_unused,RTE_LOG (ERR ,EAL ,"Memory hotplug not supported on FreeBSD\n" );return -1 ; } + +int +eal_memalloc_sync_with_primary (void ) +{ +RTE_LOG (ERR ,EAL ,"Memory hotplug not supported on FreeBSD\n" ); +return -1 ; +}
lib/librte_eal/common/eal_memalloc.h +4 -0
@@ -52,4 +52,8 @@ bool eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start, size_t len); +/* synchronize local memory map to primary process */ +int +eal_memalloc_sync_with_primary (void ); +#endif // EAL_MEMALLOC_H
lib/librte_eal/common/include/rte_eal_memconfig.h +1 -0
@@ -32,6 +32,7 @@ struct rte_memseg_list { };int socket_id;/**< Socket ID for all memsegs in this list. */ uint64_t page_sz;/**< Page size for all memsegs in this list. */ +volatile uint32_t version;/**< version number for multiprocess sync. */ struct rte_fbarray memseg_arr; };
lib/librte_eal/linuxapp/eal/eal_memalloc.c +250 -0
272 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v3 56/68 eal: read hugepage counts from node-specific sysfs path
In reply to Anatoly BurakovFor non-legacy memory init mode, instead of looking at generic sysfs path, look at sysfs paths pertaining to each NUMA node for hugepage counts. Note that per-NUMA node path does not provide information regarding reserved pages, so we might not get the best info from these paths, but this saves us from the whole mapping/remapping business before we're actually able to tell which page is on which socket, because we no longer require our memory to be physically contiguous.
Legacy memory init will not use this.
--- lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 80 +++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 6 deletions(-)
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +74 -6
@@ -31,6 +31,7 @@#include "eal_filesystem.h" static const char sys_dir_path[] ="/sys/kernel/mm/hugepages" ; +static const char sys_pages_numa_dir_path[] ="/sys/devices/system/node" ;/* this function is only called from eal_hugepage_info_init which itself * is only called from a primary process */
@@ -71,6 +72,45 @@ get_num_hugepages(const char *subdir)return num_pages; } +static uint32_t +get_num_hugepages_on_node (const char *subdir,unsigned int socket) +{ +char path[PATH_MAX ], socketpath[PATH_MAX ]; +DIR *socketdir; +unsigned long num_pages =0 ; +const char *nr_hp_file ="free_hugepages" ; + +snprintf (socketpath,sizeof (socketpath),"%s/node%u/hugepages" , + sys_pages_numa_dir_path, socket); + + socketdir =opendir (socketpath); +if (socketdir) { +/* Keep calm and carry on */ +closedir (socketdir); + }else { +/* Can't find socket dir, so ignore it */ +return 0 ; + } + +snprintf (path,sizeof (path),"%s/%s/%s" , + socketpath, subdir, nr_hp_file); +if (eal_parse_sysfs_value (path, &num_pages) <0 ) +return 0 ; + +if (num_pages ==0 ) +RTE_LOG (WARNING ,EAL ,"No free hugepages reported in %s\n" , + subdir); + +/* +* we want to return a uint32_t and more than this looks suspicious +* anyway ... +*/ +if (num_pages >UINT32_MAX ) + num_pages =UINT32_MAX ; + +return num_pages; +} +static uint64_t get_default_hp_size (void ) {
@@ -269,7 +309,7 @@ eal_hugepage_info_init(void) {const char dirent_start_text[] ="hugepages-" ;const size_t dirent_start_len =sizeof (dirent_start_text) -1 ; -unsigned i, num_sizes =0 ; +unsigned int i, total_pages, num_sizes =0 ;DIR *dir;struct dirent *dirent;
@@ -323,9 +363,28 @@ eal_hugepage_info_init(void)if (clear_hugedir (hpi->hugedir) ==-1 )break ; -/* for now, put all pages into socket 0, -* later they will be sorted */ - hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name); +/* +* first, try to put all hugepages into relevant sockets, but +* if first attempts fails, fall back to collecting all pages +* in one socket and sorting them later +*/ + total_pages =0 ; +/* we also don't want to do this for legacy init */ +if (!internal_config.legacy_mem) +for (i =0 ; i <rte_socket_count (); i++) { +int socket =rte_socket_id_by_idx (i); +unsigned int num_pages = +get_num_hugepages_on_node ( + dirent->d_name, socket); + hpi->num_pages[socket] = num_pages; + total_pages += num_pages; + } +/* +* we failed to sort memory from the get go, so fall +* back to old way +*/ +if (total_pages ==0 ) + hpi->num_pages[0 ] =get_num_hugepages (dirent->d_name);#ifndef RTE_ARCH_64 /* for 32-bit systems, limit number of hugepages to
@@ -349,10 +408,19 @@ eal_hugepage_info_init(void) sizeof(internal_config.hugepage_info[0]), compare_hpi);/* now we have all info, check we have at least one valid size */ -for (i =0 ; i < num_sizes; i++) +for (i =0 ; i < num_sizes; i++) { +/* pages may no longer all be on socket 0, so check all */ +unsigned int j, num_pages =0 ; + +for (j =0 ; j <RTE_MAX_NUMA_NODES ; j++) { +struct hugepage_info *hpi = + &internal_config.hugepage_info[i]; + num_pages += hpi->num_pages[j]; + }if (internal_config.hugepage_info[i].hugedir !=NULL && - internal_config.hugepage_info[i].num_pages[0 ] >0 ) + num_pages >0 )return 0 ; + }/* no valid hugepage mounts available, return error */ return -1 ;
Signature · 1 line
2.7.4
PATCH v3 57/68 eal: make use of memory hotplug for init
In reply to Anatoly BurakovAdd a new (non-legacy) memory init path for EAL. It uses the new memory hotplug facilities.
If no -m or --socket-mem switches were specified, the new init will not allocate anything, whereas if those switches were passed, appropriate amounts of pages would be requested, just like for legacy init.
Allocated pages will be physically discontiguous (or rather, they're not guaranteed to be physically contiguous - they may still be so by accident) unless RTE_IOVA_VA mode is used.
--- lib/librte_eal/linuxapp/eal/eal_memory.c | 62 ++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-)
lib/librte_eal/linuxapp/eal/eal_memory.c +59 -3
@@ -40,6 +40,7 @@#include <rte_string_fns.h> #include "eal_private.h" +#include "eal_memalloc.h" #include "eal_internal_cfg.h" #include "eal_filesystem.h" #include "eal_hugepages.h"
@@ -1600,6 +1601,61 @@ eal_legacy_hugepage_init(void)return -1 ; } +static int +eal_hugepage_init (void ) +{ +struct hugepage_info used_hp[MAX_HUGEPAGE_SIZES ]; +uint64_t memory[RTE_MAX_NUMA_NODES ]; +int hp_sz_idx, socket_id; + +test_phys_addrs_available (); + +memset (used_hp,0 ,sizeof (used_hp)); + +for (hp_sz_idx =0 ; + hp_sz_idx < (int ) internal_config.num_hugepage_sizes; + hp_sz_idx++) { +/* also initialize used_hp hugepage sizes in used_hp */ +struct hugepage_info *hpi; + hpi = &internal_config.hugepage_info[hp_sz_idx]; + used_hp[hp_sz_idx].hugepage_sz = hpi->hugepage_sz; + } + +/* make a copy of socket_mem, needed for balanced allocation. */ +for (hp_sz_idx =0 ; hp_sz_idx <RTE_MAX_NUMA_NODES ; hp_sz_idx++) + memory[hp_sz_idx] = internal_config.socket_mem[hp_sz_idx]; + +/* calculate final number of pages */ +if (calc_num_pages_per_socket (memory, + internal_config.hugepage_info, used_hp, + internal_config.num_hugepage_sizes) <0 ) +return -1 ; + +for (hp_sz_idx =0 ; + hp_sz_idx < (int )internal_config.num_hugepage_sizes; + hp_sz_idx++) { +for (socket_id =0 ; socket_id <RTE_MAX_NUMA_NODES ; + socket_id++) { +struct hugepage_info *hpi = &used_hp[hp_sz_idx]; +unsigned int num_pages = hpi->num_pages[socket_id]; +int num_pages_alloc; + +if (num_pages ==0 ) +continue ; + +RTE_LOG (DEBUG ,EAL ,"Allocating %u pages of size %" PRIu64"M on socket %i\n" , + num_pages, hpi->hugepage_sz >>20 , socket_id); + + num_pages_alloc =eal_memalloc_alloc_seg_bulk (NULL , + num_pages, hpi->hugepage_sz, + socket_id, true); +if (num_pages_alloc <0 ) +return -1 ; + } + } +return 0 ; +} +/* * uses fstat to report the size of a file on disk */
@@ -1722,9 +1778,9 @@ eal_legacy_hugepage_attach(void)int rte_eal_hugepage_init (void ) { -if (internal_config.legacy_mem) -return eal_legacy_hugepage_init (); -return -1 ; +return internal_config.legacy_mem ? +eal_legacy_hugepage_init () : +eal_hugepage_init (); }int
Signature · 1 line
2.7.4
PATCH v3 58/68 eal: share hugepage info primary and secondary
In reply to Anatoly BurakovSince we are going to need to map hugepages in both primary and secondary processes, we need to know where we should look for hugetlbfs mountpoints. So, share those with secondary processes, and map them on init.
--- lib/librte_eal/bsdapp/eal/eal.c | 19 ++-- lib/librte_eal/bsdapp/eal/eal_hugepage_info.c | 56 +++++++++-- lib/librte_eal/bsdapp/eal/eal_memory.c | 21 +--- lib/librte_eal/common/eal_common_options.c | 5 +- lib/librte_eal/common/eal_filesystem.h | 17 ++++ lib/librte_eal/common/eal_hugepages.h | 10 +- lib/librte_eal/common/eal_internal_cfg.h | 2 +- lib/librte_eal/linuxapp/eal/eal.c | 18 ++-- lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 121 ++++++++++++++++++++---- lib/librte_eal/linuxapp/eal/eal_memory.c | 15 +-- 10 files changed, 217 insertions(+), 67 deletions(-)
lib/librte_eal/bsdapp/eal/eal.c +12 -7
@@ -289,7 +289,7 @@ eal_get_hugepage_mem_size(void)for (i =0 ; i < internal_config.num_hugepage_sizes; i++) {struct hugepage_info *hpi = &internal_config.hugepage_info[i]; -if (hpi->hugedir !=NULL ) { +if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 ) {for (j =0 ; j <RTE_MAX_NUMA_NODES ; j++) { size += hpi->hugepage_sz * hpi->num_pages[j]; }
@@ -561,12 +561,17 @@ rte_eal_init(int argc, char **argv)/* autodetect the iova mapping mode (default is iova_pa) */ rte_eal_get_configuration ()->iova_mode =rte_bus_get_iommu_class (); -if (internal_config.no_hugetlbfs ==0 && -eal_hugepage_info_init () <0 ) { -rte_eal_init_alert ("Cannot get hugepage information." ); - rte_errno =EACCES ; -rte_atomic32_clear (&run_once); -return -1 ; +if (internal_config.no_hugetlbfs ==0 ) { +/* rte_config isn't initialized yet */ + ret = internal_config.process_type ==RTE_PROC_PRIMARY ? +eal_hugepage_info_init () : +eal_hugepage_info_read (); +if (ret <0 ) { +rte_eal_init_alert ("Cannot get hugepage information." ); + rte_errno =EACCES ; +rte_atomic32_clear (&run_once); +return -1 ; + } }if (internal_config.memory ==0 && internal_config.force_sockets ==0 ) {
lib/librte_eal/bsdapp/eal/eal_hugepage_info.c +49 -7
94 lines not on this page · raw message
lib/librte_eal/bsdapp/eal/eal_memory.c +2 -19
@@ -240,23 +240,10 @@ intrte_eal_hugepage_attach (void) {const struct hugepage_info *hpi; -int fd_hugepage_info, fd_hugepage =-1 ; +int fd_hugepage =-1 ;unsigned int i; -/* Obtain a file descriptor for hugepage_info */ - fd_hugepage_info =open (eal_hugepage_info_path (),O_RDONLY ); -if (fd_hugepage_info <0 ) { -RTE_LOG (ERR ,EAL ,"Could not open %s\n" ,eal_hugepage_info_path ()); -return -1 ; - } - -/* Map the shared hugepage_info into the process address spaces */ - hpi =mmap (NULL ,sizeof (internal_config.hugepage_info), -PROT_READ ,MAP_PRIVATE , fd_hugepage_info,0 ); -if (hpi ==MAP_FAILED ) { -RTE_LOG (ERR ,EAL ,"Could not mmap %s\n" ,eal_hugepage_info_path ()); - goto error; - } + hpi = &internal_config.hugepage_info[0 ];for (i =0 ; i < internal_config.num_hugepage_sizes; i++) {const struct hugepage_info *cur_hpi = &hpi[i];
@@ -286,13 +273,9 @@ rte_eal_hugepage_attach(void) }/* hugepage_info is no longer required */ -munmap ((void *)(uintptr_t )hpi,sizeof (internal_config.hugepage_info)); -close (fd_hugepage_info);return 0 ; error: -if (fd_hugepage_info >=0 ) -close (fd_hugepage_info);if (fd_hugepage >=0 )close (fd_hugepage);return -1 ;
lib/librte_eal/common/eal_common_options.c +4 -1
@@ -179,8 +179,11 @@ eal_reset_internal_config(struct internal_config *internal_cfg)for (i =0 ; i <RTE_MAX_NUMA_NODES ; i++) internal_cfg->socket_mem[i] =0 ;/* zero out hugedir descriptors */ -for (i =0 ; i <MAX_HUGEPAGE_SIZES ; i++) +for (i =0 ; i <MAX_HUGEPAGE_SIZES ; i++) { +memset (&internal_cfg->hugepage_info[i],0 , +sizeof (internal_cfg->hugepage_info[0 ])); internal_cfg->hugepage_info[i].lock_descriptor =-1 ; + } internal_cfg->base_virtaddr =0 ; internal_cfg->syslog_facility =LOG_DAEMON ;
lib/librte_eal/common/eal_filesystem.h +17 -0
@@ -85,6 +85,23 @@ eal_hugepage_info_path(void)return buffer; } +/** Path of hugepage info file. */ +#define HUGEPAGE_FILE_FMT "%s/.%s_hugepage_file" + +static inline const char * +eal_hugepage_file_path (void ) +{ +static char buffer[PATH_MAX ];/* static so auto-zeroed */ +const char *directory = default_config_dir; +const char *home_dir =getenv ("HOME" ); + +if (getuid () !=0 && home_dir !=NULL ) + directory = home_dir; +snprintf (buffer,sizeof (buffer) -1 ,HUGEPAGE_FILE_FMT , directory, + internal_config.hugefile_prefix); +return buffer; +} +/** String format for hugepage map files. */ #define HUGEFILE_FMT "%s/%smap_%d"#define TEMP_HUGEFILE_FMT "%s/%smap_temp_%d"
lib/librte_eal/common/eal_hugepages.h +8 -2
@@ -26,9 +26,15 @@ struct hugepage_file { };/** -* Read the information from linux on what hugepages are available -* for the EAL to use +* Read the information on what hugepages are available for the EAL to use, +* clearing out any unused ones. */ int eal_hugepage_info_init (void ); +/** +* Read whatever information primary process has shared about hugepages into +* secondary process. +*/ +int eal_hugepage_info_read (void ); +#endif /* EAL_HUGEPAGES_H */
lib/librte_eal/common/eal_internal_cfg.h +1 -1
@@ -21,7 +21,7 @@*/ struct hugepage_info {uint64_t hugepage_sz;/**< size of a huge page */ -const char *hugedir;/**< dir where hugetlbfs is mounted */ +char hugedir[PATH_MAX ];/**< dir where hugetlbfs is mounted */ uint32_t num_pages[RTE_MAX_NUMA_NODES ];/**< number of hugepages of that size on each socket */ int lock_descriptor;/**< file descriptor for hugepage dir */
lib/librte_eal/linuxapp/eal/eal.c +11 -7
@@ -807,13 +807,17 @@ rte_eal_init(int argc, char **argv) "KNI module inserted\n"); } -if (internal_config.no_hugetlbfs ==0 && - internal_config.process_type !=RTE_PROC_SECONDARY && -eal_hugepage_info_init () <0 ) { -rte_eal_init_alert ("Cannot get hugepage information." ); - rte_errno =EACCES ; -rte_atomic32_clear (&run_once); -return -1 ; +if (internal_config.no_hugetlbfs ==0 ) { +/* rte_config isn't initialized yet */ + ret = internal_config.process_type ==RTE_PROC_PRIMARY ? +eal_hugepage_info_init () : +eal_hugepage_info_read (); +if (ret <0 ) { +rte_eal_init_alert ("Cannot get hugepage information." ); + rte_errno =EACCES ; +rte_atomic32_clear (&run_once); +return -1 ; + } }if (internal_config.memory ==0 && internal_config.force_sockets ==0 ) {
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c +105 -16
170 lines not on this page · raw message
lib/librte_eal/linuxapp/eal/eal_memory.c +8 -7
@@ -1060,7 +1060,7 @@ get_socket_mem_size(int socket)for (i =0 ; i < internal_config.num_hugepage_sizes; i++){struct hugepage_info *hpi = &internal_config.hugepage_info[i]; -if (hpi->hugedir !=NULL ) +if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 ) size += hpi->hugepage_sz * hpi->num_pages[socket]; }
@@ -1160,7 +1160,8 @@ calc_num_pages_per_socket(uint64_t * memory,for (socket =0 ; socket <RTE_MAX_NUMA_NODES && total_mem !=0 ; socket++) {/* skips if the memory on specific socket wasn't requested */ for (i =0 ; i < num_hp_info && memory[socket] !=0 ; i++){ - hp_used[i].hugedir = hp_info[i].hugedir; +snprintf (hp_used[i].hugedir,sizeof (hp_used[i].hugedir), +"%s" , hp_info[i].hugedir); hp_used[i].num_pages[socket] =RTE_MIN ( memory[socket] / hp_info[i].hugepage_sz, hp_info[i].num_pages[socket]);
@@ -1235,7 +1236,7 @@ eal_get_hugepage_mem_size(void)for (i =0 ; i < internal_config.num_hugepage_sizes; i++) {struct hugepage_info *hpi = &internal_config.hugepage_info[i]; -if (hpi->hugedir !=NULL ) { +if (strnlen (hpi->hugedir,sizeof (hpi->hugedir)) !=0 ) {for (j =0 ; j <RTE_MAX_NUMA_NODES ; j++) { size += hpi->hugepage_sz * hpi->num_pages[j]; }
@@ -1508,7 +1509,7 @@ eal_legacy_hugepage_init(void) }/* create shared memory */ - hugepage =create_shared_memory (eal_hugepage_info_path (), + hugepage =create_shared_memory (eal_hugepage_file_path (), nr_hugefiles *sizeof (struct hugepage_file ));if (hugepage ==NULL ) {
@@ -1693,16 +1694,16 @@ eal_legacy_hugepage_attach(void)test_phys_addrs_available (); - fd_hugepage =open (eal_hugepage_info_path (),O_RDONLY ); + fd_hugepage =open (eal_hugepage_file_path (),O_RDONLY );if (fd_hugepage <0 ) { -RTE_LOG (ERR ,EAL ,"Could not open %s\n" ,eal_hugepage_info_path ()); +RTE_LOG (ERR ,EAL ,"Could not open %s\n" ,eal_hugepage_file_path ()); goto error; } size =getFileSize (fd_hugepage); hp =mmap (NULL , size,PROT_READ ,MAP_PRIVATE , fd_hugepage,0 );if (hp ==MAP_FAILED ) { -RTE_LOG (ERR ,EAL ,"Could not mmap %s\n" ,eal_hugepage_info_path ()); +RTE_LOG (ERR ,EAL ,"Could not mmap %s\n" ,eal_hugepage_file_path ()); goto error; }
Signature · 1 line
2.7.4
PATCH v3 59/68 eal: add secondary process init with memory hotplug
In reply to Anatoly BurakovSecondary initialization will just sync memory map with primary process.
---
Notes:
v3:
- Improved handling of EAL hugepage info
lib/librte_eal/common/eal_common_memory.c | 1 + lib/librte_eal/linuxapp/eal/eal_memory.c | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-)
lib/librte_eal/common/eal_common_memory.c +1 -0
@@ -20,6 +20,7 @@#include <rte_errno.h> #include <rte_log.h> +#include "eal_memalloc.h" #include "eal_private.h" #include "eal_internal_cfg.h"
lib/librte_eal/linuxapp/eal/eal_memory.c +15 -3
@@ -1776,6 +1776,18 @@ eal_legacy_hugepage_attach(void)return -1 ; } +static int +eal_hugepage_attach (void ) +{ +if (eal_memalloc_sync_with_primary ()) { +RTE_LOG (ERR ,EAL ,"Could not map memory from primary process\n" ); +if (aslr_enabled () >0 ) +RTE_LOG (ERR ,EAL ,"It is recommended to disable ASLR in the kernel and retry running both primary and secondary processes\n" ); +return -1 ; + } +return 0 ; +} +int rte_eal_hugepage_init (void ) {
@@ -1787,9 +1799,9 @@ rte_eal_hugepage_init(void)int rte_eal_hugepage_attach (void ) { -if (internal_config.legacy_mem) -return eal_legacy_hugepage_attach (); -return -1 ; +return internal_config.legacy_mem ? +eal_legacy_hugepage_attach () : +eal_hugepage_attach (); }int
Signature · 1 line
2.7.4
PATCH v3 60/68 eal: enable memory hotplug support in rte_malloc
In reply to Anatoly BurakovThis set of changes enables rte_malloc to allocate and free memory as needed. Currently, it is disabled because legacy mem mode is enabled unconditionally.
The way it works is, first malloc checks if there is enough memory already allocated to satisfy user's request. If there isn't, we try and allocate more memory. The reverse happens with free - we free an element, check its size (including free element merging due to adjacency) and see if it's bigger than hugepage size and that its start and end span a hugepage or more. Then we remove the area from malloc heap (adjusting element lengths where appropriate), and deallocate the page.
For legacy mode, runtime alloc/free of pages is disabled.
It is worth noting that memseg lists are being sorted by page size, and that we try our best to satisfy user's request. That is, if the user requests an element from a 2MB page memory, we will check if we can satisfy that request from existing memory, if not we try and allocate more 2MB pages. If that fails and user also specified a "size is hint" flag, we then check other page sizes and try to allocate from there. If that fails too, then, depending on flags, we may try allocating from other sockets. In other words, we try our best to give the user what they asked for, but going to other sockets is last resort - first we try to allocate more memory on the same socket.
---
Notes:
v3:
- Compile fixes
lib/librte_eal/common/eal_common_memzone.c | 26 +-- lib/librte_eal/common/malloc_elem.c | 86 +++++++ lib/librte_eal/common/malloc_elem.h | 3 + lib/librte_eal/common/malloc_heap.c | 347 ++++++++++++++++++++++++++++- lib/librte_eal/common/malloc_heap.h | 4 +- lib/librte_eal/common/rte_malloc.c | 31 +-- 6 files changed, 433 insertions(+), 64 deletions(-)
lib/librte_eal/common/eal_common_memzone.c +3 -23
@@ -94,7 +94,7 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len,struct rte_mem_config *mcfg;struct rte_fbarray *arr;size_t requested_len; -int socket, i, mz_idx; +int mz_idx;/* get pointer to global configuration */ mcfg =rte_eal_get_configuration ()->mem_config;
@@ -179,29 +179,9 @@ memzone_reserve_aligned_thread_unsafe(const char *name, size_t len, } } -if (socket_id ==SOCKET_ID_ANY ) - socket =malloc_get_numa_socket (); -else - socket = socket_id; -/* allocate memory on heap */ -void *mz_addr =malloc_heap_alloc (&mcfg->malloc_heaps[socket],NULL , - requested_len, flags, align, bound, contig); - -if ((mz_addr ==NULL ) && (socket_id ==SOCKET_ID_ANY )) { -/* try other heaps */ -for (i =0 ; i <RTE_MAX_NUMA_NODES ; i++) { -if (socket == i) -continue ; - - mz_addr =malloc_heap_alloc (&mcfg->malloc_heaps[i], -NULL , requested_len, flags, align, - bound, contig); -if (mz_addr !=NULL ) -break ; - } - } - +void *mz_addr =malloc_heap_alloc (NULL , requested_len, socket_id, flags, + align, bound, contig);if (mz_addr ==NULL ) { rte_errno =ENOMEM ;return NULL ;
lib/librte_eal/common/malloc_elem.c +86 -0
92 lines not on this page · raw message
lib/librte_eal/common/malloc_elem.h +3 -0
@@ -154,6 +154,9 @@ int malloc_elem_resize(struct malloc_elem *elem, size_t size);void +malloc_elem_hide_region (struct malloc_elem *elem,void *start,size_t len); + +void malloc_elem_free_list_remove (struct malloc_elem *elem);/*
lib/librte_eal/common/malloc_heap.c +336 -11
392 lines not on this page · raw message
lib/librte_eal/common/malloc_heap.h +2 -2
@@ -26,8 +26,8 @@ malloc_get_numa_socket(void) }void * -malloc_heap_alloc (struct malloc_heap *heap,const char *type,size_t size, -unsigned int flags,size_t align,size_t bound,bool contig); +malloc_heap_alloc (const char *type,size_t size,int socket,unsigned int flags, +size_t align,size_t bound,bool contig);int malloc_heap_free (struct malloc_elem *elem);
lib/librte_eal/common/rte_malloc.c +3 -28
@@ -40,10 +40,6 @@ void * rte_malloc_socket(const char *type, size_t size, unsigned int align, int socket_arg) { - struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; -int socket, i; -void *ret; - /* return NULL if size is 0 or alignment is not power-of-2 */ if (size == 0 || (align && !rte_is_power_of_2(align))) return NULL;
@@ -51,33 +47,12 @@ rte_malloc_socket(const char *type, size_t size, unsigned int align,if (!rte_eal_has_hugepages ()) socket_arg =SOCKET_ID_ANY ; -if (socket_arg ==SOCKET_ID_ANY ) - socket =malloc_get_numa_socket (); -else - socket = socket_arg; -/* Check socket parameter */ -if (socket >=RTE_MAX_NUMA_NODES ) +if (socket_arg >=RTE_MAX_NUMA_NODES )return NULL ; - ret =malloc_heap_alloc (&mcfg->malloc_heaps[socket], type, - size,0 , align ==0 ?1 : align,0 , false); -if (ret !=NULL || socket_arg !=SOCKET_ID_ANY ) -return ret; - -/* try other heaps */ -for (i =0 ; i <RTE_MAX_NUMA_NODES ; i++) { -/* we already tried this one */ -if (i == socket) -continue ; - - ret =malloc_heap_alloc (&mcfg->malloc_heaps[i], type, - size,0 , align ==0 ?1 : align,0 , false); -if (ret !=NULL ) -return ret; - } - -return NULL ; +return malloc_heap_alloc (type, size, socket_arg,0 , + align ==0 ?1 : align,0 , false); }/*
Signature · 1 line
2.7.4
PATCH v3 61/68 eal: add support for multiprocess memory hotplug
In reply to Anatoly BurakovThis enables multiprocess synchronization for memory hotplug requests at runtime (as opposed to initialization).
Basic workflow is the following. Primary process always does initial mapping and unmapping, and secondary processes always follow primary page map. Only one allocation request can be active at any one time.
When primary allocates memory, it ensures that all other processes have allocated the same set of hugepages successfully, otherwise any allocations made are being rolled back, and heap is freed back. Heap is locked throughout the process, and there is also a global memory hotplug lock, so no race conditions can happen.
When primary frees memory, it frees the heap, deallocates affected pages, and notifies other processes of deallocations. Since heap is freed from that memory chunk, the area basically becomes invisible to other processes even if they happen to fail to unmap that specific set of pages, so it's completely safe to ignore results of sync requests.
When secondary allocates memory, it does not do so by itself. Instead, it sends a request to primary process to try and allocate pages of specified size and on specified socket, such that a specified heap allocation request could complete. Primary process then sends all secondaries (including the requestor) a separate notification of allocated pages, and expects all secondary processes to report success before considering pages as "allocated".
Only after primary process ensures that all memory has been successfully allocated in all secondary process, it will respond positively to the initial request, and let secondary proceed with the allocation. Since the heap now has memory that can satisfy allocation request, and it was locked all this time (so no other allocations could take place), secondary process will be able to allocate memory from the heap.
When secondary frees memory, it hides pages to be deallocated from the heap. Then, it sends a deallocation request to primary process, so that it deallocates pages itself, and then sends a separate sync request to all other processes (including the requestor) to unmap the same pages. This way, even if secondary fails to notify other processes of this deallocation, that memory will become invisible to other processes, and will not be allocated from again.
So, to summarize: address space will only become part of the heap if primary process can ensure that all other processes have allocated this memory successfully. If anything goes wrong, the worst thing that could happen is that a page will "leak" and will not be available to neither DPDK nor the system, as some process will still hold onto it. It's not an actual leak, as we can account for the page - it's just that none of the processes will be able to use this page for anything useful, until it gets allocated from by the primary.
Due to underlying DPDK IPC implementation being single-threaded, some asynchronous magic had to be done, as we need to complete several requests before we can definitively allow secondary process to use allocated memory (namely, it has to be present in all other secondary processes before it can be used). Additionally, only one allocation request is allowed to be submitted at once.
Memory allocation requests are only allowed when there are no secondary processes currently initializing. To enforce that, a shared rwlock is used, that is set to read lock on init (so that several secondaries could initialize concurrently), and write lock on making allocation requests (so that either secondary init will have to wait, or allocation request will have to wait until all processes have initialized).
Any other function that wishes to iterate over memory or prevent allocations should be using memory hotplug lock.
--- lib/librte_eal/bsdapp/eal/Makefile | 1 + lib/librte_eal/common/eal_common_memory.c | 67 +- lib/librte_eal/common/include/rte_eal_memconfig.h | 3 + lib/librte_eal/common/malloc_elem.c | 124 ++-- lib/librte_eal/common/malloc_heap.c | 255 ++++++-- lib/librte_eal/common/malloc_mp.c | 744 ++++++++++++++++++++++ lib/librte_eal/common/malloc_mp.h | 86 +++ lib/librte_eal/common/meson.build | 1 + lib/librte_eal/linuxapp/eal/Makefile | 1 + lib/librte_eal/linuxapp/eal/eal_memalloc.c | 32 +- lib/librte_eal/linuxapp/eal/eal_vfio.c | 40 +- 11 files changed, 1229 insertions(+), 125 deletions(-) create mode 100644 lib/librte_eal/common/malloc_mp.c create mode 100644 lib/librte_eal/common/malloc_mp.h
lib/librte_eal/bsdapp/eal/Makefile +1 -0
@@ -59,6 +59,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_common_fbarray.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_heap.c +SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += malloc_mp.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_keepalive.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_service.c SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += rte_reciprocal.c
lib/librte_eal/common/eal_common_memory.c +49 -18
130 lines not on this page · raw message
lib/librte_eal/common/include/rte_eal_memconfig.h +3 -0
@@ -59,6 +59,9 @@ struct rte_mem_config {rte_rwlock_t qlock;/**< used for tailq operation for thread safe. */ rte_rwlock_t mplock;/**< only used by mempool LIB for thread-safe. */ +rte_rwlock_t memory_hotplug_lock; +/**< indicates whether memory hotplug request is in progress. */ +/* memory segments and zones */ struct rte_fbarray memzones;/**< Memzone descriptors. */
lib/librte_eal/common/malloc_elem.c +65 -59
139 lines not on this page · raw message
lib/librte_eal/common/malloc_heap.c +212 -43
371 lines not on this page · raw message
lib/librte_eal/common/malloc_mp.c new file +744 -0
744 lines not on this page · raw message
lib/librte_eal/common/malloc_mp.h new file +86 -0
86 lines not on this page · raw message
lib/librte_eal/common/meson.build +1 -0
@@ -27,6 +27,7 @@ common_sources = files( 'eal_common_timer.c', 'malloc_elem.c', 'malloc_heap.c', + 'malloc_mp.c', 'rte_keepalive.c', 'rte_malloc.c', 'rte_reciprocal.c',
lib/librte_eal/linuxapp/eal/Makefile +1 -0
@@ -67,6 +67,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_fbarray.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_malloc.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_elem.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_heap.c +SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += malloc_mp.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_keepalive.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_service.c SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += rte_reciprocal.c
lib/librte_eal/linuxapp/eal/eal_memalloc.c +29 -3
@@ -211,6 +211,32 @@ is_zero_length(int fd)return st.st_blocks ==0 ; } +/* we cannot use rte_memseg_list_walk() here because we will be holding a +* write lock whenever we enter every function in this file, however copying +* the same iteration code everywhere is not ideal as well. so, use a lockless +* copy of memseg list walk here. +*/ +static int +memseg_list_walk_thread_unsafe (rte_memseg_list_walk_t func,void *arg) +{ +struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; +int i, ret =0 ; + +for (i =0 ; i <RTE_MAX_MEMSEG_LISTS ; i++) { +struct rte_memseg_list *msl = &mcfg->memsegs[i]; + +if (msl->base_va ==NULL ) +continue ; + + ret =func (msl, arg); +if (ret <0 ) +return -1 ; +if (ret >0 ) +return 1 ; + } +return 0 ; +} +static int get_seg_fd (char *path,int buflen,struct hugepage_info *hi,unsigned int list_idx,unsigned int seg_idx)
@@ -739,7 +765,7 @@ eal_memalloc_alloc_seg_bulk(struct rte_memseg **ms, int n_segs, size_t page_sz, wa.socket = socket; wa.segs_allocated =0 ; - ret =rte_memseg_list_walk (alloc_seg_walk, &wa); + ret =memseg_list_walk_thread_unsafe (alloc_seg_walk, &wa);if (ret ==0 ) {RTE_LOG (ERR ,EAL ,"%s(): couldn't find suitable memseg_list\n" , __func__);
@@ -798,7 +824,7 @@ eal_memalloc_free_seg_bulk(struct rte_memseg **ms, int n_segs) wa.ms = cur; wa.hi = hi; - walk_res =rte_memseg_list_walk (free_seg_walk, &wa); + walk_res =memseg_list_walk_thread_unsafe (free_seg_walk, &wa);if (walk_res ==1 )continue ;if (walk_res ==0 )
@@ -1055,7 +1081,7 @@ eal_memalloc_sync_with_primary(void)if (rte_eal_process_type () ==RTE_PROC_PRIMARY )return 0 ; -if (rte_memseg_list_walk (sync_walk,NULL )) +if (memseg_list_walk_thread_unsafe (sync_walk,NULL ))return -1 ;return 0 ; }
lib/librte_eal/linuxapp/eal/eal_vfio.c +38 -2
@@ -53,6 +53,42 @@ static const struct vfio_iommu_type iommu_types[] = { }, }; +/* for sPAPR IOMMU, we will need to walk memseg list, but we cannot use +* rte_memseg_walk() because by the time we enter callback we will be holding a +* write lock, so regular rte-memseg_walk will deadlock. copying the same +* iteration code everywhere is not ideal as well. so, use a lockless copy of +* memseg walk here. +*/ +static int +memseg_walk_thread_unsafe (rte_memseg_walk_t func,void *arg) +{ +struct rte_mem_config *mcfg =rte_eal_get_configuration ()->mem_config; +int i, ms_idx, ret =0 ; + +for (i =0 ; i <RTE_MAX_MEMSEG_LISTS ; i++) { +struct rte_memseg_list *msl = &mcfg->memsegs[i]; +const struct rte_memseg *ms; +struct rte_fbarray *arr; + +if (msl->memseg_arr.count ==0 ) +continue ; + + arr = &msl->memseg_arr; + + ms_idx =rte_fbarray_find_next_used (arr,0 ); +while (ms_idx >=0 ) { + ms =rte_fbarray_get (arr, ms_idx); + ret =func (msl, ms, arg); +if (ret <0 ) +return -1 ; +if (ret >0 ) +return 1 ; + ms_idx =rte_fbarray_find_next_used (arr, ms_idx +1 ); + } + } +return 0 ; +} +int vfio_get_group_fd (int iommu_group_no) {
@@ -884,7 +920,7 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,/* check if window size needs to be adjusted */ memset (¶m,0 ,sizeof (param)); -if (rte_memseg_walk (vfio_spapr_window_size_walk, ¶m) <0 ) { +if (memseg_walk_thread_unsafe (vfio_spapr_window_size_walk, ¶m) <0 ) {RTE_LOG (ERR ,EAL ,"Could not get window size\n" );return -1 ; }
@@ -902,7 +938,7 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,RTE_LOG (ERR ,EAL ,"Could not create new DMA window\n" );return -1 ; } -if (rte_memseg_walk (vfio_spapr_map_walk, +if (memseg_walk_thread_unsafe (vfio_spapr_map_walk, &vfio_container_fd) <0 ) {RTE_LOG (ERR ,EAL ,"Could not recreate DMA maps\n" );return -1 ;
Signature · 1 line
2.7.4
PATCH v3 62/68 eal: add support for callbacks on memory hotplug
In reply to Anatoly BurakovEach process will have its own callbacks. Callbacks will indicate whether it's allocation and deallocation that's happened, and will also provide start VA address and length of allocated block.
Since memory hotplug isn't supported on FreeBSD and in legacy mem mode, it will not be possible to register them in either.
---
Notes:
v3:
- Made API experimental
- Compile fixes
lib/librte_eal/common/eal_common_memalloc.c | 133 ++++++++++++++++++++++++++++ lib/librte_eal/common/eal_common_memory.c | 28 ++++++ lib/librte_eal/common/eal_memalloc.h | 11 +++ lib/librte_eal/common/include/rte_memory.h | 49 ++++++++++ lib/librte_eal/rte_eal_version.map | 2 + 5 files changed, 223 insertions(+)
lib/librte_eal/common/eal_common_memalloc.c +133 -0
@@ -2,16 +2,46 @@* Copyright(c) 2017-2018 Intel Corporation */ +#include <string.h> + +#include <rte_errno.h> #include <rte_lcore.h> #include <rte_fbarray.h> #include <rte_memzone.h> #include <rte_memory.h> #include <rte_eal_memconfig.h> +#include <rte_rwlock.h> #include "eal_private.h" #include "eal_internal_cfg.h" #include "eal_memalloc.h" +struct mem_event_callback_entry { +TAILQ_ENTRY (mem_event_callback_entry) next; +char name[RTE_MEM_EVENT_CALLBACK_NAME_LEN ]; +rte_mem_event_callback_t clb; +}; + +/** Double linked list of actions. */ +TAILQ_HEAD (mem_event_callback_entry_list, mem_event_callback_entry); + +static struct mem_event_callback_entry_list mem_event_callback_list = +TAILQ_HEAD_INITIALIZER (mem_event_callback_list); + +static rte_rwlock_t mem_event_rwlock =RTE_RWLOCK_INITIALIZER ; + +static struct mem_event_callback_entry * +find_mem_event_callback (const char *name) +{ +struct mem_event_callback_entry *r; + + TAILQ_FOREACH(r, &mem_event_callback_list, next) { +if (!strcmp (r->name, name)) +break ; + } +return r; +} +bool eal_memalloc_is_contig (const struct rte_memseg_list *msl,void *start,size_t len)
@@ -88,3 +118,106 @@ eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start, }return true; } + +int +eal_memalloc_mem_event_callback_register (const char *name, +rte_mem_event_callback_t clb) +{ +struct mem_event_callback_entry *entry; +int ret, len; +if (name ==NULL || clb ==NULL ) { + rte_errno =EINVAL ; +return -1 ; + } + len =strnlen (name,RTE_MEM_EVENT_CALLBACK_NAME_LEN ); +if (len ==0 ) { + rte_errno =EINVAL ; +return -1 ; + }else if (len ==RTE_MEM_EVENT_CALLBACK_NAME_LEN ) { + rte_errno =ENAMETOOLONG ; +return -1 ; + } +rte_rwlock_write_lock (&mem_event_rwlock); + + entry =find_mem_event_callback (name); +if (entry !=NULL ) { + rte_errno =EEXIST ; + ret =-1 ; + goto unlock; + } + + entry =malloc (sizeof (*entry)); +if (entry ==NULL ) { + rte_errno =ENOMEM ; + ret =-1 ; + goto unlock; + } + +/* callback successfully created and is valid, add it to the list */ + entry->clb = clb; +snprintf (entry->name,RTE_MEM_EVENT_CALLBACK_NAME_LEN ,"%s" , name); +TAILQ_INSERT_TAIL (&mem_event_callback_list, entry, next); + + ret =0 ; + +RTE_LOG (DEBUG ,EAL ,"Mem event callback '%s' registered\n" , name); + +unlock: +rte_rwlock_write_unlock (&mem_event_rwlock); +return ret; +} + +int +eal_memalloc_mem_event_callback_unregister (const char *name) +{ +struct mem_event_callback_entry *entry; +int ret, len; + +if (name ==NULL ) { + rte_errno =EINVAL ; +return -1 ; + } + len =strnlen (name,RTE_MEM_EVENT_CALLBACK_NAME_LEN ); +if (len ==0 ) { + rte_errno =EINVAL ; +return -1 ; + }else if (len ==RTE_MEM_EVENT_CALLBACK_NAME_LEN ) { + rte_errno =ENAMETOOLONG ; +return -1 ; + } +rte_rwlock_write_lock (&mem_event_rwlock); + + entry =find_mem_event_callback (name); +if (entry ==NULL ) { + rte_errno =ENOENT ; + ret =-1 ; + goto unlock; + } +TAILQ_REMOVE (&mem_event_callback_list, entry, next); +free (entry); + + ret =0 ; + +RTE_LOG (DEBUG ,EAL ,"Mem event callback '%s' unregistered\n" , name); + +unlock: +rte_rwlock_write_unlock (&mem_event_rwlock); +return ret; +} + +void +eal_memalloc_mem_event_notify (enum rte_mem_event event,const void *start, +size_t len) +{ +struct mem_event_callback_entry *entry; + +rte_rwlock_read_lock (&mem_event_rwlock); + + TAILQ_FOREACH(entry, &mem_event_callback_list, next) { +RTE_LOG (DEBUG ,EAL ,"Calling mem event callback %s" , + entry->name); + entry->clb (event, start, len); + } + +rte_rwlock_read_unlock (&mem_event_rwlock); +}
lib/librte_eal/common/eal_common_memory.c +28 -0
@@ -604,6 +604,34 @@ dump_memseg(const struct rte_memseg_list *msl, const struct rte_memseg *ms,return 0 ; } +/* +* Defining here because declared in rte_memory.h, but the actual implementation +* is in eal_common_memalloc.c, like all other memalloc internals. +*/ +int __rte_experimental +rte_mem_event_callback_register (const char *name,rte_mem_event_callback_t clb) +{ +/* FreeBSD boots with legacy mem enabled by default */ +if (internal_config.legacy_mem) { +RTE_LOG (DEBUG ,EAL ,"Registering mem event callbacks not supported\n" ); + rte_errno =ENOTSUP ; +return -1 ; + } +return eal_memalloc_mem_event_callback_register (name, clb); +} + +int __rte_experimental +rte_mem_event_callback_unregister (const char *name) +{ +/* FreeBSD boots with legacy mem enabled by default */ +if (internal_config.legacy_mem) { +RTE_LOG (DEBUG ,EAL ,"Registering mem event callbacks not supported\n" ); + rte_errno =ENOTSUP ; +return -1 ; + } +return eal_memalloc_mem_event_callback_unregister (name); +} +/* Dump the physical memory layout on console */ void rte_dump_physmem_layout (FILE *f)
lib/librte_eal/common/eal_memalloc.h +11 -0
@@ -56,4 +56,15 @@ eal_memalloc_is_contig(const struct rte_memseg_list *msl, void *start,int eal_memalloc_sync_with_primary (void ); +int +eal_memalloc_mem_event_callback_register (const char *name, +rte_mem_event_callback_t clb); + +int +eal_memalloc_mem_event_callback_unregister (const char *name); + +void +eal_memalloc_mem_event_notify (enum rte_mem_event event,const void *start, +size_t len); +#endif // EAL_MEMALLOC_H
lib/librte_eal/common/include/rte_memory.h +49 -0
55 lines not on this page · raw message
lib/librte_eal/rte_eal_version.map +2 -0
@@ -238,6 +238,8 @@ EXPERIMENTAL { rte_fbarray_set_used; rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; + rte_mem_event_callback_register; + rte_mem_event_callback_unregister; rte_mem_iova2virt; rte_mem_virt2memseg; rte_mem_virt2memseg_list;
Signature · 1 line
2.7.4
PATCH v3 63/68 eal: enable callbacks on malloc/free and mp sync
In reply to Anatoly BurakovCallbacks will be triggered just after allocation and just before deallocation, to ensure that memory address space referenced in the callback is always valid by the time callback is called.
--- lib/librte_eal/common/malloc_heap.c | 21 +++++++++++++++++++++ lib/librte_eal/linuxapp/eal/eal_memalloc.c | 30 ++++++++++++++++++++++++++++++ lib/librte_eal/linuxapp/eal/eal_vfio.c | 15 +++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-)
lib/librte_eal/common/malloc_heap.c +21 -0
@@ -241,6 +241,7 @@ try_expand_heap_primary(struct malloc_heap *heap, uint64_t pg_sz,void *map_addr;size_t alloc_sz;int n_segs; +bool callback_triggered = false; alloc_sz =RTE_ALIGN_CEIL (align + elt_size +MALLOC_ELEM_TRAILER_LEN , pg_sz);
@@ -262,12 +263,22 @@ try_expand_heap_primary(struct malloc_heap *heap, uint64_t pg_sz, map_addr = ms[0 ]->addr; +/* notify user about changes in memory map */ +eal_memalloc_mem_event_notify (RTE_MEM_EVENT_ALLOC , map_addr, alloc_sz); +/* notify other processes that this has happened */ if (request_sync ()) {/* we couldn't ensure all processes have mapped memory, * so free it back and notify everyone that it's been * freed back. +* +* technically, we could've avoided adding memory addresses to +* the map, but that would've led to inconsistent behavior +* between primary and secondary processes, as those get +* callbacks during sync. therefore, force primary process to +* do alloc-and-rollback syncs as well. */ + callback_triggered = true; goto free_elem; } heap->total_size += alloc_sz;
@@ -280,6 +291,10 @@ try_expand_heap_primary(struct malloc_heap *heap, uint64_t pg_sz,return 0 ; free_elem: +if (callback_triggered) +eal_memalloc_mem_event_notify (RTE_MEM_EVENT_FREE , + map_addr, alloc_sz); +rollback_expand_heap (ms, n_segs, elem, map_addr, alloc_sz);request_sync ();
@@ -642,6 +657,10 @@ malloc_heap_free(struct malloc_elem *elem) heap->total_size -= aligned_len;if (rte_eal_process_type () ==RTE_PROC_PRIMARY ) { +/* notify user about changes in memory map */ +eal_memalloc_mem_event_notify (RTE_MEM_EVENT_FREE , + aligned_start, aligned_len); +/* don't care if any of this fails */ malloc_heap_free_pages (aligned_start, aligned_len);
@@ -666,6 +685,8 @@ malloc_heap_free(struct malloc_elem *elem)* already removed from the heap, so it is, for all intents and * purposes, hidden from the rest of DPDK even if some other * process (including this one) may have these pages mapped. +* +* notifications about deallocated memory happen during sync. */ request_to_primary (&req); }
lib/librte_eal/linuxapp/eal/eal_memalloc.c +30 -0
@@ -877,6 +877,21 @@ sync_chunk(struct rte_memseg_list *primary_msl, diff_len =RTE_MIN (chunk_len, diff_len); +/* if we are freeing memory, notify the application */ +if (!used) { +struct rte_memseg *ms; +void *start_va; +size_t len, page_sz; + + ms =rte_fbarray_get (l_arr, start); + start_va = ms->addr; + page_sz = (size_t )primary_msl->page_sz; + len = page_sz * diff_len; + +eal_memalloc_mem_event_notify (RTE_MEM_EVENT_FREE , + start_va, len); + } +for (i =0 ; i < diff_len; i++) {struct rte_memseg *p_ms, *l_ms;int seg_idx = start + i;
@@ -902,6 +917,21 @@ sync_chunk(struct rte_memseg_list *primary_msl, } } +/* if we just allocated memory, notify the application */ +if (used) { +struct rte_memseg *ms; +void *start_va; +size_t len, page_sz; + + ms =rte_fbarray_get (l_arr, start); + start_va = ms->addr; + page_sz = (size_t )primary_msl->page_sz; + len = page_sz * diff_len; + +eal_memalloc_mem_event_notify (RTE_MEM_EVENT_ALLOC , + start_va, len); + } +/* calculate how much we can advance until next chunk */ diff_len = used ? rte_fbarray_find_contig_used(l_arr, start) :
lib/librte_eal/linuxapp/eal/eal_vfio.c +13 -2
@@ -931,6 +931,7 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova, create.levels =1 ;if (do_map) { +void *addr;/* re-create window and remap the entire memory */ if (iova > create.window_size) { if (vfio_spapr_create_new_dma_window(vfio_container_fd,
@@ -946,9 +947,19 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova, }/* now that we've remapped all of the memory that was present * before, map the segment that we were requested to map. +* +* however, if we were called by the callback, the memory we +* were called with was already in the memseg list, so previous +* mapping should've mapped that segment already. +* +* virt2memseg_list is a relatively cheap check, so use that. if +* memory is within any memseg list, it's a memseg, so it's +* already mapped. */ -if (vfio_spapr_dma_do_map (vfio_container_fd, - vaddr, iova, len,1 ) <0 ) { + addr = (void *)(uintptr_t )vaddr; +if (rte_mem_virt2memseg_list (addr) ==NULL && +vfio_spapr_dma_do_map (vfio_container_fd, + vaddr, iova, len,1 ) <0 ) {RTE_LOG (ERR ,EAL ,"Could not map segment\n" );return -1 ; }
Signature · 1 line
2.7.4
PATCH v3 64/68 vfio: enable support for mem event callbacks
In reply to Anatoly BurakovEnable callbacks on first device attach, disable callbacks on last device attach.
---
Notes:
v3:
- Moved callbacks to attach/detach as opposed to init
lib/librte_eal/linuxapp/eal/eal_vfio.c | 83 +++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 6 deletions(-)
lib/librte_eal/linuxapp/eal/eal_vfio.c +77 -6
@@ -18,6 +18,8 @@#ifdef VFIO_PRESENT +#define VFIO_MEM_EVENT_CLB_NAME "vfio_mem_event_clb" +/* per-process VFIO config */ static struct vfio_config vfio_cfg;
@@ -250,6 +252,38 @@ vfio_group_device_count(int vfio_group_fd)return vfio_cfg.vfio_groups[i].devices; } +static void +vfio_mem_event_callback (enum rte_mem_event type,const void *addr,size_t len) +{ +struct rte_memseg_list *msl; +struct rte_memseg *ms; +size_t cur_len =0 ; + + msl =rte_mem_virt2memseg_list (addr); + +/* for IOVA as VA mode, no need to care for IOVA addresses */ +if (rte_eal_iova_mode () ==RTE_IOVA_VA ) { +uint64_t vfio_va = (uint64_t )(uintptr_t )addr; +if (type ==RTE_MEM_EVENT_ALLOC ) +rte_vfio_dma_map (vfio_va, vfio_va, len); +else +rte_vfio_dma_unmap (vfio_va, vfio_va, len); +return ; + } + +/* memsegs are contiguous in memory */ + ms =rte_mem_virt2memseg (addr, msl); +while (cur_len < len) { +if (type ==RTE_MEM_EVENT_ALLOC ) +rte_vfio_dma_map (ms->addr_64, ms->iova, ms->len); +else +rte_vfio_dma_unmap (ms->addr_64, ms->iova, ms->len); + + cur_len += ms->len; + ++ms; + } +} +int rte_vfio_clear_group (int vfio_group_fd) {
@@ -312,6 +346,8 @@ int rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr, int *vfio_dev_fd, struct vfio_device_info *device_info) { + struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; +rte_rwlock_t *mem_lock = &mcfg->memory_hotplug_lock;struct vfio_group_status group_status = { .argsz =sizeof (group_status) };
@@ -399,6 +435,10 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,rte_vfio_clear_group (vfio_group_fd);return -1 ; } +/* lock memory hotplug before mapping and release it +* after registering callback, to prevent races +*/ +rte_rwlock_read_lock (mem_lock); ret = t->dma_map_func (vfio_cfg.vfio_container_fd);if (ret) { RTE_LOG(ERR, EAL,
@@ -406,10 +446,17 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr, dev_addr, errno, strerror(errno));close (vfio_group_fd);rte_vfio_clear_group (vfio_group_fd); +rte_rwlock_read_unlock (mem_lock);return -1 ; } vfio_cfg.vfio_iommu_type = t; + +/* register callback for mem events */ +rte_mem_event_callback_register (VFIO_MEM_EVENT_CLB_NAME , + vfio_mem_event_callback); +/* unlock memory hotplug */ +rte_rwlock_read_unlock (mem_lock); } }
@@ -447,6 +494,8 @@ int rte_vfio_release_device(const char *sysfs_base, const char *dev_addr, int vfio_dev_fd) { + struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; +rte_rwlock_t *mem_lock = &mcfg->memory_hotplug_lock;struct vfio_group_status group_status = { .argsz =sizeof (group_status) };
@@ -454,13 +503,20 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,int iommu_group_no;int ret; +/* we don't want any DMA mapping messages to come while we're detaching +* VFIO device, because this might be the last device and we might need +* to unregister the callback. +*/ +rte_rwlock_read_lock (mem_lock); +/* get group number */ ret =vfio_get_group_no (sysfs_base, dev_addr, &iommu_group_no);if (ret <=0 ) {RTE_LOG (WARNING ,EAL ," %s not managed by VFIO driver\n" , dev_addr);/* This is an error at this point. */ -return -1 ; + ret =-1 ; + goto out; }/* get the actual group fd */
@@ -468,7 +524,8 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,if (vfio_group_fd <=0 ) {RTE_LOG (INFO ,EAL ,"vfio_get_group_fd failed for %s\n" , dev_addr); -return -1 ; + ret =-1 ; + goto out; }/* At this point we got an active group. Closing it will make the
@@ -480,7 +537,8 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,if (close (vfio_dev_fd) <0 ) {RTE_LOG (INFO ,EAL ,"Error when closing vfio_dev_fd for %s\n" , dev_addr); -return -1 ; + ret =-1 ; + goto out; }/* An VFIO group can have several devices attached. Just when there is
@@ -492,17 +550,30 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,if (close (vfio_group_fd) <0 ) {RTE_LOG (INFO ,EAL ,"Error when closing vfio_group_fd for %s\n" , dev_addr); -return -1 ; + ret =-1 ; + goto out; }if (rte_vfio_clear_group (vfio_group_fd) <0 ) {RTE_LOG (INFO ,EAL ,"Error when clearing group for %s\n" , dev_addr); -return -1 ; + ret =-1 ; + goto out; } } -return 0 ; +/* if there are no active device groups, unregister the callback to +* avoid spurious attempts to map/unmap memory from VFIO. +*/ +if (vfio_cfg.vfio_active_groups ==0 ) +rte_mem_event_callback_unregister (VFIO_MEM_EVENT_CLB_NAME ); + +/* success */ + ret =0 ; + +out: +rte_rwlock_read_unlock (mem_lock); +return ret; }int
Signature · 1 line
2.7.4
PATCH v3 65/68 eal: enable non-legacy memory mode
In reply to Anatoly BurakovNow that every other piece of the puzzle is in place, enable non-legacy init mode.
--- lib/librte_eal/linuxapp/eal/eal.c | 2 -- 1 file changed, 2 deletions(-)
lib/librte_eal/linuxapp/eal/eal.c +0 -2
@@ -772,8 +772,6 @@ rte_eal_init(int argc, char **argv)rte_atomic32_clear (&run_once);return -1 ; } -/* for now, always set legacy mem */ - internal_config.legacy_mem =1 ;if (eal_plugins_init () <0 ) {rte_eal_init_alert ("Cannot init plugins\n" );
Signature · 1 line
2.7.4
PATCH v3 66/68 eal: add memory validator callback
In reply to Anatoly BurakovThis API will enable application to register for notifications on page allocations that are about to happen, giving the application a chance to allow or deny the allocation when total memory utilization as a result would be above specified limit on specified socket.
--- lib/librte_eal/common/eal_common_memalloc.c | 138 +++++++++++++++++++++++++++- lib/librte_eal/common/eal_common_memory.c | 26 ++++++ lib/librte_eal/common/eal_memalloc.h | 10 ++ lib/librte_eal/common/include/rte_memory.h | 59 ++++++++++++ lib/librte_eal/rte_eal_version.map | 2 + 5 files changed, 234 insertions(+), 1 deletion(-)
lib/librte_eal/common/eal_common_memalloc.c +137 -1
@@ -22,14 +22,26 @@ struct mem_event_callback_entry {rte_mem_event_callback_t clb; }; +struct mem_alloc_validator_entry { +TAILQ_ENTRY (mem_alloc_validator_entry) next; +char name[RTE_MEM_ALLOC_VALIDATOR_NAME_LEN ]; +rte_mem_alloc_validator_t clb; +int socket_id; +size_t limit; +}; +/** Double linked list of actions. */ TAILQ_HEAD (mem_event_callback_entry_list, mem_event_callback_entry); +TAILQ_HEAD (mem_alloc_validator_entry_list, mem_alloc_validator_entry);static struct mem_event_callback_entry_list mem_event_callback_list =TAILQ_HEAD_INITIALIZER (mem_event_callback_list); -static rte_rwlock_t mem_event_rwlock =RTE_RWLOCK_INITIALIZER ; +static struct mem_alloc_validator_entry_list mem_alloc_validator_list = +TAILQ_HEAD_INITIALIZER (mem_alloc_validator_list); +static rte_rwlock_t mem_alloc_validator_rwlock =RTE_RWLOCK_INITIALIZER ; +static struct mem_event_callback_entry *find_mem_event_callback (const char *name) {
@@ -42,6 +54,18 @@ find_mem_event_callback(const char *name)return r; } +static struct mem_alloc_validator_entry * +find_mem_alloc_validator (const char *name,int socket_id) +{ +struct mem_alloc_validator_entry *r; + + TAILQ_FOREACH(r, &mem_alloc_validator_list, next) { +if (!strcmp (r->name, name) && r->socket_id == socket_id) +break ; + } +return r; +} +bool eal_memalloc_is_contig (const struct rte_memseg_list *msl,void *start,size_t len)
@@ -221,3 +245,115 @@ eal_memalloc_mem_event_notify(enum rte_mem_event event, const void *start,rte_rwlock_read_unlock (&mem_event_rwlock); } + +int +eal_memalloc_mem_alloc_validator_register (const char *name, +rte_mem_alloc_validator_t clb,int socket_id,size_t limit) +{ +struct mem_alloc_validator_entry *entry; +int ret, len; +if (name ==NULL || clb ==NULL || socket_id <0 ) { + rte_errno =EINVAL ; +return -1 ; + } + len =strnlen (name,RTE_MEM_ALLOC_VALIDATOR_NAME_LEN ); +if (len ==0 ) { + rte_errno =EINVAL ; +return -1 ; + }else if (len ==RTE_MEM_ALLOC_VALIDATOR_NAME_LEN ) { + rte_errno =ENAMETOOLONG ; +return -1 ; + } +rte_rwlock_write_lock (&mem_alloc_validator_rwlock); + + entry =find_mem_alloc_validator (name, socket_id); +if (entry !=NULL ) { + rte_errno =EEXIST ; + ret =-1 ; + goto unlock; + } + + entry =malloc (sizeof (*entry)); +if (entry ==NULL ) { + rte_errno =ENOMEM ; + ret =-1 ; + goto unlock; + } + +/* callback successfully created and is valid, add it to the list */ + entry->clb = clb; + entry->socket_id = socket_id; + entry->limit = limit; +snprintf (entry->name,RTE_MEM_ALLOC_VALIDATOR_NAME_LEN ,"%s" , name); +TAILQ_INSERT_TAIL (&mem_alloc_validator_list, entry, next); + + ret =0 ; + +RTE_LOG (DEBUG ,EAL ,"Mem alloc validator '%s' on socket %i with limit %zu registered\n" , + name, socket_id, limit); + +unlock: +rte_rwlock_write_unlock (&mem_alloc_validator_rwlock); +return ret; +} + +int +eal_memalloc_mem_alloc_validator_unregister (const char *name,int socket_id) +{ +struct mem_alloc_validator_entry *entry; +int ret, len; + +if (name ==NULL || socket_id <0 ) { + rte_errno =EINVAL ; +return -1 ; + } + len =strnlen (name,RTE_MEM_ALLOC_VALIDATOR_NAME_LEN ); +if (len ==0 ) { + rte_errno =EINVAL ; +return -1 ; + }else if (len ==RTE_MEM_ALLOC_VALIDATOR_NAME_LEN ) { + rte_errno =ENAMETOOLONG ; +return -1 ; + } +rte_rwlock_write_lock (&mem_alloc_validator_rwlock); + + entry =find_mem_alloc_validator (name, socket_id); +if (entry ==NULL ) { + rte_errno =ENOENT ; + ret =-1 ; + goto unlock; + } +TAILQ_REMOVE (&mem_alloc_validator_list, entry, next); +free (entry); + + ret =0 ; + +RTE_LOG (DEBUG ,EAL ,"Mem alloc validator '%s' on socket %i unregistered\n" , + name, socket_id); + +unlock: +rte_rwlock_write_unlock (&mem_alloc_validator_rwlock); +return ret; +} + +int +eal_memalloc_mem_alloc_validate (int socket_id,size_t new_len) +{ +struct mem_alloc_validator_entry *entry; +int ret =0 ; + +rte_rwlock_read_lock (&mem_alloc_validator_rwlock); + + TAILQ_FOREACH(entry, &mem_alloc_validator_list, next) { +if (entry->socket_id != socket_id || entry->limit > new_len) +continue ; +RTE_LOG (DEBUG ,EAL ,"Calling mem alloc validator '%s' on socket %i\n" , + entry->name, entry->socket_id); +if (entry->clb (socket_id, entry->limit, new_len) <0 ) + ret =-1 ; + } + +rte_rwlock_read_unlock (&mem_alloc_validator_rwlock); + +return ret; +}
lib/librte_eal/common/eal_common_memory.c +26 -0
@@ -632,6 +632,32 @@ rte_mem_event_callback_unregister(const char *name)return eal_memalloc_mem_event_callback_unregister (name); } +int __rte_experimental +rte_mem_alloc_validator_register (const char *name, +rte_mem_alloc_validator_t clb,int socket_id,size_t limit) +{ +/* FreeBSD boots with legacy mem enabled by default */ +if (internal_config.legacy_mem) { +RTE_LOG (DEBUG ,EAL ,"Registering mem alloc validators not supported\n" ); + rte_errno =ENOTSUP ; +return -1 ; + } +return eal_memalloc_mem_alloc_validator_register (name, clb, socket_id, + limit); +} + +int __rte_experimental +rte_mem_alloc_validator_unregister (const char *name,int socket_id) +{ +/* FreeBSD boots with legacy mem enabled by default */ +if (internal_config.legacy_mem) { +RTE_LOG (DEBUG ,EAL ,"Registering mem alloc validators not supported\n" ); + rte_errno =ENOTSUP ; +return -1 ; + } +return eal_memalloc_mem_alloc_validator_unregister (name, socket_id); +} +/* Dump the physical memory layout on console */ void rte_dump_physmem_layout (FILE *f)
lib/librte_eal/common/eal_memalloc.h +10 -0
@@ -67,4 +67,14 @@ void eal_memalloc_mem_event_notify(enum rte_mem_event event, const void *start, size_t len); +int +eal_memalloc_mem_alloc_validator_register (const char *name, +rte_mem_alloc_validator_t clb,int socket_id,size_t limit); + +int +eal_memalloc_mem_alloc_validator_unregister (const char *name,int socket_id); + +int +eal_memalloc_mem_alloc_validate (int socket_id,size_t new_len); +#endif // EAL_MEMALLOC_H
lib/librte_eal/common/include/rte_memory.h +59 -0
65 lines not on this page · raw message
lib/librte_eal/rte_eal_version.map +2 -0
@@ -238,6 +238,8 @@ EXPERIMENTAL { rte_fbarray_set_used; rte_log_register_type_and_pick_level; rte_malloc_dump_heaps; + rte_mem_alloc_validator_register; + rte_mem_alloc_validator_unregister; rte_mem_event_callback_register; rte_mem_event_callback_unregister; rte_mem_iova2virt;
Signature · 1 line
2.7.4
PATCH v3 67/68 eal: enable validation before new page allocation
In reply to Anatoly Burakov--- lib/librte_eal/common/malloc_heap.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
lib/librte_eal/common/malloc_heap.c +9 -1
@@ -196,6 +196,15 @@ alloc_pages_on_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size,int allocd_pages;void *ret, *map_addr; + alloc_sz = (size_t )pg_sz * n_segs; + +/* first, check if we're allowed to allocate this memory */ +if (eal_memalloc_mem_alloc_validate (socket, + heap->total_size + alloc_sz) <0 ) { +RTE_LOG (DEBUG ,EAL ,"User has disallowed allocation\n" ); +return NULL ; + } + allocd_pages =eal_memalloc_alloc_seg_bulk (ms, n_segs, pg_sz, socket, true);
@@ -205,7 +214,6 @@ alloc_pages_on_heap(struct malloc_heap *heap, uint64_t pg_sz, size_t elt_size, map_addr = ms[0 ]->addr; msl =rte_mem_virt2memseg_list (map_addr); - alloc_sz = (size_t )msl->page_sz * allocd_pages;/* check if we wanted contiguous memory but didn't get it */ if (contig && !eal_memalloc_is_contig (msl, map_addr, alloc_sz)) {
Signature · 1 line
2.7.4
PATCH v3 68/68 eal: prevent preallocated pages from being freed
In reply to Anatoly BurakovIt is common sense to expect for DPDK process to not deallocate any pages that were preallocated by "-m" or "--socket-mem" flags - yet, currently, DPDK memory subsystem will do exactly that once it finds that the pages are unused.
Fix this by marking pages as unfreebale, and preventing malloc from ever trying to free them.
--- lib/librte_eal/common/include/rte_memory.h | 3 +++ lib/librte_eal/common/malloc_heap.c | 23 +++++++++++++++++++++++ lib/librte_eal/linuxapp/eal/eal_memalloc.c | 7 +++++++ lib/librte_eal/linuxapp/eal/eal_memory.c | 18 +++++++++++++++--- 4 files changed, 48 insertions(+), 3 deletions(-)
lib/librte_eal/common/include/rte_memory.h +3 -0
@@ -83,6 +83,8 @@ typedef uint64_t rte_iova_t;/** * Physical memory segment descriptor. */ +#define RTE_MEMSEG_FLAG_DO_NOT_FREE (1 << 0) +/**< Prevent this segment from being freed back to the OS. */ struct rte_memseg { RTE_STD_C11 union {
@@ -99,6 +101,7 @@ struct rte_memseg {int32_t socket_id;/**< NUMA socket ID. */ uint32_t nchannel;/**< Number of channels. */ uint32_t nrank;/**< Number of ranks. */ +uint32_t flags;/**< Memseg-specific flags */ } __rte_packed;/**
lib/librte_eal/common/malloc_heap.c +23 -0
@@ -606,6 +606,7 @@ malloc_heap_free(struct malloc_elem *elem)void *start, *aligned_start, *end, *aligned_end;size_t len, aligned_len, page_sz;struct rte_memseg_list *msl; +unsigned int i, n_segs;int ret;if (!malloc_elem_cookies_ok (elem) || elem->state !=ELEM_BUSY )
@@ -647,6 +648,28 @@ malloc_heap_free(struct malloc_elem *elem)if (aligned_len < page_sz) goto free_unlock; +/* we can free something. however, some of these pages may be marked as +* unfreeable, so also check that as well +*/ + n_segs = aligned_len / page_sz; +for (i =0 ; i < n_segs; i++) { +const struct rte_memseg *tmp = +rte_mem_virt2memseg (aligned_start, msl); + +if (tmp->flags &RTE_MEMSEG_FLAG_DO_NOT_FREE ) { +/* this is an unfreeable segment, so move start */ + aligned_start =RTE_PTR_ADD (tmp->addr, tmp->len); + } + } + +/* recalculate length and number of segments */ + aligned_len =RTE_PTR_DIFF (aligned_end, aligned_start); + n_segs = aligned_len / page_sz; + +/* check if we can still free some pages */ +if (n_segs ==0 ) + goto free_unlock; +rte_rwlock_write_lock (&mcfg->memory_hotplug_lock);/*
lib/librte_eal/linuxapp/eal/eal_memalloc.c +7 -0
@@ -806,6 +806,13 @@ eal_memalloc_free_seg_bulk(struct rte_memseg **ms, int n_segs)struct free_walk_param wa;int i, walk_res; +/* if this page is marked as unfreeable, fail */ +if (cur->flags &RTE_MEMSEG_FLAG_DO_NOT_FREE ) { +RTE_LOG (DEBUG ,EAL ,"Page is not allowed to be freed\n" ); + ret =-1 ; +continue ; + } +memset (&wa,0 ,sizeof (wa)); for (i = 0; i < (int)RTE_DIM(internal_config.hugepage_info);
lib/librte_eal/linuxapp/eal/eal_memory.c +15 -3
@@ -1637,21 +1637,33 @@ eal_hugepage_init(void) hp_sz_idx++) {for (socket_id =0 ; socket_id <RTE_MAX_NUMA_NODES ; socket_id++) { +struct rte_memseg **pages;struct hugepage_info *hpi = &used_hp[hp_sz_idx];unsigned int num_pages = hpi->num_pages[socket_id]; -int num_pages_alloc; +int num_pages_alloc, i;if (num_pages ==0 )continue ; + pages =malloc (sizeof (*pages) * num_pages); +RTE_LOG (DEBUG ,EAL ,"Allocating %u pages of size %" PRIu64"M on socket %i\n" , num_pages, hpi->hugepage_sz >>20 , socket_id); - num_pages_alloc =eal_memalloc_alloc_seg_bulk (NULL , + num_pages_alloc =eal_memalloc_alloc_seg_bulk (pages, num_pages, hpi->hugepage_sz, socket_id, true); -if (num_pages_alloc <0 ) +if (num_pages_alloc <0 ) { +free (pages);return -1 ; + } + +/* mark preallocated pages as unfreeable */ +for (i =0 ; i < num_pages_alloc; i++) { +struct rte_memseg *ms = pages[i]; + ms->flags |=RTE_MEMSEG_FLAG_DO_NOT_FREE ; + } +free (pages); } }return 0 ;
Signature · 1 line
2.7.4
Hello Anatoly,
Quoted 67 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Dependencies (to be applied in specified order):
- IPC asynchronous request API patch [2]
- Function to return number of sockets [3]
- EAL IOVA fix [4]Deprecation notices relevant to this patchset:
- General outline of memory hotplug changes [5]
- EAL NUMA node count changes [6]The vast majority of changes are in the EAL and malloc, the external API disruption is minimal: a new set of API's are added for contiguous memory allocation for
rte_memzone, and a few API additions inrte_memorydue to switch tomemseg_listsas opposed to memsegs. Every other API change is internal to EAL, and all of the memory allocation/freeing is handled throughrte_malloc, with no externally visible API changes.Quick outline of all changes done as part of this patchset:
* Malloc heap adjusted to handle holes in address space
* Single memseg list replaced by multiple memseg lists
* VA space for hugepages is preallocated in advance
* Added alloc/free for pages happening as needed on rte_malloc/rte_free
* Added contiguous memory allocation API's forrte_memzone
* Added convenience API calls to walk over memsegs
* Integrated Pawel Wodkowski's patch for registering/unregistering memory with VFIO [7]
* Callbacks for registering memory allocations
* Callbacks for allowing/disallowing allocations above specified limit
* Multiprocess support done via DPDK IPC introduced in 18.02The biggest difference is a "memseg" now represents a single page (as opposed to being a big contiguous block of pages). As a consequence, both memzones and malloc elements are no longer guaranteed to be physically contiguous, unless the user asks for it at reserve time. To preserve whatever functionality that was dependent on previous behavior, a legacy memory option is also provided, however it is expected (or perhaps vainly hoped) to be temporary solution.
Why multiple memseg lists instead of one? Since memseg is a single page now, the list of memsegs will get quite big, and we need to locate pages somehow when we allocate and free them. We could of course just walk the list and allocate one contiguous chunk of VA space for memsegs, but this implementation uses separate lists instead in order to speed up many operations with memseg lists.
For v3, the following limitations are present:
- VFIO support is only smoke-tested (but is expected to work), VFIO support with secondary processes is not tested; work is ongoing to validate VFIO for all use cases
- FSLMC bus VFIO code is not yet integrated, work is in progressFor testing, it is recommended to use the GitHub repository [8], as it will have all of the dependencies already integrated.
v3:
- Lots of compile fixes
- Fixes for multiprocess synchronization
- Introduced support for sPAPR IOMMU, courtesy of Gowrishankar @ IBM
- Fixes for mempool size calculation
- Added convenience memsegwalk()API's
- Added alloc validation callbackv2: - fixed deadlock at init
- revertedrte_panicchanges at init, this is now handled inside IPC
Quoted 9 lines
[1] http://dpdk.org/dev/patchwork/bundle/aburakov/Memory_RFC/
[2] http://dpdk.org/dev/patchwork/bundle/aburakov/IPC_Async_Request/
[3] http://dpdk.org/dev/patchwork/bundle/aburakov/Num_Sockets/
[4] http://dpdk.org/dev/patchwork/bundle/aburakov/IOVA_mode_fixes/
[5] http://dpdk.org/dev/patchwork/patch/34002/
[6] http://dpdk.org/dev/patchwork/patch/33853/
[7] http://dpdk.org/dev/patchwork/patch/24484/
[8] https://github.com/anatolyburakov/dpdk
Thanks for the huge work and continuously answering my barrage of questions. Here is the update for dpaa/dpaa2. Incremental to [1]:
Note: Results based on github repo (16fbfef04a37bb9d714), rather than this series over master. Though, it shouldn't make that big a difference.
PA: Physical Addressing mode
VA: Virtual Addressing mode
1. DPAA2 PA and VA work OK over the github repo
a. Almost equal performance for VA cases as compared to non-hotplug.
Whether in --legacy-mem or without it. ($ see below)
b. 70~90% drops in performance for PA case, depending on page size
used (# see below)
2. DPAA PA (there is no VA mode) works with a minor fix over v3 which Anatoly knows about might incorporate in v4 (Patch 50/68) a. 70-90% performance drop. (# see below)
($)
There are some changes in dpaa2 code base which I will share against relevant patch in this series. That can be incorporated into v4 to enable dpaa2 in VA mode.
(#)
Physical addressing cases for both, dpaa/dpaa2, depend heavily on the fact that physical addressing was the base and was available in sorted manner. This is reversed/negated with hotplugging support. So, rework of both the drivers is required from this perspective. There are some suggestions floated by Anatoly and internally, but work still needs to be done.
It also impacts a lot of use-cases for virtualization (no-iommu).
05/04/2018 16:24, Shreyansh Jain:
Quoted 7 lines
Physical addressing cases for both, dpaa/dpaa2, depend heavily on the fact that physical addressing was the base and was available in sorted manner. This is reversed/negated with hotplugging support. So, rework of both the drivers is required from this perspective. There are some suggestions floated by Anatoly and internally, but work still needs to be done.
It also impacts a lot of use-cases for virtualization (no-iommu).
So what is your recommendation?
Can you rework PA case in dpaa/dpaa2 drivers within 18.05 timeframe?
HI Thomas,
Quoted 25 lines
-----Original Message-----
From: Thomas Monjalon [mailto:[email protected]]
Sent: Thursday, April 05, 2018 7:43 PM
To: Shreyansh Jain <[email protected]>
Cc: Anatoly Burakov <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Hemant Agrawal <[email protected]>; [email protected]; [email protected]
Subject: Re: [dpdk-dev] [PATCH v3 00/68] Memory Hotplug for DPDK
Importance: High05/04/2018 16:24, Shreyansh Jain:
Quoted 7 lines
Physical addressing cases for both, dpaa/dpaa2, depend heavily on the fact that physical addressing was the base and was available in sorted manner. This is reversed/negated with hotplugging support. So, rework of both the drivers is required from this perspective. There are some suggestions floated by Anatoly and internally, but work still needs to be done.
It also impacts a lot of use-cases for virtualization (no-iommu).
Quoted 3 lines
So what is your recommendation?
Can you rework PA case in dpaa/dpaa2 drivers within 18.05 timeframe?
We will like 2-3 more days on this before we can ack/nack this patch. We are working on priority on this. PA case rework is not a trivial change.
Regards,
Hemant
Hemant Agrawal
Tested-byHi Thomas
Quoted 25 lines
Quoted 25 lines
-----Original Message-----
From: Thomas Monjalon [mailto:[email protected]]
Sent: Thursday, April 05, 2018 7:43 PM
To: Shreyansh Jain <[email protected]>
Cc: Anatoly Burakov <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Hemant Agrawal <[email protected]>; [email protected]; [email protected]
Subject: Re: [dpdk-dev] [PATCH v3 00/68] Memory Hotplug for DPDK
Importance: High05/04/2018 16:24, Shreyansh Jain:
Quoted 7 lines
Physical addressing cases for both, dpaa/dpaa2, depend heavily on the fact that physical addressing was the base and was available in sorted manner. This is reversed/negated with hotplugging support. So, rework of both the drivers is required from this perspective. There are some suggestions floated by Anatoly and internally, but work still needs to be done.
It also impacts a lot of use-cases for virtualization (no-iommu).
Quoted 5 lines
Quoted 3 lines
So what is your recommendation?
Can you rework PA case in dpaa/dpaa2 drivers within 18.05 timeframe?We will like 2-3 more days on this before we can ack/nack this patch. We are working on priority on this. PA case rework is not a trivial change.
The patch is good to go. However, we will be making changes in dpaa/dpaa2 drivers to fix the PA issues shortly (within 18.05 timeframe)
Anatoly needs to take care of following:
1. Comment by Shreyansh on " Re: [dpdk-dev] [PATCH v3 50/68] eal: replace memzone array with fbarray"
2. I could not apply the patches cleanly on current master.
Quoted 3 lines
Regards,
Hemant
Quoted 27 lines · Hemant Agrawal
Hi Thomas
Quoted 25 lines
Quoted 25 lines
-----Original Message-----
From: Thomas Monjalon [mailto:[email protected]]
Sent: Thursday, April 05, 2018 7:43 PM
To: Shreyansh Jain <[email protected]>
Cc: Anatoly Burakov <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Hemant Agrawal <[email protected]>; [email protected]; [email protected]
Subject: Re: [dpdk-dev] [PATCH v3 00/68] Memory Hotplug for DPDK
Importance: High05/04/2018 16:24, Shreyansh Jain:
Quoted 7 lines
Physical addressing cases for both, dpaa/dpaa2, depend heavily on the fact that physical addressing was the base and was available in sorted manner. This is reversed/negated with hotplugging support. So, rework of both the drivers is required from this perspective. There are some suggestions floated by Anatoly and internally, but work still needs to be done.
It also impacts a lot of use-cases for virtualization (no-iommu).
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
So what is your recommendation?
Can you rework PA case in dpaa/dpaa2 drivers within 18.05 timeframe?We will like 2-3 more days on this before we can ack/nack this patch. We are working on priority on this. PA case rework is not a trivial change.
The patch is good to go. However, we will be making changes in dpaa/dpaa2 drivers to fix the PA issues shortly (within 18.05 timeframe)
That's great to hear!
Quoted 3 lines
Anatoly needs to take care of following:
1. Comment by Shreyansh on " Re: [dpdk-dev] [PATCH v3 50/68] eal: replace memzone array with fbarray"
Yes, that is already fixed in both github and upcoming v4.
Quoted 1 line
2. I could not apply the patches cleanly on current master.
The patchset has dependencies, listed in the cover letter. I'll rebase on latest master before sending v4 just in case.
Quoted 8 lines
Tested-by Hemant Agrawal <[email protected]>Quoted 3 lines
Regards,
Hemant
Signature · 2 lines
Thanks, Anatoly
Hi Anatoly,
Quoted 64 lines · Anatoly Burakov
This patchset introduces dynamic memory allocation for DPDK (aka memory hotplug). Based upon RFC submitted in December [1].
Dependencies (to be applied in specified order):
- IPC asynchronous request API patch [2]
- Function to return number of sockets [3]
- EAL IOVA fix [4]Deprecation notices relevant to this patchset:
- General outline of memory hotplug changes [5]
- EAL NUMA node count changes [6]The vast majority of changes are in the EAL and malloc, the external API disruption is minimal: a new set of API's are added for contiguous memory allocation for
rte_memzone, and a few API additions inrte_memorydue to switch tomemseg_listsas opposed to memsegs. Every other API change is internal to EAL, and all of the memory allocation/freeing is handled throughrte_malloc, with no externally visible API changes.Quick outline of all changes done as part of this patchset:
* Malloc heap adjusted to handle holes in address space
* Single memseg list replaced by multiple memseg lists
* VA space for hugepages is preallocated in advance
* Added alloc/free for pages happening as needed on rte_malloc/rte_free
* Added contiguous memory allocation API's forrte_memzone
* Added convenience API calls to walk over memsegs
* Integrated Pawel Wodkowski's patch for registering/unregistering memory with VFIO [7]
* Callbacks for registering memory allocations
* Callbacks for allowing/disallowing allocations above specified limit
* Multiprocess support done via DPDK IPC introduced in 18.02The biggest difference is a "memseg" now represents a single page (as opposed to being a big contiguous block of pages). As a consequence, both memzones and malloc elements are no longer guaranteed to be physically contiguous, unless the user asks for it at reserve time. To preserve whatever functionality that was dependent on previous behavior, a legacy memory option is also provided, however it is expected (or perhaps vainly hoped) to be temporary solution.
Why multiple memseg lists instead of one? Since memseg is a single page now, the list of memsegs will get quite big, and we need to locate pages somehow when we allocate and free them. We could of course just walk the list and allocate one contiguous chunk of VA space for memsegs, but this implementation uses separate lists instead in order to speed up many operations with memseg lists.
For v3, the following limitations are present:
- VFIO support is only smoke-tested (but is expected to work), VFIO support with secondary processes is not tested; work is ongoing to validate VFIO for all use cases
- FSLMC bus VFIO code is not yet integrated, work is in progressFor testing, it is recommended to use the GitHub repository [8], as it will have all of the dependencies already integrated.
v3:
- Lots of compile fixes
- Fixes for multiprocess synchronization
- Introduced support for sPAPR IOMMU, courtesy of Gowrishankar @ IBM
- Fixes for mempool size calculation
- Added convenience memsegwalk()API's
- Added alloc validation callback
Quoted 2 lines
v2: - fixed deadlock at init
- revertedrte_panicchanges at init, this is now handled inside IPC