Index: /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp	(revision 84300)
+++ /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp	(revision 84301)
@@ -1129,7 +1129,5 @@
         uint32_t    u28Rsvd0 : 28;      /**< Bits 47:32  - Reserved. */
         uint32_t    u4EvtCode : 4;      /**< Bits 63:60  - Event code. */
-        uint32_t    u4Rsvd0 : 4;        /**< Bits 67:64  - Reserved. */
-        uint32_t    u28AddrLo : 28;     /**< Bits 95:68  - Address: SPA of the invalid command (Lo). */
-        uint32_t    u32AddrHi;          /**< Bits 127:96 - Address: SPA of the invalid command (Hi). */
+        uint64_t    u64Addr;            /**< Bits 127:64 - Address: SPA of the invalid command. */
     } n;
     /** The 32-bit unsigned integer view. */
@@ -1139,4 +1137,8 @@
 } EVT_ILLEGAL_CMD_ERR_T;
 AssertCompileSize(EVT_ILLEGAL_CMD_ERR_T, 16);
+/** Pointer to an illegal command error event. */
+typedef EVT_ILLEGAL_CMD_ERR_T *PEVT_ILLEGAL_CMD_ERR_T;
+/** Pointer to a const illegal command error event. */
+typedef EVT_ILLEGAL_CMD_ERR_T const *PCEVT_ILLEGAL_CMD_ERR_T;
 
 /**
@@ -2185,4 +2187,6 @@
     kIllegalCmdErrType_IotlbNotSupported
 } EVT_ILLEGAL_CMD_ERR_TYPE_T;
+/** Pointer to an illegal command error event type. */
+typedef EVT_ILLEGAL_CMD_ERR_TYPE_T *PEVT_ILLEGAL_CMD_ERR_TYPE_T;
 
 /**
@@ -2539,5 +2543,5 @@
  * @param   uEncodedLen     The length (power-of-2 encoded).
  */
-DECLINLINE(uint32_t) iommuAmdGetBufLength(uint8_t uEncodedLen)
+DECLINLINE(uint32_t) iommuAmdGetTotalBufLength(uint8_t uEncodedLen)
 {
     Assert(uEncodedLen > 7);
@@ -3014,5 +3018,5 @@
      */
     uint32_t const offBuf = u64Value & IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK;
-    uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->CmdBufBaseAddr.n.u4Len);
+    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len);
     Assert(cbBuf <= _512K);
     if (offBuf >= cbBuf)
@@ -3046,5 +3050,5 @@
      */
     uint32_t const offBuf = u64Value & IOMMU_CMD_BUF_TAIL_PTR_VALID_MASK;
-    uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->CmdBufBaseAddr.n.u4Len);
+    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len);
     Assert(cbBuf <= _512K);
     if (offBuf >= cbBuf)
@@ -3088,5 +3092,5 @@
      */
     uint32_t const offBuf = u64Value & IOMMU_EVT_LOG_HEAD_PTR_VALID_MASK;
-    uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->EvtLogBaseAddr.n.u4Len);
+    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->EvtLogBaseAddr.n.u4Len);
     Assert(cbBuf <= _512K);
     if (offBuf >= cbBuf)
@@ -3130,5 +3134,5 @@
      */
     uint32_t const offBuf = u64Value & IOMMU_EVT_LOG_TAIL_PTR_VALID_MASK;
-    uint32_t const cbBuf  = iommuAmdGetBufLength(pThis->EvtLogBaseAddr.n.u4Len);
+    uint32_t const cbBuf  = iommuAmdGetTotalBufLength(pThis->EvtLogBaseAddr.n.u4Len);
     Assert(cbBuf <= _512K);
     if (offBuf >= cbBuf)
@@ -3569,5 +3573,5 @@
 
             /* Increment the event log tail pointer. */
-            uint32_t const cbEvtLog = iommuAmdGetBufLength(pThis->EvtLogBaseAddr.n.u4Len);
+            uint32_t const cbEvtLog = iommuAmdGetTotalBufLength(pThis->EvtLogBaseAddr.n.u4Len);
             pThis->EvtLogTailPtr.n.off = (offEvt + cbEvt) % cbEvtLog;
 
