VirtualBox

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

Last change on this file since 101475 was 101475, checked in by vboxsync, 17 months ago

Main/src-client/ConsoleImplConfigArmV8.cpp: Get rid of most of the static config and use the common constructors for the different sub-systems, bugref:10528

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.4 KB
Line 
1/* $Id: ConsoleImplConfigArmV8.cpp 101475 2023-10-17 11:56:40Z 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#ifdef VBOX_WITH_EXTPACK
70# include "ExtPackManagerImpl.h"
71#endif
72
73
74/*********************************************************************************************************************************
75* Internal Functions *
76*********************************************************************************************************************************/
77
78/* Darwin compile kludge */
79#undef PVM
80
81#ifdef VBOX_WITH_VIRT_ARMV8
82/**
83 * Worker for configConstructor.
84 *
85 * @return VBox status code.
86 * @param pUVM The user mode VM handle.
87 * @param pVM The cross context VM handle.
88 * @param pVMM The VMM vtable.
89 * @param pAlock The automatic lock instance. This is for when we have
90 * to leave it in order to avoid deadlocks (ext packs and
91 * more).
92 *
93 * @todo This is a big hack at the moment and provides a static VM config to work with, will be adjusted later
94 * on to adhere to the VM config when sorting out the API bits.
95 */
96int Console::i_configConstructorArmV8(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, AutoWriteLock *pAlock)
97{
98 RT_NOREF(pVM /* when everything is disabled */);
99 ComPtr<IMachine> pMachine = i_machine();
100
101 HRESULT hrc;
102 Utf8Str strTmp;
103 Bstr bstr;
104
105 RTFDT hFdt = NIL_RTFDT;
106 int vrc = RTFdtCreateEmpty(&hFdt);
107 AssertRCReturn(vrc, vrc);
108
109#define H() AssertLogRelMsgReturnStmt(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), RTFdtDestroy(hFdt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR)
110#define VRC() AssertLogRelMsgReturnStmt(RT_SUCCESS(vrc), ("vrc=%Rrc\n", vrc), RTFdtDestroy(hFdt), vrc)
111
112 /** @todo Find a way to figure it out before CPUM is set up, can't use CPUMGetGuestAddrWidths() and on macOS we need
113 * access to Hypervisor.framework to query the ID registers (Linux can in theory parse /proc/cpuinfo, no idea for Windows). */
114 RTGCPHYS GCPhysTopOfAddrSpace = RT_BIT_64(36);
115
116 /*
117 * Get necessary objects and frequently used parameters.
118 */
119 ComPtr<IVirtualBox> virtualBox;
120 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
121
122 ComPtr<IHost> host;
123 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
124
125 PlatformArchitecture_T platformArchHost;
126 hrc = host->COMGETTER(Architecture)(&platformArchHost); H();
127
128 ComPtr<ISystemProperties> systemProperties;
129 hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
130
131 ComPtr<IFirmwareSettings> firmwareSettings;
132 hrc = pMachine->COMGETTER(FirmwareSettings)(firmwareSettings.asOutParam()); H();
133
134 ComPtr<INvramStore> nvramStore;
135 hrc = pMachine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam()); H();
136
137 hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H();
138 RTUUID HardwareUuid;
139 vrc = RTUuidFromUtf16(&HardwareUuid, bstr.raw());
140 AssertRCReturn(vrc, vrc);
141
142 ULONG cRamMBs;
143 hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
144 uint64_t const cbRam = cRamMBs * (uint64_t)_1M;
145
146 ComPtr<IPlatform> platform;
147 hrc = pMachine->COMGETTER(Platform)(platform.asOutParam()); H();
148
149 /* Note: Should be guarded by VBOX_WITH_VIRT_ARMV8, but we check this anyway here. */
150#if 1 /* For now we only support running ARM VMs on ARM hosts. */
151 PlatformArchitecture_T platformArchMachine;
152 hrc = platform->COMGETTER(Architecture)(&platformArchMachine); H();
153 if (platformArchMachine != platformArchHost)
154 return pVMM->pfnVMR3SetError(pUVM, VERR_PLATFORM_ARCH_NOT_SUPPORTED, RT_SRC_POS,
155 N_("VM platform architecture (%s) not supported on this host (%s)."),
156 Global::stringifyPlatformArchitecture(platformArchMachine),
157 Global::stringifyPlatformArchitecture(platformArchHost));
158#endif
159
160 ComPtr<IPlatformProperties> pPlatformProperties;
161 hrc = platform->COMGETTER(Properties)(pPlatformProperties.asOutParam()); H();
162
163 ChipsetType_T chipsetType;
164 hrc = platform->COMGETTER(ChipsetType)(&chipsetType); H();
165
166 ULONG cCpus = 1;
167 hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
168 Assert(cCpus);
169
170 ULONG ulCpuExecutionCap = 100;
171 hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H();
172
173 LogRel(("Guest architecture: ARM\n"));
174
175 Bstr osTypeId;
176 hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
177 LogRel(("Guest OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
178
179 BusAssignmentManager *pBusMgr = mBusMgr = BusAssignmentManager::createInstance(pVMM, chipsetType, IommuType_None);
180
181 /*
182 * Get root node first.
183 * This is the only node in the tree.
184 */
185 PCFGMNODE pRoot = pVMM->pfnCFGMR3GetRootU(pUVM);
186 Assert(pRoot);
187
188 // catching throws from InsertConfigString and friends.
189 try
190 {
191
192 /*
193 * Set the root (and VMM) level values.
194 */
195 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H();
196 InsertConfigString(pRoot, "Name", bstr);
197 InsertConfigBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid));
198 InsertConfigInteger(pRoot, "NumCPUs", cCpus);
199 InsertConfigInteger(pRoot, "CpuExecutionCap", ulCpuExecutionCap);
200 InsertConfigInteger(pRoot, "TimerMillies", 10);
201
202 uint32_t idPHandleIntCtrl = RTFdtPHandleAllocate(hFdt);
203 Assert(idPHandleIntCtrl != UINT32_MAX);
204 uint32_t idPHandleIntCtrlMsi = RTFdtPHandleAllocate(hFdt);
205 Assert(idPHandleIntCtrlMsi != UINT32_MAX); RT_NOREF(idPHandleIntCtrlMsi);
206 uint32_t idPHandleAbpPClk = RTFdtPHandleAllocate(hFdt);
207 Assert(idPHandleAbpPClk != UINT32_MAX);
208 uint32_t idPHandleGpio = RTFdtPHandleAllocate(hFdt);
209 Assert(idPHandleGpio != UINT32_MAX);
210
211 uint32_t aidPHandleCpus[VMM_MAX_CPU_COUNT];
212 for (uint32_t i = 0; i < cCpus; i++)
213 {
214 aidPHandleCpus[i] = RTFdtPHandleAllocate(hFdt);
215 Assert(aidPHandleCpus[i] != UINT32_MAX);
216 }
217
218 vrc = RTFdtNodePropertyAddU32( hFdt, "interrupt-parent", idPHandleIntCtrl); VRC();
219 vrc = RTFdtNodePropertyAddString(hFdt, "model", "linux,dummy-virt"); VRC();
220 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
221 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
222 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "linux,dummy-virt"); VRC();
223
224 /* Configure the Power State Coordination Interface. */
225 vrc = RTFdtNodeAdd(hFdt, "psci"); VRC();
226 vrc = RTFdtNodePropertyAddU32( hFdt, "migrate", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_MIGRATE)); VRC();
227 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_on", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_ON)); VRC();
228 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_off", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_OFF)); VRC();
229 vrc = RTFdtNodePropertyAddU32( hFdt, "cpu_suspend", ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_CPU_SUSPEND)); VRC();
230 vrc = RTFdtNodePropertyAddString(hFdt, "method", "hvc"); VRC();
231 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 3,
232 "arm,psci-1.0", "arm,psci-0.2", "arm,psci"); VRC();
233 vrc = RTFdtNodeFinalize(hFdt); VRC();
234
235 /* Configure some misc system wide properties. */
236 vrc = RTFdtNodeAdd(hFdt, "chosen"); VRC();
237 vrc = RTFdtNodePropertyAddString(hFdt, "stdout-path", "/pl011@9000000"); VRC();
238 vrc = RTFdtNodeFinalize(hFdt);
239
240 /* Configure the timer and clock. */
241 vrc = RTFdtNodeAdd(hFdt, "timer"); VRC();
242 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 12,
243 0x01, 0x0d, 0x104,
244 0x01, 0x0e, 0x104,
245 0x01, 0x0b, 0x104,
246 0x01, 0x0a, 0x104); VRC();
247 vrc = RTFdtNodePropertyAddEmpty( hFdt, "always-on"); VRC();
248 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,armv7-timer"); VRC();
249 vrc = RTFdtNodeFinalize(hFdt);
250
251 vrc = RTFdtNodeAdd(hFdt, "apb-clk"); VRC();
252 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleAbpPClk); VRC();
253 vrc = RTFdtNodePropertyAddString( hFdt, "clock-output-names", "clk24mhz"); VRC();
254 vrc = RTFdtNodePropertyAddU32( hFdt, "clock-frequency", 24 * 1000 * 1000); VRC();
255 vrc = RTFdtNodePropertyAddU32( hFdt, "#clock-cells", 0); VRC();
256 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "fixed-clock"); VRC();
257 vrc = RTFdtNodeFinalize(hFdt);
258
259 /* Configure gpio keys (non functional at the moment). */
260 vrc = RTFdtNodeAdd(hFdt, "gpio-keys"); VRC();
261 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "gpio-keys"); VRC();
262
263 vrc = RTFdtNodeAdd(hFdt, "poweroff"); VRC();
264 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "gpios", 3, idPHandleGpio, 3, 0); VRC();
265 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,code", 0x74); VRC();
266 vrc = RTFdtNodePropertyAddString( hFdt, "label", "GPIO Key Poweroff"); VRC();
267 vrc = RTFdtNodeFinalize(hFdt); VRC();
268
269 vrc = RTFdtNodeFinalize(hFdt); VRC();
270
271 /*
272 * NEM
273 */
274 PCFGMNODE pNEM;
275 InsertConfigNode(pRoot, "NEM", &pNEM);
276
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
289 PCFGMNODE pMemRegion = NULL;
290 InsertConfigNode(pMem, "Conventional", &pMemRegion);
291 InsertConfigInteger(pMemRegion, "GCPhysStart", 0x40000000);
292 InsertConfigInteger(pMemRegion, "Size", cbRam);
293
294 vrc = RTFdtNodeAddF(hFdt, "memory@%RX32", 0x40000000); VRC();
295 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4,
296 0, 0x40000000,
297 (uint32_t)(cbRam >> 32), cbRam & UINT32_MAX); VRC();
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();
323 vrc = RTFdtNodePropertyAddU32(hFdt, "reg", i); VRC();
324 vrc = RTFdtNodePropertyAddString(hFdt, "compatible", "arm,cortex-a15"); VRC();
325 vrc = RTFdtNodePropertyAddString(hFdt, "device_type", "cpu"); VRC();
326 if (cCpus > 1)
327 {
328 vrc = RTFdtNodePropertyAddString(hFdt, "enable-method", "psci"); VRC();
329 }
330 vrc = RTFdtNodeFinalize(hFdt); VRC();
331 }
332
333 vrc = RTFdtNodeFinalize(hFdt); VRC();
334
335
336 /*
337 * PDM config.
338 * Load drivers in VBoxC.[so|dll]
339 */
340 vrc = i_configPdm(pMachine, pVMM, pUVM, pRoot); VRC();
341
342
343 /*
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 /*
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
362 InsertConfigNode(pDevices, "platform", &pDev);
363 InsertConfigNode(pDev, "0", &pInst);
364 InsertConfigNode(pInst, "Config", &pCfg);
365 InsertConfigNode(pInst, "LUN#0", &pLunL0);
366 InsertConfigString(pLunL0, "Driver", "ResourceStore");
367
368 /* Add the resources. */
369 PCFGMNODE pResources = NULL; /* /Devices/efi-armv8/Config/Resources */
370 PCFGMNODE pRes = NULL; /* /Devices/efi-armv8/Config/Resources/<Resource> */
371 InsertConfigString(pCfg, "ResourceNamespace", "resources");
372 InsertConfigNode(pCfg, "Resources", &pResources);
373 InsertConfigNode(pResources, "EfiRom", &pRes);
374 InsertConfigInteger(pRes, "RegisterAsRom", 1);
375 InsertConfigInteger(pRes, "GCPhysLoadAddress", 0);
376
377 /** @todo r=aeichner 32-bit guests and query the firmware type from VBoxSVC. */
378 /*
379 * Firmware.
380 */
381 FirmwareType_T eFwType = FirmwareType_EFI64;
382#ifdef VBOX_WITH_EFI_IN_DD2
383 const char *pszEfiRomFile = eFwType == FirmwareType_EFIDUAL ? "<INVALID>"
384 : eFwType == FirmwareType_EFI32 ? "VBoxEFIAArch32.fd"
385 : "VBoxEFIAArch64.fd";
386 const char *pszKey = "ResourceId";
387#else
388 Utf8Str efiRomFile;
389 vrc = findEfiRom(virtualBox, PlatformArchitecture_ARM, eFwType, &efiRomFile);
390 AssertRCReturn(vrc, vrc);
391 const char *pszEfiRomFile = efiRomFile.c_str();
392 const char *pszKey = "Filename";
393#endif
394 InsertConfigString(pRes, pszKey, pszEfiRomFile);
395
396 InsertConfigNode(pResources, "ArmV8Desc", &pRes);
397 InsertConfigInteger(pRes, "RegisterAsRom", 1);
398 InsertConfigInteger(pRes, "GCPhysLoadAddress", UINT64_MAX); /* End of physical address space. */
399 InsertConfigString(pRes, "ResourceId", "VBoxArmV8Desc");
400
401 vrc = RTFdtNodeAddF(hFdt, "platform-bus@%RX32", 0x0c000000); VRC();
402 vrc = RTFdtNodePropertyAddU32( hFdt, "interrupt-parent", idPHandleIntCtrl); VRC();
403 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 4, 0, 0, 0x0c000000, 0x02000000); VRC();
404 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 1); VRC();
405 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 1); VRC();
406 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
407 "qemu,platform", "simple-bus"); VRC();
408 vrc = RTFdtNodeFinalize(hFdt); VRC();
409
410 InsertConfigNode(pDevices, "gic", &pDev);
411 InsertConfigNode(pDev, "0", &pInst);
412 InsertConfigInteger(pInst, "Trusted", 1);
413 InsertConfigNode(pInst, "Config", &pCfg);
414 InsertConfigInteger(pCfg, "DistributorMmioBase", 0x08000000);
415 InsertConfigInteger(pCfg, "RedistributorMmioBase", 0x080a0000);
416
417 vrc = RTFdtNodeAddF(hFdt, "intc@%RX32", 0x08000000); VRC();
418 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrl); VRC();
419 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 8,
420 0, 0x08000000, 0, 0x10000,
421 0, 0x080a0000, 0, 0xf60000); VRC();
422 vrc = RTFdtNodePropertyAddU32( hFdt, "#redistributor-regions", 1); VRC();
423 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3"); VRC();
424 vrc = RTFdtNodePropertyAddEmpty( hFdt, "ranges"); VRC();
425 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
426 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 2); VRC();
427 vrc = RTFdtNodePropertyAddEmpty( hFdt, "interrupt-controller"); VRC();
428 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 3); VRC();
429
430#if 0
431 vrc = RTFdtNodeAddF(hFdt, "its@%RX32", 0x08080000); VRC();
432 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleIntCtrlMsi); VRC();
433 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x08080000, 0, 0x20000); VRC();
434 vrc = RTFdtNodePropertyAddU32( hFdt, "#msi-cells", 1); VRC();
435 vrc = RTFdtNodePropertyAddEmpty( hFdt, "msi-controller"); VRC();
436 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "arm,gic-v3-its"); VRC();
437 vrc = RTFdtNodeFinalize(hFdt); VRC();
438#endif
439
440 vrc = RTFdtNodeFinalize(hFdt); VRC();
441
442
443 InsertConfigNode(pDevices, "qemu-fw-cfg", &pDev);
444 InsertConfigNode(pDev, "0", &pInst);
445 InsertConfigNode(pInst, "Config", &pCfg);
446 InsertConfigInteger(pCfg, "MmioSize", 4096);
447 InsertConfigInteger(pCfg, "MmioBase", 0x09020000);
448 InsertConfigInteger(pCfg, "DmaEnabled", 1);
449 InsertConfigInteger(pCfg, "QemuRamfbSupport", enmGraphicsController == GraphicsControllerType_QemuRamFB ? 1 : 0);
450 if (enmGraphicsController == GraphicsControllerType_QemuRamFB)
451 {
452 InsertConfigNode(pInst, "LUN#0", &pLunL0);
453 InsertConfigString(pLunL0, "Driver", "MainDisplay");
454 }
455
456 vrc = RTFdtNodeAddF(hFdt, "fw-cfg@%RX32", 0x09020000); VRC();
457 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
458 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09020000, 0, 0x18); VRC();
459 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "qemu,fw-cfg-mmio"); VRC();
460 vrc = RTFdtNodeFinalize(hFdt); VRC();
461
462
463 InsertConfigNode(pDevices, "flash-cfi", &pDev);
464 InsertConfigNode(pDev, "0", &pInst);
465 InsertConfigNode(pInst, "Config", &pCfg);
466 InsertConfigInteger(pCfg, "BaseAddress", 64 * _1M);
467 InsertConfigInteger(pCfg, "Size", 768 * _1K);
468 InsertConfigString(pCfg, "FlashFile", "nvram");
469 /* Attach the NVRAM storage driver. */
470 InsertConfigNode(pInst, "LUN#0", &pLunL0);
471 InsertConfigString(pLunL0, "Driver", "NvramStore");
472
473 vrc = RTFdtNodeAddF(hFdt, "flash@%RX32", 0); VRC();
474 vrc = RTFdtNodePropertyAddU32( hFdt, "bank-width", 4); VRC();
475 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 8,
476 0, 0, 0, 0x04000000,
477 0, 0x04000000, 0, 0x04000000); VRC();
478 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "cfi-flash"); VRC();
479 vrc = RTFdtNodeFinalize(hFdt); VRC();
480
481 InsertConfigNode(pDevices, "arm-pl011", &pDev);
482 for (ULONG ulInstance = 0; ulInstance < 1 /** @todo SchemaDefs::SerialPortCount*/; ++ulInstance)
483 {
484 ComPtr<ISerialPort> serialPort;
485 hrc = pMachine->GetSerialPort(ulInstance, serialPort.asOutParam()); H();
486 BOOL fEnabledSerPort = FALSE;
487 if (serialPort)
488 {
489 hrc = serialPort->COMGETTER(Enabled)(&fEnabledSerPort); H();
490 }
491 if (!fEnabledSerPort)
492 {
493 m_aeSerialPortMode[ulInstance] = PortMode_Disconnected;
494 continue;
495 }
496
497 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst);
498 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
499 InsertConfigNode(pInst, "Config", &pCfg);
500
501 InsertConfigInteger(pCfg, "Irq", 1);
502 InsertConfigInteger(pCfg, "MmioBase", 0x09000000);
503
504 vrc = RTFdtNodeAddF(hFdt, "pl011@%RX32", 0x09000000); VRC();
505 vrc = RTFdtNodePropertyAddStringList(hFdt, "clock-names", 2, "uartclk", "apb_pclk"); VRC();
506 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "clocks", 2,
507 idPHandleAbpPClk, idPHandleAbpPClk); VRC();
508 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x01, 0x04); VRC();
509 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09000000, 0, 0x1000); VRC();
510 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
511 "arm,pl011", "arm,primecell"); VRC();
512 vrc = RTFdtNodeFinalize(hFdt); VRC();
513
514 BOOL fServer;
515 hrc = serialPort->COMGETTER(Server)(&fServer); H();
516 hrc = serialPort->COMGETTER(Path)(bstr.asOutParam()); H();
517
518 PortMode_T eHostMode;
519 hrc = serialPort->COMGETTER(HostMode)(&eHostMode); H();
520
521 m_aeSerialPortMode[ulInstance] = eHostMode;
522 if (eHostMode != PortMode_Disconnected)
523 {
524 vrc = i_configSerialPort(pInst, eHostMode, Utf8Str(bstr).c_str(), RT_BOOL(fServer));
525 if (RT_FAILURE(vrc))
526 return vrc;
527 }
528 }
529
530 InsertConfigNode(pDevices, "arm-pl031-rtc", &pDev);
531 InsertConfigNode(pDev, "0", &pInst);
532 InsertConfigNode(pInst, "Config", &pCfg);
533 InsertConfigInteger(pCfg, "Irq", 2);
534 InsertConfigInteger(pCfg, "MmioBase", 0x09010000);
535 vrc = RTFdtNodeAddF(hFdt, "pl032@%RX32", 0x09010000); VRC();
536 vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
537 vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
538 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x02, 0x04); VRC();
539 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09010000, 0, 0x1000); VRC();
540 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
541 "arm,pl031", "arm,primecell"); VRC();
542 vrc = RTFdtNodeFinalize(hFdt); VRC();
543
544 InsertConfigNode(pDevices, "arm-pl061-gpio",&pDev);
545 InsertConfigNode(pDev, "0", &pInst);
546 InsertConfigNode(pInst, "Config", &pCfg);
547 InsertConfigInteger(pCfg, "Irq", 7);
548 InsertConfigInteger(pCfg, "MmioBase", 0x09030000);
549 vrc = RTFdtNodeAddF(hFdt, "pl061@%RX32", 0x09030000); VRC();
550 vrc = RTFdtNodePropertyAddU32( hFdt, "phandle", idPHandleGpio); VRC();
551 vrc = RTFdtNodePropertyAddString( hFdt, "clock-names", "apb_pclk"); VRC();
552 vrc = RTFdtNodePropertyAddU32( hFdt, "clocks", idPHandleAbpPClk); VRC();
553 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupts", 3, 0x00, 0x07, 0x04); VRC();
554 vrc = RTFdtNodePropertyAddEmpty( hFdt, "gpio-controller"); VRC();
555 vrc = RTFdtNodePropertyAddU32( hFdt, "#gpio-cells", 2); VRC();
556 vrc = RTFdtNodePropertyAddStringList(hFdt, "compatible", 2,
557 "arm,pl061", "arm,primecell"); VRC();
558 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x09030000, 0, 0x1000); VRC();
559 vrc = RTFdtNodeFinalize(hFdt); VRC();
560
561 InsertConfigNode(pDevices, "pci-generic-ecam", &pDev);
562 InsertConfigNode(pDev, "0", &pInst);
563 InsertConfigNode(pInst, "Config", &pCfg);
564 InsertConfigInteger(pCfg, "MmioEcamBase", 0x3f000000);
565 InsertConfigInteger(pCfg, "MmioEcamLength", 0x01000000);
566 InsertConfigInteger(pCfg, "MmioPioBase", 0x3eff0000);
567 InsertConfigInteger(pCfg, "MmioPioSize", 0x0000ffff);
568 InsertConfigInteger(pCfg, "IntPinA", 3);
569 InsertConfigInteger(pCfg, "IntPinB", 4);
570 InsertConfigInteger(pCfg, "IntPinC", 5);
571 InsertConfigInteger(pCfg, "IntPinD", 6);
572 vrc = RTFdtNodeAddF(hFdt, "pcie@%RX32", 0x10000000); VRC();
573 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map-mask", 4, 0x1800, 0, 0, 7); VRC();
574 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "interrupt-map", 16 * 10,
575 0x00, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
576 0x00, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
577 0x00, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
578 0x00, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
579 0x800, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
580 0x800, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
581 0x800, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
582 0x800, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
583 0x1000, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04,
584 0x1000, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
585 0x1000, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
586 0x1000, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
587 0x1800, 0x00, 0x00, 0x01, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x06, 0x04,
588 0x1800, 0x00, 0x00, 0x02, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x03, 0x04,
589 0x1800, 0x00, 0x00, 0x03, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x04, 0x04,
590 0x1800, 0x00, 0x00, 0x04, idPHandleIntCtrl, 0x00, 0x00, 0x00, 0x05, 0x04); VRC();
591 vrc = RTFdtNodePropertyAddU32( hFdt, "#interrupt-cells", 1); VRC();
592 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "ranges", 14,
593 0x1000000, 0, 0, 0, 0x3eff0000, 0, 0x10000,
594 0x2000000, 0, 0x10000000, 0, 0x10000000, 0,
595 0x2eff0000); VRC();
596 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "reg", 4, 0, 0x3f000000, 0, 0x1000000); VRC();
597 /** @todo msi-map */
598 vrc = RTFdtNodePropertyAddEmpty( hFdt, "dma-coherent"); VRC();
599 vrc = RTFdtNodePropertyAddCellsU32(hFdt, "bus-range", 2, 0, 0xf); VRC();
600 vrc = RTFdtNodePropertyAddU32( hFdt, "linux,pci-domain", 0); VRC();
601 vrc = RTFdtNodePropertyAddU32( hFdt, "#size-cells", 2); VRC();
602 vrc = RTFdtNodePropertyAddU32( hFdt, "#address-cells", 3); VRC();
603 vrc = RTFdtNodePropertyAddString( hFdt, "device_type", "pci"); VRC();
604 vrc = RTFdtNodePropertyAddString( hFdt, "compatible", "pci-host-ecam-generic"); VRC();
605 vrc = RTFdtNodeFinalize(hFdt); VRC();
606
607 if ( enmGraphicsController != GraphicsControllerType_QemuRamFB
608 && enmGraphicsController != GraphicsControllerType_Null)
609 {
610 InsertConfigNode(pDevices, "vga", &pDev);
611 InsertConfigNode(pDev, "0", &pInst);
612 InsertConfigInteger(pInst, "Trusted", 1);
613 hrc = pBusMgr->assignPCIDevice("vga", pInst); H();
614 InsertConfigNode(pInst, "Config", &pCfg);
615 InsertConfigInteger(pCfg, "VRamSize", 32 * _1M);
616 InsertConfigInteger(pCfg, "MonitorCount", 1);
617 i_attachStatusDriver(pInst, DeviceType_Graphics3D);
618 InsertConfigInteger(pCfg, "VMSVGAEnabled", true);
619 InsertConfigInteger(pCfg, "VMSVGAPciBarLayout", true);
620 InsertConfigInteger(pCfg, "VMSVGAPciId", true);
621 InsertConfigInteger(pCfg, "VMSVGA3dEnabled", false);
622 InsertConfigInteger(pCfg, "VmSvga3", true);
623 InsertConfigInteger(pCfg, "VmSvgaExposeLegacyVga", false);
624
625 /* Attach the display. */
626 InsertConfigNode(pInst, "LUN#0", &pLunL0);
627 InsertConfigString(pLunL0, "Driver", "MainDisplay");
628 InsertConfigNode(pLunL0, "Config", &pCfg);
629 }
630
631 /*
632 * The USB Controllers and input devices.
633 */
634#if 0 /** @todo Make us of this and disallow PS/2 for ARM VMs for now. */
635 KeyboardHIDType_T aKbdHID;
636 hrc = pMachine->COMGETTER(KeyboardHIDType)(&aKbdHID); H();
637#endif
638
639 PointingHIDType_T aPointingHID;
640 hrc = pMachine->COMGETTER(PointingHIDType)(&aPointingHID); H();
641
642 PCFGMNODE pUsbDevices = NULL;
643 vrc = i_configUsb(pMachine, pBusMgr, pRoot, pDevices, KeyboardHIDType_USBKeyboard, aPointingHID, &pUsbDevices);
644
645 /*
646 * Storage controllers.
647 */
648 bool fFdcEnabled = false;
649 vrc = i_configStorageCtrls(pMachine, pBusMgr, pVMM, pUVM,
650 pDevices, pUsbDevices, NULL /*pBiosCfg*/, &fFdcEnabled); VRC();
651
652 /*
653 * Network adapters
654 */
655 std::list<BootNic> llBootNics;
656 vrc = i_configNetworkCtrls(pMachine, pPlatformProperties, chipsetType, pBusMgr,
657 pVMM, pUVM, pDevices, llBootNics); VRC();
658
659 /*
660 * The VMM device.
661 */
662 vrc = i_configVmmDev(pMachine, pBusMgr, pDevices, true /*fMmioReq*/); VRC();
663
664 /*
665 * Audio configuration.
666 */
667 bool fAudioEnabled = false;
668 vrc = i_configAudioCtrl(virtualBox, pMachine, pBusMgr, pDevices,
669 false /*fOsXGuest*/, &fAudioEnabled); VRC();
670 }
671 catch (ConfigError &x)
672 {
673 RTFdtDestroy(hFdt);
674
675 // InsertConfig threw something:
676 pVMM->pfnVMR3SetError(pUVM, x.m_vrc, RT_SRC_POS, "Caught ConfigError: %Rrc - %s", x.m_vrc, x.what());
677 return x.m_vrc;
678 }
679 catch (HRESULT hrcXcpt)
680 {
681 RTFdtDestroy(hFdt);
682 AssertLogRelMsgFailedReturn(("hrc=%Rhrc\n", hrcXcpt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
683 }
684
685#ifdef VBOX_WITH_EXTPACK
686 /*
687 * Call the extension pack hooks if everything went well thus far.
688 */
689 if (RT_SUCCESS(vrc))
690 {
691 pAlock->release();
692 vrc = mptrExtPackManager->i_callAllVmConfigureVmmHooks(this, pVM, pVMM);
693 pAlock->acquire();
694 }
695#endif
696
697 vrc = RTFdtNodeAdd(hFdt, "chosen"); VRC();
698 vrc = RTFdtNodePropertyAddString( hFdt, "stdout-path", "pl011@9000000"); VRC();
699 vrc = RTFdtNodePropertyAddString( hFdt, "stdin-path", "pl011@9000000"); VRC();
700 vrc = RTFdtNodeFinalize(hFdt);
701
702 /* Finalize the FDT and add it to the resource store. */
703 vrc = RTFdtFinalize(hFdt);
704 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
705
706 RTVFSFILE hVfsFileDesc = NIL_RTVFSFILE;
707 vrc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, 0 /*cbEstimate*/, &hVfsFileDesc);
708 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
709 RTVFSIOSTREAM hVfsIosDesc = RTVfsFileToIoStream(hVfsFileDesc);
710 AssertRelease(hVfsIosDesc != NIL_RTVFSIOSTREAM);
711
712 /* Initialize the VBox platform descriptor. */
713 VBOXPLATFORMARMV8 ArmV8Platform; RT_ZERO(ArmV8Platform);
714
715 vrc = RTFdtDumpToVfsIoStrm(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, hVfsIosDesc, NULL /*pErrInfo*/);
716 if (RT_SUCCESS(vrc))
717 vrc = RTVfsFileQuerySize(hVfsFileDesc, &ArmV8Platform.cbFdt);
718 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
719
720 vrc = RTVfsIoStrmZeroFill(hVfsIosDesc, (RTFOFF)(RT_ALIGN_64(ArmV8Platform.cbFdt, _64K) - ArmV8Platform.cbFdt));
721 AssertRCReturn(vrc, vrc);
722
723 ArmV8Platform.u32Magic = VBOXPLATFORMARMV8_MAGIC;
724 ArmV8Platform.u32Version = VBOXPLATFORMARMV8_VERSION;
725 ArmV8Platform.cbDesc = sizeof(ArmV8Platform);
726 ArmV8Platform.fFlags = 0;
727 ArmV8Platform.u64PhysAddrRamBase = UINT64_C(0x40000000);
728 ArmV8Platform.cbRamBase = cbRam;
729 ArmV8Platform.u64OffBackFdt = RT_ALIGN_64(ArmV8Platform.cbFdt, _64K);
730 ArmV8Platform.cbFdt = RT_ALIGN_64(ArmV8Platform.cbFdt, _64K);
731 ArmV8Platform.u64OffBackAcpiXsdp = 0;
732 ArmV8Platform.cbAcpiXsdp = 0;
733 ArmV8Platform.u64OffBackUefiRom = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform);
734 ArmV8Platform.cbUefiRom = _64M; /** @todo Fixed reservation but the ROM region is usually much smaller. */
735 ArmV8Platform.u64OffBackMmio = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform) - 0x08000000; /** @todo Start of generic MMIO area containing the GIC,UART,RTC, etc. Will be changed soon */
736 ArmV8Platform.cbMmio = _128M;
737
738 /* Add the VBox platform descriptor to the resource store. */
739 vrc = RTVfsIoStrmWrite(hVfsIosDesc, &ArmV8Platform, sizeof(ArmV8Platform), true /*fBlocking*/, NULL /*pcbWritten*/);
740 RTVfsIoStrmRelease(hVfsIosDesc);
741 vrc = mptrResourceStore->i_addItem("resources", "VBoxArmV8Desc", hVfsFileDesc);
742 RTVfsFileRelease(hVfsFileDesc);
743 AssertRCReturn(vrc, vrc);
744
745 /* Dump the DTB for debugging purposes if requested. */
746 Bstr DtbDumpVal;
747 hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/DumpDtb").raw(),
748 DtbDumpVal.asOutParam());
749 if ( hrc == S_OK
750 && DtbDumpVal.isNotEmpty())
751 {
752 vrc = RTFdtDumpToFile(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, Utf8Str(DtbDumpVal).c_str(), NULL /*pErrInfo*/);
753 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
754 }
755
756
757 /*
758 * Apply the CFGM overlay.
759 */
760 if (RT_SUCCESS(vrc))
761 vrc = i_configCfgmOverlay(pRoot, virtualBox, pMachine);
762
763 /*
764 * Dump all extradata API settings tweaks, both global and per VM.
765 */
766 if (RT_SUCCESS(vrc))
767 vrc = i_configDumpAPISettingsTweaks(virtualBox, pMachine);
768
769#undef H
770
771 pAlock->release(); /* Avoid triggering the lock order inversion check. */
772
773 /*
774 * Register VM state change handler.
775 */
776 int vrc2 = pVMM->pfnVMR3AtStateRegister(pUVM, Console::i_vmstateChangeCallback, this);
777 AssertRC(vrc2);
778 if (RT_SUCCESS(vrc))
779 vrc = vrc2;
780
781 /*
782 * Register VM runtime error handler.
783 */
784 vrc2 = pVMM->pfnVMR3AtRuntimeErrorRegister(pUVM, Console::i_atVMRuntimeErrorCallback, this);
785 AssertRC(vrc2);
786 if (RT_SUCCESS(vrc))
787 vrc = vrc2;
788
789 pAlock->acquire();
790
791 LogFlowFunc(("vrc = %Rrc\n", vrc));
792 LogFlowFuncLeave();
793
794 return vrc;
795}
796#endif /* !VBOX_WITH_VIRT_ARMV8 */
797
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