git: 254e4e5b77d7 - main - Simplify swi for bus_dma.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 28 Dec 2021 21:53:07 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=254e4e5b77d7788c46333ae35d5e9f347e22c746

commit 254e4e5b77d7788c46333ae35d5e9f347e22c746
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2021-12-28 21:51:25 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-12-28 21:51:25 +0000

    Simplify swi for bus_dma.
    
    When a DMA request using bounce pages completes, a swi is triggered to
    schedule pending DMA requests using the just-freed bounce pages.  For
    a long time this bus_dma swi has been tied to a "virtual memory" swi
    (swi_vm).  However, all of the swi_vm implementations are the same and
    consist of checking a flag (busdma_swi_pending) which is always true
    and if set calling busdma_swi.  I suspect this dates back to the
    pre-SMPng days and that the intention was for swi_vm to serve as a
    mux.  However, in the current scheme there's no need for the mux.
    
    Instead, remove swi_vm and vm_ih.  Each bus_dma implementation that
    uses bounce pages is responsible for creating its own swi (busdma_ih)
    which it now schedules directly.  This swi invokes busdma_swi directly
    removing the need for busdma_swi_pending.
    
    One consequence is that the swi now works on RISC-V which had previously
    failed to invoke busdma_swi from swi_vm.
    
    Reviewed by:    imp, kib
    Sponsored by:   Netflix
    Differential Revision:  https://reviews.freebsd.org/D33447
---
 sys/amd64/amd64/vm_machdep.c         | 10 ----------
 sys/amd64/include/cpu.h              |  1 -
 sys/arm/arm/busdma_machdep.c         | 24 ++++++++++++++++++------
 sys/arm/arm/vm_machdep.c             | 11 -----------
 sys/arm/include/cpu.h                |  1 -
 sys/arm/include/md_var.h             |  2 --
 sys/arm64/arm64/busdma_bounce.c      | 24 ++++++++++++++++++------
 sys/arm64/arm64/vm_machdep.c         |  8 --------
 sys/arm64/include/cpu.h              |  1 -
 sys/arm64/include/md_var.h           |  2 --
 sys/i386/i386/vm_machdep.c           | 10 ----------
 sys/i386/include/cpu.h               |  1 -
 sys/kern/kern_intr.c                 |  3 ---
 sys/mips/include/cpu.h               |  1 -
 sys/mips/include/md_var.h            |  3 ---
 sys/mips/mips/busdma_machdep.c       | 24 ++++++++++++++++++------
 sys/mips/mips/vm_machdep.c           | 11 -----------
 sys/powerpc/include/cpu.h            |  1 -
 sys/powerpc/include/md_var.h         |  2 --
 sys/powerpc/powerpc/busdma_machdep.c | 24 ++++++++++++++++++------
 sys/powerpc/powerpc/vm_machdep.c     | 11 -----------
 sys/riscv/include/cpu.h              |  1 -
 sys/riscv/include/md_var.h           |  1 -
 sys/riscv/riscv/busdma_bounce.c      | 24 ++++++++++++++++++------
 sys/riscv/riscv/vm_machdep.c         |  7 -------
 sys/sys/interrupt.h                  |  2 +-
 sys/x86/include/x86_var.h            |  2 --
 sys/x86/x86/busdma_bounce.c          | 24 ++++++++++++++++++------
 28 files changed, 109 insertions(+), 127 deletions(-)

diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index c0456c1d958c..232e53c63952 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -691,16 +691,6 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
 	return (0);
 }
 
-/*
- * Software interrupt handler for queued VM system processing.
- */   
-void  
-swi_vm(void *dummy) 
-{     
-	if (busdma_swi_pending != 0)
-		busdma_swi();
-}
-
 /*
  * Tell whether this address is in some physical memory region.
  * Currently used by the kernel coredump code in order to avoid
diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h
index 1b8a552d3e7c..f7732435fc39 100644
--- a/sys/amd64/include/cpu.h
+++ b/sys/amd64/include/cpu.h
@@ -80,7 +80,6 @@ void	cpu_halt(void);
 void	cpu_lock_delay(void);
 void	cpu_reset(void);
 void	fork_trampoline(void);
-void	swi_vm(void *);
 
 /*
  * Return contents of in-cpu fast counter as a sort of "bogo-time"
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index caa9ae43834e..11c306526e0d 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -114,8 +114,6 @@ struct sync_list {
 	bus_size_t	datacount;	/* client data count */
 };
 
