Index | Thread | Search

From:
Stefan Fritsch <sf@openbsd.org>
Subject:
fix bus_dmamap_destroy with bounce buffers
To:
tech@openbsd.org
Date:
Tue, 20 Aug 2024 09:55:59 +0200

Download raw body.

Thread
Hi,

with bounce buffers, we must pass a larger size to free(). Otherwise 
various drivers (azalia, xhci) cause a panic if bounce buffering is 
enabled on KVM/qemu.

ok?

Cheers,
Stefan

diff --git a/sys/arch/amd64/amd64/bus_dma.c b/sys/arch/amd64/amd64/bus_dma.c
index 6ad6583bce9..e758ea9ea05 100644
--- a/sys/arch/amd64/amd64/bus_dma.c
+++ b/sys/arch/amd64/amd64/bus_dma.c
@@ -223,12 +223,18 @@ _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
 	size_t mapsize;
 	struct vm_page **pg;
 	struct pglist mlist;
+	int use_bounce_buffer = cpu_sev_guestmode || FORCE_BOUNCE_BUFFER;
 
 	if (map->_dm_pgva) {
 		km_free((void *)map->_dm_pgva, map->_dm_npages << PGSHIFT,
 		    &kv_any, &kp_none);
 	}
 
+	mapsize = sizeof(struct bus_dmamap) +
+		(sizeof(bus_dma_segment_t) * (map->_dm_segcnt - 1));
+	if (use_bounce_buffer)
+		mapsize += sizeof(struct vm_page *) * map->_dm_npages;
+
 	if (map->_dm_pages) {
 		TAILQ_INIT(&mlist);
 		for (pg = map->_dm_pages; map->_dm_npages--; pg++) {
@@ -237,8 +243,6 @@ _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
 		uvm_pglistfree(&mlist);
 	}
 
-	mapsize = sizeof(struct bus_dmamap) +
-		(sizeof(bus_dma_segment_t) * (map->_dm_segcnt - 1));
 	free(map, M_DEVBUF, mapsize);
 }