I'm not sure of the algorithm for "memory size" here.
Technically, DPDK can reserve memory segments anywhere in the VA
space allocated by memseg lists. That space may be far bigger than
system memory (on a typical Intel server board you'd see 128GB of VA
space preallocated even though the machine itself might only have,
say, 16GB of RAM installed). The same applies to any other arch
running on Linux, so the window needs to cover at least
RTE_MIN(base_virtaddr, lowest memseglist VA address) and up to
highest memseglist VA address. That's not even mentioning the fact
that the user may register external memory for DMA which may cause
the window to be of insufficient size to cover said external memory.
I also think that in general, "system memory" metric is ill suited
for measuring VA space, because unlike system memory, the VA space is
sparse and can therefore span *a lot* of address space even though in
reality it may actually use very little physical memory.
I'm open to suggestions here. Perhaps an alternative in /proc/meminfo:
VmallocTotal: 549755813888 kB
I tested it with 1GB hugepages and it works, need to check with 2M as
well. If there's no alternative for sizing the window based on
available system parameters then I have another option which creates a
new RTE_IOVA_TA mode that forces IOVA addresses into the range 0 to X
where X is configured on the EAL command-line (--iova-base,
--iova-len). I use these command-line values to create a static window.
A whole new IOVA mode, while being a cleaner solution, would require a
lot of testing, and it doesn't really solve the external memory problem,
because we're still reliant on the user to provide IOVA addresses.
Perhaps something akin to VA/IOVA address reservation would solve the
problem, but again, lots of changes and testing, all for a comparatively
narrow use case.
The vmalloc area seems big enough (512 terabytes on your machine, 32
terabytes on mine), so it'll probably be OK. I'd settle for:
1) start at base_virtaddr OR lowest memseg list address, whichever is
lowest
The IOMMU only supports two starting addresses, 0 or 1<<59, so
implementation will need to start at 0. (I've been bit by this before,
my understanding is that the processor only supports 54 bits of the
address and that the PCI host bridge uses bit 59 of the IOVA as a signal
to do the address translation for the second DMA window.)
2) end at lowest addr + VmallocTotal OR highest memseglist addr,
whichever is higher
So, instead of rte_memseg_walk() execute rte_memseg_list_walk() to find
the lowest/highest msl addresses?
3) a check in user DMA map function that would warn/throw an error
whenever there is an attempt to map an address for DMA that doesn't fit
into the DMA window
Isn't this mostly prevented by the use of rte_mem_set_dma_mask() and
rte_mem_check_dma_mask()? I'd expect an error would be thrown by the
kernel IOMMU API for an out-of-range mapping that I would simply return
to the caller (drivers/vfio/vfio_iommu_spapr_tce.c includes the comment
/* iova is checked by the IOMMU API */). Why do you think double
checking this would help?
I think that would be best approach. Thoughts?
Dave