-int busdma_swi_pending;
-
 struct bounce_zone {
 	STAILQ_ENTRY(bounce_zone) links;
 	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -151,6 +149,7 @@ static counter_u64_t maploads_physmem;
 #endif
 
 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+static void *busdma_ih;
 
 SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "Busdma parameters");
@@ -1714,6 +1713,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 {
 	struct bus_dmamap *map;
 	struct bounce_zone *bz;
+	bool schedule_swi;
 
 	bz = dmat->bounce_zone;
 	bpage->datavaddr = 0;
@@ -1728,6 +1728,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 		bpage->busaddr &= ~PAGE_MASK;
 	}
 
+	schedule_swi = false;
 	mtx_lock(&bounce_lock);
 	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
 	bz->free_bpages++;
@@ -1737,16 +1738,17 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
 			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
 			    map, links);
-			busdma_swi_pending = 1;
 			bz->total_deferred++;
-			swi_sched(vm_ih, 0);
+			schedule_swi = true;
 		}
 	}
 	mtx_unlock(&bounce_lock);
+	if (schedule_swi)
+		swi_sched(busdma_ih, 0);
 }
 
-void
-busdma_swi(void)
+static void
+busdma_swi(void *dummy __unused)
 {
 	bus_dma_tag_t dmat;
 	struct bus_dmamap *map;
@@ -1764,3 +1766,13 @@ busdma_swi(void)
 	}
 	mtx_unlock(&bounce_lock);
 }
+
+static void
+start_busdma_swi(void *dummy __unused)
+{
+	if (swi_add(NULL, "busdma", busdma_swi, NULL, SWI_BUSDMA, INTR_MPSAFE,
+	    &busdma_ih))
+		panic("died while creating busdma swi ithread");
+}
+SYSINIT(start_busdma_swi, SI_SUB_SOFTINTR, SI_ORDER_ANY, start_busdma_swi,
+    NULL);
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index ba44aa162e8b..5f21a92d2b8b 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -290,17 +290,6 @@ cpu_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg)
 	td->td_pcb->pcb_regs.sf_r5 = (register_t)arg;	/* first arg */
 }
 
-/*
- * Software interrupt handler for queued VM system processing.
- */
-void
-swi_vm(void *dummy)
-{
-
-	if (busdma_swi_pending)
-		busdma_swi();
-}
-
 void
 cpu_exit(struct thread *td)
 {
diff --git a/sys/arm/include/cpu.h b/sys/arm/include/cpu.h
index 8937a87aebea..14e19581b819 100644
--- a/sys/arm/include/cpu.h
+++ b/sys/arm/include/cpu.h
@@ -8,7 +8,6 @@
 #include <machine/frame.h>
 
 void	cpu_halt(void);
-void	swi_vm(void *);
 
 #ifdef _KERNEL
 #include <machine/cpu-v6.h>
diff --git a/sys/arm/include/md_var.h b/sys/arm/include/md_var.h
index 63f9f8256672..b41a24247951 100644
--- a/sys/arm/include/md_var.h
+++ b/sys/arm/include/md_var.h
@@ -53,8 +53,6 @@ extern enum cpu_class cpu_class;
 
 struct dumperinfo;
 struct minidumpstate;
-extern int busdma_swi_pending;
-void busdma_swi(void);
 int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
 
 extern uint32_t initial_fpscr;
diff --git a/sys/arm64/arm64/busdma_bounce.c b/sys/arm64/arm64/busdma_bounce.c
index b2d00b9c0abd..ef2608d2dadc 100644
--- a/sys/arm64/arm64/busdma_bounce.c
+++ b/sys/arm64/arm64/busdma_bounce.c
@@ -90,8 +90,6 @@ struct bounce_page {
 	STAILQ_ENTRY(bounce_page) links;
 };
 
-int busdma_swi_pending;
-
 struct bounce_zone {
 	STAILQ_ENTRY(bounce_zone) links;
 	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -114,6 +112,7 @@ static struct mtx bounce_lock;
 static int total_bpages;
 static int busdma_zonecount;
 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+static void *busdma_ih;
 
 static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "Busdma parameters");
@@ -1417,6 +1416,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 {
 	struct bus_dmamap *map;
 	struct bounce_zone *bz;
+	bool schedule_swi;
 
 	bz = dmat->bounce_zone;
 	bpage->datavaddr = 0;
@@ -1431,6 +1431,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 		bpage->busaddr &= ~PAGE_MASK;
 	}
 
+	schedule_swi = false;
 	mtx_lock(&bounce_lock);
 	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
 	bz->free_bpages++;
@@ -1440,16 +1441,17 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
 			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
 			    map, links);
