Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 102516)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 102517)
@@ -1176,4 +1176,5 @@
  	src-client/MouseImpl.cpp \
  	src-client/RemoteUSBDeviceImpl.cpp \
+ 	$(if $(VBOX_WITH_VIRT_ARMV8),src-client/ResourceAssignmentManager.cpp,) \
  	$(if $(VBOX_WITH_VIRT_ARMV8),src-client/ResourceStoreImpl.cpp,) \
  	src-client/SessionImpl.cpp \
Index: /trunk/src/VBox/Main/include/ResourceAssignmentManager.h
===================================================================
--- /trunk/src/VBox/Main/include/ResourceAssignmentManager.h	(revision 102517)
+++ /trunk/src/VBox/Main/include/ResourceAssignmentManager.h	(revision 102517)
@@ -0,0 +1,65 @@
+/* $Id$ */
+/** @file
+ * VirtualBox resource assignment (Address ranges, interrupts) manager.
+ */
+
+/*
+ * Copyright (C) 2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef MAIN_INCLUDED_ResourceAssignmentManager_h
+#define MAIN_INCLUDED_ResourceAssignmentManager_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBox/types.h"
+#include "VirtualBoxBase.h"
+#include <vector>
+
+class ResourceAssignmentManager
+{
+private:
+    struct State;
+    State *pState;
+
+    ResourceAssignmentManager();
+
+public:
+    static ResourceAssignmentManager *createInstance(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
+                                                     RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
+                                                     RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32,
+                                                     uint32_t cInterrupts);
+
+    ~ResourceAssignmentManager();
+
+    HRESULT assignMmioRegion(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion);
+    HRESULT assignMmio32Region(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion);
+    HRESULT assignMmioRegionAligned(const char *pszName, RTGCPHYS cbRegion, RTGCPHYS cbAlignment, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion);
+    HRESULT assignFixedAddress(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion);
+    HRESULT assignRamRegion(const char *pszName, RTGCPHYS cbRam, PRTGCPHYS pGCPhysStart);
+    HRESULT assignInterrupts(const char *pszName, uint32_t cInterrupts, uint32_t *piInterruptFirst);
+    HRESULT assignSingleInterrupt(const char *pszName, uint32_t *piInterrupt);
+    HRESULT queryMmioRegion(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio);
+    HRESULT queryMmio32Region(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio);
+};
+
+#endif /* !MAIN_INCLUDED_ResourceAssignmentManager_h */
Index: /trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp	(revision 102516)
+++ /trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp	(revision 102517)
@@ -67,4 +67,5 @@
 
 #include "BusAssignmentManager.h"
+#include "ResourceAssignmentManager.h"
 #ifdef VBOX_WITH_EXTPACK
 # include "ExtPackManagerImpl.h"
@@ -90,7 +91,4 @@
  *                      to leave it in order to avoid deadlocks (ext packs and
  *                      more).
- *
- * @todo This is a big hack at the moment and provides a static VM config to work with, will be adjusted later
- *       on to adhere to the VM config when sorting out the API bits.
  */
 int Console::i_configConstructorArmV8(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
@@ -178,4 +176,10 @@
 
     BusAssignmentManager *pBusMgr = mBusMgr = BusAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None);
