Index: usr.sbin/bhyve/pci_emul.h =================================================================== --- usr.sbin/bhyve/pci_emul.h +++ usr.sbin/bhyve/pci_emul.h @@ -124,7 +124,6 @@ enum lintr_stat state; int pirq_pin; int ioapic_irq; - pthread_mutex_t lock; } pi_lintr; struct { @@ -147,6 +146,8 @@ void *pba_page; int pba_page_offset; } pi_msix; + + pthread_mutex_t pi_intr_lock; void *pi_arg; /* devemu-private data */ Index: usr.sbin/bhyve/pci_emul.c =================================================================== --- usr.sbin/bhyve/pci_emul.c +++ usr.sbin/bhyve/pci_emul.c @@ -278,15 +278,20 @@ /* * Return if table index is beyond what device supports */ + pthread_mutex_lock(&pi->pi_intr_lock); tab_index = offset / MSIX_TABLE_ENTRY_SIZE; - if (tab_index >= pi->pi_msix.table_count) + if (tab_index >= pi->pi_msix.table_count) { + pthread_mutex_unlock(&pi->pi_intr_lock); return (-1); + } msix_entry_offset = offset % MSIX_TABLE_ENTRY_SIZE; /* support only aligned writes */ - if ((msix_entry_offset % size) != 0) + if ((msix_entry_offset % size) != 0) { + pthread_mutex_unlock(&pi->pi_intr_lock); return (-1); + } dest = (char *)(pi->pi_msix.table + tab_index); dest += msix_entry_offset; @@ -295,6 +300,7 @@ *((uint32_t *)dest) = value; else *((uint64_t *)dest) = value; + pthread_mutex_unlock(&pi->pi_intr_lock); return (0); } @@ -315,10 +321,12 @@ if (size != 1 && size != 4 && size != 8) return (retval); + pthread_mutex_lock(&pi->pi_intr_lock); msix_entry_offset = offset % MSIX_TABLE_ENTRY_SIZE; /* support only aligned reads */ if ((msix_entry_offset % size) != 0) { + pthread_mutex_unlock(&pi->pi_intr_lock); return (retval); } @@ -339,6 +347,7 @@ /* return 0 for PBA access */ retval = 0; } + pthread_mutex_unlock(&pi->pi_intr_lock); return (retval); } @@ -751,7 +760,7 @@ pdi->pi_bus = bus; pdi->pi_slot = slot; pdi->pi_func = func; - pthread_mutex_init(&pdi->pi_lintr.lock, NULL); + pthread_mutex_init(&pdi->pi_intr_lock, NULL); pdi->pi_lintr.pin = 0; pdi->pi_lintr.state = IDLE; pdi->pi_lintr.pirq_pin = 0; @@ -881,6 +890,7 @@ uint16_t msgctrl, rwmask; int off; + pthread_mutex_lock(&pi->pi_intr_lock); off = offset - capoff; /* Message Control Register */ if (off == 2 && bytes == 2) { @@ -896,6 +906,7 @@ } CFGWRITE(pi, offset, val, bytes); + pthread_mutex_unlock(&pi->pi_intr_lock); } void @@ -905,6 +916,8 @@ uint16_t msgctrl, rwmask, msgdata, mme; uint32_t addrlo; + pthread_mutex_lock(&pi->pi_intr_lock); + /* * If guest is writing to the message control register make sure * we do not overwrite read-only fields. @@ -935,6 +948,7 @@ } CFGWRITE(pi, offset, val, bytes); + pthread_mutex_unlock(&pi->pi_intr_lock); } void @@ -1447,30 +1461,40 @@ { struct msix_table_entry *mte; - if (!pci_msix_enabled(pi)) + pthread_mutex_lock(&pi->pi_intr_lock); + if (!pci_msix_enabled(pi)) { + pthread_mutex_unlock(&pi->pi_intr_lock); return; + } - if (pi->pi_msix.function_mask) + if (pi->pi_msix.function_mask) { + pthread_mutex_unlock(&pi->pi_intr_lock); return; + } - if (index >= pi->pi_msix.table_count) + if (index >= pi->pi_msix.table_count) { + pthread_mutex_unlock(&pi->pi_intr_lock); return; + } mte = &pi->pi_msix.table[index]; if ((mte->vector_control & PCIM_MSIX_VCTRL_MASK) == 0) { /* XXX Set PBA bit if interrupt is disabled */ vm_lapic_msi(pi->pi_vmctx, mte->addr, mte->msg_data); } + pthread_mutex_unlock(&pi->pi_intr_lock); } void pci_generate_msi(struct pci_devinst *pi, int index) { + pthread_mutex_lock(&pi->pi_intr_lock); if (pci_msi_enabled(pi) && index < pci_msi_maxmsgnum(pi)) { vm_lapic_msi(pi->pi_vmctx, pi->pi_msi.addr, pi->pi_msi.msg_data + index); } + pthread_mutex_unlock(&pi->pi_intr_lock); } static bool @@ -1552,7 +1576,7 @@ assert(pi->pi_lintr.pin > 0); - pthread_mutex_lock(&pi->pi_lintr.lock); + pthread_mutex_lock(&pi->pi_intr_lock); if (pi->pi_lintr.state == IDLE) { if (pci_lintr_permitted(pi)) { pi->pi_lintr.state = ASSERTED; @@ -1560,7 +1584,7 @@ } else pi->pi_lintr.state = PENDING; } - pthread_mutex_unlock(&pi->pi_lintr.lock); + pthread_mutex_unlock(&pi->pi_intr_lock); } void @@ -1569,20 +1593,20 @@ assert(pi->pi_lintr.pin > 0); - pthread_mutex_lock(&pi->pi_lintr.lock); + pthread_mutex_lock(&pi->pi_intr_lock); if (pi->pi_lintr.state == ASSERTED) { pi->pi_lintr.state = IDLE; pci_irq_deassert(pi); } else if (pi->pi_lintr.state == PENDING) pi->pi_lintr.state = IDLE; - pthread_mutex_unlock(&pi->pi_lintr.lock); + pthread_mutex_unlock(&pi->pi_intr_lock); } static void pci_lintr_update(struct pci_devinst *pi) { - pthread_mutex_lock(&pi->pi_lintr.lock); + assert(pthread_mutex_isowned_np(&pi->pi_intr_lock)); if (pi->pi_lintr.state == ASSERTED && !pci_lintr_permitted(pi)) { pci_irq_deassert(pi); pi->pi_lintr.state = PENDING; @@ -1590,7 +1614,6 @@ pi->pi_lintr.state = ASSERTED; pci_irq_assert(pi); } - pthread_mutex_unlock(&pi->pi_lintr.lock); } int @@ -1736,7 +1759,9 @@ * If INTx has been unmasked and is pending, assert the * interrupt. */ + pthread_mutex_lock(&pi->pi_intr_lock); pci_lintr_update(pi); + pthread_mutex_unlock(&pi->pi_intr_lock); } static void