-			busdma_swi_pending = 1;
 			bz->total_deferred++;
-			swi_sched(vm_ih, 0);
+			schedule_swi = true;
 		}
 	}
 	mtx_unlock(&bounce_lock);
+	if (schedule_swi)
+		swi_sched(busdma_ih, 0);
 }
 
-void
-busdma_swi(void)
+static void
+busdma_swi(void *dummy __unused)
 {
 	bus_dma_tag_t dmat;
 	struct bus_dmamap *map;
@@ -1469,6 +1471,16 @@ busdma_swi(void)
 	mtx_unlock(&bounce_lock);
 }
 
+static void
+start_busdma_swi(void *dummy __unused)
+{
+	if (swi_add(NULL, "busdma", busdma_swi, NULL, SWI_BUSDMA, INTR_MPSAFE,
+	    &busdma_ih))
+		panic("died while creating busdma swi ithread");
+}
+SYSINIT(start_busdma_swi, SI_SUB_SOFTINTR, SI_ORDER_ANY, start_busdma_swi,
+    NULL);
+
 struct bus_dma_impl bus_dma_bounce_impl = {
 	.tag_create = bounce_bus_dma_tag_create,
 	.tag_destroy = bounce_bus_dma_tag_destroy,
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
index 2db20427c977..2b6a9dfebe82 100644
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -304,11 +304,3 @@ cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
 
 	return (EINVAL);
 }
-
-void
-swi_vm(void *v)
-{
-
-	if (busdma_swi_pending != 0)
-		busdma_swi();
-}
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
index c926372a0ec6..b96767ddd2d5 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -170,7 +170,6 @@ void	fork_trampoline(void);
 void	identify_cache(uint64_t);
 void	identify_cpu(u_int);
 void	install_cpu_errata(void);
-void	swi_vm(void *v);
 
 /* Functions to read the sanitised view of the special registers */
 void	update_special_regs(u_int);
diff --git a/sys/arm64/include/md_var.h b/sys/arm64/include/md_var.h
index 46a4737a6247..6c78317c830c 100644
--- a/sys/arm64/include/md_var.h
+++ b/sys/arm64/include/md_var.h
@@ -46,8 +46,6 @@ extern u_long elf32_hwcap2;
 struct dumperinfo;
 struct minidumpstate;
 
-extern int busdma_swi_pending;
-void busdma_swi(void);
 int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
 void generic_bs_fault(void) __asm(__STRING(generic_bs_fault));
 void generic_bs_peek_1(void) __asm(__STRING(generic_bs_peek_1));
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 5cdcdee96347..9dbcb9c909ce 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -651,16 +651,6 @@ sf_buf_invalidate_cache(vm_page_t m)
 	return (sf_buf_process_page(m, sf_buf_invalidate));
 }
 
