On Sat, 22 Oct 2022, Colin Percival wrote:
The branch main has been updated by cperciva:
URL:
https://cgit.FreeBSD.org/src/commit/?id=b7761f1f0830fc4b4bd7a1f9f364cfb39b7f4288
commit b7761f1f0830fc4b4bd7a1f9f364cfb39b7f4288
Author: Colin Percival <[email protected]>
AuthorDate: 2022-10-21 18:13:36 +0000
Commit: Colin Percival <[email protected]>
CommitDate: 2022-10-22 05:47:33 +0000
x86/busdma: Limit reserved pages if low nsegs
When bus_dmamap_create is called, if bouncing might be required we
reserve enough pages for a maximum-length request, subject to the
MAX_BPAGES constraint (32 MB on amd64; 32 MB or 2 MB on i386
depending on the amount of RAM).
Since pages used for bouncing are typically non-consecutive, each
bounced page will typically constitute a busdma segment; as such, we
are unlikely to ever successfully use more pages than the nsegments
limit. Limit the number of pages reserved to nsegments.
This is an interesting observation. LinuxKPI desperately needs more
consecutive pages but can only ever use one segment.
We do have observed cases of bouncing failing due to the LinuxKPI
constraints and what busdma provided.
I wonder if this is going to make it even harder to by any chance have
consecutive pages?
I've been trying for a good year to find someone to look into that.
There's also other maths which are highly questionable in the bounce
parts (c&p and altered between archs). In case anyone is interested
in reviewing some bits please get in contact with me.
On FreeBSD/Firecracker, this reduces bounce page memory consumption
from 32 MB to 512 kB, making VMs with 128 MB of RAM usable.
Reviewed by: imp, mav
Sponsored by: https://www.patreon.com/cperciva
Differential Revision: https://reviews.freebsd.org/D37082
---
sys/x86/x86/busdma_bounce.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c
index faed4b7353cc..cf919c01ca64 100644
--- a/sys/x86/x86/busdma_bounce.c
+++ b/sys/x86/x86/busdma_bounce.c
@@ -325,6 +325,7 @@ bounce_bus_dmamap_create(bus_dma_tag_t dmat, int flags,
bus_dmamap_t *mapp)
if ((dmat->bounce_flags & BUS_DMA_MIN_ALLOC_COMP) == 0 ||
(bz->map_count > 0 && bz->total_bpages < maxpages)) {
pages = MAX(atop(dmat->common.maxsize), 1);
+ pages = MIN(dmat->common.nsegments, pages);
pages = MIN(maxpages - bz->total_bpages, pages);
pages = MAX(pages, 1);
if (alloc_bounce_pages(dmat, pages) < pages)
--
Bjoern A. Zeeb r15:7