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: 李强 <liqiang6-s@360.cn> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Message-id: 1486383669-6421-1-git-send-email-kraxel@redhat.com
This commit is contained in:
		
							parent
							
								
									95ed56939e
								
							
						
					
					
						commit
						f89b60f6e5
					
				| 
						 | 
				
			
			@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue