[99913] | 1 | /* $Id: ConsoleImplConfigArmV8.cpp 104386 2024-04-20 19:05:54Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * VBox Console COM Class implementation - VM Configuration Bits for ARMv8.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
| 7 | * Copyright (C) 2023 Oracle and/or its affiliates.
|
---|
| 8 | *
|
---|
| 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
| 26 | */
|
---|
| 27 |
|
---|
| 28 |
|
---|
| 29 | /*********************************************************************************************************************************
|
---|
| 30 | * Header Files *
|
---|
| 31 | *********************************************************************************************************************************/
|
---|
| 32 | #define LOG_GROUP LOG_GROUP_MAIN_CONSOLE
|
---|
| 33 | #include "LoggingNew.h"
|
---|
| 34 |
|
---|
| 35 | #include "ConsoleImpl.h"
|
---|
[100041] | 36 | #include "ResourceStoreImpl.h"
|
---|
[99913] | 37 | #include "Global.h"
|
---|
[100706] | 38 | #include "VMMDev.h"
|
---|
[99913] | 39 |
|
---|
| 40 | // generated header
|
---|
| 41 | #include "SchemaDefs.h"
|
---|
| 42 |
|
---|
| 43 | #include "AutoCaller.h"
|
---|
| 44 |
|
---|
| 45 | #include <iprt/buildconfig.h>
|
---|
| 46 | #include <iprt/ctype.h>
|
---|
| 47 | #include <iprt/dir.h>
|
---|
[100041] | 48 | #include <iprt/fdt.h>
|
---|
[99913] | 49 | #include <iprt/file.h>
|
---|
| 50 | #include <iprt/param.h>
|
---|
| 51 | #include <iprt/path.h>
|
---|
| 52 | #include <iprt/string.h>
|
---|
| 53 | #include <iprt/system.h>
|
---|
| 54 | #if 0 /* enable to play with lots of memory. */
|
---|
| 55 | # include <iprt/env.h>
|
---|
| 56 | #endif
|
---|
| 57 | #include <iprt/stream.h>
|
---|
| 58 |
|
---|
[100105] | 59 | #include <iprt/formats/arm-psci.h>
|
---|
| 60 |
|
---|
[99913] | 61 | #include <VBox/vmm/vmmr3vtable.h>
|
---|
| 62 | #include <VBox/vmm/vmapi.h>
|
---|
| 63 | #include <VBox/err.h>
|
---|
| 64 | #include <VBox/param.h>
|
---|
| 65 | #include <VBox/version.h>
|
---|
[101443] | 66 | #include <VBox/platforms/vbox-armv8.h>
|
---|
[99913] | 67 |
|
---|
[101475] | 68 | #include "BusAssignmentManager.h"
|
---|
[102517] | 69 | #include "ResourceAssignmentManager.h"
|
---|
[99913] | 70 | #ifdef VBOX_WITH_EXTPACK
|
---|
| 71 | # include "ExtPackManagerImpl.h"
|
---|
| 72 | #endif
|
---|
| 73 |
|
---|
| 74 |
|
---|
| 75 | /*********************************************************************************************************************************
|
---|
| 76 | * Internal Functions *
|
---|
| 77 | *********************************************************************************************************************************/
|
---|
| 78 |
|
---|
| 79 | /* Darwin compile kludge */
|
---|
| 80 | #undef PVM
|
---|
| 81 |
|
---|
[99925] | 82 | #ifdef VBOX_WITH_VIRT_ARMV8
|
---|
[99913] | 83 | /**
|
---|
| 84 | * Worker for configConstructor.
|
---|
| 85 | *
|
---|
| 86 | * @return VBox status code.
|
---|
| 87 | * @param pUVM The user mode VM handle.
|
---|
| 88 | * @param pVM The cross context VM handle.
|
---|
| 89 | * @param pVMM The VMM vtable.
|
---|
| 90 | * @param pAlock The automatic lock instance. This is for when we have
|
---|
| 91 | * to leave it in order to avoid deadlocks (ext packs and
|
---|
| 92 | * more).
|
---|
| 93 | */
|
---|
| 94 | int Console::i_configConstructorArmV8(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
|
---|
| 95 | {
|
---|
| 96 | RT_NOREF(pVM /* when everything is disabled */);
|
---|
| 97 | ComPtr<IMachine> pMachine = i_machine();
|
---|
| 98 |
|
---|
| 99 | HRESULT hrc;
|
---|
| 100 | Utf8Str strTmp;
|
---|
| 101 | Bstr bstr;
|
---|
| 102 |
|
---|
[100041] | 103 | RTFDT hFdt = NIL_RTFDT;
|
---|
| 104 | int vrc = RTFdtCreateEmpty(&hFdt);
|
---|
| 105 | AssertRCReturn(vrc, vrc);
|
---|
[99913] | 106 |
|
---|
[100041] | 107 | #define H() AssertLogRelMsgReturnStmt(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), RTFdtDestroy(hFdt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
|
---|
| 108 | #define VRC() AssertLogRelMsgReturnStmt(RT_SUCCESS(vrc), ("vrc=%Rrc\n", vrc), RTFdtDestroy(hFdt), vrc)
|
---|
| 109 |
|
---|
[101443] | 110 | /** @todo Find a way to figure it out before CPUM is set up, can't use CPUMGetGuestAddrWidths() and on macOS we need
|
---|
| 111 | * access to Hypervisor.framework to query the ID registers (Linux can in theory parse /proc/cpuinfo, no idea for Windows). */
|
---|
| 112 | RTGCPHYS GCPhysTopOfAddrSpace = RT_BIT_64(36);
|
---|
[100041] | 113 |
|
---|
[99913] | 114 | /*
|
---|
| 115 | * Get necessary objects and frequently used parameters.
|
---|
| 116 | */
|
---|
| 117 | ComPtr<IVirtualBox> virtualBox;
|
---|
| 118 | hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
|
---|
| 119 |
|
---|
| 120 | ComPtr<IHost> host;
|
---|
| 121 | hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
|
---|
| 122 |
|
---|
[101468] | 123 | PlatformArchitecture_T platformArchHost;
|
---|
| 124 | hrc = host->COMGETTER(Architecture)(&platformArchHost); H();
|
---|
| 125 |
|
---|
[99913] | 126 | ComPtr<ISystemProperties> systemProperties;
|
---|
| 127 | hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
|
---|
| 128 |
|
---|
[101035] | 129 | ComPtr<IFirmwareSettings> firmwareSettings;
|
---|
| 130 | hrc = pMachine->COMGETTER(FirmwareSettings)(firmwareSettings.asOutParam()); H();
|
---|
[99913] | 131 |
|
---|
| 132 | ComPtr<INvramStore> nvramStore;
|
---|
| 133 | hrc = pMachine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam()); H();
|
---|
| 134 |
|
---|
| 135 | hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H();
|
---|
| 136 | RTUUID HardwareUuid;
|
---|
| 137 | vrc = RTUuidFromUtf16(&HardwareUuid, bstr.raw());
|
---|
| 138 | AssertRCReturn(vrc, vrc);
|
---|
| 139 |
|
---|
| 140 | ULONG cRamMBs;
|
---|
| 141 | hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
|
---|
| 142 | uint64_t const cbRam = cRamMBs * (uint64_t)_1M;
|
---|
| 143 |
|
---|
[101468] | 144 | ComPtr<IPlatform> platform;
|
---|
| 145 | hrc = pMachine->COMGETTER(Platform)(platform.asOutParam()); H();
|
---|
[101035] | 146 |
|
---|
[101468] | 147 | /* Note: Should be guarded by VBOX_WITH_VIRT_ARMV8, but we check this anyway here. */
|
---|
| 148 | #if 1 /* For now we only support running ARM VMs on ARM hosts. */
|
---|
| 149 | PlatformArchitecture_T platformArchMachine;
|
---|
| 150 | hrc = platform->COMGETTER(Architecture)(&platformArchMachine); H();
|
---|
| 151 | if (platformArchMachine != platformArchHost)
|
---|
| 152 | return pVMM->pfnVMR3SetError(pUVM, VERR_PLATFORM_ARCH_NOT_SUPPORTED, RT_SRC_POS,
|
---|
| 153 | N_("VM platform architecture (%s) not supported on this host (%s)."),
|
---|
| 154 | Global::stringifyPlatformArchitecture(platformArchMachine),
|
---|
| 155 | Global::stringifyPlatformArchitecture(platformArchHost));
|
---|
| 156 | #endif
|
---|
| 157 |
|
---|
[101035] | 158 | ComPtr<IPlatformProperties> pPlatformProperties;
|
---|
[101468] | 159 | hrc = platform->COMGETTER(Properties)(pPlatformProperties.asOutParam()); H();
|
---|
[101035] | 160 |
|
---|
[100716] | 161 | ChipsetType_T chipsetType;
|
---|
[101468] | 162 | hrc = platform->COMGETTER(ChipsetType)(&chipsetType); H();
|
---|
[100716] | 163 |
|
---|
[99913] | 164 | ULONG cCpus = 1;
|
---|
| 165 | hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
|
---|
[101035] | 166 | Assert(cCpus);
|
---|
[99913] | 167 |
|
---|
| 168 | ULONG ulCpuExecutionCap = 100;
|
---|
| 169 | hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H();
|
---|
| 170 |
|
---|
[103085] | 171 | VMExecutionEngine_T enmExecEngine = VMExecutionEngine_NotSet;
|
---|
| 172 | hrc = pMachine->COMGETTER(VMExecutionEngine)(&enmExecEngine); H();
|
---|
| 173 |
|
---|
| 174 | if ( enmExecEngine != VMExecutionEngine_Default
|
---|
| 175 | && enmExecEngine != VMExecutionEngine_NativeApi)
|
---|
| 176 | {
|
---|
| 177 | return pVMM->pfnVMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
|
---|
| 178 | N_("The ARM backend doesn't support any other execution engine than 'default' or 'native-api' right now."));
|
---|
| 179 | }
|
---|
| 180 |
|
---|
[101073] | 181 | LogRel(("Guest architecture: ARM\n"));
|
---|
| 182 |
|
---|
[99913] | 183 | Bstr osTypeId;
|
---|
| 184 | hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
|
---|
| 185 | LogRel(("Guest OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
|
---|
| 186 |
|
---|
[101475] | 187 | BusAssignmentManager *pBusMgr = mBusMgr = BusAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None);
|
---|
[102517] | 188 | ResourceAssignmentManager *pResMgr = ResourceAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None,
|
---|
| 189 | GCPhysTopOfAddrSpace - sizeof(VBOXPLATFORMARMV8),
|
---|
| 190 | _1G, /*GCPhysRam*/
|
---|
| 191 | 128 * _1M, /*GCPhysMmio32Start*/
|
---|
| 192 | _1G - 128 * _1M, /*cbMmio32*/
|
---|
| 193 | 32 /*cInterrupts*/);
|
---|
[100716] | 194 |
|
---|
[99913] | 195 | /*
|
---|
| 196 | * Get root node first.
|
---|
| 197 | * This is the only node in the tree.
|
---|
| 198 | */
|
---|
| 199 | PCFGMNODE pRoot = pVMM->pfnCFGMR3GetRootU(pUVM);
|
---|
| 200 | Assert(pRoot);
|
---|
| 201 |
|
---|
[102517] | 202 | RTGCPHYS GCPhysRam = NIL_RTGCPHYS;
|
---|
| 203 |
|
---|
[99913] | 204 | // catching throws from InsertConfigString and friends.
|
---|
| 205 | try
|
---|
| 206 | {
|
---|
| 207 |
|
---|
| 208 | /*
|
---|
| 209 | * Set the root (and VMM) level values.
|
---|
| 210 | */
|
---|
| 211 | hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H();
|
---|
| 212 | InsertConfigString(pRoot, "Name", bstr);
|
---|
| 213 | InsertConfigBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid));
|
---|
| 214 | InsertConfigInteger(pRoot, "NumCPUs", cCpus);
|
---|
| 215 | InsertConfigInteger(pRoot, "CpuExecutionCap", ulCpuExecutionCap);
|
---|
| 216 | InsertConfigInteger(pRoot, "TimerMillies", 10);
|
---|
| 217 |
|
---|
[101496] | 218 | /*
|
---|
| 219 | * NEM
|
---|
| 220 | */
|
---|
| 221 | PCFGMNODE pNEM;
|
---|
| 222 | InsertConfigNode(pRoot, "NEM", &pNEM);
|
---|
| 223 |
|
---|
[100041] | 224 | uint32_t idPHandleIntCtrl = RTFdtPHandleAllocate(hFdt);
|
---|
| 225 | Assert(idPHandleIntCtrl != UINT32_MAX);
|
---|
| 226 | uint32_t idPHandleIntCtrlMsi = RTFdtPHandleAllocate(hFdt);
|
---|
[100108] | 227 | Assert(idPHandleIntCtrlMsi != UINT32_MAX); RT_NOREF(idPHandleIntCtrlMsi);
|
---|
[100041] | 228 | uint32_t idPHandleAbpPClk = RTFdtPHandleAllocate(hFdt);
|
---|
| 229 | Assert(idPHandleAbpPClk != UINT32_MAX);
|
---|
| 230 | uint32_t idPHandleGpio = RTFdtPHandleAllocate(hFdt);
|
---|
| 231 | Assert(idPHandleGpio != UINT32_MAX);
|
---|
| 232 |
|
---|
| 233 | uint32_t aidPHandleCpus[VMM_MAX_CPU_COUNT];
|
---|
| 234 | for (uint32_t i = 0; i < cCpus; i++)
|
---|
| 235 | {
|
---|
| 236 | aidPHandleCpus[i] = RTFdtPHandleAllocate(hFdt);
|
---|
| 237 | Assert(aidPHandleCpus[i] != UINT32_MAX);
|
---|
| 238 | }
|
---|
| 239 |
|
---|
| 240 | vrc = RTFdtNodePropertyAddU32( hFdt, "interrupt-parent", idPHandleIntCtrl); VRC();
|
---|
| 241 | vrc = RTFdtNodePropertyAddString(hFdt, "model", "linux,dummy-virt"); VRC();
|
---|
| 242 | vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
|
---|
| 243 | vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
|
---|
| 244 | vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "linux,dummy-virt"); VRC();
|
---|
| 245 |
|
---|
| 246 | /* Configure the Power State Coordination Interface. */
|
---|
| 247 | vrc = RTFdtNodeAdd(hFdt, "psci"); VRC();
|
---|
[100105] | 248 | vrc = RTFdtNodePropertyAddU32( hFdt, "migrate", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_MIGRATE)); VRC();
|
---|
| 249 | vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_on", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_ON)); VRC();
|
---|
| 250 | vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_off", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_OFF)); VRC();
|
---|
| 251 | vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_suspend", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_SUSPEND)); VRC();
|
---|
[100041] | 252 | vrc = RTFdtNodePropertyAddString(hFdt, "method", "hvc"); VRC();
|
---|
| 253 | vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 3,
|
---|
| 254 | "arm,psci-1.0", "arm,psci-0.2", "arm,psci"); VRC();
|
---|
| 255 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 256 |
|
---|
| 257 | /* Configure the timer and clock. */
|
---|
[101496] | 258 | InsertConfigInteger(pNEM, "VTimerInterrupt", 0xb);
|
---|
[100041] | 259 | vrc = RTFdtNodeAdd(hFdt, "timer"); VRC();
|
---|
| 260 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 12,
|
---|
| 261 | 0x01, 0x0d, 0x104,
|
---|
| 262 | 0x01, 0x0e, 0x104,
|
---|
| 263 | 0x01, 0x0b, 0x104,
|
---|
| 264 | 0x01, 0x0a, 0x104); VRC();
|
---|
| 265 | vrc = RTFdtNodePropertyAddEmpty( hFdt, "always-on"); VRC();
|
---|
[101619] | 266 | vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,armv8-timer"); VRC();
|
---|
[100041] | 267 | vrc = RTFdtNodeFinalize(hFdt);
|
---|
| 268 |
|
---|
| 269 | vrc = RTFdtNodeAdd(hFdt, "apb-clk"); VRC();
|
---|
| 270 | vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleAbpPClk); VRC();
|
---|
| 271 | vrc = RTFdtNodePropertyAddString( hFdt, "clock-output-names", "clk24mhz"); VRC();
|
---|
| 272 | vrc = RTFdtNodePropertyAddU32( hFdt, "clock-frequency", 24 * 1000 * 1000); VRC();
|
---|
| 273 | vrc = RTFdtNodePropertyAddU32( hFdt, "#clock-cells", 0); VRC();
|
---|
| 274 | vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "fixed-clock"); VRC();
|
---|
| 275 | vrc = RTFdtNodeFinalize(hFdt);
|
---|
| 276 |
|
---|
[99913] | 277 | /*
|
---|
| 278 | * MM values.
|
---|
| 279 | */
|
---|
| 280 | PCFGMNODE pMM;
|
---|
| 281 | InsertConfigNode(pRoot, "MM", &pMM);
|
---|
| 282 |
|
---|
| 283 | /*
|
---|
| 284 | * Memory setup.
|
---|
| 285 | */
|
---|
| 286 | PCFGMNODE pMem = NULL;
|
---|
| 287 | InsertConfigNode(pMM, "MemRegions", &pMem);
|
---|
| 288 |
|
---|
[102517] | 289 | hrc = pResMgr->assignRamRegion("Conventional", cbRam, &GCPhysRam); H();
|
---|
| 290 |
|
---|
[99913] | 291 | PCFGMNODE pMemRegion = NULL;
|
---|
| 292 | InsertConfigNode(pMem, "Conventional", &pMemRegion);
|
---|
[102517] | 293 | InsertConfigInteger(pMemRegion, "GCPhysStart", GCPhysRam);
|
---|
[99913] | 294 | InsertConfigInteger(pMemRegion, "Size", cbRam);
|
---|
| 295 |
|
---|
[102517] | 296 | vrc = RTFdtNodeAddF(hFdt, "memory@%RGp", GCPhysRam); VRC();
|
---|
| 297 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysRam, cbRam); VRC();
|
---|
[100041] | 298 | vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "memory"); VRC();
|
---|
| 299 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 300 |
|
---|
| 301 | /* Configure the CPUs in the system, only one socket and cluster at the moment. */
|
---|
| 302 | vrc = RTFdtNodeAdd(hFdt, "cpus"); VRC();
|
---|
| 303 | vrc = RTFdtNodePropertyAddU32(hFdt, "#size-cells", 0); VRC();
|
---|
| 304 | vrc = RTFdtNodePropertyAddU32(hFdt, "#address-cells", 1); VRC();
|
---|
| 305 |
|
---|
| 306 | vrc = RTFdtNodeAdd(hFdt, "socket0"); VRC();
|
---|
| 307 | vrc = RTFdtNodeAdd(hFdt, "cluster0"); VRC();
|
---|
| 308 |
|
---|
| 309 | for (uint32_t i = 0; i < cCpus; i++)
|
---|
| 310 | {
|
---|
| 311 | vrc = RTFdtNodeAddF(hFdt, "core%u", i); VRC();
|
---|
| 312 | vrc = RTFdtNodePropertyAddU32(hFdt, "cpu", aidPHandleCpus[i]); VRC();
|
---|
| 313 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 314 | }
|
---|
| 315 |
|
---|
| 316 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 317 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 318 |
|
---|
| 319 | for (uint32_t i = 0; i < cCpus; i++)
|
---|
| 320 | {
|
---|
| 321 | vrc = RTFdtNodeAddF(hFdt, "cpu@%u", i); VRC();
|
---|
| 322 | vrc = RTFdtNodePropertyAddU32(hFdt, "phandle", aidPHandleCpus[i]); VRC();
|
---|
[100105] | 323 | vrc = RTFdtNodePropertyAddU32(hFdt, "reg", i); VRC();
|
---|
[100041] | 324 | vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "arm,cortex-a15"); VRC();
|
---|
| 325 | vrc = RTFdtNodePropertyAddString(hFdt, "device_type", "cpu"); VRC();
|
---|
[100105] | 326 | if (cCpus > 1)
|
---|
| 327 | {
|
---|
| 328 | vrc = RTFdtNodePropertyAddString(hFdt, "enable-method", "psci"); VRC();
|
---|
| 329 | }
|
---|
[100041] | 330 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 331 | }
|
---|
| 332 |
|
---|
| 333 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 334 |
|
---|
| 335 |
|
---|
[99913] | 336 | /*
|
---|
| 337 | * PDM config.
|
---|
| 338 | * Load drivers in VBoxC.[so|dll]
|
---|
| 339 | */
|
---|
[101462] | 340 | vrc = i_configPdm(pMachine, pVMM, pUVM, pRoot); VRC();
|
---|
[99913] | 341 |
|
---|
| 342 |
|
---|
| 343 | /*
|
---|
[101200] | 344 | * VGA.
|
---|
| 345 | */
|
---|
| 346 | ComPtr<IGraphicsAdapter> pGraphicsAdapter;
|
---|
| 347 | hrc = pMachine->COMGETTER(GraphicsAdapter)(pGraphicsAdapter.asOutParam()); H();
|
---|
| 348 | GraphicsControllerType_T enmGraphicsController;
|
---|
| 349 | hrc = pGraphicsAdapter->COMGETTER(GraphicsControllerType)(&enmGraphicsController); H();
|
---|
| 350 |
|
---|
| 351 | /*
|
---|
[99913] | 352 | * Devices
|
---|
| 353 | */
|
---|
| 354 | PCFGMNODE pDevices = NULL; /* /Devices */
|
---|
| 355 | PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
|
---|
| 356 | PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
|
---|
| 357 | PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
|
---|
| 358 | PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
|
---|
| 359 |
|
---|
| 360 | InsertConfigNode(pRoot, "Devices", &pDevices);
|
---|
| 361 |
|
---|
[101480] | 362 | InsertConfigNode(pDevices, "pci-generic-ecam-bridge", NULL);
|
---|
| 363 |
|
---|
[101322] | 364 | InsertConfigNode(pDevices, "platform", &pDev);
|
---|
[99927] | 365 | InsertConfigNode(pDev, "0", &pInst);
|
---|
| 366 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
[100041] | 367 | InsertConfigNode(pInst, "LUN#0", &pLunL0);
|
---|
| 368 | InsertConfigString(pLunL0, "Driver", "ResourceStore");
|
---|
[99927] | 369 |
|
---|
[101322] | 370 | /* Add the resources. */
|
---|
[101574] | 371 | PCFGMNODE pResources = NULL; /* /Devices/platform/Config/Resources */
|
---|
| 372 | PCFGMNODE pRes = NULL; /* /Devices/platform/Config/Resources/<Resource> */
|
---|
[101322] | 373 | InsertConfigString(pCfg, "ResourceNamespace", "resources");
|
---|
| 374 | InsertConfigNode(pCfg, "Resources", &pResources);
|
---|
| 375 | InsertConfigNode(pResources, "EfiRom", &pRes);
|
---|
| 376 | InsertConfigInteger(pRes, "RegisterAsRom", 1);
|
---|
| 377 | InsertConfigInteger(pRes, "GCPhysLoadAddress", 0);
|
---|
| 378 |
|
---|
| 379 | /** @todo r=aeichner 32-bit guests and query the firmware type from VBoxSVC. */
|
---|
| 380 | /*
|
---|
| 381 | * Firmware.
|
---|
| 382 | */
|
---|
| 383 | FirmwareType_T eFwType = FirmwareType_EFI64;
|
---|
| 384 | #ifdef VBOX_WITH_EFI_IN_DD2
|
---|
| 385 | const char *pszEfiRomFile = eFwType == FirmwareType_EFIDUAL ? "<INVALID>"
|
---|
| 386 | : eFwType == FirmwareType_EFI32 ? "VBoxEFIAArch32.fd"
|
---|
| 387 | : "VBoxEFIAArch64.fd";
|
---|
| 388 | const char *pszKey = "ResourceId";
|
---|
| 389 | #else
|
---|
| 390 | Utf8Str efiRomFile;
|
---|
| 391 | vrc = findEfiRom(virtualBox, PlatformArchitecture_ARM, eFwType, &efiRomFile);
|
---|
| 392 | AssertRCReturn(vrc, vrc);
|
---|
| 393 | const char *pszEfiRomFile = efiRomFile.c_str();
|
---|
| 394 | const char *pszKey = "Filename";
|
---|
| 395 | #endif
|
---|
| 396 | InsertConfigString(pRes, pszKey, pszEfiRomFile);
|
---|
| 397 |
|
---|
[101443] | 398 | InsertConfigNode(pResources, "ArmV8Desc", &pRes);
|
---|
| 399 | InsertConfigInteger(pRes, "RegisterAsRom", 1);
|
---|
| 400 | InsertConfigInteger(pRes, "GCPhysLoadAddress", UINT64_MAX); /* End of physical address space. */
|
---|
| 401 | InsertConfigString(pRes, "ResourceId", "VBoxArmV8Desc");
|
---|
[101322] | 402 |
|
---|
[101574] | 403 | /*
|
---|
| 404 | * Configure the interrupt controller.
|
---|
| 405 | */
|
---|
[102517] | 406 | RTGCPHYS GCPhysIntcDist;
|
---|
| 407 | RTGCPHYS GCPhysIntcReDist;
|
---|
| 408 | RTGCPHYS cbMmioIntcDist;
|
---|
| 409 | RTGCPHYS cbMmioIntcReDist;
|
---|
| 410 |
|
---|
| 411 | /* Each vCPU needs on re-distributor, this would allow for up to 256 vCPUs in the future. */
|
---|
| 412 | hrc = pResMgr->assignMmioRegion("gic", 256 * _64K, &GCPhysIntcReDist, &cbMmioIntcReDist); H();
|
---|
| 413 | hrc = pResMgr->assignMmioRegion("gic", _64K, &GCPhysIntcDist, &cbMmioIntcDist); H();
|
---|
| 414 |
|
---|
[104386] | 415 | #ifndef RT_OS_LINUX
|
---|
[99913] | 416 | InsertConfigNode(pDevices, "gic", &pDev);
|
---|
[104386] | 417 | #else
|
---|
| 418 | /* On Linux we default to the KVM in-kernel GIC for now. */
|
---|
| 419 | InsertConfigNode(pDevices, "gic-kvm", &pDev);
|
---|
| 420 | #endif
|
---|
[99913] | 421 | InsertConfigNode(pDev, "0", &pInst);
|
---|
| 422 | InsertConfigInteger(pInst, "Trusted", 1);
|
---|
| 423 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
[102517] | 424 | InsertConfigInteger(pCfg, "DistributorMmioBase", GCPhysIntcDist);
|
---|
| 425 | InsertConfigInteger(pCfg, "RedistributorMmioBase", GCPhysIntcReDist);
|
---|
[99913] | 426 |
|
---|
[102517] | 427 | vrc = RTFdtNodeAddF(hFdt, "intc@%RGp", GCPhysIntcDist); VRC();
|
---|
| 428 | vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrl); VRC();
|
---|
[101577] | 429 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 4,
|
---|
[102517] | 430 | GCPhysIntcDist, cbMmioIntcDist, /* Distributor */
|
---|
| 431 | GCPhysIntcReDist, cbMmioIntcReDist); /* Re-Distributor */ VRC();
|
---|
| 432 | vrc = RTFdtNodePropertyAddU32( hFdt, "#redistributor-regions", 1); VRC();
|
---|
| 433 | vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3"); VRC();
|
---|
| 434 | vrc = RTFdtNodePropertyAddEmpty( hFdt, "ranges"); VRC();
|
---|
| 435 | vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
|
---|
| 436 | vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
|
---|
| 437 | vrc = RTFdtNodePropertyAddEmpty( hFdt, "interrupt-controller"); VRC();
|
---|
| 438 | vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 3); VRC();
|
---|
[99913] | 439 |
|
---|
[100041] | 440 | #if 0
|
---|
| 441 | vrc = RTFdtNodeAddF(hFdt, "its@%RX32", 0x08080000); VRC();
|
---|
| 442 | vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrlMsi); VRC();
|
---|
| 443 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x08080000, 0, 0x20000); VRC();
|
---|
| 444 | vrc = RTFdtNodePropertyAddU32( hFdt, "#msi-cells", 1); VRC();
|
---|
| 445 | vrc = RTFdtNodePropertyAddEmpty( hFdt, "msi-controller"); VRC();
|
---|
| 446 | vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3-its"); VRC();
|
---|
| 447 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 448 | #endif
|
---|
| 449 |
|
---|
| 450 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 451 |
|
---|
[102517] | 452 | RTGCPHYS GCPhysMmioStart;
|
---|
| 453 | RTGCPHYS cbMmio;
|
---|
[101200] | 454 | if (enmGraphicsController == GraphicsControllerType_QemuRamFB)
|
---|
| 455 | {
|
---|
[102517] | 456 | hrc = pResMgr->assignMmioRegion("qemu-fw-cfg", _4K, &GCPhysMmioStart, &cbMmio); H();
|
---|
| 457 |
|
---|
[101574] | 458 | InsertConfigNode(pDevices, "qemu-fw-cfg", &pDev);
|
---|
| 459 | InsertConfigNode(pDev, "0", &pInst);
|
---|
| 460 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
[102517] | 461 | InsertConfigInteger(pCfg, "MmioSize", cbMmio);
|
---|
| 462 | InsertConfigInteger(pCfg, "MmioBase", GCPhysMmioStart);
|
---|
[101574] | 463 | InsertConfigInteger(pCfg, "DmaEnabled", 1);
|
---|
| 464 | InsertConfigInteger(pCfg, "QemuRamfbSupport", 1);
|
---|
[101200] | 465 | InsertConfigNode(pInst, "LUN#0", &pLunL0);
|
---|
| 466 | InsertConfigString(pLunL0, "Driver", "MainDisplay");
|
---|
[101574] | 467 |
|
---|
[102517] | 468 | vrc = RTFdtNodeAddF(hFdt, "fw-cfg@%RGp", GCPhysMmioStart); VRC();
|
---|
[101574] | 469 | vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
|
---|
[102517] | 470 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio); VRC();
|
---|
[101574] | 471 | vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "qemu,fw-cfg-mmio"); VRC();
|
---|
| 472 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
[101200] | 473 | }
|
---|
[99913] | 474 |
|
---|
| 475 | InsertConfigNode(pDevices, "flash-cfi", &pDev);
|
---|
| 476 | InsertConfigNode(pDev, "0", &pInst);
|
---|
| 477 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
[99944] | 478 | InsertConfigInteger(pCfg, "BaseAddress", 64 * _1M);
|
---|
| 479 | InsertConfigInteger(pCfg, "Size", 768 * _1K);
|
---|
| 480 | InsertConfigString(pCfg, "FlashFile", "nvram");
|
---|
| 481 | /* Attach the NVRAM storage driver. */
|
---|
| 482 | InsertConfigNode(pInst, "LUN#0", &pLunL0);
|
---|
| 483 | InsertConfigString(pLunL0, "Driver", "NvramStore");
|
---|
[99913] | 484 |
|
---|
[100041] | 485 | vrc = RTFdtNodeAddF(hFdt, "flash@%RX32", 0); VRC();
|
---|
| 486 | vrc = RTFdtNodePropertyAddU32( hFdt, "bank-width", 4); VRC();
|
---|
[101577] | 487 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 4,
|
---|
| 488 | 0, 0x04000000, /* First region (EFI). */
|
---|
| 489 | 0x04000000, 0x04000000); /* Second region (NVRAM). */ VRC();
|
---|
[100041] | 490 | vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "cfi-flash"); VRC();
|
---|
| 491 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 492 |
|
---|
[99913] | 493 | InsertConfigNode(pDevices, "arm-pl011", &pDev);
|
---|
| 494 | for (ULONG ulInstance = 0; ulInstance < 1 /** @todo SchemaDefs::SerialPortCount*/; ++ulInstance)
|
---|
| 495 | {
|
---|
| 496 | ComPtr<ISerialPort> serialPort;
|
---|
| 497 | hrc = pMachine->GetSerialPort(ulInstance, serialPort.asOutParam()); H();
|
---|
| 498 | BOOL fEnabledSerPort = FALSE;
|
---|
| 499 | if (serialPort)
|
---|
| 500 | {
|
---|
| 501 | hrc = serialPort->COMGETTER(Enabled)(&fEnabledSerPort); H();
|
---|
| 502 | }
|
---|
| 503 | if (!fEnabledSerPort)
|
---|
| 504 | {
|
---|
| 505 | m_aeSerialPortMode[ulInstance] = PortMode_Disconnected;
|
---|
| 506 | continue;
|
---|
| 507 | }
|
---|
| 508 |
|
---|
| 509 | InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst);
|
---|
| 510 | InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
|
---|
| 511 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
| 512 |
|
---|
[102517] | 513 | uint32_t iIrq = 0;
|
---|
| 514 | hrc = pResMgr->assignSingleInterrupt("arm-pl011", &iIrq); H();
|
---|
| 515 | hrc = pResMgr->assignMmioRegion("arm-pl011", _4K, &GCPhysMmioStart, &cbMmio); H();
|
---|
[99913] | 516 |
|
---|
[102517] | 517 | InsertConfigInteger(pCfg, "Irq", iIrq);
|
---|
| 518 | InsertConfigInteger(pCfg, "MmioBase", GCPhysMmioStart);
|
---|
| 519 |
|
---|
| 520 | vrc = RTFdtNodeAddF(hFdt, "pl011@%RGp", GCPhysMmioStart); VRC();
|
---|
| 521 | vrc = RTFdtNodePropertyAddStringList(hFdt, "clock-names", 2, "uartclk", "apb_pclk"); VRC();
|
---|
[101191] | 522 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "clocks", 2,
|
---|
[102517] | 523 | idPHandleAbpPClk, idPHandleAbpPClk); VRC();
|
---|
| 524 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, iIrq, 0x04); VRC();
|
---|
| 525 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio); VRC();
|
---|
[101191] | 526 | vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
|
---|
[102517] | 527 | "arm,pl011", "arm,primecell"); VRC();
|
---|
| 528 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
[101191] | 529 |
|
---|
[99913] | 530 | BOOL fServer;
|
---|
| 531 | hrc = serialPort->COMGETTER(Server)(&fServer); H();
|
---|
| 532 | hrc = serialPort->COMGETTER(Path)(bstr.asOutParam()); H();
|
---|
| 533 |
|
---|
| 534 | PortMode_T eHostMode;
|
---|
| 535 | hrc = serialPort->COMGETTER(HostMode)(&eHostMode); H();
|
---|
| 536 |
|
---|
| 537 | m_aeSerialPortMode[ulInstance] = eHostMode;
|
---|
| 538 | if (eHostMode != PortMode_Disconnected)
|
---|
| 539 | {
|
---|
| 540 | vrc = i_configSerialPort(pInst, eHostMode, Utf8Str(bstr).c_str(), RT_BOOL(fServer));
|
---|
| 541 | if (RT_FAILURE(vrc))
|
---|
| 542 | return vrc;
|
---|
| 543 | }
|
---|
| 544 | }
|
---|
| 545 |
|
---|
[101483] | 546 | BOOL fRTCUseUTC;
|
---|
| 547 | hrc = platform->COMGETTER(RTCUseUTC)(&fRTCUseUTC); H();
|
---|
| 548 |
|
---|
[102517] | 549 | uint32_t iIrq = 0;
|
---|
| 550 | hrc = pResMgr->assignSingleInterrupt("arm-pl031-rtc", &iIrq); H();
|
---|
| 551 | hrc = pResMgr->assignMmioRegion("arm-pl031-rtc", _4K, &GCPhysMmioStart, &cbMmio); H();
|
---|
[99913] | 552 | InsertConfigNode(pDevices, "arm-pl031-rtc", &pDev);
|
---|
| 553 | InsertConfigNode(pDev, "0", &pInst);
|
---|
| 554 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
[102517] | 555 | InsertConfigInteger(pCfg, "Irq", iIrq);
|
---|
| 556 | InsertConfigInteger(pCfg, "MmioBase", GCPhysMmioStart);
|
---|
[101483] | 557 | InsertConfigInteger(pCfg, "UtcOffset", fRTCUseUTC ? 1 : 0);
|
---|
| 558 |
|
---|
[102517] | 559 | vrc = RTFdtNodeAddF(hFdt, "pl032@%RGp", GCPhysMmioStart); VRC();
|
---|
[100041] | 560 | vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
|
---|
| 561 | vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
|
---|
[102517] | 562 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, iIrq, 0x04); VRC();
|
---|
| 563 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio); VRC();
|
---|
[100041] | 564 | vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
|
---|
| 565 | "arm,pl031", "arm,primecell"); VRC();
|
---|
| 566 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
[99913] | 567 |
|
---|
[101619] | 568 | /* Configure gpio keys. */
|
---|
[102517] | 569 | hrc = pResMgr->assignSingleInterrupt("arm-pl061-gpio", &iIrq); H();
|
---|
| 570 | hrc = pResMgr->assignMmioRegion("arm-pl061-gpio", _4K, &GCPhysMmioStart, &cbMmio); H();
|
---|
[99913] | 571 | InsertConfigNode(pDevices, "arm-pl061-gpio",&pDev);
|
---|
| 572 | InsertConfigNode(pDev, "0", &pInst);
|
---|
| 573 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
[102517] | 574 | InsertConfigInteger(pCfg, "Irq", iIrq);
|
---|
| 575 | InsertConfigInteger(pCfg, "MmioBase", GCPhysMmioStart);
|
---|
| 576 | vrc = RTFdtNodeAddF(hFdt, "pl061@%RGp", GCPhysMmioStart); VRC();
|
---|
[100041] | 577 | vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleGpio); VRC();
|
---|
| 578 | vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
|
---|
| 579 | vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
|
---|
[102517] | 580 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, iIrq, 0x04); VRC();
|
---|
[100041] | 581 | vrc = RTFdtNodePropertyAddEmpty( hFdt, "gpio-controller"); VRC();
|
---|
| 582 | vrc = RTFdtNodePropertyAddU32( hFdt, "#gpio-cells", 2); VRC();
|
---|
| 583 | vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
|
---|
| 584 | "arm,pl061", "arm,primecell"); VRC();
|
---|
[102517] | 585 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysMmioStart, cbMmio); VRC();
|
---|
[100041] | 586 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
[99913] | 587 |
|
---|
[101619] | 588 | InsertConfigNode(pInst, "LUN#0", &pLunL0);
|
---|
| 589 | InsertConfigString(pLunL0, "Driver", "GpioButton");
|
---|
| 590 | InsertConfigNode(pLunL0, "Config", &pCfg);
|
---|
| 591 | InsertConfigInteger(pCfg, "PowerButtonGpio", 3);
|
---|
| 592 | InsertConfigInteger(pCfg, "SleepButtonGpio", 4);
|
---|
| 593 |
|
---|
| 594 | vrc = RTFdtNodeAdd(hFdt, "gpio-keys"); VRC();
|
---|
| 595 | vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "gpio-keys"); VRC();
|
---|
| 596 |
|
---|
| 597 | vrc = RTFdtNodeAdd(hFdt, "poweroff"); VRC();
|
---|
| 598 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "gpios", 3, idPHandleGpio, 3, 0); VRC();
|
---|
| 599 | vrc = RTFdtNodePropertyAddU32( hFdt, "linux,code", 0x74); VRC();
|
---|
| 600 | vrc = RTFdtNodePropertyAddString( hFdt, "label", "GPIO Key Poweroff"); VRC();
|
---|
| 601 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 602 |
|
---|
| 603 | vrc = RTFdtNodeAdd(hFdt, "suspend"); VRC();
|
---|
| 604 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "gpios", 3, idPHandleGpio, 4, 0); VRC();
|
---|
| 605 | vrc = RTFdtNodePropertyAddU32( hFdt, "linux,code", 0xcd); VRC();
|
---|
| 606 | vrc = RTFdtNodePropertyAddString( hFdt, "label", "GPIO Key Suspend"); VRC();
|
---|
[101622] | 607 | vrc = RTFdtNodeFinalize(hFdt);
|
---|
[101619] | 608 |
|
---|
| 609 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
| 610 |
|
---|
[102517] | 611 | hrc = pResMgr->assignInterrupts("pci-generic-ecam", 4 /*cInterrupts*/, &iIrq); H();
|
---|
| 612 | uint32_t aPinIrqs[] = { iIrq, iIrq + 1, iIrq + 2, iIrq + 3 };
|
---|
| 613 | RTGCPHYS GCPhysPciMmioEcam, GCPhysPciMmio, GCPhysPciMmio32;
|
---|
| 614 | RTGCPHYS cbPciMmioEcam, cbPciMmio, cbPciMmio32;
|
---|
| 615 | hrc = pResMgr->assignMmioRegionAligned("pci-pio", _64K, _64K, &GCPhysMmioStart, &cbMmio); H();
|
---|
| 616 | hrc = pResMgr->assignMmioRegion( "pci-ecam", 16 * _1M, &GCPhysPciMmioEcam, &cbPciMmioEcam); H();
|
---|
| 617 | hrc = pResMgr->assignMmioRegion( "pci-mmio", _2G, &GCPhysPciMmio, &cbPciMmio); H();
|
---|
| 618 | hrc = pResMgr->assignMmio32Region( "pci-mmio32", (1024 - 128) * _1M, &GCPhysPciMmio32, &cbPciMmio32); H();
|
---|
| 619 |
|
---|
[99913] | 620 | InsertConfigNode(pDevices, "pci-generic-ecam", &pDev);
|
---|
| 621 | InsertConfigNode(pDev, "0", &pInst);
|
---|
| 622 | InsertConfigNode(pInst, "Config", &pCfg);
|
---|
[102517] | 623 | InsertConfigInteger(pCfg, "MmioEcamBase", GCPhysPciMmioEcam);
|
---|
| 624 | InsertConfigInteger(pCfg, "MmioEcamLength", cbPciMmioEcam);
|
---|
| 625 | InsertConfigInteger(pCfg, "MmioPioBase", GCPhysMmioStart);
|
---|
| 626 | InsertConfigInteger(pCfg, "MmioPioSize", cbMmio);
|
---|
[101480] | 627 | InsertConfigInteger(pCfg, "IntPinA", aPinIrqs[0]);
|
---|
| 628 | InsertConfigInteger(pCfg, "IntPinB", aPinIrqs[1]);
|
---|
| 629 | InsertConfigInteger(pCfg, "IntPinC", aPinIrqs[2]);
|
---|
| 630 | InsertConfigInteger(pCfg, "IntPinD", aPinIrqs[3]);
|
---|
[102517] | 631 | vrc = RTFdtNodeAddF(hFdt, "pcie@%RGp", GCPhysPciMmio); VRC();
|
---|
[101480] | 632 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map-mask", 4, 0xf800, 0, 0, 7); VRC();
|
---|
| 633 |
|
---|
| 634 | uint32_t aIrqCells[32 * 4 * 10]; RT_ZERO(aIrqCells); /* Maximum of 32 devices on the root bus, each supporting 4 interrupts (INTA# ... INTD#). */
|
---|
| 635 | uint32_t *pau32IrqCell = &aIrqCells[0];
|
---|
| 636 | uint32_t iIrqPinSwizzle = 0;
|
---|
| 637 |
|
---|
| 638 | for (uint32_t i = 0; i < 32; i++)
|
---|
| 639 | {
|
---|
| 640 | for (uint32_t iIrqPin = 0; iIrqPin < 4; iIrqPin++)
|
---|
| 641 | {
|
---|
| 642 | pau32IrqCell[0] = i << 11; /* The dev part, composed as dev.fn. */
|
---|
| 643 | pau32IrqCell[1] = 0;
|
---|
| 644 | pau32IrqCell[2] = 0;
|
---|
| 645 | pau32IrqCell[3] = iIrqPin + 1;
|
---|
| 646 | pau32IrqCell[4] = idPHandleIntCtrl;
|
---|
| 647 | pau32IrqCell[5] = 0;
|
---|
| 648 | pau32IrqCell[6] = 0;
|
---|
| 649 | pau32IrqCell[7] = 0;
|
---|
| 650 | pau32IrqCell[8] = aPinIrqs[(iIrqPinSwizzle + iIrqPin) % RT_ELEMENTS(aPinIrqs)];
|
---|
| 651 | pau32IrqCell[9] = 0x04;
|
---|
| 652 | pau32IrqCell += 10;
|
---|
| 653 | }
|
---|
| 654 |
|
---|
| 655 | iIrqPinSwizzle++;
|
---|
| 656 | }
|
---|
| 657 |
|
---|
| 658 | vrc = RTFdtNodePropertyAddCellsU32AsArray(hFdt, "interrupt-map", RT_ELEMENTS(aIrqCells), &aIrqCells[0]);
|
---|
[102517] | 659 | vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 1); VRC();
|
---|
| 660 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 21,
|
---|
| 661 | 0x1000000, 0, 0,
|
---|
| 662 | GCPhysMmioStart >> 32, GCPhysMmioStart, cbMmio >> 32, cbMmio,
|
---|
| 663 | 0x2000000, GCPhysPciMmio32 >> 32, GCPhysPciMmio32, GCPhysPciMmio32 >> 32, GCPhysPciMmio32,
|
---|
| 664 | cbPciMmio32 >> 32, cbPciMmio32,
|
---|
| 665 | 0x3000000, GCPhysPciMmio >> 32, GCPhysPciMmio, GCPhysPciMmio >> 32, GCPhysPciMmio,
|
---|
| 666 | cbPciMmio >> 32, cbPciMmio); VRC();
|
---|
| 667 | vrc = RTFdtNodePropertyAddCellsU64(hFdt, "reg", 2, GCPhysPciMmioEcam, cbPciMmioEcam); VRC();
|
---|
[100041] | 668 | /** @todo msi-map */
|
---|
[102517] | 669 | vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
|
---|
| 670 | vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf); VRC();
|
---|
| 671 | vrc = RTFdtNodePropertyAddU32( hFdt, "linux,pci-domain", 0); VRC();
|
---|
| 672 | vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
|
---|
| 673 | vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 3); VRC();
|
---|
| 674 | vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "pci"); VRC();
|
---|
| 675 | vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "pci-host-ecam-generic"); VRC();
|
---|
| 676 | vrc = RTFdtNodeFinalize(hFdt); VRC();
|
---|
[99913] | 677 |
|
---|
[101477] | 678 | /*
|
---|
| 679 | * VMSVGA compliant graphics controller.
|
---|
| 680 | */
|
---|
[101200] | 681 | if ( enmGraphicsController != GraphicsControllerType_QemuRamFB
|
---|
| 682 | && enmGraphicsController != GraphicsControllerType_Null)
|
---|
| 683 | {
|
---|
[101477] | 684 | vrc = i_configGraphicsController(pDevices, enmGraphicsController, pBusMgr, pMachine,
|
---|
| 685 | pGraphicsAdapter, firmwareSettings,
|
---|
| 686 | true /*fForceVmSvga3*/, false /*fExposeLegacyVga*/); VRC();
|
---|
[101200] | 687 | }
|
---|
[100706] | 688 |
|
---|
| 689 | /*
|
---|
[101475] | 690 | * The USB Controllers and input devices.
|
---|
[100706] | 691 | */
|
---|
[101475] | 692 | #if 0 /** @todo Make us of this and disallow PS/2 for ARM VMs for now. */
|
---|
| 693 | KeyboardHIDType_T aKbdHID;
|
---|
| 694 | hrc = pMachine->COMGETTER(KeyboardHIDType)(&aKbdHID); H();
|
---|
| 695 | #endif
|
---|
[100706] | 696 |
|
---|
[101475] | 697 | PointingHIDType_T aPointingHID;
|
---|
| 698 | hrc = pMachine->COMGETTER(PointingHIDType)(&aPointingHID); H();
|
---|
[100706] | 699 |
|
---|
[101475] | 700 | PCFGMNODE pUsbDevices = NULL;
|
---|
| 701 | vrc = i_configUsb(pMachine, pBusMgr, pRoot, pDevices, KeyboardHIDType_USBKeyboard, aPointingHID, &pUsbDevices);
|
---|
[100706] | 702 |
|
---|
| 703 | /*
|
---|
[101475] | 704 | * Storage controllers.
|
---|
[100706] | 705 | */
|
---|
[101475] | 706 | bool fFdcEnabled = false;
|
---|
| 707 | vrc = i_configStorageCtrls(pMachine, pBusMgr, pVMM, pUVM,
|
---|
| 708 | pDevices, pUsbDevices, NULL /*pBiosCfg*/, &fFdcEnabled); VRC();
|
---|
[100706] | 709 |
|
---|
[100716] | 710 | /*
|
---|
| 711 | * Network adapters
|
---|
| 712 | */
|
---|
[101475] | 713 | std::list<BootNic> llBootNics;
|
---|
| 714 | vrc = i_configNetworkCtrls(pMachine, pPlatformProperties, chipsetType, pBusMgr,
|
---|
| 715 | pVMM, pUVM, pDevices, llBootNics); VRC();
|
---|
[99913] | 716 |
|
---|
[101475] | 717 | /*
|
---|
| 718 | * The VMM device.
|
---|
| 719 | */
|
---|
| 720 | vrc = i_configVmmDev(pMachine, pBusMgr, pDevices, true /*fMmioReq*/); VRC();
|
---|
[100716] | 721 |
|
---|
[99913] | 722 | /*
|
---|
[101475] | 723 | * Audio configuration.
|
---|
[99913] | 724 | */
|
---|
[101475] | 725 | bool fAudioEnabled = false;
|
---|
| 726 | vrc = i_configAudioCtrl(virtualBox, pMachine, pBusMgr, pDevices,
|
---|
| 727 | false /*fOsXGuest*/, &fAudioEnabled); VRC();
|
---|
[99913] | 728 | }
|
---|
| 729 | catch (ConfigError &x)
|
---|
| 730 | {
|
---|
[100041] | 731 | RTFdtDestroy(hFdt);
|
---|
| 732 |
|
---|
[99913] | 733 | // InsertConfig threw something:
|
---|
| 734 | pVMM->pfnVMR3SetError(pUVM, x.m_vrc, RT_SRC_POS, "Caught ConfigError: %Rrc - %s", x.m_vrc, x.what());
|
---|
| 735 | return x.m_vrc;
|
---|
| 736 | }
|
---|
| 737 | catch (HRESULT hrcXcpt)
|
---|
| 738 | {
|
---|
[100041] | 739 | RTFdtDestroy(hFdt);
|
---|
[99913] | 740 | AssertLogRelMsgFailedReturn(("hrc=%Rhrc\n", hrcXcpt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
|
---|
| 741 | }
|
---|
| 742 |
|
---|
| 743 | #ifdef VBOX_WITH_EXTPACK
|
---|
| 744 | /*
|
---|
| 745 | * Call the extension pack hooks if everything went well thus far.
|
---|
| 746 | */
|
---|
| 747 | if (RT_SUCCESS(vrc))
|
---|
| 748 | {
|
---|
| 749 | pAlock->release();
|
---|
| 750 | vrc = mptrExtPackManager->i_callAllVmConfigureVmmHooks(this, pVM, pVMM);
|
---|
| 751 | pAlock->acquire();
|
---|
| 752 | }
|
---|
| 753 | #endif
|
---|
| 754 |
|
---|
[101515] | 755 | #if 0
|
---|
[100706] | 756 | vrc = RTFdtNodeAdd(hFdt, "chosen"); VRC();
|
---|
| 757 | vrc = RTFdtNodePropertyAddString( hFdt, "stdout-path", "pl011@9000000"); VRC();
|
---|
| 758 | vrc = RTFdtNodePropertyAddString( hFdt, "stdin-path", "pl011@9000000"); VRC();
|
---|
[100707] | 759 | vrc = RTFdtNodeFinalize(hFdt);
|
---|
[101515] | 760 | #endif
|
---|
[100706] | 761 |
|
---|
[100041] | 762 | /* Finalize the FDT and add it to the resource store. */
|
---|
| 763 | vrc = RTFdtFinalize(hFdt);
|
---|
| 764 | AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
|
---|
| 765 |
|
---|
[101443] | 766 | RTVFSFILE hVfsFileDesc = NIL_RTVFSFILE;
|
---|
| 767 | vrc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, 0 /*cbEstimate*/, &hVfsFileDesc);
|
---|
[100041] | 768 | AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
|
---|
[101443] | 769 | RTVFSIOSTREAM hVfsIosDesc = RTVfsFileToIoStream(hVfsFileDesc);
|
---|
| 770 | AssertRelease(hVfsIosDesc != NIL_RTVFSIOSTREAM);
|
---|
[100041] | 771 |
|
---|
[101443] | 772 | /* Initialize the VBox platform descriptor. */
|
---|
| 773 | VBOXPLATFORMARMV8 ArmV8Platform; RT_ZERO(ArmV8Platform);
|
---|
| 774 |
|
---|
| 775 | vrc = RTFdtDumpToVfsIoStrm(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, hVfsIosDesc, NULL /*pErrInfo*/);
|
---|
[100041] | 776 | if (RT_SUCCESS(vrc))
|
---|
[101443] | 777 | vrc = RTVfsFileQuerySize(hVfsFileDesc, &ArmV8Platform.cbFdt);
|
---|
[100041] | 778 | AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
|
---|
| 779 |
|
---|
[101443] | 780 | vrc = RTVfsIoStrmZeroFill(hVfsIosDesc, (RTFOFF)(RT_ALIGN_64(ArmV8Platform.cbFdt, _64K) - ArmV8Platform.cbFdt));
|
---|
| 781 | AssertRCReturn(vrc, vrc);
|
---|
| 782 |
|
---|
[102517] | 783 | RTGCPHYS GCPhysMmioStart;
|
---|
| 784 | RTGCPHYS cbMmio;
|
---|
| 785 | hrc = pResMgr->queryMmioRegion(&GCPhysMmioStart, &cbMmio);
|
---|
| 786 | Assert(SUCCEEDED(hrc));
|
---|
| 787 |
|
---|
| 788 | RTGCPHYS GCPhysMmio32Start;
|
---|
| 789 | RTGCPHYS cbMmio32;
|
---|
| 790 | hrc = pResMgr->queryMmio32Region(&GCPhysMmio32Start, &cbMmio32);
|
---|
| 791 | Assert(SUCCEEDED(hrc));
|
---|
| 792 |
|
---|
[101443] | 793 | ArmV8Platform.u32Magic = VBOXPLATFORMARMV8_MAGIC;
|
---|
| 794 | ArmV8Platform.u32Version = VBOXPLATFORMARMV8_VERSION;
|
---|
| 795 | ArmV8Platform.cbDesc = sizeof(ArmV8Platform);
|
---|
| 796 | ArmV8Platform.fFlags = 0;
|
---|
[102517] | 797 | ArmV8Platform.u64PhysAddrRamBase = GCPhysRam;
|
---|
[101443] | 798 | ArmV8Platform.cbRamBase = cbRam;
|
---|
| 799 | ArmV8Platform.u64OffBackFdt = RT_ALIGN_64(ArmV8Platform.cbFdt, _64K);
|
---|
| 800 | ArmV8Platform.cbFdt = RT_ALIGN_64(ArmV8Platform.cbFdt, _64K);
|
---|
| 801 | ArmV8Platform.u64OffBackAcpiXsdp = 0;
|
---|
| 802 | ArmV8Platform.cbAcpiXsdp = 0;
|
---|
| 803 | ArmV8Platform.u64OffBackUefiRom = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform);
|
---|
| 804 | ArmV8Platform.cbUefiRom = _64M; /** @todo Fixed reservation but the ROM region is usually much smaller. */
|
---|
[102517] | 805 | ArmV8Platform.u64OffBackMmio = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform) - GCPhysMmioStart;
|
---|
| 806 | ArmV8Platform.cbMmio = cbMmio;
|
---|
| 807 | ArmV8Platform.u64OffBackMmio32 = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform) - GCPhysMmio32Start;
|
---|
| 808 | ArmV8Platform.cbMmio32 = cbMmio32;
|
---|
[101443] | 809 |
|
---|
| 810 | /* Add the VBox platform descriptor to the resource store. */
|
---|
| 811 | vrc = RTVfsIoStrmWrite(hVfsIosDesc, &ArmV8Platform, sizeof(ArmV8Platform), true /*fBlocking*/, NULL /*pcbWritten*/);
|
---|
| 812 | RTVfsIoStrmRelease(hVfsIosDesc);
|
---|
| 813 | vrc = mptrResourceStore->i_addItem("resources", "VBoxArmV8Desc", hVfsFileDesc);
|
---|
| 814 | RTVfsFileRelease(hVfsFileDesc);
|
---|
| 815 | AssertRCReturn(vrc, vrc);
|
---|
| 816 |
|
---|
[100041] | 817 | /* Dump the DTB for debugging purposes if requested. */
|
---|
| 818 | Bstr DtbDumpVal;
|
---|
| 819 | hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/DumpDtb").raw(),
|
---|
| 820 | DtbDumpVal.asOutParam());
|
---|
| 821 | if ( hrc == S_OK
|
---|
| 822 | && DtbDumpVal.isNotEmpty())
|
---|
| 823 | {
|
---|
| 824 | vrc = RTFdtDumpToFile(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, Utf8Str(DtbDumpVal).c_str(), NULL /*pErrInfo*/);
|
---|
| 825 | AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
|
---|
| 826 | }
|
---|
| 827 |
|
---|
[102517] | 828 | delete pResMgr; /* Delete the address/interrupt assignment manager. */
|
---|
[100041] | 829 |
|
---|
[99913] | 830 | /*
|
---|
| 831 | * Apply the CFGM overlay.
|
---|
| 832 | */
|
---|
| 833 | if (RT_SUCCESS(vrc))
|
---|
| 834 | vrc = i_configCfgmOverlay(pRoot, virtualBox, pMachine);
|
---|
| 835 |
|
---|
| 836 | /*
|
---|
| 837 | * Dump all extradata API settings tweaks, both global and per VM.
|
---|
| 838 | */
|
---|
| 839 | if (RT_SUCCESS(vrc))
|
---|
| 840 | vrc = i_configDumpAPISettingsTweaks(virtualBox, pMachine);
|
---|
| 841 |
|
---|
| 842 | #undef H
|
---|
| 843 |
|
---|
| 844 | pAlock->release(); /* Avoid triggering the lock order inversion check. */
|
---|
| 845 |
|
---|
| 846 | /*
|
---|
| 847 | * Register VM state change handler.
|
---|
| 848 | */
|
---|
| 849 | int vrc2 = pVMM->pfnVMR3AtStateRegister(pUVM, Console::i_vmstateChangeCallback, this);
|
---|
| 850 | AssertRC(vrc2);
|
---|
| 851 | if (RT_SUCCESS(vrc))
|
---|
| 852 | vrc = vrc2;
|
---|
| 853 |
|
---|
| 854 | /*
|
---|
| 855 | * Register VM runtime error handler.
|
---|
| 856 | */
|
---|
| 857 | vrc2 = pVMM->pfnVMR3AtRuntimeErrorRegister(pUVM, Console::i_atVMRuntimeErrorCallback, this);
|
---|
| 858 | AssertRC(vrc2);
|
---|
| 859 | if (RT_SUCCESS(vrc))
|
---|
| 860 | vrc = vrc2;
|
---|
| 861 |
|
---|
| 862 | pAlock->acquire();
|
---|
| 863 |
|
---|
| 864 | LogFlowFunc(("vrc = %Rrc\n", vrc));
|
---|
| 865 | LogFlowFuncLeave();
|
---|
| 866 |
|
---|
| 867 | return vrc;
|
---|
| 868 | }
|
---|
[99925] | 869 | #endif /* !VBOX_WITH_VIRT_ARMV8 */
|
---|
| 870 |
|
---|