Index: /trunk/include/VBox/iommu-intel.h
===================================================================
--- /trunk/include/VBox/iommu-intel.h	(revision 88557)
+++ /trunk/include/VBox/iommu-intel.h	(revision 88558)
@@ -1016,4 +1016,13 @@
 /** RW: Read/write mask. */
 #define VTD_RTADDR_REG_RW_MASK                                  UINT64_C(0xfffffffffffffc00)
+
+/** RTADDR_REG.TTM: Legacy mode. */
+#define VTD_TTM_LEGACY_MODE                                     0
+/** RTADDR_REG.TTM: Scalable mode. */
+#define VTD_TTM_SCALABLE_MODE                                   1
+/** RTADDR_REG.TTM: Reserved. */
+#define VTD_TTM_RSVD                                            2
+/** RTADDR_REG.TTM: Abort DMA mode. */
+#define VTD_TTM_ABORT_DMA_MODE                                  3
 /** @} */
 
Index: /trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp	(revision 88557)
+++ /trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp	(revision 88558)
@@ -110,4 +110,32 @@
 *********************************************************************************************************************************/
 /**
+ * DMAR error diagnostics.
+ *
+ * @note Members of this enum are used as array indices, so no gaps are allowed.
+ *       Please update g_apsz when you add new fields to this enum.
+ */
+typedef enum
+{
+    kDmarDiag_None = 0,
+    kDmarDiag_IqtReg_Qt_NotAligned,
+    /* Last member for determining array index limit. */
+    kDmarDiag_End
+} DMARDIAG;
+AssertCompileSize(DMARDIAG, 4);
+
+/** DMAR diagnostic enum description expansion. */
+#define DMARDIAG_DESC(a_Def, a_Desc)                #a_Def " - " #a_Desc
+
+/** DMAR diagnostics description. */
+static const char *const g_apszDmarDiagDesc[] =
+{
+    DMARDIAG_DESC(kNone,                            "None"                ),
+    DMARDIAG_DESC(kDmarDiag_IqtReg_Qt_NotAligned,   "IqtReg_Qt_NotAligned")
+    /* kDmarDiag_End */
+};
+AssertCompile(RT_ELEMENTS(g_apszDmarDiagDesc) == kDmarDiag_End);
+#undef DMARDIAG_DESC
+
+/**
  * The shared DMAR device state.
  */
@@ -132,5 +160,7 @@
     uint8_t                     uVerReg;
     /** Alignment. */
-    uint8_t                     abPadding[7];
+    uint8_t                     abPadding[3];
+    /** Error diagnostic. */
+    DMARDIAG                    enmDiag;
     /** Copy of CAP_REG. */
     uint64_t                    fCap;
@@ -550,5 +580,5 @@
  * @param   uReg        The 64-bit value to write.
  */
