summaryrefslogtreecommitdiff
path: root/hw/usb/hcd-xhci.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2017-02-02 12:36:12 +0100
committerGerd Hoffmann <kraxel@redhat.com>2017-02-06 10:23:18 +0100
commit96d87bdda3919bb16f754b3d3fd1227e1f38f13c (patch)
treeedcb8fd8559ee64a3e0f772ac84ca999a39d10e4 /hw/usb/hcd-xhci.c
parentddb603ab6c981c1d67cb42266fc700c33e5b2d8f (diff)
downloadqemu-96d87bdda3919bb16f754b3d3fd1227e1f38f13c.tar.gz
xhci: guard xhci_kick_epctx against recursive calls
Track xhci_kick_epctx processing being active in a variable. Check the variable before calling xhci_kick_epctx from xhci_kick_ep. Add an assert to make sure we don't call recursively into xhci_kick_epctx. Cc: 1653384@bugs.launchpad.net Fixes: 94b037f2a451b3dc855f9f2c346e5049a361bd55 Reported-by: Fabian Lesniak <fabian@lesniak-it.de> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Message-id: 1486035372-3621-1-git-send-email-kraxel@redhat.com Message-id: 1485790607-31399-5-git-send-email-kraxel@redhat.com
Diffstat (limited to 'hw/usb/hcd-xhci.c')
-rw-r--r--hw/usb/hcd-xhci.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index f89d8dafba..1878dad2ce 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -390,6 +390,7 @@ struct XHCIEPContext {
dma_addr_t pctx;
unsigned int max_psize;
uint32_t state;
+ uint32_t kick_active;
/* streams */
unsigned int max_pstreams;
@@ -2131,6 +2132,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
return;
}
+ if (epctx->kick_active) {
+ return;
+ }
xhci_kick_epctx(epctx, streamid);
}
@@ -2146,6 +2150,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
int i;
trace_usb_xhci_ep_kick(epctx->slotid, epctx->epid, streamid);
+ assert(!epctx->kick_active);
/* If the device has been detached, but the guest has not noticed this
yet the 2 above checks will succeed, but we must NOT continue */
@@ -2217,6 +2222,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
}
assert(ring->dequeue != 0);
+ epctx->kick_active++;
while (1) {
length = xhci_ring_chain_length(xhci, ring);
if (length <= 0) {
@@ -2253,6 +2259,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
break;
}
}
+ epctx->kick_active--;
ep = xhci_epid_to_usbep(epctx);
if (ep) {