-/*
- * Software interrupt handler for queued VM system processing.
- */   
-void  
-swi_vm(void *dummy) 
-{     
-	if (busdma_swi_pending != 0)
-		busdma_swi();
-}
-
 /*
  * Tell whether this address is in some physical memory region.
  * Currently used by the kernel coredump code in order to avoid
diff --git a/sys/i386/include/cpu.h b/sys/i386/include/cpu.h
index 8ba5e455f714..df35c9e92cc7 100644
--- a/sys/i386/include/cpu.h
+++ b/sys/i386/include/cpu.h
@@ -75,7 +75,6 @@ void	cpu_halt(void);
 void	cpu_lock_delay(void);
 void	cpu_reset(void);
 void	fork_trampoline(void);
-void	swi_vm(void *);
 
 /*
  * Return contents of in-cpu fast counter as a sort of "bogo-time"
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 4e6e575a9fc9..3637b556af5d 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -90,7 +90,6 @@ struct	intr_entropy {
 
 struct	intr_event *clk_intr_event;
 struct	intr_event *tty_intr_event;
-void	*vm_ih;
 struct proc *intrproc;
 
 static MALLOC_DEFINE(M_ITHREAD, "ithread", "Interrupt Threads");
@@ -1639,8 +1638,6 @@ start_softintr(void *dummy)
 	if (swi_add(&clk_intr_event, "clk", NULL, NULL, SWI_CLOCK,
 	    INTR_MPSAFE, NULL))
 		panic("died while creating clk swi ithread");
-	if (swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, INTR_MPSAFE, &vm_ih))
-		panic("died while creating vm swi ithread");
 }
 SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr,
     NULL);
diff --git a/sys/mips/include/cpu.h b/sys/mips/include/cpu.h
index b4f5c59f72f5..aaec97aa25f1 100644
--- a/sys/mips/include/cpu.h
+++ b/sys/mips/include/cpu.h
@@ -84,7 +84,6 @@
 extern char btext[];
 extern char etext[];
 
-void swi_vm(void *);
 void cpu_halt(void);
 void cpu_reset(void);
 
diff --git a/sys/mips/include/md_var.h b/sys/mips/include/md_var.h
index ca2afa9a3616..138047a13b47 100644
--- a/sys/mips/include/md_var.h
+++ b/sys/mips/include/md_var.h
@@ -78,9 +78,6 @@ void	mips_postboot_fixup(void);
 void	cpu_identify(void);
 void	cpu_switch_set_userlocal(void) __asm(__STRING(cpu_switch_set_userlocal));
 
-extern int busdma_swi_pending;
-void	busdma_swi(void);
-
 struct	dumperinfo;
 struct	minidumpstate;
 int	cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
diff --git a/sys/mips/mips/busdma_machdep.c b/sys/mips/mips/busdma_machdep.c
index 80e57cd0414f..f408ca8f4260 100644
--- a/sys/mips/mips/busdma_machdep.c
+++ b/sys/mips/mips/busdma_machdep.c
@@ -117,8 +117,6 @@ struct sync_list {
 	bus_size_t	datacount;	/* client data count */
 };
 
-int busdma_swi_pending;
-
 struct bounce_zone {
 	STAILQ_ENTRY(bounce_zone) links;
 	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -141,6 +139,7 @@ static struct mtx bounce_lock;
 static int total_bpages;
 static int busdma_zonecount;
 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+static void *busdma_ih;
 
 static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0,
     "Busdma parameters");
@@ -1485,6 +1484,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 {
 	struct bus_dmamap *map;
 	struct bounce_zone *bz;
+	bool schedule_swi;
 
 	bz = dmat->bounce_zone;
 	bpage->datavaddr = 0;
@@ -1499,6 +1499,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 		bpage->busaddr &= ~PAGE_MASK;
 	}
 
+	schedule_swi = false;
 	mtx_lock(&bounce_lock);
 	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
 	bz->free_bpages++;
@@ -1508,16 +1509,17 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
 			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
 					   map, links);
-			busdma_swi_pending = 1;
 			bz->total_deferred++;
-			swi_sched(vm_ih, 0);
+			schedule_swi = true;
 		}
 	}
 	mtx_unlock(&bounce_lock);
+	if (schedule_swi)
+		swi_sched(busdma_ih, 0);
 }
 
-void
-busdma_swi(void)
+static void
+busdma_swi(void *dummy __unused)
 {
 	bus_dma_tag_t dmat;
 	struct bus_dmamap *map;
@@ -1535,3 +1537,13 @@ busdma_swi(void)
 	}
 	mtx_unlock(&bounce_lock);
 }
+
+static void
+start_busdma_swi(void *dummy __unused)
+{
+	if (swi_add(NULL, "busdma", busdma_swi, NULL, SWI_BUSDMA, INTR_MPSAFE,
+	    &busdma_ih))
+		panic("died while creating busdma swi ithread");
+}
+SYSINIT(start_busdma_swi, SI_SUB_SOFTINTR, SI_ORDER_ANY, start_busdma_swi,
+    NULL);
diff --git a/sys/mips/mips/vm_machdep.c b/sys/mips/mips/vm_machdep.c
index a635bace4a09..eb313e2da8de 100644
--- a/sys/mips/mips/vm_machdep.c
+++ b/sys/mips/mips/vm_machdep.c
@@ -459,17 +459,6 @@ cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
 	return (EINVAL);
 }
 
