Port of VirtualBox 6.1.14

This commit is contained in:
Christian Helmuth 2021-02-23 12:22:40 +01:00
parent a47b374905
commit 20caac5f3b
70 changed files with 8159 additions and 0 deletions

View File

@ -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/<NL>/\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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 :

View File

@ -0,0 +1 @@
VBOX_CC_OPT += -DRT_STRICT -DVBOX_STRICT

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -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 =

View File

@ -0,0 +1 @@
c9f6708c2753758e31b59eb38dc1abcca821a913

View File

@ -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))' \
) > $@

View File

@ -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" > $@

View File

@ -0,0 +1 @@
2021-02-23 4a5f1c7e529bb1a2419568f60d5633671549fb62

View File

@ -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

View File

@ -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 {
<config prio_levels="4" verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="VM"/>}
append_if [expr $use_top] config {
<service name="TRACE"/>}
append config {
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>
<start name="timer" priority="0">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>}
append_if [expr $use_top] config {
<start name="top" priority="0">
<resource name="RAM" quantum="2M"/>
<config period_ms="15000"/>
</start>}
append config {
<start name="drivers" caps="1500" managing_system="yes" priority="-1">
<binary name="init"/>
<resource name="RAM" quantum="64M"/>
<provides> <service name="Platform"/> </provides>
<route>
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Capture"> <child name="nitpicker"/> </service>
<service name="Event"> <child name="nitpicker"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
<start name="rtc_drv" priority="-1">
<resource name="RAM" quantum="1M"/>
<provides>
<service name="Rtc"/>
</provides>
</start>}
append_if [expr $use_net] config {
<start name="nic_router" caps="120" priority="-1">
<resource name="RAM" quantum="5M"/>
<provides>
<service name="Nic"/>
<service name="Uplink"/>
</provides>
<config verbose_domain_state="yes">
<policy label_prefix="vbox" domain="downlink"/>
<policy label_prefix="nic_drv" domain="uplink"/>
<domain name="uplink">
<nat domain="downlink"
tcp-ports="16384"
udp-ports="16384"
icmp-ids="16384"/>
</domain>
<domain name="downlink" interface="10.0.3.1/24" verbose_packets="no">
<dhcp-server ip_first="10.0.3.100" ip_last="10.0.3.200">
<dns-server ip="8.8.8.8"/>
<dns-server ip="1.1.1.1"/>
</dhcp-server>
<tcp dst="0.0.0.0/0"> <permit-any domain="uplink"/> </tcp>
<udp dst="0.0.0.0/0"> <permit-any domain="uplink"/> </udp>
<icmp dst="0.0.0.0/0" domain="uplink"/>
</domain>
</config>
</start>
<start name="nic_drv" priority="-1">
<binary name="ipxe_nic_drv"/>
<resource name="RAM" quantum="8M"/>
<config mode="uplink_client"/>
<route>
<service name="Platform"> <child name="drivers"/> </service>
<service name="Uplink"> <child name="nic_router"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>}
append_if [expr $use_serial] config {
<start name="log_terminal" priority="-1">
<resource name="RAM" quantum="2M"/>
<provides>
<service name="Terminal"/>
</provides>
</start>}
append config {
<start name="report_rom" priority="-1">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config>
<policy label="pointer -> hover" report="nitpicker -> hover"/>
<policy label="pointer -> xray" report="nitpicker -> xray"/>
<policy label="clipboard -> focus" report="nitpicker -> focus"/>
</config>
</start>
<start name="nitpicker" priority="-1">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Gui"/> <service name="Capture"/> <service name="Event"/>
</provides>
<config focus="rom">
<capture/> <event/>
<report focus="yes" hover="yes"/>
<domain name="pointer" layer="1" content="client" label="no" origin="pointer"/>
<domain name="default" layer="2" content="client" label="no" hover="always"/>
<policy label_prefix="pointer" domain="pointer"/>
<default-policy domain="default"/>
</config>
<route>
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="pointer" priority="-1">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Report"/> </provides>
<config shapes="yes"/>
<route>
<service name="Gui"> <child name="nitpicker"/> </service>
<service name="ROM" label="hover"> <child name="report_rom"/> </service>
<service name="ROM" label="xray"> <child name="report_rom"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
<start name="clipboard" priority="-1">
<resource name="RAM" quantum="2M"/>
<provides>
<service name="ROM"/> <service name="Report"/>
</provides>
<config verbose="yes" match_labels="yes">
<default-policy domain="default"/>
</config>
<route>
<service name="ROM" label="focus"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="wm" caps="1000" priority="-1">
<resource name="RAM" quantum="32M"/>
<binary name="init"/>
<provides>
<service name="Gui"/> <service name="Report"/> <service name="ROM"/>
</provides>
<route>
<service name="ROM" label="config"> <parent label="wm.config"/> </service>
<service name="ROM" label_last="clipboard"> <child name="clipboard"/> </service>
<service name="Report" label_last="clipboard"> <child name="clipboard"/> </service>
<service name="Gui"> <child name="nitpicker"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="vbox1" priority="-2" caps="1800">
<binary name="virtualbox6"/>
<resource name="RAM" quantum="3000M"/>
<config vbox_file="virtualbox6.vbox" vm_name="TestVM">
<libc stdout="/dev/log" stderr="/dev/log" pipe="/pipe" rtc="/dev/rtc">
<pthread placement="single-cpu"/>
</libc>
<vfs>
<dir name="dev">
<log/> <rtc/> <null/> <zero/>
</dir>
<dir name="pipe"> <pipe/> </dir>}
append_if [expr $use_serial] config {
<dir name="dev"> <terminal/> </dir>}
append config {
<rom name="virtualbox6.vbox"/>
<rom name="test.iso"/>}
append_if [expr $use_overlay] config {
<dir name="ram"> <ram/> </dir>
<import>
<dir name="ram"> <rom name="overlay.vdi"/> </dir>
</import>}
append config {
</vfs>
<arg value="virtualbox"/>
<env key="VBOX_USER_HOME" value="/"/>
<env key="VBOX_LOG_DEST" value="file=/dev/log"/>
<env key="VBOX_LOG" value="-*.e.l.f"/>
<env key="VBOX_RELEASE_LOG_DEST" value="file=/dev/log"/>
<env key="VBOX_RELEASE_LOG" value="-*.e.l.f"/>
</config>
<route>
<service name="Nic"> <child name="nic_router"/> </service>
<service name="Gui"> <child name="wm"/> </service>
<service name="VM"> <parent diag="yes"/> </service>
<service name="Report" label="shape"> <child name="wm"/> </service>
<service name="ROM" label="clipboard"> <child name="wm"/> </service>
<service name="Report" label="clipboard"> <child name="wm"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
</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 {<config buffered="yes"/>}
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 label=\"wm -> 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

View File

@ -0,0 +1,117 @@
<?xml version="1.0"?>
<!--
** DO NOT EDIT THIS FILE.
** If you make changes to this file while any VirtualBox related application
** is running, your changes will be overwritten later, without taking effect.
** Use VBoxManage or the VirtualBox Manager GUI to make changes.
-->
<VirtualBox xmlns="http://www.innotek.de/VirtualBox-settings" version="1.18-genode">
<Machine uuid="{410f6221-6237-4833-b02c-a54000b7b190}" name="Tinycore" OSType="Linux26" snapshotFolder="Snapshots" lastStateChange="2014-10-30T13:26:17Z">
<MediaRegistry>
<HardDisks>
<!--HardDisk uuid="{3d9a9193-0fe7-4f8c-8e1b-065dbf514c82}" location="/ram/overlay.vdi" format="VDI" autoReset="true"/-->
</HardDisks>
<DVDImages>
<Image uuid="{81763434-9a51-49e8-9444-528a5a28c4bc}" location="test.iso"/>
</DVDImages>
<FloppyImages>
<!--Image uuid="{a804c9cb-ae6d-490a-92e9-8d4605911c22}" location="bootsector.img"/-->
</FloppyImages>
</MediaRegistry>
<ExtraData/>
<Hardware>
<CPU count="2" hotplug="false">
<HardwareVirtEx enabled="true"/>
<HardwareVirtExNestedPaging enabled="true"/>
<HardwareVirtExUX enabled="true"/>
<PAE enabled="true"/>
<LongMode enabled="true"/>
</CPU>
<Memory RAMSize="2048" PageFusion="false"/>
<HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
<HPET enabled="false"/>
<Chipset type="ICH9"/>
<Boot>
<Order position="1" device="Floppy"/>
<Order position="2" device="DVD"/>
<Order position="3" device="HardDisk"/>
<Order position="4" device="None"/>
</Boot>
<Display VRAMSize="20" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
<VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
<RemoteDisplay enabled="false" authType="Null"/>
<BIOS>
<ACPI enabled="true"/>
<IOAPIC enabled="true"/>
<Logo fadeIn="true" fadeOut="true" displayTime="0"/>
<BootMenu mode="MessageAndMenu"/>
<TimeOffset value="0"/>
<PXEDebug enabled="false"/>
</BIOS>
<USB>
<Controllers>
<Controller name="OHCI" type="OHCI"/>
</Controllers>
<DeviceFilters/>
</USB>
<Network>
<Adapter slot="0" enabled="false" MACAddress="0800271D7901" cable="true" speed="0" type="82540EM">
<HostInterface/>
<DisabledModes/>
</Adapter>
</Network>
<UART>
<Port slot="0" enabled="true" IOBase="0x3f8" IRQ="4" path="/dev/terminal" hostMode="RawFile"/>
<Port slot="1" enabled="false" IOBase="0x2f8" IRQ="3" hostMode="Disconnected"/>
</UART>
<LPT>
<Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
<Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
</LPT>
<AudioAdapter controller="AC97" driver="Pulse" enabled="false"/>
<RTC localOrUTC="UTC"/>
<SharedFolders/>
<Clipboard mode="Disabled"/>
<DragAndDrop mode="Disabled"/>
<IO>
<IoCache enabled="true" size="5"/>
<BandwidthGroups/>
</IO>
<HostPci>
<Devices/>
</HostPci>
<EmulatedUSB>
<CardReader enabled="false"/>
</EmulatedUSB>
<Guest memoryBalloonSize="0"/>
<GuestProperties/>
</Hardware>
<StorageControllers>
<!--
<StorageController name="IDE" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
<AttachedDevice passthrough="false" tempeject="true" type="DVD" port="1" device="0">
<Image uuid="{81763434-9a51-49e8-9444-528a5a28c4bc}"/>
</AttachedDevice>
<AttachedDevice type="HardDisk" port="0" device="0">
<Image uuid="{3d9a9193-0fe7-4f8c-8e1b-065dbf514c82}"/>
</AttachedDevice>
</StorageController>
-->
<StorageController name="SATA" type="AHCI" PortCount="2" useHostIOCache="true" Bootable="true">
<AttachedDevice passthrough="false" tempeject="true" type="DVD" port="1" device="0">
<Image uuid="{81763434-9a51-49e8-9444-528a5a28c4bc}"/>
</AttachedDevice>
<!--
<AttachedDevice type="HardDisk" port="0" device="0">
<Image uuid="{3d9a9193-0fe7-4f8c-8e1b-065dbf514c82}"/>
</AttachedDevice>
-->
</StorageController>
<StorageController name="Floppy" type="I82078" PortCount="1" useHostIOCache="true" Bootable="true">
<AttachedDevice type="Floppy" hotpluggable="false" port="0" device="0">
<!--Image uuid="{a804c9cb-ae6d-490a-92e9-8d4605911c22}"/-->
</AttachedDevice>
</StorageController>
</StorageControllers>
</Machine>
</VirtualBox>

View File

@ -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 <base/exception.h>
class Fatal : Genode::Exception { };
template <typename FN, typename... ERR_MSG>
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_ */

View File

@ -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 <VBoxDD.h>
#include <VBoxDD2.h>
#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;
}