+    ResourceAssignmentManager *pResMgr = ResourceAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None,
+                                                                                   GCPhysTopOfAddrSpace - sizeof(VBOXPLATFORMARMV8),
+                                                                                   _1G,             /*GCPhysRam*/
+                                                                                   128 * _1M,       /*GCPhysMmio32Start*/
+                                                                                   _1G - 128 * _1M, /*cbMmio32*/
+                                                                                   32               /*cInterrupts*/);
 
     /*
@@ -185,4 +189,6 @@
     PCFGMNODE pRoot = pVMM->pfnCFGMR3GetRootU(pUVM);
     Assert(pRoot);
+
+    RTGCPHYS GCPhysRam = NIL_RTGCPHYS;
 
     // catching throws from InsertConfigString and friends.
@@ -271,11 +277,13 @@
         InsertConfigNode(pMM, "MemRegions", &pMem);
 
+        hrc = pResMgr->assignRamRegion("Conventional", cbRam, &GCPhysRam);                  H();
+
         PCFGMNODE pMemRegion = NULL;
         InsertConfigNode(pMem, "Conventional", &pMemRegion);
-        InsertConfigInteger(pMemRegion, "GCPhysStart", 0x40000000);
+        InsertConfigInteger(pMemRegion, "GCPhysStart", GCPhysRam);
         InsertConfigInteger(pMemRegion, "Size", cbRam);
 
-        vrc = RTFdtNodeAddF(hFdt, "memory@%RX32", 0x40000000);                              VRC();
-        vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, 0x40000000, cbRam);              VRC();
+        vrc = RTFdtNodeAddF(hFdt, "memory@%RGp", GCPhysRam);                                VRC();
+        vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysRam, cbRam);               VRC();
         vrc = RTFdtNodePropertyAddString(  hFdt, "device_type",      "memory");             VRC();
         vrc = RTFdtNodeFinalize(hFdt);                                                      VRC();
@@ -386,23 +394,32 @@
          * Configure the interrupt controller.
          */
+        RTGCPHYS GCPhysIntcDist;
+        RTGCPHYS GCPhysIntcReDist;
+        RTGCPHYS cbMmioIntcDist;
+        RTGCPHYS cbMmioIntcReDist;
+
+        /* Each vCPU needs on re-distributor, this would allow for up to 256 vCPUs in the future. */
+        hrc = pResMgr->assignMmioRegion("gic", 256 * _64K, &GCPhysIntcReDist, &cbMmioIntcReDist);       H();
+        hrc = pResMgr->assignMmioRegion("gic", _64K, &GCPhysIntcDist, &cbMmioIntcDist);                 H();
+
         InsertConfigNode(pDevices, "gic",                   &pDev);
         InsertConfigNode(pDev,     "0",                     &pInst);
         InsertConfigInteger(pInst, "Trusted",               1);
         InsertConfigNode(pInst,    "Config",                &pCfg);
-        InsertConfigInteger(pCfg,  "DistributorMmioBase",   0x08000000);
-        InsertConfigInteger(pCfg,  "RedistributorMmioBase", 0x080a0000);
-
-        vrc = RTFdtNodeAddF(hFdt, "intc@%RX32", 0x08000000);                                VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "phandle",          idPHandleIntCtrl);     VRC();
+        InsertConfigInteger(pCfg,  "DistributorMmioBase",   GCPhysIntcDist);
+        InsertConfigInteger(pCfg,  "RedistributorMmioBase", GCPhysIntcReDist);
+
+        vrc = RTFdtNodeAddF(hFdt, "intc@%RGp", GCPhysIntcDist);                                         VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "phandle",          idPHandleIntCtrl);                 VRC();
         vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 4,
-                                           0x08000000, 0x10000,   /* Distributor */
-                                           0x080a0000, 0xf60000); /* Re-Distributor */      VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "#redistributor-regions", 1);              VRC();
-        vrc = RTFdtNodePropertyAddString(  hFdt, "compatible",       "arm,gic-v3");         VRC();
-        vrc = RTFdtNodePropertyAddEmpty(   hFdt, "ranges");                                 VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "#size-cells",      2);                    VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "#address-cells",   2);                    VRC();
-        vrc = RTFdtNodePropertyAddEmpty(   hFdt, "interrupt-controller");                   VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "#interrupt-cells", 3);                    VRC();
+                                           GCPhysIntcDist, cbMmioIntcDist,      /* Distributor */
+                                           GCPhysIntcReDist, cbMmioIntcReDist); /* Re-Distributor */    VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "#redistributor-regions", 1);                          VRC();
+        vrc = RTFdtNodePropertyAddString(  hFdt, "compatible",       "arm,gic-v3");                     VRC();
+        vrc = RTFdtNodePropertyAddEmpty(   hFdt, "ranges");                                             VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "#size-cells",      2);                                VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "#address-cells",   2);                                VRC();
+        vrc = RTFdtNodePropertyAddEmpty(   hFdt, "interrupt-controller");                               VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "#interrupt-cells", 3);                                VRC();
 
 #if 0