-/*
- * Software interrupt handler for queued VM system processing.
- */
-void
-swi_vm(void *dummy)
-{
-
-	if (busdma_swi_pending)
-		busdma_swi();
-}
-
 int
 cpu_set_user_tls(struct thread *td, void *tls_base)
 {
diff --git a/sys/powerpc/include/cpu.h b/sys/powerpc/include/cpu.h
index 256e6d3eabf0..6eaa4a48a900 100644
--- a/sys/powerpc/include/cpu.h
+++ b/sys/powerpc/include/cpu.h
@@ -146,7 +146,6 @@ void	cpu_halt(void);
 void	cpu_reset(void);
 void	flush_disable_caches(void);
 void	fork_trampoline(void);
-void	swi_vm(void *);
 int	cpu_machine_check(struct thread *, struct trapframe *, int *);
 
 
diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h
index 6e74000340b9..56c3639fe070 100644
--- a/sys/powerpc/include/md_var.h
+++ b/sys/powerpc/include/md_var.h
@@ -48,7 +48,6 @@ int	cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
 #endif
 
 extern	long	Maxmem;
-extern	int	busdma_swi_pending;
 
 extern	vm_offset_t	kstack0;
 extern	vm_offset_t	kstack0_phys;
@@ -59,7 +58,6 @@ extern  int hw_direct_map;
 
 void	__syncicache(void *, int);
 
-void	busdma_swi(void);
 int	is_physical_memory(vm_offset_t addr);
 int	mem_valid(vm_offset_t addr, int len);
 
diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c
index d513b7e65538..44d101613e0c 100644
--- a/sys/powerpc/powerpc/busdma_machdep.c
+++ b/sys/powerpc/powerpc/busdma_machdep.c
@@ -95,8 +95,6 @@ struct bounce_page {
 	STAILQ_ENTRY(bounce_page) links;
 };
 
-int busdma_swi_pending;
-
 struct bounce_zone {
 	STAILQ_ENTRY(bounce_zone) links;
 	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -119,6 +117,7 @@ static struct mtx bounce_lock;
 static int total_bpages;
 static int busdma_zonecount;
 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+static void *busdma_ih;
 
 static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "Busdma parameters");
@@ -1178,6 +1177,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 {
 	struct bus_dmamap *map;
 	struct bounce_zone *bz;
+	bool schedule_swi;
 
 	bz = dmat->bounce_zone;
 	bpage->datavaddr = 0;
@@ -1192,6 +1192,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 		bpage->busaddr &= ~PAGE_MASK;
 	}
 
+	schedule_swi = false;
 	mtx_lock(&bounce_lock);
 	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
 	bz->free_bpages++;
@@ -1201,16 +1202,17 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
 			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
 					   map, links);
-			busdma_swi_pending = 1;
 			bz->total_deferred++;
-			swi_sched(vm_ih, 0);
+			schedule_swi = true;
 		}
 	}
 	mtx_unlock(&bounce_lock);
+	if (schedule_swi)
+		swi_sched(busdma_ih, 0);
 }
 
-void
-busdma_swi(void)
+static void
+busdma_swi(void *dummy __unused)
 {
 	bus_dma_tag_t dmat;
 	struct bus_dmamap *map;
@@ -1230,6 +1232,16 @@ busdma_swi(void)
 	mtx_unlock(&bounce_lock);
 }
 
+static void
+start_busdma_swi(void *dummy __unused)
+{
+	if (swi_add(NULL, "busdma", busdma_swi, NULL, SWI_BUSDMA, INTR_MPSAFE,
+	    &busdma_ih))
+		panic("died while creating busdma swi ithread");
+}
+SYSINIT(start_busdma_swi, SI_SUB_SOFTINTR, SI_ORDER_ANY, start_busdma_swi,
+    NULL);
+
 int
 bus_dma_tag_set_iommu(bus_dma_tag_t tag, device_t iommu, void *cookie)
 {
diff --git a/sys/powerpc/powerpc/vm_machdep.c b/sys/powerpc/powerpc/vm_machdep.c
index a7de9f0f6a1f..4a7347443407 100644
--- a/sys/powerpc/powerpc/vm_machdep.c
+++ b/sys/powerpc/powerpc/vm_machdep.c
@@ -208,17 +208,6 @@ cpu_exit(struct thread *td)
 
 }
 