View File

@ -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 <VBoxDD.h>
#include <KeyboardImpl.h>
#include <MouseImpl.h>
#include <VMMDev.h>
#include <ConsoleImpl.h>
#include <DisplayImpl.h>
#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;
}

View File

@ -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 <base/sleep.h>
#include <util/string.h>
/* local includes */
#include "stub_macros.h"
#include "util.h"
static bool const debug = true;
/* ApplianceImplExport.cpp */
#include "MachineImpl.h"
HRESULT Machine::exportTo(const ComPtr<IAppliance> &aAppliance,
const com::Utf8Str &aLocation,
ComPtr<IVirtualSystemDescription> &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<com::Utf8Str, std::allocator<com::Utf8Str> > const&,
std::vector<com::Utf8Str, std::allocator<com::Utf8Str> > const&) STOP
HRESULT USBProxyService::getDeviceCollection(std::vector<ComPtr<IHostUSBDevice>,
std::allocator<ComPtr<IHostUSBDevice> > >&) STOP
using USBDeviceSourceList =
std::__cxx11::list<settings::USBDeviceSource, std::allocator<settings::USBDeviceSource> >;
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<IAppliance> &) 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<ICloudProvider>&) STOP
HRESULT CloudProviderManager::getProviderByName (com::Utf8Str const&, ComPtr<ICloudProvider>&) STOP
HRESULT CloudProviderManager::getProviderByShortName(com::Utf8Str const&, ComPtr<ICloudProvider>&) STOP
HRESULT CloudProviderManager::getProviders(std::vector<ComPtr<ICloudProvider>,
std::allocator<ComPtr<ICloudProvider> > >&) 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<ComObjPtr<HostNetworkInterface>,
std::allocator<ComObjPtr<HostNetworkInterface> > >&) 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<ComObjPtr<HostVideoInputDevice>,
std::allocator<ComObjPtr<HostVideoInputDevice> > >;
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<char *>(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 <iprt/buildconfig.h>
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 <SharedFolderImpl.h>
HRESULT SharedFolder::init(Console*, com::Utf8Str const&, com::Utf8Str const&,
bool, bool, com::Utf8Str const&, bool) TRACE(E_FAIL)
/* ConsoleImplTeleporter.cpp */
#include <ConsoleImpl.h>
HRESULT Console::teleport(const com::Utf8Str &, ULONG, const com::Utf8Str &, ULONG, ComPtr<IProgress> &) STOP
HRESULT Console::i_teleporterTrg(PUVM, IMachine *, Utf8Str *, bool, Progress *, bool *) STOP
/* DBGFBp.cpp */
#include <DBGFInternal.h>
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 <VBox/vmm/pgm.h>
VMMR3DECL(int) PGMR3MappingsSize(PVM pVM, uint32_t *pcb)
{
*pcb = 0;
return VINF_SUCCESS;
}
/* PGMSavedState.cpp */
#include <PGMInternal.h>
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

View File

@ -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 <util/string.h>
/* VirtualBox includes */
#include <iprt/err.h>
#include <iprt/ldr.h>
#include <VBox/hgcmsvc.h>
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" */

View File

@ -0,0 +1,4 @@
#ifndef ____H_GENODEIMPL
#define ____H_GENODEIMPL
#endif // !____H_GENODEIMPL

View File

@ -0,0 +1,46 @@
#ifndef _AIO_H_
#define _AIO_H_
#include <signal.h>
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_ */

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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 <framebuffer_session/connection.h>
#include <gui_session/connection.h>
#undef Framebuffer
#include <os/texture_rgb888.h>
#include <nitpicker_gfx/texture_painter.h>
/* VirtualBox includes */
#include <Global.h>
#include <VirtualBoxBase.h>
#include <DisplayWrap.h>
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<IDisplay> _display;
ComPtr<IDisplaySourceBitmap> _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<Command::Geometry>(_view, rect);
_gui.execute();
}
Fb_Genode::Mode _initial_setup()
{
typedef Gui::Session::Command Command;
_view = _gui.create_view();
_adjust_buffer();
_gui.enqueue<Command::To_front>(_view, View_handle());
_gui.execute();
return _fb_mode;
}
public:
NS_DECL_ISUPPORTS
Genodefb(Genode::Env &env, Gui::Connection &gui, ComPtr<IDisplay> 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<Pixel_src> texture((Pixel_src *)pAddress, nullptr, area_vm);
Surface<Pixel_dst> 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<Pixel_src> texture((Pixel_src *)image, nullptr, area_vm);
Surface<Pixel_dst> 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; }
};