@@ -418,11 +435,15 @@
         vrc = RTFdtNodeFinalize(hFdt);                                                      VRC();
 
+        RTGCPHYS GCPhysMmioStart;
+        RTGCPHYS cbMmio;
         if (enmGraphicsController == GraphicsControllerType_QemuRamFB)
         {
+            hrc = pResMgr->assignMmioRegion("qemu-fw-cfg", _4K, &GCPhysMmioStart, &cbMmio); H();
+
             InsertConfigNode(pDevices, "qemu-fw-cfg",   &pDev);
             InsertConfigNode(pDev,     "0",            &pInst);
             InsertConfigNode(pInst,    "Config",        &pCfg);
-            InsertConfigInteger(pCfg,  "MmioSize",       4096);
-            InsertConfigInteger(pCfg,  "MmioBase", 0x09020000);
+            InsertConfigInteger(pCfg,  "MmioSize",       cbMmio);
+            InsertConfigInteger(pCfg,  "MmioBase", GCPhysMmioStart);
             InsertConfigInteger(pCfg,  "DmaEnabled",        1);
             InsertConfigInteger(pCfg,  "QemuRamfbSupport",  1);
@@ -430,7 +451,7 @@
             InsertConfigString(pLunL0, "Driver",          "MainDisplay");
 
-            vrc = RTFdtNodeAddF(hFdt, "fw-cfg@%RX32", 0x09020000);                          VRC();
+            vrc = RTFdtNodeAddF(hFdt, "fw-cfg@%RGp", GCPhysMmioStart);                      VRC();
             vrc = RTFdtNodePropertyAddEmpty(   hFdt, "dma-coherent");                       VRC();
-            vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, 0x09020000, 0x18);           VRC();
+            vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio);    VRC();
             vrc = RTFdtNodePropertyAddString(  hFdt, "compatible", "qemu,fw-cfg-mmio");     VRC();
             vrc = RTFdtNodeFinalize(hFdt);                                                  VRC();
@@ -475,16 +496,20 @@
             InsertConfigNode(pInst, "Config", &pCfg);
 
-            InsertConfigInteger(pCfg,  "Irq",               1);
-            InsertConfigInteger(pCfg,  "MmioBase", 0x09000000);
-
-            vrc = RTFdtNodeAddF(hFdt, "pl011@%RX32", 0x09000000);                               VRC();
-            vrc = RTFdtNodePropertyAddStringList(hFdt, "clock-names", 2, "uartclk", "apb_pclk"); VRC();
+            uint32_t iIrq = 0;
+            hrc = pResMgr->assignSingleInterrupt("arm-pl011", &iIrq);                               H();
+            hrc = pResMgr->assignMmioRegion("arm-pl011", _4K, &GCPhysMmioStart, &cbMmio);           H();
+
+            InsertConfigInteger(pCfg,  "Irq",      iIrq);
+            InsertConfigInteger(pCfg,  "MmioBase", GCPhysMmioStart);
+
+            vrc = RTFdtNodeAddF(hFdt, "pl011@%RGp", GCPhysMmioStart);                               VRC();
+            vrc = RTFdtNodePropertyAddStringList(hFdt, "clock-names", 2, "uartclk", "apb_pclk");    VRC();
             vrc = RTFdtNodePropertyAddCellsU32(hFdt, "clocks", 2,
-                                               idPHandleAbpPClk, idPHandleAbpPClk);             VRC();
-            vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x01, 0x04);        VRC();
-            vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, 0x09000000, _4K);                VRC();
+                                               idPHandleAbpPClk, idPHandleAbpPClk);                 VRC();
+            vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, iIrq, 0x04);            VRC();
+            vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio);            VRC();
             vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
-                                                 "arm,pl011", "arm,primecell");                 VRC();
-            vrc = RTFdtNodeFinalize(hFdt);                                                      VRC();
+                                                 "arm,pl011", "arm,primecell");                     VRC();
+            vrc = RTFdtNodeFinalize(hFdt);                                                          VRC();
 
             BOOL  fServer;
