Index: trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
===================================================================
--- trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp	(revision 88626)
+++ trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp	(revision 88627)
@@ -111,5 +111,5 @@
 
 /** DMAR implementation's major version number (exposed to software).
- *  We report 6 as the major version since we support queued invalidations as
+ *  We report 6 as the major version since we support queued-invalidations as
  *  software may make assumptions based on that.
  *
@@ -171,8 +171,8 @@
     /** The MMIO handle. */
     IOMMMIOHANDLE               hMmio;
-    /** The event semaphore the queued-invalidation thread waits on. */
-    SUPSEMEVENT                 hEvtQueuedInvThread;
-    /** Whether the queued-invalidation thread has been signaled. */
-    bool volatile               fQueuedInvThreadSignaled;
+    /** The event semaphore the invalidation-queue thread waits on. */
+    SUPSEMEVENT                 hEvtInvQueue;
+    /** Whether the invalidation-queue thread has been signaled. */
+    bool volatile               fInvQueueThreadSignaled;
     /** Padding. */
     bool                        afPadding0[3];
@@ -233,6 +233,6 @@
     /** The IOMMU helper. */
     R3PTRTYPE(PCPDMIOMMUHLPR3)  pIommuHlpR3;
-    /** The queued-invalidation thread. */
-    R3PTRTYPE(PPDMTHREAD)       pQueuedInvThread;
+    /** The invalidation-queue thread. */
+    R3PTRTYPE(PPDMTHREAD)       pInvQueueThread;
 } DMARR3;
 /** Pointer to the ring-3 DMAR device state. */
@@ -851,4 +851,66 @@
 
 /**
+ * Checks whether the invalidation-queue is empty.
+ *
+ * @returns @c true if empty, @c false otherwise.
+ * @param   pThis   The shared DMAR device state.
+ */
+static bool dmarInvQueueIsEmpty(PCDMAR pThis)
+{
+    uint64_t const uIqtReg      = dmarRegRead64(pThis, VTD_MMIO_OFF_IQT_REG);
+    uint32_t const offQueueTail = VTD_IQT_REG_GET_QT(uIqtReg);
+
+    uint64_t const uIqhReg      = dmarRegRead64(pThis, VTD_MMIO_OFF_IQH_REG);
+    uint32_t const offQueueHead = VTD_IQT_REG_GET_QH(uIqhReg);
+
+    return offQueueTail == offQueueHead;
+}
+
+
+/**
+ * Checks whether the invalidation-queue is capable of processing requests.
+ *
+ * @returns @c true if the invalidation-queue can be processed, @c false otherwise.
+ * @param   pThis   The shared DMAR device state.
+ */
+static bool dmarInvQueueCanProcessRequests(PCDMAR pThis)
+{
+    /* Check if queued-invalidation is enabled. */
+    uint32_t const uGstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG);
+    if (uGstsReg & VTD_BF_GSTS_REG_QIES_MASK)
+    {
+        /* Check if there are no IQ errors and that the queue isn't empty. */
+        uint32_t const uFstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_FSTS_REG);
+        if (   !(uFstsReg & VTD_BF_FSTS_REG_IQE_MASK)
+            && !dmarInvQueueIsEmpty(pThis))
+            return true;
+    }
+    return false;
+}
+
+
+/**
+ * Wakes up the invalidation-queue thread if there are requests to be processed.
+ *
+ * @param   pDevIns     The IOMMU device instance.
+ */
+static void dmarInvQueueThreadWakeUpIfNeeded(PPDMDEVINS pDevIns)
+{
+    PDMAR    pThis   = PDMDEVINS_2_DATA(pDevIns, PDMAR);
+    PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);
+    Log4Func(("\n"));
+
+    DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC);
+
+    if (   dmarInvQueueCanProcessRequests(pThis)
+        && !ASMAtomicXchgBool(&pThis->fInvQueueThreadSignaled, true))
+    {
+        Log4Func(("Signaling the invalidation-queue thread\n"));
+        PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtInvQueue);
+    }
+}
+
+
+/**
  * Raises an interrupt in response to an event.
  *
@@ -1023,13 +1085,5 @@
         if (   fDw != VTD_IQA_REG_DW_256_BIT
             || !(offQueueTail & 0x1f))
-        {
-            /* Don't bother waking the thread if an invalidation-queue error is pending. */
-            uint32_t const uFstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_FSTS_REG);
-            if (!(uFstsReg & VTD_BF_FSTS_REG_IQE_MASK))
-            {
-                /** @todo Figure out what to do here, like waking up worker thread or
-                 *        something. */
-            }
-        }
+            dmarInvQueueThreadWakeUpIfNeeded(pDevIns);
         else
             dmarIqeFaultRecord(pDevIns, kDmarDiag_IqtReg_Qt_NotAligned, kQueueTailNotAligned);
@@ -1217,5 +1271,5 @@
 #ifdef IN_RING3
 /**
- * The queued-invalidation thread function.
+ * The invalidation-queue thread.
  *
  * @returns VBox status code.
@@ -1223,5 +1277,5 @@
  * @param   pThread     The command thread.
  */
-static DECLCALLBACK(int) dmarR3QueuedInvThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+static DECLCALLBACK(int) dmarR3InvQueueThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
 {
     NOREF(pThread);
@@ -1239,16 +1293,16 @@
          * Sleep until we are woken up.
          */
-        bool const fSignaled = ASMAtomicXchgBool(&pThis->fQueuedInvThreadSignaled, false);
+        bool const fSignaled = ASMAtomicXchgBool(&pThis->fInvQueueThreadSignaled, false);
         if (!fSignaled)
         {
-            int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtQueuedInvThread, RT_INDEFINITE_WAIT);
+            int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtInvQueue, RT_INDEFINITE_WAIT);
             AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
             if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
                 break;
-            ASMAtomicWriteBool(&pThis->fQueuedInvThreadSignaled, false);
+            ASMAtomicWriteBool(&pThis->fInvQueueThreadSignaled, false);
         }
 
         /*
-         * Fetch and process queued-invalidation requests.
+         * Fetch and process invalidation requests.
          */
         DMAR_LOCK_RET(pDevIns, pThisR3, VERR_IGNORED);
@@ -1262,5 +1316,5 @@
     }
 
-    LogFlowFunc(("Queued-invalidation thread terminating\n"));
+    LogFlowFunc(("Invalidation-queue thread terminating\n"));
     return VINF_SUCCESS;
 }
@@ -1268,18 +1322,19 @@
 
 /**
- * Wakes up the queued-invalidation thread so it can respond to a state change.
+ * Wakes up the invalidation-queue thread so it can respond to a state
+ * change.
  *
  * @returns VBox status code.
  * @param   pDevIns     The IOMMU device instance.
- * @param   pThread     The queued-invalidation thread.
+ * @param   pThread     The invalidation-queue thread.
  *
  * @thread EMT.
  */
-static DECLCALLBACK(int) dmarR3QueuedInvThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+static DECLCALLBACK(int) dmarR3InvQueueThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
 {
     RT_NOREF(pThread);
     LogFlowFunc(("\n"));
     PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
-    return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtQueuedInvThread);
+    return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtInvQueue);
 }
 
@@ -1379,5 +1434,5 @@
     /* ECAP_REG */
     {
-        uint8_t const  fQi    = 1;                              /* Queued invalidations. */
+        uint8_t const  fQi    = 1;                              /* Queued-invalidations. */
         uint8_t const  fIr    = !!(DMAR_ACPI_DMAR_FLAGS & ACPI_DMAR_F_INTR_REMAP);  /* Interrupt remapping support. */
         uint8_t const  fMhmv  = 0xf;                            /* Maximum handle mask value. */
@@ -1461,8 +1516,8 @@
     LogFlowFunc(("\n"));
 
-    if (pThis->hEvtQueuedInvThread != NIL_SUPSEMEVENT)
-    {
-        PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtQueuedInvThread);
-        pThis->hEvtQueuedInvThread = NIL_SUPSEMEVENT;
+    if (pThis->hEvtInvQueue != NIL_SUPSEMEVENT)
+    {
+        PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtInvQueue);
+        pThis->hEvtInvQueue = NIL_SUPSEMEVENT;
     }
 
@@ -1595,14 +1650,14 @@
 
     /*
-     * Create queued-invalidation thread and semaphore.
+     * Create invalidation-queue thread and semaphore.
      */
-    char szQueuedInvThread[32];
-    RT_ZERO(szQueuedInvThread);
-    RTStrPrintf(szQueuedInvThread, sizeof(szQueuedInvThread), "IOMMU-QI-%u", iInstance);
-    rc = PDMDevHlpThreadCreate(pDevIns, &pThisR3->pQueuedInvThread, pThis, dmarR3QueuedInvThread, dmarR3QueuedInvThreadWakeUp,
-                               0 /* cbStack */, RTTHREADTYPE_IO, szQueuedInvThread);
+    char szInvQueueThread[32];
+    RT_ZERO(szInvQueueThread);
+    RTStrPrintf(szInvQueueThread, sizeof(szInvQueueThread), "IOMMU-QI-%u", iInstance);
+    rc = PDMDevHlpThreadCreate(pDevIns, &pThisR3->pInvQueueThread, pThis, dmarR3InvQueueThread, dmarR3InvQueueThreadWakeUp,
+                               0 /* cbStack */, RTTHREADTYPE_IO, szInvQueueThread);
     AssertLogRelRCReturn(rc, rc);
 
-    rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtQueuedInvThread);
+    rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtInvQueue);
     AssertLogRelRCReturn(rc, rc);
 