-DECLINLINE(void) dmarRegWriteRaw64(PDMAR pThis, uint16_t offReg, uint64_t uReg)
+static void dmarRegWriteRaw64(PDMAR pThis, uint16_t offReg, uint64_t uReg)
 {
     uint8_t idxGroup;
@@ -566,5 +596,5 @@
  * @param   uReg        The 32-bit value to write.
  */
-DECLINLINE(void) dmarRegWriteRaw32(PDMAR pThis, uint16_t offReg, uint32_t uReg)
+static void dmarRegWriteRaw32(PDMAR pThis, uint16_t offReg, uint32_t uReg)
 {
     uint8_t idxGroup;
@@ -584,5 +614,5 @@
  * @param   pfRw1cMask  Where to store the RW1C mask corresponding to this register.
  */
-DECLINLINE(void) dmarRegReadRaw64(PCDMAR pThis, uint16_t offReg, uint64_t *puReg, uint64_t *pfRwMask, uint64_t *pfRw1cMask)
+static void dmarRegReadRaw64(PCDMAR pThis, uint16_t offReg, uint64_t *puReg, uint64_t *pfRwMask, uint64_t *pfRw1cMask)
 {
     uint8_t idxGroup;
@@ -606,5 +636,5 @@
  * @param   pfRw1cMask  Where to store the RW1C mask corresponding to this register.
  */
-DECLINLINE(void) dmarRegReadRaw32(PCDMAR pThis, uint16_t offReg, uint32_t *puReg, uint32_t *pfRwMask, uint32_t *pfRw1cMask)
+static void dmarRegReadRaw32(PCDMAR pThis, uint16_t offReg, uint32_t *puReg, uint32_t *pfRwMask, uint32_t *pfRw1cMask)
 {
     uint8_t idxGroup;
@@ -712,4 +742,58 @@
 
 /**
+ * Gets the table translation mode from the RTADDR_REG.
+ *
+ * @returns The table translation mode.
+ * @param   pThis   The shared DMAR device state.
+ */
+static uint8_t dmarRtAddrRegGetTtm(PCDMAR pThis)
+{
+    uint64_t const uRtAddrReg = dmarRegRead64(pThis, VTD_MMIO_OFF_RTADDR_REG);
+    return RT_BF_GET(uRtAddrReg, VTD_BF_RTADDR_REG_TTM);
+}
+
+
+/**
+ * Handles writes to CCMD_REG.
+ *
+ * @returns Strict VBox status code.
+ * @param   pDevIns     The IOMMU device instance.
+ * @param   off         The MMIO register offset.
+ * @param   cb          The size of the MMIO access (in bytes).
+ * @param   uCcmdReg    The value written to CCMD_REG.
+ */
+static VBOXSTRICTRC dmarCcmdRegWrite(PPDMDEVINS pDevIns, uint16_t off, uint8_t cb, uint64_t uCcmdReg)
+{
+    /* We only care about responding to high 32-bits writes, low 32-bits are data. */
+    if (off + cb > VTD_MMIO_OFF_CCMD_REG + 4)
+    {
+        /* Check if we need to invalidate the context-context. */
+        bool const fIcc = RT_BF_GET(uCcmdReg, VTD_BF_CCMD_REG_ICC);
+        if (fIcc)
+        {
+            PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR);
+            uint8_t const uMajorVersion = RT_BF_GET(pThis->uVerReg, VTD_BF_VER_REG_MAX);
+            if (uMajorVersion < 6)
+            {
+                /** @todo Verify queued-invalidation is not enabled.
+                 *  See Intel spec. 6.5.1 "Register-based Invalidation Interface" */
+
+                /* Verify table translation mode is legacy. */
+                uint8_t const fTtm = dmarRtAddrRegGetTtm(pThis);
+                if (fTtm == VTD_TTM_LEGACY_MODE)
+                {
+                    /** @todo Invalidate. */
+                    return VINF_SUCCESS;
+                }
+            }
+
+            /** @todo Raise error. */
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Handles writes to IQT_REG.
  *
@@ -721,5 +805,5 @@
 static VBOXSTRICTRC dmarIqtRegWrite(PPDMDEVINS pDevIns, uint16_t off, uint64_t uIqtReg)
 {
-    /* We only care about the low 32-bits. */
+    /* We only care about the low 32-bits, high 32-bits are reserved. */
     if (off == VTD_MMIO_OFF_IQT_REG)
     {
@@ -732,5 +816,5 @@
             || !(offQueueTail & 0x1f))
         {
-            /** @todo IOMMU: Figure out what to do here, like waking up worker thread or
+            /** @todo Figure out what to do here, like waking up worker thread or
              *        something. */
         }
@@ -738,5 +822,5 @@
         {
             /* Raise invalidation queue error as queue tail not aligned to 256-bits. */
-            /** @todo IOMMU: Raise error. */
+            /** @todo Raise error. */
         }
     }
@@ -832,4 +916,11 @@
             {
                 rcStrict = dmarIqtRegWrite(pDevIns, offReg, uRegWritten);
+                break;
+            }
+
+            case VTD_MMIO_OFF_CCMD_REG:
+            case VTD_MMIO_OFF_CCMD_REG + 4:
+            {
+                rcStrict = dmarCcmdRegWrite(pDevIns, offReg, cb, uRegWritten);
                 break;
             }
@@ -1094,9 +1185,9 @@
     PDMPciDevSetSubSystemVendorId(pPciDev, DMAR_PCI_VENDOR_ID);         /* Intel */
 
-    /** @todo VTD: Chipset spec says PCI Express Capability Id. Relevant for us? */
+    /** @todo Chipset spec says PCI Express Capability Id. Relevant for us? */
     PDMPciDevSetStatus(pPciDev,            0);
     PDMPciDevSetCapabilityList(pPciDev,    0);
 
-    /** @todo VTD: VTBAR at 0x180? */
+    /** @todo VTBAR at 0x180? */
 
     /*
@@ -1106,5 +1197,5 @@
     AssertLogRelRCReturn(rc, rc);
 
-    /** @todo VTD: Register MSI but what's the MSI capability offset? */
+    /** @todo Register MSI but what's the MSI capability offset? */
 #if 0
     /*