@@ -507,16 +532,19 @@
         hrc = platform->COMGETTER(RTCUseUTC)(&fRTCUseUTC);                                  H();
 
+        uint32_t iIrq = 0;
+        hrc = pResMgr->assignSingleInterrupt("arm-pl031-rtc", &iIrq);                       H();
+        hrc = pResMgr->assignMmioRegion("arm-pl031-rtc", _4K, &GCPhysMmioStart, &cbMmio);   H();
         InsertConfigNode(pDevices, "arm-pl031-rtc", &pDev);
         InsertConfigNode(pDev,     "0",            &pInst);
         InsertConfigNode(pInst,    "Config",        &pCfg);
-        InsertConfigInteger(pCfg,  "Irq",               2);
-        InsertConfigInteger(pCfg,  "MmioBase", 0x09010000);
+        InsertConfigInteger(pCfg,  "Irq",            iIrq);
+        InsertConfigInteger(pCfg,  "MmioBase", GCPhysMmioStart);
         InsertConfigInteger(pCfg,  "UtcOffset", fRTCUseUTC ? 1 : 0);
 
-        vrc = RTFdtNodeAddF(hFdt, "pl032@%RX32", 0x09010000);                               VRC();
+        vrc = RTFdtNodeAddF(hFdt, "pl032@%RGp", GCPhysMmioStart);                           VRC();
         vrc = RTFdtNodePropertyAddString(  hFdt, "clock-names", "apb_pclk");                VRC();
         vrc = RTFdtNodePropertyAddU32(     hFdt, "clocks", idPHandleAbpPClk);               VRC();
-        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x02, 0x04);        VRC();
-        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09010000, 0, 0x1000);       VRC();
+        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, iIrq, 0x04);        VRC();
+        vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio);        VRC();
         vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
                                              "arm,pl031", "arm,primecell");                 VRC();
@@ -524,19 +552,21 @@
 
         /* Configure gpio keys. */
+        hrc = pResMgr->assignSingleInterrupt("arm-pl061-gpio", &iIrq);                      H();
+        hrc = pResMgr->assignMmioRegion("arm-pl061-gpio", _4K, &GCPhysMmioStart, &cbMmio);  H();
         InsertConfigNode(pDevices, "arm-pl061-gpio",&pDev);
         InsertConfigNode(pDev,     "0",            &pInst);
         InsertConfigNode(pInst,    "Config",        &pCfg);
-        InsertConfigInteger(pCfg,  "Irq",               7);
-        InsertConfigInteger(pCfg,  "MmioBase", 0x09030000);
-        vrc = RTFdtNodeAddF(hFdt, "pl061@%RX32", 0x09030000);                               VRC();
+        InsertConfigInteger(pCfg,  "Irq",            iIrq);
+        InsertConfigInteger(pCfg,  "MmioBase", GCPhysMmioStart);
+        vrc = RTFdtNodeAddF(hFdt, "pl061@%RGp", GCPhysMmioStart);                           VRC();
         vrc = RTFdtNodePropertyAddU32(     hFdt, "phandle", idPHandleGpio);                 VRC();
         vrc = RTFdtNodePropertyAddString(  hFdt, "clock-names", "apb_pclk");                VRC();
         vrc = RTFdtNodePropertyAddU32(     hFdt, "clocks", idPHandleAbpPClk);               VRC();
-        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x07, 0x04);        VRC();
+        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, iIrq, 0x04);        VRC();
         vrc = RTFdtNodePropertyAddEmpty(   hFdt, "gpio-controller");                        VRC();
         vrc = RTFdtNodePropertyAddU32(     hFdt, "#gpio-cells", 2);                         VRC();
         vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
                                              "arm,pl061", "arm,primecell");                 VRC();
-        vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, 0x09030000, _4K);                VRC();
+        vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio);        VRC();
         vrc = RTFdtNodeFinalize(hFdt);                                                      VRC();
 
@@ -564,17 +594,25 @@
         vrc = RTFdtNodeFinalize(hFdt);                                                      VRC();
 
-        uint32_t aPinIrqs[] = { 3, 4, 5, 6 };
+        hrc = pResMgr->assignInterrupts("pci-generic-ecam", 4 /*cInterrupts*/, &iIrq);      H();
+        uint32_t aPinIrqs[] = { iIrq, iIrq + 1, iIrq + 2, iIrq + 3 };
+        RTGCPHYS GCPhysPciMmioEcam, GCPhysPciMmio, GCPhysPciMmio32;
+        RTGCPHYS cbPciMmioEcam, cbPciMmio, cbPciMmio32;
+        hrc = pResMgr->assignMmioRegionAligned("pci-pio",    _64K, _64K,         &GCPhysMmioStart,   &cbMmio);         H();
+        hrc = pResMgr->assignMmioRegion(       "pci-ecam",   16 * _1M,           &GCPhysPciMmioEcam, &cbPciMmioEcam);  H();
+        hrc = pResMgr->assignMmioRegion(       "pci-mmio",   _2G,                &GCPhysPciMmio,     &cbPciMmio);      H();
+        hrc = pResMgr->assignMmio32Region(     "pci-mmio32", (1024 - 128) * _1M, &GCPhysPciMmio32,   &cbPciMmio32);    H();
+
         InsertConfigNode(pDevices, "pci-generic-ecam",  &pDev);
         InsertConfigNode(pDev,     "0",            &pInst);
         InsertConfigNode(pInst,    "Config",        &pCfg);
-        InsertConfigInteger(pCfg,  "MmioEcamBase",   0x3f000000);
-        InsertConfigInteger(pCfg,  "MmioEcamLength", 0x01000000);
-        InsertConfigInteger(pCfg,  "MmioPioBase",    0x3eff0000);
-        InsertConfigInteger(pCfg,  "MmioPioSize",    0x0000ffff);
+        InsertConfigInteger(pCfg,  "MmioEcamBase",   GCPhysPciMmioEcam);
+        InsertConfigInteger(pCfg,  "MmioEcamLength", cbPciMmioEcam);
+        InsertConfigInteger(pCfg,  "MmioPioBase",    GCPhysMmioStart);
+        InsertConfigInteger(pCfg,  "MmioPioSize",    cbMmio);
         InsertConfigInteger(pCfg,  "IntPinA",        aPinIrqs[0]);
         InsertConfigInteger(pCfg,  "IntPinB",        aPinIrqs[1]);
         InsertConfigInteger(pCfg,  "IntPinC",        aPinIrqs[2]);
         InsertConfigInteger(pCfg,  "IntPinD",        aPinIrqs[3]);
-        vrc = RTFdtNodeAddF(hFdt, "pcie@%RX32", 0x10000000);                                VRC();
+        vrc = RTFdtNodeAddF(hFdt, "pcie@%RGp", GCPhysPciMmio);                              VRC();
         vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map-mask", 4, 0xf800, 0, 0, 7); VRC();
 
@@ -604,19 +642,22 @@
 
         vrc = RTFdtNodePropertyAddCellsU32AsArray(hFdt, "interrupt-map", RT_ELEMENTS(aIrqCells), &aIrqCells[0]);
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "#interrupt-cells", 1);                    VRC();
-        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 14,
-                                           0x1000000, 0, 0, 0, 0x3eff0000, 0, 0x10000,
-                                           0x2000000, 0, 0x10000000, 0, 0x10000000, 0,
-                                           0x2eff0000);                                     VRC();
-        vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, 0x3f000000, 0x1000000);          VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "#interrupt-cells", 1);                        VRC();
+        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 21,
+                                           0x1000000, 0, 0,
+                                           GCPhysMmioStart >> 32, GCPhysMmioStart, cbMmio >> 32, cbMmio,
+                                           0x2000000, GCPhysPciMmio32 >> 32, GCPhysPciMmio32, GCPhysPciMmio32 >> 32, GCPhysPciMmio32,
+                                           cbPciMmio32 >> 32, cbPciMmio32,
+                                           0x3000000, GCPhysPciMmio >> 32, GCPhysPciMmio, GCPhysPciMmio >> 32, GCPhysPciMmio,
+                                           cbPciMmio >> 32, cbPciMmio);                         VRC();
+        vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysPciMmioEcam, cbPciMmioEcam);   VRC();
         /** @todo msi-map */
-        vrc = RTFdtNodePropertyAddEmpty(   hFdt, "dma-coherent");                           VRC();
-        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf);                   VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "linux,pci-domain", 0);                    VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "#size-cells", 2);                         VRC();
-        vrc = RTFdtNodePropertyAddU32(     hFdt, "#address-cells", 3);                      VRC();
-        vrc = RTFdtNodePropertyAddString(  hFdt, "device_type", "pci");                     VRC();
-        vrc = RTFdtNodePropertyAddString(  hFdt, "compatible", "pci-host-ecam-generic");    VRC();
-        vrc = RTFdtNodeFinalize(hFdt);                                                      VRC();
+        vrc = RTFdtNodePropertyAddEmpty(   hFdt, "dma-coherent");                               VRC();
+        vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf);                       VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "linux,pci-domain", 0);                        VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "#size-cells", 2);                             VRC();
+        vrc = RTFdtNodePropertyAddU32(     hFdt, "#address-cells", 3);                          VRC();
+        vrc = RTFdtNodePropertyAddString(  hFdt, "device_type", "pci");                         VRC();
+        vrc = RTFdtNodePropertyAddString(  hFdt, "compatible", "pci-host-ecam-generic");        VRC();
+        vrc = RTFdtNodeFinalize(hFdt);                                                          VRC();
 
         /*
@@ -725,9 +766,19 @@
     AssertRCReturn(vrc, vrc);
 
+    RTGCPHYS GCPhysMmioStart;
+    RTGCPHYS cbMmio;
+    hrc = pResMgr->queryMmioRegion(&GCPhysMmioStart, &cbMmio);
+    Assert(SUCCEEDED(hrc));
+
+    RTGCPHYS GCPhysMmio32Start;
+    RTGCPHYS cbMmio32;
+    hrc = pResMgr->queryMmio32Region(&GCPhysMmio32Start, &cbMmio32);
+    Assert(SUCCEEDED(hrc));
+
     ArmV8Platform.u32Magic            = VBOXPLATFORMARMV8_MAGIC;
     ArmV8Platform.u32Version          = VBOXPLATFORMARMV8_VERSION;
     ArmV8Platform.cbDesc              = sizeof(ArmV8Platform);
     ArmV8Platform.fFlags              = 0;
-    ArmV8Platform.u64PhysAddrRamBase  = UINT64_C(0x40000000);
+    ArmV8Platform.u64PhysAddrRamBase  = GCPhysRam;
     ArmV8Platform.cbRamBase           = cbRam;
     ArmV8Platform.u64OffBackFdt       = RT_ALIGN_64(ArmV8Platform.cbFdt, _64K);
@@ -737,6 +788,8 @@
     ArmV8Platform.u64OffBackUefiRom   = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform);
     ArmV8Platform.cbUefiRom           = _64M; /** @todo Fixed reservation but the ROM region is usually much smaller. */
-    ArmV8Platform.u64OffBackMmio      = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform) - 0x08000000; /** @todo Start of generic MMIO area containing the GIC,UART,RTC, etc. Will be changed soon */
-    ArmV8Platform.cbMmio              = _128M;
+    ArmV8Platform.u64OffBackMmio      = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform) - GCPhysMmioStart;
+    ArmV8Platform.cbMmio              = cbMmio;
+    ArmV8Platform.u64OffBackMmio32    = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform) - GCPhysMmio32Start;
+    ArmV8Platform.cbMmio32            = cbMmio32;
 
     /* Add the VBox platform descriptor to the resource store. */
@@ -758,4 +811,5 @@
     }
 
