VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/ConsoleImplConfigArmV8.cpp@ 105600

Last change on this file since 105600 was 105600, checked in by vboxsync, 7 months ago

VMM/ARM: Move the VBox ARMv8 platform descriptor from the end of the address space right after the UEFI region, bugref:10746

The original solution was to avoid as many hardcoded addresses as possible by placing the VBox region descriptor right at the end
of the guest physical address space. This turned out to be a bad idea because on M3 the host maximum physical address width and
guest maxmium physical address width differ so mapping the platform descriptor fails. Also saved states would not be portable if
a saved state is mvoed between systems with different physical address widths.
The solution is to move the platform descriptor right after the UEFI region and move the MMIO region, which grew from top to bottom
to start right after the base RAM region and grow upwards.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette