Commit f89b60f6 authored by Gerd Hoffmann's avatar Gerd Hoffmann
Browse files

xhci: apply limits to loops



Limits should be big enough that normal guest should not hit it.
Add a tracepoint to log them, just in case.  Also, while being
at it, log the existing link trb limit too.

Reported-by: default avatar李强 <liqiang6-s@360.cn>
Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Message-id: 1486383669-6421-1-git-send-email-kraxel@redhat.com
parent 95ed5693
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@
#define ER_FULL_HACK

#define TRB_LINK_LIMIT  4
#define COMMAND_LIMIT   256
#define TRANSFER_LIMIT  256

#define LEN_CAP         0x40
#define LEN_OPER        (0x400 + 0x10 * MAXPORTS)
@@ -1032,6 +1034,7 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
            return type;
        } else {
            if (++link_cnt > TRB_LINK_LIMIT) {
                trace_usb_xhci_enforced_limit("trb-link");
                return 0;
            }
            ring->dequeue = xhci_mask64(trb->parameter);
@@ -2150,6 +2153,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
    XHCIRing *ring;
    USBEndpoint *ep = NULL;
    uint64_t mfindex;
    unsigned int count = 0;
    int length;
    int i;

@@ -2262,6 +2266,10 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
            epctx->retry = xfer;
            break;
        }
        if (count++ > TRANSFER_LIMIT) {
            trace_usb_xhci_enforced_limit("transfers");
            break;
        }
    }
    epctx->kick_active--;

@@ -2734,7 +2742,7 @@ static void xhci_process_commands(XHCIState *xhci)
    TRBType type;
    XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
    dma_addr_t addr;
    unsigned int i, slotid = 0;
    unsigned int i, slotid = 0, count = 0;

    DPRINTF("xhci_process_commands()\n");
    if (!xhci_running(xhci)) {
@@ -2848,6 +2856,11 @@ static void xhci_process_commands(XHCIState *xhci)
        }
        event.slotid = slotid;
        xhci_event(xhci, &event, 0);

        if (count++ > COMMAND_LIMIT) {
            trace_usb_xhci_enforced_limit("commands");
            return;
        }
    }
}

+1 −0
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ usb_xhci_xfer_retry(void *xfer) "%p"
usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d"
usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)"
usb_xhci_enforced_limit(const char *item) "%s"

# hw/usb/desc.c
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"