-/*
- * Software interrupt handler for queued VM system processing.
- */
-void
-swi_vm(void *dummy)
-{
-
-	if (busdma_swi_pending != 0)
-		busdma_swi();
-}
-
 /*
  * Tell whether this address is in some physical memory region.
  * Currently used by the kernel coredump code in order to avoid
diff --git a/sys/riscv/include/cpu.h b/sys/riscv/include/cpu.h
index 453a6af1a0f8..ee7b1111af56 100644
--- a/sys/riscv/include/cpu.h
+++ b/sys/riscv/include/cpu.h
@@ -81,7 +81,6 @@ void	cpu_halt(void) __dead2;
 void	cpu_reset(void) __dead2;
 void	fork_trampoline(void);
 void	identify_cpu(void);
-void	swi_vm(void *v);
 
 static __inline uint64_t
 get_cyclecount(void)
diff --git a/sys/riscv/include/md_var.h b/sys/riscv/include/md_var.h
index 56007cd0c155..890f569782a3 100644
--- a/sys/riscv/include/md_var.h
+++ b/sys/riscv/include/md_var.h
@@ -44,7 +44,6 @@ extern register_t mimpid;
 struct dumperinfo;
 struct minidumpstate;
 
-void busdma_swi(void);
 int cpu_minidumpsys(struct dumperinfo *, const struct minidumpstate *);
 
 #endif /* !_MACHINE_MD_VAR_H_ */
diff --git a/sys/riscv/riscv/busdma_bounce.c b/sys/riscv/riscv/busdma_bounce.c
index 8ca803f13cd4..f6dde12fafbb 100644
--- a/sys/riscv/riscv/busdma_bounce.c
+++ b/sys/riscv/riscv/busdma_bounce.c
@@ -88,8 +88,6 @@ struct bounce_page {
 	STAILQ_ENTRY(bounce_page) links;
 };
 
-int busdma_swi_pending;
-
 struct bounce_zone {
 	STAILQ_ENTRY(bounce_zone) links;
 	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -112,6 +110,7 @@ static struct mtx bounce_lock;
 static int total_bpages;
 static int busdma_zonecount;
 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+static void *busdma_ih;
 
 static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "Busdma parameters");
@@ -1260,6 +1259,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 {
 	struct bus_dmamap *map;
 	struct bounce_zone *bz;
+	bool schedule_swi;
 
 	bz = dmat->bounce_zone;
 	bpage->datavaddr = 0;
@@ -1274,6 +1274,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 		bpage->busaddr &= ~PAGE_MASK;
 	}
 
+	schedule_swi = false;
 	mtx_lock(&bounce_lock);
 	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
 	bz->free_bpages++;
@@ -1283,16 +1284,17 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
 			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
 			    map, links);
-			busdma_swi_pending = 1;
 			bz->total_deferred++;
-			swi_sched(vm_ih, 0);
+			schedule_swi = true;
 		}
 	}
 	mtx_unlock(&bounce_lock);
+	if (schedule_swi)
+		swi_sched(busdma_ih, 0);
 }
 
-void
-busdma_swi(void)
+static void
+busdma_swi(void *dummy __unused)
 {
 	bus_dma_tag_t dmat;
 	struct bus_dmamap *map;
@@ -1312,6 +1314,16 @@ busdma_swi(void)
 	mtx_unlock(&bounce_lock);
 }
 
+static void
+start_busdma_swi(void *dummy __unused)
+{
+	if (swi_add(NULL, "busdma", busdma_swi, NULL, SWI_BUSDMA, INTR_MPSAFE,
+	    &busdma_ih))
+		panic("died while creating busdma swi ithread");
+}
+SYSINIT(start_busdma_swi, SI_SUB_SOFTINTR, SI_ORDER_ANY, start_busdma_swi,
+    NULL);
+
 struct bus_dma_impl bus_dma_bounce_impl = {
 	.tag_create = bounce_bus_dma_tag_create,
 	.tag_destroy = bounce_bus_dma_tag_destroy,
diff --git a/sys/riscv/riscv/vm_machdep.c b/sys/riscv/riscv/vm_machdep.c
index 094662413f4e..84b7fec1516d 100644
--- a/sys/riscv/riscv/vm_machdep.c
+++ b/sys/riscv/riscv/vm_machdep.c
@@ -269,10 +269,3 @@ cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
 
 	return (EINVAL);
 }
