From 20caac5f3b8c85a24d99e893fb04f22b17006da7 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Tue, 23 Feb 2021 12:22:40 +0100 Subject: [PATCH] Port of VirtualBox 6.1.14 --- .../lib/mk/spec/x86_64/virtualbox6-devices.mk | 160 +++ .../lib/mk/spec/x86_64/virtualbox6-dis.mk | 16 + .../lib/mk/spec/x86_64/virtualbox6-sup.mk | 23 + .../lib/mk/spec/x86_64/virtualbox6-vmm.mk | 140 +++ repos/ports/lib/mk/virtualbox6-apiwrap.mk | 13 + repos/ports/lib/mk/virtualbox6-bios.mk | 41 + repos/ports/lib/mk/virtualbox6-client.mk | 76 ++ repos/ports/lib/mk/virtualbox6-common.inc | 121 ++ repos/ports/lib/mk/virtualbox6-debug.inc | 1 + repos/ports/lib/mk/virtualbox6-liblzf.mk | 10 + repos/ports/lib/mk/virtualbox6-main.mk | 84 ++ repos/ports/lib/mk/virtualbox6-runtime.mk | 131 ++ repos/ports/lib/mk/virtualbox6-storage.mk | 7 + repos/ports/lib/mk/virtualbox6-xml.mk | 26 + repos/ports/lib/mk/virtualbox6-xpcom.mk | 137 ++ repos/ports/lib/mk/virtualbox6-zlib.mk | 9 + repos/ports/ports/virtualbox6.hash | 1 + repos/ports/ports/virtualbox6.port | 280 +++++ repos/ports/recipes/src/vbox6/content.mk | 77 ++ repos/ports/recipes/src/vbox6/hash | 1 + repos/ports/recipes/src/vbox6/used_apis | 16 + repos/ports/run/virtualbox6.run | 300 +++++ repos/ports/run/virtualbox6.vbox | 117 ++ repos/ports/src/virtualbox6/attempt.h | 38 + repos/ports/src/virtualbox6/devices.cc | 67 + repos/ports/src/virtualbox6/drivers.cc | 62 + repos/ports/src/virtualbox6/dummies.cc | 416 ++++++ repos/ports/src/virtualbox6/dynlib.cc | 37 + .../src/virtualbox6/include/GenodeImpl.h | 4 + repos/ports/src/virtualbox6/include/aio.h | 46 + .../virtualbox6/include/dev/acpica/acpiio.h | 41 + .../src/virtualbox6/include/dtrace/VBoxVMM.h | 9 + repos/ports/src/virtualbox6/include/fb.h | 344 +++++ .../src/virtualbox6/include/global_defs.h | 34 + .../src/virtualbox6/include/libc/osreldate.h | 5 + .../src/virtualbox6/include/libc/wchar.h | 21 + .../src/virtualbox6/include/libc/wctype.h | 5 + .../virtualbox6/include/package-generated.h | 9 + .../virtualbox6/include/product-generated.h | 10 + .../ports/src/virtualbox6/include/rpc/types.h | 0 .../virtualbox6/include/version-generated.h | 4 + repos/ports/src/virtualbox6/init.h | 22 + repos/ports/src/virtualbox6/input_adapter.h | 149 +++ repos/ports/src/virtualbox6/libc.cc | 126 ++ repos/ports/src/virtualbox6/main.cc | 373 ++++++ repos/ports/src/virtualbox6/nem.cc | 482 +++++++ .../src/virtualbox6/patches/serial.patch | 60 + repos/ports/src/virtualbox6/patches/series | 1 + repos/ports/src/virtualbox6/pdm.cc | 139 +++ repos/ports/src/virtualbox6/scan_code.h | 94 ++ repos/ports/src/virtualbox6/stub_macros.h | 50 + repos/ports/src/virtualbox6/sup.cc | 763 +++++++++++ repos/ports/src/virtualbox6/sup.h | 34 + repos/ports/src/virtualbox6/sup_drv.cc | 90 ++ repos/ports/src/virtualbox6/sup_drv.h | 77 ++ repos/ports/src/virtualbox6/sup_gip.h | 169 +++ repos/ports/src/virtualbox6/sup_gmm.cc | 197 +++ repos/ports/src/virtualbox6/sup_gmm.h | 201 +++ repos/ports/src/virtualbox6/sup_sem.cc | 124 ++ repos/ports/src/virtualbox6/sup_vm.cc | 102 ++ repos/ports/src/virtualbox6/sup_vm.h | 57 + repos/ports/src/virtualbox6/svm.h | 103 ++ repos/ports/src/virtualbox6/target.mk | 47 + repos/ports/src/virtualbox6/unimpl.cc | 104 ++ repos/ports/src/virtualbox6/util.h | 37 + repos/ports/src/virtualbox6/vcpu.cc | 1111 +++++++++++++++++ repos/ports/src/virtualbox6/vcpu.h | 234 ++++ repos/ports/src/virtualbox6/vcpu_gim.cc | 91 ++ repos/ports/src/virtualbox6/vmx.h | 111 ++ repos/ports/src/virtualbox6/xpcom_stubs.cc | 72 ++ 70 files changed, 8159 insertions(+) create mode 100644 repos/ports/lib/mk/spec/x86_64/virtualbox6-devices.mk create mode 100644 repos/ports/lib/mk/spec/x86_64/virtualbox6-dis.mk create mode 100644 repos/ports/lib/mk/spec/x86_64/virtualbox6-sup.mk create mode 100644 repos/ports/lib/mk/spec/x86_64/virtualbox6-vmm.mk create mode 100644 repos/ports/lib/mk/virtualbox6-apiwrap.mk create mode 100644 repos/ports/lib/mk/virtualbox6-bios.mk create mode 100644 repos/ports/lib/mk/virtualbox6-client.mk create mode 100644 repos/ports/lib/mk/virtualbox6-common.inc create mode 100644 repos/ports/lib/mk/virtualbox6-debug.inc create mode 100644 repos/ports/lib/mk/virtualbox6-liblzf.mk create mode 100644 repos/ports/lib/mk/virtualbox6-main.mk create mode 100644 repos/ports/lib/mk/virtualbox6-runtime.mk create mode 100644 repos/ports/lib/mk/virtualbox6-storage.mk create mode 100644 repos/ports/lib/mk/virtualbox6-xml.mk create mode 100644 repos/ports/lib/mk/virtualbox6-xpcom.mk create mode 100644 repos/ports/lib/mk/virtualbox6-zlib.mk create mode 100644 repos/ports/ports/virtualbox6.hash create mode 100644 repos/ports/ports/virtualbox6.port create mode 100644 repos/ports/recipes/src/vbox6/content.mk create mode 100644 repos/ports/recipes/src/vbox6/hash create mode 100644 repos/ports/recipes/src/vbox6/used_apis create mode 100644 repos/ports/run/virtualbox6.run create mode 100644 repos/ports/run/virtualbox6.vbox create mode 100644 repos/ports/src/virtualbox6/attempt.h create mode 100644 repos/ports/src/virtualbox6/devices.cc create mode 100644 repos/ports/src/virtualbox6/drivers.cc create mode 100644 repos/ports/src/virtualbox6/dummies.cc create mode 100644 repos/ports/src/virtualbox6/dynlib.cc create mode 100644 repos/ports/src/virtualbox6/include/GenodeImpl.h create mode 100644 repos/ports/src/virtualbox6/include/aio.h create mode 100644 repos/ports/src/virtualbox6/include/dev/acpica/acpiio.h create mode 100644 repos/ports/src/virtualbox6/include/dtrace/VBoxVMM.h create mode 100644 repos/ports/src/virtualbox6/include/fb.h create mode 100644 repos/ports/src/virtualbox6/include/global_defs.h create mode 100644 repos/ports/src/virtualbox6/include/libc/osreldate.h create mode 100644 repos/ports/src/virtualbox6/include/libc/wchar.h create mode 100644 repos/ports/src/virtualbox6/include/libc/wctype.h create mode 100644 repos/ports/src/virtualbox6/include/package-generated.h create mode 100644 repos/ports/src/virtualbox6/include/product-generated.h create mode 100644 repos/ports/src/virtualbox6/include/rpc/types.h create mode 100644 repos/ports/src/virtualbox6/include/version-generated.h create mode 100644 repos/ports/src/virtualbox6/init.h create mode 100644 repos/ports/src/virtualbox6/input_adapter.h create mode 100644 repos/ports/src/virtualbox6/libc.cc create mode 100644 repos/ports/src/virtualbox6/main.cc create mode 100644 repos/ports/src/virtualbox6/nem.cc create mode 100644 repos/ports/src/virtualbox6/patches/serial.patch create mode 100644 repos/ports/src/virtualbox6/patches/series create mode 100644 repos/ports/src/virtualbox6/pdm.cc create mode 100644 repos/ports/src/virtualbox6/scan_code.h create mode 100644 repos/ports/src/virtualbox6/stub_macros.h create mode 100644 repos/ports/src/virtualbox6/sup.cc create mode 100644 repos/ports/src/virtualbox6/sup.h create mode 100644 repos/ports/src/virtualbox6/sup_drv.cc create mode 100644 repos/ports/src/virtualbox6/sup_drv.h create mode 100644 repos/ports/src/virtualbox6/sup_gip.h create mode 100644 repos/ports/src/virtualbox6/sup_gmm.cc create mode 100644 repos/ports/src/virtualbox6/sup_gmm.h create mode 100644 repos/ports/src/virtualbox6/sup_sem.cc create mode 100644 repos/ports/src/virtualbox6/sup_vm.cc create mode 100644 repos/ports/src/virtualbox6/sup_vm.h create mode 100644 repos/ports/src/virtualbox6/svm.h create mode 100644 repos/ports/src/virtualbox6/target.mk create mode 100644 repos/ports/src/virtualbox6/unimpl.cc create mode 100644 repos/ports/src/virtualbox6/util.h create mode 100644 repos/ports/src/virtualbox6/vcpu.cc create mode 100644 repos/ports/src/virtualbox6/vcpu.h create mode 100644 repos/ports/src/virtualbox6/vcpu_gim.cc create mode 100644 repos/ports/src/virtualbox6/vmx.h create mode 100644 repos/ports/src/virtualbox6/xpcom_stubs.cc diff --git a/repos/ports/lib/mk/spec/x86_64/virtualbox6-devices.mk b/repos/ports/lib/mk/spec/x86_64/virtualbox6-devices.mk new file mode 100644 index 0000000000..88b189a833 --- /dev/null +++ b/repos/ports/lib/mk/spec/x86_64/virtualbox6-devices.mk @@ -0,0 +1,160 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +SRC_CC += Devices/Audio/AudioMixBuffer.cpp +SRC_CC += Devices/Audio/AudioMixer.cpp +SRC_CC += Devices/Audio/DevHDA.cpp +SRC_CC += Devices/Audio/DevHDACommon.cpp +SRC_CC += Devices/Audio/DevIchAc97.cpp +SRC_CC += Devices/Audio/DrvAudioCommon.cpp +SRC_CC += Devices/Audio/DrvAudio.cpp +SRC_CC += Devices/Audio/DrvHostNullAudio.cpp +SRC_CC += Devices/Audio/HDACodec.cpp +SRC_CC += Devices/Audio/HDAStream.cpp +SRC_CC += Devices/Audio/HDAStreamChannel.cpp +SRC_CC += Devices/Audio/HDAStreamMap.cpp +SRC_CC += Devices/Audio/HDAStreamPeriod.cpp +SRC_CC += Devices/Bus/DevPCI.cpp +SRC_CC += Devices/Bus/DevPciIch9.cpp +SRC_CC += Devices/Bus/MsiCommon.cpp +SRC_CC += Devices/Bus/MsixCommon.cpp +SRC_CC += Devices/EFI/DevFlash.cpp +SRC_CC += Devices/EFI/DevSmc.cpp +SRC_CC += Devices/EFI/FlashCore.cpp +SRC_CC += Devices/GIMDev/DrvUDP.cpp +SRC_CC += Devices/GIMDev/GIMDev.cpp +SRC_CC += Devices/Graphics/DevVGA.cpp +SRC_CC += Devices/Graphics/DevVGA-SVGA.cpp +SRC_CC += Devices/Graphics/DevVGA_VBVA.cpp +SRC_CC += Devices/Graphics/DevVGA_VDMA.cpp +SRC_CC += Devices/Graphics/HGSMI/HGSMIHost.cpp +SRC_CC += Devices/Graphics/HGSMI/SHGSMIHost.cpp +SRC_CC += Devices/Input/DevPS2.cpp +SRC_CC += Devices/Input/DevPS2K.cpp +SRC_CC += Devices/Input/DevPS2M.cpp +SRC_CC += Devices/Input/DrvKeyboardQueue.cpp +SRC_CC += Devices/Input/DrvMouseQueue.cpp +SRC_CC += Devices/Input/UsbKbd.cpp +SRC_CC += Devices/Input/UsbMouse.cpp +SRC_CC += Devices/Network/DevE1000.cpp +SRC_CC += Devices/Network/DevE1000Phy.cpp +SRC_CC += Devices/Network/DevEEPROM.cpp +SRC_CC += Devices/Network/DevPCNet.cpp +SRC_CC += Devices/Network/DrvNetShaper.cpp +SRC_CC += Devices/Network/DrvNetSniffer.cpp +SRC_CC += Devices/Network/DrvTAP.cpp +SRC_CC += Devices/Network/Pcap.cpp +SRC_CC += Devices/Parallel/DevParallel.cpp +SRC_CC += Devices/PC/ACPI/VBoxAcpi.cpp +SRC_CC += Devices/PC/DevACPI.cpp +SRC_CC += Devices/PC/DevDMA.cpp +SRC_CC += Devices/PC/DevFwCommon.cpp +SRC_CC += Devices/PC/DevHPET.cpp +SRC_CC += Devices/PC/DevIoApic.cpp +SRC_CC += Devices/PC/DevLpc-new.cpp +SRC_C += Devices/PC/DevPcArch.c +SRC_CC += Devices/PC/DevPcBios.cpp +SRC_CC += Devices/PC/DevPIC.cpp +SRC_CC += Devices/PC/DevPit-i8254.cpp +SRC_CC += Devices/PC/DevRTC.cpp +SRC_CC += Devices/PC/DrvACPI.cpp +SRC_CC += Devices/PC/DrvAcpiCpu.cpp +SRC_CC += Devices/PC/DevLpc-new.cpp +SRC_CC += Devices/Serial/DevSerial.cpp +SRC_CC += Devices/Serial/DrvChar.cpp +SRC_CC += Devices/Serial/DrvHostSerial.cpp +SRC_CC += Devices/Serial/DrvNamedPipe.cpp +SRC_CC += Devices/Serial/DrvRawFile.cpp +SRC_CC += Devices/Serial/DrvTCP.cpp +SRC_CC += Devices/Serial/UartCore.cpp +SRC_CC += Devices/Storage/ATAPIPassthrough.cpp +SRC_CC += Devices/Storage/Debug.cpp +SRC_CC += Devices/Storage/DevAHCI.cpp +SRC_CC += Devices/Storage/DevATA.cpp +SRC_C += Devices/Storage/DevFdc.c +SRC_CC += Devices/Storage/DrvHostBase.cpp +SRC_CC += Devices/Storage/DrvHostDVD.cpp +SRC_CC += Devices/Storage/DrvSCSI.cpp +SRC_CC += Devices/Storage/DrvVD.cpp +SRC_CC += Devices/Storage/HBDMgmt-generic.cpp +SRC_CC += Devices/Storage/IOBufMgmt.cpp +SRC_CC += Devices/Storage/VSCSI/VSCSIDevice.cpp +SRC_CC += Devices/Storage/VSCSI/VSCSIIoReq.cpp +SRC_CC += Devices/Storage/VSCSI/VSCSILun.cpp +SRC_CC += Devices/Storage/VSCSI/VSCSILunMmc.cpp +SRC_CC += Devices/Storage/VSCSI/VSCSILunSbc.cpp +SRC_CC += Devices/Storage/VSCSI/VSCSISense.cpp +SRC_CC += Devices/Storage/VSCSI/VSCSIVpdPagePool.cpp +SRC_CC += Devices/Trace/DrvIfsTrace.cpp +SRC_CC += Devices/Trace/DrvIfsTrace-serial.cpp +SRC_CC += Devices/USB/DevOHCI.cpp +SRC_CC += Devices/USB/DrvVUSBRootHub.cpp +SRC_CC += Devices/USB/USBProxyDevice.cpp +SRC_CC += Devices/USB/VUSBDevice.cpp +SRC_CC += Devices/USB/VUSBSniffer.cpp +SRC_CC += Devices/USB/VUSBSnifferPcapNg.cpp +SRC_CC += Devices/USB/VUSBSnifferUsbMon.cpp +SRC_CC += Devices/USB/VUSBSnifferVmx.cpp +SRC_CC += Devices/USB/VUSBUrb.cpp +SRC_CC += Devices/USB/VUSBUrbPool.cpp +SRC_CC += Devices/USB/VUSBUrbTrace.cpp +SRC_CC += Devices/VMMDev/VMMDev.cpp +SRC_CC += Devices/VMMDev/VMMDevHGCM.cpp + +SRC_CC += GuestHost/HGSMI/HGSMICommon.cpp +SRC_CC += GuestHost/HGSMI/HGSMIMemAlloc.cpp +SRC_CC += GuestHost/DragAndDrop/DnDTransferList.cpp +SRC_CC += GuestHost/DragAndDrop/DnDTransferObject.cpp +SRC_CC += GuestHost/DragAndDrop/DnDDroppedFiles.cpp +SRC_CC += GuestHost/DragAndDrop/DnDMIME.cpp +SRC_CC += GuestHost/DragAndDrop/DnDPath.cpp + +INC_DIR += $(VBOX_DIR)/Devices/build +INC_DIR += $(VBOX_DIR)/Devices/Bus +INC_DIR += $(VIRTUALBOX_DIR)/include/VBox/Graphics + +# found in src/VBox/Devices/Makefile.kmk +CC_OPT += -DVBOX_HGCM_HOST_CODE + +Devices/Graphics/DevVGA.o: vbetables.h + +vbetables.h: vbetables-gen + $(MSG_CONVERT)$@ + $(VERBOSE)./$^ > $@ + +vbetables-gen: Devices/Graphics/BIOS/vbetables-gen.c + $(MSG_BUILD)$@ + $(VERBOSE)gcc $(VBOX_CC_OPT) $(addprefix -I,$(INC_DIR)) -o $@ $^ + +Devices/PC/ACPI/VBoxAcpi.o: vboxaml.hex vboxssdt_standard.hex vboxssdt_cpuhotplug.hex + +vboxaml.hex: vbox.dsl + $(VERBOSE)( \ + iasl -tc -vi -vr -vs -p $@ $^ && \ + mv $@ $@.tmp && \ + sed "s/vboxaml_aml_code/AmlCode/g" <$@.tmp >$@ && \ + rm $@.tmp \ + ) + +vboxssdt_standard.hex: vbox-standard.dsl + $(VERBOSE)( \ + iasl -tc -vi -vr -vs -p $@ $^ && \ + mv $@ $@.tmp && \ + sed "s/AmlCode\|vboxssdt_standard_aml_code/AmlCodeSsdtStandard/g" <$@.tmp >$@.tmp2 && \ + sed "s/__VBOXSSDT-STANDARD_HEX__/__VBOXSSDT_STANDARD_HEX__/g" <$@.tmp2 >$@ && \ + rm $@.tmp $@.tmp2 \ + ) + +vboxssdt_cpuhotplug.hex: vbox-cpuhotplug.dsl + $(VERBOSE)( \ + gcc -E -P -x c -o $@.pre $< && \ + sed "s//\n/g" <$@.pre >$@.pre1 && \ + iasl -tc -vi -vr -vs -p $@ $@.pre1 && \ + mv $@ $@.tmp && \ + sed "s/AmlCode\|vboxssdt_cpuhotplug_aml_code/AmlCodeSsdtCpuHotPlug/g" <$@.tmp >$@.tmp2 && \ + sed "s/__VBOXSSDT-CPUHOTPLUG_HEX__/__VBOXSSDT_CPUHOTPLUG_HEX__/g" <$@.tmp2 >$@ && \ + rm $@.tmp $@.tmp2 $@.pre $@.pre1 \ + ) + +vpath %.dsl $(VBOX_DIR)/Devices/PC + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/spec/x86_64/virtualbox6-dis.mk b/repos/ports/lib/mk/spec/x86_64/virtualbox6-dis.mk new file mode 100644 index 0000000000..2e4d48c998 --- /dev/null +++ b/repos/ports/lib/mk/spec/x86_64/virtualbox6-dis.mk @@ -0,0 +1,16 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +SRC_CC += VMM/VMMR3/CPUMDbg.cpp +SRC_CC += VMM/VMMR3/DBGF.cpp +SRC_CC += VMM/VMMR3/DBGFAddr.cpp +SRC_CC += VMM/VMMR3/DBGFDisas.cpp +SRC_CC += VMM/VMMR3/DBGFR3Trace.cpp +SRC_CC += VMM/VMMR3/DBGFReg.cpp + +SRC_CC += $(addprefix Disassembler/, $(notdir $(wildcard $(VBOX_DIR)/Disassembler/*.cpp))) + +INC_DIR += $(VBOX_DIR)/VMM/include + +CC_OPT += -DVBOX_IN_VMM + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/spec/x86_64/virtualbox6-sup.mk b/repos/ports/lib/mk/spec/x86_64/virtualbox6-sup.mk new file mode 100644 index 0000000000..c53f6f85ab --- /dev/null +++ b/repos/ports/lib/mk/spec/x86_64/virtualbox6-sup.mk @@ -0,0 +1,23 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +LIBS += stdcxx + +SRC_CC := sup.cc sup_sem.cc sup_gmm.cc sup_drv.cc sup_vm.cc vcpu.cc + +SRC_CC += HostDrivers/Support/SUPLib.cpp +SRC_CC += HostDrivers/Support/SUPLibLdr.cpp + +INC_DIR += $(call select_from_repositories,src/lib/libc) + +INC_DIR += $(VIRTUALBOX_DIR)/VBoxAPIWrap +INC_DIR += $(VBOX_DIR)/HostDrivers/Support +INC_DIR += $(VBOX_DIR)/Devices/Bus +INC_DIR += $(REP_DIR)/src/virtualbox6 + +INC_DIR += $(VBOX_DIR)/Main/xml +INC_DIR += $(VBOX_DIR)/Main/include +INC_DIR += $(VBOX_DIR)/VMM/include + +vpath %.cc $(REP_DIR)/src/virtualbox6 + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/spec/x86_64/virtualbox6-vmm.mk b/repos/ports/lib/mk/spec/x86_64/virtualbox6-vmm.mk new file mode 100644 index 0000000000..dfb7457465 --- /dev/null +++ b/repos/ports/lib/mk/spec/x86_64/virtualbox6-vmm.mk @@ -0,0 +1,140 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +SRC_CC += VMM/VMMR3/VM.cpp +SRC_CC += VMM/VMMAll/VMAll.cpp +SRC_CC += VMM/VMMAll/VMMAll.cpp +SRC_CC += VMM/VMMR3/VMM.cpp + +SRC_CC += VMM/VMMR3/STAM.cpp + +SRC_CC += VMM/VMMR3/SSM.cpp + +SRC_CC += VMM/VMMR3/NEMR3.cpp +SRC_CC += VMM/VMMAll/NEMAll.cpp + +SRC_CC += VMM/VMMR3/PDM.cpp +SRC_CC += VMM/VMMR3/PDMBlkCache.cpp +SRC_CC += VMM/VMMR3/PDMDevice.cpp +SRC_CC += VMM/VMMR3/PDMQueue.cpp +SRC_CC += VMM/VMMR3/PDMCritSect.cpp +SRC_CC += VMM/VMMR3/PDMAsyncCompletion.cpp +SRC_CC += VMM/VMMR3/PDMAsyncCompletionFile.cpp +SRC_CC += VMM/VMMR3/PDMAsyncCompletionFileFailsafe.cpp +SRC_CC += VMM/VMMR3/PDMAsyncCompletionFileNormal.cpp +SRC_CC += VMM/VMMR3/PDMNetShaper.cpp +SRC_CC += VMM/VMMR3/PDMR3Task.cpp +SRC_CC += VMM/VMMAll/PDMAll.cpp +SRC_CC += VMM/VMMAll/PDMAllQueue.cpp +SRC_CC += VMM/VMMAll/PDMAllCritSect.cpp +SRC_CC += VMM/VMMAll/PDMAllCritSectRw.cpp +SRC_CC += VMM/VMMAll/PDMAllTask.cpp + +SRC_CC += VMM/VMMR3/TM.cpp +SRC_CC += VMM/VMMAll/TMAll.cpp +SRC_CC += VMM/VMMAll/TMAllVirtual.cpp +SRC_CC += VMM/VMMAll/TMAllReal.cpp +SRC_CC += VMM/VMMAll/TMAllCpu.cpp +SRC_CC += VMM/VMMAll/TRPMAll.cpp + +SRC_CC += VMM/VMMR3/CFGM.cpp + +SRC_CC += VMM/VMMR3/PDMDevHlp.cpp + +SRC_CC += VMM/VMMR3/PDMDevMiscHlp.cpp +SRC_CC += VMM/VMMR3/PDMDriver.cpp +SRC_CC += VMM/VMMR3/PDMThread.cpp + +SRC_CC += VMM/VMMR3/PDMUsb.cpp + +SRC_CC += VMM/VMMAll/CPUMAllMsrs.cpp +SRC_CC += VMM/VMMAll/CPUMAllRegs.cpp + +SRC_CC += VMM/VMMR3/VMEmt.cpp +SRC_CC += VMM/VMMR3/VMReq.cpp + +SRC_CC += VMM/VMMAll/DBGFAll.cpp +SRC_CC += VMM/VMMR3/DBGFInfo.cpp +SRC_CC += VMM/VMMR3/DBGFOS.cpp +SRC_CC += VMM/VMMR3/DBGFR3PlugIn.cpp + +SRC_CC += VMM/VMMR3/CPUM.cpp +SRC_CC += VMM/VMMR3/CPUMR3CpuId.cpp +SRC_CC += VMM/VMMR3/CPUMR3Db.cpp + +SRC_CC += VMM/VMMAll/EMAll.cpp +SRC_CC += VMM/VMMR3/EM.cpp +SRC_CC += VMM/VMMR3/EMHM.cpp +SRC_CC += VMM/VMMR3/EMR3Nem.cpp + +SRC_CC += VMM/VMMAll/HMAll.cpp +SRC_CC += VMM/VMMR3/HM.cpp +SRC_CC += VMM/VMMAll/HMSVMAll.cpp +SRC_CC += VMM/VMMAll/HMVMXAll.cpp + +SRC_CC += VMM/VMMR3/TRPM.cpp +SRC_CC += VMM/VMMAll/SELMAll.cpp + +SRC_CC += VMM/VMMR3/VMMGuruMeditation.cpp + +SRC_CC += VMM/VMMAll/IEMAll.cpp +SRC_S += VMM/VMMAll/IEMAllAImpl.asm +SRC_CC += VMM/VMMAll/IEMAllAImplC.cpp +SRC_CC += VMM/VMMR3/IEMR3.cpp + +SRC_CC += VMM/VMMAll/GIMAll.cpp +SRC_CC += VMM/VMMAll/GIMAllHv.cpp +SRC_CC += VMM/VMMAll/GIMAllKvm.cpp +SRC_CC += VMM/VMMR3/GIM.cpp +SRC_CC += VMM/VMMR3/GIMHv.cpp +SRC_CC += VMM/VMMR3/GIMKvm.cpp +SRC_CC += VMM/VMMR3/GIMMinimal.cpp + +SRC_CC += VMM/VMMR3/GMM.cpp + +SRC_CC += VMM/VMMR3/PGM.cpp +SRC_CC += VMM/VMMR3/PGMDbg.cpp +SRC_CC += VMM/VMMR3/PGMHandler.cpp +SRC_CC += VMM/VMMR3/PGMPhys.cpp +SRC_CC += VMM/VMMR3/PGMPool.cpp +SRC_S += VMM/VMMR3/PGMR3DbgA.asm +SRC_CC += VMM/VMMAll/PGMAll.cpp +SRC_CC += VMM/VMMAll/PGMAllHandler.cpp +SRC_CC += VMM/VMMAll/PGMAllPhys.cpp +SRC_CC += VMM/VMMAll/PGMAllPool.cpp + +# C++17 does not allow the use of the 'register' specifier +CC_OPT_VMM/VMMAll/PGMAll = -Dregister= + +SRC_CC += VMM/VMMR3/IOM.cpp +SRC_CC += VMM/VMMR3/IOMR3IoPort.cpp +SRC_CC += VMM/VMMR3/IOMR3Mmio.cpp +SRC_CC += VMM/VMMAll/IOMAll.cpp +SRC_CC += VMM/VMMAll/IOMAllMmioNew.cpp + +SRC_CC += VMM/VMMR3/APIC.cpp +SRC_CC += VMM/VMMAll/APICAll.cpp + +SRC_CC += VMM/VMMR3/MM.cpp +SRC_CC += VMM/VMMR3/MMHeap.cpp +SRC_CC += VMM/VMMR3/MMUkHeap.cpp +SRC_CC += VMM/VMMR3/MMHyper.cpp +SRC_CC += VMM/VMMR3/MMPagePool.cpp +SRC_CC += VMM/VMMAll/MMAll.cpp +SRC_CC += VMM/VMMAll/MMAllHyper.cpp + +CC_OPT += -DVBOX_IN_VMM + +# definitions needed by SSM.cpp +CC_OPT += -DKBUILD_TYPE=\"debug\" \ + -DKBUILD_TARGET=\"genode\" \ + -DKBUILD_TARGET_ARCH=\"x86\" + +# definitions needed by VMMAll.cpp +CC_OPT += -DVBOX_SVN_REV=~0 + +INC_DIR += $(VBOX_DIR)/VMM/include + +# override conflicting parts of the libc headers +INC_DIR += $(REP_DIR)/src/virtualbox6/include/libc + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-apiwrap.mk b/repos/ports/lib/mk/virtualbox6-apiwrap.mk new file mode 100644 index 0000000000..00f6757510 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-apiwrap.mk @@ -0,0 +1,13 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +LIBS += stdcxx + +SRC_CC += $(addprefix VBoxAPIWrap/, $(notdir $(wildcard $(VIRTUALBOX_DIR)/VBoxAPIWrap/*.cpp))) + +INC_DIR += $(REP_DIR)/src/virtualbox6/frontend +INC_DIR += $(REP_DIR)/src/virtualbox6/include +INC_DIR += $(VBOX_DIR)/Main/include + +vpath %.cpp $(VIRTUALBOX_DIR) + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-bios.mk b/repos/ports/lib/mk/virtualbox6-bios.mk new file mode 100644 index 0000000000..83887ab5a3 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-bios.mk @@ -0,0 +1,41 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +ifeq ($(shell which yasm),) +REQUIRES += installation_of_yasm +endif + +SRC_O += VBoxPcBiosBinary8086.o VBoxPcBiosBinary286.o VBoxPcBiosBinary386.o +SRC_O += VBoxVgaBiosBinary8086.o VBoxVgaBiosBinary286.o VBoxVgaBiosBinary386.o +SRC_O += XVBoxBiosLogoBin.o + +VBox%.o : VBox%.rom + $(MSG_CONVERT)$@ + $(VERBOSE)echo ".global g_ab$*, g_cb$*;" \ + ".data;" \ + "g_cb$*:; .long g_ab$*End - g_ab$*;" \ + ".align 4096;" \ + "g_ab$*:; .incbin \"$<\";" \ + "g_ab$*End:;" | \ + $(AS) $(AS_OPT) -f -o $@ - + +VBoxPcBiosBinary%.rom: Devices/PC/BIOS/VBoxBiosAlternative%.asm + $(MSG_ASSEM) + $(VERBOSE)yasm -w -f bin -o $@ $< + +VBoxVgaBiosBinary%.rom: Devices/Graphics/BIOS/VBoxVgaBiosAlternative%.asm + $(MSG_ASSEM) + $(VERBOSE)yasm -w -f bin -o $@ $< + +XVBoxBiosLogoBin.o: Devices/Graphics/BIOS/ose_logo.bmp + $(MSG_CONVERT)$@ + $(VERBOSE)echo ".global g_abVgaDefBiosLogo, g_cbVgaDefBiosLogo;" \ + ".data;" \ + "g_cbVgaDefBiosLogo:; .long g_abVgaDefBiosLogoEnd - g_abVgaDefBiosLogo;" \ + ".align 4096;" \ + "g_abVgaDefBiosLogo:; .incbin \"$<\";" \ + "g_abVgaDefBiosLogoEnd:;" | \ + $(AS) $(AS_OPT) -f -o $@ - + +vpath %.bmp $(VBOX_DIR) + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-client.mk b/repos/ports/lib/mk/virtualbox6-client.mk new file mode 100644 index 0000000000..94f7553068 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-client.mk @@ -0,0 +1,76 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +LIBS += stdcxx + +# +# The 'ProgressImpl' compilation unit is used by both the VBox server and +# VBox client, but compiled with (client) and without (server) the +# 'VBOX_COM_INPROC' define set. Since the ABI for 'ProgressImpl' is not +# the same for client and server but we want to like client and server +# together, we need to disambiguate both flavours. +# +# - At the client side, we rename the 'Progress' class to 'ClientProgress' +# - We set the 'VBOX_COM_INPROC' define for the client code only +# +VBOX_CC_OPT += -DProgress=ClientProgress +VBOX_CC_OPT += -DVBOX_COM_INPROC + +SRC_CC += Main/src-all/ProgressImpl.cpp + +SRC_CC += Main/src-client/AdditionsFacilityImpl.cpp +SRC_CC += Main/src-client/BusAssignmentManager.cpp +SRC_CC += Main/src-client/ClientTokenHolder.cpp +SRC_CC += Main/src-client/ConsoleImpl.cpp +SRC_CC += Main/src-client/ConsoleImpl2.cpp +SRC_CC += Main/src-client/ConsoleVRDPServer.cpp +SRC_CC += Main/src-client/DisplaySourceBitmapImpl.cpp +SRC_CC += Main/src-client/DisplayImpl.cpp +SRC_CC += Main/src-client/DisplayImplLegacy.cpp +SRC_CC += Main/src-client/DrvAudioVRDE.cpp +SRC_CC += Main/src-client/EmulatedUSBImpl.cpp +SRC_CC += Main/src-client/GuestCtrlImpl +SRC_CC += Main/src-client/GuestCtrlPrivate +SRC_CC += Main/src-client/GuestDirectoryImpl +SRC_CC += Main/src-client/GuestDnDPrivate +SRC_CC += Main/src-client/GuestFileImpl +SRC_CC += Main/src-client/GuestProcessImpl +SRC_CC += Main/src-client/GuestDnDSourceImpl +SRC_CC += Main/src-client/GuestFsObjInfoImpl +SRC_CC += Main/src-client/GuestSessionImpl +SRC_CC += Main/src-client/GuestDnDTargetImpl +SRC_CC += Main/src-client/GuestImpl +SRC_CC += Main/src-client/GuestSessionImpl +SRC_CC += Main/src-client/GuestSessionImplTasks + +SRC_CC += Main/src-client/HGCM.cpp +SRC_CC += Main/src-client/HGCMObjects.cpp +SRC_CC += Main/src-client/HGCMThread.cpp +SRC_CC += Main/src-client/KeyboardImpl.cpp +SRC_CC += Main/src-client/MachineDebuggerImpl.cpp +SRC_CC += Main/src-client/MouseImpl.cpp +SRC_CC += Main/src-client/RemoteUSBBackend.cpp +SRC_CC += Main/src-client/RemoteUSBDeviceImpl.cpp +SRC_CC += Main/src-client/SessionImpl.cpp +SRC_CC += Main/src-client/USBDeviceImpl.cpp +SRC_CC += Main/src-client/UsbWebcamInterface.cpp +SRC_CC += Main/src-client/VMMDevInterface.cpp + +# +# Suppress warnings caused by using anonymous enum values in 'a ? b : c' +# expressions. +# +# "enumeral mismatch in conditional expression" +# +CC_OPT_Main/src-client/ConsoleImpl = -Wno-enum-compare +CC_OPT_Main/src-client/ConsoleImpl2 = -Wno-enum-compare +CC_OPT_Main/src-client/GuestImpl = -Wno-enum-compare +CC_OPT_Main/src-client/RemoteUSBDeviceImpl = -Wno-enum-compare +CC_OPT_Main/src-client/GuestDnDPrivate = -Wno-enum-compare + +INC_DIR += $(VBOX_DIR)/Main/xml +INC_DIR += $(VBOX_DIR)/Main/include +INC_DIR += $(REP_DIR)/src/virtualbox6/frontend +INC_DIR += $(VIRTUALBOX_DIR)/VBoxAPIWrap +INC_DIR += $(VIRTUALBOX_DIR)/include/VBox/Graphics + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-common.inc b/repos/ports/lib/mk/virtualbox6-common.inc new file mode 100644 index 0000000000..710a23bdc6 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-common.inc @@ -0,0 +1,121 @@ +REQUIRES += x86 + +VBOX_MACH := $(filter $(SPECS), x86_32 x86_64) + +VBOX_MACH_CC_OPT_x86_32 = -DRT_ARCH_X86 -D__X86__ +VBOX_MACH_ASM_OPT_x86_32 = -f elf32 +VBOX_MACH_CC_OPT_x86_64 = -DRT_ARCH_AMD64 -D__AMD64__ +VBOX_MACH_ASM_OPT_x86_64 = -f elf64 + +ifeq ($(shell which yasm),) +REQUIRES += installation_of_yasm +REQUIRES += installation_of_iasl +endif + +VIRTUALBOX_DIR := $(call select_from_ports,virtualbox6)/src/virtualbox6 +VIRTUALBOX_SDK_DIR := $(call select_from_ports,virtualbox6)/src/virtualbox6_sdk + +VBOX_DIR := $(VIRTUALBOX_DIR)/src/VBox + +VBOX_CC_OPT += -DIN_RING3 -DVBOX -DVBOX_OSE +VBOX_CC_OPT += -D_FILE_OFFSET_BITS=64 -DLOG_ENABLED + +VBOX_CC_OPT += $(VBOX_MACH_CC_OPT_$(VBOX_MACH)) + +VBOX_CC_OPT += -DUSING_VMM_COMMON_DEFS +VBOX_CC_OPT += -DVBOX_WITH_64_BITS_GUESTS +VBOX_CC_OPT += -DIN_SUP_R3 -DIN_VMM_R3 +VBOX_CC_OPT += -DVBOX_WITH_NATIVE_NEM + +# we use the libc headers from FreeBSD +VBOX_CC_OPT += -DRT_OS_FREEBSD + +VBOX_CC_OPT += -DVBOX_WITH_3RD_IEM_STEP +VBOX_CC_OPT += -DVBOX_WITH_HGCM -DVBOX_WITH_HGSMI +VBOX_CC_OPT += -DVBOX_WITHOUT_TESTING_FEATURES +VBOX_CC_OPT += -DVBOX_WITH_VIDEOHWACCEL +VBOX_CC_OPT += -DVBOX_WITH_XPCOM +VBOX_CC_OPT += -DVBOX_WITH_PDM_ASYNC_COMPLETION +VBOX_CC_OPT += -DVBOX_WITH_NETSHAPER +VBOX_CC_OPT += -DVBOX_WITH_RESOURCE_USAGE_API +VBOX_CC_OPT += -DVBOX_WITH_GUEST_CONTROL +VBOX_CC_OPT += -DVBOX_WITH_GENERIC_SESSION_WATCHER +VBOX_CC_OPT += -DVBOX_WITH_NAT_SERVICE +VBOX_CC_OPT += -DVBOX_WITH_AUDIO_HDA_ASYNC_IO +VBOX_CC_OPT += -DVBOX_WITH_DRAG_AND_DROP + +include $(REP_DIR)/lib/mk/virtualbox6-debug.inc + +VBOX_CC_OPT += -DVBOX_WITH_USB -DVBOX_WITH_VUSB + +VBOX_CC_OPT += -DVBOX_WITH_NEW_LPC_DEVICE +VBOX_CC_OPT += -DVBOX_WITH_E1000 +VBOX_CC_OPT += -DVBOX_WITH_AHCI +VBOX_CC_OPT += -DVBOX_WITH_MULTI_CORE +VBOX_CC_OPT += -DVBOX_WITH_AUDIO_OSS +VBOX_CC_OPT += -DVBOX_WITH_INTEL_HDA + +# required for guest additions 5++ +VBOX_CC_OPT += -DVBOX_WITH_GUEST_PROPS + +# prevent access to port content at the dependency stage of the build system +ifeq ($(called_from_lib_mk),yes) +include $(VIRTUALBOX_DIR)/Version.kmk +endif + +VIRTUALBOX_PACKAGE_STRING_x86_32 = GenodeOS_32BIT_GENERIC +VIRTUALBOX_PACKAGE_STRING_x86_64 = GenodeOS_64BIT_GENERIC + +VBOX_CC_OPT += -DVBOX_VERSION_MAJOR=$(VBOX_VERSION_MAJOR) \ + -DVBOX_VERSION_MINOR=$(VBOX_VERSION_MINOR) \ + -DVBOX_VERSION_BUILD=$(VBOX_VERSION_BUILD) \ + -DVBOX_VERSION_STRING=\"$(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD)_OSE\" \ + -DVBOX_VERSION_STRING_RAW=\"$(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD)\" \ + -DVBOX_PACKAGE_STRING=\"$(VIRTUALBOX_PACKAGE_STRING_$(VBOX_MACH))\" \ + -DVBOX_API_VERSION_STRING=\"$(VBOX_VERSION_MAJOR)_$(VBOX_VERSION_MINOR)\" \ + -DIPRT_BLDCFG_VERSION_STRING=\"$(VBOX_VERSION_MAJOR).$(VBOX_VERSION_MINOR).$(VBOX_VERSION_BUILD)_OSE\" \ + -DIPRT_BLDCFG_TARGET=\"genode\" \ + -DIPRT_BLDCFG_TARGET_ARCH=\"$(VBOX_MACH)\" + +VBOX_CC_OPT += -DVBOX_WITH_WDDM -DVBOXWDDM_WITH_VBVA +VBOX_CC_OPT += -DVBOX_WITH_VDMA +VBOX_CC_OPT += -DVBOX_WITH_VMSVGA +VBOX_CC_OPT += -DVBOX_HDD_NO_DYNAMIC_BACKENDS +VBOX_CC_OPT += -DVBOX_WITH_SCSI +VBOX_CC_OPT += -DVBOX_WITH_HOSTNETIF_API + +# prevent error preprocessor directive in VBox/version.h +VBOX_CC_OPT += -DVBOX_PRIVATE_BUILD_DESC + +CC_WARN += -Wno-trigraphs -Werror + +CC_OPT += $(VBOX_CC_OPT) + +# enforce some global definitions (e.g., include of base/log.h) +CC_OPT += -include global_defs.h + +# VirtualBox expects wchar_t to be a 16-bit type. yasm does not understand this +# flag, therefore it gets added to CC_OPT instead of VBOX_CC_OPT. +CC_OPT += -fshort-wchar + +LIBS += libc libm libc-mem + +INC_DIR += $(REP_DIR)/src/virtualbox6/include +INC_DIR += $(VIRTUALBOX_DIR)/include +INC_DIR += $(VIRTUALBOX_SDK_DIR)/sdk/bindings/xpcom/include +INC_DIR += $(VIRTUALBOX_SDK_DIR)/sdk/bindings/xpcom/include/xpcom +INC_DIR += $(VIRTUALBOX_SDK_DIR)/sdk/bindings/xpcom/include/nsprpub +INC_DIR += $(VIRTUALBOX_SDK_DIR)/sdk/bindings/xpcom/include/ipcd +INC_DIR += $(VIRTUALBOX_SDK_DIR)/sdk/bindings/xpcom/include/string +INC_DIR += $(VBOX_DIR)/Devices/build + +vpath %.cpp $(VBOX_DIR) +vpath %.c $(VBOX_DIR) +vpath %.asm $(VBOX_DIR) + +%.o: %.asm + $(MSG_ASSEM)$@ + $(VERBOSE)yasm $(VBOX_MACH_ASM_OPT_$(VBOX_MACH)) -DASM_FORMAT_ELF -D__YASM__ \ + $(addprefix -I,$(INC_DIR)) $(VBOX_CC_OPT) -o $@ $< + +# vi: set ft=make : diff --git a/repos/ports/lib/mk/virtualbox6-debug.inc b/repos/ports/lib/mk/virtualbox6-debug.inc new file mode 100644 index 0000000000..83b76f5df7 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-debug.inc @@ -0,0 +1 @@ +VBOX_CC_OPT += -DRT_STRICT -DVBOX_STRICT diff --git a/repos/ports/lib/mk/virtualbox6-liblzf.mk b/repos/ports/lib/mk/virtualbox6-liblzf.mk new file mode 100644 index 0000000000..f243de0019 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-liblzf.mk @@ -0,0 +1,10 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +LIBLZF_DIR = $(VIRTUALBOX_DIR)/src/libs/liblzf-3.4 +INC_DIR += $(LIBLZF_DIR) +CC_OPT += -DULTRA_FAST=1 -DHLOG=12 -DSTRICT_ALIGN=0 -DPIC +SRC_C = lzf_c.c lzf_d.c + +vpath % $(LIBLZF_DIR) + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-main.mk b/repos/ports/lib/mk/virtualbox6-main.mk new file mode 100644 index 0000000000..6428e4110d --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-main.mk @@ -0,0 +1,84 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +LIBS += stdcxx + +SRC_CC += Main/xml/Settings.cpp + +SRC_CC += Main/src-all/AuthLibrary.cpp +SRC_CC += Main/src-all/AutoCaller.cpp +SRC_CC += Main/src-all/EventImpl.cpp +SRC_CC += Main/src-all/DisplayResampleImage.cpp +SRC_CC += Main/src-all/DisplayUtils.cpp +SRC_CC += Main/src-all/Global.cpp +SRC_CC += Main/src-all/HashedPw.cpp +SRC_CC += Main/src-all/PCIDeviceAttachmentImpl.cpp +SRC_CC += Main/src-all/ProgressImpl.cpp +SRC_CC += Main/src-all/SecretKeyStore.cpp +SRC_CC += Main/src-all/SharedFolderImpl.cpp +SRC_CC += Main/src-all/ThreadTask.cpp +SRC_CC += Main/src-all/VirtualBoxBase.cpp +SRC_CC += Main/src-all/GlobalStatusConversion.cpp +SRC_CC += Main/src-all/VirtualBoxErrorInfoImpl.cpp +SRC_CC += Main/src-server/AudioAdapterImpl.cpp +SRC_CC += Main/src-server/BandwidthControlImpl.cpp +SRC_CC += Main/src-server/BandwidthGroupImpl.cpp +SRC_CC += Main/src-server/BIOSSettingsImpl.cpp +SRC_CC += Main/src-server/ClientToken.cpp +SRC_CC += Main/src-server/ClientWatcher.cpp +SRC_CC += Main/src-server/DHCPServerImpl.cpp +SRC_CC += Main/src-server/DHCPConfigImpl.cpp +SRC_CC += Main/src-server/GraphicsAdapterImpl.cpp +SRC_CC += Main/src-server/GuestOSTypeImpl.cpp +SRC_CC += Main/src-server/HostImpl.cpp +SRC_CC += Main/src-server/MachineImpl.cpp +SRC_CC += Main/src-server/MachineImplCloneVM.cpp +SRC_CC += Main/src-server/Matching.cpp +SRC_CC += Main/src-server/MediumAttachmentImpl.cpp +SRC_CC += Main/src-server/MediumImpl.cpp +SRC_CC += Main/src-server/MediumFormatImpl.cpp +SRC_CC += Main/src-server/MediumLock.cpp +SRC_CC += Main/src-server/NATEngineImpl.cpp +SRC_CC += Main/src-server/NATNetworkImpl.cpp +SRC_CC += Main/src-server/NetworkAdapterImpl.cpp +SRC_CC += Main/src-server/NetworkServiceRunner.cpp +SRC_CC += Main/src-server/ParallelPortImpl.cpp +SRC_CC += Main/src-server/Performance.cpp +SRC_CC += Main/src-server/PerformanceImpl.cpp +SRC_CC += Main/src-server/ProgressProxyImpl.cpp +SRC_CC += Main/src-server/RecordingSettingsImpl.cpp +SRC_CC += Main/src-server/RecordingScreenSettingsImpl.cpp +SRC_CC += Main/src-server/SerialPortImpl.cpp +SRC_CC += Main/src-server/SnapshotImpl.cpp +SRC_CC += Main/src-server/StorageControllerImpl.cpp +SRC_CC += Main/src-server/SystemPropertiesImpl.cpp +SRC_CC += Main/src-server/TokenImpl.cpp +SRC_CC += Main/src-server/USBControllerImpl.cpp +SRC_CC += Main/src-server/USBDeviceFilterImpl.cpp +SRC_CC += Main/src-server/USBDeviceFiltersImpl.cpp +SRC_CC += Main/src-server/VirtualBoxImpl.cpp +SRC_CC += Main/src-server/VRDEServerImpl.cpp +SRC_CC += Main/src-server/HostDnsService.cpp +SRC_CC += Main/src-server/HostNetworkInterfaceImpl.cpp +SRC_CC += Main/src-server/MediumIOImpl.cpp +SRC_CC += Main/src-server/DataStreamImpl.cpp +SRC_CC += Main/src-server/HostPower.cpp + +# use OS/2 version of 'pm::createHAL()' because it is empty +SRC_CC += Main/src-server/os2/PerformanceOs2.cpp + +# generated from VBox/Main/idl/comimpl.xsl +SRC_CC += Main/VBoxEvents.cpp + +# see comment in virtualbox6-client.mk +CC_OPT_Main/src-server/MediumImpl = -Wno-enum-compare + +# prevent double define of 'LOG_GROUP' +VBOX_CC_OPT += -DIN_VBOXSVC + +INC_DIR += $(VBOX_DIR)/Main/xml +INC_DIR += $(VBOX_DIR)/Main/include +INC_DIR += $(REP_DIR)/src/virtualbox6/frontend +INC_DIR += $(VIRTUALBOX_DIR)/VBoxAPIWrap +INC_DIR += $(VIRTUALBOX_DIR)/include/VBox/Graphics + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-runtime.mk b/repos/ports/lib/mk/virtualbox6-runtime.mk new file mode 100644 index 0000000000..10f2667949 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-runtime.mk @@ -0,0 +1,131 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +INC_DIR += $(VBOX_DIR)/Runtime/include + +INC_DIR += $(VIRTUALBOX_DIR)/src/libs/liblzf-3.4 +INC_DIR += $(VIRTUALBOX_DIR)/src/libs/zlib-1.2.11 +INC_DIR += $(call select_from_ports,libiconv)/include/iconv +INC_DIR += $(REP_DIR)/src/virtualbox6/include/libc + +LIBS += stdcxx + +CC_WARN += -Wno-unused-variable + +all_cpp_files_of_sub_dir = \ + $(addprefix $1, $(notdir $(wildcard $(VBOX_DIR)/$1*.cpp))) + +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/alloc/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/err/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/log/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/misc/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/path/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/rand/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/string/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/common/table/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/generic/) +SRC_CC += $(call all_cpp_files_of_sub_dir,Runtime/r3/) + +SRC_CC += Runtime/common/checksum/alt-md5.cpp +SRC_CC += Runtime/common/checksum/alt-sha512.cpp +SRC_CC += Runtime/common/checksum/crc16ccitt.cpp +SRC_CC += Runtime/common/checksum/crc32c.cpp +SRC_CC += Runtime/common/checksum/crc32.cpp +SRC_CC += Runtime/common/checksum/ipv4.cpp +SRC_CC += Runtime/common/checksum/ipv6.cpp +SRC_CC += Runtime/common/checksum/sha512str.cpp +SRC_CC += Runtime/common/dbg/dbgstackdumpself.cpp +SRC_CC += Runtime/common/fs/isovfs.cpp +SRC_CC += Runtime/common/ldr/ldr.cpp +SRC_CC += Runtime/common/ldr/ldrEx.cpp +SRC_CC += Runtime/common/net/macstr.cpp +SRC_CC += Runtime/common/net/netaddrstr2.cpp +SRC_CC += Runtime/common/sort/shellsort.cpp +SRC_CC += Runtime/common/time/time.cpp +SRC_CC += Runtime/common/time/timeprog.cpp +SRC_CC += Runtime/common/time/timesup.cpp +SRC_CC += Runtime/common/time/timesupref.cpp +SRC_CC += Runtime/common/vfs/vfsbase.cpp +SRC_CC += Runtime/common/vfs/vfschain.cpp +SRC_CC += Runtime/common/vfs/vfsstddir.cpp +SRC_CC += Runtime/common/vfs/vfsstdfile.cpp +SRC_CC += Runtime/common/zip/zip.cpp +SRC_CC += Runtime/r3/generic/dirrel-r3-generic.cpp +SRC_CC += Runtime/r3/generic/semspinmutex-r3-generic.cpp +SRC_CC += Runtime/r3/posix/dir-posix.cpp +SRC_CC += Runtime/r3/posix/env-posix.cpp +SRC_CC += Runtime/r3/posix/fileaio-posix.cpp +SRC_CC += Runtime/r3/posix/fileio2-posix.cpp +SRC_CC += Runtime/r3/posix/fileio-posix.cpp +SRC_CC += Runtime/r3/posix/fs2-posix.cpp +SRC_CC += Runtime/r3/posix/fs3-posix.cpp +SRC_CC += Runtime/r3/posix/fs-posix.cpp +SRC_CC += Runtime/r3/posix/path2-posix.cpp +SRC_CC += Runtime/r3/posix/path-posix.cpp +SRC_CC += Runtime/r3/posix/pipe-posix.cpp +SRC_CC += Runtime/r3/posix/process-posix.cpp +SRC_CC += Runtime/r3/posix/rtmempage-exec-mmap-posix.cpp +SRC_CC += Runtime/r3/posix/RTPathUserHome-posix.cpp +SRC_CC += Runtime/r3/posix/RTTimeNow-posix.cpp +SRC_CC += Runtime/r3/posix/semeventmulti-posix.cpp +SRC_CC += Runtime/r3/posix/semevent-posix.cpp +SRC_CC += Runtime/r3/posix/semmutex-posix.cpp +SRC_CC += Runtime/r3/posix/serialport-posix.cpp +SRC_CC += Runtime/r3/posix/symlink-posix.cpp +SRC_CC += Runtime/r3/posix/thread2-posix.cpp +SRC_CC += Runtime/r3/posix/thread-posix.cpp +SRC_CC += Runtime/r3/posix/time-posix.cpp +SRC_CC += Runtime/r3/posix/tls-posix.cpp +SRC_CC += Runtime/r3/posix/utf8-posix.cpp +SRC_CC += Runtime/VBox/log-vbox.cpp +SRC_S += Runtime/common/asm/ASMAtomicCmpXchgExU64.asm +SRC_S += Runtime/common/asm/ASMAtomicCmpXchgU64.asm +SRC_S += Runtime/common/asm/ASMAtomicReadU64.asm +SRC_S += Runtime/common/asm/ASMAtomicUoReadU64.as +SRC_S += Runtime/common/asm/ASMAtomicXchgU64.asm +SRC_S += Runtime/common/asm/ASMCpuIdExSlow.asm +SRC_S += Runtime/common/asm/ASMGetXcr0.asm +SRC_S += Runtime/common/asm/ASMFxSave.asm +SRC_S += Runtime/common/asm/ASMMemFirstMismatchingU8.asm +SRC_S += Runtime/common/dbg/dbgstackdumpself-amd64-x86.asm + +FILTERED_OUT_SRC_CC += Runtime/common/misc/RTSystemIsInsideVM-amd64-x86.cpp +FILTERED_OUT_SRC_CC += Runtime/common/misc/s3.cpp +FILTERED_OUT_SRC_CC += Runtime/common/string/ministring.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/fs-stubs-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/http-curl.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/mppresent-generic-online.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTDirExists-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTFileExists-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTLogDefaultInit-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTLogWriteStdErr-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTLogWriteStdOut-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTMpGetDescription-generic-stub.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTMpOnPair-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTProcessQueryUsernameA-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTSemEventMultiWait-2-ex-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTSemEventWait-2-ex-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTSemEventWait-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTSemEventWaitNoResume-2-ex-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTSemMutexRequestDebug-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/RTSemMutexRequest-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/semrw-lockless-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/strcache-stubs-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/generic/tls-generic.cpp +FILTERED_OUT_SRC_CC += Runtime/r3/xml.cpp +FILTERED_OUT_SRC_CC += Runtime/r3/alloc-ef.cpp +FILTERED_OUT_SRC_CC += Runtime/r3/alloc-ef-cpp.cpp +FILTERED_OUT_SRC_CC += Runtime/r3/memsafer-r3.cpp + +# avoid static allocation of 1 MiB array 'g_aCPInfo' +FILTERED_OUT_SRC_CC += Runtime/common/string/uniread.cpp + +SRC_CC := $(filter-out $(FILTERED_OUT_SRC_CC), $(SRC_CC)) + +Runtime/common/err/errmsg.o: errmsgdata.h + +errmsgdata.h: $(VIRTUALBOX_DIR)/include/iprt/err.h \ + $(VIRTUALBOX_DIR)/include/VBox/err.h + $(MSG_CONVERT)$@ + $(VERBOSE)sed -f $(VBOX_DIR)/Runtime/common/err/errmsg.sed $^ > $@ + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-storage.mk b/repos/ports/lib/mk/virtualbox6-storage.mk new file mode 100644 index 0000000000..d441af8e1e --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-storage.mk @@ -0,0 +1,7 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +SRC_CC += $(addprefix Storage/, $(notdir $(wildcard $(VBOX_DIR)/Storage/*.cpp))) + +SRC_CC := $(filter-out Storage/VDIfTcpNet.cpp, $(SRC_CC)) + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-xml.mk b/repos/ports/lib/mk/virtualbox6-xml.mk new file mode 100644 index 0000000000..840b0be98e --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-xml.mk @@ -0,0 +1,26 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +ZLIB_DIR = $(VIRTUALBOX_DIR)/src/libs/zlib-1.2.11 +LIBXML_DIR = $(VIRTUALBOX_DIR)/src/libs/libxml2-2.9.4 + +INC_DIR += $(ZLIB_DIR) +INC_DIR += $(LIBXML_DIR)/include +INC_DIR += $(call select_from_ports,libiconv)/include/iconv +INC_DIR += $(VBOX_DIR)/Runtime/include + +LIBS += stdcxx + +VBOX_CC_OPT += -DLIBXML_THREAD_ENABLED + +SRC_C += buf.c catalog.c chvalid.c debugXML.c dict.c encoding.c error.c entities.c +SRC_C += globals.c hash.c list.c parser.c parserInternals.c pattern.c +SRC_C += relaxng.c threads.c tree.c uri.c valid.c HTMLtree.c HTMLparser.c +SRC_C += SAX.c SAX2.c xmlIO.c xmlmemory.c xmlreader.c xmlregexp.c xmlschemas.c +SRC_C += xmlschemastypes.c xmlsave.c xmlstring.c xmlunicode.c xpath.c xpointer.c + +SRC_CC += Runtime/r3/xml.cpp +SRC_CC += Runtime/common/string/ministring.cpp + +vpath %.c $(LIBXML_DIR) + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-xpcom.mk b/repos/ports/lib/mk/virtualbox6-xpcom.mk new file mode 100644 index 0000000000..ab26ed88e8 --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-xpcom.mk @@ -0,0 +1,137 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +XPCOM_DIR := $(VIRTUALBOX_DIR)/src/libs/xpcom18a4 + +all_cpp_files_of_sub_dir = \ + $(addprefix $1, $(notdir $(wildcard $(XPCOM_DIR)/$1*.cpp))) + +LIBS += stdcxx + +SRC_CC += $(call all_cpp_files_of_sub_dir,xpcom/ds/) +SRC_CC += $(call all_cpp_files_of_sub_dir,xpcom/base/) +SRC_CC += Main/glue/AutoLock.cpp +SRC_CC += Main/glue/com.cpp +SRC_CC += Main/glue/ErrorInfo.cpp +SRC_CC += Main/glue/EventQueue.cpp +SRC_CC += Main/glue/NativeEventQueue.cpp +SRC_CC += Main/glue/GetVBoxUserHomeDirectory.cpp +SRC_CC += Main/glue/string.cpp +SRC_CC += Main/glue/xpcom/helpers.cpp +SRC_CC += xpcom/base/nsID.cpp +SRC_CC += xpcom/build/nsXPComInit.cpp +SRC_CC += xpcom/components/nsCategoryManager.cpp +SRC_CC += xpcom/components/nsComponentManager.cpp +SRC_CC += xpcom/components/nsNativeComponentLoader.cpp +SRC_CC += xpcom/components/nsStaticComponentLoader.cpp +SRC_CC += xpcom/components/xcDll.cpp +SRC_CC += xpcom/glue/nsComponentManagerUtils.cpp +SRC_CC += xpcom/glue/nsCOMPtr.cpp +SRC_CC += xpcom/glue/nsGenericFactory.cpp +SRC_CC += xpcom/glue/nsMemory.cpp +SRC_CC += xpcom/glue/nsWeakReference.cpp +SRC_CC += xpcom/io/nsAppFileLocationProvider.cpp +SRC_CC += xpcom/io/nsBinaryStream.cpp +SRC_CC += xpcom/io/nsDirectoryService.cpp +SRC_CC += xpcom/io/nsLocalFileCommon.cpp +SRC_CC += xpcom/io/nsLocalFileUnix.cpp +SRC_CC += xpcom/io/nsNativeCharsetUtils.cpp +SRC_CC += xpcom/io/nsSegmentedBuffer.cpp +SRC_CC += xpcom/io/nsStorageStream.cpp +SRC_CC += xpcom/string/src/nsAString.cpp +SRC_CC += xpcom/string/src/nsDependentSubstring.cpp +SRC_CC += xpcom/string/src/nsObsoleteAStringThunk.cpp +SRC_CC += xpcom/string/src/nsPrintfCString.cpp +SRC_CC += xpcom/string/src/nsPromiseFlatString.cpp +SRC_CC += xpcom/string/src/nsReadableUtils.cpp +SRC_CC += xpcom/string/src/nsStringComparator.cpp +SRC_CC += xpcom/string/src/nsString.cpp +SRC_CC += xpcom/string/src/nsSubstring.cpp +SRC_CC += xpcom/string/src/nsSubstringTuple.cpp +SRC_CC += xpcom/threads/nsAutoLock.cpp +SRC_CC += xpcom/threads/nsEnvironment.cpp +SRC_CC += xpcom/threads/nsEventQueue.cpp +SRC_CC += xpcom/threads/nsEventQueueService.cpp +SRC_CC += xpcom/threads/nsProcessCommon.cpp +SRC_CC += xpcom/threads/nsThread.cpp +SRC_CC += xpcom/threads/nsTimerImpl.cpp +SRC_CC += xpcom/threads/TimerThread.cpp + +FILTERED_OUT_SRC_CC += xpcom/base/nsStackFrameWin.cpp +FILTERED_OUT_SRC_CC += xpcom/ds/nsPersistentProperties.cpp +FILTERED_OUT_SRC_CC += xpcom/ds/nsTextFormatter.cpp + +SRC_CC := $(filter-out $(FILTERED_OUT_SRC_CC), $(SRC_CC)) + +SRC_C += nsprpub/lib/ds/plarena.c +SRC_C += nsprpub/lib/libc/src/strccmp.c +SRC_C += nsprpub/lib/libc/src/strccmp.c +SRC_C += nsprpub/lib/libc/src/strcmp.c +SRC_C += nsprpub/lib/libc/src/strdup.c +SRC_C += nsprpub/pr/src/io/prfdcach.c +SRC_C += nsprpub/pr/src/io/priometh.c +SRC_C += nsprpub/pr/src/io/prlog.c +SRC_C += nsprpub/pr/src/io/prmmap.c +SRC_C += nsprpub/pr/src/io/prmwait.c +SRC_C += nsprpub/pr/src/io/prprf.c +SRC_C += nsprpub/pr/src/io/prstdio.c +SRC_C += nsprpub/pr/src/malloc/prmem.c +SRC_C += nsprpub/pr/src/md/prosdep.c +SRC_C += nsprpub/pr/src/md/unix/unix.c +SRC_C += nsprpub/pr/src/md/unix/unix_errors.c +SRC_C += nsprpub/pr/src/misc/pratom.c +SRC_C += nsprpub/pr/src/misc/prdtoa.c +SRC_C += nsprpub/pr/src/misc/prenv.c +SRC_C += nsprpub/pr/src/misc/prerr.c +SRC_C += nsprpub/pr/src/misc/prerror.c +SRC_C += nsprpub/pr/src/misc/prerrortable.c +SRC_C += nsprpub/pr/src/misc/prinit.c +SRC_C += nsprpub/pr/src/misc/prinrval.c +SRC_C += nsprpub/pr/src/misc/prlog2.c +SRC_C += nsprpub/pr/src/misc/prlong.c +SRC_C += nsprpub/pr/src/misc/prnetdb.c +SRC_C += nsprpub/pr/src/pthreads/ptio.c +SRC_C += nsprpub/pr/src/pthreads/ptsynch.c +SRC_C += nsprpub/pr/src/pthreads/ptthread.c +SRC_C += nsprpub/pr/src/threads/prcmon.c +SRC_C += nsprpub/pr/src/threads/prrwlock.c +SRC_C += nsprpub/pr/src/threads/prtpd.c +SRC_C += xpcom/ds/pldhash.c +SRC_C += xpcom/threads/plevent.c + +vpath %.cpp $(XPCOM_DIR) +vpath %.c $(XPCOM_DIR) + +INC_DIR += $(REP_DIR)/src/virtualbox6 +SRC_CC += xpcom_stubs.cc +vpath xpcom_stubs.cc $(REP_DIR)/src/virtualbox6 + +INC_DIR += $(XPCOM_DIR) +INC_DIR += $(XPCOM_DIR)/nsprpub/pr/include/private +INC_DIR += $(XPCOM_DIR)/nsprpub/pr/include/md +INC_DIR += $(XPCOM_DIR)/xpcom/build +INC_DIR += $(XPCOM_DIR)/xpcom/ds +INC_DIR += $(XPCOM_DIR)/xpcom/io +INC_DIR += $(XPCOM_DIR)/xpcom/base +INC_DIR += $(XPCOM_DIR)/xpcom/threads +INC_DIR += $(XPCOM_DIR)/xpcom/proxy/src +INC_DIR += $(XPCOM_DIR)/xpcom/components +INC_DIR += $(XPCOM_DIR)/ipc/ipcd/client/src +INC_DIR += $(XPCOM_DIR)/ipc/ipcd/shared/src +INC_DIR += $(XPCOM_DIR)/ipc/ipcd/extensions/lock/src +INC_DIR += $(XPCOM_DIR)/ipc/ipcd/extensions/transmngr/src +INC_DIR += $(XPCOM_DIR)/ipc/ipcd/extensions/transmngr/common +INC_DIR += $(XPCOM_DIR)/ipc/ipcd/extensions/dconnect/src + +CC_OPT += -D_PR_PTHREADS +CC_OPT += -DMOZ_DLL_SUFFIX= '-DMOZ_USER_DIR=""' + +CC_OPT_xpcom/ds/nsQuickSort := -Dregister= + +CC_OPT_nsprpub/pr/src/md/unix/unix.c := -Wno-incompatible-pointer-types +CC_OPT_nsprpub/pr/src/pthreads/ptthread.c := -Wno-incompatible-pointer-types + +CC_WARN := +CC_C_WARN := -Wno-pointer-to-int-cast +CC_CXX_WARN := -Wno-stringop-overflow -Wno-literal-suffix -Wno-invalid-offsetof + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/mk/virtualbox6-zlib.mk b/repos/ports/lib/mk/virtualbox6-zlib.mk new file mode 100644 index 0000000000..f1af06b9aa --- /dev/null +++ b/repos/ports/lib/mk/virtualbox6-zlib.mk @@ -0,0 +1,9 @@ +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +ZLIB_DIR = $(VIRTUALBOX_DIR)/src/libs/zlib-1.2.11 +INC_DIR += $(ZLIB_DIR) +SRC_C = $(notdir $(wildcard $(ZLIB_DIR)/*.c)) + +vpath % $(ZLIB_DIR) + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/ports/virtualbox6.hash b/repos/ports/ports/virtualbox6.hash new file mode 100644 index 0000000000..69f0a04f07 --- /dev/null +++ b/repos/ports/ports/virtualbox6.hash @@ -0,0 +1 @@ +c9f6708c2753758e31b59eb38dc1abcca821a913 diff --git a/repos/ports/ports/virtualbox6.port b/repos/ports/ports/virtualbox6.port new file mode 100644 index 0000000000..5d63f0b317 --- /dev/null +++ b/repos/ports/ports/virtualbox6.port @@ -0,0 +1,280 @@ +LICENSE := GPLv2 +VERSION := 6.1.14 +DOWNLOADS := virtualbox.archive virtualbox_sdk.archive + +VIRTUALBOX_TBZ2 := VirtualBox-$(VERSION).tar.bz2 +VIRTUALBOX_SDK_ZIP := VirtualBoxSDK-$(VERSION)-140239.zip + +URL(virtualbox) := http://download.virtualbox.org/virtualbox/$(VERSION)/$(VIRTUALBOX_TBZ2) +DIR(virtualbox) := src/virtualbox6 +SHA(virtualbox) := 91fa05bcfce36316ca93e3927c9550ea66286fff4c5bec900b753fca278ce1a0 + +URL(virtualbox_sdk) := http://download.virtualbox.org/virtualbox/$(VERSION)/$(VIRTUALBOX_SDK_ZIP) +DIR(virtualbox_sdk) := src/virtualbox6_sdk +SHA(virtualbox_sdk) := 935c210fda2b0fbed42c4bc6acdf7d1fd2b197e348ad4c42b4be4c4d2ffd2c75 + +PATCHES_DIR := src/virtualbox6/patches +PATCHES := $(addprefix $(PATCHES_DIR)/, $(shell cat $(REP_DIR)/$(PATCHES_DIR)/series)) +PATCH_OPT := -p1 + +$(call check_tool,xsltproc) +$(call check_tool,yasm) +$(call check_tool,iasl) + +VBOX_MAIN_GLUE := AutoLock EventQueue string xpcom/helpers com ErrorInfo +VBOX_MAIN_GLUE += NativeEventQueue GetVBoxUserHomeDirectory + +VBOX_MAIN_ALL := AuthLibrary AutoCaller DisplayResampleImage DisplayUtils +VBOX_MAIN_ALL += PCIDeviceAttachmentImpl ProgressImpl SharedFolderImpl +VBOX_MAIN_ALL += ThreadTask VirtualBoxBase GlobalStatusConversion +VBOX_MAIN_ALL += EventImpl Global HashedPw SecretKeyStore +VBOX_MAIN_ALL += VirtualBoxErrorInfoImpl + +VBOX_MAIN_CLI := AdditionsFacilityImpl BusAssignmentManager +VBOX_MAIN_CLI += ConsoleImpl ConsoleImpl2 ConsoleVRDPServer +VBOX_MAIN_CLI += DisplayImpl DisplayImplLegacy DisplaySourceBitmapImpl +VBOX_MAIN_CLI += DrvAudioVRDE EmulatedUSBImpl GuestCtrlImpl GuestImpl +VBOX_MAIN_CLI += HGCM HGCMThread HGCMObjects +VBOX_MAIN_CLI += KeyboardImpl SessionImpl VMMDevInterface +VBOX_MAIN_CLI += MouseImpl MachineDebuggerImpl +VBOX_MAIN_CLI += USBDeviceImpl UsbWebcamInterface VBoxDriversRegister +VBOX_MAIN_CLI += RemoteUSBDeviceImpl RemoteUSBBackend ClientTokenHolder +VBOX_MAIN_CLI += GuestCtrlPrivate +VBOX_MAIN_CLI += GuestDirectoryImpl +VBOX_MAIN_CLI += GuestDnDPrivate +VBOX_MAIN_CLI += GuestFileImpl +VBOX_MAIN_CLI += GuestProcessImpl +VBOX_MAIN_CLI += GuestDnDSourceImpl +VBOX_MAIN_CLI += GuestFsObjInfoImpl +VBOX_MAIN_CLI += GuestSessionImpl +VBOX_MAIN_CLI += GuestSessionImplTasks +VBOX_MAIN_CLI += GuestDnDTargetImpl + +VBOX_MAIN_SRV := AudioAdapterImpl ClientToken DHCPServerImpl Matching +VBOX_MAIN_SRV += MediumAttachmentImpl NATEngineImpl NATNetworkImpl +VBOX_MAIN_SRV += BandwidthControlImpl GuestOSTypeImpl HostUSBDeviceImpl +VBOX_MAIN_SRV += MediumFormatImpl NetworkAdapterImpl SnapshotImpl +VBOX_MAIN_SRV += BandwidthGroupImpl MachineImplCloneVM MediumImpl +VBOX_MAIN_SRV += NetworkServiceRunner StorageControllerImpl VirtualBoxImpl +VBOX_MAIN_SRV += BIOSSettingsImpl MachineImpl MediumLock ParallelPortImpl +VBOX_MAIN_SRV += SystemPropertiesImpl VRDEServerImpl TokenImpl SerialPortImpl +VBOX_MAIN_SRV += USBControllerImpl USBDeviceFilterImpl USBDeviceFiltersImpl +VBOX_MAIN_SRV += DHCPConfigImpl PerformanceImpl Performance RecordingSettingsImpl +VBOX_MAIN_SRV += HostImpl GraphicsAdapterImpl RecordingScreenSettingsImpl +VBOX_MAIN_SRV += HostDnsService HostNetworkInterfaceImpl MediumIOImpl +VBOX_MAIN_SRV += DataStreamImpl HostPower ProgressProxyImpl +VBOX_MAIN_SRV += os2/PerformanceOs2 ClientWatcher + +VBOX_MAIN_INC := AdditionsFacilityImpl AudioAdapterImpl AuthLibrary +VBOX_MAIN_INC += AutoCaller AutostartDb AutoStateDep BandwidthControlImpl +VBOX_MAIN_INC += BandwidthGroupImpl BIOSSettingsImpl BusAssignmentManager +VBOX_MAIN_INC += ClientToken ConsoleImpl DHCPServerImpl DisplayImpl HostImpl +VBOX_MAIN_INC += DisplayUtils DrvAudioVRDE EventImpl ExtPackManagerImpl Global +VBOX_MAIN_INC += GuestCtrlImplPrivate GuestDirectoryImpl LoggingNew +VBOX_MAIN_INC += GuestFileImpl GuestFsObjInfoImpl GuestImpl GuestOSTypeImpl +VBOX_MAIN_INC += GuestSessionImpl HashedPw KeyboardImpl MachineImplCloneVM +VBOX_MAIN_INC += HGCM HGCMThread HGCMObjects +VBOX_MAIN_INC += MachineImpl MediumAttachmentImpl MediumFormatImpl MediumImpl +VBOX_MAIN_INC += MediumLock MouseImpl NATEngineImpl NATNetworkImpl +VBOX_MAIN_INC += NetworkAdapterImpl NetworkServiceRunner +VBOX_MAIN_INC += objectslist ObjectState vector netif +VBOX_MAIN_INC += ParallelPortImpl PCIDeviceAttachmentImpl Performance +VBOX_MAIN_INC += ProgressImpl ProgressProxyImpl QMTranslator SnapshotImpl +VBOX_MAIN_INC += SecretKeyStore SerialPortImpl SessionImpl SharedFolderImpl +VBOX_MAIN_INC += StorageControllerImpl SystemPropertiesImpl TokenImpl VMMDev +VBOX_MAIN_INC += UsbWebcamInterface +VBOX_MAIN_INC += USBControllerImpl USBDeviceFilterImpl USBDeviceFiltersImpl +VBOX_MAIN_INC += USBIdDatabase USBProxyService VirtualBoxImpl VRDEServerImpl GuestProcessImpl +VBOX_MAIN_INC += USBDeviceImpl HostUSBDeviceImpl Matching Wrapper +VBOX_MAIN_INC += RemoteUSBDeviceImpl RemoteUSBBackend ConsoleVRDPServer +VBOX_MAIN_INC += MachineDebuggerImpl EmulatedUSBImpl +VBOX_MAIN_INC += ThreadTask USBProxyBackend +VBOX_MAIN_INC += RecordingSettingsImpl GraphicsAdapterImpl PerformanceImpl +VBOX_MAIN_INC += AudioDriver GuestSessionImplTasks ClientTokenHolder +VBOX_MAIN_INC += DHCPConfigImpl MachineImplMoveVM MediumIOImpl +VBOX_MAIN_INC += MachineLaunchVMCommonWorker ClientWatcher +VBOX_MAIN_INC += CloudProviderManagerImpl HostNetworkInterfaceImpl +VBOX_MAIN_INC += HostVideoInputDeviceImpl HostPower HostHardwareLinux +VBOX_MAIN_INC += RecordingScreenSettingsImpl DataStreamImpl +VBOX_MAIN_INC += GuestDnDSourceImpl GuestDnDTargetImpl GuestDnDPrivate +VBOX_MAIN_INC += VirtualBoxBase VirtualBoxErrorInfoImpl + +VBOX_SRC_VBOX := VMM Devices Runtime GuestHost/HGSMI GuestHost/DragAndDrop +VBOX_SRC_VBOX += Storage Disassembler +VBOX_SRC_VBOX += HostDrivers/Support +VBOX_SRC_VBOX += HostServices/SharedFolders Main/xml/Settings.cpp +VBOX_SRC_VBOX += HostServices/SharedClipboard +VBOX_SRC_VBOX += HostServices/GuestProperties +VBOX_SRC_VBOX += HostServices/common/message.cpp +VBOX_SRC_VBOX += NetworkServices/Dhcpd +VBOX_SRC_VBOX += Main/xml/VirtualBox-settings.xsd Main/xml/SchemaDefs.xsl +VBOX_SRC_VBOX += Main/idl/docstrip.xsl Main/idl/VirtualBox.xidl +VBOX_SRC_VBOX += Main/idl/comimpl.xsl +VBOX_SRC_VBOX += Main/idl/apiwrap-server.xsl +VBOX_SRC_VBOX += Main/idl/typemap-shared.inc.xsl +VBOX_SRC_VBOX += Main/src-server/HostDnsService.h +VBOX_SRC_VBOX += $(addsuffix .h, $(addprefix Main/include/, $(VBOX_MAIN_INC))) +VBOX_SRC_VBOX += $(addsuffix .cpp, $(addprefix Main/src-client/, $(VBOX_MAIN_CLI))) +VBOX_SRC_VBOX += $(addsuffix .cpp, $(addprefix Main/src-server/, $(VBOX_MAIN_SRV))) +VBOX_SRC_VBOX += $(addsuffix .cpp, $(addprefix Main/src-all/, $(VBOX_MAIN_ALL))) +VBOX_SRC_VBOX += $(addsuffix .cpp, $(addprefix Main/glue/, $(VBOX_MAIN_GLUE))) + +VBOX_INC := types.h cdefs.h hgcmsvc.h err.h dis.h disopcode.h log.h sup.h pci.h +VBOX_INC += param.h ostypes.h VMMDev.h vusb.h dbg.h version.h scsiinline.h +VBOX_INC += bioslogo.h scsi.h shflsvc.h vd.h vdmedia.h vd-common.h +VBOX_INC += vd-plugin.h vd-ifs.h vd-ifs-internal.h vd-image-backend.h +VBOX_INC += vd-cache-backend.h vd-filter-backend.h msi.h asmdefs.mac err.mac +VBOX_INC += settings.h VBoxAuth.h VBoxTpG.h +VBOX_INC += usb.h usbfilter.h vrdpusb.h AssertGuest.h bios.h ata.h vscsi.h +VBOX_INC += RemoteDesktop Graphics ExtPack/ExtPack.h VMMDevCoreTypes.h +VBOX_INC += VBoxGuestCoreTypes.h intnet.h + +VBOX_INC_COM := array.h assert.h AutoLock.h ErrorInfo.h EventQueue.h Guid.h +VBOX_INC_COM += list.h MultiResult.h string.h defs.h ptr.h VirtualBox.h com.h +VBOX_INC_COM += utils.h listeners.h NativeEventQueue.h + +VBOX_CONTENT := $(addprefix src/VBox/,$(VBOX_SRC_VBOX)) +VBOX_CONTENT += $(addprefix include/VBox/, $(VBOX_INC)) +VBOX_CONTENT += $(addprefix include/VBox/com/, $(VBOX_INC_COM)) +VBOX_CONTENT += include/VBox/HostServices/ +VBOX_CONTENT += include/VBox/GuestHost/ + +VBOX_CONTENT += src/libs/zlib-1.2.11 src/libs/liblzf-3.4 src/libs/libxml2-2.9.4 +VBOX_CONTENT += src/libs/xpcom18a4 +VBOX_CONTENT += include/VBox/vmm include/iprt Version.kmk +VBOX_CONTENT += COPYING + + +TAR_OPT(virtualbox) := \ + --strip-components 1 \ + $(addprefix $(VIRTUALBOX_TBZ2:.tar.bz2=)/,$(VBOX_CONTENT)) + +UNZIP_OPT(virtualbox_sdk) := $(VIRTUALBOX_SDK_ZIP) "sdk/bindings/xpcom/include*" \# + + +default : additional_steps +additional_steps : $(DOWNLOADS) + $(VERBOSE)xsltproc --stringparam mode declare \ + -o src/virtualbox6/src/VBox/Main/xml/SchemaDefs.h \ + src/virtualbox6/src/VBox/Main/xml/SchemaDefs.xsl \ + src/virtualbox6/src/VBox/Main/xml/VirtualBox-settings.xsd + $(VERBOSE)xsltproc -o src/virtualbox6/VirtualBox_stripped.xidl \ + src/virtualbox6/src/VBox/Main/idl/docstrip.xsl \ + src/virtualbox6/src/VBox/Main/idl/VirtualBox.xidl + $(VERBOSE)xsltproc \ + -o src/virtualbox6/src/VBox/Runtime/common/err/errmsgvboxcomdata.h \ + src/virtualbox6/src/VBox/Runtime/VBox/errmsgvboxcom.xsl \ + src/virtualbox6/VirtualBox_stripped.xidl + $(VERBOSE)xsltproc --stringparam G_kind VBoxEventHeader \ + -o src/virtualbox6/src/VBox/Main/include/VBoxEvents.h \ + src/virtualbox6/src/VBox/Main/idl/comimpl.xsl \ + src/virtualbox6/VirtualBox_stripped.xidl + $(VERBOSE)xsltproc --stringparam G_kind VBoxEvent \ + -o src/virtualbox6/src/VBox/Main/VBoxEvents.cpp \ + src/virtualbox6/src/VBox/Main/idl/comimpl.xsl \ + src/virtualbox6/VirtualBox_stripped.xidl + $(VERBOSE)xsltproc --stringparam KBUILD_HOST genode \ + --stringparam generating "headers" -o src/virtualbox6/VBoxAPIWrap/apiwrappers-headers \ + src/virtualbox6/src/VBox/Main/idl/apiwrap-server.xsl \ + src/virtualbox6/VirtualBox_stripped.xidl + $(VERBOSE)xsltproc --stringparam KBUILD_HOST genode \ + --stringparam generating "sources" --param reminder 0 \ + -o src/virtualbox6/VBoxAPIWrap/apiwrappers-sources-even \ + src/virtualbox6/src/VBox/Main/idl/apiwrap-server.xsl \ + src/virtualbox6/VirtualBox_stripped.xidl + $(VERBOSE)xsltproc --stringparam KBUILD_HOST genode \ + --stringparam generating "sources" --param reminder 1 \ + -o src/virtualbox6/VBoxAPIWrap/apiwrappers-sources-odd \ + src/virtualbox6/src/VBox/Main/idl/apiwrap-server.xsl \ + src/virtualbox6/VirtualBox_stripped.xidl + $(VERBOSE)mkdir -p src/virtualbox6/VBoxAPIWrap ; \ + cd src/virtualbox6 ; \ + csplit -s -n 1 -f "VBoxAPIWrap/xx" VBoxAPIWrap/apiwrappers-headers '/##### ENDFILE.*$$/' '{*}' && \ + i=0 && \ + for f in $$(grep "BEGINFILE \"" VBoxAPIWrap/apiwrappers-headers | sed "s,//.*BEGINFILE \",,g" | sed "s,\",,g"); do \ + mv "VBoxAPIWrap/xx$$((i++))" "VBoxAPIWrap/$$f"; \ + done && \ + rm "VBoxAPIWrap/xx$$((i))" ; \ + csplit -s -n 1 -f "VBoxAPIWrap/xx" VBoxAPIWrap/apiwrappers-sources-even '/##### ENDFILE.*$$/' '{*}' && \ + i=0 && \ + for f in $$(grep "BEGINFILE \"" VBoxAPIWrap/apiwrappers-sources-even | sed "s,//.*BEGINFILE \",,g" | sed "s,\",,g"); do \ + mv "VBoxAPIWrap/xx$$((i++))" "VBoxAPIWrap/$$f"; \ + done && \ + rm "VBoxAPIWrap/xx$$((i))" ; \ + csplit -s -n 1 -f "VBoxAPIWrap/xx" VBoxAPIWrap/apiwrappers-sources-odd '/##### ENDFILE.*$$/' '{*}' && \ + i=0 && \ + for f in $$(grep "BEGINFILE \"" VBoxAPIWrap/apiwrappers-sources-odd | sed "s,//.*BEGINFILE \",,g" | sed "s,\",,g"); do \ + mv "VBoxAPIWrap/xx$$((i++))" "VBoxAPIWrap/$$f"; \ + done && \ + rm "VBoxAPIWrap/xx$$((i))" + + +# +# Generate IEMInstructionStatisticsTmpl.h from the IEM implementation +# +# The sed script is based in VBox/VMM/Makefile.kmk. +# + +default: src/virtualbox6/src/VBox/VMM/include/IEMInstructionStatisticsTmpl.h + +IEM_INSTRUCTIONS_CPP_H := $(addprefix src/virtualbox6/src/VBox/VMM/VMMAll/, \ + IEMAllInstructions.cpp.h \ + IEMAllInstructionsOneByte.cpp.h \ + IEMAllInstructionsTwoByte0f.cpp.h \ + IEMAllInstructionsThree0f38.cpp.h \ + IEMAllInstructionsThree0f3a.cpp.h \ + IEMAllInstructionsVexMap1.cpp.h \ + IEMAllInstructionsVexMap2.cpp.h \ + IEMAllInstructionsVexMap3.cpp.h \ + IEMAllInstructions3DNow.cpp.h) + +define IEM_INSTRUCTION_STATISTICS_TMPL_HEADER +/* Warning: autogenerated by ports/ports/virtualbox6.port */ +#define IEM_DO_INSTR_STAT0(f,u,l,fd,fi) IEM_DO_INSTR_STAT(l, #l) +#define IEM_DO_INSTR_STAT1(f,u,l,o1,fd,fi) IEM_DO_INSTR_STAT(l ## _ ## o1, #l " " #o1) +#define IEM_DO_INSTR_STAT2(f,u,l,o1,o2,fd,fi) IEM_DO_INSTR_STAT(l ## _ ## o1 ## _ ## o2, #l " " #o1 "," #o2) +#define IEM_DO_INSTR_STAT3(f,u,l,o1,o2,o3,fd,fi) IEM_DO_INSTR_STAT(l ## _ ## o1 ## _ ## o2 ## _ ## o3, #l " " #o1 "," #o2 "," #o3) +#define IEM_DO_INSTR_STAT4(f,u,l,o1,o2,o3,o4,fd,fi) IEM_DO_INSTR_STAT(l ## _ ## o1 ## _ ## o2 ## _ ## o3 ## _ ## o4, #l " " #o1 "," #o2 "," #o3 "," #o4) +#define IEM_DO_INSTR_STAT0EX(s,m,f,u,l,fd,fi) IEM_DO_INSTR_STAT(s,m) +#define IEM_DO_INSTR_STAT1EX(s,m,f,u,l,o1,fd,fi) IEM_DO_INSTR_STAT(s,m) +#define IEM_DO_INSTR_STAT2EX(s,m,f,u,l,o1,o2,fd,fi) IEM_DO_INSTR_STAT(s,m) +#define IEM_DO_INSTR_STAT3EX(s,m,f,u,l,o1,o2,o3,fd,fi) IEM_DO_INSTR_STAT(s,m) +#define IEM_DO_INSTR_STAT4EX(s,m,f,u,l,o1,o2,o3,o4,fd,fi) IEM_DO_INSTR_STAT(s,m) +endef + +define IEM_INSTRUCTION_STATISTICS_TMPL_FOOTER +#undef IEM_DO_INSTR_STAT0 +#undef IEM_DO_INSTR_STAT1 +#undef IEM_DO_INSTR_STAT2 +#undef IEM_DO_INSTR_STAT3 +#undef IEM_DO_INSTR_STAT4 +#undef IEM_DO_INSTR_STAT0EX +#undef IEM_DO_INSTR_STAT1EX +#undef IEM_DO_INSTR_STAT2EX +#undef IEM_DO_INSTR_STAT3EX +#undef IEM_DO_INSTR_STAT4EX +endef + +define NEWLINE + + +endef + +src/virtualbox6/src/VBox/VMM/include/IEMInstructionStatisticsTmpl.h: additional_steps + $(VERBOSE)( \ + echo -e '$(subst $(NEWLINE),\n,$(IEM_INSTRUCTION_STATISTICS_TMPL_HEADER))'; \ + sed \ + -e '/IEMOP_MNEMONIC\(\|[01234]\|[01234]EX\)(/!d' \ + -e ':look-for-end-of-invocation' \ + -e '/)/bend-of-invocation' \ + -e 'N' \ + -e 'blook-for-end-of-invocation' \ + -e ':end-of-invocation' \ + -e 's/\n/ /g' \ + -e 's/ */ /g' \ + -e 's/^.*IEMOP_MNEMONIC\(\|[01234]\|[01234]EX\)(/IEM_DO_INSTR_STAT\1(/' \ + -e 's/;.*$(DOLLAR)//' \ + $(IEM_INSTRUCTIONS_CPP_H) | sort ; \ + echo -e '$(subst $(NEWLINE),\n,$(IEM_INSTRUCTION_STATISTICS_TMPL_FOOTER))' \ + ) > $@ + diff --git a/repos/ports/recipes/src/vbox6/content.mk b/repos/ports/recipes/src/vbox6/content.mk new file mode 100644 index 0000000000..08fb66186d --- /dev/null +++ b/repos/ports/recipes/src/vbox6/content.mk @@ -0,0 +1,77 @@ +LIB_MK_FILES := $(notdir $(wildcard $(REP_DIR)/lib/mk/virtualbox6*)) +LIB_MK_ARCH_FILES := $(notdir $(wildcard $(REP_DIR)/lib/mk/spec/x86_64/virtualbox6*)) + +MIRROR_FROM_REP_DIR := $(addprefix lib/mk/,$(LIB_MK_FILES)) \ + $(addprefix lib/mk/spec/x86_64/,$(LIB_MK_ARCH_FILES)) + +content: $(MIRROR_FROM_REP_DIR) + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +content: disable_assertions + +disable_assertions: $(MIRROR_FROM_REP_DIR) + #TODO + #rm lib/mk/virtualbox6-debug.inc + #touch lib/mk/virtualbox6-debug.inc + +PORT_DIR := $(call port_dir,$(REP_DIR)/ports/virtualbox6) + +content: src/virtualbox6 src/virtualbox6_sdk + +src/virtualbox6: + mkdir -p $(dir $@) + cp -r $(REP_DIR)/$@ $(dir $@) + cp -r $(PORT_DIR)/$@ $(dir $@) + +src/virtualbox6_sdk: + mkdir -p $(dir $@) + cp -r $(PORT_DIR)/$@ $(dir $@) + +MIRROR_FROM_LIBPORTS := lib/mk/libc-mem.mk \ + lib/mk/libc-common.inc \ + src/lib/libc/internal/init.h \ + src/lib/libc/internal/mem_alloc.h \ + src/lib/libc/internal/monitor.h \ + src/lib/libc/internal/pthread.h \ + src/lib/libc/internal/thread_create.h \ + src/lib/libc/internal/timer.h \ + src/lib/libc/internal/types.h \ + src/lib/libc/libc_mem_alloc.cc \ + lib/import/import-qemu-usb_include.mk \ + lib/mk/qemu-usb_include.mk \ + lib/mk/qemu-usb.mk \ + include/qemu \ + src/lib/qemu-usb + +content: $(MIRROR_FROM_LIBPORTS) + +$(MIRROR_FROM_LIBPORTS): + mkdir -p $(dir $@) + cp -r $(GENODE_DIR)/repos/libports/$@ $(dir $@) + +QEMU_USB_PORT_DIR := $(call port_dir,$(GENODE_DIR)/repos/libports/ports/qemu-usb) + +MIRROR_FROM_QEMU_USB_PORT_DIR := src/lib/qemu + +content: $(MIRROR_FROM_QEMU_USB_PORT_DIR) + +$(MIRROR_FROM_QEMU_USB_PORT_DIR): + mkdir -p $(dir $@) + cp -r $(QEMU_USB_PORT_DIR)/$@ $(dir $@) + +MIRROR_FROM_OS := src/drivers/ps2/scan_code_set_1.h \ + include/pointer/shape_report.h \ + +content: $(MIRROR_FROM_OS) + +$(MIRROR_FROM_OS): + mkdir -p $(dir $@) + cp -r $(GENODE_DIR)/repos/os/$@ $(dir $@) + +content: LICENSE + +LICENSE: + echo "GNU GPL version 2, see src/app/virtualbox/COPYING" > $@ + diff --git a/repos/ports/recipes/src/vbox6/hash b/repos/ports/recipes/src/vbox6/hash new file mode 100644 index 0000000000..41c70ed52e --- /dev/null +++ b/repos/ports/recipes/src/vbox6/hash @@ -0,0 +1 @@ +2021-02-23 4a5f1c7e529bb1a2419568f60d5633671549fb62 diff --git a/repos/ports/recipes/src/vbox6/used_apis b/repos/ports/recipes/src/vbox6/used_apis new file mode 100644 index 0000000000..d8ed7e0240 --- /dev/null +++ b/repos/ports/recipes/src/vbox6/used_apis @@ -0,0 +1,16 @@ +base +blit +framebuffer_session +gui_session +input_session +libc +libiconv +nic_session +nitpicker_gfx +os +report_session +stdcxx +timer_session +usb_session +vfs +vm_session diff --git a/repos/ports/run/virtualbox6.run b/repos/ports/run/virtualbox6.run new file mode 100644 index 0000000000..36bd9c3a85 --- /dev/null +++ b/repos/ports/run/virtualbox6.run @@ -0,0 +1,300 @@ +assert_spec x86_64 + +set use_net 0 +set use_overlay 0 +set use_serial 1 +set use_top 1 + +create_boot_directory + + +set depot_archives { } + +lappend depot_archives [depot_user]/pkg/[drivers_interactive_pkg] +lappend depot_archives [depot_user]/pkg/themed_wm +lappend depot_archives [depot_user]/src/[base_src] +lappend depot_archives [depot_user]/src/clipboard +lappend depot_archives [depot_user]/src/init +lappend depot_archives [depot_user]/src/libc +lappend depot_archives [depot_user]/src/nitpicker +lappend depot_archives [depot_user]/src/report_rom +lappend depot_archives [depot_user]/src/vfs_import +lappend depot_archives [depot_user]/src/vfs_pipe + +lappend_if [expr $use_net] depot_archives [depot_user]/src/ipxe_nic_drv +lappend_if [expr $use_net] depot_archives [depot_user]/src/nic_router + +import_from_depot $depot_archives + + +set build_components { virtualbox6 } + +lappend_if [expr $use_top] build_components app/top +lappend_if [expr $use_serial] build_components server/log_terminal +lappend_if [have_spec x86] build_components drivers/rtc + +build $build_components + +set config { + + + + + + + + + + + } + +append_if [expr $use_top] config { + } + +append config { + + + + + + + + + } + + +append_if [expr $use_top] config { + + + + } + +append config { + + + + + + + + + + + + + + + + + + + } + +append_if [expr $use_net] config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + +append_if [expr $use_serial] config { + + + + + + } + +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + +append_if [expr $use_serial] config { + } + +append config { + + } +append_if [expr $use_overlay] config { + + + + } +append config { + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +file copy -force [genode_dir]/repos/ports/run/virtualbox6.vbox bin/ + +# +# Instruct vesa_drv to use maximum resolution +# +set fd [open bin/fb_drv.config w] +puts $fd {} +close $fd + +# +# Pin the nitpicker focus to the window manager by providing a static focus ROM +# +set fd [open [run_dir]/genode/focus w] +puts $fd " focus\"/>" +close $fd + +set boot_modules { + rtc_drv + virtualbox6 libc.lib.so vfs.lib.so libm.lib.so libiconv.lib.so stdcxx.lib.so + qemu-usb.lib.so + fb_drv.config test.iso virtualbox6.vbox +} + +# platform-specific modules +lappend_if [expr $use_top] boot_modules top + +append_if [expr $use_net] boot_modules { ipxe_nic_drv } +append_if [expr $use_net] boot_modules { nic_router } +append_if [expr $use_serial] boot_modules { log_terminal } +append_if [expr $use_overlay] boot_modules { overlay.vdi } + +build_boot_image $boot_modules + +append qemu_args " -m 3500 -cpu phenom " + +run_genode_until forever diff --git a/repos/ports/run/virtualbox6.vbox b/repos/ports/run/virtualbox6.vbox new file mode 100644 index 0000000000..a589a2023d --- /dev/null +++ b/repos/ports/run/virtualbox6.vbox @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/repos/ports/src/virtualbox6/attempt.h b/repos/ports/src/virtualbox6/attempt.h new file mode 100644 index 0000000000..299bb68492 --- /dev/null +++ b/repos/ports/src/virtualbox6/attempt.h @@ -0,0 +1,38 @@ +/* + * \brief Utility for attempting VirtualBox operations + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-12-11 + * + * The utility avoids repetitive code for checking the return value of + * VirtualBox API functions that are expected to always succeed. + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _ATTEMPT_H_ +#define _ATTEMPT_H_ + +#include + + +class Fatal : Genode::Exception { }; + + +template +static void attempt(FN const &fn, ERR_MSG &&... err_msg) +{ + HRESULT const rc = fn(); + + if (FAILED(rc)) { + Genode::error(err_msg..., " (rc=", rc, ")"); + throw Fatal(); + } +} + +#endif /* _ATTEMPT_H_ */ diff --git a/repos/ports/src/virtualbox6/devices.cc b/repos/ports/src/virtualbox6/devices.cc new file mode 100644 index 0000000000..71e487cb3b --- /dev/null +++ b/repos/ports/src/virtualbox6/devices.cc @@ -0,0 +1,67 @@ +/* + * \brief VirtualBox device models + * \author Norman Feske + * \author Christian Helmuth + * \date 2013-08-20 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* VirtualBox includes */ +#include +#include + +#define REGISTER(device) \ + do { \ + rc = pCallbacks->pfnRegister(pCallbacks, &g_##device); \ + if (RT_FAILURE(rc)) \ + return rc; \ + } while (0) + + +extern "C" int VBoxDevicesRegister(PPDMDEVREGCB pCallbacks, uint32_t u32Version) +{ + int rc = 0; + + /* platform */ + REGISTER(DevicePCI); + REGISTER(DevicePciIch9); + REGISTER(DevicePcArch); + REGISTER(DevicePcBios); + REGISTER(DeviceIOAPIC); + REGISTER(DevicePS2KeyboardMouse); + REGISTER(DevicePIIX3IDE); + REGISTER(DeviceI8254); + REGISTER(DeviceI8259); + REGISTER(DeviceHPET); + REGISTER(DeviceSmc); + REGISTER(DeviceFlash); +#ifdef VBOX_WITH_EFI + REGISTER(DeviceEFI); +#endif + REGISTER(DeviceMC146818); + REGISTER(DeviceVga); + REGISTER(DeviceVMMDev); + REGISTER(DevicePCNet); + REGISTER(DeviceE1000); + REGISTER(DeviceICHAC97); + REGISTER(DeviceHDA); + REGISTER(DeviceOHCI); + REGISTER(DeviceACPI); + REGISTER(DeviceDMA); + REGISTER(DeviceFloppyController); + REGISTER(DeviceSerialPort); + REGISTER(DeviceParallelPort); + REGISTER(DeviceAHCI); + REGISTER(DevicePCIBridge); + REGISTER(DevicePciIch9Bridge); + REGISTER(DeviceGIMDev); + REGISTER(DeviceLPC); + + return VINF_SUCCESS; +} diff --git a/repos/ports/src/virtualbox6/drivers.cc b/repos/ports/src/virtualbox6/drivers.cc new file mode 100644 index 0000000000..eb3deb0648 --- /dev/null +++ b/repos/ports/src/virtualbox6/drivers.cc @@ -0,0 +1,62 @@ +/* + * \brief VirtualBox host drivers + * \author Norman Feske + * \author Christian Helmuth + * \date 2013-08-20 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* VirtualBox includes */ +#include +#include +#include +#include +#include +#include + +#define REGISTER(driver) \ + do { \ + rc = pCallbacks->pfnRegister(pCallbacks, &driver); \ + if (RT_FAILURE(rc)) \ + return rc; \ + } while (0) + + +extern "C" DECLEXPORT(int) VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_t u32Version) +{ + int rc = 0; + + REGISTER(g_DrvMouseQueue); + REGISTER(g_DrvKeyboardQueue); + REGISTER(g_DrvVD); + REGISTER(g_DrvSCSI); + REGISTER(g_DrvHostDVD); + REGISTER(g_DrvHostInterface); + REGISTER(g_DrvAUDIO); + REGISTER(g_DrvHostNullAudio); + REGISTER(g_DrvACPI); + REGISTER(g_DrvAcpiCpu); + REGISTER(g_DrvVUSBRootHub); + REGISTER(g_DrvNamedPipe); + REGISTER(g_DrvTCP); + REGISTER(g_DrvUDP); + REGISTER(g_DrvRawFile); + REGISTER(g_DrvChar); + REGISTER(g_DrvHostSerial); + REGISTER(g_DrvIfTrace); + + REGISTER(Keyboard::DrvReg); + REGISTER(Mouse::DrvReg); + REGISTER(VMMDev::DrvReg); + REGISTER(Console::DrvStatusReg); + REGISTER(Display::DrvReg); + + return VINF_SUCCESS; +} + diff --git a/repos/ports/src/virtualbox6/dummies.cc b/repos/ports/src/virtualbox6/dummies.cc new file mode 100644 index 0000000000..1a1408a7bc --- /dev/null +++ b/repos/ports/src/virtualbox6/dummies.cc @@ -0,0 +1,416 @@ +/* + * \brief Dummy implementations of symbols needed by VirtualBox + * \author Norman Feske + * \author Christian Helmuth + * \date 2013-08-22 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include "stub_macros.h" +#include "util.h" + +static bool const debug = true; + + +/* ApplianceImplExport.cpp */ + +#include "MachineImpl.h" + +HRESULT Machine::exportTo(const ComPtr &aAppliance, + const com::Utf8Str &aLocation, + ComPtr &aDescription) STOP + +/* com.cpp */ + +int com::VBoxLogRelCreate(char const*, char const*, unsigned int, char const*, + char const*, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned long, RTERRINFO*) TRACE(NS_OK) + + +/* DisplayPNGUtil.cpp */ + +#include "DisplayImpl.h" + +int DisplayMakePNG(uint8_t *, uint32_t, uint32_t, uint8_t **, uint32_t *, + uint32_t *, uint32_t *, uint8_t) STOP + + +/* initterm.cpp */ + +#include "VBox/com/com.h" + +HRESULT com::Initialize(uint32_t) TRACE(S_OK) +HRESULT com::Shutdown() STOP + + +/* USBFilter.cpp */ + +#include "VBox/usbfilter.h" + +USBFILTERMATCH USBFilterGetMatchingMethod(PCUSBFILTER, USBFILTERIDX) STOP +char const * USBFilterGetString (PCUSBFILTER, USBFILTERIDX) STOP + +int USBFilterGetNum (PCUSBFILTER, USBFILTERIDX) STOP +void USBFilterInit (PUSBFILTER, USBFILTERTYPE) STOP +bool USBFilterIsMethodNumeric (USBFILTERMATCH) STOP +bool USBFilterIsMethodString (USBFILTERMATCH) STOP +bool USBFilterIsNumericField (USBFILTERIDX) STOP +bool USBFilterIsStringField (USBFILTERIDX) STOP +bool USBFilterMatch (PCUSBFILTER, PCUSBFILTER) STOP +int USBFilterSetIgnore (PUSBFILTER, USBFILTERIDX) STOP +int USBFilterSetNumExact (PUSBFILTER, USBFILTERIDX, uint16_t, bool) STOP +int USBFilterSetNumExpression(PUSBFILTER, USBFILTERIDX, const char *, bool) STOP +int USBFilterSetStringExact (PUSBFILTER, USBFILTERIDX, const char *, bool) STOP +int USBFilterSetStringPattern(PUSBFILTER, USBFILTERIDX, const char *, bool) STOP +int USBFilterSetStringExact (PUSBFILTER, USBFILTERIDX, const char *, bool, bool) STOP +int USBFilterMatchRated (PCUSBFILTER, PCUSBFILTER) STOP + + +/* USBProxyBackend.cpp */ + +#include "USBProxyBackend.h" + +USBProxyBackendFreeBSD::USBProxyBackendFreeBSD() STOP + +USBProxyBackend::USBProxyBackend() STOP +USBProxyBackend::~USBProxyBackend() { } + +HRESULT USBProxyBackend::FinalConstruct() STOP +com::Utf8Str const &USBProxyBackend::i_getAddress() STOP +com::Utf8Str const &USBProxyBackend::i_getId() STOP + +USBProxyBackendUsbIp::USBProxyBackendUsbIp() STOP + + +/* USBProxyService.cpp */ + +#include "USBProxyService.h" + +USBProxyService::USBProxyService(Host* aHost) : mHost(aHost), mDevices(), mBackends() { } +USBProxyService::~USBProxyService() { } + +HRESULT USBProxyService::init() { return VINF_SUCCESS; } +RWLockHandle *USBProxyService::lockHandle() const STOP +HRESULT USBProxyService::autoCaptureDevicesForVM(SessionMachine *) TRACE(S_OK) +HRESULT USBProxyService::captureDeviceForVM(SessionMachine *, IN_GUID, + com::Utf8Str const&) STOP +HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine*, bool, bool) STOP +HRESULT USBProxyService::detachDeviceFromVM(SessionMachine*, IN_GUID, bool) STOP +void *USBProxyService::insertFilter(PCUSBFILTER aFilter) STOP +void USBProxyService::removeFilter(void *aId) STOP +int USBProxyService::getLastError() TRACE(VINF_SUCCESS) +bool USBProxyService::isActive() TRACE(false) +HRESULT USBProxyService::removeUSBDeviceSource(com::Utf8Str const&) STOP +HRESULT USBProxyService::addUSBDeviceSource(com::Utf8Str const&, + com::Utf8Str const&, + com::Utf8Str const&, + std::vector > const&, + std::vector > const&) STOP +HRESULT USBProxyService::getDeviceCollection(std::vector, + std::allocator > >&) STOP + +using USBDeviceSourceList = + std::__cxx11::list >; + +HRESULT USBProxyService::i_saveSettings(USBDeviceSourceList &) TRACE(VINF_SUCCESS) +HRESULT USBProxyService::i_loadSettings(USBDeviceSourceList const &) TRACE(VINF_SUCCESS) + + +/* USBFilter.cpp */ + +#include "VBox/usbfilter.h" + +USBLIB_DECL(USBFILTERTYPE) USBFilterGetFilterType(PCUSBFILTER) STOP +USBLIB_DECL(int) USBFilterSetFilterType(PUSBFILTER, USBFILTERTYPE) STOP + + +/* ApplianceImpl.cpp */ + +HRESULT VirtualBox::createAppliance(ComPtr &) STOP + + +/* CloudProviderManagerImpl.cpp */ + +#include "CloudProviderManagerImpl.h" + +CloudProviderManager::CloudProviderManager() TRACE() +CloudProviderManager::~CloudProviderManager() { } + +HRESULT CloudProviderManager::FinalConstruct() TRACE(VINF_SUCCESS) +void CloudProviderManager::FinalRelease() TRACE() +HRESULT CloudProviderManager::init() TRACE(VINF_SUCCESS) +void CloudProviderManager::uninit() STOP +HRESULT CloudProviderManager::getProviderById (com::Guid const&, ComPtr&) STOP +HRESULT CloudProviderManager::getProviderByName (com::Utf8Str const&, ComPtr&) STOP +HRESULT CloudProviderManager::getProviderByShortName(com::Utf8Str const&, ComPtr&) STOP +HRESULT CloudProviderManager::getProviders(std::vector, + std::allocator > >&) STOP + + +/* NetIf-freebsd.cpp */ + +#include "HostNetworkInterfaceImpl.h" +#include "netif.h" + +int NetIfGetLinkSpeed(const char *, uint32_t *) STOP +int NetIfGetState(const char *, NETIFSTATUS *) STOP +int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *, const Guid &, IProgress **) STOP +int NetIfList(std::__cxx11::list, + std::allocator > >&) TRACE(VINF_SUCCESS) + + +/* fatvfs.cpp */ + +#include "iprt/fsvfs.h" + +RTDECL(int) RTFsFatVolFormat(RTVFSFILE, uint64_t, uint64_t, uint32_t, uint16_t, + uint16_t, RTFSFATTYPE, uint32_t, uint32_t, + uint8_t, uint16_t, uint32_t, PRTERRINFO) STOP + +/* dvm.cpp */ + +#include "iprt/dvm.h" + +RTDECL(uint32_t) RTDvmRelease(RTDVM) STOP +RTDECL(int) RTDvmCreate(PRTDVM, RTVFSFILE, uint32_t, uint32_t) STOP +RTDECL(int) RTDvmMapInitialize(RTDVM, const char *) STOP + + +/* MachineImplMoveVM.cpp */ + +#include "MachineImplMoveVM.h" + +HRESULT MachineMoveVM::init() STOP +void MachineMoveVM::i_MoveVMThreadTask(MachineMoveVM *) STOP + + +/* NetIf-generic.cpp */ + +int NetIfCreateHostOnlyNetworkInterface(VirtualBox *, IHostNetworkInterface **, + IProgress **, const char *) STOP + + +/* systemmem-freebsd.cpp */ + +#include "iprt/system.h" + +RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb) STOP + + +/* HostDnsServiceResolvConf.cpp */ + +#include "HostDnsService.h" + +HostDnsServiceResolvConf::~HostDnsServiceResolvConf() { } + +HRESULT HostDnsServiceResolvConf::init(HostDnsMonitorProxy*, char const*) TRACE(VINF_SUCCESS) +void HostDnsServiceResolvConf::uninit() STOP + + +/* HostVideoInputDeviceImpl.cpp */ + +#include "HostVideoInputDeviceImpl.h" + +using VideoDeviceList = + std::__cxx11::list, + std::allocator > >; + +HRESULT HostVideoInputDevice::queryHostDevices(VirtualBox*, VideoDeviceList *) STOP + + +/* HostUSBDeviceImpl.cpp */ + +#include "HostUSBDeviceImpl.h" + +bool HostUSBDevice::i_isMatch(const USBDeviceFilter::BackupableUSBDeviceFilterData &) STOP + + +/* DhcpOptions.cpp */ + +#undef LOG_GROUP +#include "Dhcpd/DhcpOptions.h" + +DhcpOption *DhcpOption::parse(unsigned char, int, char const*, int*) STOP + + +/* AutostartDb-generic.cpp */ + +#include "AutostartDb.h" + +int AutostartDb::addAutostartVM (char const *) STOP +int AutostartDb::addAutostopVM (char const *) STOP +int AutostartDb::removeAutostopVM (char const *) STOP +int AutostartDb::removeAutostartVM(char const *) STOP + +AutostartDb::AutostartDb() TRACE() +AutostartDb::~AutostartDb() { } +int AutostartDb::setAutostartDbPath(char const*) TRACE(VINF_SUCCESS) + +RT_C_DECLS_BEGIN + +static_assert(sizeof(RTR0PTR) == sizeof(RTR3PTR), "pointer transformation bug"); +static_assert(sizeof(RTR0PTR) == sizeof(void *) , "pointer transformation bug"); +static_assert(sizeof(RTR3PTR) == sizeof(RTR0PTR), "pointer transformation bug"); + +int emR3InitDbg(PVM) TRACE(VINF_SUCCESS) +int SELMR3Init(PVM) TRACE(VINF_SUCCESS) +int SELMR3Term(PVM) TRACE(VINF_SUCCESS) +void SELMR3Relocate(PVM) TRACE() +void SELMR3Reset(PVM) TRACE() + +/* module loader of pluggable device manager */ +int pdmR3LdrInitU(PUVM) TRACE(VINF_SUCCESS) +int PDMR3LdrLoadVMMR0U(PUVM) TRACE(VINF_SUCCESS) +void PDMR3LdrRelocateU(PUVM, RTGCINTPTR) TRACE() +int pdmR3LoadR3U(PUVM, const char *, const char *) TRACE(VINF_SUCCESS) +void pdmR3LdrTermU(PUVM) TRACE() +int PDMR3LdrLoadR0(PUVM, const char *, const char *) TRACE(VINF_SUCCESS) + +char *pdmR3FileR3(const char * file, bool) +{ + char * pv = reinterpret_cast(RTMemTmpAllocZ(1)); + + if (debug) + Genode::log(__func__, ": file ", file, " ", (void *)pv, " ", __builtin_return_address(0)); + + TRACE(pv) +} + +const char * RTBldCfgRevisionStr(void) +{ + return "Genode"; +} + +DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath) +{ + Genode::copy_cstring(pszPath, "/undefined_ProcInitExePath", cchPath); + + return VINF_SUCCESS; +} + +RT_C_DECLS_END + + +/* HostHardwareLinux.cpp */ + +#include "HostHardwareLinux.h" + +int VBoxMainDriveInfo::updateDVDs() TRACE(VINF_SUCCESS) + + +/* buildconfig.cpp */ + +#include + +uint32_t RTBldCfgRevision(void) { return ~0; } +uint32_t RTBldCfgVersionBuild(void) { return ~0; } +uint32_t RTBldCfgVersionMajor(void) { return ~0; } +uint32_t RTBldCfgVersionMinor(void) { return ~0; } + + +/* VDIfTcpNet.cpp */ + +VBOXDDU_DECL(int) VDIfTcpNetInstDefaultCreate(PVDIFINST, PVDINTERFACE *) TRACE(VINF_SUCCESS) + + +/* SharedFolderImpl.cpp */ + +#include + +HRESULT SharedFolder::init(Console*, com::Utf8Str const&, com::Utf8Str const&, + bool, bool, com::Utf8Str const&, bool) TRACE(E_FAIL) + + +/* ConsoleImplTeleporter.cpp */ + +#include + +HRESULT Console::teleport(const com::Utf8Str &, ULONG, const com::Utf8Str &, ULONG, ComPtr &) STOP +HRESULT Console::i_teleporterTrg(PUVM, IMachine *, Utf8Str *, bool, Progress *, bool *) STOP + + +/* DBGFBp.cpp */ + +#include + +int dbgfR3BpInit(VM*) TRACE(VINF_SUCCESS) + + +/* DBGFR3BugCheck.cpp */ + +int dbgfR3BugCheckInit(VM*) TRACE(VINF_SUCCESS) + + +/* dbgcfg.cpp */ + +int RTDbgCfgCreate(PRTDBGCFG, const char *, bool) TRACE(VINF_SUCCESS) +int RTDbgCfgChangeUInt(RTDBGCFG, RTDBGCFGPROP, RTDBGCFGOP, uint64_t) TRACE(VINF_SUCCESS) +int RTDbgCfgChangeString(RTDBGCFG, RTDBGCFGPROP, RTDBGCFGOP, const char *) TRACE(VINF_SUCCESS) + + +/* dbgas.cpp */ + +int RTDbgAsCreate(PRTDBGAS, RTUINTPTR, RTUINTPTR, const char *) TRACE(VINF_SUCCESS) + +const char * RTDbgAsName(RTDBGAS hDbgAs) { return "RTDbgAsName dummy"; } + +uint32_t RTDbgAsRetain(RTDBGAS) { return 1; /* fake handle - UINT32_MAX is invalid */ } +uint32_t RTDbgAsRelease(RTDBGAS) { return 1; /* fake reference counter */ } + + +/* DBGFAddrSpace.cpp */ + +int dbgfR3AsInit(PUVM) TRACE(VINF_SUCCESS) +void dbgfR3AsTerm(PUVM) { } +void dbgfR3AsRelocate(PUVM, RTGCUINTPTR) TRACE() + +int DBGFR3AsSymbolByAddr(PUVM, RTDBGAS, PCDBGFADDRESS, uint32_t, + PRTGCINTPTR, PRTDBGSYMBOL, PRTDBGMOD) TRACE(VERR_NOT_IMPLEMENTED) + +PRTDBGSYMBOL DBGFR3AsSymbolByAddrA(PUVM, RTDBGAS, PCDBGFADDRESS, uint32_t, + PRTGCINTPTR, PRTDBGMOD) +{ + return nullptr; +} + +PRTDBGLINE DBGFR3AsLineByAddrA(PUVM, RTDBGAS, PCDBGFADDRESS, + PRTGCINTPTR, PRTDBGMOD) +{ + return nullptr; +} + + +/* PGMMap.cpp */ + +#include + +VMMR3DECL(int) PGMR3MappingsSize(PVM pVM, uint32_t *pcb) +{ + *pcb = 0; + return VINF_SUCCESS; +} + + +/* PGMSavedState.cpp */ + +#include + +int pgmR3InitSavedState(PVM, uint64_t) TRACE(VINF_SUCCESS) + + +/* nsProxyRelease.cpp */ + +#include "nsProxyRelease.h" + +NS_COM nsresult NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy) STOP diff --git a/repos/ports/src/virtualbox6/dynlib.cc b/repos/ports/src/virtualbox6/dynlib.cc new file mode 100644 index 0000000000..4e57f80b43 --- /dev/null +++ b/repos/ports/src/virtualbox6/dynlib.cc @@ -0,0 +1,37 @@ +/* + * \brief Support to link libraries statically supposed to be dynamic + * \author Alexander Boettcher + * \author Christian Helmuth + * \date 2014-05-13 + */ + +/* + * Copyright (C) 2014-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include + +/* VirtualBox includes */ +#include +#include +#include + +extern "C" { + +int RTLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod) +{ + Genode::error("shared library '", pszFilename, "' not supported"); + return VERR_NOT_SUPPORTED; +} + + +RTDECL(const char *) RTLdrGetSuff(void) +{ + return ".so"; +} + +} /* extern "C" */ diff --git a/repos/ports/src/virtualbox6/include/GenodeImpl.h b/repos/ports/src/virtualbox6/include/GenodeImpl.h new file mode 100644 index 0000000000..c4c4d06e52 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/GenodeImpl.h @@ -0,0 +1,4 @@ +#ifndef ____H_GENODEIMPL +#define ____H_GENODEIMPL + +#endif // !____H_GENODEIMPL diff --git a/repos/ports/src/virtualbox6/include/aio.h b/repos/ports/src/virtualbox6/include/aio.h new file mode 100644 index 0000000000..7679f9cae0 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/aio.h @@ -0,0 +1,46 @@ +#ifndef _AIO_H_ +#define _AIO_H_ + +#include + +extern "C" { + +#define LIO_NOWAIT 0x0 +#define LIO_WRITE 0x1 +#define LIO_READ 0x2 + +#define AIO_CANCELED 0x1 +#define AIO_NOTCANCELED 0x2 +#define AIO_ALLDONE 0x3 + +#define AIO_LISTIO_MAX 16 + +struct aiocb +{ + int aio_fildes; + size_t aio_nbytes; + int aio_lio_opcode; + off_t aio_offset; + + struct sigevent aio_sigevent; + + volatile void *aio_buf; +}; + +int aio_fsync(int op, struct aiocb *aiocbp); + +ssize_t aio_return(struct aiocb *aiocbp); + +int aio_error(const struct aiocb *aiocbp); + +int aio_cancel(int fd, struct aiocb *aiocbp); + +int aio_suspend(const struct aiocb * const aiocb_list[], + int nitems, const struct timespec *timeout); + +int lio_listio(int mode, struct aiocb *const aiocb_list[], + int nitems, struct sigevent *sevp); + +} /* extern "C" */ + +#endif /* _AIO_H_ */ diff --git a/repos/ports/src/virtualbox6/include/dev/acpica/acpiio.h b/repos/ports/src/virtualbox6/include/dev/acpica/acpiio.h new file mode 100644 index 0000000000..8c38b4cbf8 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/dev/acpica/acpiio.h @@ -0,0 +1,41 @@ +/* + * This is merely a stub to successfully compile Devices/PC/DrvACPI.cpp + */ + +#ifndef _DEV__ACPICA__ACPIIO_H_ +#define _DEV__ACPICA__ACPIIO_H_ + +union acpi_battery_ioctl_arg +{ + unsigned unit; + + struct { + unsigned state; + int cap; + } battinfo; + + struct { + unsigned units; + } bif; + + struct { + unsigned volt; + unsigned rate; + } bst; +}; + +/* + * Note that these enum values are not meaningful. + */ +enum { + ACPIIO_BATT_GET_BIF, + ACPIIO_BATT_GET_BST, + ACPIIO_BATT_GET_BATTINFO, + ACPI_BIF_UNITS_MW, + ACPI_BATT_STAT_NOT_PRESENT, + ACPI_BATT_STAT_CHARGING, + ACPI_BATT_STAT_DISCHARG, + ACPI_BATT_STAT_CRITICAL, +}; + +#endif /* _DEV__ACPICA__ACPIIO_H_ */ diff --git a/repos/ports/src/virtualbox6/include/dtrace/VBoxVMM.h b/repos/ports/src/virtualbox6/include/dtrace/VBoxVMM.h new file mode 100644 index 0000000000..0225ded80f --- /dev/null +++ b/repos/ports/src/virtualbox6/include/dtrace/VBoxVMM.h @@ -0,0 +1,9 @@ +#ifndef _DTRACE__VBOXVMM_H_ +#define _DTRACE__VBOXVMM_H_ + +#define VBOXVMM_PDM_IRQ_GET(...) do { } while (0) +#define VBOXVMM_PDM_IRQ_HIGH(...) do { } while (0) +#define VBOXVMM_PDM_IRQ_HILO(...) do { } while (0) +#define VBOXVMM_PDM_IRQ_LOW(...) do { } while (0) + +#endif /* _DTRACE__VBOXVMM_H_ */ diff --git a/repos/ports/src/virtualbox6/include/fb.h b/repos/ports/src/virtualbox6/include/fb.h new file mode 100644 index 0000000000..caec3f8f6f --- /dev/null +++ b/repos/ports/src/virtualbox6/include/fb.h @@ -0,0 +1,344 @@ +/* + * \brief Virtualbox framebuffer implementation for Genode + * \author Alexander Boettcher + * \date 2013-10-16 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#define Framebuffer Fb_Genode +#include +#include +#undef Framebuffer + +#include +#include + +/* VirtualBox includes */ +#include +#include +#include + +typedef Gui::Session::View_handle View_handle; + +class Genodefb : + VBOX_SCRIPTABLE_IMPL(IFramebuffer) +{ + private: + + Genode::Env &_env; + Gui::Connection &_gui; + Fb_Genode::Session &_fb; + View_handle _view; + Fb_Genode::Mode _fb_mode { .area = { 1024, 768 } }; + + /* + * The mode currently used by the VM. Can be smaller than the + * framebuffer mode. + */ + Fb_Genode::Mode _virtual_fb_mode; + + void *_fb_base; + RTCRITSECT _fb_lock; + + ComPtr _display; + ComPtr _display_bitmap; + + void _clear_screen() + { + if (!_fb_base) return; + + size_t const max_h = Genode::min(_fb_mode.area.h(), _virtual_fb_mode.area.h()); + size_t const num_pixels = _fb_mode.area.w() * max_h; + memset(_fb_base, 0, num_pixels * _fb_mode.bytes_per_pixel()); + _fb.refresh(0, 0, _virtual_fb_mode.area.w(), _virtual_fb_mode.area.h()); + } + + void _adjust_buffer() + { + _gui.buffer(_fb_mode, false); + + typedef Gui::Session::Command Command; + + Gui::Rect rect(Gui::Point(0, 0), _fb_mode.area); + + _gui.enqueue(_view, rect); + _gui.execute(); + } + + Fb_Genode::Mode _initial_setup() + { + typedef Gui::Session::Command Command; + + _view = _gui.create_view(); + + _adjust_buffer(); + + _gui.enqueue(_view, View_handle()); + _gui.execute(); + + return _fb_mode; + } + + public: + + NS_DECL_ISUPPORTS + + Genodefb(Genode::Env &env, Gui::Connection &gui, ComPtr const &display) + : + _env(env), + _gui(gui), + _fb(*gui.framebuffer()), + _virtual_fb_mode(_initial_setup()), + _fb_base(env.rm().attach(_fb.dataspace())), + _display(display) + { + int rc = RTCritSectInit(&_fb_lock); + Assert(rc == VINF_SUCCESS); + } + + virtual ~Genodefb() { } + + int w() const { return _fb_mode.area.w(); } + int h() const { return _fb_mode.area.h(); } + + void update_mode(Fb_Genode::Mode mode) + { + Lock(); + + _fb_mode = mode; + + if (_fb_base) + _env.rm().detach(_fb_base); + + _adjust_buffer(); + + try { + _fb_base = _env.rm().attach(_fb.dataspace()); + } catch (...) { + _fb_base = nullptr; + } + + Unlock(); + } + + STDMETHODIMP Lock() + { + return Global::vboxStatusCodeToCOM(RTCritSectEnter(&_fb_lock)); + } + + STDMETHODIMP Unlock() + { + return Global::vboxStatusCodeToCOM(RTCritSectLeave(&_fb_lock)); + } + + STDMETHODIMP NotifyChange(PRUint32 screen, PRUint32, PRUint32, + PRUint32 w, PRUint32 h) override + { + HRESULT result = E_FAIL; + + Lock(); + + /* save the new bitmap reference */ + _display->QuerySourceBitmap(screen, _display_bitmap.asOutParam()); + + bool ok = (w <= (ULONG)_fb_mode.area.w()) && + (h <= (ULONG)_fb_mode.area.h()); + + if (ok) { + Genode::log("fb resize : [", screen, "] ", + _virtual_fb_mode.area, " -> ", + w, "x", h, + " (host: ", _fb_mode.area, ")"); + + if ((w < (ULONG)_fb_mode.area.w()) || + (h < (ULONG)_fb_mode.area.h())) { + /* clear the old content around the new, smaller area. */ + _clear_screen(); + } + + _virtual_fb_mode = Fb_Genode::Mode { .area = { w, h } }; + + result = S_OK; + } else { + Genode::log("fb resize : [", screen, "] ", + _virtual_fb_mode.area, " -> ", + w, "x", h, " ignored" + " (host: ", _fb_mode.area, ")"); + } + + Unlock(); + + /* request appropriate NotifyUpdate() */ + _display->InvalidateAndUpdateScreen(screen); + + return result; + } + + STDMETHODIMP COMGETTER(Capabilities)(ComSafeArrayOut(FramebufferCapabilities_T, enmCapabilities)) override + { + if (ComSafeArrayOutIsNull(enmCapabilities)) + return E_POINTER; + + return S_OK; + } + + STDMETHODIMP COMGETTER(HeightReduction) (ULONG *reduce) override + { + if (!reduce) + return E_POINTER; + + *reduce = 0; + return S_OK; + } + + HRESULT NotifyUpdate(ULONG o_x, ULONG o_y, ULONG width, ULONG height) override + { + if (!_fb_base) return S_OK; + + Lock(); + + if (_display_bitmap.isNull()) { + _clear_screen(); + Unlock(); + return S_OK; + } + + BYTE *pAddress = NULL; + ULONG ulWidth = 0; + ULONG ulHeight = 0; + ULONG ulBitsPerPixel = 0; + ULONG ulBytesPerLine = 0; + BitmapFormat_T bitmapFormat = BitmapFormat_Opaque; + _display_bitmap->QueryBitmapInfo(&pAddress, + &ulWidth, + &ulHeight, + &ulBitsPerPixel, + &ulBytesPerLine, + &bitmapFormat); + + Gui::Area const area_fb = Gui::Area(_fb_mode.area.w(), + _fb_mode.area.h()); + Gui::Area const area_vm = Gui::Area(ulWidth, ulHeight); + + using namespace Genode; + + typedef Pixel_rgb888 Pixel_src; + typedef Pixel_rgb888 Pixel_dst; + + Texture texture((Pixel_src *)pAddress, nullptr, area_vm); + Surface surface((Pixel_dst *)_fb_base, area_fb); + + surface.clip(Surface_base::Rect(Surface_base::Point(o_x, o_y), + Surface_base::Area(width, height))); + + Texture_painter::paint(surface, + texture, + Genode::Color(0, 0, 0), + Surface_base::Point(0, 0), + Texture_painter::SOLID, + false); + + _fb.refresh(o_x, o_y, width, height); + + Unlock(); + + return S_OK; + } + + STDMETHODIMP NotifyUpdateImage(PRUint32 o_x, PRUint32 o_y, + PRUint32 width, PRUint32 height, + PRUint32 imageSize, + PRUint8 *image) override + { + if (!_fb_base) return S_OK; + + Lock(); + + Gui::Area const area_fb = _fb_mode.area; + Gui::Area const area_vm = Gui::Area(width, height); + + using namespace Genode; + + typedef Pixel_rgb888 Pixel_src; + typedef Pixel_rgb888 Pixel_dst; + + Texture texture((Pixel_src *)image, nullptr, area_vm); + Surface surface((Pixel_dst *)_fb_base, area_fb); + + Texture_painter::paint(surface, + texture, + Genode::Color(0, 0, 0), + Gui::Point(o_x, o_y), + Texture_painter::SOLID, + false); + + _fb.refresh(o_x, o_y, area_vm.w(), area_vm.h()); + + Unlock(); + + return S_OK; + } + + STDMETHODIMP COMGETTER(Overlay) (IFramebufferOverlay **) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP COMGETTER(WinId) (PRInt64 *winId) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP VideoModeSupported(ULONG width, ULONG height, + ULONG bpp, BOOL *supported) override + { + if (!supported) + return E_POINTER; + + *supported = ((width <= (ULONG)_fb_mode.area.w()) && + (height <= (ULONG)_fb_mode.area.h())); + + return S_OK; + } + + STDMETHODIMP Notify3DEvent(PRUint32, PRUint32, PRUint8 *) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP ProcessVHWACommand(BYTE *, LONG, BOOL) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP GetVisibleRegion(BYTE *, ULONG, ULONG *) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP SetVisibleRegion(BYTE *, ULONG) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP COMGETTER(PixelFormat) (BitmapFormat_T *format) { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP COMGETTER(BitsPerPixel)(ULONG *bits) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP COMGETTER(BytesPerLine)(ULONG *line) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP COMGETTER(Width)(ULONG *width) override { + Assert(!"FixMe"); + return E_NOTIMPL; } + + STDMETHODIMP COMGETTER(Height)(ULONG *height) override { + Assert(!"FixMe"); + return E_NOTIMPL; } +}; diff --git a/repos/ports/src/virtualbox6/include/global_defs.h b/repos/ports/src/virtualbox6/include/global_defs.h new file mode 100644 index 0000000000..6e9468d708 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/global_defs.h @@ -0,0 +1,34 @@ +/* + * \brief Enforced global definitions + * \author Christian Helmuth + * \date 2020-11-25 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef ___global_defs_h___ +#define ___global_defs_h___ + +#ifdef __cplusplus + +/* + * Prevent inclusion of the Genode::Log definition after the vbox #define + * of 'Log'. Otherwise, the attempt to compile base/log.h will fail. + */ +#include + +/* + * Place hook to return current log configuration to SVC main initialization. + */ +#define VBOXSVC_LOG_DEFAULT vboxsvc_log_default_string() + +extern "C" char const * vboxsvc_log_default_string(); + +#endif /* __cplusplus */ + +#endif /* ___global_defs_h___ */ diff --git a/repos/ports/src/virtualbox6/include/libc/osreldate.h b/repos/ports/src/virtualbox6/include/libc/osreldate.h new file mode 100644 index 0000000000..37ae46b59d --- /dev/null +++ b/repos/ports/src/virtualbox6/include/libc/osreldate.h @@ -0,0 +1,5 @@ +/* + * Override libc's osreldate.h because the libc's param.h as included by the + * original osreldate.h provides a definition of PAGE_SIZE, which collides with + * VirtualBox' iprt/param.h. + */ diff --git a/repos/ports/src/virtualbox6/include/libc/wchar.h b/repos/ports/src/virtualbox6/include/libc/wchar.h new file mode 100644 index 0000000000..2d4bdaa398 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/libc/wchar.h @@ -0,0 +1,21 @@ +/* + * Override the lib'c wchar.h header to work around the type conflict between + * the libc's wint_t (defined as signed integer) and GCC's builtin type + * (defined as unsigned integer). E.g., + * + * COMPILE Runtime/r3/posix/utf8-posix.o + * .../libc/wctype.h:61:5: error: declaration of ‘int iswalnum(wint_t)’ + * conflicts with built-in declaration ‘int iswalnum(unsigned int)’ + * [-Werror=builtin-declaration-mismatch] + */ + +#ifndef _LIBC__WCHAR_H_ +#define _LIBC__WCHAR_H_ + +#include + +typedef __mbstate_t mbstate_t; + +typedef unsigned int wint_t; + +#endif /* _LIBC__WCHAR_H_ */ diff --git a/repos/ports/src/virtualbox6/include/libc/wctype.h b/repos/ports/src/virtualbox6/include/libc/wctype.h new file mode 100644 index 0000000000..125c317b9c --- /dev/null +++ b/repos/ports/src/virtualbox6/include/libc/wctype.h @@ -0,0 +1,5 @@ +/* + * Override the libc's wctype.h header. See the comment in the wchar.h header. + */ + +#include diff --git a/repos/ports/src/virtualbox6/include/package-generated.h b/repos/ports/src/virtualbox6/include/package-generated.h new file mode 100644 index 0000000000..037a9f97a3 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/package-generated.h @@ -0,0 +1,9 @@ +#ifndef ___package_generated_h___ +#define ___package_generated_h___ + +/* + * The definition of 'VBOX_PACKAGE_STRING' is provided via + * 'lib/mk/virtualbox6-common.inc' + */ + +#endif diff --git a/repos/ports/src/virtualbox6/include/product-generated.h b/repos/ports/src/virtualbox6/include/product-generated.h new file mode 100644 index 0000000000..680eafa952 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/product-generated.h @@ -0,0 +1,10 @@ +#ifndef ___product_generated_h___ +#define ___product_generated_h___ + +#define VBOX_VENDOR "Oracle Corporation" +#define VBOX_VENDOR_SHORT "Oracle" +#define VBOX_PRODUCT "Oracle VM VirtualBox" +#define VBOX_BUILD_PUBLISHER "_OSE" +#define VBOX_C_YEAR "2013" + +#endif diff --git a/repos/ports/src/virtualbox6/include/rpc/types.h b/repos/ports/src/virtualbox6/include/rpc/types.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/repos/ports/src/virtualbox6/include/version-generated.h b/repos/ports/src/virtualbox6/include/version-generated.h new file mode 100644 index 0000000000..9cf630c5b9 --- /dev/null +++ b/repos/ports/src/virtualbox6/include/version-generated.h @@ -0,0 +1,4 @@ +#ifndef ___version_generated_h___ +#define ___version_generated_h___ +/* VBOX_VERSION_* set in lib/mk/virtualbox-common.inc */ +#endif diff --git a/repos/ports/src/virtualbox6/init.h b/repos/ports/src/virtualbox6/init.h new file mode 100644 index 0000000000..920b7c2ef0 --- /dev/null +++ b/repos/ports/src/virtualbox6/init.h @@ -0,0 +1,22 @@ +/* + * \brief Initialization of sub-modules + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-10-14 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _INIT_H_ +#define _INIT_H_ + +namespace Genode { struct Env; } + +namespace Sup { void init(Genode::Env &); } + +#endif /* _INIT_H_ */ diff --git a/repos/ports/src/virtualbox6/input_adapter.h b/repos/ports/src/virtualbox6/input_adapter.h new file mode 100644 index 0000000000..e9e757238d --- /dev/null +++ b/repos/ports/src/virtualbox6/input_adapter.h @@ -0,0 +1,149 @@ +/* + * \brief Input adapter for VirtualBox main + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-12-11 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _INPUT_ADAPTER_H_ +#define _INPUT_ADAPTER_H_ + +#include + + +struct Input_adapter +{ + struct Mouse + { + ComPtr _imouse; + + Mouse(ComPtr &iconsole) + { + attempt([&] () { return iconsole->COMGETTER(Mouse)(_imouse.asOutParam()); }, + "unable to request mouse interface from console"); + } + + bool _key_status[Input::KEY_MAX + 1]; + + typedef Genode::Surface_base::Point Point; + + Point _abs_pos { 0, 0 }; + + bool _absolute { false }; + + static bool _mouse_button(Input::Keycode keycode) + { + return keycode == Input::BTN_LEFT + || keycode == Input::BTN_RIGHT + || keycode == Input::BTN_MIDDLE; + } + + void handle_input_event(Input::Event const &); + + void absolute(bool absolute) { _absolute = absolute; } + + } _mouse; + + struct Keyboard + { + ComPtr _ikeyboard; + + Keyboard(ComPtr &iconsole) + { + attempt([&] () { return iconsole->COMGETTER(Keyboard)(_ikeyboard.asOutParam()); }, + "unable to request keyboard interface from console"); + } + + void handle_input_event(Input::Event const &); + + } _keyboard; + + Input_adapter(ComPtr &iconsole) + : _mouse(iconsole), _keyboard(iconsole) { } + + void handle_input_event(Input::Event const &); + + void mouse_absolute(bool absolute) { _mouse.absolute(absolute); } +}; + + +void Input_adapter::Keyboard::handle_input_event(Input::Event const &ev) +{ + auto keyboard_submit = [&] (Input::Keycode key, bool release) { + + Scan_code scan_code(key); + + unsigned char const release_bit = release ? 0x80 : 0; + + if (scan_code.normal()) + _ikeyboard->PutScancode(scan_code.code() | release_bit); + + if (scan_code.ext()) { + _ikeyboard->PutScancode(0xe0); + _ikeyboard->PutScancode(scan_code.ext() | release_bit); + } + }; + + ev.handle_press([&] (Input::Keycode key, Genode::Codepoint) { + keyboard_submit(key, false); }); + + ev.handle_release([&] (Input::Keycode key) { + keyboard_submit(key, true); }); +} + + +void Input_adapter::Mouse::handle_input_event(Input::Event const &ev) +{ + /* obtain bit mask of currently pressed mouse buttons */ + auto curr_mouse_button_bits = [&] () { + return (_key_status[Input::BTN_LEFT] ? MouseButtonState_LeftButton : 0) + | (_key_status[Input::BTN_RIGHT] ? MouseButtonState_RightButton : 0) + | (_key_status[Input::BTN_MIDDLE] ? MouseButtonState_MiddleButton : 0); + }; + + unsigned const old_mouse_button_bits = curr_mouse_button_bits(); + Point const old_abs_pos = _abs_pos; + + ev.handle_press([&] (Input::Keycode key, Genode::Codepoint) { + if (_mouse_button(key)) + _key_status[key] = true; }); + + ev.handle_release([&] (Input::Keycode key) { + if (_mouse_button(key)) + _key_status[key] = false; }); + + ev.handle_absolute_motion([&] (int ax, int ay) { + _abs_pos = Point(ax, ay); }); + + unsigned const mouse_button_bits = curr_mouse_button_bits(); + + bool const abs_pos_changed = (old_abs_pos != _abs_pos); + bool const buttons_changed = (old_mouse_button_bits != mouse_button_bits); + + if (abs_pos_changed || buttons_changed) { + if (_absolute) { + _imouse->PutMouseEventAbsolute(_abs_pos.x(), _abs_pos.y(), 0, 0, mouse_button_bits); + } else { + Point const rel = _abs_pos - old_abs_pos; + + _imouse->PutMouseEvent(rel.x(), rel.y(), 0, 0, mouse_button_bits); + } + } +} + + +void Input_adapter::handle_input_event(Input::Event const &ev) +{ + /* present the event to potential consumers */ + _keyboard.handle_input_event(ev); + _mouse.handle_input_event(ev); +} + +#endif /* _INPUT_ADAPTER_H_ */ diff --git a/repos/ports/src/virtualbox6/libc.cc b/repos/ports/src/virtualbox6/libc.cc new file mode 100644 index 0000000000..69bc24bd0b --- /dev/null +++ b/repos/ports/src/virtualbox6/libc.cc @@ -0,0 +1,126 @@ +/* + * \brief VirtualBox runtime (RT) + * \author Norman Feske + * \author Christian Helmuth + * \date 2013-08-20 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* libc includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include /* memset */ +#include /* statfs */ +#include /* fstatvfs */ +#include /* open */ + +/* local includes */ +#include + +static bool const debug = true; + + +extern "C" { + +int sched_yield() +{ + static unsigned long counter = 0; + + if (++counter % 100'000 == 0) + Genode::warning(__func__, " called ", counter, " times"); + + return 0; +} + +int sched_get_priority_max(int policy) TRACE(0) +int sched_get_priority_min(int policy) TRACE(0) +int pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) TRACE(0) +int pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) TRACE(0) +int futimes(int fd, const struct timeval tv[2]) TRACE(0) +int lutimes(const char *filename, const struct timeval tv[2]) TRACE(0) +int lchown(const char *pathname, uid_t owner, gid_t group) TRACE(0) +int mlock(const void *addr, size_t len) TRACE(0) +int aio_fsync(int op, struct aiocb *aiocbp) STOP +ssize_t aio_return(struct aiocb *aiocbp) STOP +int aio_error(const struct aiocb *aiocbp) STOP +int aio_cancel(int fd, struct aiocb *aiocbp) STOP +int aio_suspend(const struct aiocb * const aiocb_list[], + int nitems, const struct timespec *timeout) STOP +int lio_listio(int mode, struct aiocb *const aiocb_list[], + int nitems, struct sigevent *sevp) STOP + +} /* extern "C" */ + + + +/* Helper for VBOXSVC_LOG_DEFAULT hook in global_defs.h */ +extern "C" char const * vboxsvc_log_default_string() +{ + char const *vbox_log_string = getenv("VBOX_LOG"); + + return vbox_log_string ? vbox_log_string : ""; +} + + +/* used by Shared Folders and RTFsQueryType() in media checking */ +extern "C" int statfs(const char *path, struct statfs *buf) +{ + if (!buf) { + errno = EFAULT; + return -1; + } + + int fd = open(path, 0); + + if (fd < 0) + return fd; + + struct statvfs result; + int res = fstatvfs(fd, &result); + + close(fd); + + if (res) + return res; + + memset(buf, 0, sizeof(*buf)); + + buf->f_bavail = result.f_bavail; + buf->f_bfree = result.f_bfree; + buf->f_blocks = result.f_blocks; + buf->f_ffree = result.f_ffree; + buf->f_files = result.f_files; + buf->f_bsize = result.f_bsize; + + /* set file-system type to unknown to prevent application of any quirks */ + strcpy(buf->f_fstypename, "unknown"); + + bool show_warning = !buf->f_bsize || !buf->f_blocks || !buf->f_bavail; + + if (!buf->f_bsize) + buf->f_bsize = 4096; + if (!buf->f_blocks) + buf->f_blocks = 128 * 1024; + if (!buf->f_bavail) + buf->f_bavail = buf->f_blocks; + + if (show_warning) + Genode::warning("statfs provides bogus values for '", path, "' (probably a shared folder)"); + + return res; +} + diff --git a/repos/ports/src/virtualbox6/main.cc b/repos/ports/src/virtualbox6/main.cc new file mode 100644 index 0000000000..6902b03e1c --- /dev/null +++ b/repos/ports/src/virtualbox6/main.cc @@ -0,0 +1,373 @@ +/* + * \brief Port of VirtualBox to Genode + * \author Norman Feske + * \author Alexander Boettcher + * \author Christian Helmuth + * \date 2013-08-20 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include + +/* Virtualbox includes */ +#include +#include +#include +#include +#include + +/* Virtualbox includes of generic Main frontend */ +#include "ConsoleImpl.h" +#include "MachineImpl.h" +#include "MouseImpl.h" +#include "SessionImpl.h" +#include "VirtualBoxImpl.h" + +/* Genode port specific includes */ +#include +#include +#include +#include + +using namespace Genode; + + +struct Event_handler : Interface +{ + virtual void handle_vbox_event(VBoxEventType_T, IEvent &) = 0; +}; + + +struct Event_listener +{ + Event_handler *_handler_ptr = nullptr; + + virtual ~Event_listener() { } + + HRESULT init(Event_handler &handler) + { + _handler_ptr = &handler; + return S_OK; + } + + void uninit() { } + + STDMETHOD(HandleEvent)(VBoxEventType_T ev_type, IEvent *ev) + { + if (_handler_ptr) + _handler_ptr->handle_vbox_event(ev_type, *ev); + + return S_OK; + } +}; + +typedef ListenerImpl Event_listener_impl; + +VBOX_LISTENER_DECLARE(Event_listener_impl) + + +struct Main : Event_handler +{ + Env &_env; + + Attached_rom_dataspace _config { _env, "config" }; + + struct Vbox_file_path + { + typedef String<128> Path; + + Path const _path; + + com::Utf8Str const utf8 { _path.string() }; + + Vbox_file_path(Xml_node config) + : + _path(config.attribute_value("vbox_file", Path())) + { + if (!_path.valid()) { + error("missing 'vbox_file' attribute in config"); + throw Fatal(); + } + } + } _vbox_file_path { _config.xml() }; + + /* + * Create VirtualBox object + * + * We cannot create the object via 'ComObjPtr::createObject' + * because 'FinalConstruction' uses a temporary 'ComObjPtr' + * (implicitly constructed as argument for the 'ClientWatcher' constructor. + * Upon the destruction of the temporary, the 'VirtualBox' refcnt becomes + * zero, which prompts 'VirtualBox::Release' to destruct the object. + * + * To sidestep this suicidal behavior, we manually perform the steps of + * 'createObject' but calling 'AddRef' before 'FinalConstruct'. + */ + struct Virtualbox_instance : ComObjPtr + { + VirtualBox _instance; + + Virtualbox_instance() + { + _instance.AddRef(); + + attempt([&] () { return _instance.FinalConstruct(); }, + "construction of VirtualBox object failed"); + + ComObjPtr::operator = (&_instance); + } + } _virtualbox { }; + + struct Session_instance : ComObjPtr<::Session> + { + Session_instance() + { + attempt([&] () { return createObject(); }, + "construction of VirtualBox session object failed"); + } + } _session { }; + + struct Monitor_count { PRUint32 value; }; + + struct Machine_instance : ComObjPtr + { + Machine_instance(Virtualbox_instance &virtualbox, + Session_instance &session, + Vbox_file_path const &vbox_file_path) + { + attempt([&] () { return createObject(); }, + "failed to create Machine object"); + + attempt([&] () { return (*this)->initFromSettings(virtualbox, + vbox_file_path.utf8, + nullptr); }, + "failed to init machine from settings"); + + /* + * Add the machine to the VirtualBox::allMachines list + * + * Unfortunately, the 'i_registerMachine' function performs a + * 'i_saveSettings' should the 'VirtualBox' object not be in the + * 'InInit' state. However, the object is already in 'Ready' state. + * So, 'i_saveSettings' attempts to write a 'VirtualBox.xml' file + */ + { + AutoWriteLock alock(virtualbox.m_p COMMA_LOCKVAL_SRC_POS); + + attempt([&] () { return (*this)->i_prepareRegister(); }, + "could not enter registered state for machine"); + } + + attempt([&] () { return (*this)->LockMachine(session, LockType_VM); }, + "failed to lock machine"); + } + + Monitor_count monitor_count() + { + ComPtr adapter; + + attempt([&] () { return (*this)->COMGETTER(GraphicsAdapter)(adapter.asOutParam()); }, + "attempt to access virtual graphics adapter failed"); + + Monitor_count result { 0 }; + + attempt([&] () { return adapter->COMGETTER(MonitorCount)(&result.value); }, + "unable to determine the number of virtual monitors"); + + return result; + } + + } _machine { _virtualbox, _session, _vbox_file_path }; + + struct Console_interface : ComPtr + { + Console_interface(Session_instance &session) + { + attempt([&] () { return session->COMGETTER(Console)(this->asOutParam()); }, + "unable to request console for session"); + } + } _iconsole { _session }; + + struct Display_interface : ComPtr + { + Display_interface(Console_interface &iconsole) + { + attempt([&] () { return iconsole->COMGETTER(Display)(this->asOutParam()); }, + "unable to request display from console interface"); + } + } _idisplay { _iconsole }; + + Registry> _gui_connections { }; + + Signal_handler
_input_handler { _env.ep(), *this, &Main::_handle_input }; + + void _handle_input_event(Input::Event const &); + + void _handle_input() + { + Libc::with_libc([&] { + _gui_connections.for_each([&] (Gui::Connection &gui) { + gui.input()->for_each_event([&] (Input::Event const &ev) { + _handle_input_event(ev); }); }); }); + } + + Input_adapter _input_adapter { _iconsole }; + + bool const _genode_gui_attached = ( _attach_genode_gui(), true ); + + void _attach_genode_gui() + { + Monitor_count const num_monitors = _machine.monitor_count(); + + for (unsigned i = 0; i < num_monitors.value; i++) { + + Gui::Connection &gui = *new Registered(_gui_connections, _env); + + gui.input()->sigh(_input_handler); + + Genodefb *fb = new Genodefb(_env, gui, _idisplay); + + Bstr fb_id { }; + + attempt([&] () { return _idisplay->AttachFramebuffer(i, fb, fb_id.asOutParam()); }, + "unable to attach framebuffer to virtual monitor ", i); + } + } + + bool const _machine_powered_up = ( _power_up_machine(), true ); + + void _power_up_machine() + { + ComPtr progress; + + attempt([&] () { return _iconsole->PowerUp(progress.asOutParam()); }, + "powering up via console interface failed"); + + /* wait until VM is up */ + MachineState_T state = MachineState_Null; + do { + if (state != MachineState_Null) + RTThreadSleep(1000); + + attempt([&] () { return _machine->COMGETTER(State)(&state); }, + "failed to obtain machine state"); + + } while (state == MachineState_Starting); + + if (state != MachineState_Running) { + error("machine could not enter running state"); + throw Fatal(); + } + } + + void handle_vbox_event(VBoxEventType_T, IEvent &) override; + + bool const _vbox_event_handler_installed = ( _install_vbox_event_handler(), true ); + + void _install_vbox_event_handler() + { + ComObjPtr listener; + + listener.createObject(); + listener->init(new Event_listener(), *this); + + ComPtr ievent_source; + _iconsole->COMGETTER(EventSource)(ievent_source.asOutParam()); + + com::SafeArray event_types; + event_types.push_back(VBoxEventType_OnMouseCapabilityChanged); + event_types.push_back(VBoxEventType_OnMousePointerShapeChanged); + event_types.push_back(VBoxEventType_OnKeyboardLedsChanged); + + ievent_source->RegisterListener(listener, ComSafeArrayAsInParam(event_types), true); + } + + Main(Genode::Env &env) : _env(env) { } +}; + + +void Main::_handle_input_event(Input::Event const &ev) +{ + _input_adapter.handle_input_event(ev); +} + + +void Main::handle_vbox_event(VBoxEventType_T ev_type, IEvent &ev) +{ + switch (ev_type) { + case VBoxEventType_OnMouseCapabilityChanged: + { + ComPtr cap_ev = &ev; + BOOL absolute; + cap_ev->COMGETTER(SupportsAbsolute)(&absolute); + _input_adapter.mouse_absolute(!!absolute); + } break; + + case VBoxEventType_OnMousePointerShapeChanged: break; + case VBoxEventType_OnKeyboardLedsChanged: break; + + default: /* ignore other events */ break; + } +} + + +/* initial environment for the FreeBSD libc implementation */ +extern char **environ; + + +void Libc::Component::construct(Libc::Env &env) +{ + Libc::with_libc([&] () { + + /* extract args and environment variables from config */ + int argc = 0; + char **argv = nullptr; + char **envp = nullptr; + + populate_args_and_env(env, argc, argv, envp); + + environ = envp; + + /* sidestep 'rtThreadPosixSelectPokeSignal' */ + uint32_t const fFlags = RTR3INIT_FLAGS_UNOBTRUSIVE; + + { + int const rc = RTR3InitExe(argc, &argv, fFlags); + if (RT_FAILURE(rc)) + throw -1; + } + + { + nsCOMPtr serviceManager; + HRESULT const rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsnull, nsnull); + if (NS_FAILED(rc)) + { + Genode::error("failed to initialize XPCOM, rc=", rc); + throw -2; + } + } + + Sup::init(env); + + try { + static Main main(env); + } + catch (...) { + error("startup of virtual machine failed, giving up."); + } + }); +} + + +NS_IMPL_THREADSAFE_ISUPPORTS1_CI(Genodefb, IFramebuffer) +NS_DECL_CLASSINFO(Genodefb) diff --git a/repos/ports/src/virtualbox6/nem.cc b/repos/ports/src/virtualbox6/nem.cc new file mode 100644 index 0000000000..1b8c4b0cef --- /dev/null +++ b/repos/ports/src/virtualbox6/nem.cc @@ -0,0 +1,482 @@ +/* + * \brief Genode backend for VirtualBox native execution manager + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-11-05 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* VirtualBox includes */ +#include /* must be included before CPUMInternal.h */ +#define VMCPU_INCL_CPUM_GST_CTX /* needed for cpum.GstCtx */ +#include /* enable access to cpum.s.* */ +#include /* enable access to hm.s.* */ +#define RT_OS_WINDOWS /* needed for definition all nem.s members */ +#include /* enable access to nem.s.* */ +#undef RT_OS_WINDOWS +#include /* enable access to pgm.s.* */ +#include /* must be included before PGMInline.h */ +#include +#include +#include +#include +#include + +/* local includes */ +#include +#include +#include +#include +#include + +static bool const debug = true; + +using namespace Genode; + + +namespace Sup { struct Nem; } + +struct Sup::Nem +{ + Gmm &_gmm; + + typedef Sup::Gmm::Protection Protection; + + struct Range + { + addr_t first_byte { 0 }; + addr_t last_byte { 0 }; + + Protection prot { false, false, false }; + + size_t size() const { return last_byte ? last_byte - first_byte + 1 : 0; } + + /* empty ranges are invalid */ + bool valid() const { return size() != 0; } + + enum class Extend_result { PREPENDED, APPENDED, FAILED }; + + Extend_result extend(Range const &other) + { + /* ignore invalid ranges */ + if (!other.valid()) + return Extend_result::APPENDED; + + if (!(prot == other.prot)) + return Extend_result::FAILED; + + /* initialize if uninitialized */ + if (!valid()) { + first_byte = other.first_byte; + last_byte = other.last_byte; + prot = other.prot; + + return Extend_result::APPENDED; + } + + /* prepend */ + if (first_byte == other.last_byte + 1) { + first_byte = other.first_byte; + + return Extend_result::PREPENDED; + } + + /* append */ + if (last_byte + 1 == other.first_byte) { + last_byte = other.last_byte; + + return Extend_result::APPENDED; + } + + /* not contiguous (which includes overlaps) */ + return Extend_result::FAILED; + } + + void print(Output &o) const + { + Genode::print(o, prot, ":", Hex_range(first_byte, size())); + } + }; + + Range host_range { }; + Range guest_range { }; + + void commit_range() + { + /* ignore commit of invalid ranges */ + if (!host_range.valid()) + return; + + /* commit the current range to GMM */ + _gmm.map_to_guest(Gmm::Vmm_addr { host_range.first_byte }, + Gmm::Guest_addr { guest_range.first_byte }, + Gmm::Pages { host_range.size() >> PAGE_SHIFT }, + host_range.prot); + + /* reset ranges */ + host_range = { }; + guest_range = { }; + } + + void map_to_guest(addr_t host_addr, addr_t guest_addr, size_t size, Protection prot) + { + Range new_host_range { host_addr, host_addr + (size - 1), prot }; + Range new_guest_range { guest_addr, guest_addr + (size - 1), prot }; + + /* new page just extends the current ranges */ + Range::Extend_result const host_extend_result = new_host_range.extend(host_range); + Range::Extend_result const guest_extend_result = new_guest_range.extend(guest_range); + + bool const failed = (host_extend_result == Range::Extend_result::FAILED); + bool const same_result = (host_extend_result == guest_extend_result); + + if (!failed && same_result) { + host_range = new_host_range; + guest_range = new_guest_range; + + return; + } + + /* new page starts a new range */ + commit_range(); + + /* start over with new page */ + host_range = { host_addr, host_addr + (size - 1), prot }; + guest_range = { guest_addr, guest_addr + (size - 1), prot }; + } + + void map_page_to_guest(addr_t host_addr, addr_t guest_addr, Protection prot) + { + map_to_guest(host_addr, guest_addr, X86_PAGE_SIZE, prot); + } + + Gmm::Vmm_addr alloc_large_page() + { + Gmm::Pages const pages { X86_PAGE_2M_SIZE/X86_PAGE_4K_SIZE }; + + return _gmm.alloc_from_reservation(pages); + } + + Gmm & gmm() { return _gmm; } + + Nem(Gmm &gmm) : _gmm(gmm) { } +}; + + +Sup::Nem * nem_ptr; + +void Sup::nem_init(Gmm &gmm) +{ + nem_ptr = new Nem(gmm); +} + + +VMM_INT_DECL(int) NEMImportStateOnDemand(PVMCPUCC pVCpu, ::uint64_t fWhat) STOP + + +VMM_INT_DECL(int) NEMHCQueryCpuTick(PVMCPUCC pVCpu, ::uint64_t *pcTicks, + ::uint32_t *puAux) STOP + + +VMM_INT_DECL(int) NEMHCResumeCpuTickOnAll(PVMCC pVM, PVMCPUCC pVCpu, + ::uint64_t uPausedTscValue) STOP + + +void nemHCNativeNotifyHandlerPhysicalRegister(PVMCC pVM, + PGMPHYSHANDLERKIND enmKind, + RTGCPHYS GCPhys, RTGCPHYS cb) +{ +} + + +int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced) +{ + VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API); + + return VINF_SUCCESS; +} + + +int nemR3NativeInitAfterCPUM(PVM pVM) +{ + return VINF_SUCCESS; +} + + +int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat) +{ + return VINF_SUCCESS; +} + + +int nemR3NativeTerm(PVM pVM) STOP + + +/** + * VM reset notification. + * + * @param pVM The cross context VM structure. + */ +void nemR3NativeReset(PVM pVM) TRACE() + + +/** + * Reset CPU due to INIT IPI or hot (un)plugging. + * + * @param pVCpu The cross context virtual CPU structure of the CPU being + * reset. + * @param fInitIpi Whether this is the INIT IPI or hot (un)plugging case. + */ +void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi) TRACE() + + +VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu) +{ + using namespace Sup; + + Vm &vm = *static_cast(pVM); + + /* commit on VM entry */ + nem_ptr->commit_range(); + + VBOXSTRICTRC result = 0; + vm.with_vcpu_handler(Cpu_index { pVCpu->idCpu }, [&] (Sup::Vcpu_handler &handler) { + result = handler.run_hw(vm); + }); + + return result; +} + + +bool nemR3NativeCanExecuteGuest(PVM pVM, PVMCPU pVCpu) +{ + return true; +} + + +bool nemR3NativeSetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable) TRACE(false) + + +/** + * Forced flag notification call from VMEmt.h. + * + * This is only called when pVCpu is in the VMCPUSTATE_STARTED_EXEC_NEM state. + * + * @param pVM The cross context VM structure. + * @param pVCpu The cross context virtual CPU structure of the CPU + * to be notified. + * @param fFlags Notification flags + * (VMNOTIFYFF_FLAGS_DONE_REM/VMNOTIFYFF_FLAGS_POKE) + */ +void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, ::uint32_t fFlags) +{ + /* nemHCWinCancelRunVirtualProcessor(pVM, pVCpu); */ + if (fFlags & VMNOTIFYFF_FLAGS_POKE) { + Sup::Vm &vm = *(Sup::Vm *)pVM; + + vm.with_vcpu_handler(Sup::Cpu_index { pVCpu->idCpu }, [&] (Sup::Vcpu_handler &handler) { + handler.recall(vm); }); + } +} + + +static void update_pgm_large_page(PVM pVM, addr_t guest_addr, addr_t host_addr, + uint32_t page_id) +{ + /* init all pages in large page (see PGMR3PhysAllocateLargeHandyPage()) */ + for (unsigned i = 0; i < X86_PAGE_2M_SIZE/X86_PAGE_4K_SIZE; ++i) { + + PPGMPAGE page = nullptr; + + pgmPhysGetPageEx(pVM, guest_addr, &page); + + if (PGM_PAGE_GET_TYPE(page) != PGMPAGETYPE_RAM) + error(__func__, ": page is not RAM"); + if (!PGM_PAGE_IS_ZERO(page)) + error(__func__, ": page is not zero page"); + + pVM->pgm.s.cZeroPages--; + pVM->pgm.s.cPrivatePages++; + PGM_PAGE_SET_HCPHYS(pVM, page, host_addr); + PGM_PAGE_SET_PAGEID(pVM, page, page_id); + PGM_PAGE_SET_STATE(pVM, page, PGM_PAGE_STATE_ALLOCATED); + PGM_PAGE_SET_PDE_TYPE(pVM, page, PGM_PAGE_PDE_TYPE_PDE); + PGM_PAGE_SET_PTE_INDEX(pVM, page, 0); + PGM_PAGE_SET_TRACKING(pVM, page, 0); + + page_id++; + + host_addr += X86_PAGE_4K_SIZE; + guest_addr += X86_PAGE_4K_SIZE; + } +} + + +/** + * NEM is notified about each RAM range by calling this function repeatedly + * + * PGMR3PhysRegisterRam() holds the PGM lock while calling. + */ +int nemR3NativeNotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb) +{ + /* + * PGM notifies us about each RAM range configured, which means "Base RAM" + * below 4 GiB and "Above 4GB Base RAM" (see MMR3InitPaging()). We eagerly + * map all 2M-aligened "large" pages in the ranges to guest memory and + * initialize PGM to benefit from reduced TLB usage and less backing store + * for many mapped regions. RAM pages outside the large pages are backed on + * demand by PGM by "small" handy pages by default. Unfortunately, the + * configuration of NEM disables automatic use of large pages in PGM. + */ + + /* start at first 2M-aligned page in range */ + addr_t const guest_base = RT_ALIGN(GCPhys, X86_PAGE_2M_SIZE); + + /* iterate over all large pages in range */ + for (addr_t addr = guest_base; addr + _2M <= GCPhys + cb; addr += _2M ) { + + /* + * We skip the first 2 MiB to prevent errors with ROM mappings below 1 + * MiB. Also, a range of 64 KiB at 1 MiB is replaced regularly on A20 + * switching. Both facts invalidate our large-page mapping. + */ + if (addr < _2M) continue; + + /* allocate and map in GMM */ + Sup::Gmm::Vmm_addr const vmm_addr = nem_ptr->alloc_large_page(); + Sup::Gmm::Page_id const vmm_page_id = nem_ptr->gmm().page_id(vmm_addr); + uint32_t const page_id32 = nem_ptr->gmm().page_id_as_uint32(vmm_page_id); + + Sup::Nem::Protection const prot { true, true, true }; + + nem_ptr->map_to_guest(vmm_addr.value, addr, X86_PAGE_2M_SIZE, prot); + + update_pgm_large_page(pVM, addr, vmm_addr.value, page_id32); + } + + /* invalidate PGM caches (see pgmPhysAllocPage()) */ + PGM_INVL_ALL_VCPU_TLBS(pVM); + pgmPhysInvalidatePageMapTLB(pVM); + + return VINF_SUCCESS; +} + + +int nemR3NativeNotifyPhysMmioExMap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, + ::uint32_t fFlags, void *pvMmio2) +{ + /* + * This is called from PGMPhys.cpp with + * + * fFlags = (pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_MMIO2 ? NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 : 0) + * | (pFirstMmio->fFlags & PGMREGMMIO2RANGE_F_OVERLAPPING ? NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE : 0); + */ + + return VINF_SUCCESS; +} + + +int nemR3NativeNotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, + ::uint32_t fFlags) +{ + return VINF_SUCCESS; +} + + +int nemR3NativeNotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, + RTGCPHYS cb, ::uint32_t fFlags) +{ + return VINF_SUCCESS; +} + + +int nemR3NativeNotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, + RTGCPHYS cb, ::uint32_t fFlags) +{ + return VINF_SUCCESS; +} + + +/** + * Called when the A20 state changes. + * + * Do a very minimal emulation of the HMA to make DOS happy. + * + * @param pVCpu The CPU the A20 state changed on. + * @param fEnabled Whether it was enabled (true) or disabled. + */ +void nemR3NativeNotifySetA20(PVMCPU pVCpu, bool fEnabled) +{ + PVM pVM = pVCpu->CTX_SUFF(pVM); + + /* unmap HMA guest memory on A20 change */ + if (pVM->nem.s.fA20Enabled != fEnabled) { + pVM->nem.s.fA20Enabled = fEnabled; + + Sup::Nem::Protection const prot_none { + .readable = false, + .writeable = false, + .executable = false, + }; + + for (RTGCPHYS GCPhys = _1M; GCPhys < _1M + _64K; GCPhys += X86_PAGE_SIZE) + nem_ptr->map_page_to_guest(0, GCPhys | RT_BIT_32(20), prot_none); + } +} + + +void nemHCNativeNotifyHandlerPhysicalDeregister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, + RTGCPHYS GCPhys, RTGCPHYS cb, + int fRestoreAsRAM, + bool fRestoreAsRAM2) +{ +} + + +void nemHCNativeNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, + RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, + RTGCPHYS cb, bool fRestoreAsRAM) STOP + + +int nemHCNativeNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, + ::uint32_t fPageProt, PGMPAGETYPE enmType, + ::uint8_t *pu2State) +{ + nemHCNativeNotifyPhysPageProtChanged(pVM, GCPhys, HCPhys, + fPageProt, enmType, pu2State); + + return VINF_SUCCESS; +} + + +void nemHCNativeNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, + ::uint32_t fPageProt, PGMPAGETYPE enmType, + ::uint8_t *pu2State) +{ + Sup::Nem::Protection const prot { + .readable = fPageProt & NEM_PAGE_PROT_READ, + .writeable = fPageProt & NEM_PAGE_PROT_WRITE, + .executable = fPageProt & NEM_PAGE_PROT_EXECUTE, + }; + + /* + * The passed host and guest addresses may not be aligned, e.g., when + * called from DevVGA.cpp vgaLFBAccess(). Therefore, we do the alignment + * here explicitly. + */ + + nem_ptr->map_page_to_guest(HCPhys & ~PAGE_OFFSET_MASK, + GCPhys & ~PAGE_OFFSET_MASK, prot); +} + + +void nemHCNativeNotifyPhysPageChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, + RTHCPHYS HCPhysNew, ::uint32_t fPageProt, + PGMPAGETYPE enmType, ::uint8_t *pu2State) STOP + diff --git a/repos/ports/src/virtualbox6/patches/serial.patch b/repos/ports/src/virtualbox6/patches/serial.patch new file mode 100644 index 0000000000..0de16a6623 --- /dev/null +++ b/repos/ports/src/virtualbox6/patches/serial.patch @@ -0,0 +1,60 @@ +Patch for serial raw-file backend to really kick the consumer of the FIFO to +consume the (mostly one-byte) content by waiting for an acknowledgement. This +prevents guests that poll the UART LSR.THRE before writing the next character +into the FIFO from redundant exits due to a not processing UART state machine. +The original implementation alleviates this behavior wih RTYield() on LSR read. + +--- a/src/virtualbox6/src/VBox/Devices/Serial/DrvRawFile.cpp ++++ b/src/virtualbox6/src/VBox/Devices/Serial/DrvRawFile.cpp +@@ -58,6 +58,7 @@ + RTFILE hOutputFile; + /** Event semaphore for the poll interface. */ + RTSEMEVENT hSemEvtPoll; ++ RTSEMEVENT hSemEvtPollAck; + } DRVRAWFILE, *PDRVRAWFILE; + + +@@ -78,7 +79,9 @@ + return VINF_SUCCESS; + } + +- return RTSemEventWait(pThis->hSemEvtPoll, cMillies); ++ int rc = RTSemEventWait(pThis->hSemEvtPoll, cMillies); ++ RTSemEventSignal(pThis->hSemEvtPollAck); ++ return rc; + } + + +@@ -86,7 +89,9 @@ + static DECLCALLBACK(int) drvRawFilePollInterrupt(PPDMISTREAM pInterface) + { + PDRVRAWFILE pThis = RT_FROM_MEMBER(pInterface, DRVRAWFILE, IStream); +- return RTSemEventSignal(pThis->hSemEvtPoll); ++ int rc = RTSemEventSignal(pThis->hSemEvtPoll); ++ RTSemEventWait(pThis->hSemEvtPollAck, RT_INDEFINITE_WAIT); ++ return rc; + } + + +@@ -177,6 +182,12 @@ + RTSemEventDestroy(pThis->hSemEvtPoll); + pThis->hSemEvtPoll = NIL_RTSEMEVENT; + } ++ ++ if (pThis->hSemEvtPollAck != NIL_RTSEMEVENT) ++ { ++ RTSemEventDestroy(pThis->hSemEvtPollAck); ++ pThis->hSemEvtPollAck = NIL_RTSEMEVENT; ++ } + } + + +@@ -217,6 +228,8 @@ + + rc = RTSemEventCreate(&pThis->hSemEvtPoll); + AssertRCReturn(rc, rc); ++ rc = RTSemEventCreate(&pThis->hSemEvtPollAck); ++ AssertRCReturn(rc, rc); + + /* + * Open the raw file. diff --git a/repos/ports/src/virtualbox6/patches/series b/repos/ports/src/virtualbox6/patches/series new file mode 100644 index 0000000000..72b8487e74 --- /dev/null +++ b/repos/ports/src/virtualbox6/patches/series @@ -0,0 +1 @@ +serial.patch diff --git a/repos/ports/src/virtualbox6/pdm.cc b/repos/ports/src/virtualbox6/pdm.cc new file mode 100644 index 0000000000..1e3599e505 --- /dev/null +++ b/repos/ports/src/virtualbox6/pdm.cc @@ -0,0 +1,139 @@ +/* + * \brief VirtualBox pluggable device manager (PDM) + * \author Norman Feske + * \author Christian Helmuth + * \date 2013-08-20 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include + +/* VirtualBox includes */ +#include +#include +#include +#include + +#include "util.h" + + +static void RCSymbolDummy() +{ + Genode::log(__func__, ": unexpected call of RC symbol"); + for (;;); +} + + +int PDMR3LdrGetSymbolRC(PVM pVM, const char *pszModule, const char *pszSymbol, + PRTRCPTR pRCPtrValue) +{ + *pRCPtrValue = to_rtrcptr(RCSymbolDummy); + return VINF_SUCCESS; +} + + +int PDMR3LdrGetSymbolRCLazy(PVM pVM, const char *pszModule, + const char *pszSearchPath, const char *pszSymbol, + PRTRCPTR pRCPtrValue) +{ + *pRCPtrValue = to_rtrcptr(RCSymbolDummy); + return VINF_SUCCESS; +} + + +static void R0SymbolDummy() +{ + Assert(!"unexpected call of R0 symbol"); +} + + +int PDMR3LdrGetSymbolR0(PVM pVM, const char *pszModule, const char *pszSymbol, + PRTR0PTR ppvValue) +{ + *ppvValue = (RTR0PTR)R0SymbolDummy; + return VINF_SUCCESS; +} + + +int PDMR3LdrGetSymbolR0Lazy(PVM pVM, const char *pszModule, + const char *pszSearchPath, const char *pszSymbol, + PRTR0PTR ppvValue) +{ + *ppvValue = (RTR0PTR)R0SymbolDummy; + return VINF_SUCCESS; +} + + +extern "C" int VBoxDriversRegister(PCPDMDRVREGCB, uint32_t); +extern "C" int VBoxDevicesRegister(PPDMDEVREGCB, uint32_t); +extern "C" int VBoxDriversRegister_Main(PCPDMDRVREGCB, uint32_t); + +static int dummy_VBoxUsbRegister (PCPDMUSBREGCB, uint32_t) { return VINF_SUCCESS; } +static int dummy_VBoxDriversRegister(PCPDMDRVREGCB, uint32_t) { return VINF_SUCCESS; } +static int dummy_VBoxDevicesRegister(PPDMDEVREGCB, uint32_t) { return VINF_SUCCESS; } + + +int PDMR3LdrGetSymbolR3(PVM pVM, const char *pszModule, const char *pszSymbol, + void **ppvValue) +{ + /* + * This function is called at initialization time via + * PDMR3Init -> pdmR3DrvInit -> pdmR3DrvLoad -> PDMR3LdrGetSymbolR3 + * + * In this case, it is expected to return the pointer to the symbol + * called 'VBoxDriversRegister', which is normally contained in the + * dynamically loaded VBoxDD module. However, we link the drivers + * statically to the binary. So we return the local pointer. + */ + if (Genode::strcmp(pszModule, "VBoxDD") == 0) { + + if (Genode::strcmp(pszSymbol, "VBoxDriversRegister") == 0) { + *ppvValue = (void *)VBoxDriversRegister; + return VINF_SUCCESS; + } + + if (Genode::strcmp(pszSymbol, "VBoxDevicesRegister") == 0) { + *ppvValue = (void *)VBoxDevicesRegister; + return VINF_SUCCESS; + } + + if (Genode::strcmp(pszSymbol, "VBoxUsbRegister") == 0) { + *ppvValue = (void *)dummy_VBoxUsbRegister; + return VINF_SUCCESS; + } + } + + if (Genode::strcmp(pszModule, "VBoxDD2") == 0) { + + if (Genode::strcmp(pszSymbol, "VBoxDriversRegister") == 0) { + *ppvValue = (void *)dummy_VBoxDriversRegister; + return VINF_SUCCESS; + } + + if (Genode::strcmp(pszSymbol, "VBoxDevicesRegister") == 0) { + *ppvValue = (void *)dummy_VBoxDevicesRegister; + return VINF_SUCCESS; + } + } + + if (Genode::strcmp(pszModule, "VBoxC") == 0) { + + if (Genode::strcmp(pszSymbol, "VBoxDriversRegister") == 0) { + *ppvValue = (void *)dummy_VBoxDriversRegister; + return VINF_SUCCESS; + } + } + + Genode::error("pszModule=", pszModule, " pszSymbol=", pszSymbol); + + return VERR_SYMBOL_NOT_FOUND; +} + + diff --git a/repos/ports/src/virtualbox6/scan_code.h b/repos/ports/src/virtualbox6/scan_code.h new file mode 100644 index 0000000000..4fe9ade3e6 --- /dev/null +++ b/repos/ports/src/virtualbox6/scan_code.h @@ -0,0 +1,94 @@ +/* + * \brief Conversion of Genode input events to PS/2 scan codes + * \author Norman Feske + * \author Alexander Boettcher + * \date 2013-08-20 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SCAN_CODE_H_ +#define _SCAN_CODE_H_ + +/* Genode includes */ +#include /* included from os/src/drivers/ps2 */ + + +class Scan_code +{ + private: + + class Converter + { + public: + + unsigned char scan_code [Input::KEY_UNKNOWN]; + unsigned char scan_code_ext [Input::KEY_UNKNOWN]; + + private: + + unsigned char _search_scan_code(Input::Keycode keycode) + { + for (unsigned i = 0; i < SCAN_CODE_SET_1_NUM_KEYS; i++) + if (scan_code_set_1[i] == keycode) + return i; + return 0; + } + + unsigned char _search_scan_code_ext(Input::Keycode keycode) + { + for (unsigned i = 0; i < SCAN_CODE_SET_1_NUM_KEYS; i++) + if (scan_code_set_1_0xe0[i] == keycode) + return i; + return 0; + } + + public: + + Converter() + { + init_scan_code_set_1_0xe0(); + + for (unsigned i = 0; i < Input::KEY_UNKNOWN; i++) { + scan_code [i] = _search_scan_code ((Input::Keycode)i); + scan_code_ext [i] = _search_scan_code_ext((Input::Keycode)i); + } + } + }; + + static Converter &converter() + { + static Converter inst; + return inst; + } + + Input::Keycode _keycode; + + public: + + Scan_code(Input::Keycode keycode) : _keycode(keycode) { } + + bool normal() const { return converter().scan_code[_keycode]; } + + bool valid() const + { + return normal() || ext(); + } + + unsigned char code() const + { + return converter().scan_code[_keycode]; + } + + unsigned char ext() const + { + return converter().scan_code_ext[_keycode]; + } +}; + +#endif /* _SCAN_CODE_H_ */ diff --git a/repos/ports/src/virtualbox6/stub_macros.h b/repos/ports/src/virtualbox6/stub_macros.h new file mode 100644 index 0000000000..6d5c6bd068 --- /dev/null +++ b/repos/ports/src/virtualbox6/stub_macros.h @@ -0,0 +1,50 @@ +/* + * \brief Dummy implementations of symbols needed by VirtualBox + * \author Norman Feske + * \date 2013-08-22 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _STUB_MACROS_H_ +#define _STUB_MACROS_H_ + +#include + +#define TRACE(retval) \ + { \ + if (debug) \ + Genode::log(__PRETTY_FUNCTION__, " called (", __FILE__, ") - eip=", \ + __builtin_return_address(0)); \ + return retval; \ + } + +#define STOP \ + { \ + Genode::error(__PRETTY_FUNCTION__, " called (", __FILE__, ":", __LINE__, "), " \ + "not implemented, eip=", \ + __builtin_return_address(0)); \ + while (1); \ + \ + class Not_implemented { }; \ + throw Not_implemented(); /* sparing the need for a return value */ \ + } + +#define DUMMY_STATIC(X) \ + { \ + static X dummy; \ + Genode::error("static ", __PRETTY_FUNCTION__, " called (", __FILE__, "), " \ + "not implemented, eip=", \ + __builtin_return_address(0)); \ + while (1) \ + asm volatile ("ud2a"); \ + \ + return dummy; \ + } + +#endif /* _STUB_MACROS_H_ */ diff --git a/repos/ports/src/virtualbox6/sup.cc b/repos/ports/src/virtualbox6/sup.cc new file mode 100644 index 0000000000..a830114c5c --- /dev/null +++ b/repos/ports/src/virtualbox6/sup.cc @@ -0,0 +1,763 @@ +/* + * \brief Genode backend for VirtualBox Suplib + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-10-12 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include + +/* VirtualBox includes */ +#include /* enable access to iom.s.* */ +#include /* enable access to nem.s.* */ +#include /* enable access to pgm.s.* */ +#include /* enable access to vmm.s.* */ +#define PDMPCIDEV_INCLUDE_PRIVATE /* needed for PDMPCIDEVINT_DECLARED */ +#define VBOX_IN_VMM /* needed for definition of PDMTASKTYPE */ +#include +#undef VBOX_IN_VMM +#include +#include +#include +#include +#include + +/* local includes */ +#include +#include +#include +#include + +static bool const debug = true; + +using namespace Genode; + +static Sup::Drv *sup_drv; + +void Sup::init(Env &env) +{ + sup_drv = new Sup::Drv(env); + + nem_init(sup_drv->gmm()); +} + + +static bool before_first_call_of_ioctl_query_funcs = true; + + +/******************************* + ** Ioctl interface functions ** + *******************************/ + +/* + * Helper to remove aliasing between request.u.In and request.u.Out + * + * The request structures pass IN and OUT parameters in a union, which + * creates two problems. + * + * - OUT are not initialized to zero by default. Instead, they contain + * bits of IN parameters. + * + * - IN parameters cannot safely be consumed after assigning any OUT + * parameter. + * + * This utility solves these issues by copying-out IN parameters first, + * resetting the OUT parameters to zero, and calling 'fn' with separate + * IN and OUT arguments. + */ +template +static void with_inout_ioctl(T &request, FN const &fn) +{ + auto const in = request.u.In; + auto &out = request.u.Out; + auto &rc = request.Hdr.rc; + + out = { }; + rc = VINF_SUCCESS; + + fn(in, out, request.Hdr.rc); +} + + +template +static void with_out_ioctl(T &request, FN const &fn) +{ + auto &out = request.u.Out; + auto &rc = request.Hdr.rc; + + out = { }; + rc = VINF_SUCCESS; + + fn(out, request.Hdr.rc); +} + + +static void ioctl(SUPCOOKIE &request) +{ + with_inout_ioctl(request, [&] (auto const &, auto &out, auto &) { + + out.u32SessionVersion = SUPDRV_IOC_VERSION; + }); +} + + +static void ioctl(SUPQUERYFUNCS &request) +{ + with_out_ioctl(request, [&] (auto &out, auto &) { }); + + before_first_call_of_ioctl_query_funcs = false; +} + + +static void ioctl(SUPGIPMAP &request) +{ + with_out_ioctl(request, [&] (auto &out, auto &) { + + request.u.Out.pGipR3 = sup_drv->gip(); + }); +} + + +static void ioctl(SUPVTCAPS &request) +{ + with_out_ioctl(request, [&] (auto &out, auto &rc) { + + /* + * Return VERR_VMX_NO_VMX and VERR_SVM_NO_SVM to trigger the use of + * the native execution manager (follow NEMR3Init). + */ + switch (sup_drv->cpu_virt()) { + case Sup::Drv::Cpu_virt::VMX: + rc = VERR_VMX_NO_VMX; + out.fCaps = SUPVTCAPS_VT_X | SUPVTCAPS_NESTED_PAGING; + break; + case Sup::Drv::Cpu_virt::SVM: + rc = VERR_SVM_NO_SVM; + out.fCaps = SUPVTCAPS_AMD_V | SUPVTCAPS_NESTED_PAGING; + break; + case Sup::Drv::Cpu_virt::NONE: + rc = VERR_UNSUPPORTED_CPU; + out.fCaps = 0; + break; + } + + /* + * Prevent returning an erroneous rc value when VT caps are queried + * during the early initialization path of Host::init, + * i_updateProcessorFeatures. Otherwise, the assertions in + * i_updateProcessorFeatures would trigger. + * + * Later, when called during the VM initialization via vmR3InitRing3, + * HMR3Init, we have to return VERR_VMX_NO_VMX or VERR_SVM_NO_SVM to + * force the call of NEMR3Init. + */ + if (before_first_call_of_ioctl_query_funcs) + rc = VINF_SUCCESS; + + /* + * XXX are the following interesting? + * SUPVTCAPS_VTX_VMCS_SHADOWING + * SUPVTCAPS_VTX_UNRESTRICTED_GUEST + */ + }); +} + + +static int vmmr0_gvmm_create_vm(GVMMCREATEVMREQ &request) +{ + Sup::Cpu_count cpu_count { request.cCpus }; + + Sup::Vm &new_vm = Sup::Vm::create(request.pSession, cpu_count); + + for (unsigned i = 0; i < cpu_count.value; i++) { + + Sup::Cpu_index const index { i }; + + Sup::Vcpu_handler &handler = sup_drv->create_vcpu_handler(index); + + new_vm.register_vcpu_handler(index, handler); + } + + request.pVMR3 = &new_vm; + request.pVMR0 = (PVMR0)request.pVMR3; + + return VINF_SUCCESS; +} + + +static int vmmr0_gvmm_register_vcpu(PVMR0 pvmr0, uint32_t cpu) +{ + warning(__PRETTY_FUNCTION__, " cpu=", cpu); + + /* + * EMT threads for additional CPUs are registered on initialization. + * The EMT-0 thread does not register via this function. + * + * GVMMR0RegisterVCpu() does the following... + * + * pGVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = RTThreadNativeSelf(); + */ + + return VINF_SUCCESS; +} + + +static int vmmr0_gvmm_sched_halt(PVMR0 pvmr0, ::uint32_t cpu, ::uint64_t expire_timestamp) +{ + Sup::Vm &vm = *(Sup::Vm *)pvmr0; + + ::uint64_t const now_timestamp = RTTimeNanoTS(); + + ::uint64_t ns_diff = expire_timestamp > now_timestamp + ? expire_timestamp - now_timestamp : 0; + + if (!ns_diff) + return VINF_SUCCESS; + + if (ns_diff > RT_NS_1SEC) { + warning(" clamping halt duration of ", ns_diff, " ns to 1 s"); + ns_diff = RT_NS_1SEC; + } + + vm.with_vcpu_handler(Sup::Cpu_index { cpu }, [&] (Sup::Vcpu_handler &handler) { + handler.halt(ns_diff); + }); + + /* + * returns VINF_SUCCESS on normal wakeup (timeout or kicked by other thread) + * VERR_INTERRUPTED if a signal was scheduled for the thread + */ + return VINF_SUCCESS; +} + + +static int vmmr0_gvmm_wake_up(PVMR0 pvmr0, uint32_t cpu) +{ + Sup::Vm &vm = *(Sup::Vm *)pvmr0; + + vm.with_vcpu_handler(Sup::Cpu_index { cpu }, [&] (Sup::Vcpu_handler &handler) { + handler.wake_up(); + }); + + return VINF_SUCCESS; +} + + +static int vmmr0_gvmm_sched_poll(PVMR0 pvmr0, uint32_t cpu, bool yield) +{ + /* + * GVMMR0SchedPoll() just wakes up waiters on gvmm.s.HaltEventMulti. In our + * case, we could just call vmmr0_gvmm_wake_up(). Note, 'yield' must always + * be false according to comment in GVMMR0SchedPoll(). + */ + + /* XXX still not sure if vmmr0_gvmm_wake_up(pvmr0, cpu) makes sense here */ + return VINF_SUCCESS; +} + + +static int vmmr0_gmm_initial_reservation(GMMINITIALRESERVATIONREQ &request) +{ + Sup::Gmm::Pages pages { request.cBasePages + + request.cShadowPages + + request.cFixedPages }; + + sup_drv->gmm().reservation_pages(pages); + + return VINF_SUCCESS; +} + + +static int vmmr0_gmm_update_reservation(GMMUPDATERESERVATIONREQ &request) +{ + Sup::Gmm::Pages pages { request.cBasePages + + request.cShadowPages + + request.cFixedPages }; + + sup_drv->gmm().reservation_pages(pages); + + return VINF_SUCCESS; +} + + +static int vmmr0_gmm_allocate_pages(GMMALLOCATEPAGESREQ &request) +{ + Sup::Gmm::Pages pages { request.cPages }; + + using Vmm_addr = Sup::Gmm::Vmm_addr; + using Page_id = Sup::Gmm::Page_id; + + Vmm_addr const vmm_addr = sup_drv->gmm().alloc_from_reservation(pages); + + for (unsigned i = 0; i < request.cPages; i++) { + + GMMPAGEDESC &page = request.aPages[i]; + + Vmm_addr const page_addr { vmm_addr.value + i*PAGE_SIZE }; + Page_id const page_id = sup_drv->gmm().page_id(page_addr); + + page.HCPhysGCPhys = page_addr.value; + page.idPage = sup_drv->gmm().page_id_as_uint32(page_id); + page.idSharedPage = NIL_GMM_PAGEID; + } + + return VINF_SUCCESS; +} + + +static int vmmr0_gmm_map_unmap_chunk(GMMMAPUNMAPCHUNKREQ &request) +{ + if (request.idChunkMap != NIL_GMM_CHUNKID) { + Sup::Gmm::Page_id const page_id { request.idChunkMap << GMM_CHUNKID_SHIFT }; + + request.pvR3 = (RTR3PTR)sup_drv->gmm().vmm_addr(page_id).value; + } + + return VINF_SUCCESS; +} + + +static int vmmr0_iom_grow_io_ports(PVMR0 pvmr0, ::uint64_t min_entries) +{ + /* satisfy IOMR3IoPortCreate */ + Sup::Vm &vm = *(Sup::Vm *)pvmr0; + + unsigned const old_bound = vm.iom.s.cIoPortAlloc; + unsigned const new_bound = max(min_entries, old_bound); + + IOMIOPORTENTRYR3 *r3_entries = new IOMIOPORTENTRYR3 [new_bound] { }; + IOMIOPORTLOOKUPENTRY *lookup_entries = new IOMIOPORTLOOKUPENTRY[new_bound] { }; + + /* preserve content of the existing arrays */ + for (unsigned i = 0; i < old_bound; i++) { + r3_entries [i] = vm.iom.s.paIoPortRegs[i]; + lookup_entries[i] = vm.iom.s.paIoPortLookup[i]; + } + + /* initialize new array elements */ + for (unsigned i = old_bound; i < new_bound; i++) { + r3_entries[i].idxSelf = (uint16_t)i; + r3_entries[i].idxStats = UINT16_MAX; + } + + /* replace old arrays with new ones */ + delete vm.iom.s.paIoPortLookup; + delete vm.iom.s.paIoPortRegs; + + vm.iom.s.paIoPortRegs = r3_entries; + vm.iom.s.paIoPortLookup = lookup_entries; + vm.iom.s.cIoPortAlloc = new_bound; + + return VINF_SUCCESS; +} + + +static int vmmr0_iom_grow_mmio_regs(PVMR0 pvmr0, ::uint64_t min_entries) +{ + /* satisfy IOMR3MmioCreate */ + Sup::Vm &vm = *(Sup::Vm *)pvmr0; + + unsigned const old_bound = vm.iom.s.cMmioAlloc; + unsigned const new_bound = max(min_entries, old_bound); + + IOMMMIOENTRYR3 *r3_entries = new IOMMMIOENTRYR3 [new_bound] { }; + IOMMMIOLOOKUPENTRY *lookup_entries = new IOMMMIOLOOKUPENTRY[new_bound] { }; + + /* preserve content of the existing arrays */ + for (unsigned i = 0; i < old_bound; i++) { + r3_entries [i] = vm.iom.s.paMmioRegs[i]; + lookup_entries[i] = vm.iom.s.paMmioLookup[i]; + } + + /* initialize new array elements */ + for (unsigned i = old_bound; i < new_bound; i++) { + r3_entries[i].idxSelf = (uint16_t)i; + r3_entries[i].idxStats = UINT16_MAX; + } + + /* replace old arrays with new ones */ + delete vm.iom.s.paMmioLookup; + delete vm.iom.s.paMmioRegs; + + vm.iom.s.paMmioRegs = r3_entries; + vm.iom.s.paMmioLookup = lookup_entries; + vm.iom.s.cMmioAlloc = new_bound; + + return VINF_SUCCESS; +} + + +static int vmmr0_pdm_device_create(PDMDEVICECREATEREQ &request) +{ + /* + * Allocate all PDM device ingredients as a single contiguous memory block. + * + * 1. The actual PDMDEVINSR3 structure (Head) + * + * 2. The CC (current context) size is passed as 'cbInstanceR3' + * request argument. Its backing store must immediately follow the + * PDMDEVINSR3 structure because the PDMDEVINSR3 last member + * 'achInstanceData[0]' is expected to correspond to the InstanceCC + * object. + * + * 3. The shared state of the device instance. The size of this + * object is known only by the respective device model and passed as + * 'cbInstanceShared' request argument. + * + * 4. Backing store of the objects referenced by the 'PDMDEVINSR3' (Tail) + * + * PDMDevHlp.cpp tests for certain allocation patterns, e.g., in + * pdmR3DevHlp_SetDeviceCritSect, there is the following assertion: + * + * Assert((uintptr_t)pOldCritSect - (uintptr_t)pDevIns < pDevIns->cbRing3); + */ + struct Head + { + PDMDEVINSR3 pdmdev { }; + }; + + size_t const r3_size = request.cbInstanceR3; + + /* + * The 'pvInstanceDataForR3' backing store is used for the R3 device state, + * e.g., DEVPCIROOT for the PCI bus, or KBDSTATE for the PS2 keyboard. + */ + size_t const shared_size = request.cbInstanceShared; + + struct Tail + { + PDMCRITSECT critsect { }; + + enum { NUM_PCI_DEVS = sizeof(PDMDEVINSR3::apPciDevs) / + sizeof(PDMDEVINSR3::apPciDevs[0]) }; + + PDMPCIDEV pcidevs[NUM_PCI_DEVS] { }; + }; + + size_t const alloc_size = sizeof(Head) + r3_size + shared_size + sizeof(Tail); + char * const alloc_ptr = (char *)RTMemPageAllocZ(alloc_size); + + /* define placement of head, r3 instance object, and tail */ + Head &head = *(Head *)alloc_ptr; + + char * const r3_instance_ptr = (char *)&head.pdmdev.achInstanceData[0]; + char * const shared_instance_ptr = (char *)&head + sizeof(Head) + r3_size; + + Tail &tail = *(Tail *)(shared_instance_ptr + shared_size); + + /* initialize PDMDEVINSR3 */ + { + PDMDEVINSR3 &pdmdev = head.pdmdev; + + pdmdev.pvInstanceDataForR3 = r3_instance_ptr; + pdmdev.pvInstanceDataR3 = shared_instance_ptr; + pdmdev.pCritSectRoR3 = &tail.critsect; + pdmdev.cbRing3 = alloc_size; + + /* needed for PDMDEV_CALC_PPCIDEV */ + pdmdev.cPciDevs = Tail::NUM_PCI_DEVS; + pdmdev.cbPciDev = sizeof(PDMPCIDEV); + + for (size_t i = 0; i < Tail::NUM_PCI_DEVS; i++) { + + PDMPCIDEV &pcidev = tail.pcidevs[i]; + + pcidev.cbConfig = _4K; + /* PDMR0Device.cpp also initializes pcidev.cbMsixState here */ + pcidev.Int.s.idxSubDev = i; + pcidev.idxSubDev = i; + pcidev.u32Magic = PDMPCIDEV_MAGIC; + + pdmdev.apPciDevs[i] = &pcidev; + } + + pdmdev.fR0Enabled = true; + pdmdev.Internal.s.fIntFlags = PDMDEVINSINT_FLAGS_R0_ENABLED; + pdmdev.u32Version = PDM_DEVINS_VERSION; + + request.pDevInsR3 = &pdmdev; + } + + return VINF_SUCCESS; +} + + +static int vmmr0_pdm_device_gen_call(PDMDEVICEGENCALLREQ &request) +{ + warning("PDMDEVICEGENCALLREQ PDMDEVICEGENCALL=", (int)request.enmCall, " not implemented"); + + return VINF_SUCCESS; +} + + +static int vmmr0_pgm_allocate_handy_pages(PVMR0 pvmr0) +{ + Sup::Vm &vm = *(Sup::Vm *)pvmr0; + + uint32_t const start_idx = vm.pgm.s.cHandyPages; + uint32_t const stop_idx = RT_ELEMENTS(vm.pgm.s.aHandyPages); + + Sup::Gmm::Pages pages { stop_idx - start_idx }; + + using Vmm_addr = Sup::Gmm::Vmm_addr; + using Page_id = Sup::Gmm::Page_id; + + Vmm_addr const vmm_addr = sup_drv->gmm().alloc_from_reservation(pages); + + for (unsigned i = start_idx; i < stop_idx; ++i) { + + GMMPAGEDESC &page = vm.pgm.s.aHandyPages[i]; + + Vmm_addr const page_addr { vmm_addr.value + i*PAGE_SIZE }; + Page_id const page_id = sup_drv->gmm().page_id(page_addr); + + page.HCPhysGCPhys = page_addr.value; + page.idPage = sup_drv->gmm().page_id_as_uint32(page_id); + page.idSharedPage = NIL_GMM_PAGEID; + } + + vm.pgm.s.cHandyPages = stop_idx; + + return VINF_SUCCESS; +} + + +static int vmmr0_vmmr0_init(PVMR0 pvmr0) +{ + Sup::Vm &vm = *(Sup::Vm *)pvmr0; + + /* produces + * + * [init -> vbox1] EMT VMM: Thread-context hooks unavailable + * [init -> vbox1] EMT VMM: Warning! RTThreadPreemptIsPending() cannot be trusted! Need to update kernel info? + * [init -> vbox1] EMT VMM: Kernel preemption is not possible it seems + */ + + return VINF_SUCCESS; +} + + +static int vmmr0_vmmr0_init_emt(PVMR0 pvmr0, uint32_t cpu) +{ + Sup::Vm &vm = *(Sup::Vm *)pvmr0; + + return VINF_SUCCESS; +} + + +static void ioctl(SUPCALLVMMR0 &request) +{ + auto &rc = request.Hdr.rc; + + VMMR0OPERATION const operation = VMMR0OPERATION(request.u.In.uOperation); + + switch (operation) { + + case VMMR0_DO_GVMM_CREATE_VM: + rc = vmmr0_gvmm_create_vm(*(GVMMCREATEVMREQ *)request.abReqPkt); + return; + + case VMMR0_DO_GVMM_REGISTER_VMCPU: + rc = vmmr0_gvmm_register_vcpu(request.u.In.pVMR0, request.u.In.idCpu); + return; + + case VMMR0_DO_GVMM_SCHED_HALT: + rc = vmmr0_gvmm_sched_halt(request.u.In.pVMR0, request.u.In.idCpu, request.u.In.u64Arg); + return; + + case VMMR0_DO_GVMM_SCHED_WAKE_UP: + rc = vmmr0_gvmm_wake_up(request.u.In.pVMR0, request.u.In.idCpu); + return; + + case VMMR0_DO_GVMM_SCHED_POLL: + rc = vmmr0_gvmm_sched_poll(request.u.In.pVMR0, request.u.In.idCpu, !!request.u.In.u64Arg); + return; + + case VMMR0_DO_GMM_INITIAL_RESERVATION: + rc = vmmr0_gmm_initial_reservation(*(GMMINITIALRESERVATIONREQ *)request.abReqPkt); + return; + + case VMMR0_DO_GMM_UPDATE_RESERVATION: + rc = vmmr0_gmm_update_reservation(*(GMMUPDATERESERVATIONREQ *)request.abReqPkt); + return; + + case VMMR0_DO_GMM_ALLOCATE_PAGES: + rc = vmmr0_gmm_allocate_pages(*(GMMALLOCATEPAGESREQ *)request.abReqPkt); + return; + + case VMMR0_DO_GMM_MAP_UNMAP_CHUNK: + rc = vmmr0_gmm_map_unmap_chunk(*(GMMMAPUNMAPCHUNKREQ *)request.abReqPkt); + return; + + case VMMR0_DO_IOM_GROW_IO_PORTS: + rc = vmmr0_iom_grow_io_ports(request.u.In.pVMR0, request.u.In.u64Arg); + return; + + case VMMR0_DO_IOM_GROW_MMIO_REGS: + rc = vmmr0_iom_grow_mmio_regs(request.u.In.pVMR0, request.u.In.u64Arg); + return; + + case VMMR0_DO_PDM_DEVICE_CREATE: + rc = vmmr0_pdm_device_create(*(PDMDEVICECREATEREQ *)request.abReqPkt); + return; + + case VMMR0_DO_PDM_DEVICE_GEN_CALL: + rc = vmmr0_pdm_device_gen_call(*(PDMDEVICEGENCALLREQ *)request.abReqPkt); + return; + + case VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES: + rc = vmmr0_pgm_allocate_handy_pages(request.u.In.pVMR0); + return; + + case VMMR0_DO_VMMR0_INIT: + rc = vmmr0_vmmr0_init(request.u.In.pVMR0); + return; + + case VMMR0_DO_VMMR0_INIT_EMT: + rc = vmmr0_vmmr0_init_emt(request.u.In.pVMR0, request.u.In.idCpu); + return; + + default: + error(__func__, " operation=", (int)operation); + rc = VERR_NOT_IMPLEMENTED; + STOP + } +} + + +static void ioctl(SUPGETHWVIRTMSRS &request) +{ + with_inout_ioctl(request, [&] (auto const &in, auto &, auto &) { + + warning("SUPGETHWVIRTMSRS fForce=", in.fForce); + }); +} + + +static void ioctl(SUPUCODEREV &request) +{ + with_out_ioctl(request, [&] (auto &out, auto &) { + + out.MicrocodeRev = ~0u; + }); +} + + +static void ioctl(SUPGETPAGINGMODE &request) +{ + with_out_ioctl(request, [&] (auto &out, auto &) { + + out.enmMode = sizeof(long) == 32 ? SUPPAGINGMODE_32_BIT_GLOBAL + : SUPPAGINGMODE_AMD64_GLOBAL_NX; + }); +} + + +static void ioctl(SUPPAGEALLOCEX &request) +{ + /* + * PGMR3PhysMMIORegister() allocates RAM pages for use as MMIO pages in + * guests via MMHyperAlloc(). The actual guest mappings are created via + * nemHCNativeNotifyPhysPageProtChanged(). Therefore, we allocate also + * MMHyper page allocations from GMM. + */ + + with_inout_ioctl(request, [&] (auto const &in, auto &out, auto &) { + + Sup::Gmm::Pages pages { in.cPages }; + + using Vmm_addr = Sup::Gmm::Vmm_addr; + + Vmm_addr const vmm_addr = sup_drv->gmm().alloc_ex(pages); + + out.pvR3 = (R3PTRTYPE(void *))vmm_addr.value; + out.pvR0 = (R0PTRTYPE(void *))vmm_addr.value; + + for (unsigned i = 0; i < pages.value; i++) + out.aPages[i] = vmm_addr.value + i*PAGE_SIZE; + }); +} + + +static void ioctl(SUPSETVMFORFAST &request) +{ + request.Hdr.rc = VINF_SUCCESS; +} + + +/********************************* + ** VirtualBox suplib interface ** + *********************************/ + +int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited, bool fUnrestricted, + SUPINITOP *penmWhat, PRTERRINFO pErrInfo) +{ + /* set hDevice to !NIL_RTFILE - checked by SUPR3PageAllocEx() */ + pThis->hDevice = !NIL_RTFILE; + pThis->fUnrestricted = fUnrestricted; + + return VINF_SUCCESS; +} + + +int suplibOsTerm(PSUPLIBDATA pThis) TRACE(VINF_SUCCESS) + + +int suplibOsInstall(void) TRACE(VERR_NOT_IMPLEMENTED) + + +int suplibOsUninstall(void) TRACE(VERR_NOT_IMPLEMENTED) + + +int suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t opcode, void *req, size_t len) +{ + bool not_implemented = false; + + switch (SUP_CTL_CODE_NO_SIZE(opcode)) { + + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_COOKIE): ioctl(*(SUPCOOKIE *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_QUERY_FUNCS()): ioctl(*(SUPQUERYFUNCS *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_GIP_MAP): ioctl(*(SUPGIPMAP *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_VT_CAPS): ioctl(*(SUPVTCAPS *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_CALL_VMMR0_NO_SIZE()): ioctl(*(SUPCALLVMMR0 *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_GET_HWVIRT_MSRS): ioctl(*(SUPGETHWVIRTMSRS *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_UCODE_REV): ioctl(*(SUPUCODEREV *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_GET_PAGING_MODE): ioctl(*(SUPGETPAGINGMODE *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_PAGE_ALLOC_EX): ioctl(*(SUPPAGEALLOCEX *)req); break; + case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_SET_VM_FOR_FAST): ioctl(*(SUPSETVMFORFAST *)req); break; + + default: + + /* + * Ioctl not handled, print diagnostic info and spin. + * opcode number in lowest 7 bits + */ + error(__func__, " function=", opcode & 0x7f); + not_implemented = true; + STOP + } + + if (((SUPREQHDR *)req)->rc == VERR_NOT_IMPLEMENTED) + not_implemented = true; + + return not_implemented ? VERR_NOT_IMPLEMENTED : VINF_SUCCESS; +} + + +int suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction, + uintptr_t idCpu) STOP + + +int suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages) STOP + + +int suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t cPages) STOP + diff --git a/repos/ports/src/virtualbox6/sup.h b/repos/ports/src/virtualbox6/sup.h new file mode 100644 index 0000000000..6dee7cf82b --- /dev/null +++ b/repos/ports/src/virtualbox6/sup.h @@ -0,0 +1,34 @@ +/* + * \brief Suplib implementation + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-10-12 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SUP_H_ +#define _SUP_H_ + +/* VirtualBox includes */ +#include + +namespace Genode { } + +namespace Sup { + using namespace Genode; + + struct Cpu_count { unsigned value; }; + struct Cpu_index { unsigned value; }; + struct Cpu_freq_khz { unsigned value; }; + + struct Gmm; + void nem_init(Gmm &); +} + +#endif /* _SUP_H_ */ diff --git a/repos/ports/src/virtualbox6/sup_drv.cc b/repos/ports/src/virtualbox6/sup_drv.cc new file mode 100644 index 0000000000..a9fe8a67d4 --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_drv.cc @@ -0,0 +1,90 @@ +/* + * \brief Suplib driver implementation + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-11-20 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Virtualbox includes */ +#include /* enable access to nem.s.* */ + +/* local includes */ +#include +#include + + +Sup::Cpu_freq_khz Sup::Drv::_cpu_freq_khz_from_rom() +{ + unsigned khz = 0; + + _platform_info_rom.xml().with_sub_node("hardware", [&] (Xml_node const &node) { + node.with_sub_node("tsc", [&] (Xml_node const &node) { + khz = node.attribute_value("freq_khz", khz); }); + }); + + if (khz == 0) { + error("could not read CPU frequency"); + sleep_forever(); + } + + return Cpu_freq_khz { khz }; +} + + +Sup::Drv::Cpu_virt Sup::Drv::_cpu_virt_from_rom() +{ + Cpu_virt virt = Cpu_virt::NONE; + + _platform_info_rom.xml().with_sub_node("hardware", [&] (Xml_node const &node) { + node.with_sub_node("features", [&] (Xml_node const &node) { + if (node.attribute_value("vmx", false)) + virt = Cpu_virt::VMX; + else if (node.attribute_value("svm", false)) + virt = Cpu_virt::SVM; + }); + }); + + return virt; +} + + +Sup::Vcpu_handler &Sup::Drv::create_vcpu_handler(Cpu_index cpu_index) +{ + Libc::Allocator alloc { }; + + Affinity::Location const location = + _affinity_space.location_of_index(cpu_index.value); + + size_t const stack_size = 64*1024; + + switch (_cpu_virt) { + + case Cpu_virt::VMX: + return *new Vcpu_handler_vmx(_env, + stack_size, + location, + cpu_index.value, + _vm_connection, + alloc); + + case Cpu_virt::SVM: + return *new Vcpu_handler_svm(_env, + stack_size, + location, + cpu_index.value, + _vm_connection, + alloc); + + case Cpu_virt::NONE: + break; + } + + throw Virtualization_support_missing(); +} diff --git a/repos/ports/src/virtualbox6/sup_drv.h b/repos/ports/src/virtualbox6/sup_drv.h new file mode 100644 index 0000000000..e19351e103 --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_drv.h @@ -0,0 +1,77 @@ +/* + * \brief Suplib driver implementation + * \author Norman Feske + * \author Christian Helmuth + * \author Alexander Boettcher + * \date 2020-10-12 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SUP_DRV_H_ +#define _SUP_DRV_H_ + +/* local includes */ +#include +#include +#include +#include + +/* Genode includes */ +#include +#include +#include + +namespace Sup { struct Drv; } + +class Sup::Drv +{ + public: + + enum class Cpu_virt { NONE, VMX, SVM }; + + class Virtualization_support_missing : Exception { }; + + private: + + Env &_env; + + Attached_rom_dataspace const _platform_info_rom { _env, "platform_info" }; + + Affinity::Space const _affinity_space { _env.cpu().affinity_space() }; + + Cpu_count const _cpu_count { _affinity_space.total() }; + + Cpu_freq_khz _cpu_freq_khz_from_rom(); + + Cpu_virt _cpu_virt_from_rom(); + + Cpu_virt const _cpu_virt { _cpu_virt_from_rom() }; + + Vm_connection _vm_connection { _env }; + + Gip _gip { _env, _cpu_count, _cpu_freq_khz_from_rom() }; + Gmm _gmm { _env, _vm_connection }; + + public: + + Drv(Env &env) : _env(env) { } + + SUPGLOBALINFOPAGE *gip() { return _gip.gip(); } + + Gmm &gmm() { return _gmm; } + + Cpu_virt cpu_virt() { return _cpu_virt; } + + /* + * \throw Virtualization_support_missing + */ + Vcpu_handler &create_vcpu_handler(Cpu_index); +}; + +#endif /* _SUP_DRV_H_ */ diff --git a/repos/ports/src/virtualbox6/sup_gip.h b/repos/ports/src/virtualbox6/sup_gip.h new file mode 100644 index 0000000000..2df85f1edb --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_gip.h @@ -0,0 +1,169 @@ +/* + * \brief Suplib global info page implementation + * \author Norman Feske + * \author Christian Helmuth + * \author Alexander Boettcher + * \date 2020-10-12 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SUP_GIP_H_ +#define _SUP_GIP_H_ + +/* VirtualBox includes */ +#include +#include +#include +#include +#include + +/* Genode includes */ +#include +#include +#include +#include + +namespace Sup { + using namespace Genode; + + struct Gip; +} + +class Sup::Gip +{ + private: + + struct Entrypoint : Genode::Entrypoint + { + SUPGIPCPU *cpu; + + Genode::uint64_t const cpu_hz; + + Timer::Connection timer; + Signal_handler handler; + + Entrypoint(Env &env, SUPGIPCPU *cpu, Genode::uint64_t cpu_hz) + : + Genode::Entrypoint(env, 512*1024, "gip_ep", Affinity::Location()), + cpu(cpu), cpu_hz(cpu_hz), + timer(env), handler(*this, *this, &Entrypoint::update) + { + timer.sigh(handler); + timer.trigger_periodic(UPDATE_US); + } + + void update() + { + Genode::uint64_t tsc_current = Genode::Trace::timestamp(); + + /* + * Convert tsc to nanoseconds. + * + * There is no 'uint128_t' type on x86_32, so we use the 128-bit type + * and functions provided by VirtualBox. + * + * nanots128 = tsc_current * 1000*1000*1000 / genode_cpu_hz() + * + */ + + RTUINT128U nanots128; + RTUInt128AssignU64(&nanots128, tsc_current); + + RTUINT128U multiplier; + RTUInt128AssignU32(&multiplier, 1'000'000'000); + RTUInt128AssignMul(&nanots128, &multiplier); + + RTUINT128U divisor; + RTUInt128AssignU64(&divisor, cpu_hz); + RTUInt128AssignDiv(&nanots128, &divisor); + + /* + * Transaction id must be incremented before and after update, + * read struct SUPGIPCPU description for more details. + */ + ASMAtomicIncU32(&cpu->u32TransactionId); + + cpu->u64TSC = tsc_current; + cpu->u64NanoTS = nanots128.s.Lo; + + /* + * Transaction id must be incremented before and after update, + * read struct SUPGIPCPU description for more details. + */ + ASMAtomicIncU32(&cpu->u32TransactionId); + } + }; + + enum { + UPDATE_HZ = 10'000, + UPDATE_US = 1'000'000/UPDATE_HZ, + UPDATE_NS = 1'000*UPDATE_US + }; + + Genode::size_t const _gip_size; + SUPGLOBALINFOPAGE &_gip; + + public: + + Gip(Env &env, Cpu_count cpu_count, Cpu_freq_khz cpu_khz) + : + _gip_size(RT_ALIGN_Z(RT_UOFFSETOF_DYN(SUPGLOBALINFOPAGE, aCPUs[cpu_count.value]), + PAGE_SIZE)), + _gip(*(SUPGLOBALINFOPAGE *)RTMemPageAllocZ(_gip_size)) + { + Genode::uint64_t const cpu_hz = 1'000ull*cpu_khz.value; + + /* checked by TMR3Init */ + _gip.u32Magic = SUPGLOBALINFOPAGE_MAGIC; + _gip.u32Version = SUPGLOBALINFOPAGE_VERSION; + _gip.u32Mode = SUPGIPMODE_SYNC_TSC; + _gip.cCpus = cpu_count.value; + _gip.cPages = _gip_size/PAGE_SIZE; + _gip.u32UpdateHz = UPDATE_HZ; + _gip.u32UpdateIntervalNS = UPDATE_NS; + _gip.u64NanoTSLastUpdateHz = 0; + _gip.u64CpuHz = cpu_hz; + _gip.cOnlineCpus = cpu_count.value; + _gip.cPresentCpus = cpu_count.value; + _gip.cPossibleCpus = cpu_count.value; + _gip.cPossibleCpuGroups = 1; + _gip.idCpuMax = cpu_count.value - 1; + _gip.enmUseTscDelta = SUPGIPUSETSCDELTA_NOT_APPLICABLE; + /* evaluated by rtTimeNanoTSInternalRediscover in Runtime/common/time/timesup.cpp */ + _gip.fGetGipCpu = SUPGIPGETCPU_APIC_ID; + + /* from SUPDrvGip.cpp */ + for (unsigned i = 0; i < RT_ELEMENTS(_gip.aiCpuFromCpuSetIdx); ++i) + _gip.aiCpuFromCpuSetIdx[i] = UINT16_MAX; + + SUPGIPCPU *cpu = _gip.aCPUs; + + /* XXX in SUPGIPMODE_SYNC_TSC only the first CPU's TSC is updated */ + Entrypoint &ep = *new Entrypoint(env, cpu, cpu_hz); + + for (unsigned i = 0; i < cpu_count.value; ++i) { + cpu[i].u32TransactionId = 0; + cpu[i].u32UpdateIntervalTSC = cpu_hz/UPDATE_HZ; + cpu[i].u64NanoTS = 0ull; + cpu[i].u64TSC = 0ull; + cpu[i].u64CpuHz = cpu_hz; + cpu[i].cErrors = 0; + cpu[i].iTSCHistoryHead = 0; + cpu[i].u32PrevUpdateIntervalNS = UPDATE_NS; + cpu[i].enmState = SUPGIPCPUSTATE_ONLINE; + cpu[i].idCpu = i; + cpu[i].iCpuSet = 0; + cpu[i].idApic = i; + } + } + + SUPGLOBALINFOPAGE *gip() { return &_gip; }; +}; + +#endif /* _SUP_GIP_H_ */ diff --git a/repos/ports/src/virtualbox6/sup_gmm.cc b/repos/ports/src/virtualbox6/sup_gmm.cc new file mode 100644 index 0000000000..eb68f32e3e --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_gmm.cc @@ -0,0 +1,197 @@ +/* + * \brief Guest memory management + * \author Norman Feske + * \author Christian Helmuth + * \author Alexander Boettcher + * \date 2020-11-09 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* VirtualBox includes */ +#include + +/* local includes */ +#include + +namespace { + using Alloc_return = Genode::Range_allocator::Alloc_return; +} + + +void Sup::Gmm::_add_one_slice() +{ + /* attach new region behind previous region */ + size_t const slice_size = _slice_size.value; + addr_t const attach_base = _size_pages.value << PAGE_SHIFT; + addr_t const attach_end = attach_base + (slice_size - 1); + + bool const fits_into_map = attach_end <= _map.end.value; + + if (!fits_into_map) + throw Out_of_range(); + + Ram_dataspace_capability ds = _env.ram().alloc(slice_size); + + _map.connection.retry_with_upgrade(Ram_quota{8192}, Cap_quota{2}, [&] () { + _map.rm.attach_executable(ds, attach_base, slice_size); }); + + _slices[_slice_index(Offset{attach_base})] = ds; + + _alloc.add_range(attach_base, slice_size); + + /* update allocation size */ + _size_pages = { (attach_base + slice_size) >> PAGE_SHIFT }; +} + + +void Sup::Gmm::_update_pool_size() +{ + size_t const size_pages = _size_pages.value; + size_t const new_size_pages = _reservation_pages.value + _alloc_ex_pages.value; + + if (new_size_pages <= size_pages) { + warning("Can't shrink guest memory pool from ", + size_pages, " to ", new_size_pages, " pages"); + return; + } + + size_t const map_pages = _map.size.value >> PAGE_SHIFT; + + if (new_size_pages > map_pages) { + warning("Can't grow guest memory pool beyond ", + map_pages, ", requested ", new_size_pages, " pages"); + return; + } + + /* grow backing-store allocations to accomodate requirements */ + while (_size_pages.value < new_size_pages) + _add_one_slice(); +} + + +Sup::Gmm::Vmm_addr Sup::Gmm::_alloc_pages(Pages pages) +{ + void *out_addr = nullptr; + + size_t const alloc_size = pages.value << PAGE_SHIFT; + + Alloc_return const result = _alloc.alloc_aligned(alloc_size, &out_addr, + log2(alloc_size)); + if (result.error()) { + error("Gmm allocation failed"); + throw Allocation_failed(); + } + + return Vmm_addr { _map.base.value + (addr_t)out_addr }; +} + + +void Sup::Gmm::reservation_pages(Pages pages) +{ + _reservation_pages = pages; + + _update_pool_size(); +} + + +Sup::Gmm::Vmm_addr Sup::Gmm::alloc_ex(Pages pages) +{ + _alloc_ex_pages = { _alloc_ex_pages.value + pages.value }; + + _update_pool_size(); + + return _alloc_pages(pages); +} + + +Sup::Gmm::Vmm_addr Sup::Gmm::alloc_from_reservation(Pages pages) +{ + return _alloc_pages(pages); +} + + +Sup::Gmm::Page_id Sup::Gmm::page_id(Vmm_addr addr) +{ + bool const inside_map = (addr.value >= _map.base.value) + && (addr.value <= _map.end.value); + + if (!inside_map) + throw Out_of_range(); + + addr_t const page_index = (addr.value - _map.base.value) >> PAGE_SHIFT; + + /* NIL_GMM_CHUNKID kept unused - so offset 0 is chunk ID 1 */ + return { page_index + (1u << GMM_CHUNKID_SHIFT) }; +} + + +uint32_t Sup::Gmm::page_id_as_uint32(Page_id page_id) +{ + if (page_id.value << PAGE_SHIFT > PAGE_BASE_MASK) + throw Out_of_range(); + + return page_id.value; +} + + +Sup::Gmm::Vmm_addr Sup::Gmm::vmm_addr(Page_id page_id) +{ + /* NIL_GMM_CHUNKID kept unused - so offset 0 is chunk ID 1 */ + addr_t const addr = _map.base.value + + ((page_id.value - (1u << GMM_CHUNKID_SHIFT)) << PAGE_SHIFT); + + bool const inside_map = (addr >= _map.base.value) + && (addr <= _map.end.value); + + if (!inside_map) + throw Out_of_range(); + + return { addr }; +} + + +void Sup::Gmm::map_to_guest(Vmm_addr from, Guest_addr to, Pages pages, Protection prot) +{ + /* revoke existing mappings to avoid overmap */ + _vm_connection.detach(to.value, pages.value << PAGE_SHIFT); + + if (prot.none()) + return; + + Vmm_addr const from_end { from.value + (pages.value << PAGE_SHIFT) - 1 }; + + for (unsigned i = _slice_index(from); i <= _slice_index(from_end); i++) { + + addr_t const slice_start = i*_slice_size.value; + + addr_t const first_byte_within_slice = + max(_offset(from).value, slice_start); + + addr_t const last_byte_within_slice = + min(_offset(from_end).value, slice_start + _slice_size.value - 1); + + Vm_session::Attach_attr const attr + { + .offset = first_byte_within_slice - slice_start, + .size = last_byte_within_slice - first_byte_within_slice + 1, + .executable = prot.executable, + .writeable = prot.writeable + }; + + _vm_connection.attach(_slices[i], to.value, attr); + + to.value += attr.size; + } +} + + +Sup::Gmm::Gmm(Env &env, Vm_connection &vm_connection) +: + _env(env), _vm_connection(vm_connection) +{ } diff --git a/repos/ports/src/virtualbox6/sup_gmm.h b/repos/ports/src/virtualbox6/sup_gmm.h new file mode 100644 index 0000000000..337aa8a613 --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_gmm.h @@ -0,0 +1,201 @@ +/* + * \brief Suplib GMM implementation + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-11-09 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SUP_GMM_H_ +#define _SUP_GMM_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include + +/* local includes */ +#include + + +namespace Sup { struct Gmm; } + +/** + * Global (guest-memory) manager.(GMM) + * + * Layers in this pool are (top-down) + * + * - Page-sized allocation from Allocator_avl + * - Linear map of 32 GiB in VMM address space (Vmm_addr) + * - VirtualBox GMM chunks of GMM_CHUNK_SIZE (2 MiB) filled with pages and + * referenced with PAGEIDs (offset in linear area) + * - Slices of 128 MiB RAM dataspaces as backing store + * + * Notes + * + * - expect that guest-physical address not required here + * - NIL_GMM_CHUNKID kept unused - so offset 0 is chunk ID 1 + * - we have to allocate from pool - so we need an allocator + */ +class Sup::Gmm +{ + public: + + struct Vmm_addr { addr_t value; }; + struct Guest_addr { addr_t value; }; + struct Offset { addr_t value; }; + struct Bytes { size_t value; }; + struct Pages { size_t value; }; + struct Page_id { addr_t value; }; /* CHUNKID | PAGEIDX */ + + struct Protection + { + bool readable; + bool writeable; + bool executable; + + bool none() const + { + return !readable && ! writeable && !executable; + } + + bool operator == (Protection const &other) const + { + return readable == other.readable + && writeable == other.writeable + && executable == other.executable; + } + + void print(Output &o) const + { + Genode::print(o, readable ? "r" : "-", + writeable ? "w" : "-", + executable ? "x" : "-"); + } + }; + + private: + + Env &_env; + + Vm_connection &_vm_connection; + + static constexpr Bytes _slice_size { 128*1024*1024ul }; + static constexpr Bytes _map_size { 32*1024*1024*1024ul }; + static constexpr auto _num_slices { _map_size.value / _slice_size.value }; + + Dataspace_capability _slices[_num_slices]; + + Pages _size_pages { 0 }; /* current backing-store allocations */ + Pages _reservation_pages { 0 }; /* current VMMR0_DO_GMM_UPDATE_RESERVATION pages */ + Pages _alloc_ex_pages { 0 }; /* current SUPPAGEALLOCEX pages */ + + struct Map + { + Env &env; + + Bytes const size; + + Rm_connection connection { env }; + + Region_map_client rm { connection.create(size.value) }; + + Vmm_addr const base { (addr_t)env.rm().attach(rm.dataspace()) }; + Vmm_addr const end { base.value + size.value - 1 }; + + Map(Env &env, Bytes size) : env(env), size(size) { } + + } _map { _env, _map_size }; + + void _add_one_slice(); + + void _update_pool_size(); + + Vmm_addr _alloc_pages(Pages); + + Offset _offset(Vmm_addr addr) const + { + if (addr.value < _map.base.value || addr.value > _map.end.value) + throw Out_of_range(); + + return Offset { addr.value - _map.base.value }; + } + + unsigned _slice_index(Offset offset) const + { + unsigned const index = offset.value / _slice_size.value; + + if (index > _num_slices) + throw Out_of_range(); + + return index; + } + + unsigned _slice_index(Vmm_addr addr) const + { + return _slice_index(_offset(addr)); + } + + Libc::Allocator _md_alloc; + Allocator_avl _alloc { &_md_alloc }; + + public: + + struct Out_of_range : Exception { }; + struct Allocation_failed : Exception { }; + + Gmm(Env &env, Vm_connection &); + + /** + * Extend pool according to VMMR0_DO_GMM_UPDATE_RESERVATION + */ + void reservation_pages(Pages); + + /** + * Allocate pages from reservation pool + */ + Vmm_addr alloc_from_reservation(Pages); + + /** + * Extend pool and allocate pages + */ + Vmm_addr alloc_ex(Pages); + + /** + * Free pages in pool + */ + void free(Vmm_addr, Pages); + + /** + * Get page ID for VMM address inside linear area + */ + Page_id page_id(Vmm_addr); + + /** + * Get 32-bit PAGEID from page ID + */ + static uint32_t page_id_as_uint32(Page_id); + + /** + * Get VMM address inside linear area for page ID + */ + Vmm_addr vmm_addr(Page_id); + + /** + * Make VMM memory available to the guest-physical address space + * + * \throw Out_of_range + */ + void map_to_guest(Vmm_addr, Guest_addr, Pages, Protection); +}; + +#endif /* _SUP_GMM_H_ */ diff --git a/repos/ports/src/virtualbox6/sup_sem.cc b/repos/ports/src/virtualbox6/sup_sem.cc new file mode 100644 index 0000000000..f739b8aade --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_sem.cc @@ -0,0 +1,124 @@ +/* + * \brief Genode backend for VirtualBox Suplib + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-10-12 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* VirtualBox includes */ +#include +#include +#include +#include + +/* local includes */ +#include + +static bool const debug = true; + +/* check type assumptions */ +static_assert(sizeof(RTSEMEVENT) == sizeof(PSUPSEMEVENT), "type mismatch"); +static_assert(sizeof(RTSEMEVENTMULTI) == sizeof(PSUPSEMEVENTMULTI), "type mismatch"); + + +int SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent) +{ + return RTSemEventCreate((RTSEMEVENT *)phEvent); +} + + +int SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent) +{ + Assert (hEvent); + + return RTSemEventDestroy((RTSEMEVENT)hEvent); +} + + +int SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent) +{ + Assert (hEvent); + + return RTSemEventSignal((RTSEMEVENT)hEvent); +} + + +int SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, + SUPSEMEVENT hEvent, + uint32_t cMillies) +{ + Assert (hEvent); + + return RTSemEventWaitNoResume((RTSEMEVENT)hEvent, cMillies); +} + + +int SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, + SUPSEMEVENT hEvent, + uint64_t uNsTimeout) STOP + + +int SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, + SUPSEMEVENT hEvent, + uint64_t cNsTimeout) STOP + + +uint32_t SUPSemEventGetResolution(PSUPDRVSESSION pSession) +{ + return 10'000'000; /* nanoseconds */ +} + + +int SUPSemEventMultiCreate(PSUPDRVSESSION pSession, + PSUPSEMEVENTMULTI phEventMulti) +{ + AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER); + + RTSEMEVENTMULTI sem; + + return RTSemEventMultiCreate((RTSEMEVENTMULTI*)phEventMulti); +} + + +int SUPSemEventMultiClose(PSUPDRVSESSION pSession, + SUPSEMEVENTMULTI hEventMulti) +{ + return RTSemEventMultiDestroy(reinterpret_cast(hEventMulti)); +} + + +int SUPSemEventMultiSignal(PSUPDRVSESSION pSession, + SUPSEMEVENTMULTI hEventMulti) STOP + + +int SUPSemEventMultiReset(PSUPDRVSESSION pSession, + SUPSEMEVENTMULTI hEventMulti) STOP + + +int SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, + SUPSEMEVENTMULTI hEventMulti, + uint32_t cMillies) STOP + + +int SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, + SUPSEMEVENTMULTI hEventMulti, + uint64_t uNsTimeout) STOP + + +int SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, + SUPSEMEVENTMULTI hEventMulti, + uint64_t cNsTimeout) STOP + + +uint32_t SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession) +{ + return 10'000'000; /* nanoseconds */ +} + diff --git a/repos/ports/src/virtualbox6/sup_vm.cc b/repos/ports/src/virtualbox6/sup_vm.cc new file mode 100644 index 0000000000..e30b1a886f --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_vm.cc @@ -0,0 +1,102 @@ +/* + * \brief Suplib VM implementation + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-10-12 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* VirtualBox includes */ +#include /* must be included before CPUMInternal.h */ +#include /* enable access to cpum.s.* */ +#include /* enable access to hm.s.* */ +#include /* enable access to nem.s.* */ +#include + +/* local includes */ +#include +#include + + +static size_t gvm_size(Sup::Cpu_count cpu_count) +{ + /* expected size of GVM structure (taken from GVMMR0.cpp) */ + return RT_ALIGN_32(RT_UOFFSETOF_DYN(GVM, aCpus[cpu_count.value]), PAGE_SIZE); +} + + +void Sup::Vm::init(PSUPDRVSESSION psession, Cpu_count cpu_count) +{ + /* alloc and emulate R0MEMOBJ */ + size_t const num_pages = gvm_size(cpu_count) / PAGE_SIZE; + SUPPAGE * const pages = (SUPPAGE *)RTMemAllocZ(sizeof(SUPPAGE)*num_pages); + + for (size_t i = 0; i < num_pages; ++i) + pages[i] = { .Phys = (RTHCPHYS)this + i*PAGE_SIZE, .uReserved = 0 }; + + /* + * Some members of VM also exist in GVM (e.g., pSession) therefore we + * explicitly qualify which one is used. + */ + + VM::enmVMState = VMSTATE_CREATING; + VM::paVMPagesR3 = (R3PTRTYPE(PSUPPAGE))pages; + VM::pVMR0ForCall = (PVMR0)this; + VM::pSession = psession; + VM::cbSelf = sizeof(VM); + VM::cbVCpu = sizeof(VMCPU); + VM::cCpus = cpu_count.value; + VM::uCpuExecutionCap = 100; /* expected by 'vmR3CreateU()' */ + VM::nem.s.fEnabled = true; + + for (uint32_t i = 0; i < cpu_count.value; ++i) { + VMCPU &cpu = GVM::aCpus[i]; + + cpu.pVMR3 = this; + cpu.idHostCpu = NIL_RTCPUID; + cpu.hNativeThreadR0 = NIL_RTNATIVETHREAD; + + VM::apCpusR3[i] = &cpu; + log(this, ": apCpusR3[", i, "]=", apCpusR3[i]); + } +} + + +Sup::Vm & Sup::Vm::create(PSUPDRVSESSION psession, Cpu_count cpu_count) +{ + /* + * Allocate and initialize VM struct + * + * The original R0 GVM struct inherits VM and is also followed by the + * variable-sized array of GVMCPU objects. We only allocate and maintain + * the R3 VM struct, which must be page-aligned and contains an array of + * VMCPU pointers in apCpusR3. + */ + Vm *vm_ptr = (Vm *)RTMemPageAllocZ(gvm_size(cpu_count)); + + vm_ptr->init(psession, cpu_count); + + return *vm_ptr; +} + + +void Sup::Vm::register_vcpu_handler(Cpu_index cpu_index, Vcpu_handler &handler) +{ + if (cpu_index.value >= VM::cCpus) + throw Cpu_index_out_of_range(); + + VMCPU &cpu = GVM::aCpus[cpu_index.value]; + + /* + * We misuse the pVCpuR0ForVtg member for storing the pointer + * to the CPU's corresponding Vcpu_handler. + */ + cpu.pVCpuR0ForVtg = (RTR0PTR)&handler; +} + diff --git a/repos/ports/src/virtualbox6/sup_vm.h b/repos/ports/src/virtualbox6/sup_vm.h new file mode 100644 index 0000000000..86e7800048 --- /dev/null +++ b/repos/ports/src/virtualbox6/sup_vm.h @@ -0,0 +1,57 @@ +/* + * \brief Suplib VM implementation + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-10-12 + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SUP_VM_H_ +#define _SUP_VM_H_ + +/* VirtualBox includes */ +#include +#include + +/* local includes */ +#include + +namespace Sup { + struct Vm; + struct Vcpu_handler; +} + +struct Sup::Vm : GVM +{ + void init(PSUPDRVSESSION psession, Cpu_count cpu_count); + + static Vm & create(PSUPDRVSESSION psession, Cpu_count cpu_count); + + class Cpu_index_out_of_range : Exception { }; + + void register_vcpu_handler(Cpu_index cpu_index, Vcpu_handler &handler); + + template + void with_vcpu_handler(Cpu_index cpu_index, FN const &fn) + { + if (cpu_index.value >= VM::cCpus) + throw Cpu_index_out_of_range(); + + VMCPU &cpu = GVM::aCpus[cpu_index.value]; + + Vcpu_handler * const handler_ptr = (Vcpu_handler *)cpu.pVCpuR0ForVtg; + + Assert(handler_ptr); + + fn(*handler_ptr); + } +}; + +#endif /* _SUP_VM_H_ */ + diff --git a/repos/ports/src/virtualbox6/svm.h b/repos/ports/src/virtualbox6/svm.h new file mode 100644 index 0000000000..7f5b278434 --- /dev/null +++ b/repos/ports/src/virtualbox6/svm.h @@ -0,0 +1,103 @@ +/* + * \brief Genode specific VirtualBox SUPLib supplements + * \author Norman Feske + * \author Alexander Boettcher + * \author Christian Helmuth + * \date 2013-08-21 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _VIRTUALBOX__SVM_H_ +#define _VIRTUALBOX__SVM_H_ + +/* based on HWSVMR0.h - adjusted to Genode */ + +#define GENODE_SVM_ASSERT_SELREG(REG) \ + AssertMsg(!pCtx->REG.Attr.n.u1Present || \ + (pCtx->REG.Attr.n.u1Granularity \ + ? (pCtx->REG.u32Limit & 0xfffU) == 0xfffU \ + : pCtx->REG.u32Limit <= 0xfffffU), \ + ("%u %u %#x %#x %#llx\n", pCtx->REG.Attr.n.u1Present, \ + pCtx->REG.Attr.n.u1Granularity, pCtx->REG.u32Limit, \ + pCtx->REG.Attr.u, pCtx->REG.u64Base)) + +#define GENODE_READ_SELREG(REG) \ + pCtx->REG.Sel = state.REG.value().sel; \ + pCtx->REG.ValidSel = state.REG.value().sel; \ + pCtx->REG.fFlags = CPUMSELREG_FLAGS_VALID; \ + pCtx->REG.u32Limit = state.REG.value().limit; \ + pCtx->REG.u64Base = state.REG.value().base; \ + pCtx->REG.Attr.u = sel_ar_conv_from_genode(state.REG.value().ar) + +static inline bool svm_save_state(Genode::Vcpu_state const &state, VM *pVM, PVMCPU pVCpu) +{ + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); + + GENODE_READ_SELREG(cs); + GENODE_READ_SELREG(ds); + GENODE_READ_SELREG(es); + GENODE_READ_SELREG(fs); + GENODE_READ_SELREG(gs); + GENODE_READ_SELREG(ss); + + GENODE_SVM_ASSERT_SELREG(cs); + GENODE_SVM_ASSERT_SELREG(ds); + GENODE_SVM_ASSERT_SELREG(es); + GENODE_SVM_ASSERT_SELREG(fs); + GENODE_SVM_ASSERT_SELREG(gs); + GENODE_SVM_ASSERT_SELREG(ss); + + GENODE_READ_SELREG(ldtr); + GENODE_READ_SELREG(tr); + + return true; +} + +#undef GENODE_ASSERT_SELREG +#undef GENODE_READ_SELREG + + +#define GENODE_WRITE_SELREG(REG) \ + Assert(pCtx->REG.fFlags & CPUMSELREG_FLAGS_VALID); \ + Assert(pCtx->REG.ValidSel == pCtx->REG.Sel); \ + state.REG.charge(Segment { .sel = pCtx->REG.Sel, \ + .ar = sel_ar_conv_to_genode(pCtx->REG.Attr.u), \ + .limit = pCtx->REG.u32Limit, \ + .base = pCtx->REG.u64Base}); + +static inline bool svm_load_state(Genode::Vcpu_state &state, VM const *pVM, PVMCPU pVCpu) +{ + typedef Genode::Vcpu_state::Segment Segment; + + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); + + state.efer.charge(pCtx->msrEFER | MSR_K6_EFER_SVME); + /* unimplemented */ + if (CPUMIsGuestInLongModeEx(pCtx)) + return false; + state.efer.charge(state.efer.value() & ~MSR_K6_EFER_LME); + + GENODE_WRITE_SELREG(es); + GENODE_WRITE_SELREG(ds); + + GENODE_WRITE_SELREG(fs); + GENODE_WRITE_SELREG(gs); + + GENODE_WRITE_SELREG(cs); + GENODE_WRITE_SELREG(ss); + + GENODE_WRITE_SELREG(ldtr); + GENODE_WRITE_SELREG(tr); + + return true; +} + +#undef GENODE_WRITE_SELREG + +#endif /* _VIRTUALBOX__SVM_H_ */ diff --git a/repos/ports/src/virtualbox6/target.mk b/repos/ports/src/virtualbox6/target.mk new file mode 100644 index 0000000000..7e5da19f84 --- /dev/null +++ b/repos/ports/src/virtualbox6/target.mk @@ -0,0 +1,47 @@ +TARGET = virtualbox6 + +include $(REP_DIR)/lib/mk/virtualbox6-common.inc + +CC_WARN += -Wall + +SRC_CC := main.cc drivers.cc vcpu_gim.cc +SRC_CC += libc.cc unimpl.cc dummies.cc pdm.cc devices.cc nem.cc dynlib.cc + +LIBS += base +LIBS += stdcxx +LIBS += libiconv + +CC_OPT_main = -Wno-multistatement-macros +CC_OPT += -DProgress=ClientProgress + +LIB_MK_FILES := $(notdir $(wildcard $(REP_DIR)/lib/mk/virtualbox6-*.mk) \ + $(wildcard $(REP_DIR)/lib/mk/spec/x86_64/virtualbox6-*.mk)) + +LIBS += $(LIB_MK_FILES:.mk=) + +INC_DIR += $(call select_from_repositories,src/lib/libc) + +INC_DIR += $(VBOX_DIR)/Runtime/include + +SRC_CC += HostServices/common/message.cpp + +INC_DIR += $(REP_DIR)/src/virtualbox6 + +INC_DIR += $(VBOX_DIR)/Main/include +INC_DIR += $(VBOX_DIR)/VMM/include + +INC_DIR += $(VIRTUALBOX_DIR)/VBoxAPIWrap + +INC_DIR += $(VBOX_DIR)/Main/xml +INC_DIR += $(VIRTUALBOX_DIR)/include/VBox/Graphics +INC_DIR += $(VBOX_DIR)/Main/src-server +INC_DIR += $(VBOX_DIR)/NetworkServices + +# search path to 'scan_code_set_1.h' +INC_DIR += $(call select_from_repositories,src/drivers/ps2) + +LIBS += blit + +vpath %.cc $(REP_DIR)/src/virtualbox6/ + +CC_CXX_WARN_STRICT = diff --git a/repos/ports/src/virtualbox6/unimpl.cc b/repos/ports/src/virtualbox6/unimpl.cc new file mode 100644 index 0000000000..0cfdbf589c --- /dev/null +++ b/repos/ports/src/virtualbox6/unimpl.cc @@ -0,0 +1,104 @@ +/* + * \brief Dummy implementations of symbols needed by VirtualBox + * \author Norman Feske + * \author Christian Helmuth + * \date 2013-08-22 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +extern "C" { + +#define DUMMY(name) \ +void name(void) { \ + Genode::error(__func__, ": " #name " called, not implemented, eip=", \ + __builtin_return_address(0)); \ + for (;;); \ +} + +DUMMY(DBGFR3CoreWrite) +DUMMY(DBGFR3LogModifyDestinations) +DUMMY(DBGFR3LogModifyFlags) +DUMMY(DBGFR3LogModifyGroups) +DUMMY(DBGFR3PagingDumpEx) +DUMMY(DBGFR3ReportBugCheck) +DUMMY(DBGFR3StackWalkBegin) +DUMMY(DBGFR3StackWalkBeginEx) +DUMMY(DBGFR3StackWalkEnd) +DUMMY(DBGFR3StackWalkNext) +DUMMY(drvHostBaseDestructOs) +DUMMY(drvHostBaseDoLockOs) +DUMMY(drvHostBaseEjectOs) +DUMMY(drvHostBaseFlushOs) +DUMMY(drvHostBaseGetMediaSizeOs) +DUMMY(drvHostBaseInitOs) +DUMMY(drvHostBaseIsMediaPollingRequiredOs) +DUMMY(drvHostBaseMediaRefreshOs) +DUMMY(drvHostBaseOpenOs) +DUMMY(drvHostBaseQueryMediaStatusOs) +DUMMY(drvHostBaseReadOs) +DUMMY(drvHostBaseScsiCmdGetBufLimitOs) +DUMMY(drvHostBaseScsiCmdOs) +DUMMY(drvHostBaseWriteOs) +DUMMY(PDMCritSectBothFF) +DUMMY(PDMNsAllocateBandwidth) +DUMMY(PDMR3LdrEnumModules) +DUMMY(PDMR3LdrGetInterfaceSymbols) +DUMMY(PGMR3MappingsFix) +DUMMY(PGMR3MappingsUnfix) +DUMMY(PGMR3SharedModuleCheckAll) +DUMMY(PGMR3SharedModuleRegister) +DUMMY(PGMR3SharedModuleUnregister) +DUMMY(RTDbgAsLineByAddr) +DUMMY(RTDbgAsLockExcl) +DUMMY(RTDbgAsModuleByIndex) +DUMMY(RTDbgAsModuleCount) +DUMMY(RTDbgAsModuleLink) +DUMMY(RTDbgAsModuleQueryMapByIndex) +DUMMY(RTDbgAsModuleUnlink) +DUMMY(RTDbgAsSymbolByAddr) +DUMMY(RTDbgAsUnlockExcl) +DUMMY(RTDbgCfgRelease) +DUMMY(RTDbgLineDup) +DUMMY(RTDbgLineFree) +DUMMY(RTDbgModCreateFromImage) +DUMMY(RTDbgModLineByAddr) +DUMMY(RTDbgModName) +DUMMY(RTDbgModRelease) +DUMMY(RTDbgModSegmentRva) +DUMMY(RTDbgModSymbolByAddr) +DUMMY(RTDbgModUnwindFrame) +DUMMY(RTDbgSymbolDup) +DUMMY(RTDbgSymbolFree) +DUMMY(RTFileQueryFsSizes) +DUMMY(RTFsIsoMakerCmdEx) +DUMMY(RTLdrLoadAppPriv) +DUMMY(RTLdrLoadEx) +DUMMY(RTProcCreate) +DUMMY(RTSystemQueryAvailableRam) +DUMMY(RTZipXarFsStreamFromIoStream) +DUMMY(SELMR3GetSelectorInfo) +DUMMY(SUPGetCpuHzFromGipForAsyncMode) +DUMMY(SUPReadTscWithDelta) +DUMMY(USBFilterClone) +DUMMY(VDIfTcpNetInstDefaultDestroy) + +/* xpcom */ +DUMMY(_MD_CreateUnixProcess) +DUMMY(_MD_CreateUnixProcessDetached) +DUMMY(_MD_KillUnixProcess) +DUMMY(_MD_WaitUnixProcess) +DUMMY(PR_FindSymbol) +DUMMY(PR_LoadLibrary) +DUMMY(PR_LoadLibraryWithFlags) +DUMMY(_PR_MapOptionName) +DUMMY(PR_UnloadLibrary) + +} /* extern "C" */ diff --git a/repos/ports/src/virtualbox6/util.h b/repos/ports/src/virtualbox6/util.h new file mode 100644 index 0000000000..18062c0679 --- /dev/null +++ b/repos/ports/src/virtualbox6/util.h @@ -0,0 +1,37 @@ +/* + * \brief VirtualBox utilities + * \author Christian Helmuth + * \date 2013-08-28 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +/* VirtualBox includes */ +#include +#include + + +/** + * 64bit-aware cast of pointer to RTRCPTR (uint32_t) + */ +template +RTRCPTR to_rtrcptr(T* ptr) +{ + unsigned long long u64 = reinterpret_cast(ptr); + RTRCPTR rtrcptr = u64 & 0xFFFFFFFFULL; + + AssertMsg((u64 == rtrcptr) || (u64 >> 32) == 0xFFFFFFFFULL, + ("pointer transformation - %llx != %x", u64, rtrcptr)); + + return rtrcptr; +} + +#endif /* _UTIL_H_ */ diff --git a/repos/ports/src/virtualbox6/vcpu.cc b/repos/ports/src/virtualbox6/vcpu.cc new file mode 100644 index 0000000000..e993bcdbcd --- /dev/null +++ b/repos/ports/src/virtualbox6/vcpu.cc @@ -0,0 +1,1111 @@ +/* + * \brief SUPLib vCPU utility + * \author Alexander Boettcher + * \author Norman Feske + * \author Christian Helmuth + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include + +/* VirtualBox includes */ +#include /* must be included before CPUMInternal.h */ +#include /* enable access to cpum.s.* */ +#include /* enable access to hm.s.* */ +#include +#include +#include +#include +#include +#include +#include + +/* libc includes */ +#include /* for exit() */ +#include + +/* local includes */ +#include + + +/* + * VirtualBox stores segment attributes in Intel format using 17 bits of a + * 32-bit value, which includes bits 19:16 of segment limit (see + * X86DESCATTRBITS). + * + * Genode represents the attributes in packed SVM VMCB format using 13 bits of + * a 16-bit value without segment-limit bits. + */ +static inline Genode::uint16_t sel_ar_conv_to_genode(Genode::uint32_t v) +{ + return (v & 0xff) | ((v & 0x1f000) >> 4); +} + + +static inline Genode::uint32_t sel_ar_conv_from_genode(Genode::uint16_t v) +{ + return (v & 0xff) | (((uint32_t )v << 4) & 0x1f000); +} + +/* XXX these headers use the functions defined above */ +#include +#include + + +/***************** + ** SVM handler ** + *****************/ + +void Sup::Vcpu_handler_svm::_svm_default() { _default_handler(); } +void Sup::Vcpu_handler_svm::_svm_vintr() { _irq_window(); } + + +void Sup::Vcpu_handler_svm::_svm_ioio() +{ + Vcpu_state &state { _vcpu.state() }; + + if (state.qual_primary.value() & 0x4) { + unsigned ctrl0 = state.ctrl_primary.value(); + + Genode::warning("invalid gueststate"); + + state.discharge(); + + state.ctrl_primary.charge(ctrl0); + state.ctrl_secondary.charge(0); + + _run_vm(); + } else + _default_handler(); +} + + +template void Sup::Vcpu_handler_svm::_svm_npt() +{ + Vcpu_state &state { _vcpu.state() }; + + bool const unmap = state.qual_primary.value() & 1; + Genode::addr_t const exit_addr = state.qual_secondary.value(); + RTGCUINT const vbox_errorcode = state.qual_primary.value(); + + _npt_ept_exit_addr = exit_addr; + _npt_ept_unmap = unmap; + _npt_ept_errorcode = vbox_errorcode; + + _npt_ept(); +} + + +void Sup::Vcpu_handler_svm::_svm_startup() +{ + /* enable VM exits for CPUID */ + _next_utcb.ctrl[0] = SVM_CTRL_INTERCEPT_CPUID; + _next_utcb.ctrl[1] = 0; +} + + +void Sup::Vcpu_handler_svm::_handle_exit() +{ + /* + * Table B-1. 070h 63:0 EXITCODE + * + * Appendix C SVM Intercept Exit Codes defines only + * 0x000..0x403 plus -1 and -2 + */ + unsigned short const exit = _vcpu.state().exit_reason & 0xffff; + bool recall_wait = true; + +// Genode::warning(__PRETTY_FUNCTION__, ": ", HMGetSvmExitName(exit)); + + switch (exit) { + case SVM_EXIT_IOIO: _svm_ioio(); break; + case SVM_EXIT_VINTR: _svm_vintr(); break; +// case SVM_EXIT_RDTSC: _svm_default(); break; + case SVM_EXIT_MSR: + /* XXX distiguish write from read */ + _last_exit_triggered_by_wrmsr = true; + _svm_default(); + break; + case SVM_NPT: _svm_npt(); break; + case SVM_EXIT_HLT: _svm_default(); break; + case SVM_EXIT_CPUID: _svm_default(); break; + case RECALL: + recall_wait = Vcpu_handler::_recall_handler(); + break; + case VCPU_STARTUP: + _svm_startup(); + _blockade_emt.wakeup(); + /* pause - no resume */ + break; + default: + Genode::error(__func__, " unknown exit - stop - ", + Genode::Hex(exit)); + _vm_state = PAUSED; + return; + } + + if (exit == RECALL && !recall_wait) { + _vm_state = RUNNING; + _run_vm(); + return; + } + + /* wait until EMT thread wake's us up */ + _sem_handler.down(); + + /* resume vCPU */ + _vm_state = RUNNING; + if (_next_state == RUN) + _run_vm(); + else + _pause_vm(); /* cause pause exit */ +} + + +bool Sup::Vcpu_handler_svm::_hw_save_state(VM * pVM, PVMCPU pVCpu) +{ + return svm_save_state(_vcpu.state(), pVM, pVCpu); +} + + +bool Sup::Vcpu_handler_svm::_hw_load_state(VM * pVM, PVMCPU pVCpu) +{ + return svm_load_state(_vcpu.state(), pVM, pVCpu); +} + + +int Sup::Vcpu_handler_svm::_vm_exit_requires_instruction_emulation(PCPUMCTX) +{ + if (_state->exit_reason == RECALL) + return VINF_SUCCESS; + + return VINF_EM_RAW_EMULATE_INSTR; +} + + +Sup::Vcpu_handler_svm::Vcpu_handler_svm(Genode::Env &env, size_t stack_size, + Genode::Affinity::Location location, + unsigned int cpu_id, + Genode::Vm_connection &vm_connection, + Genode::Allocator &alloc) +: + Vcpu_handler(env, stack_size, location, cpu_id), + _handler(_ep, *this, &Vcpu_handler_svm::_handle_exit), + _vm_connection(vm_connection), + _vcpu(_vm_connection, alloc, _handler, _exit_config) +{ + _state = &_vcpu.state(); + + _vcpu.run(); + + /* sync with initial startup exception */ + _blockade_emt.block(); +} + + +/***************** + ** VMX handler ** + *****************/ + +void Sup::Vcpu_handler_vmx::_vmx_default() { _default_handler(); } +void Sup::Vcpu_handler_vmx::_vmx_irqwin() { _irq_window(); } +void Sup::Vcpu_handler_vmx::_vmx_mov_crx() { _default_handler(); } + + +template void Sup::Vcpu_handler_vmx::_vmx_ept() +{ + Genode::addr_t const exit_qual = _state->qual_primary.value(); + Genode::addr_t const exit_addr = _state->qual_secondary.value(); + bool const unmap = exit_qual & 0x38; + + RTGCUINT vbox_errorcode = 0; + if (exit_qual & VMX_EXIT_QUAL_EPT_INSTR_FETCH) + vbox_errorcode |= X86_TRAP_PF_ID; + if (exit_qual & VMX_EXIT_QUAL_EPT_DATA_WRITE) + vbox_errorcode |= X86_TRAP_PF_RW; + if (exit_qual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT) + vbox_errorcode |= X86_TRAP_PF_P; + + _npt_ept_exit_addr = exit_addr; + _npt_ept_unmap = unmap; + _npt_ept_errorcode = vbox_errorcode; + + _npt_ept(); +} + + + +void Sup::Vcpu_handler_vmx::_vmx_startup() +{ + /* configure VM exits to get */ + /* from src/VBox/VMM/VMMR0/HWVMXR0.cpp of virtualbox sources */ + _next_utcb.ctrl[0] = 0 + | VMX_PROC_CTLS_HLT_EXIT + | VMX_PROC_CTLS_MOV_DR_EXIT + | VMX_PROC_CTLS_UNCOND_IO_EXIT +// | VMX_PROC_CTLS_MONITOR_EXIT +// | VMX_PROC_CTLS_MWAIT_EXIT +// | VMX_PROC_CTLS_CR8_LOAD_EXIT +// | VMX_PROC_CTLS_CR8_STORE_EXIT + | VMX_PROC_CTLS_USE_TPR_SHADOW + | VMX_PROC_CTLS_RDPMC_EXIT +// | VMX_PROC_CTLS_PAUSE_EXIT + /* + * Disable trapping RDTSC for now as it creates a huge load with + * VM guests that execute it frequently. + */ +// | VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT + ; + + _next_utcb.ctrl[1] = 0 + | VMX_PROC_CTLS2_APIC_REG_VIRT + | VMX_PROC_CTLS2_WBINVD_EXIT + | VMX_PROC_CTLS2_UNRESTRICTED_GUEST + | VMX_PROC_CTLS2_VPID + | VMX_PROC_CTLS2_RDTSCP + | VMX_PROC_CTLS2_EPT + | VMX_PROC_CTLS2_INVPCID + ; +} + + +void Sup::Vcpu_handler_vmx::_vmx_triple() +{ + Genode::error("triple fault - dead"); + exit(-1); +} + + +__attribute__((noreturn)) void Sup::Vcpu_handler_vmx::_vmx_invalid() +{ + unsigned const dubious = _state->inj_info.value() | + _state->intr_state.value() | + _state->actv_state.value(); + if (dubious) + Genode::warning(__func__, " - dubious -" + " inj_info=", Genode::Hex(_state->inj_info.value()), + " inj_error=", Genode::Hex(_state->inj_error.value()), + " intr_state=", Genode::Hex(_state->intr_state.value()), + " actv_state=", Genode::Hex(_state->actv_state.value())); + + Genode::error("invalid guest state - dead"); + exit(-1); +} + + +void Sup::Vcpu_handler_vmx::_handle_exit() +{ + /* table 24-14. Format of Exit Reason - 15:0 Basic exit reason */ + unsigned short const exit = _state->exit_reason & 0xffff; + bool recall_wait = true; + +// Genode::warning(__PRETTY_FUNCTION__, ": ", HMGetVmxExitName(exit)); + + switch (exit) { + case VMX_EXIT_TRIPLE_FAULT: _vmx_triple(); break; + case VMX_EXIT_INIT_SIGNAL: _vmx_default(); break; + case VMX_EXIT_INT_WINDOW: _vmx_irqwin(); break; + case VMX_EXIT_TASK_SWITCH: _vmx_default(); break; + case VMX_EXIT_CPUID: _vmx_default(); break; + case VMX_EXIT_HLT: _vmx_default(); break; + /* we don't support tsc offsetting for now - so let the rdtsc exit */ + case VMX_EXIT_RDTSC: _vmx_default(); break; + case VMX_EXIT_RDTSCP: _vmx_default(); break; + case VMX_EXIT_VMCALL: _vmx_default(); break; + case VMX_EXIT_IO_INSTR: _vmx_default(); break; + case VMX_EXIT_RDMSR: _vmx_default(); break; + case VMX_EXIT_WRMSR: + _last_exit_triggered_by_wrmsr = true; + _vmx_default(); + break; + case VMX_EXIT_ERR_INVALID_GUEST_STATE: _vmx_invalid(); break; + case VMX_EXIT_PAUSE: _vmx_default(); break; + case VMX_EXIT_WBINVD: _vmx_default(); break; + case VMX_EXIT_MOV_CRX: _vmx_mov_crx(); break; + case VMX_EXIT_MOV_DRX: _vmx_default(); break; + case VMX_EXIT_XSETBV: _vmx_default(); break; + case VMX_EXIT_TPR_BELOW_THRESHOLD: _vmx_default(); break; + case VMX_EXIT_EPT_VIOLATION: _vmx_ept(); break; + case RECALL: + recall_wait = Vcpu_handler::_recall_handler(); + break; + case VCPU_STARTUP: + _vmx_startup(); + _blockade_emt.wakeup(); + /* pause - no resume */ + break; + default: + Genode::error(__func__, " unknown exit - stop - ", + Genode::Hex(exit)); + _vm_state = PAUSED; + return; + } + + if (exit == RECALL && !recall_wait) { + _vm_state = RUNNING; + _run_vm(); + return; + } + + /* wait until EMT thread wake's us up */ + _sem_handler.down(); + + /* resume vCPU */ + _vm_state = RUNNING; + if (_next_state == RUN) + _run_vm(); + else + _pause_vm(); /* cause pause exit */ +} + + +bool Sup::Vcpu_handler_vmx::_hw_save_state(PVM pVM, PVMCPU pVCpu) +{ + return vmx_save_state(_vcpu.state(), pVM, pVCpu); +} + + +bool Sup::Vcpu_handler_vmx::_hw_load_state(PVM pVM, PVMCPU pVCpu) +{ + return vmx_load_state(_vcpu.state(), pVM, pVCpu); +} + + +int Sup::Vcpu_handler_vmx::_vm_exit_requires_instruction_emulation(PCPUMCTX pCtx) +{ + switch (_state->exit_reason) { + case VMX_EXIT_HLT: + pCtx->rip++; + return VINF_EM_HALT; + case VMX_EXIT_IO_INSTR: + /* EMHandleRCTmpl.h does not distinguish READ/WRITE rc */ + return VINF_IOM_R3_IOPORT_WRITE; + case VMX_EXIT_RDMSR: + return VINF_CPUM_R3_MSR_READ; + case VMX_EXIT_WRMSR: + return VINF_CPUM_R3_MSR_WRITE; + case VMX_EXIT_TPR_BELOW_THRESHOLD: + /* the instruction causing the exit has already been executed */ + case RECALL: + return VINF_SUCCESS; + case VMX_EXIT_EPT_VIOLATION: + if (_ept_fault_addr_type == PGMPAGETYPE_MMIO) + /* EMHandleRCTmpl.h does not distinguish READ/WRITE rc */ + return VINF_IOM_R3_MMIO_READ_WRITE; + case VMX_EXIT_MOV_DRX: + /* looks complicated in original R0 code -> emulate instead */ + return VINF_EM_RAW_EMULATE_INSTR; + default: + return VINF_EM_RAW_EMULATE_INSTR; + } +} + + +Sup::Vcpu_handler_vmx::Vcpu_handler_vmx(Genode::Env &env, size_t stack_size, + Genode::Affinity::Location location, + unsigned int cpu_id, + Genode::Vm_connection &vm_connection, + Genode::Allocator &alloc) +: + Vcpu_handler(env, stack_size, location, cpu_id), + _handler(_ep, *this, &Vcpu_handler_vmx::_handle_exit), + _vm_connection(vm_connection), + _vcpu(_vm_connection, alloc, _handler, _exit_config) +{ + _state = &_vcpu.state(); + + _vcpu.run(); + + /* sync with initial startup exception */ + _blockade_emt.block(); +} + + +/********************* + ** Generic handler ** + *********************/ + +Genode::Vm_connection::Exit_config const Sup::Vcpu_handler::_exit_config { /* ... */ }; + + +timespec Sup::Vcpu_handler::_add_timespec_ns(timespec a, ::uint64_t ns) const +{ + enum { NSEC_PER_SEC = 1'000'000'000ull }; + + long sec = a.tv_sec; + + while (a.tv_nsec >= NSEC_PER_SEC) { + a.tv_nsec -= NSEC_PER_SEC; + sec++; + } + while (ns >= NSEC_PER_SEC) { + ns -= NSEC_PER_SEC; + sec++; + } + + long nsec = a.tv_nsec + ns; + while (nsec >= NSEC_PER_SEC) { + nsec -= NSEC_PER_SEC; + sec++; + } + return timespec { sec, nsec }; +} + + +void Sup::Vcpu_handler::_switch_to_hw(PCPUMCTX pCtx) +{ +again: + + /* export FPU state */ + AssertCompile(sizeof(Vcpu_state::Fpu::State) >= sizeof(X86FXSTATE)); + _state->fpu.charge([&] (Vcpu_state::Fpu::State &fpu) { + ::memcpy(&fpu, pCtx->pXStateR3, sizeof(fpu)); + }); + + Assert(_vm_state == IRQ_WIN || _vm_state == PAUSED || _vm_state == NPT_EPT); + Assert(_next_state == PAUSE_EXIT || _next_state == RUN); + + /* wake up vcpu ep handler */ + _sem_handler.up(); + + /* wait for next exit */ + _blockade_emt.block(); + + /* next time run - recall() may change this */ + _next_state = RUN; + + /* import FPU state */ + _state->fpu.with_state([&] (Vcpu_state::Fpu::State const &fpu) { + ::memcpy(pCtx->pXStateR3, &fpu, sizeof(X86FXSTATE)); + }); + + if (_vm_state == IRQ_WIN) { + _state->discharge(); + _irq_window_pthread(); + goto again; + } else + if (_vm_state == NPT_EPT) { +// if (_npt_ept_unmap) { +// Genode::error("NPT/EPT unmap not supported - stop"); +// while (true) { +// _blockade_emt.block(); +// } +// } + } + + if (!(_vm_state == PAUSED || _vm_state == NPT_EPT)) + Genode::error("which state we are ? ", (int)_vm_state, " ", Genode::Thread::myself()->name()); + + Assert(_vm_state == PAUSED || _vm_state == NPT_EPT); +} + + +void Sup::Vcpu_handler::_default_handler() +{ + if (_vm_state != RUNNING) + Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason)); + Assert(_vm_state == RUNNING); + + Assert(_state->actv_state.value() == ACTIVITY_STATE_ACTIVE); + Assert(!(_state->inj_info.value() & IRQ_INJ_VALID_MASK)); + + _vm_exits++; + + _vm_state = PAUSED; + + _blockade_emt.wakeup(); +} + + +bool Sup::Vcpu_handler::_recall_handler() +{ + if (_vm_state != RUNNING) + Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason)); + Assert(_vm_state == RUNNING); + + _vm_exits++; + _recall_inv++; + + Assert(_state->actv_state.value() == ACTIVITY_STATE_ACTIVE); + + if (_state->inj_info.value() & IRQ_INJ_VALID_MASK) { + + Assert(_state->flags.value() & X86_EFL_IF); + + if (_state->intr_state.value() != INTERRUPT_STATE_NONE) + Genode::log("intr state ", Genode::Hex(_state->intr_state.value()), + " ", Genode::Hex(_state->intr_state.value() & 0xf)); + + Assert(_state->intr_state.value() == INTERRUPT_STATE_NONE); + + if (!_continue_hw_accelerated()) + _recall_drop ++; + + /* got recall during irq injection and the guest is ready for + * delivery of IRQ - just continue */ + return /* no-wait */ false; + } + + /* are we forced to go back to emulation mode ? */ + if (!_continue_hw_accelerated()) { + /* go back to emulation mode */ + _default_handler(); + return /* wait */ true; + } + + /* check whether we have to request irq injection window */ + if (_check_to_request_irq_window(_vcpu)) { + _state->discharge(); + _state->inj_info.charge(_state->inj_info.value()); + _irq_win = true; + return /* no-wait */ false; + } + + _default_handler(); + return /* wait */ true; +} + + +bool Sup::Vcpu_handler::_vbox_to_state(VM *pVM, PVMCPU pVCpu) +{ + typedef Genode::Vcpu_state::Range Range; + + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); + + _state->ip.charge(pCtx->rip); + _state->sp.charge(pCtx->rsp); + + _state->ax.charge(pCtx->rax); + _state->bx.charge(pCtx->rbx); + _state->cx.charge(pCtx->rcx); + _state->dx.charge(pCtx->rdx); + + _state->bp.charge(pCtx->rbp); + _state->si.charge(pCtx->rsi); + _state->di.charge(pCtx->rdi); + + _state->r8.charge(pCtx->r8); + _state->r9.charge(pCtx->r9); + _state->r10.charge(pCtx->r10); + _state->r11.charge(pCtx->r11); + _state->r12.charge(pCtx->r12); + _state->r13.charge(pCtx->r13); + _state->r14.charge(pCtx->r14); + _state->r15.charge(pCtx->r15); + + _state->flags.charge(pCtx->rflags.u); + + _state->sysenter_cs.charge(pCtx->SysEnter.cs); + _state->sysenter_sp.charge(pCtx->SysEnter.esp); + _state->sysenter_ip.charge(pCtx->SysEnter.eip); + + _state->dr7.charge(pCtx->dr[7]); + + _state->cr0.charge(pCtx->cr0); + _state->cr2.charge(pCtx->cr2); + _state->cr3.charge(pCtx->cr3); + _state->cr4.charge(pCtx->cr4); + + _state->idtr.charge(Range { .limit = pCtx->idtr.cbIdt, + .base = pCtx->idtr.pIdt }); + _state->gdtr.charge(Range { .limit = pCtx->gdtr.cbGdt, + .base = pCtx->gdtr.pGdt }); + + _state->efer.charge(CPUMGetGuestEFER(pVCpu)); + + /* + * Update the PDPTE registers if necessary + * + * Intel manual sections 4.4.1 of Vol. 3A and 26.3.2.4 of Vol. 3C + * indicate the conditions when this is the case. The following + * code currently does not check if the recompiler modified any + * CR registers, which means the update can happen more often + * than really necessary. + */ + if (pVM->hm.s.vmx.fSupported && + CPUMIsGuestPagingEnabledEx(pCtx) && + CPUMIsGuestInPAEModeEx(pCtx)) { + + Genode::warning("PDPTE updates disabled!"); +// Genode::uint64_t *pdpte = pdpte_map(pVM, pCtx->cr3); +// +// _state->pdpte_0.charge(pdpte[0]); +// _state->pdpte_1.charge(pdpte[1]); +// _state->pdpte_2.charge(pdpte[2]); +// _state->pdpte_3.charge(pdpte[3]); + } + + _state->star.charge(pCtx->msrSTAR); + _state->lstar.charge(pCtx->msrLSTAR); + _state->fmask.charge(pCtx->msrSFMASK); + _state->kernel_gs_base.charge(pCtx->msrKERNELGSBASE); + + /* from HMVMXR0.cpp */ + bool interrupt_pending = false; + uint8_t tpr = 0; + uint8_t pending_interrupt = 0; + APICGetTpr(pVCpu, &tpr, &interrupt_pending, &pending_interrupt); + + _state->tpr.charge(tpr); + _state->tpr_threshold.charge(0); + + if (interrupt_pending) { + const uint8_t pending_priority = (pending_interrupt >> 4) & 0xf; + const uint8_t tpr_priority = (tpr >> 4) & 0xf; + if (pending_priority <= tpr_priority) + _state->tpr_threshold.charge(pending_priority); + else + _state->tpr_threshold.charge(tpr_priority); + } + + return true; +} + + +bool Sup::Vcpu_handler::_state_to_vbox(VM *pVM, PVMCPU pVCpu) +{ + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); + + pCtx->rip = _state->ip.value(); + pCtx->rsp = _state->sp.value(); + + pCtx->rax = _state->ax.value(); + pCtx->rbx = _state->bx.value(); + pCtx->rcx = _state->cx.value(); + pCtx->rdx = _state->dx.value(); + + pCtx->rbp = _state->bp.value(); + pCtx->rsi = _state->si.value(); + pCtx->rdi = _state->di.value(); + pCtx->rflags.u = _state->flags.value(); + + pCtx->r8 = _state->r8.value(); + pCtx->r9 = _state->r9.value(); + pCtx->r10 = _state->r10.value(); + pCtx->r11 = _state->r11.value(); + pCtx->r12 = _state->r12.value(); + pCtx->r13 = _state->r13.value(); + pCtx->r14 = _state->r14.value(); + pCtx->r15 = _state->r15.value(); + + pCtx->dr[7] = _state->dr7.value(); + + if (pCtx->SysEnter.cs != _state->sysenter_cs.value()) + CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_CS, _state->sysenter_cs.value()); + + if (pCtx->SysEnter.esp != _state->sysenter_sp.value()) + CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_ESP, _state->sysenter_sp.value()); + + if (pCtx->SysEnter.eip != _state->sysenter_ip.value()) + CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_EIP, _state->sysenter_ip.value()); + + if (pCtx->idtr.cbIdt != _state->idtr.value().limit || + pCtx->idtr.pIdt != _state->idtr.value().base) + CPUMSetGuestIDTR(pVCpu, _state->idtr.value().base, _state->idtr.value().limit); + + if (pCtx->gdtr.cbGdt != _state->gdtr.value().limit || + pCtx->gdtr.pGdt != _state->gdtr.value().base) + CPUMSetGuestGDTR(pVCpu, _state->gdtr.value().base, _state->gdtr.value().limit); + + CPUMSetGuestEFER(pVCpu, _state->efer.value()); + + if (pCtx->cr0 != _state->cr0.value()) + CPUMSetGuestCR0(pVCpu, _state->cr0.value()); + + if (pCtx->cr2 != _state->cr2.value()) + CPUMSetGuestCR2(pVCpu, _state->cr2.value()); + + if (pCtx->cr3 != _state->cr3.value()) { + CPUMSetGuestCR3(pVCpu, _state->cr3.value()); + VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3); + } + + if (pCtx->cr4 != _state->cr4.value()) + CPUMSetGuestCR4(pVCpu, _state->cr4.value()); + + if (pCtx->msrSTAR != _state->star.value()) + CPUMSetGuestMsr(pVCpu, MSR_K6_STAR, _state->star.value()); + + if (pCtx->msrLSTAR != _state->lstar.value()) + CPUMSetGuestMsr(pVCpu, MSR_K8_LSTAR, _state->lstar.value()); + + if (pCtx->msrSFMASK != _state->fmask.value()) + CPUMSetGuestMsr(pVCpu, MSR_K8_SF_MASK, _state->fmask.value()); + + if (pCtx->msrKERNELGSBASE != _state->kernel_gs_base.value()) + CPUMSetGuestMsr(pVCpu, MSR_K8_KERNEL_GS_BASE, _state->kernel_gs_base.value()); + + const uint32_t tpr = _state->tpr.value(); + + /* reset message transfer descriptor for next invocation */ +// Assert (!(_state->inj_info.value() & IRQ_INJ_VALID_MASK)); + _next_utcb.intr_state = _state->intr_state.value(); + _next_utcb.ctrl[0] = _state->ctrl_primary.value(); + _next_utcb.ctrl[1] = _state->ctrl_secondary.value(); + + if (_next_utcb.intr_state & 3) { + _next_utcb.intr_state &= ~3U; + } + + VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3); + + pVCpu->cpum.s.fUseFlags |= (CPUM_USED_FPU_GUEST); +// CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM); +// pVCpu->cpum.s.fUseFlags |= (CPUM_USED_FPU_GUEST | CPUM_USED_FPU_SINCE_REM); + + if (_state->intr_state.value() != 0) { + Assert(_state->intr_state.value() == INTERRUPT_STATE_BLOCKING_BY_STI || + _state->intr_state.value() == INTERRUPT_STATE_BLOCKING_BY_MOV_SS); + EMSetInhibitInterruptsPC(pVCpu, pCtx->rip); + } else + VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); + + APICSetTpr(pVCpu, tpr); + + return true; +} + + +bool Sup::Vcpu_handler::_check_to_request_irq_window(PVMCPU pVCpu) +{ + if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) + return false; + + if (!TRPMHasTrap(pVCpu) && + !VMCPU_FF_IS_SET(pVCpu, (VMCPU_FF_INTERRUPT_APIC | + VMCPU_FF_INTERRUPT_PIC))) + return false; + + _irq_request++; + + unsigned const vector = 0; + _state->inj_info.charge(REQ_IRQWIN_EXIT | vector); + + return true; +} + + +void Sup::Vcpu_handler::_irq_window() +{ + if (_vm_state != RUNNING) + Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason)); + Assert(_vm_state == RUNNING); + + _vm_exits++; + + _vm_state = IRQ_WIN; + _blockade_emt.wakeup(); +} + + +void Sup::Vcpu_handler::_npt_ept() +{ + if (_vm_state != RUNNING) + Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason)); + Assert(_vm_state == RUNNING); + + _vm_exits++; + + _vm_state = NPT_EPT; + _blockade_emt.wakeup(); +} + + +void Sup::Vcpu_handler::_irq_window_pthread() +{ + PVMCPU pVCpu = _vcpu; + + Assert(_state->intr_state.value() == INTERRUPT_STATE_NONE); + Assert(_state->flags.value() & X86_EFL_IF); + Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)); + Assert(!(_state->inj_info.value() & IRQ_INJ_VALID_MASK)); + + Assert(_irq_win); + + _irq_win = false; + + /* request current tpr state from guest, it may block IRQs */ + APICSetTpr(pVCpu, _state->tpr_threshold.value()); + + if (!TRPMHasTrap(pVCpu)) { + + bool res = VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI); + if (res) + Genode::log("NMI was set"); + + if (VMCPU_FF_IS_SET(pVCpu, (VMCPU_FF_INTERRUPT_APIC | + VMCPU_FF_INTERRUPT_PIC))) { + + uint8_t irq; + int rc = PDMGetInterrupt(pVCpu, &irq); + Assert(RT_SUCCESS(rc)); + + rc = TRPMAssertTrap(pVCpu, irq, TRPM_HARDWARE_INT); + Assert(RT_SUCCESS(rc)); + } + + if (!TRPMHasTrap(pVCpu)) { + _irq_drop++; + /* happens if APICSetTpr (see above) mask IRQ */ + _state->inj_info.charge(IRQ_INJ_NONE); + Genode::error("virq window pthread aaaaaaa while loop"); + return; + } + } + _irq_inject++; + + /* + * If we have no IRQ for injection, something with requesting the + * IRQ window went wrong. Probably it was forgotten to be reset. + */ + Assert(TRPMHasTrap(pVCpu)); + + /* interrupt can be dispatched */ + uint8_t u8Vector; + TRPMEVENT enmType; + SVMEVENT Event; + uint32_t u32ErrorCode; + RTGCUINT cr2; + + Event.u = 0; + + /* If a new event is pending, then dispatch it now. */ + int rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, &cr2, 0, 0); + AssertRC(rc); + Assert(enmType == TRPM_HARDWARE_INT); + Assert(u8Vector != X86_XCPT_NMI); + + /* Clear the pending trap. */ + rc = TRPMResetTrap(pVCpu); + AssertRC(rc); + + Event.n.u8Vector = u8Vector; + Event.n.u1Valid = 1; + Event.n.u32ErrorCode = u32ErrorCode; + + Event.n.u3Type = SVM_EVENT_EXTERNAL_IRQ; + + _state->inj_info.charge(Event.u); + _state->inj_error.charge(Event.n.u32ErrorCode); + + _last_inj_info = _state->inj_info.value(); + _last_inj_error = _state->inj_error.value(); + +// Genode::log("type:info:vector ", Genode::Hex(Event.n.u3Type), +// Genode::Hex(utcb->inj_info), Genode::Hex(u8Vector), +// " intr:actv - ", Genode::Hex(utcb->intr_state), +// Genode::Hex(utcb->actv_state), " mtd ", +// Genode::Hex(utcb->mtd)); +} + + +bool Sup::Vcpu_handler::_continue_hw_accelerated() +{ + uint32_t check_vm = VM_FF_HM_TO_R3_MASK | VM_FF_REQUEST + | VM_FF_PGM_POOL_FLUSH_PENDING + | VM_FF_PDM_DMA; + uint32_t check_vcpu = VMCPU_FF_HM_TO_R3_MASK + | VMCPU_FF_PGM_SYNC_CR3 + | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL + | VMCPU_FF_REQUEST; + + if (!VM_FF_IS_SET(_vm, check_vm) && + !VMCPU_FF_IS_SET(_vcpu, check_vcpu)) + return true; + + Assert(!(VM_FF_IS_SET(_vm, VM_FF_PGM_NO_MEMORY))); + +#define VERBOSE_VM(flag) \ + if (VM_FF_IS_SET(_vm, flag)) Genode::log("flag ", flag, " pending") + +#define VERBOSE_VMCPU(flag) \ + if (VMCPU_FF_IS_SET(_vcpu, flag)) Genode::log("flag ", flag, " pending") + + if (false) { + VERBOSE_VM(VM_FF_TM_VIRTUAL_SYNC); + VERBOSE_VM(VM_FF_PGM_NEED_HANDY_PAGES); + /* handled by the assertion above */ + //VERBOSE_VM(VM_FF_PGM_NO_MEMORY); + VERBOSE_VM(VM_FF_PDM_QUEUES); + VERBOSE_VM(VM_FF_EMT_RENDEZVOUS); + VERBOSE_VM(VM_FF_REQUEST); + VERBOSE_VM(VM_FF_PGM_POOL_FLUSH_PENDING); + VERBOSE_VM(VM_FF_PDM_DMA); + + VERBOSE_VMCPU(VMCPU_FF_TO_R3); + /* when this flag gets set, a recall request follows */ + //VERBOSE_VMCPU(VMCPU_FF_TIMER); + VERBOSE_VMCPU(VMCPU_FF_PDM_CRITSECT); + VERBOSE_VMCPU(VMCPU_FF_PGM_SYNC_CR3); + VERBOSE_VMCPU(VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL); + VERBOSE_VMCPU(VMCPU_FF_REQUEST); + } + +#undef VERBOSE_VMCPU +#undef VERBOSE_VM + + return false; +} + + +void Sup::Vcpu_handler::recall(VM &vm) +{ + VM *pVM = &vm; + + if (!_vm || !_vcpu) { + _vm = pVM; + _vcpu = pVM->apCpusR3[_cpu_id]; + } + + if (_vm != pVM || _vcpu != pVM->apCpusR3[_cpu_id]) + Genode::error("wrong CPU !?"); + + _recall_req++; + + if (_irq_win) { + _recall_skip++; + return; + } + + asm volatile ("":::"memory"); + + if (_vm_state != PAUSED) + _pause_vm(); + + _next_state = PAUSE_EXIT; +} + + +void Sup::Vcpu_handler::halt(Genode::uint64_t const wait_ns) +{ + /* calculate timeout */ + timespec ts { 0, 0 }; + clock_gettime(CLOCK_REALTIME, &ts); + ts = _add_timespec_ns(ts, wait_ns); + + /* wait for condition or timeout */ + pthread_mutex_lock(&_mutex); + pthread_cond_timedwait(&_cond_wait, &_mutex, &ts); + pthread_mutex_unlock(&_mutex); +} + + +void Sup::Vcpu_handler::wake_up() +{ + pthread_mutex_lock(&_mutex); + pthread_cond_signal(&_cond_wait); + pthread_mutex_unlock(&_mutex); +} + + +int Sup::Vcpu_handler::run_hw(VM &vm) +{ + VM * pVM = &vm; + PVMCPU pVCpu = pVM->apCpusR3[_cpu_id]; + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); + + if (!_vm || !_vcpu) { + _vm = pVM; + _vcpu = pVM->apCpusR3[_cpu_id]; + } + + if (_vm != pVM || _vcpu != pVM->apCpusR3[_cpu_id]) + Genode::error("wrong CPU !?"); + + /* take the utcb state prepared during the last exit */ + _state->inj_info.charge(IRQ_INJ_NONE); + _state->intr_state.charge(_next_utcb.intr_state); + _state->actv_state.charge(ACTIVITY_STATE_ACTIVE); + _state->ctrl_primary.charge(_next_utcb.ctrl[0]); + _state->ctrl_secondary.charge(_next_utcb.ctrl[1]); + + /* Transfer vCPU state from vbox to Genode format */ + if (!_vbox_to_state(pVM, pVCpu) || + !_hw_load_state(pVM, pVCpu)) { + + Genode::error("loading vCPU state failed"); + return VERR_INTERNAL_ERROR; + } + + /* handle interrupt injection - move to Vcpu_handler */ +// warning(__PRETTY_FUNCTION__, " 1 VMCPU_FF_IS_ANY_SET=", +// VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_PIC +// | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI)); +// warning(__PRETTY_FUNCTION__, " 2 VM_FF_IS_ANY_SET=", +// VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC), +// " VMCPU_FF_IS_ANY_SET=", +// VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK)); + + _last_exit_triggered_by_wrmsr = false; + + /* check whether to request interrupt window for injection */ + _irq_win = _check_to_request_irq_window(pVCpu); + + /* mimic state machine implemented in nemHCWinRunGC() etc. */ + VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM); + + /* switch to hardware accelerated mode */ + _switch_to_hw(pCtx); + + Assert(_state->actv_state.value() == ACTIVITY_STATE_ACTIVE); + + /* see hmR0VmxExitToRing3 - sync recompiler state */ + CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR | + CPUM_CHANGED_LDTR | CPUM_CHANGED_GDTR | + CPUM_CHANGED_IDTR | CPUM_CHANGED_TR | + CPUM_CHANGED_HIDDEN_SEL_REGS | + CPUM_CHANGED_GLOBAL_TLB_FLUSH); + + VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED); + + /* Transfer vCPU state from Genode to vbox format */ + if (!_state_to_vbox(pVM, pVCpu) || + !_hw_save_state(pVM, pVCpu)) { + + Genode::error("saving vCPU state failed"); + return VERR_INTERNAL_ERROR; + } + + /* + * Dispatch write to MSR_KVM_SYSTEM_TIME_NEW to emulate + * gimR0KvmUpdateSystemTime before entering the gimKvmWriteMsr function. + */ + if (_last_exit_triggered_by_wrmsr) { + enum { MSR_KVM_SYSTEM_TIME_NEW = 0x4b564d01 }; + if (pCtx->ecx == MSR_KVM_SYSTEM_TIME_NEW) + _update_gim_system_time(); + } + + /* XXX track guest mode changes - see VMM/VMMAll/IEMAllCImpl.cpp.h */ + PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER); + + int rc = _vm_exit_requires_instruction_emulation(pCtx); + + /* evaluated in VMM/include/EMHandleRCTmpl.h */ + return rc; +} + + +Sup::Vcpu_handler::Vcpu_handler(Env &env, size_t stack_size, + Affinity::Location location, + unsigned int cpu_id) +: + _ep(env, stack_size, + Genode::String<12>("EP-EMT-", cpu_id).string(), location), + _cpu_id(cpu_id) +{ + pthread_mutexattr_t _attr; + pthread_mutexattr_init(&_attr); + + pthread_cond_init(&_cond_wait, nullptr); + + pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutex_init(&_mutex, &_attr); +} diff --git a/repos/ports/src/virtualbox6/vcpu.h b/repos/ports/src/virtualbox6/vcpu.h new file mode 100644 index 0000000000..eab629efa5 --- /dev/null +++ b/repos/ports/src/virtualbox6/vcpu.h @@ -0,0 +1,234 @@ +/* + * \brief SUPLib vCPU utility + * \author Alexander Boettcher + * \author Norman Feske + * \author Christian Helmuth + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _VIRTUALBOX__VCPU_H_ +#define _VIRTUALBOX__VCPU_H_ + +/* Genode includes */ +#include +#include +#include +#include + +/* local includes */ +#include + +namespace Sup { + struct Vcpu_handler; + struct Vcpu_handler_vmx; + struct Vcpu_handler_svm; +} + + +class Sup::Vcpu_handler : Genode::Noncopyable +{ + protected: + + static Genode::Vm_connection::Exit_config const _exit_config; + + Genode::Entrypoint _ep; + Genode::Blockade _blockade_emt { }; + Genode::Semaphore _sem_handler; + Genode::Vcpu_state *_state { nullptr }; + + bool _last_exit_triggered_by_wrmsr = false; + + pthread_cond_t _cond_wait; + pthread_mutex_t _mutex; + + /* information used for NPT/EPT handling */ + Genode::addr_t _npt_ept_exit_addr { 0 }; + RTGCUINT _npt_ept_errorcode { 0 }; + bool _npt_ept_unmap { false }; + + /* state machine between EMT and EP thread of a vCPU */ + enum { RUNNING, PAUSED, IRQ_WIN, NPT_EPT } _vm_state { PAUSED }; + enum { PAUSE_EXIT, RUN } _next_state { RUN }; + + private: + + bool _irq_win = false; + + unsigned const _cpu_id; + PVM _vm { nullptr }; + PVMCPU _vcpu { nullptr }; + + unsigned int _last_inj_info = 0; + unsigned int _last_inj_error = 0; + + enum { + REQ_IRQWIN_EXIT = 0x1000U, + IRQ_INJ_VALID_MASK = 0x80000000UL, + IRQ_INJ_NONE = 0U, + + /* + * Intel® 64 and IA-32 Architectures Software Developer’s Manual + * Volume 3C, Chapter 24.4.2. + * May 2012 + */ + ACTIVITY_STATE_ACTIVE = 0U, + INTERRUPT_STATE_NONE = 0U, + INTERRUPT_STATE_BLOCKING_BY_STI = 1U << 0, + INTERRUPT_STATE_BLOCKING_BY_MOV_SS = 1U << 1, + }; + + timespec _add_timespec_ns(timespec a, ::uint64_t ns) const; + + void _update_gim_system_time(); + + protected: + + Genode::addr_t _vm_exits = 0; + Genode::addr_t _recall_skip = 0; + Genode::addr_t _recall_req = 0; + Genode::addr_t _recall_inv = 0; + Genode::addr_t _recall_drop = 0; + Genode::addr_t _irq_request = 0; + Genode::addr_t _irq_inject = 0; + Genode::addr_t _irq_drop = 0; + + struct { + unsigned intr_state; + unsigned ctrl[2]; + } _next_utcb; + + unsigned _ept_fault_addr_type; + + Genode::uint64_t * _pdpte_map(VM *pVM, RTGCPHYS cr3); + + void _switch_to_hw(PCPUMCTX pCtx); + + /* VM exit handlers */ + void _default_handler(); + bool _recall_handler(); + void _irq_window(); + void _npt_ept(); + + void _irq_window_pthread(); + + inline bool _vbox_to_state(VM *pVM, PVMCPU pVCpu); + inline bool _state_to_vbox(VM *pVM, PVMCPU pVCpu); + inline bool _check_to_request_irq_window(PVMCPU pVCpu); + inline bool _continue_hw_accelerated(); + + virtual bool _hw_load_state(VM *, PVMCPU) = 0; + virtual bool _hw_save_state(VM *, PVMCPU) = 0; + virtual int _vm_exit_requires_instruction_emulation(PCPUMCTX) = 0; + + virtual void _run_vm() = 0; + virtual void _pause_vm() = 0; + + public: + + enum Exit_condition + { + SVM_NPT = 0xfc, + SVM_INVALID = 0xfd, + + VCPU_STARTUP = 0xfe, + + RECALL = 0xff, + }; + + Vcpu_handler(Genode::Env &env, size_t stack_size, + Genode::Affinity::Location location, + unsigned int cpu_id); + + unsigned int cpu_id() const { return _cpu_id; } + + void recall(VM &vm); + + void halt(Genode::uint64_t const wait_ns); + + void wake_up(); + + int run_hw(VM &vm); +}; + + +class Sup::Vcpu_handler_vmx : public Vcpu_handler +{ + private: + + Genode::Vcpu_handler _handler; + + Genode::Vm_connection &_vm_connection; + Genode::Vm_connection::Vcpu _vcpu; + + /* VM exit handlers */ + void _vmx_default(); + void _vmx_startup(); + void _vmx_triple(); + void _vmx_irqwin(); + void _vmx_mov_crx(); + + template void _vmx_ept(); + __attribute__((noreturn)) void _vmx_invalid(); + + void _handle_exit(); + + void _run_vm() override { _vcpu.run(); } + void _pause_vm() override { _vcpu.pause(); } + + bool _hw_save_state(VM * pVM, PVMCPU pVCpu) override; + bool _hw_load_state(VM * pVM, PVMCPU pVCpu) override; + int _vm_exit_requires_instruction_emulation(PCPUMCTX pCtx) override; + + public: + + Vcpu_handler_vmx(Genode::Env &env, size_t stack_size, + Genode::Affinity::Location location, + unsigned int cpu_id, + Genode::Vm_connection &vm_connection, + Genode::Allocator &alloc); +}; + + +class Sup::Vcpu_handler_svm : public Vcpu_handler +{ + private: + + Genode::Vcpu_handler _handler; + + Genode::Vm_connection &_vm_connection; + Genode::Vm_connection::Vcpu _vcpu; + + /* VM exit handlers */ + void _svm_default(); + void _svm_vintr(); + void _svm_ioio(); + + template void _svm_npt(); + + void _svm_startup(); + + void _handle_exit(); + + void _run_vm() override { _vcpu.run(); } + void _pause_vm() override { _vcpu.pause(); } + + bool _hw_save_state(VM * pVM, PVMCPU pVCpu) override; + bool _hw_load_state(VM * pVM, PVMCPU pVCpu) override; + int _vm_exit_requires_instruction_emulation(PCPUMCTX) override; + + public: + + Vcpu_handler_svm(Genode::Env &env, size_t stack_size, + Genode::Affinity::Location location, + unsigned int cpu_id, + Genode::Vm_connection &vm_connection, + Genode::Allocator &alloc); +}; + +#endif /* _VIRTUALBOX__VCPU_H_ */ diff --git a/repos/ports/src/virtualbox6/vcpu_gim.cc b/repos/ports/src/virtualbox6/vcpu_gim.cc new file mode 100644 index 0000000000..69f37a05ee --- /dev/null +++ b/repos/ports/src/virtualbox6/vcpu_gim.cc @@ -0,0 +1,91 @@ +/* + * \brief Guest-interface manager support + * \author Norman Feske + * \author Christian Helmuth + * \date 2020-12-03 + * + * The GIM KVM device is a mechanism for providing a stable time source + * to the guest. The hypervisor provides a pair of TSC value, nanosecond + * value along with a conversion factor (TSC <-> nanosecond) to the guest. + * + * - The values are communicated on memory shared between guest and VMM + * + * - The location of the guest-physical address is picked by the guest + * and propagated to the hypervisor via the MSR MSR_KVM_SYSTEM_TIME_NEW + * (0x4b564d01). + * + * - The values on the shared page are supposed to be periodically updated. + * Apparently, VirtualBox updates the values only when the MSR is written. + */ + +/* + * Copyright (C) 2020-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* Genode includes */ +#include + +/* VirtualBox includes */ +#include /* needed for access to VM::gim.s */ +#include +#include +#include + +/* local includes */ +#include + +using namespace Genode; + + +/* + * This function must be called by the VCPU handler when detecting an MSR-write + * VM exit for MSR_KVM_SYSTEM_TIME_NEW before entering the VirtualBox code + * (which calls gimKvmWriteMsr). Since we are never executing any R0 code, the + * pKvmCpu value would remain undefined when arriving the the following + * assertion: + * + * Assert(pKvmCpu->uTsc); + * Assert(pKvmCpu->uVirtNanoTS); + * + * The implementation roughly corresponds to 'gimR0KvmUpdateSystemTime' + */ +void Sup::Vcpu_handler::_update_gim_system_time() +{ + using ::uint64_t; + + uint64_t uTsc = 0; + uint64_t uVirtNanoTS = 0; + + /* + * If we got preempted during the measurement, repeat. + */ + for (unsigned round = 1; ; ++round) { + + uTsc = TMCpuTickGetNoCheck(_vcpu) | UINT64_C(1); + uVirtNanoTS = TMVirtualGetNoCheck(_vm) | UINT64_C(1); + uint64_t const uTsc_again = TMCpuTickGetNoCheck(_vcpu) | UINT64_C(1); + + enum { MAX_MEASUREMENT_DURATION = 200U }; + + if (uTsc_again - uTsc < MAX_MEASUREMENT_DURATION) + break; + + if (round > 3 && round % 2 == 0) + warning("preemption during measurement, uTsc=", uTsc, + " uTsc_again=", uTsc_again, " uVirtNanoTS=", uVirtNanoTS); + } + + for (VMCPUID idCpu = 0; idCpu < _vm->cCpus; idCpu++) { + + PGIMKVMCPU pKvmCpu = &VMCC_GET_CPU(_vm, idCpu)->gim.s.u.KvmCpu; + + if (!pKvmCpu->uTsc && !pKvmCpu->uVirtNanoTS) { + pKvmCpu->uTsc = uTsc; + pKvmCpu->uVirtNanoTS = uVirtNanoTS; + } + } +} + diff --git a/repos/ports/src/virtualbox6/vmx.h b/repos/ports/src/virtualbox6/vmx.h new file mode 100644 index 0000000000..8a68b2f9a5 --- /dev/null +++ b/repos/ports/src/virtualbox6/vmx.h @@ -0,0 +1,111 @@ +/* + * \brief Genode specific VirtualBox SUPLib supplements + * \author Norman Feske + * \author Alexander Boettcher + * \author Christian Helmuth + * \date 2013-08-21 + */ + +/* + * Copyright (C) 2013-2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _VIRTUALBOX__VMX_H_ +#define _VIRTUALBOX__VMX_H_ + +#define GENODE_READ_SELREG_REQUIRED(REG) \ + (pCtx->REG.Sel != state.REG.value().sel) || \ + (pCtx->REG.ValidSel != state.REG.value().sel) || \ + (pCtx->REG.fFlags != CPUMSELREG_FLAGS_VALID) || \ + (pCtx->REG.u32Limit != state.REG.value().limit) || \ + (pCtx->REG.u64Base != state.REG.value().base) || \ + (pCtx->REG.Attr.u != sel_ar_conv_from_genode(state.REG.value().ar)) + +#define GENODE_READ_SELREG(REG) \ + pCtx->REG.Sel = state.REG.value().sel; \ + pCtx->REG.ValidSel = state.REG.value().sel; \ + pCtx->REG.fFlags = CPUMSELREG_FLAGS_VALID; \ + pCtx->REG.u32Limit = state.REG.value().limit; \ + pCtx->REG.u64Base = state.REG.value().base; \ + pCtx->REG.Attr.u = sel_ar_conv_from_genode(state.REG.value().ar) + +static inline bool vmx_save_state(Genode::Vcpu_state const &state, VM *pVM, PVMCPU pVCpu) +{ + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); + + GENODE_READ_SELREG(cs); + GENODE_READ_SELREG(ds); + GENODE_READ_SELREG(es); + GENODE_READ_SELREG(fs); + GENODE_READ_SELREG(gs); + GENODE_READ_SELREG(ss); + + if (GENODE_READ_SELREG_REQUIRED(ldtr)) { + GENODE_READ_SELREG(ldtr); + CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_LDTR); + } + if (GENODE_READ_SELREG_REQUIRED(tr)) { + GENODE_READ_SELREG(tr); + CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_TR); + } + + return true; +} + +#undef GENODE_READ_SELREG_REQUIRED +#undef GENODE_READ_SELREG + + +enum { VMCS_SEG_UNUSABLE = 0x10000 }; + +#define GENODE_WRITE_SELREG(REG) \ + Assert(pCtx->REG.fFlags & CPUMSELREG_FLAGS_VALID); \ + Assert(pCtx->REG.ValidSel == pCtx->REG.Sel); \ + state.REG.charge( Segment { .sel = pCtx->REG.Sel, \ + .ar = sel_ar_conv_to_genode(pCtx->REG.Attr.u ? : VMCS_SEG_UNUSABLE), \ + .limit = pCtx->REG.u32Limit, \ + .base = pCtx->REG.u64Base }); + +static inline bool vmx_load_state(Genode::Vcpu_state &state, VM const *pVM, PVMCPU pVCpu) +{ + PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu); + + typedef Genode::Vcpu_state::Segment Segment; + + GENODE_WRITE_SELREG(es); + GENODE_WRITE_SELREG(ds); + + GENODE_WRITE_SELREG(fs); + GENODE_WRITE_SELREG(gs); + + GENODE_WRITE_SELREG(cs); + GENODE_WRITE_SELREG(ss); + + /* ldtr */ + if (pCtx->ldtr.Sel == 0) { + state.ldtr.charge(Segment { .sel = 0, + .ar = sel_ar_conv_to_genode(0x82), + .limit = 0, + .base = 0 }); + } else { + state.ldtr.charge(Segment { .sel = pCtx->ldtr.Sel, + .ar = sel_ar_conv_to_genode(pCtx->ldtr.Attr.u), + .limit = pCtx->ldtr.u32Limit, + .base = pCtx->ldtr.u64Base }); + } + + /* tr */ + state.tr.charge(Segment { .sel = pCtx->tr.Sel, + .ar = sel_ar_conv_to_genode(pCtx->tr.Attr.u), + .limit = pCtx->tr.u32Limit, + .base = pCtx->tr.u64Base }); + + return true; +} + +#undef GENODE_WRITE_SELREG + +#endif /* _VIRTUALBOX__VMX_H_ */ diff --git a/repos/ports/src/virtualbox6/xpcom_stubs.cc b/repos/ports/src/virtualbox6/xpcom_stubs.cc new file mode 100644 index 0000000000..99b0f565ae --- /dev/null +++ b/repos/ports/src/virtualbox6/xpcom_stubs.cc @@ -0,0 +1,72 @@ +/* + * \brief Dummy implementations of symbols needed by XPCOM + * \author Norman Feske + * \date 2020-10-09 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +static bool const debug = true; + + +#include + +nsresult GetSpecialSystemDirectory(SystemDirectories, nsILocalFile**) STOP +void StartupSpecialSystemDirectory() TRACE() + + +#include + +nsresult nsFastLoadService::Create(nsISupports*, nsID const&, void**) STOP + + +#include + +nsresult nsMultiplexInputStreamConstructor(nsISupports*, nsID const&, void**) STOP + + +#include + +nsresult nsPersistentProperties::Create(nsISupports*, nsID const&, void**) STOP + + +#include + +nsresult nsProxyObjectManager::Create(nsISupports*, nsID const&, void**) STOP + + +#include + +nsresult nsScriptableInputStream::Create(nsISupports*, nsID const&, void**) STOP + + +#include + +nsresult nsStringInputStreamConstructor(nsISupports*, nsID const&, void**) STOP + + +#include + +nsIInterfaceInfoManager *XPTI_GetInterfaceInfoManager() TRACE(nullptr) + + +extern "C" { +#include <_freebsd.h> +#include + +void _MD_EarlyInit(void) TRACE() +void _PR_InitCPUs(void) TRACE() +void _pr_init_ipv6(void) TRACE() +void _PR_InitLayerCache(void) TRACE() +void _PR_InitLinker(void) TRACE() +void _PR_InitSegs(void) TRACE() +void _PR_InitStacks(void) TRACE() +} +