Index: /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp	(revision 83665)
+++ /trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp	(revision 83666)
@@ -1131,4 +1131,5 @@
 } IOMMU_EXCL_RANGE_BAR_T;
 AssertCompileSize(IOMMU_EXCL_RANGE_BAR_T, 8);
+#define IOMMU_EXCL_RANGE_BAR_VALID_MASK     UINT64_C(0x000ffffffffff003)
 
 /**
@@ -1148,4 +1149,6 @@
 } IOMMU_EXCL_RANGE_LIMIT_T;
 AssertCompileSize(IOMMU_EXCL_RANGE_LIMIT_T, 8);
+#define IOMMU_EXCL_RANGE_LIMIT_VALID_MASK   UINT64_C(0x000ffffffffff000)
+
 
 /**
@@ -1222,4 +1225,5 @@
 } PPR_LOG_BAR_T;
 AssertCompileSize(PPR_LOG_BAR_T, 8);
+#define IOMMU_PPR_LOG_BAR_VALID_MASK    UINT64_C(0x0f0ffffffffff000)
 
 /**
@@ -2053,4 +2057,34 @@
 
 /**
+ * Logs if the buffer length is invalid.
+ *
+ * @param   uEncodedLen     The length to decode.
+ * @param   pszFunc         Name of the calling function for logging purposes.
+ */
+DECLINLINE(void) iommuAmdCheckBufferLength(uint8_t uEncodedLen, const char *pszFunc)
+{
+#ifdef VBOX_STRICT
+    uint32_t cEntries;
+    iommuAmdDecodeBufferLength(uEncodedLen, &cEntries, NULL /* pcbBuffer */);
+    if (!cEntries)
+        Log((IOMMU_LOG_PFX ": %s: Invalid length %#x\n", pszFunc, uEncodedLen));
+#else
+    RT_NOREF(uEncodedLen, pszFunc);
+#endif
+}
+
+
+/**
+ * Writes to a read-only register.
+ */
+static VBOXSTRICTRC iommuAmdIgnore_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t  u64Value)
+{
+    RT_NOREF(pDevIns, pThis, iReg);
+    Log((IOMMU_LOG_PFX ": iommuAmdIgnore_w: Write to read-only register (%#x) with value %#RX64 ignored\n", iReg, u64Value));
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Writes the Device Table Base Address Register.
  */
@@ -2070,12 +2104,5 @@
     RT_NOREF(pDevIns, pThis, iReg);
     pThis->CmdBufBaseAddr.u64 = u64Value & IOMMU_CMD_BUF_BAR_VALID_MASK;
-
-#ifdef VBOX_STRICT
-    uint32_t cEntries;
-    uint8_t const uLen = pThis->CmdBufBaseAddr.n.u4CmdLen;
-    iommuAmdDecodeBufferLength(uLen, &cEntries, NULL /* pcbBuffer */);
-    if (!cEntries)
-        Log((IOMMU_LOG_PFX ": iommuAmdCmdBufBar_w: Invalid length %#x\n", uLen));
-#endif
+    iommuAmdCheckBufferLength(pThis->CmdBufBaseAddr.n.u4CmdLen, __PRETTY_FUNCTION__);
     return VINF_SUCCESS;
 }
@@ -2088,12 +2115,39 @@
     RT_NOREF(pDevIns, pThis, iReg);
     pThis->EvtLogBaseAddr.u64 = u64Value & IOMMU_EVT_LOG_BAR_VALID_MASK;
