|
|
6e0c7aa |
From 05f43d44e4bc26611ce25fd7d726e483f73363ce Mon Sep 17 00:00:00 2001
|
|
|
6e0c7aa |
From: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
6e0c7aa |
Date: Mon, 10 Oct 2016 12:46:22 +0200
|
|
|
6e0c7aa |
Subject: [PATCH] xhci: limit the number of link trbs we are willing to process
|
|
|
6e0c7aa |
|
|
|
6e0c7aa |
Needed to avoid we run in circles forever in case the guest builds
|
|
|
6e0c7aa |
an endless loop with link trbs.
|
|
|
6e0c7aa |
|
|
|
6e0c7aa |
Reported-by: Li Qiang <liqiang6-s@360.cn>
|
|
|
6e0c7aa |
Tested-by: P J P <ppandit@redhat.com>
|
|
|
6e0c7aa |
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
|
|
6e0c7aa |
Message-id: 1476096382-7981-1-git-send-email-kraxel@redhat.com
|
|
|
6e0c7aa |
---
|
|
|
6e0c7aa |
hw/usb/hcd-xhci.c | 10 ++++++++++
|
|
|
6e0c7aa |
1 files changed, 10 insertions(+), 0 deletions(-)
|
|
|
6e0c7aa |
|
|
|
6e0c7aa |
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
|
|
|
6e0c7aa |
index 726435c..ee4fa48 100644
|
|
|
6e0c7aa |
--- a/hw/usb/hcd-xhci.c
|
|
|
6e0c7aa |
+++ b/hw/usb/hcd-xhci.c
|
|
|
6e0c7aa |
@@ -54,6 +54,8 @@
|
|
|
6e0c7aa |
* to the specs when it gets them */
|
|
|
6e0c7aa |
#define ER_FULL_HACK
|
|
|
6e0c7aa |
|
|
|
6e0c7aa |
+#define TRB_LINK_LIMIT 4
|
|
|
6e0c7aa |
+
|
|
|
6e0c7aa |
#define LEN_CAP 0x40
|
|
|
6e0c7aa |
#define LEN_OPER (0x400 + 0x10 * MAXPORTS)
|
|
|
6e0c7aa |
#define LEN_RUNTIME ((MAXINTRS + 1) * 0x20)
|
|
|
6e0c7aa |
@@ -1000,6 +1002,7 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
|
|
|
6e0c7aa |
dma_addr_t *addr)
|
|
|
6e0c7aa |
{
|
|
|
6e0c7aa |
PCIDevice *pci_dev = PCI_DEVICE(xhci);
|
|
|
6e0c7aa |
+ uint32_t link_cnt = 0;
|
|
|
6e0c7aa |
|
|
|
6e0c7aa |
while (1) {
|
|
|
6e0c7aa |
TRBType type;
|
|
|
6e0c7aa |
@@ -1026,6 +1029,9 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
|
|
|
6e0c7aa |
ring->dequeue += TRB_SIZE;
|
|
|
6e0c7aa |
return type;
|
|
|
6e0c7aa |
} else {
|
|
|
6e0c7aa |
+ if (++link_cnt > TRB_LINK_LIMIT) {
|
|
|
6e0c7aa |
+ return 0;
|
|
|
6e0c7aa |
+ }
|
|
|
6e0c7aa |
ring->dequeue = xhci_mask64(trb->parameter);
|
|
|
6e0c7aa |
if (trb->control & TRB_LK_TC) {
|
|
|
6e0c7aa |
ring->ccs = !ring->ccs;
|
|
|
6e0c7aa |
@@ -1043,6 +1049,7 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
|
|
|
6e0c7aa |
bool ccs = ring->ccs;
|
|
|
6e0c7aa |
/* hack to bundle together the two/three TDs that make a setup transfer */
|
|
|
6e0c7aa |
bool control_td_set = 0;
|
|
|
6e0c7aa |
+ uint32_t link_cnt = 0;
|
|
|
6e0c7aa |
|
|
|
6e0c7aa |
while (1) {
|
|
|
6e0c7aa |
TRBType type;
|
|
|
6e0c7aa |
@@ -1058,6 +1065,9 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
|
|
|
6e0c7aa |
type = TRB_TYPE(trb);
|
|
|
6e0c7aa |
|
|
|
6e0c7aa |
if (type == TR_LINK) {
|
|
|
6e0c7aa |
+ if (++link_cnt > TRB_LINK_LIMIT) {
|
|
|
6e0c7aa |
+ return -length;
|
|
|
6e0c7aa |
+ }
|
|
|
6e0c7aa |
dequeue = xhci_mask64(trb.parameter);
|
|
|
6e0c7aa |
if (trb.control & TRB_LK_TC) {
|
|
|
6e0c7aa |
ccs = !ccs;
|
|
|
6e0c7aa |
--
|
|
|
6e0c7aa |
1.7.0.4
|
|
|
6e0c7aa |
|