Changeset 106957 in vbox for trunk/src/VBox/Main/src-client
- Timestamp:
- Nov 12, 2024 12:09:04 PM (2 months ago)
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp
r106476 r106957 187 187 188 188 BusAssignmentManager *pBusMgr = mBusMgr = BusAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None); 189 ResourceAssignmentManager *pResMgr = ResourceAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None, 190 RT_MAX(_1G + cbRam, _4G), /*GCPhysMmio*/ 191 _1G, /*GCPhysRam*/ 192 VBOXPLATFORMARMV8_PHYS_ADDR + _1M, /*GCPhysMmio32Start*/ 193 _1G - (VBOXPLATFORMARMV8_PHYS_ADDR + _1M), /*cbMmio32*/ 194 32 /*cInterrupts*/); 189 ResourceAssignmentManager *pResMgr = ResourceAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None, 32 /*cInterrupts*/, 190 _4G); /* Start looking for free MMIO regions at 4GiB downwards. */ 195 191 SystemTableBuilder *pSysTblsBldAcpi = NULL; 196 192 … … 211 207 Assert(pRoot); 212 208 213 RTGCPHYS GCPhysRam = NIL_RTGCPHYS; 209 /* 210 * The VBox platform descriptor, FDT and ACPI tables will reside at the end of the 4GiB 211 * address space and we reserve 2MiB for those. 212 */ 213 RTGCPHYS cbPlatformDesc = _2M; 214 RTGCPHYS GCPhysPlatformDesc = VBOXPLATFORMARMV8_PHYS_ADDR - (cbPlatformDesc - _64K); 215 216 RTGCPHYS GCPhysRamBase = 128 * _1M; 217 RTGCPHYS cbRamBase = RT_MIN(cbRam, _4G - _512M - 128 * _1M); 218 219 RTGCPHYS GCPhysFw = 0; 220 RTGCPHYS cbFw = _64M; 214 221 215 222 // catching throws from InsertConfigString and friends. … … 281 288 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleAbpPClk); VRC(); 282 289 vrc = RTFdtNodePropertyAddString( hFdt, "clock-output-names", "clk24mhz"); VRC(); 283 vrc = RTFdtNodePropertyAddU32( hFdt, "clock-frequency", 24 * 1000 * 1000);VRC();290 vrc = RTFdtNodePropertyAddU32( hFdt, "clock-frequency", ASMReadCntFrqEl0()); VRC(); 284 291 vrc = RTFdtNodePropertyAddU32( hFdt, "#clock-cells", 0); VRC(); 285 292 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "fixed-clock"); VRC(); … … 304 311 InsertConfigNode(pMM, "MemRegions", &pMem); 305 312 306 hrc = pResMgr->assignRamRegion("Conventional", cbRam, &GCPhysRam); H(); 313 /* 314 * Windows requires the TPM to be available at 0xfed40000 so reserve this region first, even 315 * if no TPM is configured. 316 */ 317 RTGCPHYS GCPhysTpm = 0xfed40000; 318 RTGCPHYS cbTpm = 0x5000 + 0x1000; /* TPM + PPI region. */ 319 hrc = pResMgr->assignFixedMmioRegion("tpm", GCPhysTpm, cbTpm); H(); 320 321 /* 322 * The firmware ROM will start at the beginning of the address space and span 64MiB 323 * After that comes the flash and spans another 64MiB (even if the real size is smaller). 324 */ 325 hrc = pResMgr->assignFixedRomRegion("firmware", GCPhysFw, cbFw); H(); 326 327 RTGCPHYS GCPhysFlash = _64M; 328 RTGCPHYS cbFlash = _64M; 329 hrc = pResMgr->assignFixedMmioRegion("flash", GCPhysFlash, cbFlash); H(); 330 331 hrc = pResMgr->assignFixedRomRegion("platform-tables", GCPhysPlatformDesc, cbPlatformDesc); H(); 332 333 /* 334 * The base RAM will start at 128MiB (end of flash region) and goes up to 4GiB - 512MiB 335 * (for the MMIO hole). 336 * If more RAM is configured the high region will start at 4GiB. 337 */ 338 hrc = pResMgr->assignFixedRamRegion("RAM Base", GCPhysRamBase, cbRamBase); H(); 307 339 308 340 PCFGMNODE pMemRegion = NULL; 309 InsertConfigNode(pMem, " Conventional", &pMemRegion);310 InsertConfigInteger(pMemRegion, "GCPhysStart", GCPhysRam );311 InsertConfigInteger(pMemRegion, "Size", cbRam );312 313 vrc = RTFdtNodeAddF(hFdt, "memory@%RGp", GCPhysRam );VRC();314 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysRam , cbRam);VRC();341 InsertConfigNode(pMem, "Base", &pMemRegion); 342 InsertConfigInteger(pMemRegion, "GCPhysStart", GCPhysRamBase); 343 InsertConfigInteger(pMemRegion, "Size", cbRamBase); 344 345 vrc = RTFdtNodeAddF(hFdt, "memory@%RGp", GCPhysRamBase); VRC(); 346 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysRamBase, cbRamBase); VRC(); 315 347 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "memory"); VRC(); 316 348 vrc = RTFdtNodeFinalize(hFdt); VRC(); … … 318 350 if (pSysTblsBldAcpi) 319 351 { 320 vrc = pSysTblsBldAcpi->addMemory(GCPhysRam , cbRam);352 vrc = pSysTblsBldAcpi->addMemory(GCPhysRamBase, cbRamBase); 321 353 VRC(); 354 } 355 356 if (cbRamBase < cbRam) 357 { 358 RTGCPHYS GCPhysRamHigh = _4G; 359 RTGCPHYS cbRamHigh = cbRam - cbRamBase; 360 361 hrc = pResMgr->assignFixedRamRegion("RAM High", GCPhysRamHigh, cbRamHigh); H(); 362 363 InsertConfigNode(pMem, "High", &pMemRegion); 364 InsertConfigInteger(pMemRegion, "GCPhysStart", GCPhysRamHigh); 365 InsertConfigInteger(pMemRegion, "Size", cbRamHigh); 366 367 vrc = RTFdtNodeAddF(hFdt, "memory@%RGp", GCPhysRamHigh); VRC(); 368 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysRamHigh, cbRamHigh); VRC(); 369 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "memory"); VRC(); 370 vrc = RTFdtNodeFinalize(hFdt); VRC(); 371 372 if (pSysTblsBldAcpi) 373 { 374 vrc = pSysTblsBldAcpi->addMemory(GCPhysRamHigh, cbRamHigh); 375 VRC(); 376 } 322 377 } 323 378 … … 440 495 InsertConfigNode(pResources, "ArmV8Desc", &pRes); 441 496 InsertConfigInteger(pRes, "RegisterAsRom", 1); 442 InsertConfigInteger(pRes, "GCPhysLoadAddress", VBOXPLATFORMARMV8_PHYS_ADDR);497 InsertConfigInteger(pRes, "GCPhysLoadAddress", GCPhysPlatformDesc); 443 498 InsertConfigString(pRes, "ResourceId", "VBoxArmV8Desc"); 444 499 … … 447 502 */ 448 503 RTGCPHYS GCPhysIntcDist; 504 RTGCPHYS GCPhysIntcIts; 505 RTGCPHYS cbMmioIntcDist; 506 RTGCPHYS cbMmioIntcIts; 449 507 RTGCPHYS GCPhysIntcReDist; 450 RTGCPHYS cbMmioIntcDist;451 508 RTGCPHYS cbMmioIntcReDist; 452 509 453 /* Each vCPU needs on re-distributor, this would allow for up to 256 vCPUs in the future. */ 454 hrc = pResMgr->assignMmioRegion("gic", 256 * _64K, &GCPhysIntcReDist, &cbMmioIntcReDist); H(); 455 hrc = pResMgr->assignMmioRegion("gic", _64K, &GCPhysIntcDist, &cbMmioIntcDist); H(); 456 457 #ifndef RT_OS_LINUX 510 /* Allow for up to 256 vCPUs in the future without changing the address space layout. */ 511 hrc = pResMgr->assignMmioRegion("gic", _64K + 256 * _128K, &GCPhysIntcDist, &cbMmioIntcDist); H(); 512 GCPhysIntcReDist = GCPhysIntcDist + _64K; 513 cbMmioIntcReDist = 256 * _128K; 514 cbMmioIntcDist = _64K; 515 516 hrc = pResMgr->assignMmioRegion("gic-its", 2 * _64K, &GCPhysIntcIts, &cbMmioIntcIts); H(); 517 518 #ifdef RT_OS_DARWIN 458 519 InsertConfigNode(pDevices, "gic", &pDev); 459 520 #else 460 /* On Linux we default to the KVM in-kernel GIC for now. */521 /* On Linux we default to the KVM in-kernel GIC and on Windows we are forced to the Hyper-V GIC for now. */ 461 522 InsertConfigNode(pDevices, "gic-nem", &pDev); 462 523 #endif … … 466 527 InsertConfigInteger(pCfg, "DistributorMmioBase", GCPhysIntcDist); 467 528 InsertConfigInteger(pCfg, "RedistributorMmioBase", GCPhysIntcReDist); 529 InsertConfigInteger(pCfg, "ItsMmioBase", GCPhysIntcIts); 468 530 469 531 vrc = RTFdtNodeAddF(hFdt, "intc@%RGp", GCPhysIntcDist); VRC(); 470 532 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrl); VRC(); 471 533 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 4, 472 GCPhysIntcDist, cbMmioIntcDist, /* Distributor */534 GCPhysIntcDist, cbMmioIntcDist, /* Distributor */ 473 535 GCPhysIntcReDist, cbMmioIntcReDist); /* Re-Distributor */ VRC(); 474 536 vrc = RTFdtNodePropertyAddU32( hFdt, "#redistributor-regions", 1); VRC(); … … 500 562 501 563 /* 502 * Configure the per ofrmance monitoring unit.564 * Configure the performance monitoring unit. 503 565 */ 504 566 /** @todo Make this configurable and enable as default for Windows VMs because they assume a working PMU … … 542 604 InsertConfigNode(pDev, "0", &pInst); 543 605 InsertConfigNode(pInst, "Config", &pCfg); 544 InsertConfigInteger(pCfg, "BaseAddress", 64 * _1M);606 InsertConfigInteger(pCfg, "BaseAddress", GCPhysFlash); 545 607 InsertConfigInteger(pCfg, "Size", 768 * _1K); 546 608 InsertConfigString(pCfg, "FlashFile", "nvram"); … … 552 614 vrc = RTFdtNodePropertyAddU32( hFdt, "bank-width", 4); VRC(); 553 615 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 4, 554 0, 0x04000000,/* First region (EFI). */555 0x04000000, 0x04000000); /* Second region (NVRAM). */ VRC();616 GCPhysFw, cbFw, /* First region (EFI). */ 617 GCPhysFlash, cbFlash); /* Second region (NVRAM). */ VRC(); 556 618 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "cfi-flash"); VRC(); 557 619 vrc = RTFdtNodeFinalize(hFdt); VRC(); … … 638 700 vrc = RTFdtNodeFinalize(hFdt); VRC(); 639 701 640 /* Configure gpio keys . */702 /* Configure gpio keys (The Windows GPIO PL061 driver doesn't like 64-bit MMIO addresses...). */ 641 703 hrc = pResMgr->assignSingleInterrupt("arm-pl061-gpio", &iIrq); H(); 642 hrc = pResMgr->assignMmio Region("arm-pl061-gpio", _4K, &GCPhysMmioStart, &cbMmio); H();704 hrc = pResMgr->assignMmio32Region("arm-pl061-gpio", _4K, &GCPhysMmioStart, &cbMmio); H(); 643 705 InsertConfigNode(pDevices, "arm-pl061-gpio",&pDev); 644 706 InsertConfigNode(pDev, "0", &pInst); … … 660 722 if (pSysTblsBldAcpi) 661 723 { 662 vrc = pSysTblsBldAcpi->addMmioDevice("arm-pl061-gpio", 0, GCPhysMmioStart, _4K, iIrq);724 vrc = pSysTblsBldAcpi->addMmioDevice("arm-pl061-gpio", 0, GCPhysMmioStart, cbMmio, iIrq); 663 725 VRC(); 664 726 } … … 687 749 vrc = RTFdtNodeFinalize(hFdt); VRC(); 688 750 689 hrc = pResMgr->assignInterrupts("pci-generic-ecam", 4 /*cInterrupts*/, &iIrq); H();690 uint32_t aPinIrqs[] = { iIrq, iIrq + 1, iIrq + 2, iIrq + 3 };691 RTGCPHYS GCPhysPciMmioEcam, GCPhysPciMmio, GCPhysPciMmio32;692 RTGCPHYS cbPciMmioEcam, cbPciMmio, cbPciMmio32;693 hrc = pResMgr->assignMmioRegionAligned("pci-pio", _64K, _64K, &GCPhysMmioStart, &cbMmio); H();694 hrc = pResMgr->assignMmioRegion( "pci-ecam", 16 * _1M, &GCPhysPciMmioEcam, &cbPciMmioEcam); H();695 hrc = pResMgr->assignMmioRegion( "pci-mmio", _2G, &GCPhysPciMmio, &cbPciMmio); H();696 hrc = pResMgr->assignMmio32Region( "pci-mmio32", _1G - VBOXPLATFORMARMV8_PHYS_ADDR - _1M, &GCPhysPciMmio32, &cbPciMmio32); H();697 698 InsertConfigNode(pDevices, "pci-generic-ecam", &pDev);699 InsertConfigNode(pDev, "0", &pInst);700 InsertConfigNode(pInst, "Config", &pCfg);701 InsertConfigInteger(pCfg, "MmioEcamBase", GCPhysPciMmioEcam);702 InsertConfigInteger(pCfg, "MmioEcamLength", cbPciMmioEcam);703 InsertConfigInteger(pCfg, "MmioPioBase", GCPhysMmioStart);704 InsertConfigInteger(pCfg, "MmioPioSize", cbMmio);705 InsertConfigInteger(pCfg, "IntPinA", aPinIrqs[0]);706 InsertConfigInteger(pCfg, "IntPinB", aPinIrqs[1]);707 InsertConfigInteger(pCfg, "IntPinC", aPinIrqs[2]);708 InsertConfigInteger(pCfg, "IntPinD", aPinIrqs[3]);709 vrc = RTFdtNodeAddF(hFdt, "pcie@%RGp", GCPhysPciMmio); VRC();710 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map-mask", 4, 0xf800, 0, 0, 7); VRC();711 712 uint32_t aIrqCells[32 * 4 * 10]; RT_ZERO(aIrqCells); /* Maximum of 32 devices on the root bus, each supporting 4 interrupts (INTA# ... INTD#). */713 uint32_t *pau32IrqCell = &aIrqCells[0];714 uint32_t iIrqPinSwizzle = 0;715 716 for (uint32_t i = 0; i < 32; i++)717 {718 for (uint32_t iIrqPin = 0; iIrqPin < 4; iIrqPin++)719 {720 pau32IrqCell[0] = i << 11; /* The dev part, composed as dev.fn. */721 pau32IrqCell[1] = 0;722 pau32IrqCell[2] = 0;723 pau32IrqCell[3] = iIrqPin + 1;724 pau32IrqCell[4] = idPHandleIntCtrl;725 pau32IrqCell[5] = 0;726 pau32IrqCell[6] = 0;727 pau32IrqCell[7] = 0;728 pau32IrqCell[8] = aPinIrqs[(iIrqPinSwizzle + iIrqPin) % RT_ELEMENTS(aPinIrqs)];729 pau32IrqCell[9] = 0x04;730 pau32IrqCell += 10;731 }732 733 iIrqPinSwizzle++;734 }735 736 vrc = RTFdtNodePropertyAddCellsU32AsArray(hFdt, "interrupt-map", RT_ELEMENTS(aIrqCells), &aIrqCells[0]);737 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 1); VRC();738 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 21,739 0x1000000, 0, 0,740 GCPhysMmioStart >> 32, GCPhysMmioStart, cbMmio >> 32, cbMmio,741 0x2000000, GCPhysPciMmio32 >> 32, GCPhysPciMmio32, GCPhysPciMmio32 >> 32, GCPhysPciMmio32,742 cbPciMmio32 >> 32, cbPciMmio32,743 0x3000000, GCPhysPciMmio >> 32, GCPhysPciMmio, GCPhysPciMmio >> 32, GCPhysPciMmio,744 cbPciMmio >> 32, cbPciMmio); VRC();745 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysPciMmioEcam, cbPciMmioEcam); VRC();746 /** @todo msi-map */747 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();748 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf); VRC();749 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,pci-domain", 0); VRC();750 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();751 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 3); VRC();752 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "pci"); VRC();753 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "pci-host-ecam-generic"); VRC();754 vrc = RTFdtNodeFinalize(hFdt); VRC();755 756 if (pSysTblsBldAcpi)757 {758 vrc = pSysTblsBldAcpi->configurePcieRootBus("pci-generic-ecam", aPinIrqs, GCPhysMmioStart, GCPhysPciMmioEcam,759 cbPciMmioEcam, GCPhysMmioStart, cbMmio, GCPhysPciMmio32, cbPciMmio32);760 VRC();761 }762 763 751 #if defined(VBOX_WITH_TPM) 764 752 /* … … 773 761 { 774 762 hrc = pResMgr->assignSingleInterrupt("tpm", &iIrq); H(); 775 hrc = pResMgr->assignMmioRegion("tpm", 5 * _1K, &GCPhysMmioStart, &cbMmio); H();776 763 777 764 InsertConfigNode(pDevices, "tpm", &pDev); … … 779 766 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 780 767 InsertConfigNode(pInst, "Config", &pCfg); 781 InsertConfigInteger(pCfg, "MmioBase", GCPhys MmioStart);768 InsertConfigInteger(pCfg, "MmioBase", GCPhysTpm); 782 769 InsertConfigInteger(pCfg, "Irq", iIrq); 783 //InsertConfigInteger(pCfg, "Crb", 1); /* boolean */770 InsertConfigInteger(pCfg, "Crb", 1); /* boolean */ 784 771 785 772 InsertConfigNode(pInst, "LUN#0", &pLunL0); … … 811 798 } 812 799 813 vrc = RTFdtNodeAddF(hFdt, "tpm@%RGp", GCPhys MmioStart);VRC();800 vrc = RTFdtNodeAddF(hFdt, "tpm@%RGp", GCPhysTpm); VRC(); 814 801 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, iIrq, 0x04); VRC(); 815 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhys MmioStart, cbMmio);VRC();802 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysTpm, cbTpm); VRC(); 816 803 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 1, "tcg,tpm-tis-mmio"); VRC(); 817 804 vrc = RTFdtNodeFinalize(hFdt); VRC(); … … 819 806 if (pSysTblsBldAcpi) 820 807 { 821 vrc = pSysTblsBldAcpi->configureTpm2( false /*fCrb*/, GCPhysMmioStart, cbMmio, iIrq);808 vrc = pSysTblsBldAcpi->configureTpm2(true /*fCrb*/, GCPhysTpm, cbTpm, iIrq); 822 809 VRC(); 823 810 } 824 811 825 #if 0826 812 /* Add the device for the physical presence interface. */ 827 813 InsertConfigNode( pDevices, "tpm-ppi", &pDev); … … 829 815 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 830 816 InsertConfigNode( pInst, "Config", &pCfg); 831 InsertConfigInteger(pCfg, "MmioBase", TPM_PPI_MMIO_BASE_DEFAULT); 817 InsertConfigInteger(pCfg, "MmioBase", GCPhysTpm + 0x5000); 818 } 832 819 #endif 833 } 834 #endif 820 821 hrc = pResMgr->assignInterrupts("pci-generic-ecam", 4 /*cInterrupts*/, &iIrq); H(); 822 uint32_t aPinIrqs[] = { iIrq, iIrq + 1, iIrq + 2, iIrq + 3 }; 823 RTGCPHYS GCPhysPciMmioEcam, GCPhysPciMmio, GCPhysPciMmio32; 824 RTGCPHYS cbPciMmioEcam, cbPciMmio, cbPciMmio32; 825 826 hrc = pResMgr->assignMmioRegionAligned("pci-pio", _64K, _64K, &GCPhysMmioStart, &cbMmio, false /*fOnly32Bit*/); H(); 827 hrc = pResMgr->assignMmioRegion( "pci-ecam", 16 * _1M, &GCPhysPciMmioEcam, &cbPciMmioEcam); H(); 828 hrc = pResMgr->assignMmioRegion( "pci-mmio", _2G, &GCPhysPciMmio, &cbPciMmio); H(); 829 hrc = pResMgr->assignMmio32Region( "pci-mmio32", _256M, &GCPhysPciMmio32, &cbPciMmio32); H(); 830 831 InsertConfigNode(pDevices, "pci-generic-ecam", &pDev); 832 InsertConfigNode(pDev, "0", &pInst); 833 InsertConfigNode(pInst, "Config", &pCfg); 834 InsertConfigInteger(pCfg, "MmioEcamBase", GCPhysPciMmioEcam); 835 InsertConfigInteger(pCfg, "MmioEcamLength", cbPciMmioEcam); 836 InsertConfigInteger(pCfg, "MmioPioBase", GCPhysMmioStart); 837 InsertConfigInteger(pCfg, "MmioPioSize", cbMmio); 838 InsertConfigInteger(pCfg, "IntPinA", aPinIrqs[0]); 839 InsertConfigInteger(pCfg, "IntPinB", aPinIrqs[1]); 840 InsertConfigInteger(pCfg, "IntPinC", aPinIrqs[2]); 841 InsertConfigInteger(pCfg, "IntPinD", aPinIrqs[3]); 842 vrc = RTFdtNodeAddF(hFdt, "pcie@%RGp", GCPhysPciMmio); VRC(); 843 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map-mask", 4, 0xf800, 0, 0, 7); VRC(); 844 845 uint32_t aIrqCells[32 * 4 * 10]; RT_ZERO(aIrqCells); /* Maximum of 32 devices on the root bus, each supporting 4 interrupts (INTA# ... INTD#). */ 846 uint32_t *pau32IrqCell = &aIrqCells[0]; 847 uint32_t iIrqPinSwizzle = 0; 848 849 for (uint32_t i = 0; i < 32; i++) 850 { 851 for (uint32_t iIrqPin = 0; iIrqPin < 4; iIrqPin++) 852 { 853 pau32IrqCell[0] = i << 11; /* The dev part, composed as dev.fn. */ 854 pau32IrqCell[1] = 0; 855 pau32IrqCell[2] = 0; 856 pau32IrqCell[3] = iIrqPin + 1; 857 pau32IrqCell[4] = idPHandleIntCtrl; 858 pau32IrqCell[5] = 0; 859 pau32IrqCell[6] = 0; 860 pau32IrqCell[7] = 0; 861 pau32IrqCell[8] = aPinIrqs[(iIrqPinSwizzle + iIrqPin) % RT_ELEMENTS(aPinIrqs)]; 862 pau32IrqCell[9] = 0x04; 863 pau32IrqCell += 10; 864 } 865 866 iIrqPinSwizzle++; 867 } 868 869 vrc = RTFdtNodePropertyAddCellsU32AsArray(hFdt, "interrupt-map", RT_ELEMENTS(aIrqCells), &aIrqCells[0]); 870 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 1); VRC(); 871 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 21, 872 0x1000000, 0, 0, 873 GCPhysMmioStart >> 32, GCPhysMmioStart, cbMmio >> 32, cbMmio, 874 0x2000000, GCPhysPciMmio32 >> 32, GCPhysPciMmio32, GCPhysPciMmio32 >> 32, GCPhysPciMmio32, 875 cbPciMmio32 >> 32, cbPciMmio32, 876 0x3000000, GCPhysPciMmio >> 32, GCPhysPciMmio, GCPhysPciMmio >> 32, GCPhysPciMmio, 877 cbPciMmio >> 32, cbPciMmio); VRC(); 878 vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysPciMmioEcam, cbPciMmioEcam); VRC(); 879 /** @todo msi-map */ 880 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC(); 881 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf); VRC(); 882 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,pci-domain", 0); VRC(); 883 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC(); 884 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 3); VRC(); 885 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "pci"); VRC(); 886 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "pci-host-ecam-generic"); VRC(); 887 vrc = RTFdtNodeFinalize(hFdt); VRC(); 888 889 if (pSysTblsBldAcpi) 890 { 891 vrc = pSysTblsBldAcpi->configurePcieRootBus("pci-generic-ecam", aPinIrqs, GCPhysMmioStart, GCPhysPciMmioEcam, 892 cbPciMmioEcam, GCPhysMmioStart, cbMmio, GCPhysPciMmio32, cbPciMmio32); 893 VRC(); 894 } 835 895 836 896 /* … … 931 991 VBOXPLATFORMARMV8 ArmV8Platform; RT_ZERO(ArmV8Platform); 932 992 933 /* Make room for the descriptor at the beginning. */934 vrc = RTVfsIoStrmZeroFill(hVfsIosDesc, sizeof(ArmV8Platform));935 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);936 937 993 vrc = RTFdtDumpToVfsIoStrm(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, hVfsIosDesc, NULL /*pErrInfo*/); 938 994 uint64_t cbFdt = 0; 939 995 if (RT_SUCCESS(vrc)) 940 {941 996 vrc = RTVfsFileQuerySize(hVfsFileDesc, &cbFdt); 942 cbFdt -= sizeof(ArmV8Platform);943 }944 997 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc); 945 998 946 999 vrc = RTVfsIoStrmZeroFill(hVfsIosDesc, (RTFOFF)(RT_ALIGN_64(cbFdt, _64K) - cbFdt)); 947 1000 AssertRCReturn(vrc, vrc); 1001 1002 cbFdt = RT_ALIGN_64(cbFdt, _64K); 948 1003 949 1004 RTGCPHYS GCPhysMmioStart; … … 962 1017 if (pSysTblsBldAcpi) 963 1018 { 964 vrc = pSysTblsBldAcpi->finishTables( VBOXPLATFORMARMV8_PHYS_ADDR + sizeof(ArmV8Platform) + RT_ALIGN_64(cbFdt, _64K),1019 vrc = pSysTblsBldAcpi->finishTables(GCPhysPlatformDesc + cbFdt, 965 1020 hVfsIosDesc, &GCPhysXsdp, &cbAcpiXsdp, &cbAcpi); 966 1021 AssertRCReturn(vrc, vrc); 967 Assert(GCPhysXsdp > VBOXPLATFORMARMV8_PHYS_ADDR); 1022 Assert( GCPhysXsdp > GCPhysPlatformDesc 1023 && GCPhysXsdp < VBOXPLATFORMARMV8_PHYS_ADDR); 968 1024 969 1025 /* Dump the ACPI table for debugging purposes if requested. */ … … 982 1038 vrc = RTVfsIoStrmZeroFill(hVfsIosDesc, (RTFOFF)(RT_ALIGN_64(cbAcpi, _64K) - cbAcpi)); 983 1039 AssertRCReturn(vrc, vrc); 1040 1041 cbAcpi = RT_ALIGN_64(cbAcpi, _64K); 984 1042 } 1043 1044 /* Fill the room until the end where the platform descriptor lives. */ 1045 vrc = RTVfsIoStrmZeroFill(hVfsIosDesc, cbPlatformDesc - sizeof(ArmV8Platform) - cbFdt - cbAcpi); 1046 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc); 1047 1048 RTGCPHYS GCPhysMmio = 0; 1049 RTGCPHYS cbMmioAbove4G = 0; 1050 pResMgr->queryMmioRegion(&GCPhysMmio, &cbMmioAbove4G); 985 1051 986 1052 ArmV8Platform.u32Magic = VBOXPLATFORMARMV8_MAGIC; … … 988 1054 ArmV8Platform.cbDesc = sizeof(ArmV8Platform); 989 1055 ArmV8Platform.fFlags = 0; 990 ArmV8Platform.u64PhysAddrRamBase = GCPhysRam ;991 ArmV8Platform.cbRamBase = cbRam ;992 ArmV8Platform.i64OffFdt = sizeof(ArmV8Platform);993 ArmV8Platform.cbFdt = RT_ALIGN_64(cbFdt, _64K);1056 ArmV8Platform.u64PhysAddrRamBase = GCPhysRamBase; 1057 ArmV8Platform.cbRamBase = cbRamBase; 1058 ArmV8Platform.i64OffFdt = (int64_t)GCPhysPlatformDesc - VBOXPLATFORMARMV8_PHYS_ADDR; 1059 ArmV8Platform.cbFdt = cbFdt; 994 1060 if (cbAcpi) 995 1061 { 996 ArmV8Platform.i64OffAcpi = sizeof(ArmV8Platform) + RT_ALIGN_64(cbFdt, _64K);997 ArmV8Platform.cbAcpi = RT_ALIGN_64(cbAcpi, _64K);998 ArmV8Platform.i64OffAcpiXsdp = GCPhysXsdp - VBOXPLATFORMARMV8_PHYS_ADDR;1062 ArmV8Platform.i64OffAcpi = (int64_t)(GCPhysPlatformDesc + cbFdt) - VBOXPLATFORMARMV8_PHYS_ADDR; 1063 ArmV8Platform.cbAcpi = cbAcpi; 1064 ArmV8Platform.i64OffAcpiXsdp = (int64_t)GCPhysXsdp - VBOXPLATFORMARMV8_PHYS_ADDR; 999 1065 ArmV8Platform.cbAcpiXsdp = cbAcpiXsdp; 1000 1066 } 1001 ArmV8Platform.i64OffUefiRom = -128 * _1M;1067 ArmV8Platform.i64OffUefiRom = (int64_t)GCPhysFw - VBOXPLATFORMARMV8_PHYS_ADDR; 1002 1068 ArmV8Platform.cbUefiRom = _64M; 1003 ArmV8Platform.i64OffMmio = GCPhysMmio Start - _128M;1004 ArmV8Platform.cbMmio = cbMmio ;1005 ArmV8Platform.i64OffMmio32 = GCPhysMmio32Start - _128M;1006 ArmV8Platform.cbMmio32 = cbMmio32;1069 ArmV8Platform.i64OffMmio = GCPhysMmio ? (int64_t)GCPhysMmio - VBOXPLATFORMARMV8_PHYS_ADDR : 0; 1070 ArmV8Platform.cbMmio = cbMmioAbove4G; 1071 ArmV8Platform.i64OffMmio32 = (int64_t)(_4G - _512M) - VBOXPLATFORMARMV8_PHYS_ADDR; 1072 ArmV8Platform.cbMmio32 = _512M - _2M; /* Just assign the whole MMIO hole (except for the platform descriptor region). */ 1007 1073 1008 1074 /* Add the VBox platform descriptor to the resource store. */ 1009 vrc = RTVfsIoStrmWrite At(hVfsIosDesc, 0, &ArmV8Platform, sizeof(ArmV8Platform), true /*fBlocking*/, NULL /*pcbWritten*/);1075 vrc = RTVfsIoStrmWrite(hVfsIosDesc, &ArmV8Platform, sizeof(ArmV8Platform), true /*fBlocking*/, NULL /*pcbWritten*/); 1010 1076 RTVfsIoStrmRelease(hVfsIosDesc); 1011 1077 vrc = mptrResourceStore->i_addItem("resources", "VBoxArmV8Desc", hVfsFileDesc); … … 1024 1090 } 1025 1091 1092 pResMgr->dumpMemoryRegionsToReleaseLog(); 1093 1026 1094 delete pResMgr; /* Delete the address/interrupt assignment manager. */ 1027 1095 -
trunk/src/VBox/Main/src-client/ResourceAssignmentManager.cpp
r106061 r106957 35 35 #include "ResourceAssignmentManager.h" 36 36 37 #include <VBox/com/array.h> 38 37 39 #include <iprt/asm.h> 40 #include <iprt/mem.h> 38 41 #include <iprt/string.h> 39 40 #include <VBox/vmm/cfgm.h>41 #include <VBox/vmm/vmmr3vtable.h>42 #include <VBox/com/array.h>43 44 #include <map>45 #include <vector>46 #include <algorithm>47 42 48 43 … … 50 45 * Structures and Typedefs * 51 46 *********************************************************************************************************************************/ 47 /** 48 * Address space range type. 49 */ 50 typedef enum RESOURCEREGIONTYPE 51 { 52 /** Free region. */ 53 kResourceRegionType_Free = 0, 54 /** RAM. */ 55 kResourceRegionType_Ram, 56 /** ROM. */ 57 kResourceRegionType_Rom, 58 /** MMIO. */ 59 kResourceRegionType_Mmio, 60 /** 32bit hack. */ 61 kResourceRegionType_32Bit_Hack = 0x7fffffff 62 } RESOURCEREGIONTYPE; 63 64 65 /** 66 * Address space range descriptor. 67 */ 68 typedef struct RESOURCEREGION 69 { 70 /** Region name. */ 71 char szName[32]; 72 /** Physical start address of the region. */ 73 RTGCPHYS GCPhysStart; 74 /** Physical end address of the region. */ 75 RTGCPHYS GCPhysEnd; 76 /** Region type. */ 77 RESOURCEREGIONTYPE enmType; 78 /** Padding. */ 79 uint32_t u32Pad; 80 } RESOURCEREGION; 81 AssertCompileSize(RESOURCEREGION, 56); 82 /** Pointer to a resource region. */ 83 typedef RESOURCEREGION *PRESOURCEREGION; 84 /** Pointer to a const resource region. */ 85 typedef const RESOURCEREGION *PCRESOURCEREGION; 52 86 53 87 … … 63 97 struct ResourceAssignmentManager::State 64 98 { 65 struct MemoryRange66 {67 char szDevName[32];68 RTGCPHYS mGCPhysStart;69 RTGCPHYS mGCPhysEnd;70 71 MemoryRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd)72 {73 RTStrCopy(this->szDevName, sizeof(szDevName), pszName);74 this->mGCPhysStart = GCPhysStart;75 this->mGCPhysEnd = GCPhysEnd;76 }77 78 bool operator==(const MemoryRange &a) const79 {80 return RTStrNCmp(szDevName, a.szDevName, sizeof(szDevName)) == 0;81 }82 };83 84 typedef std::vector<MemoryRange> AddrRangeList;85 86 99 ChipsetType_T mChipsetType; 87 100 IommuType_T mIommuType; 88 PCVMMR3VTABLE mpVMM; 89 AddrRangeList mAddrRanges; 90 91 RTGCPHYS mGCPhysMmioStartOrig; 92 RTGCPHYS mGCPhysMmioStart; 93 RTGCPHYS mGCPhysMmio32StartOrig; 94 RTGCPHYS mGCPhysMmio32Start; 95 RTGCPHYS mcbMmio32; 96 RTGCPHYS mGCPhysRamStart; 101 102 /** Pointer to the array of regions (sorted by address, not overlapping, adjacent). */ 103 PRESOURCEREGION m_paRegions; 104 /** Number of used regions. */ 105 uint32_t m_cRegions; 106 /** Number of regions the allocated array can hold. */ 107 uint32_t m_cRegionsMax; 108 97 109 uint32_t mcInterrupts; 98 110 uint32_t miInterrupt; 99 111 100 112 State() 101 : mChipsetType(ChipsetType_Null), mpVMM(NULL) 113 : mChipsetType(ChipsetType_Null) 114 , mIommuType(IommuType_None) 115 , m_paRegions(NULL) 116 , m_cRegions(0) 117 , m_cRegionsMax(0) 118 , mcInterrupts(0) 119 , miInterrupt(0) 102 120 {} 103 121 ~State() 104 122 {} 105 123 106 HRESULT init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType, 107 RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart, 108 RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts); 109 110 HRESULT addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd); 124 HRESULT init(ChipsetType_T chipsetType, IommuType_T iommuType, uint32_t cInterrupts); 125 126 HRESULT ensureAdditionalRegions(uint32_t cRegions); 127 void setRegion(PRESOURCEREGION pRegion, const char *pszName, RESOURCEREGIONTYPE enmType, 128 RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd); 129 HRESULT addAddrRange(const char *pszName, RESOURCEREGIONTYPE enmType, RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd); 130 HRESULT findNextFreeAddrRange(RTGCPHYS cbRegion, RTGCPHYS cbAlignment, RTGCPHYS GCPhysMax, RTGCPHYS GCPhysHint, 131 PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion); 132 133 void dumpToReleaseLog(void); 111 134 }; 112 135 113 136 114 HRESULT ResourceAssignmentManager::State::init(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType, 115 RTGCPHYS GCPhysMmioStart, RTGCPHYS GCPhysRamStart, 116 RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, uint32_t cInterrupts) 117 { 118 mpVMM = pVMM; 119 137 HRESULT ResourceAssignmentManager::State::init(ChipsetType_T chipsetType, IommuType_T iommuType, 138 uint32_t cInterrupts) 139 { 120 140 Assert(chipsetType == ChipsetType_ARMv8Virtual); 121 141 Assert(iommuType == IommuType_None); /* For now no IOMMU support on ARMv8. */ … … 123 143 mChipsetType = chipsetType; 124 144 mIommuType = iommuType; 125 mGCPhysMmioStart = GCPhysMmioStart;126 mGCPhysMmioStartOrig = GCPhysMmioStart;127 mGCPhysRamStart = GCPhysRamStart;128 mGCPhysMmio32Start = GCPhysMmio32Start;129 mGCPhysMmio32StartOrig = GCPhysMmio32Start;130 mcbMmio32 = cbMmio32;131 145 mcInterrupts = cInterrupts; 132 146 miInterrupt = 0; 133 return S_OK; 134 } 135 136 HRESULT ResourceAssignmentManager::State::addAddrRange(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion) 137 { 138 MemoryRange memRange(pszName, GCPhysStart, GCPhysStart + cbRegion - 1); 139 mAddrRanges.push_back(memRange); 140 return S_OK; 141 } 147 148 m_paRegions = (PRESOURCEREGION)RTMemRealloc(m_paRegions, 32 * sizeof(*m_paRegions)); 149 if (!m_paRegions) 150 return E_OUTOFMEMORY; 151 152 m_paRegions[m_cRegions].enmType = kResourceRegionType_Free; 153 m_paRegions[m_cRegions].GCPhysStart = 0; 154 m_paRegions[m_cRegions].GCPhysEnd = UINT64_MAX; 155 strcpy(&m_paRegions[m_cRegions].szName[0], "Free"); 156 m_cRegions++; 157 158 return S_OK; 159 } 160 161 162 HRESULT ResourceAssignmentManager::State::ensureAdditionalRegions(uint32_t cRegions) 163 { 164 if (m_cRegions + cRegions == m_cRegionsMax) 165 { 166 uint32_t const cRegionsNew = m_cRegionsMax + 32; 167 PRESOURCEREGION paDescsNew = (PRESOURCEREGION)RTMemRealloc(m_paRegions, cRegionsNew * sizeof(*paDescsNew)); 168 if (!paDescsNew) 169 return E_OUTOFMEMORY; 170 171 m_paRegions = paDescsNew; 172 m_cRegionsMax = cRegionsNew; 173 } 174 175 return S_OK; 176 } 177 178 179 void ResourceAssignmentManager::State::setRegion(PRESOURCEREGION pRegion, const char *pszName, RESOURCEREGIONTYPE enmType, 180 RTGCPHYS GCPhysStart, RTGCPHYS GCPhysEnd) 181 { 182 strncpy(&pRegion->szName[0], pszName, sizeof(pRegion->szName)); 183 pRegion->szName[sizeof(pRegion->szName) - 1] = '\0'; 184 pRegion->enmType = enmType; 185 pRegion->GCPhysStart = GCPhysStart; 186 pRegion->GCPhysEnd = GCPhysEnd; 187 } 188 189 190 HRESULT ResourceAssignmentManager::State::addAddrRange(const char *pszName, RESOURCEREGIONTYPE enmType, 191 RTGCPHYS GCPhysStart, RTGCPHYS cbRegion) 192 { 193 RTGCPHYS GCPhysEnd = GCPhysStart + cbRegion - 1; 194 195 /* Find the right spot in the array where to insert the range, it must not overlap with an existing used range. */ 196 uint32_t iRegion = 0; 197 while ( iRegion < m_cRegions 198 && GCPhysStart > m_paRegions[iRegion].GCPhysEnd) 199 iRegion++; 200 201 Assert( iRegion == m_cRegions - 1 202 || m_paRegions[iRegion].enmType != m_paRegions[iRegion + 1].enmType); 203 204 /* Check that there is sufficient free space. */ 205 if ( (m_paRegions[iRegion].enmType != kResourceRegionType_Free) 206 || GCPhysEnd > m_paRegions[iRegion].GCPhysEnd) 207 return E_INVALIDARG; 208 209 Assert(m_paRegions[iRegion].enmType == kResourceRegionType_Free); 210 211 /* Requested region fits exactly into the free region. */ 212 if ( GCPhysStart == m_paRegions[iRegion].GCPhysStart 213 && GCPhysEnd == m_paRegions[iRegion].GCPhysEnd) 214 { 215 setRegion(&m_paRegions[iRegion], pszName, enmType, GCPhysStart, GCPhysEnd); 216 return S_OK; 217 } 218 219 HRESULT hrc = ensureAdditionalRegions(2 /*cRegions*/); /* Need two additional region descriptors max. */ 220 if (FAILED(hrc)) 221 return hrc; 222 223 /* Need to split the region into two or three depending on where the requested region lies. */ 224 if (GCPhysStart == m_paRegions[iRegion].GCPhysStart) 225 { 226 /* At the start, move the free regions and everything at the end. */ 227 memmove(&m_paRegions[iRegion + 1], &m_paRegions[iRegion], (m_cRegions - iRegion) * sizeof(*m_paRegions)); 228 setRegion(&m_paRegions[iRegion], pszName, enmType, GCPhysStart, GCPhysEnd); 229 230 /* Adjust the free region. */ 231 m_paRegions[iRegion + 1].GCPhysStart = GCPhysStart + cbRegion; 232 m_cRegions++; 233 } 234 else if (GCPhysStart + cbRegion - 1 == m_paRegions[iRegion].GCPhysEnd) 235 { 236 /* At the end of the region, move the remaining regions and adjust ranges. */ 237 if (iRegion < m_cRegions) 238 memmove(&m_paRegions[iRegion + 2], &m_paRegions[iRegion + 1], (m_cRegions - iRegion) * sizeof(*m_paRegions)); 239 setRegion(&m_paRegions[iRegion + 1], pszName, enmType, GCPhysStart, GCPhysEnd); 240 m_paRegions[iRegion].GCPhysEnd = GCPhysStart - 1; 241 m_cRegions++; 242 } 243 else 244 { 245 /* Somewhere in the middle, split into three regions. */ 246 if (iRegion < m_cRegions) 247 memmove(&m_paRegions[iRegion + 3], &m_paRegions[iRegion + 1], (m_cRegions - iRegion) * sizeof(*m_paRegions)); 248 setRegion(&m_paRegions[iRegion + 1], pszName, enmType, GCPhysStart, GCPhysEnd); 249 setRegion(&m_paRegions[iRegion + 2], "Free", kResourceRegionType_Free, GCPhysStart + cbRegion, m_paRegions[iRegion].GCPhysEnd); 250 m_paRegions[iRegion].GCPhysEnd = GCPhysStart - 1; 251 m_cRegions += 2; 252 } 253 254 return S_OK; 255 } 256 257 258 HRESULT ResourceAssignmentManager::State::findNextFreeAddrRange(RTGCPHYS cbRegion, RTGCPHYS cbAlignment, RTGCPHYS GCPhysMax, 259 RTGCPHYS GCPhysHint, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion) 260 { 261 AssertReturn(GCPhysMax >= cbRegion, E_FAIL); 262 GCPhysMax -= cbRegion; 263 264 uint32_t iRegion = 0; 265 if (GCPhysHint) 266 { 267 /* Look for free address range downwards from the hint first. */ 268 iRegion = m_cRegions - 1; 269 while (iRegion) 270 { 271 PCRESOURCEREGION pRegion = &m_paRegions[iRegion]; 272 273 /* Region must be free and satisfy the alignment++ requirements. */ 274 RTGCPHYS GCPhysStartAligned = RT_ALIGN_T(pRegion->GCPhysEnd - cbRegion + 1, cbAlignment, RTGCPHYS); 275 if ( pRegion->enmType == kResourceRegionType_Free 276 && GCPhysHint >= pRegion->GCPhysEnd 277 && GCPhysMax >= pRegion->GCPhysEnd 278 && GCPhysStartAligned >= pRegion->GCPhysStart 279 && pRegion->GCPhysEnd - GCPhysStartAligned + 1 >= cbRegion) 280 { 281 *pGCPhysStart = GCPhysStartAligned; 282 *pcbRegion = cbRegion; 283 return S_OK; 284 } 285 286 iRegion--; 287 } 288 } 289 290 /* Find a free region which satisfies or requirements. */ 291 while ( iRegion < m_cRegions 292 && GCPhysMax >= m_paRegions[iRegion].GCPhysStart) 293 { 294 PCRESOURCEREGION pRegion = &m_paRegions[iRegion]; 295 296 /* Region must be free and satisfy the alignment++ requirements. */ 297 RTGCPHYS GCPhysStartAligned = RT_ALIGN_T(pRegion->GCPhysStart, cbAlignment, RTGCPHYS); 298 if ( pRegion->enmType == kResourceRegionType_Free 299 && GCPhysStartAligned >= pRegion->GCPhysStart 300 && pRegion->GCPhysEnd - GCPhysStartAligned + 1 >= cbRegion) 301 { 302 *pGCPhysStart = pRegion->GCPhysStart; 303 *pcbRegion = cbRegion; 304 return S_OK; 305 } 306 307 iRegion++; 308 } 309 310 return E_OUTOFMEMORY; 311 } 312 313 314 static const char *resourceManagerRegionType2Str(RESOURCEREGIONTYPE enmType) 315 { 316 switch (enmType) 317 { 318 case kResourceRegionType_Free: return "FREE"; 319 case kResourceRegionType_Ram: return "RAM "; 320 case kResourceRegionType_Rom: return "ROM "; 321 case kResourceRegionType_Mmio: return "MMIO"; 322 default: AssertFailed(); return "UNKNOWN"; 323 } 324 } 325 326 327 void ResourceAssignmentManager::State::dumpToReleaseLog(void) 328 { 329 LogRel(("Memory Regions:\n")); 330 for (uint32_t iRegion = 0; iRegion < m_cRegions; iRegion++) 331 { 332 LogRel((" %RGp - %RGp (%zu) %s %s\n", 333 m_paRegions[iRegion].GCPhysStart, 334 m_paRegions[iRegion].GCPhysEnd, 335 m_paRegions[iRegion].GCPhysEnd - m_paRegions[iRegion].GCPhysStart + 1, 336 m_paRegions[iRegion].szName)); 337 } 338 } 339 142 340 143 341 ResourceAssignmentManager::ResourceAssignmentManager() 144 : pState(NULL) 145 { 146 pState = new State(); 147 Assert(pState); 148 } 342 : m_pState(NULL) 343 { 344 m_pState = new State(); 345 Assert(m_pState); 346 } 347 149 348 150 349 ResourceAssignmentManager::~ResourceAssignmentManager() 151 350 { 152 if (pState) 153 { 154 delete pState; 155 pState = NULL; 156 } 157 } 351 if (m_pState) 352 { 353 delete m_pState; 354 m_pState = NULL; 355 } 356 } 357 158 358 159 359 ResourceAssignmentManager *ResourceAssignmentManager::createInstance(PCVMMR3VTABLE pVMM, ChipsetType_T chipsetType, IommuType_T iommuType, 160 RTGCPHYS GCPhysMmioTop, RTGCPHYS GCPhysRamStart,161 RTGCPHYS GCPhysMmio32Start, RTGCPHYS cbMmio32, 162 uint32_t cInterrupts)163 { 360 uint32_t cInterrupts, RTGCPHYS GCPhysMmioHint) 361 { 362 RT_NOREF(pVMM); 363 164 364 ResourceAssignmentManager *pInstance = new ResourceAssignmentManager(); 165 pInstance->pState->init(pVMM, chipsetType, iommuType, GCPhysMmioTop, GCPhysRamStart, GCPhysMmio32Start, cbMmio32, cInterrupts); 365 366 pInstance->m_GCPhysMmioHint = GCPhysMmioHint; 367 pInstance->m_pState->init(chipsetType, iommuType, cInterrupts); 166 368 Assert(pInstance); 167 369 return pInstance; 168 370 } 169 371 372 373 HRESULT ResourceAssignmentManager::assignFixedRomRegion(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion) 374 { 375 return m_pState->addAddrRange(pszName, kResourceRegionType_Rom, GCPhysStart, cbRegion); 376 } 377 378 379 HRESULT ResourceAssignmentManager::assignFixedRamRegion(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion) 380 { 381 return m_pState->addAddrRange(pszName, kResourceRegionType_Ram, GCPhysStart, cbRegion); 382 } 383 384 385 HRESULT ResourceAssignmentManager::assignFixedMmioRegion(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion) 386 { 387 return m_pState->addAddrRange(pszName, kResourceRegionType_Mmio, GCPhysStart, cbRegion); 388 } 389 390 391 HRESULT ResourceAssignmentManager::assignMmioRegionAligned(const char *pszName, RTGCPHYS cbRegion, RTGCPHYS cbAlignment, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion, 392 bool fOnly32Bit) 393 { 394 RTGCPHYS GCPhysRegionStart; 395 RTGCPHYS cbRegionFinal; 396 HRESULT hrc = m_pState->findNextFreeAddrRange(cbRegion, cbAlignment, fOnly32Bit ? _4G : RTGCPHYS_MAX, 397 m_GCPhysMmioHint, &GCPhysRegionStart, &cbRegionFinal); 398 if (SUCCEEDED(hrc)) 399 { 400 *pGCPhysStart = GCPhysRegionStart; 401 *pcbRegion = cbRegionFinal; 402 return assignFixedMmioRegion(pszName, GCPhysRegionStart, cbRegion); 403 } 404 405 return hrc; 406 } 407 408 170 409 HRESULT ResourceAssignmentManager::assignMmioRegion(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion) 171 410 { 172 RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS); 173 RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart; 174 175 *pGCPhysStart = GCPhysMmioStart; 176 *pcbRegion = cbRegionAligned; 177 pState->mGCPhysMmioStart += cbRegionAligned; 178 pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned); 179 return S_OK; 180 } 411 return assignMmioRegionAligned(pszName, cbRegion, _4K, pGCPhysStart, pcbRegion, false /*fOnly32Bit*/); 412 } 413 181 414 182 415 HRESULT ResourceAssignmentManager::assignMmio32Region(const char *pszName, RTGCPHYS cbRegion, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion) 183 416 { 184 RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, _4K, RTGCPHYS); 185 RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmio32Start; 186 187 if (GCPhysMmioStart > pState->mGCPhysRamStart) 188 { 189 AssertLogRelMsgFailed(("ResourceAssignmentManager: MMIO32 range for %s would overlap RAM region\n", pszName)); 190 return E_INVALIDARG; 191 } 192 193 *pGCPhysStart = GCPhysMmioStart; 194 *pcbRegion = cbRegionAligned; 195 pState->mGCPhysMmio32Start += cbRegionAligned; 196 pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned); 197 return S_OK; 198 } 199 200 HRESULT ResourceAssignmentManager::assignMmioRegionAligned(const char *pszName, RTGCPHYS cbRegion, RTGCPHYS cbAlignment, PRTGCPHYS pGCPhysStart, PRTGCPHYS pcbRegion) 201 { 202 RTGCPHYS cbRegionAligned = RT_ALIGN_T(cbRegion, cbAlignment, RTGCPHYS); 203 RTGCPHYS GCPhysMmioStart = pState->mGCPhysMmioStart; 204 205 GCPhysMmioStart = RT_ALIGN_T(GCPhysMmioStart, cbAlignment, RTGCPHYS); 206 207 *pGCPhysStart = GCPhysMmioStart; 208 *pcbRegion = cbRegionAligned; 209 pState->mGCPhysMmioStart = GCPhysMmioStart + cbRegionAligned; 210 pState->addAddrRange(pszName, GCPhysMmioStart, cbRegionAligned); 211 return S_OK; 212 } 213 214 HRESULT ResourceAssignmentManager::assignFixedAddress(const char *pszName, RTGCPHYS GCPhysStart, RTGCPHYS cbRegion) 215 { 216 RT_NOREF(pszName, GCPhysStart, cbRegion); 217 AssertReleaseFailed(); 218 return S_OK; 219 } 220 221 HRESULT ResourceAssignmentManager::assignRamRegion(const char *pszName, RTGCPHYS cbRam, PRTGCPHYS pGCPhysStart) 222 { 223 *pGCPhysStart = pState->mGCPhysRamStart; 224 pState->mGCPhysRamStart += cbRam; 225 pState->addAddrRange(pszName, *pGCPhysStart, cbRam); 226 return S_OK; 227 } 417 return assignMmioRegionAligned(pszName, cbRegion, _4K, pGCPhysStart, pcbRegion, true /*fOnly32Bit*/); 418 } 419 228 420 229 421 HRESULT ResourceAssignmentManager::assignInterrupts(const char *pszName, uint32_t cInterrupts, uint32_t *piInterruptFirst) 230 422 { 231 if ( pState->miInterrupt + cInterrupts >pState->mcInterrupts)423 if (m_pState->miInterrupt + cInterrupts > m_pState->mcInterrupts) 232 424 { 233 425 AssertLogRelMsgFailed(("ResourceAssignmentManager: Interrupt count for %s exceeds number of available interrupts\n", pszName)); … … 235 427 } 236 428 237 *piInterruptFirst = pState->miInterrupt; 238 pState->miInterrupt += cInterrupts; 239 return S_OK; 240 } 429 *piInterruptFirst = m_pState->miInterrupt; 430 m_pState->miInterrupt += cInterrupts; 431 return S_OK; 432 } 433 434 HRESULT ResourceAssignmentManager::queryMmioRegion(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio) 435 { 436 /* 437 * This ASSUMES that there are adjacent MMIO regions above 4GiB which can be combined into one single region 438 * (adjacent and no ROM/RAM regions inbetween). 439 */ 440 *pGCPhysMmioStart = 0; 441 *pcbMmio = 0; 442 443 /* Look for the start. */ 444 for (uint32_t i = 0; i < m_pState->m_cRegions; i++) 445 { 446 PCRESOURCEREGION pRegion = &m_pState->m_paRegions[i]; 447 448 if ( pRegion->GCPhysStart >= _4G 449 && pRegion->enmType == kResourceRegionType_Mmio) 450 { 451 RTGCPHYS cbMmio = pRegion->GCPhysEnd - pRegion->GCPhysStart + 1; 452 453 *pGCPhysMmioStart = pRegion->GCPhysStart; 454 455 /* Add up any remaining MMIO regions adjacent to this one. */ 456 for (uint32_t j = i; j < m_pState->m_cRegions; j++) 457 { 458 pRegion = &m_pState->m_paRegions[i]; 459 if ( pRegion->enmType == kResourceRegionType_Mmio 460 && pRegion->GCPhysStart == *pGCPhysMmioStart + cbMmio) 461 cbMmio += pRegion->GCPhysEnd - pRegion->GCPhysStart + 1; 462 else 463 break; 464 } 465 466 *pcbMmio = cbMmio; 467 return S_OK; 468 } 469 } 470 471 return S_OK; 472 } 473 474 475 HRESULT ResourceAssignmentManager::queryMmio32Region(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio) 476 { 477 RT_NOREF(pGCPhysMmioStart, pcbMmio); 478 return S_OK; 479 } 480 241 481 242 482 HRESULT ResourceAssignmentManager::assignSingleInterrupt(const char *pszName, uint32_t *piInterrupt) … … 245 485 } 246 486 247 HRESULT ResourceAssignmentManager::queryMmioRegion(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio) 248 { 249 *pGCPhysMmioStart = pState->mGCPhysMmioStartOrig; 250 *pcbMmio = pState->mGCPhysMmioStart - pState->mGCPhysMmioStartOrig; 251 return S_OK; 252 } 253 254 HRESULT ResourceAssignmentManager::queryMmio32Region(PRTGCPHYS pGCPhysMmioStart, PRTGCPHYS pcbMmio) 255 { 256 *pGCPhysMmioStart = pState->mGCPhysMmio32StartOrig; 257 *pcbMmio = pState->mcbMmio32; 258 return S_OK; 259 } 487 488 void ResourceAssignmentManager::dumpMemoryRegionsToReleaseLog(void) 489 { 490 m_pState->dumpToReleaseLog(); 491 }
Note:
See TracChangeset
for help on using the changeset viewer.