VirtualBox

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

Last change on this file since 101477 was 101477, checked in by vboxsync, 19 months ago

Main/ConsoleImpl: Use the common method to configure the graphics controller respecting monitor count and VRAM settings, bugref:10528

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.7 KB
Line 
1/* $Id: ConsoleImplConfigArmV8.cpp 101477 2023-10-17 12:09:33Z 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.215389.xyz.
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 /*
608 * VMSVGA compliant graphics controller.
609 */
610 if ( enmGraphicsController != GraphicsControllerType_QemuRamFB
611 && enmGraphicsController != GraphicsControllerType_Null)
612 {
613 vrc = i_configGraphicsController(pDevices, enmGraphicsController, pBusMgr, pMachine,
614 pGraphicsAdapter, firmwareSettings,
615 true /*fForceVmSvga3*/, false /*fExposeLegacyVga*/); VRC();
616 }
617
618 /*
619 * The USB Controllers and input devices.
620 */
621#if 0 /** @todo Make us of this and disallow PS/2 for ARM VMs for now. */
622 KeyboardHIDType_T aKbdHID;
623 hrc = pMachine->COMGETTER(KeyboardHIDType)(&aKbdHID); H();
624#endif
625
626 PointingHIDType_T aPointingHID;
627 hrc = pMachine->COMGETTER(PointingHIDType)(&aPointingHID); H();
628
629 PCFGMNODE pUsbDevices = NULL;
630 vrc = i_configUsb(pMachine, pBusMgr, pRoot, pDevices, KeyboardHIDType_USBKeyboard, aPointingHID, &pUsbDevices);
631
632 /*
633 * Storage controllers.
634 */
635 bool fFdcEnabled = false;
636 vrc = i_configStorageCtrls(pMachine, pBusMgr, pVMM, pUVM,
637 pDevices, pUsbDevices, NULL /*pBiosCfg*/, &fFdcEnabled); VRC();
638
639 /*
640 * Network adapters
641 */
642 std::list<BootNic> llBootNics;
643 vrc = i_configNetworkCtrls(pMachine, pPlatformProperties, chipsetType, pBusMgr,
644 pVMM, pUVM, pDevices, llBootNics); VRC();
645
646 /*
647 * The VMM device.
648 */
649 vrc = i_configVmmDev(pMachine, pBusMgr, pDevices, true /*fMmioReq*/); VRC();
650
651 /*
652 * Audio configuration.
653 */
654 bool fAudioEnabled = false;
655 vrc = i_configAudioCtrl(virtualBox, pMachine, pBusMgr, pDevices,
656 false /*fOsXGuest*/, &fAudioEnabled); VRC();
657 }
658 catch (ConfigError &x)
659 {
660 RTFdtDestroy(hFdt);
661
662 // InsertConfig threw something:
663 pVMM->pfnVMR3SetError(pUVM, x.m_vrc, RT_SRC_POS, "Caught ConfigError: %Rrc - %s", x.m_vrc, x.what());
664 return x.m_vrc;
665 }
666 catch (HRESULT hrcXcpt)
667 {
668 RTFdtDestroy(hFdt);
669 AssertLogRelMsgFailedReturn(("hrc=%Rhrc\n", hrcXcpt), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
670 }
671
672#ifdef VBOX_WITH_EXTPACK
673 /*
674 * Call the extension pack hooks if everything went well thus far.
675 */
676 if (RT_SUCCESS(vrc))
677 {
678 pAlock->release();
679 vrc = mptrExtPackManager->i_callAllVmConfigureVmmHooks(this, pVM, pVMM);
680 pAlock->acquire();
681 }
682#endif
683
684 vrc = RTFdtNodeAdd(hFdt, "chosen"); VRC();
685 vrc = RTFdtNodePropertyAddString( hFdt, "stdout-path", "pl011@9000000"); VRC();
686 vrc = RTFdtNodePropertyAddString( hFdt, "stdin-path", "pl011@9000000"); VRC();
687 vrc = RTFdtNodeFinalize(hFdt);
688
689 /* Finalize the FDT and add it to the resource store. */
690 vrc = RTFdtFinalize(hFdt);
691 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
692
693 RTVFSFILE hVfsFileDesc = NIL_RTVFSFILE;
694 vrc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, 0 /*cbEstimate*/, &hVfsFileDesc);
695 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
696 RTVFSIOSTREAM hVfsIosDesc = RTVfsFileToIoStream(hVfsFileDesc);
697 AssertRelease(hVfsIosDesc != NIL_RTVFSIOSTREAM);
698
699 /* Initialize the VBox platform descriptor. */
700 VBOXPLATFORMARMV8 ArmV8Platform; RT_ZERO(ArmV8Platform);
701
702 vrc = RTFdtDumpToVfsIoStrm(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, hVfsIosDesc, NULL /*pErrInfo*/);
703 if (RT_SUCCESS(vrc))
704 vrc = RTVfsFileQuerySize(hVfsFileDesc, &ArmV8Platform.cbFdt);
705 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
706
707 vrc = RTVfsIoStrmZeroFill(hVfsIosDesc, (RTFOFF)(RT_ALIGN_64(ArmV8Platform.cbFdt, _64K) - ArmV8Platform.cbFdt));
708 AssertRCReturn(vrc, vrc);
709
710 ArmV8Platform.u32Magic = VBOXPLATFORMARMV8_MAGIC;
711 ArmV8Platform.u32Version = VBOXPLATFORMARMV8_VERSION;
712 ArmV8Platform.cbDesc = sizeof(ArmV8Platform);
713 ArmV8Platform.fFlags = 0;
714 ArmV8Platform.u64PhysAddrRamBase = UINT64_C(0x40000000);
715 ArmV8Platform.cbRamBase = cbRam;
716 ArmV8Platform.u64OffBackFdt = RT_ALIGN_64(ArmV8Platform.cbFdt, _64K);
717 ArmV8Platform.cbFdt = RT_ALIGN_64(ArmV8Platform.cbFdt, _64K);
718 ArmV8Platform.u64OffBackAcpiXsdp = 0;
719 ArmV8Platform.cbAcpiXsdp = 0;
720 ArmV8Platform.u64OffBackUefiRom = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform);
721 ArmV8Platform.cbUefiRom = _64M; /** @todo Fixed reservation but the ROM region is usually much smaller. */
722 ArmV8Platform.u64OffBackMmio = GCPhysTopOfAddrSpace - sizeof(ArmV8Platform) - 0x08000000; /** @todo Start of generic MMIO area containing the GIC,UART,RTC, etc. Will be changed soon */
723 ArmV8Platform.cbMmio = _128M;
724
725 /* Add the VBox platform descriptor to the resource store. */
726 vrc = RTVfsIoStrmWrite(hVfsIosDesc, &ArmV8Platform, sizeof(ArmV8Platform), true /*fBlocking*/, NULL /*pcbWritten*/);
727 RTVfsIoStrmRelease(hVfsIosDesc);
728 vrc = mptrResourceStore->i_addItem("resources", "VBoxArmV8Desc", hVfsFileDesc);
729 RTVfsFileRelease(hVfsFileDesc);
730 AssertRCReturn(vrc, vrc);
731
732 /* Dump the DTB for debugging purposes if requested. */
733 Bstr DtbDumpVal;
734 hrc = mMachine->GetExtraData(Bstr("VBoxInternal2/DumpDtb").raw(),
735 DtbDumpVal.asOutParam());
736 if ( hrc == S_OK
737 && DtbDumpVal.isNotEmpty())
738 {
739 vrc = RTFdtDumpToFile(hFdt, RTFDTTYPE_DTB, 0 /*fFlags*/, Utf8Str(DtbDumpVal).c_str(), NULL /*pErrInfo*/);
740 AssertRCReturnStmt(vrc, RTFdtDestroy(hFdt), vrc);
741 }
742
743
744 /*
745 * Apply the CFGM overlay.
746 */
747 if (RT_SUCCESS(vrc))
748 vrc = i_configCfgmOverlay(pRoot, virtualBox, pMachine);
749
750 /*
751 * Dump all extradata API settings tweaks, both global and per VM.
752 */
753 if (RT_SUCCESS(vrc))
754 vrc = i_configDumpAPISettingsTweaks(virtualBox, pMachine);
755
756#undef H
757
758 pAlock->release(); /* Avoid triggering the lock order inversion check. */
759
760 /*
761 * Register VM state change handler.
762 */
763 int vrc2 = pVMM->pfnVMR3AtStateRegister(pUVM, Console::i_vmstateChangeCallback, this);
764 AssertRC(vrc2);
765 if (RT_SUCCESS(vrc))
766 vrc = vrc2;
767
768 /*
769 * Register VM runtime error handler.
770 */
771 vrc2 = pVMM->pfnVMR3AtRuntimeErrorRegister(pUVM, Console::i_atVMRuntimeErrorCallback, this);
772 AssertRC(vrc2);
773 if (RT_SUCCESS(vrc))
774 vrc = vrc2;
775
776 pAlock->acquire();
777
778 LogFlowFunc(("vrc = %Rrc\n", vrc));
779 LogFlowFuncLeave();
780
781 return vrc;
782}
783#endif /* !VBOX_WITH_VIRT_ARMV8 */
784
Note: See TracBrowser for help on using the repository browser.

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