@@ -3770,4 +3774,45 @@
     Log((IOMMU_LOG_PFX ": Raised DEV_TAB_HARDWARE_ERROR. uDevId=%#x GCPhysDte=%#RGp enmOp=%u enmType=%u\n",
          pEvtDevTabHwErr->n.u16DevId, pEvtDevTabHwErr->n.u64Addr, enmOp, enmEvtType));
+    NOREF(enmEvtType);
+}
+
+
+/**
+ * Initializes an ILLEGAL_COMMAND_ERROR event.
+ *
+ * @param   GCPhysCmd       The system physical address of the failed command
+ *                          access.
+ * @param   pEvtIllegalCmd  Where to store the initialized event.
+ */
+static void iommuAmdInitIllegalCmdEvent(RTGCPHYS GCPhysCmd, PEVT_ILLEGAL_CMD_ERR_T pEvtIllegalCmd)
+{
+    Assert(!(GCPhysCmd & UINT64_C(0xf)));
+    memset(pEvtIllegalCmd, 0, sizeof(*pEvtIllegalCmd));
+    pEvtIllegalCmd->n.u4EvtCode = IOMMU_EVT_ILLEGAL_CMD_ERROR;
+    pEvtIllegalCmd->n.u64Addr   = GCPhysCmd;
+}
+
+
+/**
+ * Raises an ILLEGAL_COMMAND_ERROR event.
+ *
+ * @param   pDevIns         The IOMMU device instance.
+ * @param   pEvtIllegalCmd  The illegal command error event.
+ * @param   enmEvtType      The illegal command error event type.
+ */
+static void iommuAmdRaiseIllegalCmdEvent(PPDMDEVINS pDevIns, PCEVT_ILLEGAL_CMD_ERR_T pEvtIllegalCmd,
+                                         EVT_ILLEGAL_CMD_ERR_TYPE_T enmEvtType)
+{
+    AssertCompile(sizeof(EVT_GENERIC_T) == sizeof(EVT_ILLEGAL_DTE_T));
+    PCEVT_GENERIC_T pEvent = (PCEVT_GENERIC_T)pEvtIllegalCmd;
+
+    IOMMU_LOCK_NORET(pDevIns);
+
+    iommuAmdWriteEvtLogEntry(pDevIns, pEvent);
+    iommuAmdHaltCmdProcessing(pDevIns);
+
+    IOMMU_UNLOCK(pDevIns);
+
+    Log((IOMMU_LOG_PFX ": Raised ILLEGAL_COMMAND_ERROR. GCPhysCmd=%#RGp enmType=%u\n", pEvtIllegalCmd->n.u64Addr, enmEvtType));
     NOREF(enmEvtType);
 }
@@ -3808,5 +3853,5 @@
  * @param   enmOp           The IOMMU operation being performed.
  * @param   pEvtIllegalDte  The illegal device table entry event.
- * @param   enmEvtType      The illegal DTE event type.
+ * @param   enmEvtType      The illegal device table entry event type.
  *
  * @thread  Any.
@@ -4577,8 +4622,10 @@
  *
  * @returns VBox status code.
- * @param   pDevIns     The IOMMU device instance.
- * @param   pCmd        The command to process.
- */
-static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, PCCMD_GENERIC_T pCmd)
+ * @param   pDevIns         The IOMMU device instance.
+ * @param   pCmd            The command to process.
+ * @param   penmEvtType     Where to store the illegal command error event type in
+ *                          case of failures.
+ */
+static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, PCCMD_GENERIC_T pCmd, PEVT_ILLEGAL_CMD_ERR_TYPE_T penmEvtType)
 {
     IOMMU_ASSERT_NOT_LOCKED(pDevIns);
@@ -4606,4 +4653,5 @@
 
     Log((IOMMU_LOG_PFX ": Invalid/Unrecognized command opcode %u (%#x)\n", bCmd, bCmd));
+    *penmEvtType = kIllegalCmdErrType_CmdNotSupported;
     return VERR_INVALID_FUNCTION;
 }
@@ -4658,10 +4706,12 @@
             IOMMU_LOCK(pDevIns);
 