+    delete pResMgr; /* Delete the address/interrupt assignment manager. */
 
     /*
Index: /trunk/src/VBox/Main/src-client/ResourceAssignmentManager.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ResourceAssignmentManager.cpp	(revision 102517)
+++ /trunk/src/VBox/Main/src-client/ResourceAssignmentManager.cpp	(revision 102517)
@@ -0,0 +1,276 @@
+/* $Id$ */
+/** @file
+ * VirtualBox bus slots assignment manager
+ */
+
+/*
+ * Copyright (C) 2010-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_MAIN
+#include "LoggingNew.h"
+
+#include "ResourceAssignmentManager.h"
+
+#include <iprt/asm.h>
+#include <iprt/string.h>
+
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/vmmr3vtable.h>
+#include <VBox/com/array.h>
+
+#include <map>
+#include <vector>
+#include <algorithm>
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+
+
+/**
+ * Resource assignment manage state data.
+ * @internal
+ */
+struct ResourceAssignmentManager::State
+{
+    struct MemoryRange
+    {
+        char          szDevName[32];
+        RTGCPHYS      GCPhysStart;
+        RTGCPHYS      GCPhysEnd;
+
+        MemoryRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd)
+        {
+            RTStrCopy(this->szDevName, sizeof(szDevName), pszName);
+            this->GCPhysStart = GCPhysStart;
+            this->GCPhysEnd   = GCPhysEnd;
+        }
+
+        bool operator==(const MemoryRange &a) const
+        {
+            return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) == 0;
+        }
+    };
+
+    typedef std::vector<MemoryRange> AddrRangeList;
+
+    ChipsetType_T    mChipsetType;
+    IommuType_T      mIommuType;
+    PCVMMR3VTABLE    mpVMM;
+    AddrRangeList    mAddrRanges;
+
+    RTGCPHYS         mGCPhysMmioStartOrig;
+    RTGCPHYS         mGCPhysMmioStart;
+    RTGCPHYS         mGCPhysMmio32StartOrig;
+    RTGCPHYS         mGCPhysMmio32Start;
+    RTGCPHYS         mcbMmio32;
+    RTGCPHYS         mGCPhysRamStart;
+    uint32_t         mcInterrupts;
+    uint32_t         miInterrupt;
+
+    State()
+        : mChipsetType(ChipsetType_Null), mpVMM(NULL)
+    {}
+    ~State()
+    {}
+
+    HRESULT init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
+                 RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
+                 RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts);
+
+    HRESULT addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd);
+};
+
+
+HRESULT ResourceAssignmentManager::State::init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
+                                               RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
+                                               RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts)
+{
+    mpVMM = pVMM;
+
+    Assert(chipsetType == ChipsetType_ARMv8Virtual);
+    Assert(iommuType == IommuType_None); /* For now no IOMMU support on ARMv8. */
+
+    mChipsetType           = chipsetType;
+    mIommuType             = iommuType;
+    mGCPhysMmioStart       = GCPhysMmioTop;
+    mGCPhysMmioStartOrig   = GCPhysMmioTop;
+    mGCPhysRamStart        = GCPhysRamStart;
+    mGCPhysMmio32Start     = GCPhysMmio32Start;
+    mGCPhysMmio32StartOrig = GCPhysMmio32Start;
+    mcbMmio32              = cbMmio32;
+    mcInterrupts           = cInterrupts;
+    miInterrupt            = 0;
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::State::addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
+{
+    MemoryRange memRange(pszName, GCPhysStart, GCPhysStart + cbRegion - 1);
+    mAddrRanges.push_back(memRange);
+    return S_OK;
+}
+
+ResourceAssignmentManager::ResourceAssignmentManager()
+    : pState(NULL)
+{
+    pState = new State();
+    Assert(pState);
+}
+
+ResourceAssignmentManager::~ResourceAssignmentManager()
+{
+    if (pState)
+    {
+        delete pState;
+        pState = NULL;
+    }
+}
+
+ResourceAssignmentManager *ResourceAssignmentManager::createInstance(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType,
+                                                                     RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,
+                                                                     RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32,
+                                                                     uint32_t cInterrupts)
+{
+    ResourceAssignmentManager *pInstance = new ResourceAssignmentManager();
+    pInstance->pState->init(pVMM, chipsetType, iommuType, GCPhysMmioTop, GCPhysRamStart, GCPhysMmio32Start, cbMmio32, cInterrupts);
+    Assert(pInstance);
+    return pInstance;
+}
+
+HRESULT ResourceAssignmentManager::assignMmioRegion(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
+{
+    RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS);
+    RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart - cbRegionAligned;
+
+    if (GCPhysMmioStart < pState->mGCPhysRamStart)
+    {
+        AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO range for %s would overlap RAM region\n", pszName));
+        return E_INVALIDARG;
+    }
+
+    *pGCPhysStart = GCPhysMmioStart;
+    *pcbRegion    = cbRegionAligned;
+    pState->mGCPhysMmioStart -= cbRegionAligned;
+    pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::assignMmio32Region(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
+{
+    RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS);
+    RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmio32Start;
+
+    if (GCPhysMmioStart > pState->mGCPhysRamStart)
+    {
+        AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO32 range for %s would overlap RAM region\n", pszName));
+        return E_INVALIDARG;
+    }
+
+    *pGCPhysStart = GCPhysMmioStart;
+    *pcbRegion    = cbRegionAligned;
+    pState->mGCPhysMmio32Start += cbRegionAligned;
+    pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::assignMmioRegionAligned(const char *pszName, RTGCPHYS cbRegion, RTGCPHYS cbAlignment, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion)
+{
+    RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, cbAlignment, RTGCPHYS);
+    RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart - cbRegionAligned;
+
+    GCPhysMmioStart = GCPhysMmioStart & ~(cbAlignment - 1);
+    if (GCPhysMmioStart < pState->mGCPhysRamStart)
+    {
+        AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO range for %s would overlap RAM region\n", pszName));
+        return E_INVALIDARG;
+    }
+
+    *pGCPhysStart = GCPhysMmioStart;
+    *pcbRegion    = cbRegionAligned;
+    pState->mGCPhysMmioStart = GCPhysMmioStart;
+    pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned);
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::assignFixedAddress(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion)
+{
+    RT_NOREF(pszName, GCPhysStart, cbRegion);
+    AssertReleaseFailed();
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::assignRamRegion(const char *pszName, RTGCPHYS cbRam, PRTGCPHYS pGCPhysStart)
+{
+    if (pState->mGCPhysRamStart + cbRam > pState->mGCPhysMmioStart)
+    {
+        AssertLogRelMsgFailed(("ResourceAssignmentManager: RAM range for %s would overlap MMIO range\n", pszName));
+        return E_INVALIDARG;
+    }
+
+    *pGCPhysStart = pState->mGCPhysRamStart;
+    pState->mGCPhysRamStart += cbRam;
+    pState->addAddrRange(pszName, *pGCPhysStart, cbRam);
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::assignInterrupts(const char *pszName, uint32_t cInterrupts, uint32_t *piInterruptFirst)
+{
+    if (pState->miInterrupt + cInterrupts > pState->mcInterrupts)
+    {
+        AssertLogRelMsgFailed(("ResourceAssignmentManager: Interrupt count for %s exceeds number of available interrupts\n", pszName));
+        return E_INVALIDARG;
+    }
+
+    *piInterruptFirst = pState->miInterrupt;
+    pState->miInterrupt += cInterrupts;
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::assignSingleInterrupt(const char *pszName, uint32_t *piInterrupt)
+{
+    return assignInterrupts(pszName, 1, piInterrupt);
+}
+
+HRESULT ResourceAssignmentManager::queryMmioRegion(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
+{
+    *pGCPhysMmioStart = pState->mGCPhysMmioStart;
+    *pcbMmio          = pState->mGCPhysMmioStartOrig - pState->mGCPhysMmioStart;
+    return S_OK;
+}
+
+HRESULT ResourceAssignmentManager::queryMmio32Region(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio)
+{
+    *pGCPhysMmioStart = pState->mGCPhysMmio32StartOrig;
+    *pcbMmio          = pState->mcbMmio32;
+    return S_OK;
+}
