diff --git a/sys/arm64/arm64/autoconf.c b/sys/arm64/arm64/autoconf.c --- a/sys/arm64/arm64/autoconf.c +++ b/sys/arm64/arm64/autoconf.c @@ -69,9 +69,10 @@ static void configure(void *dummy) { - + bus_topo_lock(); /* initialize new bus architecture */ root_bus_configure(); + bus_topo_unlock(); } static void diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c --- a/sys/dev/hyperv/vmbus/vmbus.c +++ b/sys/dev/hyperv/vmbus/vmbus.c @@ -596,7 +596,7 @@ */ bus_topo_assert(); while (!sc->vmbus_scandone) - mtx_sleep(&sc->vmbus_scandone, bus_topo_mtx(), 0, "vmbusdev", 0); + bus_topo_sleep(&sc->vmbus_scandone, 0, "vmbusdev"); if (bootverbose) { device_printf(sc->vmbus_dev, "device scan, probe and attach " diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c --- a/sys/dev/pci/pci_pci.c +++ b/sys/dev/pci/pci_pci.c @@ -1287,7 +1287,6 @@ pcib_pcie_cc_timeout, sc); TIMEOUT_TASK_INIT(taskqueue_bus, &sc->pcie_dll_task, 0, pcib_pcie_dll_timeout, sc); - sc->pcie_hp_lock = bus_topo_mtx(); /* Allocate IRQ. */ if (pcib_alloc_pcie_irq(sc) != 0) diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h --- a/sys/dev/pci/pcib_private.h +++ b/sys/dev/pci/pcib_private.h @@ -124,12 +124,11 @@ struct timeout_task pcie_ab_task; struct timeout_task pcie_cc_task; struct timeout_task pcie_dll_task; - struct mtx *pcie_hp_lock; }; -#define PCIB_HP_LOCK(sc) mtx_lock((sc)->pcie_hp_lock) -#define PCIB_HP_UNLOCK(sc) mtx_unlock((sc)->pcie_hp_lock) -#define PCIB_HP_LOCK_ASSERT(sc) mtx_assert((sc)->pcie_hp_lock, MA_OWNED) +#define PCIB_HP_LOCK(sc) bus_topo_lock() +#define PCIB_HP_UNLOCK(sc) bus_topo_unlock() +#define PCIB_HP_LOCK_ASSERT(sc) bus_topo_assert() #define PCIB_SUPPORTED_ARI_VER 1 diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -271,6 +272,9 @@ #endif #endif + bus_topo_lock_init(); + bus_topo_lock(); + /* * Perform each system initialization task from the ordered list. Note * that if sysinit_list is modified (e.g. by a KLD) we will nonetheless @@ -327,6 +331,8 @@ TSEXIT(); /* Here so we don't overlap with start_init. */ BOOTTRACE("mi_startup done"); + bus_topo_unlock(); + /* Release Giant, acquired in mutex_init() during MD initialization. */ mtx_assert(&Giant, MA_OWNED | MA_NOTRECURSED); mtx_unlock(&Giant); diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -229,6 +230,7 @@ */ last = SI_SUB_DUMMY; sx_xunlock(&kld_sx); + bus_topo_lock(); mtx_lock(&Giant); for (sipp = start; sipp < stop; sipp++) { if ((*sipp)->subsystem == SI_SUB_DUMMY) @@ -243,6 +245,7 @@ last = (*sipp)->subsystem; } mtx_unlock(&Giant); + bus_topo_unlock(); sx_xlock(&kld_sx); } diff --git a/sys/kern/kern_module.c b/sys/kern/kern_module.c --- a/sys/kern/kern_module.c +++ b/sys/kern/kern_module.c @@ -27,6 +27,7 @@ */ #include +#include #include #include #include @@ -95,12 +96,14 @@ if (arg2 & RB_NOSYNC) return; + bus_topo_lock(); mtx_lock(&Giant); MOD_SLOCK; TAILQ_FOREACH_REVERSE(mod, &modules, modulelist, link) MOD_EVENT(mod, MOD_SHUTDOWN); MOD_SUNLOCK; mtx_unlock(&Giant); + bus_topo_unlock(); } void @@ -110,7 +113,7 @@ int error; module_t mod; - mtx_lock(&Giant); + bus_topo_lock(); MOD_SLOCK; mod = module_lookupbyname(data->name); if (mod == NULL) @@ -142,7 +145,7 @@ } MOD_XUNLOCK; } - mtx_unlock(&Giant); + bus_topo_unlock(); } int diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -416,32 +416,41 @@ DEFINE_CLASS(null, null_methods, 0); +static struct sx bus_topo_sx; + void -bus_topo_assert(void) +bus_topo_lock_init(void) { - - GIANT_REQUIRED; + sx_init_flags(&bus_topo_sx, "bus topology", SX_RECURSE); } -struct mtx * -bus_topo_mtx(void) +void +bus_topo_assert(void) { - return (&Giant); + GIANT_REQUIRED; + sx_assert(&bus_topo_sx, SX_XLOCKED); } void bus_topo_lock(void) { - - mtx_lock(bus_topo_mtx()); + sx_xlock(&bus_topo_sx); + mtx_lock(&Giant); } void bus_topo_unlock(void) { + mtx_unlock(&Giant); + sx_xunlock(&bus_topo_sx); +} - mtx_unlock(bus_topo_mtx()); +void +bus_topo_sleep(void *chan, int pri, const char *wmesg) +{ + /* Rely on the fact that Giant is released implictly. */ + sx_sleep(chan, &bus_topo_sx, pri, wmesg, 0); } /* diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -805,9 +805,11 @@ badstack_sbuf_size = witness_count * 256; /* - * We have to release Giant before initializing its witness - * structure so that WITNESS doesn't get confused. + * We have to release Giant and the bus topology lock before + * initializing their witness structures so that WITNESS doesn't get + * confused. */ + bus_topo_unlock(); mtx_unlock(&Giant); mtx_assert(&Giant, MA_NOTOWNED); @@ -867,6 +869,7 @@ witness_cold = 0; mtx_lock(&Giant); + bus_topo_lock(); } void diff --git a/sys/sys/bus.h b/sys/sys/bus.h --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -817,10 +817,11 @@ * Routines to lock / unlock the newbus lock. * Must be taken out to interact with newbus. */ +void bus_topo_lock_init(void); void bus_topo_lock(void); void bus_topo_unlock(void); -struct mtx * bus_topo_mtx(void); void bus_topo_assert(void); +void bus_topo_sleep(void *chan, int pri, const char *wmesg); /** * Shorthands for constructing method tables. diff --git a/sys/x86/x86/autoconf.c b/sys/x86/x86/autoconf.c --- a/sys/x86/x86/autoconf.c +++ b/sys/x86/x86/autoconf.c @@ -94,6 +94,7 @@ configure(void *dummy) { + bus_topo_lock(); /* initialize new bus architecture */ root_bus_configure(); @@ -105,6 +106,7 @@ if (isa_bus_device) isa_probe_children(isa_bus_device); #endif + bus_topo_unlock(); } static void