View File

@ -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 <base/log.h>
/*
* 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___ */

View File

@ -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.
*/

View File

@ -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 <sys/_types.h>
typedef __mbstate_t mbstate_t;
typedef unsigned int wint_t;
#endif /* _LIBC__WCHAR_H_ */

View File

@ -0,0 +1,5 @@
/*
* Override the libc's wctype.h header. See the comment in the wchar.h header.
*/
#include <wchar.h>

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,4 @@
#ifndef ___version_generated_h___
#define ___version_generated_h___
/* VBOX_VERSION_* set in lib/mk/virtualbox-common.inc */
#endif

View File

@ -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_ */

View File

@ -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 <scan_code.h>
struct Input_adapter
{
struct Mouse
{
ComPtr<IMouse> _imouse;
Mouse(ComPtr<IConsole> &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> _ikeyboard;
Keyboard(ComPtr<IConsole> &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> &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_ */

View File

@ -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 <signal.h>
#include <sys/times.h>
#include <unistd.h>
#include <aio.h>
#include <sched.h>
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h> /* memset */
#include <sys/mount.h> /* statfs */
#include <sys/statvfs.h> /* fstatvfs */
#include <fcntl.h> /* open */
/* local includes */
#include <stub_macros.h>
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;
}

View File

@ -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 <base/attached_rom_dataspace.h>
#include <base/registry.h>
#include <libc/component.h>
#include <libc/args.h>
/* Virtualbox includes */
#include <nsXPCOM.h>
#include <nsCOMPtr.h>
#include <iprt/initterm.h>
#include <iprt/err.h>
#include <VBox/com/listeners.h>
/* 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 <attempt.h>
#include <init.h>
#include <fb.h>
#include <input_adapter.h>
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, Event_handler &> 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<VirtualBox>::createObject'
* because 'FinalConstruction' uses a temporary 'ComObjPtr<VirtualBox>'
* (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>
{
VirtualBox _instance;
Virtualbox_instance()
{
_instance.AddRef();
attempt([&] () { return _instance.FinalConstruct(); },
"construction of VirtualBox object failed");
ComObjPtr<VirtualBox>::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>
{
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<IGraphicsAdapter> 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<IConsole>
{
Console_interface(Session_instance &session)
{
attempt([&] () { return session->COMGETTER(Console)(this->asOutParam()); },
"unable to request console for session");
}
} _iconsole { _session };
struct Display_interface : ComPtr<IDisplay>
{
Display_interface(Console_interface &iconsole)
{
attempt([&] () { return iconsole->COMGETTER(Display)(this->asOutParam()); },
"unable to request display from console interface");
}
} _idisplay { _iconsole };
Registry<Registered<Gui::Connection>> _gui_connections { };
Signal_handler<Main> _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::Connection>(_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 <IProgress> 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<Event_listener_impl> listener;
listener.createObject();
listener->init(new Event_listener(), *this);
ComPtr<IEventSource> ievent_source;
_iconsole->COMGETTER(EventSource)(ievent_source.asOutParam());
com::SafeArray<VBoxEventType_T> 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<IMouseCapabilityChangedEvent> 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<nsIServiceManager> 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)

View File

@ -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 <VBox/vmm/cpum.h> /* must be included before CPUMInternal.h */
#define VMCPU_INCL_CPUM_GST_CTX /* needed for cpum.GstCtx */
#include <CPUMInternal.h> /* enable access to cpum.s.* */
#include <HMInternal.h> /* enable access to hm.s.* */
#define RT_OS_WINDOWS /* needed for definition all nem.s members */
#include <NEMInternal.h> /* enable access to nem.s.* */
#undef RT_OS_WINDOWS
#include <PGMInternal.h> /* enable access to pgm.s.* */
#include <VBox/vmm/vmcc.h> /* must be included before PGMInline.h */
#include <PGMInline.h>
#include <VBox/vmm/nem.h>
#include <VBox/vmm/apic.h>
#include <VBox/vmm/em.h>
#include <VBox/err.h>
/* local includes */
#include <stub_macros.h>
#include <sup.h>
#include <vcpu.h>
#include <sup_gmm.h>
#include <sup_vm.h>
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<Vm *>(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

View File

@ -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.

View File

@ -0,0 +1 @@
serial.patch

View File

@ -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 <util/string.h>
/* VirtualBox includes */
#include <VBox/vmm/pdmapi.h>
#include <VBox/vmm/pdmdrv.h>
#include <VBox/vmm/pdmdev.h>
#include <VBox/vmm/pdmusb.h>
#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;
}

View File

@ -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 <scan_code_set_1.h> /* 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_ */

View File

@ -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 <base/log.h>
#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_ */

View File

@ -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 <base/env.h>
/* VirtualBox includes */
#include <IOMInternal.h> /* enable access to iom.s.* */
#include <NEMInternal.h> /* enable access to nem.s.* */
#include <PGMInternal.h> /* enable access to pgm.s.* */
#include <VMMInternal.h> /* enable access to vmm.s.* */
#define PDMPCIDEV_INCLUDE_PRIVATE /* needed for PDMPCIDEVINT_DECLARED */
#define VBOX_IN_VMM /* needed for definition of PDMTASKTYPE */
#include <PDMInternal.h>
#undef VBOX_IN_VMM
#include <SUPDrvIOC.h>
#include <VBox/err.h>
#include <VBox/vmm/vmm.h>
#include <VBox/vmm/gvmm.h>
#include <SUPLibInternal.h>
/* local includes */
#include <init.h>
#include <sup_drv.h>
#include <sup_vm.h>
#include <stub_macros.h>
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 <typename T, typename FN>
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 <typename T, typename FN>
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

View File

@ -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 <VBox/sup.h>
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_ */

View File

@ -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 <NEMInternal.h> /* enable access to nem.s.* */
/* local includes */
#include <sup_drv.h>
#include <vcpu.h>
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();
}

View File

@ -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 <sup.h>
#include <sup_gip.h>
#include <sup_gmm.h>
#include <vcpu.h>
/* Genode includes */
#include <base/env.h>
#include <base/attached_rom_dataspace.h>
#include <base/sleep.h>
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_ */

View File

@ -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 <iprt/mem.h>
#include <iprt/cdefs.h>
#include <iprt/param.h>
#include <iprt/uint128.h>
#include <VBox/sup.h>
/* Genode includes */
#include <base/entrypoint.h>
#include <base/signal.h>
#include <timer_session/connection.h>
#include <trace/timestamp.h>
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<Entrypoint> 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_ */

View File

@ -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 <VBox/vmm/gmm.h>
/* local includes */
#include <sup_gmm.h>
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)
{ }

View File

@ -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 <base/allocator_avl.h>
#include <base/attached_dataspace.h>
#include <rm_session/connection.h>
#include <vm_session/connection.h>
#include <region_map/client.h>
#include <libc/allocator.h>
/* local includes */
#include <sup.h>
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_ */

View File

@ -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 <iprt/err.h>
#include <iprt/semaphore.h>
#include <VBox/sup.h>
#include <SUPLibInternal.h>
/* local includes */
#include <stub_macros.h>
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<RTSEMEVENTMULTI>(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 */
}

View File

@ -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 <VBox/vmm/cpum.h> /* must be included before CPUMInternal.h */
#include <CPUMInternal.h> /* enable access to cpum.s.* */
#include <HMInternal.h> /* enable access to hm.s.* */
#include <NEMInternal.h> /* enable access to nem.s.* */
#include <iprt/mem.h>
/* local includes */
#include <sup_vm.h>
#include <vcpu.h>
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;
}

