Index: trunk/src/VBox/VMM/VMMAll/GICAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/GICAll.cpp	(revision 108472)
+++ trunk/src/VBox/VMM/VMMAll/GICAll.cpp	(revision 108473)
@@ -1421,5 +1421,5 @@
     else
     {
-        /* SGIs are always edge-triggered ignore writes, verify value on strict builds (arm64 Win11 guests writes this). */
+        /* SGIs are always edge-triggered ignore writes. Windows 11 (24H2) arm64 guests writes these. */
         Assert(uValue == 0xaaaaaaaa);
         Assert(pGicCpu->bmIntrConfig[0] == uValue);
@@ -2038,4 +2038,55 @@
             ASMBitSet(&pGicCpu->bmIntrActive[0], idxIntr);
 
+            /** @todo Duplicate block Id=E5ED12D2-088D-4525-9609-8325C02846C3 (start). */
+            /* Update the active priorities bitmap. */
+            AssertCompile(sizeof(pGicCpu->bmActivePriorityGroup0) * 8 >= 128);
+            AssertCompile(sizeof(pGicCpu->bmActivePriorityGroup1) * 8 >= 128);
+            uint8_t const idxPreemptionLevel = bIntrPriority >> 1;
+            if (fGroup0)
+                ASMBitSet(&pGicCpu->bmActivePriorityGroup0, idxPreemptionLevel);
+            if (fGroup1)
+                ASMBitSet(&pGicCpu->bmActivePriorityGroup1, idxPreemptionLevel);
+
+            /* Drop priority. */
+            if (RT_LIKELY(pGicCpu->idxRunningPriority < RT_ELEMENTS(pGicCpu->abRunningPriorities) - 1))
+            {
+                LogFlowFunc(("Dropping interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n",
+                             pGicCpu->abRunningPriorities[pGicCpu->idxRunningPriority],
+                             bIntrPriority,
+                             pGicCpu->idxRunningPriority, pGicCpu->idxRunningPriority + 1));
+                pGicCpu->abRunningPriorities[++pGicCpu->idxRunningPriority] = bIntrPriority;
+            }
+            else
+                AssertReleaseMsgFailed(("Index of running interrupt priority out-of-bounds %u\n", pGicCpu->idxRunningPriority));
+            /** @todo Duplicate block Id=E5ED12D2-088D-4525-9609-8325C02846C3 (end). */
+
+            /* If it is an edge-triggered interrupt, mark it as no longer pending. */
+            AssertRelease(2 * idxIntr + 1 < sizeof(pGicCpu->bmIntrConfig) * 8);
+            bool const fEdgeTriggered = ASMBitTest(&pGicCpu->bmIntrConfig[0], 2 * idxIntr + 1);
+            if (fEdgeTriggered)
+                ASMBitClear(&pGicCpu->bmIntrPending[0], idxIntr);
+
+            /* Update the redistributor IRQ state to reflect change to the active interrupt. */
+            gicReDistUpdateIrqState(pGicDev, pVCpu);
+        }
+        else
+        {
+            /* Sanity check if the interrupt ID belongs to the distributor. */
+            Assert(GIC_IS_INTR_SPI(uIntId) || GIC_IS_INTR_EXT_SPI(uIntId));
+
+            /* Mark the interrupt as active. */
+            Assert(idxIntr < sizeof(pGicDev->bmIntrActive) * 8);
+            ASMBitSet(&pGicDev->bmIntrActive[0], idxIntr);
+
+            /** @todo Duplicate block Id=E5ED12D2-088D-4525-9609-8325C02846C3 (start). */
+            /* Update the active priorities bitmap. */
+            AssertCompile(sizeof(pGicCpu->bmActivePriorityGroup0) * 8 >= 128);
+            AssertCompile(sizeof(pGicCpu->bmActivePriorityGroup1) * 8 >= 128);
+            uint8_t const idxPreemptionLevel = bIntrPriority >> 1;
+            if (fGroup0)
+                ASMBitSet(&pGicCpu->bmActivePriorityGroup0, idxPreemptionLevel);
+            if (fGroup1)
+                ASMBitSet(&pGicCpu->bmActivePriorityGroup1, idxPreemptionLevel);
+
             /* Drop priority. */
             Assert(pGicCpu->idxRunningPriority < RT_ELEMENTS(pGicCpu->abRunningPriorities) - 1);
@@ -2046,31 +2097,5 @@
                          pGicCpu->idxRunningPriority, pGicCpu->idxRunningPriority + 1));
             pGicCpu->abRunningPriorities[++pGicCpu->idxRunningPriority] = bIntrPriority;