-
-void
-swi_vm(void *v)
-{
-
-	/* Nothing to do here - busdma bounce buffers are not implemented. */
-}
diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h
index 56952e45fe75..b333c5f74b65 100644
--- a/sys/sys/interrupt.h
+++ b/sys/sys/interrupt.h
@@ -144,7 +144,7 @@ struct intr_event {
 #define	SWI_TTY		0
 #define	SWI_NET		1
 #define	SWI_CAMBIO	2
-#define	SWI_VM		3
+#define	SWI_BUSDMA	3
 #define	SWI_CLOCK	4
 #define	SWI_TQ_FAST	5
 #define	SWI_TQ		6
diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h
index 47b630d076d2..78acadd2b733 100644
--- a/sys/x86/include/x86_var.h
+++ b/sys/x86/include/x86_var.h
@@ -38,7 +38,6 @@
 
 extern	long	Maxmem;
 extern	u_int	basemem;
-extern	int	busdma_swi_pending;
 extern	u_int	cpu_exthigh;
 extern	u_int	cpu_feature;
 extern	u_int	cpu_feature2;
@@ -115,7 +114,6 @@ typedef void alias_for_inthand_t(void);
 
 bool	acpi_get_fadt_bootflags(uint16_t *flagsp);
 void	*alloc_fpusave(int flags);
-void	busdma_swi(void);
 u_int	cpu_auxmsr(void);
 vm_paddr_t cpu_getmaxphyaddr(void);
 bool	cpu_mwait_usable(void);
diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c
index ee6d2d50d542..7afa4cf6e2aa 100644
--- a/sys/x86/x86/busdma_bounce.c
+++ b/sys/x86/x86/busdma_bounce.c
@@ -90,8 +90,6 @@ struct bounce_page {
 	STAILQ_ENTRY(bounce_page) links;
 };
 
-int busdma_swi_pending;
-
 struct bounce_zone {
 	STAILQ_ENTRY(bounce_zone) links;
 	STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
@@ -115,6 +113,7 @@ static struct mtx bounce_lock;
 static int total_bpages;
 static int busdma_zonecount;
 static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+static void *busdma_ih;
 
 static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "Busdma parameters");
@@ -1311,6 +1310,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 {
 	struct bus_dmamap *map;
 	struct bounce_zone *bz;
+	bool schedule_swi;
 
 	bz = dmat->bounce_zone;
 	bpage->datavaddr = 0;
@@ -1325,6 +1325,7 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 		bpage->busaddr &= ~PAGE_MASK;
 	}
 
+	schedule_swi = false;
 	mtx_lock(&bounce_lock);
 	STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
 	bz->free_bpages++;
@@ -1334,16 +1335,17 @@ free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
 			STAILQ_REMOVE_HEAD(&bounce_map_waitinglist, links);
 			STAILQ_INSERT_TAIL(&bounce_map_callbacklist,
 			    map, links);
-			busdma_swi_pending = 1;
 			bz->total_deferred++;
-			swi_sched(vm_ih, 0);
+			schedule_swi = true;
 		}
 	}
 	mtx_unlock(&bounce_lock);
+	if (schedule_swi)
+		swi_sched(busdma_ih, 0);
 }
 
-void
-busdma_swi(void)
+static void
+busdma_swi(void *dummy __unused)
 {
 	bus_dma_tag_t dmat;
 	struct bus_dmamap *map;
@@ -1363,6 +1365,16 @@ busdma_swi(void)
 	mtx_unlock(&bounce_lock);
 }
 
+static void
+start_busdma_swi(void *dummy __unused)
+{
+	if (swi_add(NULL, "busdma", busdma_swi, NULL, SWI_BUSDMA, INTR_MPSAFE,
+	    &busdma_ih))
+		panic("died while creating busdma swi ithread");
+}
+SYSINIT(start_busdma_swi, SI_SUB_SOFTINTR, SI_ORDER_ANY, start_busdma_swi,
+    NULL);
+
 struct bus_dma_impl bus_dma_bounce_impl = {
 	.tag_create = bounce_bus_dma_tag_create,
 	.tag_destroy = bounce_bus_dma_tag_destroy,