View File

@ -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 <iprt/assert.h>
#include <VBox/vmm/gvm.h>
/* local includes */
#include <sup.h>
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 <typename FN>
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_ */

View File

@ -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_ */

View File

@ -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 =

View File

@ -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 <iprt/assert.h>
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" */

View File

@ -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 <iprt/types.h>
#include <iprt/assert.h>
/**
* 64bit-aware cast of pointer to RTRCPTR (uint32_t)
*/
template <typename T>
RTRCPTR to_rtrcptr(T* ptr)
{
unsigned long long u64 = reinterpret_cast<unsigned long long>(ptr);
RTRCPTR rtrcptr = u64 & 0xFFFFFFFFULL;
AssertMsg((u64 == rtrcptr) || (u64 >> 32) == 0xFFFFFFFFULL,
("pointer transformation - %llx != %x", u64, rtrcptr));
return rtrcptr;
}
#endif /* _UTIL_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -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 <base/attached_dataspace.h>
#include <vm_session/connection.h>
#include <vm_session/handler.h>
#include <util/noncopyable.h>
/* local includes */
#include <sup.h>
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 Developers 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<Vcpu_handler_vmx> _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 <unsigned X> 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<Vcpu_handler_svm> _handler;
Genode::Vm_connection &_vm_connection;
Genode::Vm_connection::Vcpu _vcpu;
/* VM exit handlers */
void _svm_default();
void _svm_vintr();
void _svm_ioio();
template <unsigned X> 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_ */