-
-#ifdef VBOX_STRICT
-    uint32_t cEntries;
-    uint8_t const uLen = pThis->EvtLogBaseAddr.n.u4EvtLen;
-    iommuAmdDecodeBufferLength(uLen, &cEntries, NULL /* pcbBuffer */);
-    if (!cEntries)
-        Log((IOMMU_LOG_PFX ": iommuAmdEvtLogBar_w: Invalid length %#x\n", uLen));
-#endif
+    iommuAmdCheckBufferLength(pThis->EvtLogBaseAddr.n.u4EvtLen, __PRETTY_FUNCTION__);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Writes to the Excluse Range Base Address Register.
+ */
+static VBOXSTRICTRC iommuAmdExclRangeBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t  u64Value)
+{
+    RT_NOREF(pDevIns, pThis, iReg);
+    pThis->ExclRangeBaseAddr.u64 = u64Value & IOMMU_EXCL_RANGE_BAR_VALID_MASK;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Writes to the Excluse Range Limit Register.
+ */
+static VBOXSTRICTRC iommuAmdExclRangeLimit_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t  u64Value)
+{
+    RT_NOREF(pDevIns, pThis, iReg);
+    pThis->ExclRangeLimit.u64 = u64Value & IOMMU_EXCL_RANGE_LIMIT_VALID_MASK;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Writes the PPR Log Base Address Register.
+ */
+static VBOXSTRICTRC iommuAmdPprLogBar_w(PPDMDEVINS pDevIns, PIOMMU pThis, uint32_t iReg, uint64_t  u64Value)
+{
+    RT_NOREF(pDevIns, pThis, iReg);
+    pThis->PprLogBaseAddr.u64 = u64Value & IOMMU_PPR_LOG_BAR_VALID_MASK;
+    iommuAmdCheckBufferLength(pThis->PprLogBaseAddr.n.u4PprLogLen, __PRETTY_FUNCTION__);
     return VINF_SUCCESS;
 }
@@ -2122,5 +2176,5 @@
  * @returns Strict VBox status code.
  * @param   pDevIns     The device instance.
- * @param   off         Offset in bytes.
+ * @param   off         MMIO byte offset to the register.
  * @param   cb          The size of the write access.
  * @param   uValue      The value being written.
@@ -2135,25 +2189,24 @@
     Assert(pThis);
 
-    VBOXSTRICTRC rcStrict;
     switch (off)
     {
         case IOMMU_MMIO_OFF_DEV_TAB_BAR:        return iommuAmdDevTabBar_w(pDevIns, pThis, off, uValue);
         case IOMMU_MMIO_OFF_CMD_BUF_BAR:        return iommuAmdCmdBufBar_w(pDevIns, pThis, off, uValue);
-        case IOMMU_MMIO_OFF_EVT_LOG_BAR:        return iommuAmdEvtLogBar_w(pDevIns, pThis, off,  uValue);
+        case IOMMU_MMIO_OFF_EVT_LOG_BAR:        return iommuAmdEvtLogBar_w(pDevIns, pThis, off, uValue);
         case IOMMU_MMIO_OFF_CTRL:
-        case IOMMU_MMIO_OFF_EXCL_BAR:
-        case IOMMU_MMIO_OFF_EXCL_RANGE_LIMIT:
-        case IOMMU_MMIO_OFF_EXT_FEAT:
-
-        case IOMMU_MMIO_OFF_PPR_LOG_BAR:
-        case IOMMU_MMIO_OFF_HW_EVT_HI:
-        case IOMMU_MMIO_OFF_HW_EVT_LO:
+        case IOMMU_MMIO_OFF_EXCL_BAR:           return iommuAmdExclRangeBar_w(pDevIns, pThis, off, uValue);
+        case IOMMU_MMIO_OFF_EXCL_RANGE_LIMIT:   return iommuAmdExclRangeLimit_w(pDevIns, pThis, off, uValue);
+        case IOMMU_MMIO_OFF_EXT_FEAT:           return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
+
+        case IOMMU_MMIO_OFF_PPR_LOG_BAR:        return iommuAmdPprLogBar_w(pDevIns, pThis, off, uValue);
+        case IOMMU_MMIO_OFF_HW_EVT_HI:          return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
+        case IOMMU_MMIO_OFF_HW_EVT_LO:          return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
         case IOMMU_MMIO_OFF_HW_EVT_STATUS:
 
-        case IOMMU_MMIO_OFF_GALOG_BAR:
-        case IOMMU_MMIO_OFF_GALOG_TAIL_ADDR:
-
-        case IOMMU_MMIO_OFF_PPR_LOG_B_BAR:
-        case IOMMU_MMIO_OFF_PPR_EVT_B_BAR:
+        case IOMMU_MMIO_OFF_GALOG_BAR:          return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
+        case IOMMU_MMIO_OFF_GALOG_TAIL_ADDR:    return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
+
+        case IOMMU_MMIO_OFF_PPR_LOG_B_BAR:      return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
+        case IOMMU_MMIO_OFF_PPR_EVT_B_BAR:      return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
 
         case IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST:
@@ -2162,5 +2215,5 @@
             uint8_t const idxDevTabSeg = (off - IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST) >> 3;
             Assert(idxDevTabSeg < RT_ELEMENTS(pThis->DevTabSeg));
-            break;
+            return iommuAmdIgnore_w(pDevIns, pThis, off, uValue);
         }
 
@@ -2227,6 +2280,5 @@
             Log((IOMMU_LOG_PFX ": iommuAmdWriteRegister: Writing unsupported register: SMI filter %u -> Ignored\n",
                  (off - IOMMU_MMIO_OFF_SMI_FLT_FIRST) >> 3));
-            rcStrict = VINF_SUCCESS;
-            break;
+            return VINF_SUCCESS;
         }
 
@@ -2236,10 +2288,7 @@
             Log((IOMMU_LOG_PFX ": iommuAmdWriteRegister: Trying to write unknown register at %u (%#x) with %#RX64\n", off, off,
                  uValue));
-            rcStrict = VINF_SUCCESS;
-            break;
+            return VINF_SUCCESS;
         }
     }
-
-    return rcStrict;
 }
 
