From nobody Wed Oct 14 16:04:38 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4j4bck5Kdvz6vmrS for ; Wed, 14 Oct 2026 16:04:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4j4bck1yVgz4bq0 for ; Wed, 14 Oct 2026 16:04:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791993878; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=2bs4FUJ9RogH9jnBGD6N5MUJlHczgDdspXKqO5hokRk=; b=ft/3GF1blo0OSUtQ/xD1kT4X2xO5tULtogD4NZMRnFKeqe6ZM2VhWYFFzMjzP2CvE+6h0r ktQ73GIK2ifXKo9VfqFmgnRDwfiZHvtMHipYRr2iexJRM9YVWJmhKZB3VxgNgTh2uy/Znx 4CqWT5H9akiIERUX3O4x4rOc1KQNSfn7NiadQvfSJXJx7c+vBK+13Jcq1QL/DV+ki8/hIt oEYrIbVwNycS9gvwQKSTNkNomtl5FvU3IRZkbdpZbjG9ysr8Mh8q5/+oqCXyUvi8GaqsKE ALQgvLE4ONEyvX9giKRFe6z1LWSOSI/sCJ6kSwA/4It3s15CqD88xkoOWtKAhQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791993878; b=L/z99pro2XQ3Wuoa3hf4AWLwRg0K3IR4D8VVx5EHVdF143p9hKcmswYnV1fVo1L5yHfoqU Y7rRmz+1kNueU8EGXJS7tBzMBhBXCfagwj/uwWjMW6lrVRlQNY7TsMxJiUqL/5w9c07vy8 K17m97DVDtwC4rwXR+ECp7a11ROLFp+rXwkCSpWCJu3b/EsFdnzHeb4uBHh3ipZQhC68xo I08vdRCBC79DpmyJ0xbsn3xHyEkKl5mGdahedmH7neAi01+O4zpDrfEHggJjIU+2NbnB9M xt3Zui4XLGJ3ZxCvNYiqlIIMb/NT5xYOQXokf1c1lyHnZk8+T6vsf3clUM9bKw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791993878; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=2bs4FUJ9RogH9jnBGD6N5MUJlHczgDdspXKqO5hokRk=; b=ZeP3wmkCS14PpDVA3iomjB9AIrbT8+jiHHUqLG2CX2y+Q9wCw2H7uVBJfuXD7AlosSJJis sac3N0xpsn9v4qY91vuqv4wh2PI2mBZ5HIvOP0zGr4FO762AIIgBtOYtBZgMJ+7e3Ygw+7 Wi/kHDgo5lVmVzQl0tZXIZ9K7XfAOHJZypQebF1ywMBp1BilzMOxVRIWwdXZV7Bhce3xVG W4LlLCtK2pVUwTAxyu/BWkXfA1Xf0K8kkfod7WZz1gyiXx1Mgd+XbcRNmJxFgrNhHlMptq UXafY7mzlp6jtIJ2p7Fr64T0d5AJP01FcHyIONxtz9J2Lbi2b82rz8XWWQiAbg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j4bck11yhz18Tm for ; Wed, 14 Oct 2026 16:04:38 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 30f80 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 14 Oct 2026 16:04:38 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: 32b2ee469ee2 - releng/15.1 - bhyve: Fix handling of the xhci event ring List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/releng/15.1 X-Git-Reftype: branch X-Git-Commit: 32b2ee469ee2d433ec5101be61df4164b0591e64 Auto-Submitted: auto-generated Date: Wed, 14 Oct 2026 16:04:38 +0000 Message-Id: <6acfa816.30f80.4ddfe0a6@gitrepo.freebsd.org> The branch releng/15.1 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=32b2ee469ee2d433ec5101be61df4164b0591e64 commit 32b2ee469ee2d433ec5101be61df4164b0591e64 Author: Mark Johnston AuthorDate: 2026-10-13 19:56:47 +0000 Commit: Mark Johnston CommitDate: 2026-10-13 20:20:45 +0000 bhyve: Fix handling of the xhci event ring rts->erst_p and rts->erstba_p are pointers to guest-controlled memory which describe the event rings and pending event array, respectively. The device model was not validating the size nor saving the value. As a result, the bounds checks in pci_xhci_insert_event() were susceptible to TOCTOU races. Fix pci_xhci_rtsregs_write() to save the ring size in a softc field. Validate that the size isn't larger than the maximum allowed by the XHCI specification (64KB, or 4096 TRBs). When processing TRBs, make sure we don't load fields more than once. Make sure that pci_xhci_trb_next() doesn't return a pointer to host memory. When handling ERDP writes, make sure that the guest-supplied address is actually a pointer into the TRB array, and ignore the write if not. Approved by: so Security: FreeBSD-SA-26:72.bhyve Security: CVE-2026-101309 Reported by: Brian Delgado from Intel using Anthropic Opus 4.8 Differential Revision: https://reviews.freebsd.org/D60677 --- usr.sbin/bhyve/pci_xhci.c | 164 ++++++++++++++++++++++++++++------------------ 1 file changed, 99 insertions(+), 65 deletions(-) diff --git a/usr.sbin/bhyve/pci_xhci.c b/usr.sbin/bhyve/pci_xhci.c index ff12e40359e2..3ec4cedeea0f 100644 --- a/usr.sbin/bhyve/pci_xhci.c +++ b/usr.sbin/bhyve/pci_xhci.c @@ -38,6 +38,8 @@ #include #include +#include + #include #include #include @@ -79,6 +81,7 @@ static int xhci_debug = 0; #define XHCI_PADDR_SZ 4096 /* paddr_guest2host max size */ #define XHCI_ERST_MAX 0 /* max 2^entries event ring seg tbl */ +#define XHCI_EVR_MAX 4096 /* max entries in an event ring */ #define XHCI_CAPLEN (4*8) /* offset of op register space */ #define XHCI_HCCPRAMS2 0x1C /* offset of HCCPARAMS2 register */ @@ -234,6 +237,7 @@ struct pci_xhci_rtsregs { int er_deq_seg; /* event ring dequeue segment */ int er_enq_idx; /* event ring enqueue index - xHCI */ int er_enq_seg; /* event ring enqueue segment */ + uint32_t er_size; /* number of entries */ uint32_t er_events_cnt; /* number of events in ER */ uint32_t event_pcs; /* producer cycle state flag */ }; @@ -601,22 +605,22 @@ pci_xhci_get_dev_ctx(struct pci_xhci_softc *sc, uint32_t slot) static struct xhci_trb * pci_xhci_trb_next(struct pci_xhci_softc *sc, struct xhci_trb *curtrb, - uint64_t *guestaddr) + uint32_t type, uint64_t *guestaddr) { struct xhci_trb *next; - assert(curtrb != NULL); - - if (XHCI_TRB_3_TYPE_GET(curtrb->dwTrb3) == XHCI_TRB_TYPE_LINK) { - if (guestaddr) - *guestaddr = curtrb->qwTrb0 & ~0xFUL; + if (type == XHCI_TRB_TYPE_LINK) { + uint64_t trb0; - next = XHCI_GADDR(sc, curtrb->qwTrb0 & ~0xFUL); + trb0 = atomic_load_64(&curtrb->qwTrb0) & ~0xFUL; + *guestaddr = trb0; + next = XHCI_GADDR(sc, trb0); } else { - if (guestaddr) - *guestaddr += sizeof(struct xhci_trb) & ~0xFUL; - - next = curtrb + 1; + *guestaddr += sizeof(struct xhci_trb); + if (XHCI_GADDR(sc, *guestaddr) == NULL) + next = NULL; + else + next = curtrb + 1; } return (next); @@ -764,14 +768,14 @@ pci_xhci_insert_event(struct pci_xhci_softc *sc, struct xhci_trb *evtrb, evtrbptr = &rts->erst_p[rts->er_enq_idx]; /* TODO: multi-segment table */ - if (rts->er_events_cnt >= rts->erstba_p->dwEvrsTableSize) { + if (rts->er_events_cnt >= rts->er_size) { DPRINTF(("pci_xhci[%d] cannot insert event; ring full", __LINE__)); err = XHCI_TRB_ERROR_EV_RING_FULL; goto done; } - if (rts->er_events_cnt == rts->erstba_p->dwEvrsTableSize - 1) { + if (rts->er_events_cnt == rts->er_size - 1) { struct xhci_trb errev; if ((evtrbptr->dwTrb3 & 0x1) == (rts->event_pcs & 0x1)) { @@ -788,8 +792,7 @@ pci_xhci_insert_event(struct pci_xhci_softc *sc, struct xhci_trb *evtrb, rts->er_events_cnt++; memcpy(&rts->erst_p[rts->er_enq_idx], &errev, sizeof(struct xhci_trb)); - rts->er_enq_idx = (rts->er_enq_idx + 1) % - rts->erstba_p->dwEvrsTableSize; + rts->er_enq_idx = (rts->er_enq_idx + 1) % rts->er_size; err = XHCI_TRB_ERROR_EV_RING_FULL; do_intr = 1; @@ -803,8 +806,7 @@ pci_xhci_insert_event(struct pci_xhci_softc *sc, struct xhci_trb *evtrb, evtrb->dwTrb3 |= rts->event_pcs; memcpy(&rts->erst_p[rts->er_enq_idx], evtrb, sizeof(struct xhci_trb)); - rts->er_enq_idx = (rts->er_enq_idx + 1) % - rts->erstba_p->dwEvrsTableSize; + rts->er_enq_idx = (rts->er_enq_idx + 1) % rts->er_size; if (rts->er_enq_idx == 0) rts->event_pcs ^= 1; @@ -1402,7 +1404,6 @@ pci_xhci_complete_commands(struct pci_xhci_softc *sc) struct xhci_trb *trb; uint64_t crcr; uint32_t ccs; /* cycle state (XHCI 4.9.2) */ - uint32_t type; uint32_t slot; uint32_t cmderr; int error; @@ -1415,18 +1416,22 @@ pci_xhci_complete_commands(struct pci_xhci_softc *sc) crcr = sc->opregs.crcr & ~0xF; while (1) { - sc->opregs.cr_p = trb; + uint32_t trb3, type; - type = XHCI_TRB_3_TYPE_GET(trb->dwTrb3); + sc->opregs.cr_p = trb; - if ((trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT) != + if (trb == NULL) + break; + trb3 = atomic_load_32(&trb->dwTrb3); + type = XHCI_TRB_3_TYPE_GET(trb3); + if ((trb3 & XHCI_TRB_3_CYCLE_BIT) != (ccs & XHCI_TRB_3_CYCLE_BIT)) break; DPRINTF(("pci_xhci: cmd type 0x%x, Trb0 x%016lx dwTrb2 x%08x" " dwTrb3 x%08x, TRB_CYCLE %u/ccs %u", - type, trb->qwTrb0, trb->dwTrb2, trb->dwTrb3, - trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT, ccs)); + type, trb->qwTrb0, trb->dwTrb2, trb3, + trb3 & XHCI_TRB_3_CYCLE_BIT, ccs)); cmderr = XHCI_TRB_ERROR_SUCCESS; evtrb.dwTrb2 = 0; @@ -1436,7 +1441,7 @@ pci_xhci_complete_commands(struct pci_xhci_softc *sc) switch (type) { case XHCI_TRB_TYPE_LINK: /* 0x06 */ - if (trb->dwTrb3 & XHCI_TRB_3_TC_BIT) + if (trb3 & XHCI_TRB_3_TC_BIT) ccs ^= XHCI_CRCR_LO_RCS; break; @@ -1445,44 +1450,44 @@ pci_xhci_complete_commands(struct pci_xhci_softc *sc) break; case XHCI_TRB_TYPE_DISABLE_SLOT: /* 0x0A */ - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_disable_slot(sc, slot); break; case XHCI_TRB_TYPE_ADDRESS_DEVICE: /* 0x0B */ - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_address_device(sc, slot, trb); break; case XHCI_TRB_TYPE_CONFIGURE_EP: /* 0x0C */ - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_config_ep(sc, slot, trb); break; case XHCI_TRB_TYPE_EVALUATE_CTX: /* 0x0D */ - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_eval_ctx(sc, slot, trb); break; case XHCI_TRB_TYPE_RESET_EP: /* 0x0E */ DPRINTF(("Reset Endpoint on slot %d", slot)); - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_reset_ep(sc, slot, trb); break; case XHCI_TRB_TYPE_STOP_EP: /* 0x0F */ DPRINTF(("Stop Endpoint on slot %d", slot)); - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_reset_ep(sc, slot, trb); break; case XHCI_TRB_TYPE_SET_TR_DEQUEUE: /* 0x10 */ - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_set_tr(sc, slot, trb); break; case XHCI_TRB_TYPE_RESET_DEVICE: /* 0x11 */ - slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); + slot = XHCI_TRB_3_SLOT_GET(trb3); cmderr = pci_xhci_cmd_reset_device(sc, slot); break; @@ -1522,7 +1527,7 @@ pci_xhci_complete_commands(struct pci_xhci_softc *sc) pci_xhci_insert_event(sc, &evtrb, 1); } - trb = pci_xhci_trb_next(sc, trb, &crcr); + trb = pci_xhci_trb_next(sc, trb, type, &crcr); } sc->opregs.crcr = crcr | (sc->opregs.crcr & XHCI_CRCR_LO_CA) | ccs; @@ -1757,7 +1762,6 @@ pci_xhci_handle_transfer(struct pci_xhci_softc *sc, struct usb_data_xfer *xfer; struct usb_data_xfer_block *xfer_block; uint64_t val; - uint32_t trbflags; int do_intr, err; int do_retry; @@ -1776,23 +1780,25 @@ retry: setup_trb = NULL; while (1) { - pci_xhci_dump_trb(trb); + uint32_t trb3, type; - trbflags = trb->dwTrb3; + pci_xhci_dump_trb(trb); - if (XHCI_TRB_3_TYPE_GET(trbflags) != XHCI_TRB_TYPE_LINK && - (trbflags & XHCI_TRB_3_CYCLE_BIT) != + trb3 = atomic_load_32(&trb->dwTrb3); + type = XHCI_TRB_3_TYPE_GET(trb3); + if (type != XHCI_TRB_TYPE_LINK && + (trb3 & XHCI_TRB_3_CYCLE_BIT) != (ccs & XHCI_TRB_3_CYCLE_BIT)) { DPRINTF(("Cycle-bit changed trbflags %x, ccs %x", - trbflags & XHCI_TRB_3_CYCLE_BIT, ccs)); + trb3 & XHCI_TRB_3_CYCLE_BIT, ccs)); break; } xfer_block = NULL; - switch (XHCI_TRB_3_TYPE_GET(trbflags)) { + switch (type) { case XHCI_TRB_TYPE_LINK: - if (trb->dwTrb3 & XHCI_TRB_3_TC_BIT) + if (trb3 & XHCI_TRB_3_TC_BIT) ccs ^= 0x1; xfer_block = usb_data_xfer_append(xfer, NULL, 0, @@ -1801,7 +1807,7 @@ retry: break; case XHCI_TRB_TYPE_SETUP_STAGE: - if ((trbflags & XHCI_TRB_3_IDT_BIT) == 0 || + if ((trb3 & XHCI_TRB_3_IDT_BIT) == 0 || XHCI_TRB_2_BYTES_GET(trb->dwTrb2) != 8) { DPRINTF(("pci_xhci: invalid setup trb")); err = XHCI_TRB_ERROR_TRB; @@ -1833,7 +1839,7 @@ retry: case XHCI_TRB_TYPE_DATA_STAGE: xfer_block = usb_data_xfer_append(xfer, - (void *)(trbflags & XHCI_TRB_3_IDT_BIT ? + (void *)(trb3 & XHCI_TRB_3_IDT_BIT ? &trb->qwTrb0 : XHCI_GADDR(sc, trb->qwTrb0)), trb->dwTrb2 & 0x1FFFF, (void *)addr, ccs); break; @@ -1852,21 +1858,19 @@ retry: case XHCI_TRB_TYPE_EVENT_DATA: xfer_block = usb_data_xfer_append(xfer, NULL, 0, (void *)addr, ccs); - if ((epid > 1) && (trbflags & XHCI_TRB_3_IOC_BIT)) { + if ((epid > 1) && (trb3 & XHCI_TRB_3_IOC_BIT)) { xfer_block->processed = 1; } break; default: DPRINTF(("pci_xhci: handle xfer unexpected trb type " - "0x%x", - XHCI_TRB_3_TYPE_GET(trbflags))); + "0x%x", type)); err = XHCI_TRB_ERROR_TRB; goto errout; } - trb = pci_xhci_trb_next(sc, trb, &addr); - + trb = pci_xhci_trb_next(sc, trb, type, &addr); DPRINTF(("pci_xhci: next trb: 0x%lx", (uint64_t)trb)); if (xfer_block) { @@ -1874,13 +1878,13 @@ retry: xfer_block->streamid = streamid; } - if (!setup_trb && !(trbflags & XHCI_TRB_3_CHAIN_BIT) && - XHCI_TRB_3_TYPE_GET(trbflags) != XHCI_TRB_TYPE_LINK) { + if (!setup_trb && !(trb3 & XHCI_TRB_3_CHAIN_BIT) && + type != XHCI_TRB_TYPE_LINK) { break; } /* handle current batch that requires interrupt on complete */ - if (trbflags & XHCI_TRB_3_IOC_BIT) { + if (trb3 & XHCI_TRB_3_IOC_BIT) { DPRINTF(("pci_xhci: trb IOC bit set")); if (epid == 1) do_retry = 1; @@ -2106,23 +2110,42 @@ pci_xhci_rtsregs_write(struct pci_xhci_softc *sc, uint64_t offset, case 0x14: /* ERSTBA high bits */ + { + uint64_t evtap; + rts->intrreg.erstba = (value << 32) | MASK_64_LO(sc->rtsregs.intrreg.erstba); rts->erstba_p = XHCI_GADDR(sc, - sc->rtsregs.intrreg.erstba & ~0x3FUL); - - rts->erst_p = XHCI_GADDR(sc, - sc->rtsregs.erstba_p->qwEvrsTablePtr & ~0x3FUL); + sc->rtsregs.intrreg.erstba & ~0x3FUL); + if (rts->erstba_p == NULL) { + DPRINTF(("pci_xhci: ERSTBA not mapped")); + break; + } rts->er_enq_idx = 0; rts->er_events_cnt = 0; + rts->er_size = atomic_load_32(&rts->erstba_p->dwEvrsTableSize) & + 0xFFFFUL; + if (rts->er_size > XHCI_EVR_MAX) { + DPRINTF(("pci_xhci: ERST size %u > max", rts->er_size)); + rts->er_size = XHCI_EVR_MAX; + } + + evtap = atomic_load_64(&rts->erstba_p->qwEvrsTablePtr) & + ~0x3FUL; + rts->erst_p = paddr_guest2host(sc->xsc_pi->pi_vmctx, + evtap, rts->er_size * sizeof(struct xhci_trb)); + if (rts->erst_p == NULL) { + DPRINTF(("pci_xhci: ERST table not mapped")); + rts->erstba_p = NULL; + rts->er_size = 0; + } DPRINTF(("pci_xhci: wr erstba erst (%p) ptr 0x%lx, sz %u", - rts->erstba_p, - rts->erstba_p->qwEvrsTablePtr, - rts->erstba_p->dwEvrsTableSize)); + rts->erstba_p, evtap, rts->er_size)); break; + } case 0x18: /* ERDP low bits */ @@ -2145,19 +2168,27 @@ pci_xhci_rtsregs_write(struct pci_xhci_softc *sc, uint64_t offset, MASK_64_LO(sc->rtsregs.intrreg.erdp); if (rts->er_events_cnt > 0) { + void *trb; uint64_t erdp; int erdp_i; erdp = rts->intrreg.erdp & ~0xF; - erdp_i = (erdp - rts->erstba_p->qwEvrsTablePtr) / - sizeof(struct xhci_trb); + trb = XHCI_GADDR(sc, erdp); + if ((uintptr_t)trb < (uintptr_t)rts->erst_p || + (uintptr_t)trb >= (uintptr_t)rts->erst_p + + rts->er_size * sizeof(struct xhci_trb)) { + DPRINTF(("pci_xhci: ERDP 0x%lx out of range", + erdp)); + break; + } + erdp_i = ((uintptr_t)trb - (uintptr_t)rts->erst_p) / + sizeof(struct xhci_trb); if (erdp_i <= rts->er_enq_idx) rts->er_events_cnt = rts->er_enq_idx - erdp_i; else rts->er_events_cnt = - rts->erstba_p->dwEvrsTableSize - - (erdp_i - rts->er_enq_idx); + rts->er_size - (erdp_i - rts->er_enq_idx); DPRINTF(("pci_xhci: erdp 0x%lx, events cnt %u", erdp, rts->er_events_cnt)); @@ -2659,12 +2690,13 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx) dev = hci->hci_sc; sc = dev->xsc; + pthread_mutex_lock(&sc->mtx); /* check if device is ready; OS has to initialise it */ if (sc->rtsregs.erstba_p == NULL || (sc->opregs.usbcmd & XHCI_CMD_RS) == 0 || dev->dev_ctx == NULL) - return (0); + goto done; p = XHCI_PORTREG_PTR(sc, hci->hci_port); @@ -2673,7 +2705,7 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx) p->portsc &= ~XHCI_PS_PLS_MASK; p->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_RESUME); if ((p->portsc & XHCI_PS_PLC) != 0) - return (0); + goto done; p->portsc |= XHCI_PS_PLC; @@ -2689,7 +2721,7 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx) if ((ep_ctx->dwEpCtx0 & 0x7) == XHCI_ST_EPCTX_DISABLED) { DPRINTF(("xhci device interrupt on disabled endpoint %d", epid)); - return (0); + goto done; } DPRINTF(("xhci device interrupt on endpoint %d", epid)); @@ -2697,6 +2729,7 @@ pci_xhci_dev_intr(struct usb_hci *hci, int epctx) pci_xhci_device_doorbell(sc, hci->hci_port, epid, 0); done: + pthread_mutex_unlock(&sc->mtx); return (error); } @@ -3146,6 +3179,7 @@ pci_xhci_snapshot(struct vm_snapshot_meta *meta) SNAPSHOT_VAR_OR_LEAVE(sc->rtsregs.er_deq_seg, meta, ret, done); SNAPSHOT_VAR_OR_LEAVE(sc->rtsregs.er_enq_idx, meta, ret, done); SNAPSHOT_VAR_OR_LEAVE(sc->rtsregs.er_enq_seg, meta, ret, done); + SNAPSHOT_VAR_OR_LEAVE(sc->rtsregs.er_size, meta, ret, done); SNAPSHOT_VAR_OR_LEAVE(sc->rtsregs.er_events_cnt, meta, ret, done); SNAPSHOT_VAR_OR_LEAVE(sc->rtsregs.event_pcs, meta, ret, done);