-            uint32_t const cbCmdBuf = iommuAmdGetBufLength(pThis->CmdBufBaseAddr.n.u4Len);
+            /* Get the offset we need to read the command from memory (circular buffer offset). */
+            uint32_t const cbCmdBuf = iommuAmdGetTotalBufLength(pThis->CmdBufBaseAddr.n.u4Len);
             uint32_t offHead = pThis->CmdBufHeadPtr.n.off;
             Assert(!(offHead & ~IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK));
+            Assert(offHead < cbCmdBuf);
             while (offHead != pThis->CmdBufTailPtr.n.off)
             {
-                /* Fetch the command from guest memory. */
+                /* Read the command from memory. */
                 CMD_GENERIC_T Cmd;
                 RTGCPHYS const GCPhysCmd = (pThis->CmdBufBaseAddr.n.u40Base << X86_PAGE_4K_SHIFT) + offHead;
@@ -4674,6 +4724,7 @@
 
                     /* Process the fetched command. */
+                    EVT_ILLEGAL_CMD_ERR_TYPE_T enmEvtType;
                     IOMMU_UNLOCK(pDevIns);
-                    rc = iommuAmdR3ProcessCmd(pDevIns, &Cmd);
+                    rc = iommuAmdR3ProcessCmd(pDevIns, &Cmd, &enmEvtType);
                     IOMMU_LOCK(pDevIns);
                     if (RT_SUCCESS(rc))
@@ -4681,7 +4732,7 @@
                     else
                     {
-                        /** @todo IOMMU: Raise illegal command error. */
-                        /* Stop command processing. */
-                        ASMAtomicAndU64(&pThis->Status.u64, ~IOMMU_STATUS_CMD_BUF_RUNNING);
+                        EVT_ILLEGAL_CMD_ERR_T EvtIllegalCmdErr;
+                        iommuAmdInitIllegalCmdEvent(GCPhysCmd, &EvtIllegalCmdErr);
+                        iommuAmdRaiseIllegalCmdEvent(pDevIns, &EvtIllegalCmdErr, enmEvtType);
                         break;
                     }
@@ -4846,5 +4897,5 @@
         uint8_t const  uEncodedLen = CmdBufBar.n.u4Len;
         uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
-        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
+        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
         pHlp->pfnPrintf(pHlp, "  Command buffer BAR                      = %#RX64\n", CmdBufBar.u64);
         if (fVerbose)
@@ -4860,5 +4911,5 @@
         uint8_t const  uEncodedLen = EvtLogBar.n.u4Len;
         uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
-        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
+        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
         pHlp->pfnPrintf(pHlp, "  Event log BAR                           = %#RX64\n", EvtLogBar.u64);
         if (fVerbose)
@@ -4982,5 +5033,5 @@
         uint8_t const  uEncodedLen = PprLogBar.n.u4Len;
         uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
-        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
+        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
         pHlp->pfnPrintf(pHlp, "  PPR Log BAR                             = %#RX64\n",   PprLogBar.u64);
         if (fVerbose)
@@ -5018,5 +5069,5 @@
         uint8_t const  uEncodedLen = GALogBar.n.u4Len;
         uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
-        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
+        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
         pHlp->pfnPrintf(pHlp, "  Guest Log BAR                           = %#RX64\n",    GALogBar.u64);
         if (fVerbose)
@@ -5039,5 +5090,5 @@
         uint8_t const uEncodedLen  = PprLogBBar.n.u4Len;
         uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
-        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
+        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
         pHlp->pfnPrintf(pHlp, "  PPR Log B BAR                           = %#RX64\n",   PprLogBBar.u64);
         if (fVerbose)
@@ -5053,5 +5104,5 @@
         uint8_t const  uEncodedLen = EvtLogBBar.n.u4Len;
         uint32_t const cEntries    = iommuAmdGetBufMaxEntries(uEncodedLen);
-        uint32_t const cbBuffer    = iommuAmdGetBufLength(uEncodedLen);
+        uint32_t const cbBuffer    = iommuAmdGetTotalBufLength(uEncodedLen);
         pHlp->pfnPrintf(pHlp, "  Event Log B BAR                         = %#RX64\n",   EvtLogBBar.u64);
         if (fVerbose)