View File

@ -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 <base/log.h>
/* VirtualBox includes */
#include <GIMInternal.h> /* needed for access to VM::gim.s */
#include <GIMKvmInternal.h>
#include <VBox/vmm/tm.h>
#include <VBox/vmm/vmcc.h>
/* local includes */
#include <vcpu.h>
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;
}
}
}

View File

@ -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_ */

View File

@ -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 <stub_macros.h>
static bool const debug = true;
#include <SpecialSystemDirectory.h>
nsresult GetSpecialSystemDirectory(SystemDirectories, nsILocalFile**) STOP
void StartupSpecialSystemDirectory() TRACE()
#include <nsFastLoadService.h>
nsresult nsFastLoadService::Create(nsISupports*, nsID const&, void**) STOP
#include <nsMultiplexInputStream.h>
nsresult nsMultiplexInputStreamConstructor(nsISupports*, nsID const&, void**) STOP
#include <nsPersistentProperties.h>
nsresult nsPersistentProperties::Create(nsISupports*, nsID const&, void**) STOP
#include <nsProxyEventPrivate.h>
nsresult nsProxyObjectManager::Create(nsISupports*, nsID const&, void**) STOP
#include <nsScriptableInputStream.h>
nsresult nsScriptableInputStream::Create(nsISupports*, nsID const&, void**) STOP
#include <nsStringStream.h>
nsresult nsStringInputStreamConstructor(nsISupports*, nsID const&, void**) STOP
#include <xptinfo.h>
nsIInterfaceInfoManager *XPTI_GetInterfaceInfoManager() TRACE(nullptr)
extern "C" {
#include <_freebsd.h>
#include <primpl.h>
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()
}