Index: /trunk/include/VBox/err.h
===================================================================
--- /trunk/include/VBox/err.h	(revision 84316)
+++ /trunk/include/VBox/err.h	(revision 84317)
@@ -2981,4 +2981,10 @@
 /** Access denied for the address. */
 #define VERR_IOMMU_ADDR_ACCESS_DENIED               (-7205)
+/** Internal error - Command not supported. */
+#define VERR_IOMMU_CMD_NOT_SUPPORTED                (-7206)
+/** Internal error - Command format (or reserved bits) invalid. */
+#define VERR_IOMMU_CMD_INVALID_FORMAT               (-7207)
+/** Internal error - Command hardware failure. */
+#define VERR_IOMMU_CMD_HW_ERROR                     (-7208)
 /** @} */
 
Index: /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp	(revision 84316)
+++ /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp	(revision 84317)
@@ -2183,17 +2183,4 @@
 
 /**
- * ILLEGAL_COMMAND_ERROR Event Types.
- * In accordance with the AMD spec.
- */
-typedef enum EVT_ILLEGAL_CMD_ERR_TYPE_T
-{
-    kIllegalCmdErrType_RsvdNotZero = 0,
-    kIllegalCmdErrType_CmdNotSupported,
-    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;
-
-/**
  * IOTLB_INV_TIMEOUT Event Types.
  * In accordance with the AMD spec.
@@ -3346,6 +3333,6 @@
     Assert(!(off & 7) || !(off & 3));
 
-    PIOMMU     pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
-    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
+    PIOMMU      pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
+    PCPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
 
@@ -3784,8 +3771,6 @@
  * @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)
+ */
+static void iommuAmdRaiseIllegalCmdEvent(PPDMDEVINS pDevIns, PCEVT_ILLEGAL_CMD_ERR_T pEvtIllegalCmd)
 {
     AssertCompile(sizeof(EVT_GENERIC_T) == sizeof(EVT_ILLEGAL_DTE_T));
@@ -3800,6 +3785,5 @@
     IOMMU_UNLOCK(pDevIns);
 
-    Log((IOMMU_LOG_PFX ": Raised ILLEGAL_COMMAND_ERROR. GCPhysCmd=%#RGp enmType=%u\n", pEvtIllegalCmd->n.u64Addr, enmEvtType));
-    NOREF(enmEvtType);
+    Log((IOMMU_LOG_PFX ": Raised ILLEGAL_COMMAND_ERROR. Addr=%#RGp\n", pEvtIllegalCmd->n.u64Addr));
 }
 
@@ -4609,14 +4593,13 @@
  * @returns VBox status code.
  * @param   pDevIns         The IOMMU device instance.
+ * @param   pCmd            The command to process.
  * @param   GCPhysCmd       The system physical address of the command.
- * @param   pCmd            The command to process.
+ * @param   pEvtError       Where to store the error event in case of failures.
  *
  * @thread  Command thread.
  */
-static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCmd, PCCMD_GENERIC_T pCmd)
+static int iommuAmdR3ProcessCmd(PPDMDEVINS pDevIns, PCCMD_GENERIC_T pCmd, RTGCPHYS GCPhysCmd, PEVT_GENERIC_T pEvtError)
 {
     IOMMU_ASSERT_NOT_LOCKED(pDevIns);
-
-    EVT_ILLEGAL_CMD_ERR_T EvtIllegalCmdErr;
 
     PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
@@ -4632,22 +4615,20 @@
             if (!(pCmdComWait->au64[0] & ~IOMMU_CMD_COM_WAIT_QWORD_0_VALID_MASK))
             {
-                /* If Completion Store is requested, write the Store Data to the specified Store Address.*/
+                /* If Completion Store is requested, write the StoreData to the specified address.*/
                 if (pCmdComWait->n.u1Store)
                 {
                     RTGCPHYS const GCPhysStore = RT_MAKE_U64(pCmdComWait->n.u29StoreAddrLo << 3, pCmdComWait->n.u20StoreAddrHi);
                     uint64_t const u64Data     = pCmdComWait->n.u64StoreData;
-
                     int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysStore, &u64Data, sizeof(u64Data));
                     if (RT_FAILURE(rc))
                     {
-                        EVT_CMD_HW_ERR_T EvtCmdHwErr;
-                        iommuAmdInitCmdHwErrorEvent(GCPhysStore, &EvtCmdHwErr);
-                        iommuAmdRaiseCmdHwErrorEvent(pDevIns, &EvtCmdHwErr);
-                        Log((IOMMU_LOG_PFX ": Failed to write StoreData (%#RX64) to %#RGp. rc=%Rrc\n", u64Data, GCPhysStore, rc));
-                        return rc;
+                        Log((IOMMU_LOG_PFX ": Cmd(%#x): Failed to write StoreData (%#RX64) to %#RGp, rc=%Rrc\n", bCmd, u64Data,
+                             GCPhysStore, rc));
+                        iommuAmdInitCmdHwErrorEvent(GCPhysStore, (PEVT_CMD_HW_ERR_T)pEvtError);
+                        return VERR_IOMMU_CMD_HW_ERROR;
                     }
                 }
 
-                /* If command completion interrupt is requested, honor it. */
+                /* If command completion interrupt is requested, raise an interrupt. */
                 if (pCmdComWait->n.u1Interrupt)
                 {
@@ -4668,16 +4649,39 @@
                 return VINF_SUCCESS;
             }
-
-            iommuAmdInitIllegalCmdEvent(GCPhysCmd, &EvtIllegalCmdErr);
-            iommuAmdRaiseIllegalCmdEvent(pDevIns, &EvtIllegalCmdErr, kIllegalCmdErrType_RsvdNotZero);
-            return VERR_INVALID_FUNCTION;
+            iommuAmdInitIllegalCmdEvent(GCPhysCmd, (PEVT_ILLEGAL_CMD_ERR_T)pEvtError);
+            return VERR_IOMMU_CMD_INVALID_FORMAT;
         }
 
         case IOMMU_CMD_INV_DEV_TAB_ENTRY:
+        {
+            /** @todo IOMMU: Implement this once we implement IOTLB. Pretend success until
+             *        then. */
+            return VINF_SUCCESS;
+        }
+
         case IOMMU_CMD_INV_IOMMU_PAGES:
+        {
+            /** @todo IOMMU: Implement this once we implement IOTLB. Pretend success until
+             *        then. */
+            return VINF_SUCCESS;
+        }
+
         case IOMMU_CMD_INV_IOTLB_PAGES:
+        {
+            uint32_t const uCapHdr = PDMPciDevGetDWord(pDevIns->apPciDevs[0], IOMMU_PCI_OFF_CAP_HDR);
+            if (RT_BF_GET(uCapHdr, IOMMU_BF_CAPHDR_IOTLB_SUP))
+            {
+                /** @todo IOMMU: Implement remote IOTLB invalidation. */
+                return VERR_NOT_IMPLEMENTED;
+            }
+            iommuAmdInitIllegalCmdEvent(GCPhysCmd, (PEVT_ILLEGAL_CMD_ERR_T)pEvtError);
+            return VERR_IOMMU_CMD_NOT_SUPPORTED;
+        }
+
         case IOMMU_CMD_INV_INTR_TABLE:
         {
-            return VERR_NOT_IMPLEMENTED;
+            /** @todo IOMMU: Implement this once we implement IOTLB. Pretend success until
+             *        then. */
+            return VINF_SUCCESS;
         }
 
@@ -4686,25 +4690,34 @@
             if (pThis->ExtFeat.n.u1PrefetchSup)
             {
-                /** @todo IOMMU: Implement prefetch. */
+                /** @todo IOMMU: Implement prefetch. Pretend success until then. */
                 return VINF_SUCCESS;
             }
-            iommuAmdInitIllegalCmdEvent(GCPhysCmd, &EvtIllegalCmdErr);
-            iommuAmdRaiseIllegalCmdEvent(pDevIns, &EvtIllegalCmdErr, kIllegalCmdErrType_CmdNotSupported);
-            return VERR_INVALID_FUNCTION;
+            iommuAmdInitIllegalCmdEvent(GCPhysCmd, (PEVT_ILLEGAL_CMD_ERR_T)pEvtError);
+            return VERR_IOMMU_CMD_NOT_SUPPORTED;
         }
 
         case IOMMU_CMD_COMPLETE_PPR_REQ:
+        {
+            /* We don't support PPR requests yet. */
+            Assert(!pThis->ExtFeat.n.u1PprSup);
+            iommuAmdInitIllegalCmdEvent(GCPhysCmd, (PEVT_ILLEGAL_CMD_ERR_T)pEvtError);
+            return VERR_IOMMU_CMD_NOT_SUPPORTED;
+        }
+
         case IOMMU_CMD_INV_IOMMU_ALL:
         {
-            NOREF(pThis);
-            return VERR_NOT_IMPLEMENTED;
-        }
-
-        default:
-            break;
-    }
-
-    Log((IOMMU_LOG_PFX ": Unrecognized or unsupported command opcode %u (%#x)\n", bCmd, bCmd));
-    return VERR_NOT_SUPPORTED;
+            if (pThis->ExtFeat.n.u1InvAllSup)
+            {
+                /** @todo IOMMU: Invalidate all. Pretend success until then. */
+                return VINF_SUCCESS;
+            }
+            iommuAmdInitIllegalCmdEvent(GCPhysCmd, (PEVT_ILLEGAL_CMD_ERR_T)pEvtError);
+            return VERR_IOMMU_CMD_NOT_SUPPORTED;
+        }
+    }
+
+    Log((IOMMU_LOG_PFX ": Cmd(%#x): Unrecognized\n", bCmd));
+    iommuAmdInitIllegalCmdEvent(GCPhysCmd, (PEVT_ILLEGAL_CMD_ERR_T)pEvtError);
+    return VERR_IOMMU_CMD_NOT_SUPPORTED;
 }
 
@@ -4776,9 +4789,17 @@
 
                     /* Process the fetched command. */
+                    EVT_GENERIC_T EvtError;
                     IOMMU_UNLOCK(pDevIns);
-                    rc = iommuAmdR3ProcessCmd(pDevIns, GCPhysCmd, &Cmd);
+                    rc = iommuAmdR3ProcessCmd(pDevIns, &Cmd, GCPhysCmd, &EvtError);
                     IOMMU_LOCK(pDevIns);
                     if (RT_FAILURE(rc))
+                    {
+                        if (   rc == VERR_IOMMU_CMD_NOT_SUPPORTED
+                            || rc == VERR_IOMMU_CMD_INVALID_FORMAT)
+                            iommuAmdRaiseIllegalCmdEvent(pDevIns, (PCEVT_ILLEGAL_CMD_ERR_T)&EvtError);
+                        else if (rc == VERR_IOMMU_CMD_HW_ERROR)
+                            iommuAmdRaiseCmdHwErrorEvent(pDevIns, (PCEVT_CMD_HW_ERR_T)&EvtError);
                         break;
+                    }
                 }
                 else
@@ -4919,5 +4940,5 @@
 {
     PCIOMMU    pThis   = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
-    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
+    PCPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
 
