Blame 0311-ehci-trace-guest-bugs.patch

c8dfc6
From 044dcae94243d03739c309935a68b646424a4d4e Mon Sep 17 00:00:00 2001
c8dfc6
From: Gerd Hoffmann <kraxel@redhat.com>
c8dfc6
Date: Fri, 31 Aug 2012 10:44:21 +0200
c8dfc6
Subject: [PATCH 311/366] ehci: trace guest bugs
c8dfc6
c8dfc6
make qemu_queue_{cancel,reset} return the number of packets released,
c8dfc6
so the caller can figure whenever there have been active packets even
c8dfc6
though there shouldn't have been any.  Add tracepoint to log this.
c8dfc6
c8dfc6
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
c8dfc6
---
c8dfc6
 hw/usb/hcd-ehci.c | 26 ++++++++++++++++++++------
c8dfc6
 trace-events      |  1 +
c8dfc6
 2 files changed, 21 insertions(+), 6 deletions(-)
c8dfc6
c8dfc6
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
c8dfc6
index 23221d0..4564615 100644
c8dfc6
--- a/hw/usb/hcd-ehci.c
c8dfc6
+++ b/hw/usb/hcd-ehci.c
c8dfc6
@@ -716,6 +716,12 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
c8dfc6
                         (bool)(sitd->results & SITD_RESULTS_ACTIVE));
c8dfc6
 }
c8dfc6
 
c8dfc6
+static void ehci_trace_guest_bug(EHCIState *s, const char *message)
c8dfc6
+{
c8dfc6
+    trace_usb_ehci_guest_bug(message);
c8dfc6
+    fprintf(stderr, "ehci warning: %s\n", message);
c8dfc6
+}
c8dfc6
+
c8dfc6
 static inline bool ehci_enabled(EHCIState *s)
c8dfc6
 {
c8dfc6
     return s->usbcmd & USBCMD_RUNSTOP;
c8dfc6
@@ -785,27 +791,33 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
c8dfc6
     return q;
c8dfc6
 }
c8dfc6
 
c8dfc6
-static void ehci_cancel_queue(EHCIQueue *q)
c8dfc6
+static int ehci_cancel_queue(EHCIQueue *q)
c8dfc6
 {
c8dfc6
     EHCIPacket *p;
c8dfc6
+    int packets = 0;
c8dfc6
 
c8dfc6
     p = QTAILQ_FIRST(&q->packets);
c8dfc6
     if (p == NULL) {
c8dfc6
-        return;
c8dfc6
+        return 0;
c8dfc6
     }
c8dfc6
 
c8dfc6
     trace_usb_ehci_queue_action(q, "cancel");
c8dfc6
     do {
c8dfc6
         ehci_free_packet(p);
c8dfc6
+        packets++;
c8dfc6
     } while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
c8dfc6
+    return packets;
c8dfc6
 }
c8dfc6
 
c8dfc6
-static void ehci_reset_queue(EHCIQueue *q)
c8dfc6
+static int ehci_reset_queue(EHCIQueue *q)
c8dfc6
 {
c8dfc6
+    int packets;
c8dfc6
+
c8dfc6
     trace_usb_ehci_queue_action(q, "reset");
c8dfc6
-    ehci_cancel_queue(q);
c8dfc6
+    packets = ehci_cancel_queue(q);
c8dfc6
     q->dev = NULL;
c8dfc6
     q->qtdaddr = 0;
c8dfc6
+    return packets;
c8dfc6
 }
c8dfc6
 
c8dfc6
 static void ehci_free_queue(EHCIQueue *q)
c8dfc6
@@ -1817,7 +1829,9 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
c8dfc6
         (memcmp(&qh.current_qtd, &q->qh.current_qtd,
c8dfc6
                                  9 * sizeof(uint32_t)) != 0) ||
c8dfc6
         (q->dev != NULL && q->dev->addr != devaddr)) {
c8dfc6
-        ehci_reset_queue(q);
c8dfc6
+        if (ehci_reset_queue(q) > 0) {
c8dfc6
+            ehci_trace_guest_bug(ehci, "guest updated active QH");
c8dfc6
+        }
c8dfc6
         p = NULL;
c8dfc6
     }
c8dfc6
     q->qh = qh;
c8dfc6
@@ -1979,8 +1993,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
c8dfc6
             (!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) ||
c8dfc6
             (!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||
c8dfc6
             p->qtd.bufptr[0] != qtd.bufptr[0]) {
c8dfc6
-            /* guest bug: guest updated active QH or qTD underneath us */
c8dfc6
             ehci_cancel_queue(q);
c8dfc6
+            ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD");
c8dfc6
             p = NULL;
c8dfc6
         } else {
c8dfc6
             p->qtd = qtd;
c8dfc6
diff --git a/trace-events b/trace-events
c8dfc6
index 8fcbc50..5112a47 100644
c8dfc6
--- a/trace-events
c8dfc6
+++ b/trace-events
c8dfc6
@@ -263,6 +263,7 @@ usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t l
c8dfc6
 usb_ehci_queue_action(void *q, const char *action) "q %p: %s"
c8dfc6
 usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s"
c8dfc6
 usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x"
c8dfc6
+usb_ehci_guest_bug(const char *reason) "%s"
c8dfc6
 
c8dfc6
 # hw/usb/hcd-uhci.c
c8dfc6
 usb_uhci_reset(void) "=== RESET ==="
c8dfc6
-- 
c8dfc6
1.7.12
c8dfc6