-
-            /* If it is an edge-triggered interrupt, mark it as no longer pending. */
-            AssertRelease(2 * idxIntr + 1 < sizeof(pGicCpu->bmIntrConfig) * 8);
-            bool const fEdgeTriggered = ASMBitTest(&pGicCpu->bmIntrConfig[0], 2 * idxIntr + 1);
-            if (fEdgeTriggered)
-                ASMBitClear(&pGicCpu->bmIntrPending[0], idxIntr);
-
-            /* Update the redistributor IRQ state to reflect change to the active interrupt. */
-            gicReDistUpdateIrqState(pGicDev, pVCpu);
-        }
-        else
-        {
-            /* Sanity check if the interrupt ID belongs to the distirbutor. */
-            Assert(GIC_IS_INTR_SPI(uIntId) || GIC_IS_INTR_EXT_SPI(uIntId));
-
-            /* Mark the interrupt as active. */
-            Assert(idxIntr < sizeof(pGicDev->bmIntrActive) * 8);
-            ASMBitSet(&pGicDev->bmIntrActive[0], idxIntr);
-
-            /* Drop priority. */
-            Assert(pGicCpu->idxRunningPriority < RT_ELEMENTS(pGicCpu->abRunningPriorities) - 1);
-
-            LogFlowFunc(("Dropping interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n",
-                         pGicCpu->abRunningPriorities[pGicCpu->idxRunningPriority],
-                         bIntrPriority,
-                         pGicCpu->idxRunningPriority, pGicCpu->idxRunningPriority + 1));
-            pGicCpu->abRunningPriorities[++pGicCpu->idxRunningPriority] = bIntrPriority;
+            /** @todo Duplicate block Id=E5ED12D2-088D-4525-9609-8325C02846C3 (end). */
 
             /* If it is an edge-triggered interrupt, mark it as no longer pending. */
@@ -2717,6 +2742,12 @@
             break;
         default:
-            //AssertReleaseFailed();
-            break;
+        {
+            /* Windows 11 arm64 (24H2) writes zeroes into these reserved registers. We ignore them. */
+            if (offReg >= 0x7fe0 && offReg <= 0x7ffc)
+                LogFlowFunc(("Bad guest writing to reserved GIC distributor register space [0x7fe0..0x7ffc] -- ignoring!"));
+            else
+                AssertReleaseMsgFailed(("offReg=%#x uValue=%#RX32\n", offReg, uValue));
+            break;
+        }
     }
 
@@ -3600,5 +3631,5 @@
             break;
         case ARMV8_AARCH64_SYSREG_ICC_AP0R0_EL1:
-            /** @todo */
+            AssertReleaseFailed();
             break;
         case ARMV8_AARCH64_SYSREG_ICC_AP0R1_EL1:
@@ -3612,5 +3643,5 @@
             break;
         case ARMV8_AARCH64_SYSREG_ICC_AP1R0_EL1:
-            /** @todo */
+            AssertReleaseFailed();
             break;
         case ARMV8_AARCH64_SYSREG_ICC_AP1R1_EL1:
@@ -3763,8 +3794,8 @@
 
             /*
-             * Restore previous interrupt priority.
+             * Drop priority by restoring previous interrupt.
              */
             Assert(pGicCpu->idxRunningPriority > 0);
-            if (RT_LIKELY(pGicCpu->idxRunningPriority))
+            if (RT_LIKELY(pGicCpu->idxRunningPriority > 0))
             {
                 LogFlowFunc(("Restoring interrupt priority from %u -> %u (idxRunningPriority: %u -> %u)\n",
@@ -3772,4 +3803,11 @@
                              pGicCpu->abRunningPriorities[pGicCpu->idxRunningPriority - 1],
                              pGicCpu->idxRunningPriority, pGicCpu->idxRunningPriority - 1));
+
+                /* Update the active priorities bitmap. */
+                /** @todo Double check if this is doing the right thing :/ */
+                uint8_t const idxPreemptionLevel = pGicCpu->abRunningPriorities[pGicCpu->idxRunningPriority] >> 1;
+                AssertCompile(sizeof(pGicCpu->bmActivePriorityGroup1) * 8 >= 128);
+                ASMBitClear(&pGicCpu->bmActivePriorityGroup1, idxPreemptionLevel);
+
                 pGicCpu->idxRunningPriority--;
             }
