vmm: experimental virtualbox 5 support

The main feature for this version upgrade is the use of the instruction
emulator (IEM) to speed up execution and less often the slow recompiler.

issue #2059
This commit is contained in:
Alexander Boettcher 2016-08-15 12:27:54 +02:00 committed by Christian Helmuth
parent 4dbfbdb7c4
commit 57b90e8d75
70 changed files with 8766 additions and 5 deletions

View File

@ -0,0 +1,12 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
SRC_CC = sup.cc pgm.cc
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(call select_from_repositories,src/lib/pthread)
INC_DIR += $(VBOX_DIR)/VMM/include
INC_DIR += $(REP_DIR)/src/virtualbox5
vpath sup.cc $(REP_DIR)/src/virtualbox5/spec/nova/
vpath pgm.cc $(REP_DIR)/src/virtualbox5/spec/nova/

View File

@ -0,0 +1,10 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
LIBS += stdcxx
SRC_CC += $(addprefix VBoxAPIWrap/, $(notdir $(wildcard $(VIRTUALBOX_DIR)/VBoxAPIWrap/*.cpp)))
INC_DIR += $(REP_DIR)/src/virtualbox5/frontend
INC_DIR += $(VBOX_DIR)/Main/include
vpath %.cpp $(VIRTUALBOX_DIR)

View File

@ -0,0 +1,37 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
ifeq ($(shell which yasm),)
REQUIRES += installation_of_yasm
endif
SRC_O += VBoxPcBiosBin.o VBoxVgaBiosBin.o VBoxBiosLogoBin.o
VBox%Bin.o : VBox%Bin.rom
$(MSG_CONVERT)$@
$(VERBOSE)echo ".global g_ab$*Binary, g_cb$*Binary;" \
".data;" \
"g_cb$*Binary:; .long g_ab$*BinaryEnd - g_ab$*Binary;" \
".align 4096;" \
"g_ab$*Binary:; .incbin \"$<\";" \
"g_ab$*BinaryEnd:;" | \
$(AS) $(AS_OPT) -f -o $@ -
VBoxPcBiosBin.rom: Devices/PC/BIOS/VBoxBiosAlternative.asm
$(MSG_ASSEM)
$(VERBOSE)yasm -f bin -o $@ $<
VBoxVgaBiosBin.rom: Devices/Graphics/BIOS/VBoxVgaBiosAlternative.asm
$(MSG_ASSEM)
$(VERBOSE)yasm -f bin -o $@ $<
VBoxBiosLogoBin.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)

View File

@ -0,0 +1,104 @@
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,virtualbox5)/src/app/virtualbox
VIRTUALBOX_SDK_DIR = $(call select_from_ports,virtualbox5)/src/app/virtualbox_sdk
VBOX_DIR = $(VIRTUALBOX_DIR)/src/VBox
VBOX_CC_OPT += -DIN_RING3 -DVBOX -DVBOX_OSE \
-D_FILE_OFFSET_BITS=64 -DLOG_ENABLED
VBOX_CC_OPT += $(VBOX_MACH_CC_OPT_$(VBOX_MACH))
VBOX_CC_OPT += -DVBOX_WITH_64_BITS_GUESTS
VBOX_CC_OPT += -DVBOX_WITH_NEW_MSR_CODE
VBOX_CC_OPT += -DIN_SUP_R3 -DIN_VMM_R3
# we use the libc headers from FreeBSD
VBOX_CC_OPT += -DRT_OS_FREEBSD
VBOX_CC_OPT += -DVBOX_WITH_REM
VBOX_CC_OPT += -DVBOX_WITH_2ND_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 += -DRTLOG_REL_ENABLED -DRT_STRICT -DVBOX_STRICT
VBOX_CC_OPT += -DVBOX_WITH_USB -DVBOX_WITH_VUSB
# Enable Intel Network model E1000
VBOX_CC_OPT += -DVBOX_WITH_E1000
VBOX_CC_OPT += -DVBOX_WITH_AHCI
VIRTUALBOX_VERSION_MAJOR := $(shell cat $(VIRTUALBOX_DIR)/Config.kmk | grep "VBOX_VERSION_MAJOR = " | grep -v "'VBOX_VERSION_MAJOR" | sed "s/^.*= //")
VIRTUALBOX_VERSION_MINOR := $(shell cat $(VIRTUALBOX_DIR)/Config.kmk | grep "VBOX_VERSION_MINOR = " | grep -v "'VBOX_VERSION_MINOR" | sed "s/^.*= //")
VIRTUALBOX_VERSION_BUILD := $(shell cat $(VIRTUALBOX_DIR)/Config.kmk | grep "VBOX_VERSION_BUILD = " | grep -v "'VBOX_VERSION_BUILD" | sed "s/^.*= //")
ifeq ($(VBOX_MACH),x86_32)
VIRTUALBOX_PACKAGE_STRING = GenodeOS_32BIT_GENERIC
else
VIRTUALBOX_PACKAGE_STRING = GenodeOS_64BIT_GENERIC
endif
VBOX_CC_OPT += -DVBOX_VERSION_MAJOR=$(VIRTUALBOX_VERSION_MAJOR) \
-DVBOX_VERSION_MINOR=$(VIRTUALBOX_VERSION_MINOR) \
-DVBOX_VERSION_BUILD=$(VIRTUALBOX_VERSION_BUILD) \
-DVBOX_VERSION_STRING=\"$(VIRTUALBOX_VERSION_MAJOR).$(VIRTUALBOX_VERSION_MINOR).$(VIRTUALBOX_VERSION_BUILD)_OSE\" \
-DVBOX_PACKAGE_STRING=\"$(VIRTUALBOX_PACKAGE_STRING)\" \
-DVBOX_API_VERSION_STRING=\"$(VIRTUALBOX_VERSION_MAJOR)_$(VIRTUALBOX_VERSION_MINOR)\" \
-DIPRT_BLDCFG_VERSION_STRING=\"$(VIRTUALBOX_VERSION_MAJOR).$(VIRTUALBOX_VERSION_MINOR).$(VIRTUALBOX_VERSION_BUILD)_OSE\" \
-DIPRT_BLDCFG_TARGET=\"genode\" \
-DIPRT_BLDCFG_TARGET_ARCH=\"$(VBOX_MACH)\" \
-DVBOX_BUILD_SERVER_BUILD
VBOX_CC_OPT += -DVBOX_WITH_WDDM -DVBOX_WITH_WDDM_W8 -DVBOXWDDM_WITH_VBVA
VBOX_CC_OPT += -DVBOX_WITH_VDMA
VBOX_CC_OPT += -DVBOX_WITH_VMSVGA
VBOX_CC_OPT += -DVBOX_HDD_NO_DYNAMIC_BACKENDS
CC_WARN += -Wno-trigraphs
CC_OPT += $(VBOX_CC_OPT)
# 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
INC_DIR += $(REP_DIR)/src/virtualbox/include
INC_DIR += $(REP_DIR)/src/virtualbox/include/xpcom
INC_DIR += $(VIRTUALBOX_DIR)/include
INC_DIR += $(VIRTUALBOX_SDK_DIR)/sdk/bindings/xpcom/include
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,97 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
SRC_CC += Devices/PC/DevFwCommon.cpp
SRC_CC += Devices/PC/DevPcBios.cpp
SRC_CC += Devices/Bus/DevPCI.cpp
SRC_CC += Devices/PC/DevACPI.cpp
SRC_CC += Devices/PC/ACPI/VBoxAcpi.cpp
SRC_C += Devices/PC/DevPcArch.c
SRC_CC += Devices/Input/DevPS2.cpp
SRC_CC += Devices/Input/PS2K.cpp
SRC_CC += Devices/PC/DevPit-i8254.cpp
SRC_CC += Devices/PC/DevPIC.cpp
SRC_CC += Devices/PC/DevRTC.cpp
SRC_CC += Devices/PC/DevDMA.cpp
SRC_CC += Devices/PC/DevAPIC.cpp
SRC_CC += Devices/Graphics/DevVGA.cpp
SRC_CC += Devices/Graphics/DevVGA_VBVA.cpp
SRC_CC += Devices/Graphics/DevVGA_VDMA.cpp
SRC_CC += Devices/Graphics/DevVGA-SVGA.cpp
SRC_CC += Devices/Graphics/HGSMI/HGSMIHost.cpp
SRC_CC += Devices/Graphics/HGSMI/SHGSMIHost.cpp
SRC_CC += Devices/Storage/ATAPIPassthrough.cpp
SRC_CC += Devices/Storage/DevAHCI.cpp
SRC_CC += Devices/Storage/DevATA.cpp
SRC_CC += Devices/Storage/Debug.cpp
SRC_CC += Devices/Storage/DevFdc.c
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/VMMDev/VMMDev.cpp
SRC_CC += Devices/VMMDev/VMMDevHGCM.cpp
SRC_CC += Devices/Serial/DevSerial.cpp
SRC_CC += Devices/PC/DevIoApic.cpp
SRC_CC += Devices/Audio/AudioMixBuffer.cpp
SRC_CC += Devices/Audio/AudioMixer.cpp
SRC_CC += Devices/Audio/DevIchAc97.cpp
SRC_CC += Devices/Audio/DevIchHda.cpp
SRC_CC += Devices/Audio/DevIchHdaCodec.cpp
SRC_CC += Devices/Audio/DrvAudioCommon.cpp
SRC_CC += Devices/USB/DevOHCI.cpp
SRC_CC += Devices/USB/USBProxyDevice.cpp
SRC_CC += Devices/USB/VUSBDevice.cpp
SRC_CC += Devices/USB/VUSBReadAhead.cpp
SRC_CC += Devices/USB/VUSBSniffer.cpp
SRC_CC += Devices/USB/VUSBUrb.cpp
SRC_CC += Devices/Input/UsbMouse.cpp
SRC_CC += Devices/Input/UsbKbd.cpp
SRC_CC += Devices/build/VBoxDD.cpp
SRC_CC += devxhci.cc
vpath devxhci.cc $(REP_DIR)/src/virtualbox
SRC_CC += GuestHost/HGSMI/HGSMICommon.cpp
SRC_CC += GuestHost/HGSMI/HGSMIMemAlloc.cpp
INC_DIR += $(VBOX_DIR)/Devices/build
INC_DIR += $(VBOX_DIR)/Devices/Bus
CC_WARN += -Wno-unused-but-set-variable
# 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
iasl -tc -vs -p $@ $^
vboxssdt-standard.hex: vbox-standard.dsl
iasl -tc -vs -p $@ $^ && \
mv $@ $@.tmp && \
sed "s/AmlCode/AmlCodeSsdtStandard/g" <$@.tmp >$@ && \
rm $@.tmp
vboxssdt-cpuhotplug.hex: vbox-cpuhotplug.dsl
gcc -E -P -x c -o $@.pre $< && \
sed "s/<NL>/\n/g" <$@.pre >$@.pre1 && \
iasl -tc -vs -p $@ $@.pre1 && \
mv $@ $@.tmp && \
sed "s/AmlCode/AmlCodeSsdtCpuHotPlug/g" <$@.tmp >$@ && \
rm $@.tmp $@.pre $@.pre1
vpath %.dsl $(VBOX_DIR)/Devices/PC
vpath %.cc $(REP_DIR)/src/virtualbox

View File

@ -0,0 +1,19 @@
include $(REP_DIR)/lib/mk/virtualbox5-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 += Disassembler/DisasmCore.cpp
SRC_CC += Disassembler/DisasmTables.cpp
SRC_CC += Disassembler/DisasmReg.cpp
SRC_CC += Disassembler/DisasmTablesX64.cpp
SRC_CC += Disassembler/DisasmFormatYasm.cpp
SRC_CC += Disassembler/DisasmFormatBytes.cpp
INC_DIR += $(VBOX_DIR)/VMM/include
CC_OPT += -DVBOX_IN_VMM

View File

@ -0,0 +1,28 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
#
# Prevent inclusion of the Genode::Log definition after the vbox #define
# of 'Log'. Otherwise, the attempt to compile base/log.h will fail.
#
VBOX_CC_OPT += -include base/log.h
SRC_CC += Devices/Input/DrvKeyboardQueue.cpp
SRC_CC += Devices/Input/DrvMouseQueue.cpp
SRC_CC += Devices/USB/DrvVUSBRootHub.cpp
SRC_CC += Devices/Storage/DrvBlock.cpp
SRC_CC += Devices/Storage/DrvMediaISO.cpp
SRC_CC += Devices/Storage/DrvVD.cpp
SRC_CC += Devices/Storage/DrvRawImage.cpp
SRC_CC += Devices/PC/DrvACPI.cpp
SRC_CC += Devices/Serial/DrvChar.cpp
SRC_CC += Devices/Serial/DrvRawFile.cpp
SRC_CC += Devices/Serial/DrvHostSerial.cpp
SRC_CC += Devices/Audio/DrvAudio.cpp
#SRC_CC += audiodrv.cpp
SRC_CC += network.cpp
INC_DIR += $(VBOX_DIR)/Devices/Audio
#vpath audiodrv.cpp $(REP_DIR)/src/virtualbox
vpath network.cpp $(REP_DIR)/src/virtualbox

View File

@ -0,0 +1,8 @@
include $(REP_DIR)/lib/mk/virtualbox5-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)

View File

@ -0,0 +1,95 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
VBOX_CC_OPT += -DVBOX_WITH_GENERIC_SESSION_WATCHER
#
# Prevent inclusion of the Genode::Log definition after the vbox #define
# of 'Log'. Otherwise, the attemt to compile base/log.h will fail.
#
VBOX_CC_OPT += -include base/log.h
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/VirtualBoxBase.cpp
SRC_CC += Main/src-client/AdditionsFacilityImpl.cpp
SRC_CC += Main/src-client/BusAssignmentManager.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/GuestImpl.cpp
SRC_CC += Main/src-client/GuestCtrlImpl.cpp
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/UsbWebcamInterface.cpp
SRC_CC += Main/src-client/VBoxDriversRegister.cpp
SRC_CC += Main/src-client/VMMDevInterface.cpp
SRC_CC += Main/src-client/USBDeviceImpl.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/DHCPServerImpl.cpp
SRC_CC += Main/src-server/GuestOSTypeImpl.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/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/glue/AutoLock.cpp
SRC_CC += Main/glue/EventQueue.cpp
SRC_CC += Main/glue/string.cpp
SRC_CC += Main/glue/xpcom/helpers.cpp
INC_DIR += $(VBOX_DIR)/Main/xml
INC_DIR += $(VBOX_DIR)/Main/include
INC_DIR += $(REP_DIR)/src/virtualbox5/frontend
INC_DIR += $(VIRTUALBOX_DIR)/VBoxAPIWrap
# search path to 'scan_code_set_2.h'
INC_DIR += $(call select_from_repositories,src/drivers/input/spec/ps2)

View File

@ -0,0 +1,29 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
RECOMPILER_DIR = $(VIRTUALBOX_DIR)/src/recompiler
RECOMPILER_SRC_C = cpu-exec.c cutils.c exec.c host-utils.c tcg-runtime.c \
translate-all.c VBoxRecompiler.c \
tcg/tcg-dyngen.c tcg/tcg.c \
fpu/softfloat-native.c \
target-i386/helper.c target-i386/op_helper.c \
target-i386/translate.c
SRC_C = $(addprefix recompiler/,$(RECOMPILER_SRC_C))
INC_DIR += $(VBOX_DIR)/VMM/include
INC_DIR += $(RECOMPILER_DIR)/Sun/crt
INC_DIR += $(RECOMPILER_DIR)/Sun
INC_DIR += $(RECOMPILER_DIR)/target-i386
INC_DIR += $(RECOMPILER_DIR)/tcg
INC_DIR += $(RECOMPILER_DIR)/tcg/i386
INC_DIR += $(RECOMPILER_DIR)/fpu
INC_DIR += $(RECOMPILER_DIR)
CC_OPT += -DIN_REM_R3 \
-DREM_INCLUDE_CPU_H -DNEED_CPU_H -DLOG_USE_C99 -D_GNU_SOURCE
CC_WARN += -Wno-unused-but-set-variable]
vpath %.cpp $(VIRTUALBOX_DIR)/src
vpath %.c $(VIRTUALBOX_DIR)/src

View File

@ -0,0 +1,172 @@
include $(REP_DIR)/lib/mk/virtualbox5-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.8
INC_DIR += $(call select_from_ports,libiconv)/include/iconv
GENERIC_SRC_CC = $(notdir $(wildcard $(VBOX_DIR)/Runtime/generic/*.cpp))
FILTERED_OUT_SRC_CC = fs-stubs-generic.cpp \
http-curl.cpp \
semrw-lockless-generic.cpp \
tls-generic.cpp \
RTDirExists-generic.cpp \
RTFileExists-generic.cpp \
RTLogDefaultInit-generic.cpp \
RTLogWriteStdErr-generic.cpp \
RTLogWriteStdOut-generic.cpp \
RTMpGetDescription-generic-stub.cpp \
RTMpOnPair-generic.cpp \
RTSemEventWait-2-ex-generic.cpp \
RTSemEventWait-generic.cpp \
RTSemEventWaitNoResume-2-ex-generic.cpp \
RTSemEventMultiWait-2-ex-generic.cpp \
RTSemMutexRequest-generic.cpp \
RTSemMutexRequestDebug-generic.cpp \
RTTimeLocalExplode-generic.cpp
CC_WARN += -Wno-unused-variable
SRC_CC += Runtime/common/log/logrel.cpp \
Runtime/r3/init.cpp \
Runtime/common/misc/thread.cpp \
$(addprefix Runtime/generic/,$(filter-out $(FILTERED_OUT_SRC_CC), $(GENERIC_SRC_CC)))
SRC_CC += Runtime/common/alloc/memcache.cpp
SRC_CC += Runtime/common/alloc/heapoffset.cpp
SRC_CC += Runtime/common/checksum/alt-md5.cpp
SRC_CC += Runtime/common/checksum/alt-sha512.cpp
SRC_CC += Runtime/common/checksum/crc32.cpp
SRC_CC += Runtime/common/checksum/crc32c.cpp
SRC_CC += Runtime/common/checksum/ipv4.cpp
SRC_CC += Runtime/common/checksum/sha512str.cpp
SRC_CC += Runtime/common/err/errmsgxpcom.cpp
SRC_CC += Runtime/common/err/RTErrConvertFromErrno.cpp
SRC_CC += Runtime/common/log/log.cpp
SRC_CC += Runtime/common/log/log.cpp
SRC_CC += Runtime/common/log/logellipsis.cpp
SRC_CC += Runtime/common/log/logrelellipsis.cpp
SRC_CC += Runtime/common/log/logformat.cpp
SRC_CC += Runtime/common/misc/assert.cpp
SRC_CC += Runtime/common/misc/buildconfig.cpp
SRC_CC += Runtime/common/misc/cidr.cpp
SRC_CC += Runtime/common/misc/lockvalidator.cpp
SRC_CC += Runtime/common/misc/once.cpp
SRC_CC += Runtime/common/misc/req.cpp
SRC_CC += Runtime/common/misc/reqpool.cpp
SRC_CC += Runtime/common/misc/reqqueue.cpp
SRC_CC += Runtime/common/misc/sg.cpp
SRC_CC += Runtime/common/misc/term.cpp
SRC_CC += Runtime/common/misc/RTAssertMsg1Weak.cpp
SRC_CC += Runtime/common/misc/RTAssertMsg2AddWeak.cpp
SRC_CC += Runtime/common/misc/RTAssertMsg2AddWeakV.cpp
SRC_CC += Runtime/common/misc/RTAssertMsg2Weak.cpp
SRC_CC += Runtime/common/misc/RTAssertMsg2WeakV.cpp
SRC_CC += Runtime/common/misc/RTMemWipeThoroughly.cpp
SRC_CC += Runtime/common/net/netaddrstr2.cpp
SRC_CC += Runtime/common/path/comparepaths.cpp
SRC_CC += Runtime/common/path/RTPathAbsDup.cpp
SRC_CC += Runtime/common/path/RTPathAbsEx.cpp
SRC_CC += Runtime/common/path/RTPathAppendEx.cpp
SRC_CC += Runtime/common/path/RTPathCalcRelative.cpp
SRC_CC += Runtime/common/path/RTPathExt.cpp
SRC_CC += Runtime/common/path/RTPathFilename.cpp
SRC_CC += Runtime/common/path/RTPathHasPath.cpp
SRC_CC += Runtime/common/path/RTPathJoinA.cpp
SRC_CC += Runtime/common/path/RTPathJoinEx.cpp
SRC_CC += Runtime/common/path/RTPathParse.cpp
SRC_CC += Runtime/common/path/RTPathParseSimple.cpp
SRC_CC += Runtime/common/path/RTPathRealDup.cpp
SRC_CC += Runtime/common/path/RTPathStartsWithRoot.cpp
SRC_CC += Runtime/common/path/RTPathStripExt.cpp
SRC_CC += Runtime/common/path/RTPathStripFilename.cpp
SRC_CC += Runtime/common/path/RTPathStripTrailingSlash.cpp
SRC_CC += Runtime/common/path/rtPathVolumeSpecLen.cpp
SRC_CC += Runtime/common/path/rtPathRootSpecLen.cpp
SRC_CC += Runtime/common/rand/rand.cpp
SRC_CC += Runtime/common/rand/randadv.cpp
SRC_CC += Runtime/common/rand/randparkmiller.cpp
SRC_CC += Runtime/common/string/base64.cpp
SRC_CC += Runtime/common/string/RTStrCmp.cpp
SRC_CC += Runtime/common/string/RTStrCopy.cpp
SRC_CC += Runtime/common/string/RTStrCopyEx.cpp
SRC_CC += Runtime/common/string/RTStrCopyP.cpp
SRC_CC += Runtime/common/string/RTStrNCmp.cpp
SRC_CC += Runtime/common/string/RTStrNLen.cpp
SRC_CC += Runtime/common/string/RTStrNLenEx.cpp
SRC_CC += Runtime/common/string/RTStrPrintHexBytes.cpp
SRC_CC += Runtime/common/string/simplepattern.cpp
SRC_CC += Runtime/common/string/straprintf.cpp
SRC_CC += Runtime/common/string/strformat.cpp
SRC_CC += Runtime/common/string/strformatnum.cpp
SRC_CC += Runtime/common/string/strformatrt.cpp
SRC_CC += Runtime/common/string/strformattype.cpp
SRC_CC += Runtime/common/string/stringalloc.cpp
SRC_CC += Runtime/common/string/strprintf.cpp
SRC_CC += Runtime/common/string/strspace.cpp
SRC_CC += Runtime/common/string/strstrip.cpp
SRC_CC += Runtime/common/string/strtonum.cpp
SRC_CC += Runtime/common/string/unidata-lower.cpp
SRC_CC += Runtime/common/string/unidata-upper.cpp
SRC_CC += Runtime/common/string/utf-8.cpp
SRC_CC += Runtime/common/string/utf-8-case.cpp
SRC_CC += Runtime/common/string/utf-16.cpp
SRC_CC += Runtime/common/string/utf-16-case.cpp
SRC_CC += Runtime/common/table/avlohcphys.cpp
SRC_CC += Runtime/common/table/avlpv.cpp
SRC_CC += Runtime/common/table/avlroioport.cpp
SRC_CC += Runtime/common/table/avlrogcphys.cpp
SRC_CC += Runtime/common/table/avlul.cpp
SRC_CC += Runtime/common/table/avlu32.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/zip/zip.cpp
SRC_CC += Runtime/r3/alloc.cpp
SRC_CC += Runtime/r3/dir.cpp
SRC_CC += Runtime/r3/fileio.cpp
SRC_CC += Runtime/r3/fs.cpp
SRC_CC += Runtime/r3/path.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/fileio-posix.cpp
SRC_CC += Runtime/r3/posix/fileio2-posix.cpp
SRC_CC += Runtime/r3/posix/fs-posix.cpp
SRC_CC += Runtime/r3/posix/fs2-posix.cpp
SRC_CC += Runtime/r3/posix/fs3-posix.cpp
SRC_CC += Runtime/r3/posix/path-posix.cpp
SRC_CC += Runtime/r3/posix/path2-posix.cpp
SRC_CC += Runtime/r3/posix/pipe-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/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/r3/process.cpp
SRC_CC += Runtime/r3/stream.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_CC += Runtime/common/err/errmsg.cpp
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 $^ > $@

View File

@ -0,0 +1,17 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
SRC_CC += Storage/VCICache.cpp
SRC_CC += Storage/VD.cpp
SRC_CC += Storage/VMDK.cpp
SRC_CC += Storage/DMG.cpp
SRC_CC += Storage/ISCSI.cpp
SRC_CC += Storage/Parallels.cpp
SRC_CC += Storage/QCOW.cpp
SRC_CC += Storage/QED.cpp
SRC_CC += Storage/RAW.cpp
SRC_CC += Storage/VD.cpp
SRC_CC += Storage/VDI.cpp
SRC_CC += Storage/VDIfVfs.cpp
SRC_CC += Storage/VHD.cpp
SRC_CC += Storage/VHDX.cpp
SRC_CC += Storage/VMDK.cpp

View File

@ -0,0 +1,100 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
#
# Prevent inclusion of the Genode::Log definition after the vbox #define
# of 'Log'. Otherwise, the attempt to compile base/log.h will fail.
#
VBOX_CC_OPT += -include base/log.h
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/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/VMMAll/PDMAll.cpp
SRC_CC += VMM/VMMAll/PDMAllQueue.cpp
SRC_CC += VMM/VMMAll/PDMAllCritSect.cpp
SRC_CC += VMM/VMMAll/PDMAllCritSectRw.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/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/TRPM.cpp
SRC_CC += VMM/VMMAll/SELMAll.cpp
SRC_CC += VMM/VMMAll/REMAll.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/VMMR3/GMM.cpp
SRC_CC += VMM/VMMR3/PGM.cpp
SRC_CC += VMM/VMMR3/PGMHandler.cpp
SRC_CC += VMM/VMMR3/PGMPhys.cpp
SRC_CC += VMM/VMMR3/PGMPool.cpp
SRC_CC += VMM/VMMAll/PGMAll.cpp
SRC_CC += VMM/VMMAll/PGMAllHandler.cpp
SRC_CC += VMM/VMMAll/PGMAllPhys.cpp
SRC_CC += VMM/VMMAll/PGMAllPool.cpp
SRC_CC += VMM/VMMR3/IOM.cpp
SRC_CC += VMM/VMMAll/IOMAll.cpp
SRC_CC += VMM/VMMAll/IOMAllMMIO.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
CC_WARN += -Wno-unused-but-set-variable

View File

@ -0,0 +1,23 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
ZLIB_DIR = $(VIRTUALBOX_DIR)/src/libs/zlib-1.2.8
LIBXML_DIR = $(VIRTUALBOX_DIR)/src/libs/libxml2-2.9.2
INC_DIR += $(ZLIB_DIR)
INC_DIR += $(LIBXML_DIR)/include
INC_DIR += $(call select_from_ports,libiconv)/include/iconv
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)

View File

@ -0,0 +1,7 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
ZLIB_DIR = $(VIRTUALBOX_DIR)/src/libs/zlib-1.2.8
INC_DIR += $(ZLIB_DIR)
SRC_C = $(notdir $(wildcard $(ZLIB_DIR)/*.c))
vpath % $(ZLIB_DIR)

View File

@ -0,0 +1 @@
14b453967da93f0915e476d45b80a8a400c37eb4

View File

@ -0,0 +1,158 @@
LICENSE := GPLv2
VERSION := 5.0.26
DOWNLOADS := virtualbox.archive virtualbox_sdk.archive
VIRTUALBOX_TBZ2 := VirtualBox-$(VERSION).tar.bz2
VIRTUALBOX_SDK_ZIP := VirtualBoxSDK-$(VERSION)-108824.zip
URL(virtualbox) := http://download.virtualbox.org/virtualbox/$(VERSION)/$(VIRTUALBOX_TBZ2)
DIR(virtualbox) := src/app/virtualbox
SHA(virtualbox) := 5e58c952f010b679a80ba3ce7ccb2641895f515f
URL(virtualbox_sdk) := http://download.virtualbox.org/virtualbox/$(VERSION)/$(VIRTUALBOX_SDK_ZIP)
DIR(virtualbox_sdk) := src/app/virtualbox_sdk
SHA(virtualbox_sdk) := 8c03425d13095a951725d763a8a3a6f51a64ed67
PATCHES_DIR := src/virtualbox5/patches
PATCHES_DIR_VBOX4 := src/virtualbox/patches
PATCHES := $(addprefix $(PATCHES_DIR)/, $(shell cat $(REP_DIR)/$(PATCHES_DIR)/series))
PATCHES += $(addprefix $(PATCHES_DIR_VBOX4)/, $(shell cat $(REP_DIR)/$(PATCHES_DIR_VBOX4)/series_common))
PATCH_OPT := -p1
$(call check_tool,xsltproc)
$(call check_tool,yasm)
$(call check_tool,iasl)
VBOX_MAIN_GLUE := AutoLock EventQueue string xpcom/helpers
VBOX_MAIN_ALL := AuthLibrary AutoCaller DisplayResampleImage DisplayUtils EventImpl Global HashedPw
VBOX_MAIN_ALL += PCIDeviceAttachmentImpl ProgressImpl SharedFolderImpl SecretKeyStore
VBOX_MAIN_ALL += VirtualBoxBase
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
VBOX_MAIN_SRV := AudioAdapterImpl ClientToken DHCPServerImpl Matching
VBOX_MAIN_SRV += MediumAttachmentImpl NATEngineImpl NATNetworkImpl SerialPortImpl
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
VBOX_MAIN_SRV += USBControllerImpl USBDeviceFilterImpl USBDeviceFiltersImpl
VBOX_MAIN_INC := AdditionsFacilityImpl AudioAdapterImpl AuthLibrary
VBOX_MAIN_INC += AutoCaller AutostartDb AutoStateDep BandwidthControlImpl
VBOX_MAIN_INC += BandwidthGroupImpl BIOSSettingsImpl BusAssignmentManager Nvram
VBOX_MAIN_INC += ClientToken ConsoleImpl DHCPServerImpl DisplayImpl HostImpl
VBOX_MAIN_INC += DisplayUtils DrvAudioVRDE EventImpl ExtPackManagerImpl Global
VBOX_MAIN_INC += GuestCtrlImplPrivate GuestDirectoryImpl Logging
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
VBOX_MAIN_INC += ParallelPortImpl PCIDeviceAttachmentImpl Performance
VBOX_MAIN_INC += ProgressImpl ProgressProxyImpl 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_SRC_VBOX := VMM Devices Runtime GuestHost/HGSMI Storage Disassembler
VBOX_SRC_VBOX += HostServices/SharedFolders Main/xml/Settings.cpp
VBOX_SRC_VBOX += HostServices/SharedClipboard
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/apiwrap-server.xsl
VBOX_SRC_VBOX += Main/idl/typemap-shared.inc.xsl
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 VMMDev2.h vusb.h dbg.h version.h HGSMI
VBOX_INC += VBoxVideo.h Hardware bioslogo.h scsi.h shflsvc.h VBoxGuest2.h vd.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 += VBoxVideoHost3D.h VBoxVideo3D.h settings.h VBoxAuth.h
VBOX_INC += usb.h usbfilter.h vrdpusb.h
VBOX_INC += RemoteDesktop ExtPack/ExtPack.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
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 += src/libs/zlib-1.2.8 src/libs/liblzf-3.4 src/libs/libxml2-2.9.2
VBOX_CONTENT += src/recompiler include/VBox/vmm include/iprt Config.kmk
TAR_OPT(virtualbox) := \
--strip-components 1 \
$(addprefix $(VIRTUALBOX_TBZ2:.tar.bz2=)/,$(VBOX_CONTENT))
UNZIP_OPT(virtualbox_sdk) := $(VIRTUALBOX_SDK_ZIP) sdk/bindings/xpcom/include/VirtualBox_XPCOM.h \#
default : additional_steps
additional_steps : $(DOWNLOADS)
@xsltproc --stringparam mode declare \
-o src/app/virtualbox/src/VBox/Main/xml/SchemaDefs.h \
src/app/virtualbox/src/VBox/Main/xml/SchemaDefs.xsl \
src/app/virtualbox/src/VBox/Main/xml/VirtualBox-settings.xsd
xsltproc -o VirtualBox_stripped.xidl \
src/app/virtualbox/src/VBox/Main/idl/docstrip.xsl \
src/app/virtualbox/src/VBox/Main/idl/VirtualBox.xidl
xsltproc --stringparam KBUILD_HOST genode \
--stringparam generating "headers" -o VBoxAPIWrap/apiwrappers-headers \
src/app/virtualbox/src/VBox/Main/idl/apiwrap-server.xsl \
VirtualBox_stripped.xidl
xsltproc --stringparam KBUILD_HOST genode \
--stringparam generating "sources" --param reminder 0 \
-o VBoxAPIWrap/apiwrappers-sources-even \
src/app/virtualbox/src/VBox/Main/idl/apiwrap-server.xsl \
VirtualBox_stripped.xidl
xsltproc --stringparam KBUILD_HOST genode \
--stringparam generating "sources" --param reminder 1 \
-o VBoxAPIWrap/apiwrappers-sources-odd \
src/app/virtualbox/src/VBox/Main/idl/apiwrap-server.xsl \
VirtualBox_stripped.xidl
mkdir -p src/app/virtualbox/VBoxAPIWrap
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++))" "src/app/virtualbox/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++))" "src/app/virtualbox/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++))" "src/app/virtualbox/VBoxAPIWrap/$$f"; \
done && \
rm "VBoxAPIWrap/xx$$((i))"

View File

@ -4,6 +4,9 @@
set flavor "win7"
set use_vbox4 1
set use_vbox5 0
# Write overlay only into ram
set use_ram_fs 1
# However read initial overlay from disk

View File

@ -69,6 +69,10 @@ if {(![have_spec nova] && ![have_spec hw_x86_64_muen])} {
}
set flavor "win7"
set use_vbox4 1
set use_vbox5 0
set vdi_image "${flavor}.vdi"
# Write overlay back to harddisk if set to 0
set use_ram_fs 0

View File

@ -0,0 +1,21 @@
#
# Windows 7 in VirtualBox 5
#
assert_spec nova
assert_spec 64bit
set flavor "win7"
set use_vbox4 0
set use_vbox5 5
# Write overlay only into ram
set use_ram_fs 1
# However read initial overlay from disk
set use_overlay_from_disk 1
set use_usb 1
set use_ps2 [have_spec ps2]
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -6,6 +6,9 @@ assert_spec 64bit
set flavor "win8"
set use_vbox4 1
set use_vbox5 0
# Write overlay back to harddisk if set to 0
set use_ram_fs 0
set use_overlay_from_disk 0

View File

@ -6,6 +6,9 @@ assert_spec 64bit
set flavor "win81_64"
set use_vbox4 1
set use_vbox5 0
# Write overlay back to harddisk if set to 0
set use_ram_fs 0
set use_overlay_from_disk 0

View File

@ -148,8 +148,13 @@ append config_of_app {
</provides>
</start>
<start name="vbox" priority="-2">
<binary name="virtualbox" />
<start name="vbox" priority="-2">}
append_if [expr $use_vbox4] config_of_app {
<binary name="virtualbox" />}
append_if [expr $use_vbox5] config_of_app {
<binary name="virtualbox5" />}
append config_of_app {
<resource name="RAM" quantum="1280M"/>}
append config_of_app "
<config ld_verbose=\"yes\" vbox_file=\"${vbox_file}\" vm_name=\"${flavor}\" xhci=\"yes\">"

View File

@ -9,7 +9,7 @@ if {[have_include "power_on/qemu"]} {
}
append build_components {
core init virtualbox
core init
server/part_blk
server/rump_fs
server/fs_rom
@ -18,6 +18,8 @@ append build_components {
drivers/timer
}
lappend_if [expr $use_vbox4] build_components virtualbox
lappend_if [expr $use_vbox5] build_components virtualbox5
lappend_if [expr $use_ps2] build_components drivers/input
lappend_if [expr $use_usb] build_components drivers/usb
lappend_if [expr $use_usb] build_components app/usb_report_filter
@ -270,9 +272,11 @@ append boot_modules {
libc_pipe.lib.so libc_terminal.lib.so
libiconv.lib.so stdcxx.lib.so
rump.lib.so rump_fs.lib.so rump_fs
virtualbox qemu-usb.lib.so
qemu-usb.lib.so
}
lappend_if [expr $use_vbox4] boot_modules virtualbox
lappend_if [expr $use_vbox5] boot_modules virtualbox5
lappend_if [expr $use_ram_fs || $use_usb] boot_modules ram_fs
lappend_if [expr $use_ram_fs && !$use_overlay_from_disk] boot_modules ${overlay_image}

View File

@ -196,7 +196,7 @@ struct Timer_queue : public Qemu::Timer_queue
** TMTimer callback **
**********************/
static void tm_timer_cb(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
static DECLCALLBACK(void) tm_timer_cb(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
{
PXHCI pThis = PDMINS_2_DATA(pDevIns, PXHCI);
Timer_queue *q = pThis->timer_queue;

View File

@ -26,6 +26,7 @@
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DRV_TUN
#include <base/log.h>
#include <VBox/log.h>
#include <VBox/vmm/pdmdrv.h>
#include <VBox/vmm/pdmnetifs.h>

View File

@ -0,0 +1,169 @@
/*
* \brief Dummy implementations of symbols needed by VirtualBox
* \author Norman Feske
* \date 2013-08-22
*/
/*
* Copyright (C) 2013-2014 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <string.h> /* libc memcpy */
#include "VMMInternal.h"
#include "EMInternal.h"
#include "PDMInternal.h"
#include <iprt/err.h>
#include <iprt/mem.h>
#include <VBox/vmm/cpum.h>
#include <VBox/vmm/mm.h>
#include <VBox/vmm/dbgf.h>
#include <VBox/vmm/ftm.h>
#include <VBox/vmm/selm.h>
#include <VBox/vmm/hm.h>
#include <VBox/vmm/iom.h>
#include "util.h"
static const bool trace = false;
#define TRACE(retval) \
{ \
if (trace) \
Genode::log(__func__, " called, return dummy, eip=", \
__builtin_return_address(0)); \
return retval; \
}
RT_C_DECLS_BEGIN
RTDECL(int) RTMemProtect(void *pv, size_t cb, unsigned fProtect)
{
if (!trace)
return VINF_SUCCESS;
char type[4];
if (fProtect & RTMEM_PROT_READ)
type[0] = 'r';
else
type[0] = '-';
if (fProtect & RTMEM_PROT_WRITE)
type[1] = 'w';
else
type[1] = '-';
if (fProtect & RTMEM_PROT_EXEC)
type[2] = 'x';
else
type[2] = '-';
type[3] = 0;
Genode::warning(__func__, " called - not implemented - ", pv, "+",
Genode::Hex(cb), " protect ", Genode::Hex(fProtect), " - "
"'", (char const *)type, "'");
return VINF_SUCCESS;
}
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");
RTR0PTR MMHyperR3ToR0(PVM pVM, RTR3PTR R3Ptr) { return (RTR0PTR)R3Ptr; }
RTRCPTR MMHyperR3ToRC(PVM pVM, RTR3PTR R3Ptr) { return to_rtrcptr(R3Ptr); }
RTR0PTR MMHyperCCToR0(PVM pVM, void *pv) { return (RTR0PTR)pv; }
RTRCPTR MMHyperCCToRC(PVM pVM, void *pv) { return to_rtrcptr(pv); }
RTR3PTR MMHyperR0ToR3(PVM pVM, RTR0PTR R0Ptr) { return (RTR3PTR*)(R0Ptr | 0UL); }
RTR3PTR MMHyperRCToR3(PVM pVM, RTRCPTR RCPtr)
{
static_assert(sizeof(RCPtr) <= sizeof(RTR3PTR), "ptr transformation bug");
return reinterpret_cast<RTR3PTR>(0UL | RCPtr);
}
/* debugger */
int DBGFR3AsSymbolByAddr(PUVM, RTDBGAS, PCDBGFADDRESS, uint32_t, PRTGCINTPTR,
PRTDBGSYMBOL, PRTDBGMOD) TRACE(VERR_INVALID_HANDLE)
/* called by 'VMMR3InitRC', but we don't use GC */
void CPUMPushHyper(PVMCPU, uint32_t) TRACE()
int PGMR3FinalizeMappings(PVM) TRACE(VINF_SUCCESS)
int pgmR3InitSavedState(PVM pVM, uint64_t cbRam) TRACE(VINF_SUCCESS)
int vmmR3SwitcherInit(PVM pVM) TRACE(VINF_SUCCESS)
void vmmR3SwitcherRelocate(PVM, RTGCINTPTR) TRACE()
int VMMR3DisableSwitcher(PVM) TRACE(VINF_SUCCESS)
int emR3InitDbg(PVM pVM) TRACE(VINF_SUCCESS)
int FTMR3Init(PVM) TRACE(VINF_SUCCESS)
int FTMR3SetCheckpoint(PVM, FTMCHECKPOINTTYPE) TRACE(-1)
int FTMSetCheckpoint(PVM, FTMCHECKPOINTTYPE) TRACE(VINF_SUCCESS)
int FTMR3Term(PVM) TRACE(VINF_SUCCESS)
int GIMR3Init(PVM) TRACE(VINF_SUCCESS)
void GIMR3Reset(PVM) TRACE()
bool GIMIsEnabled(PVM) TRACE(false)
bool GIMIsParavirtTscEnabled(PVM) TRACE(false)
int GIMR3InitCompleted(PVM pVM)
{
/* from original GIMR3InitCompleted code */
if (!TMR3CpuTickIsFixedRateMonotonic(pVM, true /* fWithParavirtEnabled */))
Genode::warning("GIM: Warning!!! Host TSC is unstable. The guest may ",
"behave unpredictably with a paravirtualized clock.");
TRACE(VINF_SUCCESS)
}
void HMR3Relocate(PVM) TRACE()
void HMR3Reset(PVM pVM) TRACE()
int SELMR3Init(PVM) TRACE(VINF_SUCCESS)
int SELMR3Term(PVM) TRACE(VINF_SUCCESS)
int SELMR3InitFinalize(PVM) TRACE(VINF_SUCCESS)
void SELMR3Relocate(PVM) TRACE()
void SELMR3Reset(PVM) TRACE()
void SELMR3DisableMonitoring(PVM) TRACE()
int SUPR3SetVMForFastIOCtl(PVMR0) TRACE(VINF_SUCCESS)
_AVLOU32NodeCore* RTAvloU32RemoveBestFit(PAVLOU32TREE, AVLOU32KEY, bool) TRACE(VINF_SUCCESS)
int RTAvlrFileOffsetDestroy(PAVLRFOFFTREE, PAVLRFOFFCALLBACK, void*) TRACE(VINF_SUCCESS)
/* 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()
char *pdmR3FileR3(const char * file, bool)
{
char * pv = reinterpret_cast<char *>(RTMemTmpAllocZ(1));
if (trace)
Genode::log(__func__, ": file ", file, " ", (void *)pv, " ", __builtin_return_address(0));
TRACE(pv)
}
void RTAssertMsg2Add(const char *pszFormat, ...)
{
Genode::error(__func__, "not implemented");
Genode::Lock lock(Genode::Lock::LOCKED);
lock.lock();
}
RT_C_DECLS_END

View File

@ -0,0 +1,14 @@
#ifndef ____H_CLIENTWATCHER
#define ____H_CLIENTWATCHER
class VirtualBox::ClientWatcher
{
public:
ClientWatcher(VirtualBox* const) { }
bool isReady() { return true; }
void update() { }
void addProcess(RTPROCESS pid);
};
#endif /* !____H_CLIENTWATCHER */

View File

@ -0,0 +1,10 @@
#ifndef ____H_GENODEIMPL
#define ____H_GENODEIMPL
/* GuestControlSvc.h */
typedef struct { } VBOXGUESTCTRLHOSTCBCTX, *PVBOXGUESTCTRLHOSTCBCTX;
typedef struct { } VBOXGUESTCTRLHOSTCALLBACK, *PVBOXGUESTCTRLHOSTCALLBACK;
enum GUEST_FILE_SEEKTYPE { };
#endif // !____H_GENODEIMPL

View File

@ -0,0 +1,51 @@
#include "EventImpl.h"
void fireStateChangedEvent(IEventSource* aSource, MachineState_T a_state);
void fireRuntimeErrorEvent(IEventSource* aSource, BOOL a_fatal, CBSTR a_id,
CBSTR a_message);
#define fireAdditionsStateChangedEvent(a)
#define fireBandwidthGroupChangedEvent(a, b)
#define fireClipboardModeChangedEvent(a, b)
#define fireCPUChangedEvent(a, b, c)
#define fireCPUExecutionCapChangedEvent(a, b)
#define fireDnDModeChangedEvent(a, b)
#define fireExtraDataChangedEvent(a, b, c, d)
#define fireGuestUserStateChangedEvent(a, b, c, d, e)
#define fireGuestMonitorChangedEvent(a, b, c, d, e, f, g)
#define fireHostNameResolutionConfigurationChangeEvent(a)
#define fireHostPCIDevicePlugEvent(a, b, c, d, e, f)
#define fireKeyboardLedsChangedEvent(a, b, c, d)
#define fireMediumChangedEvent(a, b)
#define fireMousePointerShapeChangedEvent(a, b, c, d, e, f, g, h)
#define fireMouseCapabilityChangedEvent(a, b, c, d, e)
#define fireNATRedirectEvent(a, b, c, d, e, f, g, h, i, j)
#define fireNATNetworkChangedEvent(a, b)
#define fireNATNetworkPortForwardEvent(a, b, c, d, e, f, g, h, i, j)
#define fireNATNetworkSettingEvent(a, b, c, d, e, f, g)
#define fireNATNetworkStartStopEvent(a, b, c)
#define fireNetworkAdapterChangedEvent(a, b)
#define fireParallelPortChangedEvent(a, b)
#define fireSerialPortChangedEvent(a, b)
#define fireSharedFolderChangedEvent(a, b)
#define fireStorageControllerChangedEvent(a)
#define fireStorageDeviceChangedEvent(a, b, c, d)
#define fireUSBControllerChangedEvent(a)
#define fireUSBDeviceStateChangedEvent(a, b, c, d)
#define fireVideoCaptureChangedEvent(a)
#define fireVRDEServerChangedEvent(a)
#define fireVRDEServerInfoChangedEvent(a)

View File

@ -0,0 +1,468 @@
#ifndef ____H_VIRTUALBOXBASEIMPL
#define ____H_VIRTUALBOXBASEIMPL
#include <base/log.h>
#include <iprt/cdefs.h>
#include <iprt/thread.h>
#include <list>
#include <map>
#include "ObjectState.h"
#include "VBox/com/AutoLock.h"
#include "VBox/com/string.h"
#include "VBox/com/Guid.h"
#include "VBox/com/VirtualBox.h"
namespace com
{
class ErrorInfo;
}
using namespace com;
using namespace util;
class AutoInitSpan;
class AutoUninitSpan;
class VirtualBox;
class Machine;
class Medium;
typedef std::list<ComObjPtr<Medium> > MediaList;
typedef std::list<Utf8Str> StringsList;
class VirtualBoxTranslatable : public util::Lockable
{
public:
/* should be used for translations */
inline static const char *tr(const char *pcszSourceText,
const char *aComment = NULL)
{
return pcszSourceText;
}
};
class VirtualBoxBase : public VirtualBoxTranslatable
{
private:
RWLockHandle *_lock;
/** Primary state of this object */
ObjectState mState;
/** Thread that caused the last state change */
RTTHREAD mStateChangeThread;
/** Total number of active calls to this object */
unsigned mCallers;
/** Posted when the number of callers drops to zero */
RTSEMEVENT mZeroCallersSem;
/** Posted when the object goes from InInit/InUninit to some other state */
RTSEMEVENTMULTI mInitUninitSem;
/** Number of threads waiting for mInitUninitDoneSem */
unsigned mInitUninitWaiters;
/** User-level object lock for subclasses */
mutable RWLockHandle *mObjectLock;
friend class AutoInitSpan;
friend class AutoReinitSpan;
friend class AutoUninitSpan;
protected:
HRESULT BaseFinalConstruct() { return S_OK; }
void BaseFinalRelease() { }
public:
VirtualBoxBase(); // : _lock(nullptr) { }
~VirtualBoxBase();
virtual void uninit() { }
ObjectState &getObjectState()
{
return mState;
}
virtual const char* getComponentName() const = 0;
static HRESULT handleUnexpectedExceptions(VirtualBoxBase *const aThis, RT_SRC_POS_DECL);
static HRESULT initializeComForThread(void);
static void uninitializeComForThread(void);
static void clearError(void);
HRESULT setError(HRESULT aResultCode);
HRESULT setError(HRESULT aResultCode, const char *pcsz, ...);
HRESULT setError(const com::ErrorInfo &ei);
HRESULT setErrorVrc(int vrc);
HRESULT setErrorVrc(int vrc, const char *pcszMsgFmt, ...);
HRESULT setErrorBoth(HRESULT hrc, int vrc);
HRESULT setErrorBoth(HRESULT hrc, int vrc, const char *pcszMsgFmt, ...);
HRESULT setErrorNoLog(HRESULT aResultCode, const char *pcsz, ...);
static HRESULT setErrorInternal(HRESULT aResultCode,
const GUID &aIID,
const char *aComponent,
Utf8Str aText,
bool aWarning,
bool aLogIt);
virtual VBoxLockingClass getLockingClass() const
{
return LOCKCLASS_OTHEROBJECT;
}
RWLockHandle * lockHandle() const;
};
/**
* Dummy macro that is used to shut down Qt's lupdate tool warnings in some
* situations. This macro needs to be present inside (better at the very
* beginning) of the declaration of the class that inherits from
* VirtualBoxTranslatable, to make lupdate happy.
*/
#define Q_OBJECT
template <typename T>
class Shareable
{
private:
bool _verbose;
T * _obj;
public:
Shareable<T> () : _verbose(false), _obj(nullptr) { }
/* operators */
T * operator->() const { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); return _obj; }
bool isNull() const { return _obj == nullptr; }
bool operator!() const { return isNull(); }
void allocate() { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); _obj = new T; }
void attach(T * t) { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); }
void attach(Shareable &s) { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); }
void share(const Shareable &s) { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); _obj = s._obj; }
void share(T * obj) { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); _obj = obj; }
void free() { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); }
void attachCopy(const T *) { if(_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); }
void attachCopy(const Shareable &) { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); }
T *data() const { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); return _obj; }
bool isShared() const { if (_verbose) Genode::log(__PRETTY_FUNCTION__, " called"); return false; }
};
template <typename T>
class Backupable : public Shareable<T>
{
public:
Backupable() : Shareable<T>() { }
void backup() { }
void rollback() { }
void commit() { }
void commitCopy() { }
void assignCopy(const T *) { }
void assignCopy(const Backupable &) { }
HRESULT backupEx() { return S_OK; }
T *backedUpData() const { Genode::log(__PRETTY_FUNCTION__, " called"); return nullptr; }
bool isBackedUp() const { return false; }
};
/**
* Special version of the Assert macro to be used within VirtualBoxBase
* subclasses.
*
* In the debug build, this macro is equivalent to Assert.
* In the release build, this macro uses |setError(E_FAIL, ...)| to set the
* error info from the asserted expression.
*
* @see VirtualBoxBase::setError
*
* @param expr Expression which should be true.
*/
#if defined(DEBUG)
#define ComAssert(expr) Assert(expr)
#else
#define ComAssert(expr) \
do { \
if (RT_UNLIKELY(!(expr))) \
setError(E_FAIL, \
"Assertion failed: [%s] at '%s' (%d) in %s.\nPlease contact the product vendor!", \
#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
} while (0)
#endif
/**
* Special version of the AssertFailed macro to be used within VirtualBoxBase
* subclasses.
*
* In the debug build, this macro is equivalent to AssertFailed.
* In the release build, this macro uses |setError(E_FAIL, ...)| to set the
* error info from the asserted expression.
*
* @see VirtualBoxBase::setError
*
*/
#if defined(DEBUG)
#define ComAssertFailed() AssertFailed()
#else
#define ComAssertFailed() \
do { \
setError(E_FAIL, \
"Assertion failed: at '%s' (%d) in %s.\nPlease contact the product vendor!", \
__FILE__, __LINE__, __PRETTY_FUNCTION__); \
} while (0)
#endif
/**
* Special version of the AssertMsg macro to be used within VirtualBoxBase
* subclasses.
*
* See ComAssert for more info.
*
* @param expr Expression which should be true.
* @param a printf argument list (in parenthesis).
*/
#if defined(DEBUG)
#define ComAssertMsg(expr, a) AssertMsg(expr, a)
#else
#define ComAssertMsg(expr, a) \
do { \
if (RT_UNLIKELY(!(expr))) \
setError(E_FAIL, \
"Assertion failed: [%s] at '%s' (%d) in %s.\n%s.\nPlease contact the product vendor!", \
#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__, Utf8StrFmt a .c_str()); \
} while (0)
#endif
/**
* Special version of the AssertComRC macro to be used within VirtualBoxBase
* subclasses.
*
* See ComAssert for more info.
*
* @param rc COM result code
*/
#if defined(DEBUG)
#define ComAssertComRC(rc) AssertComRC(rc)
#else
#define ComAssertComRC(rc) ComAssertMsg(SUCCEEDED(rc), ("COM RC = %Rhrc (0x%08X)", (rc), (rc)))
#endif
/**
* Special version of the AssertMsgRC macro to be used within VirtualBoxBase
* subclasses.
*
* See ComAssert for more info.
*
* @param vrc VBox status code.
* @param msg printf argument list (in parenthesis).
*/
#if defined(DEBUG)
#define ComAssertMsgRC(vrc, msg) AssertMsgRC(vrc, msg)
#else
#define ComAssertMsgRC(vrc, msg) ComAssertMsg(RT_SUCCESS(vrc), msg)
#endif
/**
* Special version of the AssertRC macro to be used within VirtualBoxBase
* subclasses.
*
* See ComAssert for more info.
*
* @param vrc VBox status code.
*/
#if defined(DEBUG)
#define ComAssertRC(vrc) AssertRC(vrc)
#else
#define ComAssertRC(vrc) ComAssertMsgRC(vrc, ("%Rra", vrc))
#endif
/** Special version of ComAssert that returns ret if expr fails */
#define ComAssertRet(expr, ret) \
do { ComAssert(expr); if (!(expr)) return (ret); } while (0)
/** Special version of ComAssertMsg that returns ret if expr fails */
#define ComAssertMsgRet(expr, a, ret) \
do { ComAssertMsg(expr, a); if (!(expr)) return (ret); } while (0)
/** Special version of ComAssertComRC that returns ret if rc does not succeed */
#define ComAssertComRCRet(rc, ret) \
do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (ret); } while (0)
/** Special version of ComAssertMsg that evaluates eval and breaks if expr fails */
#define ComAssertMsgBreak(expr, a, eval) \
if (1) { ComAssertMsg(expr, a); if (!(expr)) { eval; break; } } else do {} while (0)
/** Special version of ComAssert that evaluates eval and throws it if expr fails */
#define ComAssertThrow(expr, eval) \
do { ComAssert(expr); if (!(expr)) { throw (eval); } } while (0)
/** Special version of ComAssertRC that evaluates eval and throws it if vrc does not succeed */
#define ComAssertRCThrow(vrc, eval) \
do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) { throw (eval); } } while (0)
/** Special version of ComAssertFailed that returns ret */
#define ComAssertFailedRet(ret) \
do { ComAssertFailed(); return (ret); } while (0)
/** Special version of ComAssertFailed that returns ret */
#define ComAssertFailedRet(ret) \
do { ComAssertFailed(); return (ret); } while (0)
/** Special version of ComAssertRC that returns ret if vrc does not succeed */
#define ComAssertRCRet(vrc, ret) \
do { ComAssertRC(vrc); if (!RT_SUCCESS(vrc)) return (ret); } while (0)
/** Special version of ComAssertComRC that just throws rc if rc does not succeed */
#define ComAssertComRCThrowRC(rc) \
do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) { throw rc; } } while (0)
/** Special version of ComAssertComRC that returns rc if rc does not succeed */
#define ComAssertComRCRetRC(rc) \
do { ComAssertComRC(rc); if (!SUCCEEDED(rc)) return (rc); } while (0)
/**
* Checks that the pointer argument is not NULL and returns E_INVALIDARG +
* extended error info on failure.
* @param arg Input pointer-type argument (strings, interface pointers...)
*/
#define CheckComArgNotNull(arg) \
do { \
if (RT_UNLIKELY((arg) == NULL)) \
return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
} while (0)
/**
* Checks that the given expression (that must involve the argument) is true and
* returns E_INVALIDARG + extended error info on failure.
* @param arg Argument.
* @param expr Expression to evaluate.
*/
#define CheckComArgExpr(arg, expr) \
do { \
if (RT_UNLIKELY(!(expr))) \
return setError(E_INVALIDARG, \
tr("Argument %s is invalid (must be %s)"), #arg, #expr); \
} while (0)
/**
* Checks that the given pointer to an output argument is valid and returns
* E_POINTER + extended error info otherwise.
* @param arg Pointer argument.
*/
#define CheckComArgOutPointerValid(arg) \
do { \
if (RT_UNLIKELY(!VALID_PTR(arg))) \
return setError(E_POINTER, \
tr("Output argument %s points to invalid memory location (%p)"), \
#arg, (void *)(arg)); \
} while (0)
/**
* Checks that a string input argument is valid (not NULL or obviously invalid
* pointer), returning E_INVALIDARG + extended error info if invalid.
* @param a_bstrIn Input string argument (IN_BSTR).
*/
#define CheckComArgStr(a_bstrIn) \
do { \
IN_BSTR const bstrInCheck = (a_bstrIn); /* type check */ \
if (RT_UNLIKELY(!RT_VALID_PTR(bstrInCheck))) \
return setError(E_INVALIDARG, tr("Argument %s is an invalid pointer"), #a_bstrIn); \
} while (0)
/**
* Checks that the string argument is not a NULL, a invalid pointer or an empty
* string, returning E_INVALIDARG + extended error info on failure.
* @param a_bstrIn Input string argument (BSTR etc.).
*/
#define CheckComArgStrNotEmptyOrNull(a_bstrIn) \
do { \
IN_BSTR const bstrInCheck = (a_bstrIn); /* type check */ \
if (RT_UNLIKELY(!RT_VALID_PTR(bstrInCheck) || *(bstrInCheck) == '\0')) \
return setError(E_INVALIDARG, tr("Argument %s is empty or an invalid pointer"), #a_bstrIn); \
} while (0)
/**
* Checks that the given pointer to an output safe array argument is valid and
* returns E_POINTER + extended error info otherwise.
* @param arg Safe array argument.
*/
#define CheckComArgOutSafeArrayPointerValid(arg) \
do { \
if (RT_UNLIKELY(ComSafeArrayOutIsNull(arg))) \
return setError(E_POINTER, \
tr("Output argument %s points to invalid memory location (%p)"), \
#arg, (void*)(arg)); \
} while (0)
/**
* Checks that safe array argument is not NULL and returns E_INVALIDARG +
* extended error info on failure.
* @param arg Input safe array argument (strings, interface pointers...)
*/
#define CheckComArgSafeArrayNotNull(arg) \
do { \
if (RT_UNLIKELY(ComSafeArrayInIsNull(arg))) \
return setError(E_INVALIDARG, tr("Argument %s is NULL"), #arg); \
} while (0)
/**
* Sets the extended error info and returns E_NOTIMPL.
*/
#define ReturnComNotImplemented() \
do { \
return setError(E_NOTIMPL, tr("Method %s is not implemented"), __FUNCTION__); \
} while (0)
#define DECLARE_EMPTY_CTOR_DTOR(X) public: X(); ~X();
#define DEFINE_EMPTY_CTOR_DTOR(X) X::X() {} X::~X() {}
#define VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface) \
virtual const GUID& getClassIID() const \
{ \
return cls::getStaticClassIID(); \
} \
static const GUID& getStaticClassIID() \
{ \
return COM_IIDOF(iface); \
} \
virtual const char* getComponentName() const \
{ \
return cls::getStaticComponentName(); \
} \
static const char* getStaticComponentName() \
{ \
return #cls; \
}
/**
* VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT:
* This macro must be used once in the declaration of any class derived
* from VirtualBoxBase. It implements the pure virtual getClassIID() and
* getComponentName() methods. If this macro is not present, instances
* of a class derived from VirtualBoxBase cannot be instantiated.
*
* @param X The class name, e.g. "Class".
* @param IX The interface name which this class implements, e.g. "IClass".
*/
#define VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(cls, iface) \
VIRTUALBOXBASE_ADD_VIRTUAL_COMPONENT_METHODS(cls, iface)
#include "GenodeImpl.h"
#endif // !____H_VIRTUALBOXBASEIMPL

View File

@ -0,0 +1,6 @@
#include "dummy/macros.h"
#include "VirtualBoxErrorInfoImpl.h"
HRESULT VirtualBoxErrorInfo::init(HRESULT, const GUID &, const char *,
const Utf8Str &, IVirtualBoxErrorInfo *) DUMMY(E_FAIL)

View File

@ -0,0 +1,49 @@
#ifndef ____H_VIRTUALBOXERRORINFO
#define ____H_VIRTUALBOXERRORINFO
#include <VirtualBoxBase.h>
class VirtualBoxErrorInfo :
public VirtualBoxBase,
VBOX_SCRIPTABLE_IMPL(IVirtualBoxErrorInfo)
{
public:
VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT(VirtualBoxErrorInfo, IVirtualBoxErrorInfo)
DECLARE_NOT_AGGREGATABLE(VirtualBoxErrorInfo)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(VirtualBoxErrorInfo)
COM_INTERFACE_ENTRY(IErrorInfo)
COM_INTERFACE_ENTRY(IVirtualBoxErrorInfo)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
HRESULT init(HRESULT aResultCode, const GUID &aIID,
const char *pcszComponent, const com::Utf8Str &strText,
IVirtualBoxErrorInfo *aNext = NULL);
HRESULT FinalConstruct() { return S_OK; }
/* readonly attribute long resultCode; */
HRESULT GetResultCode(PRInt32 *aResultCode) { return S_OK; }
/* readonly attribute long resultDetail; */
HRESULT GetResultDetail(PRInt32 *aResultDetail) { return S_OK; }
/* readonly attribute wstring interfaceID; */
HRESULT GetInterfaceID(PRUnichar * *aInterfaceID) { return S_OK; }
/* readonly attribute wstring component; */
HRESULT GetComponent(PRUnichar * *aComponent) { return S_OK; }
/* readonly attribute wstring text; */
HRESULT GetText(PRUnichar * *aText) { return S_OK; }
/* readonly attribute IVirtualBoxErrorInfo next; */
HRESULT GetNext(IVirtualBoxErrorInfo * *aNext) { return S_OK; }
};
#endif /* ____H_VIRTUALBOXERRORINFO */

View File

@ -0,0 +1,520 @@
/*
* \brief Port of VirtualBox to Genode
* \author Norman Feske
* \author Alexander Boettcher
*/
/*
* Copyright (C) 2013-2015 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <util/xml_node.h>
#include <VBox/settings.h>
#include <SharedClipboard/VBoxClipboard.h>
#include <VBox/HostServices/VBoxClipboardSvc.h>
#include "ConsoleImpl.h"
#include "MouseImpl.h"
#include "DisplayImpl.h"
#include "GuestImpl.h"
#include "dummy/macros.h"
#include "console.h"
#include "fb.h"
static const bool debug = false;
static Genode::Attached_rom_dataspace *clipboard_rom = nullptr;
static Genode::Reporter *clipboard_reporter = nullptr;
static char *decoded_clipboard_content = nullptr;
void Console::uninit()
DUMMY()
HRESULT Console::teleport(const com::Utf8Str &, ULONG, const com::Utf8Str &,
ULONG, ComPtr<IProgress> &aProgress)
DUMMY(E_FAIL)
HRESULT Console::i_teleporterTrg(PUVM, IMachine *, Utf8Str *, bool, Progress *,
bool *)
DUMMY(E_FAIL)
HRESULT Console::i_attachToTapInterface(INetworkAdapter *networkAdapter)
{
ULONG slot = 0;
HRESULT rc = networkAdapter->COMGETTER(Slot)(&slot);
AssertComRC(rc);
maTapFD[slot] = (RTFILE)1;
TRACE(rc)
}
HRESULT Console::i_detachFromTapInterface(INetworkAdapter *networkAdapter)
{
ULONG slot = 0;
HRESULT rc = networkAdapter->COMGETTER(Slot)(&slot);
AssertComRC(rc);
if (maTapFD[slot] != NIL_RTFILE)
maTapFD[slot] = NIL_RTFILE;
TRACE(rc)
}
void fireStateChangedEvent(IEventSource* aSource,
MachineState_T a_state)
{
if (a_state != MachineState_PoweredOff)
return;
Genode::env()->parent()->exit(0);
}
void fireRuntimeErrorEvent(IEventSource* aSource, BOOL a_fatal,
CBSTR a_id, CBSTR a_message)
{
Genode::error(__func__, " : ", a_fatal, " ",
Utf8Str(a_id).c_str(), " ",
Utf8Str(a_message).c_str());
TRACE();
}
void Console::i_onAdditionsStateChange()
{
dynamic_cast<GenodeConsole *>(this)->update_video_mode();
}
void GenodeConsole::update_video_mode()
{
Display *d = i_getDisplay();
Guest *g = i_getGuest();
IFramebuffer *pFramebuffer = NULL;
HRESULT rc = d->QueryFramebuffer(0, &pFramebuffer);
Assert(SUCCEEDED(rc) && pFramebuffer);
Genodefb *fb = dynamic_cast<Genodefb *>(pFramebuffer);
LONG64 ignored = 0;
if (fb && (fb->w() == 0) && (fb->h() == 0)) {
/* interpret a size of 0x0 as indication to quit VirtualBox */
if (PowerButton() != S_OK)
Genode::error("ACPI shutdown failed");
return;
}
AdditionsFacilityType_T is_graphics;
g->GetFacilityStatus(AdditionsFacilityType_Graphics, &ignored, &is_graphics);
if (fb && is_graphics)
d->SetVideoModeHint(0 /*=display*/,
true /*=enabled*/, false /*=changeOrigin*/,
0 /*=originX*/, 0 /*=originY*/,
fb->w(), fb->h(),
/* Windows 8 only accepts 32-bpp modes */
32);
}
void GenodeConsole::handle_input(unsigned)
{
static LONG64 mt_events [64];
unsigned mt_number = 0;
/* read out input capabilities of guest */
bool guest_abs = false, guest_rel = false, guest_multi = false;
_vbox_mouse->COMGETTER(AbsoluteSupported)(&guest_abs);
_vbox_mouse->COMGETTER(RelativeSupported)(&guest_rel);
_vbox_mouse->COMGETTER(MultiTouchSupported)(&guest_multi);
for (int i = 0, num_ev = _input.flush(); i < num_ev; ++i) {
Input::Event &ev = _ev_buf[i];
bool const press = ev.type() == Input::Event::PRESS;
bool const release = ev.type() == Input::Event::RELEASE;
bool const key = press || release;
bool const motion = ev.type() == Input::Event::MOTION;
bool const wheel = ev.type() == Input::Event::WHEEL;
bool const touch = ev.type() == Input::Event::TOUCH;
if (key) {
Scan_code scan_code(ev.keycode());
unsigned char const release_bit =
(ev.type() == Input::Event::RELEASE) ? 0x80 : 0;
if (scan_code.normal())
_vbox_keyboard->PutScancode(scan_code.code() | release_bit);
if (scan_code.ext()) {
_vbox_keyboard->PutScancode(0xe0);
_vbox_keyboard->PutScancode(scan_code.ext() | release_bit);
}
}
/*
* Track press/release status of keys and buttons. Currently,
* only the mouse-button states are actually used.
*/
if (press)
_key_status[ev.keycode()] = true;
if (release)
_key_status[ev.keycode()] = false;
bool const mouse_button_event =
key && _mouse_button(ev.keycode());
bool const mouse_event = mouse_button_event || motion;
if (mouse_event) {
unsigned const buttons = (_key_status[Input::BTN_LEFT] ? MouseButtonState_LeftButton : 0)
| (_key_status[Input::BTN_RIGHT] ? MouseButtonState_RightButton : 0)
| (_key_status[Input::BTN_MIDDLE] ? MouseButtonState_MiddleButton : 0);
if (ev.absolute_motion()) {
_last_received_motion_event_was_absolute = true;
/* transform absolute to relative if guest is so odd */
if (!guest_abs && guest_rel) {
int const boundary = 20;
int rx = ev.ax() - _ax;
int ry = ev.ay() - _ay;
rx = Genode::min(boundary, Genode::max(-boundary, rx));
ry = Genode::min(boundary, Genode::max(-boundary, ry));
_vbox_mouse->PutMouseEvent(rx, ry, 0, 0, buttons);
} else
_vbox_mouse->PutMouseEventAbsolute(ev.ax(), ev.ay(), 0,
0, buttons);
_ax = ev.ax();
_ay = ev.ay();
} else if (ev.relative_motion()) {
_last_received_motion_event_was_absolute = false;
/* prefer relative motion event */
if (guest_rel)
_vbox_mouse->PutMouseEvent(ev.rx(), ev.ry(), 0, 0, buttons);
else if (guest_abs) {
_ax += ev.rx();
_ay += ev.ry();
_vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
}
}
/* only the buttons changed */
else {
if (_last_received_motion_event_was_absolute) {
/* prefer absolute button event */
if (guest_abs)
_vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
else if (guest_rel)
_vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons);
} else {
/* prefer relative button event */
if (guest_rel)
_vbox_mouse->PutMouseEvent(0, 0, 0, 0, buttons);
else if (guest_abs)
_vbox_mouse->PutMouseEventAbsolute(_ax, _ay, 0, 0, buttons);
}
}
}
if (wheel) {
if (_last_received_motion_event_was_absolute)
_vbox_mouse->PutMouseEventAbsolute(_ax, _ay, -ev.ry(), -ev.rx(), 0);
else
_vbox_mouse->PutMouseEvent(0, 0, -ev.ry(), -ev.rx(), 0);
}
if (touch) {
/* if multitouch queue is full - send it */
if (mt_number >= sizeof(mt_events) / sizeof(mt_events[0])) {
_vbox_mouse->PutEventMultiTouch(mt_number, mt_number,
mt_events, RTTimeMilliTS());
mt_number = 0;
}
int x = ev.ax();
int y = ev.ay();
int slot = ev.code();
/* Mouse::putEventMultiTouch drops values of 0 */
if (x <= 0) x = 1;
if (y <= 0) y = 1;
enum MultiTouch {
None = 0x0,
InContact = 0x01,
InRange = 0x02
};
int status = MultiTouch::InContact | MultiTouch::InRange;
if (ev.touch_release())
status = MultiTouch::None;
uint16_t const s = RT_MAKE_U16(slot, status);
mt_events[mt_number++] = RT_MAKE_U64_FROM_U16(x, y, s, 0);
}
}
/* if there are elements - send it */
if (mt_number)
_vbox_mouse->PutEventMultiTouch(mt_number, mt_number, mt_events,
RTTimeMilliTS());
}
void GenodeConsole::handle_mode_change(unsigned)
{
IFramebuffer *pFramebuffer = NULL;
HRESULT rc = i_getDisplay()->QueryFramebuffer(0, &pFramebuffer);
Assert(SUCCEEDED(rc) && pFramebuffer);
Genodefb *fb = dynamic_cast<Genodefb *>(pFramebuffer);
fb->update_mode();
update_video_mode();
}
void GenodeConsole::init_clipboard()
{
if (!&*i_machine())
return;
ClipboardMode_T mode;
i_machine()->COMGETTER(ClipboardMode)(&mode);
if (mode == ClipboardMode_Bidirectional ||
mode == ClipboardMode_HostToGuest) {
_clipboard_rom = new Genode::Attached_rom_dataspace("clipboard");
_clipboard_rom->sigh(_clipboard_signal_dispatcher);
clipboard_rom = _clipboard_rom;
}
if (mode == ClipboardMode_Bidirectional ||
mode == ClipboardMode_GuestToHost) {
_clipboard_reporter = new Genode::Reporter("clipboard");
_clipboard_reporter->enabled(true);
clipboard_reporter = _clipboard_reporter;
}
}
void GenodeConsole::handle_cb_rom_change(unsigned)
{
if (!_clipboard_rom)
return;
vboxClipboardSync(nullptr);
}
void GenodeConsole::event_loop(IKeyboard * gKeyboard, IMouse * gMouse)
{
_vbox_keyboard = gKeyboard;
_vbox_mouse = gMouse;
/* register the mode change signal dispatcher at the framebuffer */
IFramebuffer *pFramebuffer = NULL;
HRESULT rc = i_getDisplay()->QueryFramebuffer(0, &pFramebuffer);
Assert(SUCCEEDED(rc) && pFramebuffer);
Genodefb *fb = dynamic_cast<Genodefb *>(pFramebuffer);
fb->mode_sigh(_mode_change_signal_dispatcher);
for (;;) {
Genode::Signal sig = _receiver.wait_for_signal();
Genode::Signal_dispatcher_base *dispatcher =
dynamic_cast<Genode::Signal_dispatcher_base *>(sig.context());
if (dispatcher)
dispatcher->dispatch(sig.num());
}
}
void GenodeConsole::i_onMouseCapabilityChange(BOOL supportsAbsolute,
BOOL supportsRelative,
BOOL supportsMT,
BOOL needsHostCursor)
{
if (supportsAbsolute) {
/* let the guest hide the software cursor */
Mouse *gMouse = i_getMouse();
gMouse->PutMouseEventAbsolute(-1, -1, 0, 0, 0);
}
}
/**********************
* Clipboard handling *
**********************/
struct _VBOXCLIPBOARDCONTEXT
{
VBOXCLIPBOARDCLIENTDATA *pClient;
};
static VBOXCLIPBOARDCONTEXT context;
int vboxClipboardInit (void) { return VINF_SUCCESS; }
void vboxClipboardDestroy (void)
{
free(decoded_clipboard_content);
clipboard_rom = nullptr;
}
int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless)
{
if (!pClient || context.pClient != NULL)
return VERR_NOT_SUPPORTED;
vboxSvcClipboardLock();
pClient->pCtx = &context;
pClient->pCtx->pClient = pClient;
vboxSvcClipboardUnlock();
int rc = vboxClipboardSync (pClient);
return rc;
}
void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient)
{
if (!pClient || !pClient->pCtx)
return;
vboxSvcClipboardLock();
pClient->pCtx->pClient = NULL;
vboxSvcClipboardUnlock();
}
void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient,
uint32_t formats)
{
if (!pClient)
return;
vboxSvcClipboardReportMsg (pClient,
VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
formats);
}
int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t format,
void *pv, uint32_t const cb, uint32_t *pcbActual)
{
if (!clipboard_rom || format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
return VERR_NOT_SUPPORTED;
if (!pv || !pcbActual || cb == 0)
return VERR_INVALID_PARAMETER;
clipboard_rom->update();
if (!clipboard_rom->valid()) {
Genode::error("invalid clipboard dataspace");
return VERR_NOT_SUPPORTED;
}
char * data = clipboard_rom->local_addr<char>();
try {
Genode::Xml_node node(data);
if (!node.has_type("clipboard")) {
Genode::error("invalid clipboard xml syntax");
return VERR_INVALID_PARAMETER;
}
free(decoded_clipboard_content);
decoded_clipboard_content = (char*)malloc(node.content_size());
if (!decoded_clipboard_content) {
Genode::error("could not allocate buffer for decoded clipboard content");
return 0;
}
size_t const len = node.decoded_content(decoded_clipboard_content,
node.content_size());
size_t written = 0;
PRTUTF16 utf16_string = reinterpret_cast<PRTUTF16>(pv);
int rc = RTStrToUtf16Ex(decoded_clipboard_content, len, &utf16_string, cb, &written);
if (RT_SUCCESS(rc)) {
if ((written * 2) + 2 > cb)
written = (cb - 2) / 2;
/* +1 stuff required for Windows guests ... linux guest doesn't care */
*pcbActual = (written + 1) * 2;
utf16_string[written] = 0;
} else
*pcbActual = 0;
} catch (Genode::Xml_node::Invalid_syntax) {
Genode::error("invalid clipboard xml syntax");
return VERR_INVALID_PARAMETER;
}
return VINF_SUCCESS;
}
void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv,
uint32_t cb, uint32_t format)
{
if (format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT || !pv || !pClient ||
!clipboard_reporter)
return;
PCRTUTF16 utf16str = reinterpret_cast<PCRTUTF16>(pv);
char * message = 0;
int rc = RTUtf16ToUtf8(utf16str, &message);
if (!RT_SUCCESS(rc) || !message)
return;
try {
Genode::Reporter::Xml_generator xml(*clipboard_reporter, [&] () {
xml.append_sanitized(message, strlen(message)); });
} catch (...) {
Genode::error("could not write clipboard data");
}
RTStrFree(message);
}
int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient)
{
if (!pClient)
pClient = context.pClient;
if (!pClient)
return VERR_NOT_SUPPORTED;
vboxSvcClipboardReportMsg (pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS,
VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
return VINF_SUCCESS;
}

View File

@ -0,0 +1,234 @@
/*
* \brief Console implementation of VirtualBox for Genode
* \author Alexander Boettcher
* \author Norman Feske
* \date 2013-10-16
*/
/*
* Copyright (C) 2013-2014 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <input/event.h>
#include <input/keycodes.h>
#include <input_session/connection.h>
#include <os/attached_dataspace.h>
#include <os/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <report_session/connection.h>
#include <timer_session/connection.h>
/* included from os/src/drivers/input/spec/ps2 */
#include <scan_code_set_1.h>
/* repos/ports includes */
#include <vbox_pointer/shape_report.h>
/* VirtualBox includes */
#include "ConsoleImpl.h"
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];
}
};
class GenodeConsole : public Console {
private:
Input::Connection _input;
Genode::Signal_receiver _receiver;
Input::Event *_ev_buf;
unsigned _ax, _ay;
bool _last_received_motion_event_was_absolute;
Report::Connection _shape_report_connection;
Genode::Attached_dataspace _shape_report_ds;
Vbox_pointer::Shape_report *_shape_report;
Genode::Reporter *_clipboard_reporter;
Genode::Attached_rom_dataspace *_clipboard_rom;
IKeyboard *_vbox_keyboard;
IMouse *_vbox_mouse;
Genode::Signal_dispatcher<GenodeConsole> _input_signal_dispatcher;
Genode::Signal_dispatcher<GenodeConsole> _mode_change_signal_dispatcher;
Genode::Signal_dispatcher<GenodeConsole> _clipboard_signal_dispatcher;
bool _key_status[Input::KEY_MAX + 1];
static bool _mouse_button(Input::Keycode keycode)
{
return keycode == Input::BTN_LEFT
|| keycode == Input::BTN_RIGHT
|| keycode == Input::BTN_MIDDLE;
}
public:
GenodeConsole()
:
Console(),
_ev_buf(static_cast<Input::Event *>(Genode::env()->rm_session()->attach(_input.dataspace()))),
_ax(0), _ay(0),
_last_received_motion_event_was_absolute(false),
_shape_report_connection("shape", sizeof(Vbox_pointer::Shape_report)),
_shape_report_ds(_shape_report_connection.dataspace()),
_shape_report(_shape_report_ds.local_addr<Vbox_pointer::Shape_report>()),
_clipboard_reporter(nullptr),
_clipboard_rom(nullptr),
_vbox_keyboard(0),
_vbox_mouse(0),
_input_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_input),
_mode_change_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_mode_change),
_clipboard_signal_dispatcher(_receiver, *this, &GenodeConsole::handle_cb_rom_change)
{
for (unsigned i = 0; i <= Input::KEY_MAX; i++)
_key_status[i] = 0;
_input.sigh(_input_signal_dispatcher);
}
void init_clipboard();
void event_loop(IKeyboard * gKeyboard, IMouse * gMouse);
void i_onMouseCapabilityChange(BOOL supportsAbsolute,
BOOL supportsRelative, BOOL supportsMT,
BOOL needsHostCursor);
void i_onMousePointerShapeChange(bool fVisible, bool fAlpha,
uint32_t xHot, uint32_t yHot,
uint32_t width, uint32_t height,
const uint8_t *pu8Shape,
uint32_t cbShape)
{
if (fVisible && ((width == 0) || (height == 0)))
return;
_shape_report->visible = fVisible;
_shape_report->x_hot = xHot;
_shape_report->y_hot = yHot;
_shape_report->width = width;
_shape_report->height = height;
unsigned int and_mask_size = (_shape_report->width + 7) / 8 *
_shape_report->height;
const unsigned char *and_mask = pu8Shape;
const unsigned char *shape = and_mask + ((and_mask_size + 3) & ~3);
size_t shape_size = cbShape - (shape - and_mask);
if (shape_size > Vbox_pointer::MAX_SHAPE_SIZE) {
Genode::error(__func__, ": shape data buffer is too small for ",
shape_size, " bytes");
return;
}
Genode::memcpy(_shape_report->shape,
shape,
shape_size);
if (fVisible && !fAlpha) {
for (unsigned int i = 0; i < width * height; i++) {
unsigned int *color =
&((unsigned int*)_shape_report->shape)[i];
/* heuristic from VBoxSDL.cpp */
if (and_mask[i / 8] & (1 << (7 - (i % 8)))) {
if (*color & 0x00ffffff)
*color = 0xff000000;
else
*color = 0x00000000;
} else
*color |= 0xff000000;
}
}
_shape_report_connection.submit(sizeof(Vbox_pointer::Shape_report));
}
void update_video_mode();
void handle_input(unsigned);
void handle_mode_change(unsigned);
void handle_cb_rom_change(unsigned);
};

View File

@ -0,0 +1,17 @@
#include "VirtualBoxBase.h"
#include "dummy/macros.h"
#include "AutostartDb.h"
static bool debug = false;
int AutostartDb::addAutostartVM(const char *pszVMId) DUMMY(-1)
int AutostartDb::addAutostopVM(char const*) DUMMY(-1)
int AutostartDb::removeAutostopVM(char const*) DUMMY(-1)
int AutostartDb::removeAutostartVM(char const*) DUMMY(-1)
AutostartDb::AutostartDb() TRACE()
AutostartDb::~AutostartDb() DUMMY()
int AutostartDb::setAutostartDbPath(char const*path) TRACE(VINF_SUCCESS)

View File

@ -0,0 +1,14 @@
#include "VirtualBoxBase.h"
#include "dummy/macros.h"
#include <VBox/com/ErrorInfo.h>
static bool debug = false;
void ErrorInfo::init(bool aKeepObj) TRACE()
void ErrorInfo::cleanup() TRACE()
HRESULT ErrorInfoKeeper::restore() TRACE(S_OK)
void ErrorInfo::copyFrom(const ErrorInfo &x) DUMMY()

View File

@ -0,0 +1,191 @@
#include "VirtualBoxBase.h"
#include <VBox/usbfilter.h>
#include "dummy/macros.h"
#include "HostImpl.h"
static bool debug = false;
DEFINE_EMPTY_CTOR_DTOR(Host)
HRESULT Host::i_findHostDriveByName(DeviceType_T mediumType,
const Utf8Str &strLocationFull,
bool fRefresh,
ComObjPtr<Medium> &pMedium)
DUMMY(E_FAIL)
HRESULT Host::i_findHostDriveById(DeviceType_T, com::Guid const&, bool,
ComObjPtr<Medium>&)
TRACE(VBOX_E_OBJECT_NOT_FOUND)
HRESULT Host::i_saveSettings(settings::Host&)
TRACE(S_OK)
HRESULT Host::i_loadSettings(const settings::Host &)
TRACE(S_OK)
HRESULT Host::FinalConstruct()
TRACE(S_OK)
HRESULT Host::init(VirtualBox *aParent)
{
/* Enclose the state transition NotReady->InInit->Ready */
AutoInitSpan autoInitSpan(this);
AssertReturn(autoInitSpan.isOk(), E_FAIL);
/* Confirm a successful initialization */
autoInitSpan.setSucceeded();
return S_OK;
}
void Host::uninit()
DUMMY()
void Host::i_generateMACAddress(Utf8Str &mac)
{
static unsigned counter = 1;
mac = Utf8StrFmt("080027%06X", counter++);
TRACE();
}
HRESULT Host::generateMACAddress(com::Utf8Str &aAddress)
{
i_generateMACAddress(aAddress);
return S_OK;
}
HRESULT Host::getProcessorFeature(ProcessorFeature_T feature, BOOL *supported)
{
CheckComArgOutPointerValid(supported);
switch (feature)
{
case ProcessorFeature_HWVirtEx:
*supported = true;
break;
case ProcessorFeature_PAE:
*supported = true;
break;
case ProcessorFeature_LongMode:
*supported = (sizeof(void *) > 4);
break;
case ProcessorFeature_NestedPaging:
*supported = true;
break;
default:
return setError(E_INVALIDARG, tr("The feature value is out of range."));
}
return S_OK;
}
#ifdef VBOX_WITH_USB
USBProxyService* Host::i_usbProxyService()
{
TRACE(nullptr)
}
VirtualBox* Host::i_parent()
DUMMY(nullptr)
void Host::i_getUSBFilters(Host::USBDeviceFilterList *aGlobalFilters)
DUMMY()
HRESULT Host::i_checkUSBProxyService()
TRACE(S_OK)
/*
#include "HostUSBDeviceImpl.h"
#include "USBDeviceFilterImpl.h"
bool HostUSBDevice::isMatch(const USBDeviceFilter::Data &aData)
DUMMY(false)
*/
#endif
HRESULT Host::createHostOnlyNetworkInterface(ComPtr<IHostNetworkInterface> &,
ComPtr<IProgress> &)
DUMMY(E_FAIL)
HRESULT Host::removeHostOnlyNetworkInterface(const com::Guid &,
ComPtr<IProgress> &)
DUMMY(E_FAIL)
HRESULT Host::createUSBDeviceFilter(const com::Utf8Str &,
ComPtr<IHostUSBDeviceFilter> &)
DUMMY(E_FAIL)
HRESULT Host::insertUSBDeviceFilter(ULONG, const ComPtr<IHostUSBDeviceFilter> &)
DUMMY(E_FAIL)
HRESULT Host::removeUSBDeviceFilter(ULONG aPosition)
DUMMY(E_FAIL)
HRESULT Host::getAcceleration3DAvailable(BOOL *)
DUMMY(E_FAIL)
HRESULT Host::getDomainName(com::Utf8Str &)
DUMMY(E_FAIL)
HRESULT Host::getDVDDrives(std::vector<ComPtr<IMedium> > &)
DUMMY(E_FAIL)
HRESULT Host::getFloppyDrives(std::vector<ComPtr<IMedium> > &)
DUMMY(E_FAIL)
HRESULT Host::getMemorySize(ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getMemoryAvailable(ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getNameServers(std::vector<com::Utf8Str> &)
DUMMY(E_FAIL)
HRESULT Host::getNetworkInterfaces(std::vector<ComPtr<IHostNetworkInterface> > &)
DUMMY(E_FAIL)
HRESULT Host::getOperatingSystem(com::Utf8Str &)
DUMMY(E_FAIL)
HRESULT Host::getOSVersion(com::Utf8Str &)
DUMMY(E_FAIL)
HRESULT Host::getProcessorCount(ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getProcessorCoreCount(ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getProcessorDescription(ULONG, com::Utf8Str &)
DUMMY(E_FAIL)
HRESULT Host::getProcessorOnlineCount(ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getProcessorOnlineCoreCount(ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getProcessorSpeed(ULONG, ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getProcessorCPUIDLeaf(ULONG, ULONG, ULONG, ULONG *, ULONG *,
ULONG *, ULONG *)
DUMMY(E_FAIL)
HRESULT Host::getSearchStrings(std::vector<com::Utf8Str> &)
DUMMY(E_FAIL)
HRESULT Host::getUTCTime(LONG64 *)
DUMMY(E_FAIL)
HRESULT Host::getUSBDevices(std::vector<ComPtr<IHostUSBDevice> > &)
DUMMY(E_FAIL)
HRESULT Host::getUSBDeviceFilters(std::vector<ComPtr<IHostUSBDeviceFilter> > &)
DUMMY(E_FAIL)
HRESULT Host::getVideoInputDevices(std::vector<ComPtr<IHostVideoInputDevice> > &)
DUMMY(E_FAIL)
HRESULT Host::findHostDVDDrive(const com::Utf8Str &, ComPtr<IMedium> &)
DUMMY(E_FAIL)
HRESULT Host::findHostFloppyDrive(const com::Utf8Str &aName, ComPtr<IMedium> &)
DUMMY(E_FAIL)
HRESULT Host::findHostNetworkInterfaceByName(const com::Utf8Str &,
ComPtr<IHostNetworkInterface> &)
DUMMY(E_FAIL)
HRESULT Host::findHostNetworkInterfaceById(const com::Guid &,
ComPtr<IHostNetworkInterface> &)
DUMMY(E_FAIL)
HRESULT Host::findHostNetworkInterfacesOfType(HostNetworkInterfaceType_T,
std::vector<ComPtr<IHostNetworkInterface> > &)
DUMMY(E_FAIL)
HRESULT Host::findUSBDeviceByAddress(const com::Utf8Str &,
ComPtr<IHostUSBDevice> &)
DUMMY(E_FAIL)
HRESULT Host::findUSBDeviceById(const com::Guid &, ComPtr<IHostUSBDevice> &)
DUMMY(E_FAIL)

View File

@ -0,0 +1,37 @@
#ifndef ____H_MACROS
#define ____H_MACROS
#include <base/log.h>
#define TRACE(X) \
{ \
if (debug) \
Genode::log(__func__, " called (", __FILE__, ") - eip=", \
__builtin_return_address(0)); \
return X; \
}
#define DUMMY(X) \
{ \
Genode::error(__func__, " called (", __FILE__, ":", __LINE__, "), " \
"not implemented, eip=", \
__builtin_return_address(0)); \
while (1) \
asm volatile ("ud2a"); \
\
return X; \
}
#define DUMMY_STATIC(X) \
{ \
static X dummy; \
Genode::error(__func__, " called (", __FILE__, "), " \
"not implemented, eip=", \
__builtin_return_address(0)); \
while (1) \
asm volatile ("ud2a"); \
\
return dummy; \
}
#endif /* ____H_MACROS */

View File

@ -0,0 +1,127 @@
#include "dummy/macros.h"
static bool debug = false;
/* ApplianceImplExport.cpp */
#include "MachineImpl.h"
HRESULT Machine::exportTo(const ComPtr<IAppliance> &aAppliance,
const com::Utf8Str &aLocation,
ComPtr<IVirtualSystemDescription> &aDescription) DUMMY(E_FAIL)
/* com.cpp */
#include "VBox/com/Guid.h"
const com::Guid com::Guid::Empty;
/* DisplayPNGUtil.cpp */
#include "DisplayImpl.h"
int DisplayMakePNG(uint8_t *, uint32_t, uint32_t, uint8_t **, uint32_t *,
uint32_t *, uint32_t *, uint8_t) DUMMY(-1)
/* ErrorInfo.cpp */
#include "VBox/com/ErrorInfo.h"
com::ProgressErrorInfo::ProgressErrorInfo(IProgress*) DUMMY()
/* EventImpl.cpp */
#include "EventImpl.h"
HRESULT VBoxEventDesc::init(IEventSource* aSource, VBoxEventType_T aType, ...) TRACE(S_OK)
HRESULT VBoxEventDesc::reinit(VBoxEventType_T aType, ...) TRACE(S_OK)
/* initterm.cpp */
#include "VBox/com/com.h"
HRESULT com::Initialize(bool fGui) TRACE(S_OK)
HRESULT com::Shutdown() DUMMY(E_FAIL)
/* ProgressProxyImpl.cpp */
#include "ProgressProxyImpl.h"
STDMETHODIMP ProgressProxy::Cancel() DUMMY(E_FAIL)
void ProgressProxy::clearOtherProgressObjectInternal(bool fEarly) DUMMY()
STDMETHODIMP ProgressProxy::COMGETTER(Cancelable)(BOOL *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(Percent)(ULONG *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(TimeRemaining)(LONG *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(Completed)(BOOL *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(Canceled)(BOOL *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(ResultCode)(LONG *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(Operation)(ULONG *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(OperationDescription)(BSTR *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(OperationPercent)(ULONG *) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMSETTER(Timeout)(ULONG) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::COMGETTER(Timeout)(ULONG *) DUMMY(E_FAIL)
void ProgressProxy::copyProgressInfo(IProgress *pOtherProgress, bool fEarly) DUMMY()
HRESULT ProgressProxy::FinalConstruct() DUMMY(E_FAIL)
void ProgressProxy::FinalRelease() DUMMY()
HRESULT ProgressProxy::init(VirtualBox*, IUnknown*, unsigned short const*,
bool) DUMMY(E_FAIL)
HRESULT ProgressProxy::init(VirtualBox*, void*, unsigned short const*, bool,
unsigned int, unsigned short const*, unsigned int,
unsigned int) DUMMY(E_FAIL)
HRESULT ProgressProxy::notifyComplete(HRESULT) DUMMY(E_FAIL)
HRESULT ProgressProxy::notifyComplete(HRESULT, GUID const&, char const*,
char const*, ...) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::SetCurrentOperationProgress(ULONG aPercent) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::SetNextOperation(IN_BSTR, ULONG) DUMMY(E_FAIL)
bool ProgressProxy::setOtherProgressObject(IProgress*) DUMMY(false)
void ProgressProxy::uninit() DUMMY()
STDMETHODIMP ProgressProxy::WaitForCompletion(LONG aTimeout) DUMMY(E_FAIL)
STDMETHODIMP ProgressProxy::WaitForOperationCompletion(ULONG, LONG) DUMMY(E_FAIL)
/* SharedFolderImpl.cpp */
#include "SharedFolderImpl.h"
HRESULT SharedFolder::init(Console*, com::Utf8Str const&, com::Utf8Str const&,
bool, bool, bool) DUMMY(E_FAIL)
/* USBFilter.cpp */
#include "VBox/usbfilter.h"
USBFILTERMATCH USBFilterGetMatchingMethod(PCUSBFILTER, USBFILTERIDX) DUMMY(USBFILTERMATCH_INVALID)
int USBFilterGetNum(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx) DUMMY(-1)
const char * USBFilterGetString(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx) DUMMY(nullptr)
void USBFilterInit(PUSBFILTER pFilter, USBFILTERTYPE enmType) DUMMY()
bool USBFilterIsMethodNumeric(USBFILTERMATCH enmMatchingMethod) DUMMY(false)
bool USBFilterIsMethodString(USBFILTERMATCH enmMatchingMethod) DUMMY(false)
bool USBFilterIsNumericField(USBFILTERIDX enmFieldIdx) DUMMY(false)
bool USBFilterIsStringField(USBFILTERIDX enmFieldIdx) DUMMY(false)
bool USBFilterMatch(PCUSBFILTER pFilter, PCUSBFILTER pDevice) DUMMY(false)
int USBFilterSetIgnore(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx) DUMMY(-1)
int USBFilterSetNumExact(PUSBFILTER, USBFILTERIDX, uint16_t, bool) DUMMY(-1)
int USBFilterSetNumExpression(PUSBFILTER, USBFILTERIDX, const char *, bool) DUMMY(-1)
int USBFilterSetStringExact(PUSBFILTER, USBFILTERIDX, const char *, bool) DUMMY(-1)
int USBFilterSetStringPattern(PUSBFILTER, USBFILTERIDX, const char *, bool) DUMMY(-1)
int USBFilterSetStringExact(PUSBFILTER, USBFILTERIDX, const char *, bool,
bool) DUMMY(-1)
/* USBProxyService.cpp */
#include "USBProxyService.h"
HRESULT USBProxyService::autoCaptureDevicesForVM(SessionMachine *) DUMMY(E_FAIL)
HRESULT USBProxyService::captureDeviceForVM(SessionMachine *, IN_GUID,
com::Utf8Str const&) DUMMY(E_FAIL)
HRESULT USBProxyService::detachAllDevicesFromVM(SessionMachine*, bool, bool) DUMMY(E_FAIL)
HRESULT USBProxyService::detachDeviceFromVM(SessionMachine*, IN_GUID, bool) DUMMY(E_FAIL)

View File

@ -0,0 +1,38 @@
#include <base/log.h>
#include "VirtualBoxImpl.h"
#include "VBox/com/MultiResult.h"
#include "dummy/macros.h"
static bool debug = false;
HRESULT VirtualBoxBase::setError(HRESULT aResultCode, const char *pcsz, ...)
{
va_list list;
va_start(list, pcsz);
Genode::error(this->getComponentName(), " : ", Utf8Str(pcsz, list).c_str());
va_end(list);
TRACE(aResultCode);
}
HRESULT VirtualBox::createAppliance(ComPtr<IAppliance> &aAppliance) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::setErrorBoth(HRESULT, int) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::setErrorBoth(HRESULT, int, const char *, ...) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::setErrorVrc(int) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::setErrorVrc(int, char const*, ...) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::setErrorNoLog(HRESULT, const char *, ...) DUMMY(E_FAIL)
void VirtualBoxBase::clearError() TRACE()
HRESULT VirtualBoxBase::setError(HRESULT aResultCode) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::setError(const com::ErrorInfo &ei) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::handleUnexpectedExceptions(VirtualBoxBase *const,
RT_SRC_POS_DECL) TRACE(E_FAIL)
HRESULT VirtualBoxBase::setErrorInternal(HRESULT, GUID const&, char const*,
com::Utf8Str, bool, bool) DUMMY(E_FAIL)
HRESULT VirtualBoxBase::initializeComForThread(void) TRACE(S_OK)
void VirtualBoxBase::uninitializeComForThread(void) TRACE()

View File

@ -0,0 +1,225 @@
/*
* \brief Virtualbox framebuffer implementation for Genode
* \author Alexander Boettcher
* \date 2013-10-16
*/
/*
* Copyright (C) 2013-2014 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 <nitpicker_session/nitpicker_session.h>
#undef Framebuffer
#include <os/texture_rgb565.h>
#include <os/texture_rgb888.h>
#include <os/dither_painter.h>
/* VirtualBox includes */
#include "Global.h"
#include "VirtualBoxBase.h"
class Genodefb :
VBOX_SCRIPTABLE_IMPL(IFramebuffer)
{
private:
Fb_Genode::Connection _fb;
/* The mode matching the currently attached dataspace */
Fb_Genode::Mode _fb_mode;
/* The mode at the time when the mode change signal was received */
Fb_Genode::Mode _next_fb_mode;
/*
* 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;
void _clear_screen()
{
size_t const num_pixels = _fb_mode.width() * _virtual_fb_mode.height();
memset(_fb_base, 0, num_pixels * _fb_mode.bytes_per_pixel());
_fb.refresh(0, 0, _virtual_fb_mode.width(), _virtual_fb_mode.height());
}
public:
Genodefb ()
:
_fb_mode(_fb.mode()),
_next_fb_mode(_fb_mode),
_virtual_fb_mode(_fb_mode),
_fb_base(Genode::env()->rm_session()->attach(_fb.dataspace()))
{
int rc = RTCritSectInit(&_fb_lock);
Assert(rc == VINF_SUCCESS);
}
/* Return the next mode of the framebuffer */
int w() const { return _next_fb_mode.width(); }
int h() const { return _next_fb_mode.height(); }
void mode_sigh(Genode::Signal_context_capability sigh)
{
_fb.mode_sigh(sigh);
}
void update_mode()
{
Lock();
_next_fb_mode = _fb.mode();
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();
bool ok = (w <= (ULONG)_next_fb_mode.width()) &&
(h <= (ULONG)_next_fb_mode.height());
if (ok) {
Genode::log("fb resize : [", screen, "] ",
_virtual_fb_mode.width(), "x",
_virtual_fb_mode.height(), " -> ",
w, "x", h);
if ((w < (ULONG)_next_fb_mode.width()) ||
(h < (ULONG)_next_fb_mode.height())) {
/* clear the old content around the new, smaller area. */
_clear_screen();
}
_fb_mode = _next_fb_mode;
_virtual_fb_mode = Fb_Genode::Mode(w, h, Fb_Genode::Mode::RGB565);
Genode::env()->rm_session()->detach(_fb_base);
_fb_base = Genode::env()->rm_session()->attach(_fb.dataspace());
result = S_OK;
} else
Genode::log("fb resize : [", screen, "] ",
_virtual_fb_mode.width(), "x",
_virtual_fb_mode.height(), " -> ",
w, "x", h, " ignored");
Unlock();
return result;
}
STDMETHODIMP COMGETTER(Capabilities)(ComSafeArrayOut(FramebufferCapabilities_T, enmCapabilities)) override
{
if (ComSafeArrayOutIsNull(enmCapabilities))
return E_POINTER;
com::SafeArray<FramebufferCapabilities_T> caps;
caps.resize(1);
caps[0] = FramebufferCapabilities_UpdateImage;
//caps[0] = FramebufferCapabilities_VHWA;
caps.detachTo(ComSafeArrayOutArg(enmCapabilities));
return S_OK;
}
STDMETHODIMP COMGETTER(HeightReduction) (ULONG *reduce) override
{
if (!reduce)
return E_POINTER;
*reduce = 0;
return S_OK;
}
STDMETHODIMP NotifyUpdateImage(PRUint32 o_x, PRUint32 o_y,
PRUint32 width, PRUint32 height,
PRUint32 imageSize,
PRUint8 *image) override
{
Nitpicker::Area area_fb = Nitpicker::Area(_fb_mode.width(),
_fb_mode.height());
Nitpicker::Area area_vm = Nitpicker::Area(width, height);
using namespace Genode;
typedef Pixel_rgb888 Pixel_src;
typedef Pixel_rgb565 Pixel_dst;
Texture<Pixel_src> texture((Pixel_src *)image, nullptr, area_vm);
Surface<Pixel_dst> surface((Pixel_dst *)_fb_base, area_fb);
Dither_painter::paint(surface, texture, Surface_base::Point(o_x, o_y));
_fb.refresh(o_x, o_y, area_vm.w(), area_vm.h());
return S_OK;
}
STDMETHODIMP COMGETTER(Overlay) (IFramebufferOverlay **) override {
return E_NOTIMPL; }
STDMETHODIMP COMGETTER(WinId) (PRInt64 *winId) override {
return E_NOTIMPL; }
STDMETHODIMP VideoModeSupported(ULONG, ULONG, ULONG, BOOL *) override {
return E_NOTIMPL; }
STDMETHODIMP Notify3DEvent(PRUint32, PRUint32, PRUint8 *) override {
return E_NOTIMPL; }
STDMETHODIMP ProcessVHWACommand(BYTE *pCommand) override {
return E_NOTIMPL; }
STDMETHODIMP GetVisibleRegion(BYTE *, ULONG, ULONG *) override {
return E_NOTIMPL; }
STDMETHODIMP SetVisibleRegion(BYTE *, ULONG) override {
return E_NOTIMPL; }
STDMETHODIMP COMGETTER(PixelFormat) (ULONG *format) override {
return E_NOTIMPL; }
HRESULT NotifyUpdate(ULONG x, ULONG y, ULONG w, ULONG h) override {
return E_NOTIMPL; }
STDMETHODIMP COMGETTER(BitsPerPixel)(ULONG *bits) override {
return E_NOTIMPL; }
STDMETHODIMP COMGETTER(BytesPerLine)(ULONG *line) override {
return E_NOTIMPL; }
STDMETHODIMP COMGETTER(Width)(ULONG *width) override {
return E_NOTIMPL; }
STDMETHODIMP COMGETTER(Height)(ULONG *height) override {
return E_NOTIMPL; }
};

View File

@ -0,0 +1,256 @@
/*
* \brief Port of VirtualBox to Genode
* \author Norman Feske
* \author Alexander Boettcher
* \date 2013-08-20
*/
/*
* Copyright (C) 2013-2014 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <os/config.h>
/* Virtualbox includes */
#include <iprt/initterm.h>
#include <iprt/assert.h>
#include <iprt/err.h>
#include <VBox/com/com.h>
#include <VBox/vmm/vmapi.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 "console.h"
#include "fb.h"
static char c_vbox_file[128];
static char c_vbox_vmname[128];
/**
* xpcom style memory allocation
*/
void * nsMemory::Alloc(size_t size)
{
return new char[size];
}
void nsMemory::Free(void* ptr)
{
Assert(ptr);
delete [] reinterpret_cast<char *>(ptr);
}
void *nsMemory::Realloc(void* ptr, size_t size)
{
Assert(!"not implemented");
return nullptr;
}
void * nsMemory::Clone(const void*, size_t)
{
Assert(!"not implemented");
return nullptr;
}
/**
* Other stuff
*/
int com::GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen, bool fCreateDir)
{
AssertReturn(aDir, VERR_INVALID_POINTER);
AssertReturn(aDirLen > 1, VERR_BUFFER_OVERFLOW);
memcpy(aDir, "/", 1);
aDir[1] = 0;
return VINF_SUCCESS;
}
extern "C"
RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
{
return com::GetVBoxUserHomeDirectory(pszPath, cchPath);
}
extern "C" VirtualBox * genode_global_vbox_pointer;
VirtualBox * genode_global_vbox_pointer = nullptr;
HRESULT setupmachine()
{
HRESULT rc;
static com::Utf8Str vm_config(c_vbox_file);
static com::Utf8Str vm_name(c_vbox_vmname);
/* Machine object */
ComObjPtr<Machine> machine;
rc = machine.createObject();
if (FAILED(rc))
return rc;
/* Virtualbox object */
ComObjPtr<VirtualBox> virtualbox;
rc = virtualbox.createObject();
if (FAILED(rc))
return rc;
/*
* Used in src-client/ConsoleImpl.cpp, which constructs Progress objects,
* which requires the only-one pointer to VirtualBox object
*/
genode_global_vbox_pointer = virtualbox;
rc = machine->initFromSettings(virtualbox, vm_config, nullptr);
if (FAILED(rc))
return rc;
rc = virtualbox->RegisterMachine(machine);
if (FAILED(rc))
return rc;
// open a session
ComObjPtr<Session> session;
rc = session.createObject();
if (FAILED(rc))
return rc;
rc = machine->LockMachine(session, LockType_VM);
if (FAILED(rc))
return rc;
/* Validate configured memory of vbox file and Genode config */
ULONG memory_vbox;
rc = machine->COMGETTER(MemorySize)(&memory_vbox);
if (FAILED(rc))
return rc;
/* request max available memory */
size_t memory_genode = Genode::env()->ram_session()->avail() >> 20;
size_t memory_vmm = 28;
if (memory_vbox + memory_vmm > memory_genode) {
using Genode::error;
error("Configured memory ", memory_vmm, " MB (vbox file) is insufficient.");
error(memory_genode, " MB (1) - ",
memory_vmm, " MB (2) = ",
memory_genode - memory_vmm, " MB (3)");
error("(1) available memory based defined by Genode config");
error("(2) minimum memory required for VBox VMM");
error("(3) maximal available memory to VM");
return E_FAIL;
}
/* Console object */
ComPtr<IConsole> gConsole;
rc = session->COMGETTER(Console)(gConsole.asOutParam());
/* handle input of Genode and forward it to VMM layer */
ComPtr<GenodeConsole> genodeConsole = gConsole;
RTLogPrintf("genodeConsole = %p\n", genodeConsole);
genodeConsole->init_clipboard();
/* Display object */
ComPtr<IDisplay> display;
rc = gConsole->COMGETTER(Display)(display.asOutParam());
if (FAILED(rc))
return rc;
ULONG cMonitors = 1;
rc = machine->COMGETTER(MonitorCount)(&cMonitors);
if (FAILED(rc))
return rc;
static Bstr gaFramebufferId[64];
unsigned uScreenId;
for (uScreenId = 0; uScreenId < cMonitors; uScreenId++)
{
Genodefb *fb = new Genodefb();
HRESULT rc = display->AttachFramebuffer(uScreenId, fb, gaFramebufferId[uScreenId].asOutParam());
if (FAILED(rc))
return rc;
}
/* Power up the VMM */
ComPtr <IProgress> progress;
rc = gConsole->PowerUp(progress.asOutParam());
if (FAILED(rc))
return rc;
/* wait until VM is up */
MachineState_T machineState = MachineState_Null;
do {
if (machineState != MachineState_Null)
RTThreadSleep(1000);
rc = machine->COMGETTER(State)(&machineState);
} while (machineState == MachineState_Starting);
if (rc != S_OK || (machineState != MachineState_Running))
return E_FAIL;
/* request mouse object */
static ComPtr<IMouse> gMouse;
rc = gConsole->COMGETTER(Mouse)(gMouse.asOutParam());
if (FAILED(rc))
return rc;
Assert (&*gMouse);
/* request keyboard object */
ComPtr<IKeyboard> gKeyboard;
rc = gConsole->COMGETTER(Keyboard)(gKeyboard.asOutParam());
if (FAILED(rc))
return rc;
Assert (&*gKeyboard);
genodeConsole->event_loop(gKeyboard, gMouse);
Assert(!"return not expected");
return E_FAIL;
}
int main(int argc, char **argv)
{
try {
using namespace Genode;
Xml_node node = config()->xml_node();
Xml_node::Attribute vbox_file = node.attribute("vbox_file");
vbox_file.value(c_vbox_file, sizeof(c_vbox_file));
Xml_node::Attribute vm_name = node.attribute("vm_name");
vm_name.value(c_vbox_vmname, sizeof(c_vbox_vmname));
} catch (...) {
Genode::error("missing attributes in configuration, minimum requirements: ");
Genode::error(" <config vbox_file=\"...\" vm_name=\"...\">" );
throw;
}
int rc = RTR3InitExe(argc, &argv, 0);
if (RT_FAILURE(rc))
return -1;
HRESULT hrc = setupmachine();
if (FAILED(hrc)) {
Genode::error("startup of VMM failed - reason ", hrc, " '",
RTErrCOMGet(hrc)->pszMsgFull, "' - exiting ...");
return -2;
}
Genode::error("VMM exiting ...");
return 0;
}

View File

@ -0,0 +1,208 @@
/*
* \brief VirtualBox hardware-acceleration manager
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013 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 "HMInternal.h" /* enable access to hm.s.* */
#include <VBox/vmm/hm.h>
#include <VBox/vmm/vm.h>
/* Genode's VirtualBox includes */
#include "sup.h"
enum { VERBOSE_HM = false };
static bool enabled_hm = true;
static bool enable_pae_nx = false;
static bool enable_64bit = false;
VMMR3DECL(int) HMR3Init(PVM pVM)
{
PCFGMNODE pCfgHM = CFGMR3GetChild(CFGMR3GetRoot(pVM), "HM/");
/* check whether to stay for non-paged modi in recompiler */
int rc = CFGMR3QueryBoolDef(pCfgHM, "EnableUX",
&pVM->hm.s.vmx.fAllowUnrestricted, true);
AssertRCReturn(rc, rc);
/* check whether to enable pae and nx bit - in 64bit host mode */
rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "EnablePAE", &enable_pae_nx,
false);
AssertRCReturn(rc, rc);
/* check whether to enable long-mode bit - in 64bit host mode */
rc = CFGMR3QueryBoolDef(pCfgHM, "64bitEnabled", &enable_64bit, false);
AssertRCReturn(rc, rc);
/*
* We always set the fHMEnabled flag. Otherwise, the EM won't
* consult us for taking scheduling decisions. The actual switch to
* HW accelerated mode is still dependent on the result of the
* HMR3CanExecuteGuest function.
*/
pVM->fHMEnabled = true;
for (VMCPUID i = 0; i < pVM->cCpus; i++)
pVM->aCpus[i].hm.s.fActive = false;
pVM->hm.s.fNestedPaging = true;
#if HC_ARCH_BITS == 64
PGMSetLargePageUsage(pVM, true);
#endif
return VINF_SUCCESS;
}
VMMR3_INT_DECL(int) HMR3Term(PVM pVM)
{
return VINF_SUCCESS;
}
VMMR3_INT_DECL(int) HMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
{
enabled_hm = pVM->hm.s.svm.fSupported || pVM->hm.s.vmx.fSupported;
if (!enabled_hm || enmWhat != VMINITCOMPLETED_RING0)
return VINF_SUCCESS;
int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HM_SETUP_VM, 0, NULL);
if (rc == VINF_SUCCESS) {
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SEP);
/* nova kernel supports solely on 64bit the following features */
if (sizeof(void *) > 4 && enable_pae_nx) {
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
}
if (sizeof(void *) > 4 && enable_64bit) {
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL);
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
}
}
return rc;
}
VMMDECL(bool) HMIsEnabledNotMacro(PVM pVM)
{
return pVM->fHMEnabled;
}
VMMR3DECL(bool) HMR3IsVmxPreemptionTimerUsed(PVM pVM)
{
if (VERBOSE_HM)
Genode::log(__func__, "called");
return false;
}
VMMR3DECL(bool) HMR3IsActive(PVMCPU pVCpu)
{
return pVCpu->hm.s.fActive;
}
VMM_INT_DECL(bool) HMIsLongModeAllowed(PVM pVM)
{
return HMIsEnabled(pVM) && pVM->hm.s.fAllow64BitGuests;
}
VMMR3DECL(bool) HMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx)
{
if (pVM->hm.s.vmx.fAllowUnrestricted)
return false;
return !CPUMIsGuestInPagedProtectedModeEx(pCtx);
}
VMMR3DECL(bool) HMR3IsEventPending(PVMCPU pVCpu)
{
return false;
}
VMMR3DECL(bool) HMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx)
{
if (!enabled_hm)
return false;
PVMCPU pVCpu = VMMGetCpu(pVM);
if (pVM->hm.s.vmx.fAllowUnrestricted) {
pVCpu->hm.s.fActive = true;
} else
/* enable H/W acceleration in protected and paged mode only */
pVCpu->hm.s.fActive = CPUMIsGuestInPagedProtectedModeEx(pCtx);
return pVCpu->hm.s.fActive;
}
VMM_INT_DECL(int) HMFlushTLB(PVMCPU pVCpu) {
return VINF_SUCCESS;
}
VMM_INT_DECL(bool) HMAreNestedPagingAndFullGuestExecEnabled(PVM pVM)
{
return HMIsEnabled(pVM)
&& ( (pVM->hm.s.vmx.fSupported && pVM->hm.s.vmx.fAllowUnrestricted)
|| pVM->hm.s.svm.fSupported);
}
VMMR3_INT_DECL(void) HMR3ResetCpu(PVMCPU pVCpu)
{
pVCpu->hm.s.fActive = false;
}
VMM_INT_DECL(bool) HMIsNestedPagingActive(PVM pVM)
{
return HMIsEnabled(pVM);
}
/* VMM/VMMAll/HMAll.cpp */
VMM_INT_DECL(PGMMODE) HMGetShwPagingMode(PVM pVM)
{
Assert(HMIsNestedPagingActive(pVM));
if (pVM->hm.s.svm.fSupported)
return PGMMODE_NESTED;
// Assert(pVM->hm.s.vmx.fSupported);
return PGMMODE_EPT;
}
VMMR3_INT_DECL(void) HMR3PagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode)
{
}
VMM_INT_DECL(int) HMFlushTLBOnAllVCpus(PVM pVM)
{
if (VERBOSE_HM)
Genode::log(__func__, "called");
return VINF_SUCCESS;
}
VBOXSTRICTRC HMR3RestartPendingIOInstr(PVM, PVMCPU, PCPUMCTX) {
return VERR_NOT_FOUND; }

View File

@ -0,0 +1,474 @@
/*
* \brief VirtualBox memory manager (MMR3)
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <util/string.h>
#include <rm_session/connection.h>
#include <os/attached_ram_dataspace.h>
/* VirtualBox includes */
#include <VBox/vmm/mm.h>
#include <VBox/vmm/cfgm.h>
#include <VBox/err.h>
#include <VBox/vmm/gmm.h>
#include <VBox/vmm/vm.h>
#include <VBox/vmm/pgm.h>
#include <iprt/err.h>
#include <iprt/mem.h>
#include <iprt/string.h>
/* libc memory allocator */
#include <libc_mem_alloc.h>
#include "util.h"
#include "mm.h"
enum { VERBOSE_MM = false };
static struct {
Sub_rm_connection * conn;
Libc::Mem_alloc_impl * heap;
} memory_regions [MM_TAG_HM + 1];
static Libc::Mem_alloc * heap_by_mmtag(MMTAG enmTag)
{
enum { REGION_SIZE = 4096 * 4096 };
static Genode::Lock memory_init_lock;
Assert(enmTag < sizeof(memory_regions) / sizeof(memory_regions[0]));
if (memory_regions[enmTag].conn)
return memory_regions[enmTag].heap;
Genode::Lock::Guard guard(memory_init_lock);
if (memory_regions[enmTag].conn)
return memory_regions[enmTag].heap;
memory_regions[enmTag].conn = new Sub_rm_connection(REGION_SIZE);
memory_regions[enmTag].heap = new Libc::Mem_alloc_impl(memory_regions[enmTag].conn);
return memory_regions[enmTag].heap;
}
static Libc::Mem_alloc * heap_by_pointer(void * pv)
{
for (unsigned i = 0; i < sizeof(memory_regions) / sizeof(memory_regions[0]); i++) {
if (!memory_regions[i].heap)
continue;
if (memory_regions[i].conn->contains(pv))
return memory_regions[i].heap;
}
return nullptr;
}
int MMR3Init(PVM) { return VINF_SUCCESS; }
int MMR3Term(PVM) { return VINF_SUCCESS; }
int MMR3InitUVM(PUVM) { return VINF_SUCCESS; }
void MMR3TermUVM(PUVM) { }
void *MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
{
return heap_by_mmtag(enmTag)->alloc(cbSize, Genode::log2(RTMEM_ALIGNMENT));
}
/**
* Return alignment to be used for allocations of given tag
*/
static unsigned align_by_mmtag(MMTAG enmTag)
{
switch (enmTag) {
case MM_TAG_PGM:
case MM_TAG_PDM_DEVICE:
case MM_TAG_PDM_DEVICE_USER:
case MM_TAG_VMM:
case MM_TAG_CPUM_CTX:
return 12;
case MM_TAG_CPUM_CPUID:
case MM_TAG_CPUM_MSRS:
return Genode::log2(32);
case MM_TAG_PGM_PHYS:
return Genode::log2(16);
default:
return Genode::log2(RTMEM_ALIGNMENT);
}
}
/**
* Round allocation size for a given tag
*/
static size_t round_size_by_mmtag(MMTAG enmTag, size_t cb)
{
return Genode::align_addr(cb, align_by_mmtag(enmTag));
}
void *MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize)
{
size_t const rounded_size = round_size_by_mmtag(enmTag, cbSize);
return heap_by_mmtag(enmTag)->alloc(rounded_size, align_by_mmtag(enmTag));
}
void *MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize)
{
void * const ret = MMR3HeapAlloc(pVM, enmTag, cbSize);
if (ret)
Genode::memset(ret, 0, cbSize);
return ret;
}
void * MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize) {
void * const ret = MMR3HeapAllocU(pUVM, enmTag, cbSize);
if (ret)
Genode::memset(ret, 0, cbSize);
return ret;
}
void * MMR3UkHeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize, PRTR0PTR pR0Ptr)
{
if (pR0Ptr)
*pR0Ptr = NIL_RTR0PTR;
return MMR3HeapAllocZ(pVM, enmTag, cbSize);
}
int MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
{
*ppv = MMR3HeapAllocZ(pVM, enmTag, cbSize);
return VINF_SUCCESS;
}
int MMR3HyperInitFinalize(PVM)
{
Genode::log(__func__, "called");
return VINF_SUCCESS;
}
int MMR3HyperSetGuard(PVM, void* ptr, size_t, bool)
{
Genode::log(__func__, "called ", ptr);
return VINF_SUCCESS;
}
int MMR3HyperAllocOnceNoRel(PVM pVM, size_t cb, unsigned uAlignment,
MMTAG enmTag, void **ppv)
{
AssertRelease(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0));
unsigned const align_log2 = uAlignment ? Genode::log2(uAlignment)
: align_by_mmtag(enmTag);
size_t const rounded_size = round_size_by_mmtag(enmTag, cb);
void *ret = heap_by_mmtag(enmTag)->alloc(rounded_size, align_log2);
if (ret)
Genode::memset(ret, 0, cb);
*ppv = ret;
return VINF_SUCCESS;
}
int MMR3HyperAllocOnceNoRelEx(PVM pVM, size_t cb, uint32_t uAlignment,
MMTAG enmTag, uint32_t fFlags, void **ppv)
{
AssertRelease(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0));
return MMR3HyperAllocOnceNoRel(pVM, cb, uAlignment, enmTag, ppv);
}
int MMHyperAlloc(PVM pVM, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv)
{
if (!(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0)))
Genode::error(__func__, " ", (int)enmTag, " ", uAlignment, " ", (int)MM_TAG_PGM);
AssertRelease(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0));
*ppv = MMR3HeapAllocZ(pVM, enmTag, cb);
return VINF_SUCCESS;
}
int MMHyperFree(PVM pVM, void *pv)
{
MMR3HeapFree(pv);
return VINF_SUCCESS;
}
int MMHyperDupMem(PVM pVM, const void *pvSrc, size_t cb,
unsigned uAlignment, MMTAG enmTag, void **ppv)
{
int rc = MMHyperAlloc(pVM, cb, uAlignment, enmTag, ppv);
if (RT_SUCCESS(rc))
memcpy(*ppv, pvSrc, cb);
return rc;
}
bool MMHyperIsInsideArea(PVM, RTGCPTR ptr)
{
Genode::log(__func__, "called");
return false;
}
void MMR3HeapFree(void *pv)
{
Libc::Mem_alloc *heap = heap_by_pointer(pv);
Assert(heap);
heap->free(pv);
}
uint64_t MMR3PhysGetRamSize(PVM pVM)
{
/* when called from REMR3Init, it is expected to return 0 */
return 0;
}
int MMR3HyperMapHCPhys(PVM pVM, void *pvR3, RTR0PTR pvR0, RTHCPHYS HCPhys,
size_t cb, const char *pszDesc, PRTGCPTR pGCPtr)
{
static_assert(sizeof(*pGCPtr) == sizeof(HCPhys) , "pointer transformation bug");
*pGCPtr = (RTGCPTR)HCPhys;
return VINF_SUCCESS;
}
int MMR3HyperReserve(PVM pVM, unsigned cb, const char *pszDesc, PRTGCPTR pGCPtr)
{
if (VERBOSE_MM)
Genode::log("MMR3HyperReserve: cb=", Genode::Hex(cb), ", "
"pszDesc=", pszDesc);
return VINF_SUCCESS;
}
VMMR3DECL(int) MMR3IncreaseBaseReservation(PVM pVM, uint64_t cAddBasePages)
{
return VINF_SUCCESS;
}
int MMR3AdjustFixedReservation(PVM, int32_t, const char *pszDesc)
{
if (VERBOSE_MM)
Genode::log(__func__, " called for '", pszDesc, "'");
return VINF_SUCCESS;
}
int MMR3HyperMapMMIO2(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
RTGCPHYS off, RTGCPHYS cb, const char *pszDesc,
PRTRCPTR pRCPtr)
{
if (VERBOSE_MM)
Genode::log("pszDesc=", pszDesc, " iRegion=", iRegion, " "
"off=", Genode::Hex(off), " cb=", Genode::Hex(cb));
return VINF_SUCCESS;
}
/*
* Based on 'VBox/VMM/VMMR3/MM.cpp'
*/
int MMR3InitPaging(PVM pVM)
{
/*
* Query the CFGM values.
*/
int rc;
PCFGMNODE pMMCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "MM");
if (!pMMCfg)
{
rc = CFGMR3InsertNode(CFGMR3GetRoot(pVM), "MM", &pMMCfg);
AssertRCReturn(rc, rc);
}
/** @cfgm{RamSize, uint64_t, 0, 16TB, 0}
* Specifies the size of the base RAM that is to be set up during
* VM initialization.
*/
uint64_t cbRam;
rc = CFGMR3QueryU64(CFGMR3GetRoot(pVM), "RamSize", &cbRam);
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
cbRam = 0;
else
AssertMsgRCReturn(rc, ("Configuration error: Failed to query integer \"RamSize\", rc=%Rrc.\n", rc), rc);
cbRam &= X86_PTE_PAE_PG_MASK;
/** @cfgm{RamHoleSize, uint32_t, 0, 4032MB, 512MB}
* Specifies the size of the memory hole. The memory hole is used
* to avoid mapping RAM to the range normally used for PCI memory regions.
* Must be aligned on a 4MB boundary. */
uint32_t cbRamHole;
rc = CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
uint64_t const offRamHole = _4G - cbRamHole;
/*
* Make the initial memory reservation with GMM.
*/
LogFlow(("GMMR3INitialReservation missing\n"));
/*
* If RamSize is 0 we're done now.
*/
if (cbRam < PAGE_SIZE)
{
Log(("MM: No RAM configured\n"));
return VINF_SUCCESS;
}
/*
* Setup the base ram (PGM).
*/
if (cbRam > offRamHole)
{
rc = PGMR3PhysRegisterRam(pVM, 0, offRamHole, "Base RAM");
if (RT_SUCCESS(rc))
rc = PGMR3PhysRegisterRam(pVM, _4G, cbRam - offRamHole, "Above 4GB Base RAM");
}
else
rc = PGMR3PhysRegisterRam(pVM, 0, RT_MIN(cbRam, offRamHole), "Base RAM");
LogFlow(("MMR3InitPaging: returns %Rrc\n", rc));
return rc;
}
char * MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *string)
{
if (!string)
return NULL;
size_t len = strlen(string) + 1;
char *dup = reinterpret_cast<char *>(MMR3HeapAllocU(pUVM, enmTag, len));
if (dup)
memcpy(dup, string, len);
return dup;
}
char * MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *string)
{
Assert(pVM);
Assert(pVM->pUVM);
return MMR3HeapStrDupU(pVM->pUVM, enmTag, string);
}
char * MMR3HeapAPrintfVU(PUVM pUVM, MMTAG enmTag, const char *pszFormat, va_list va)
{
/*
* The lazy bird way.
*/
char *psz;
int cch = RTStrAPrintfV(&psz, pszFormat, va);
if (cch < 0)
return NULL;
Assert(psz[cch] == '\0');
char *pszRet = (char *)MMR3HeapAllocU(pUVM, enmTag, cch + 1);
if (pszRet)
memcpy(pszRet, psz, cch + 1);
RTStrFree(psz);
Genode::log(__func__, " called ", Genode::Cstring(pszRet), " ", Genode::Cstring(pszFormat));
return pszRet;
}
VMMR3DECL(RTHCPHYS) MMR3HyperHCVirt2HCPhys(PVM pVM, void *pvR3) {
return (RTHCPHYS)(uintptr_t)pvR3; }
VMMDECL(RTHCPHYS) MMPage2Phys(PVM pVM, void *pvPage) {
return (RTHCPHYS)(uintptr_t)pvPage; }
VMMR3DECL(void *) MMR3PageAlloc(PVM pVM)
{
using Genode::Attached_ram_dataspace;
Attached_ram_dataspace * ds = new Attached_ram_dataspace(Genode::env()->ram_session(), 4096);
return ds->local_addr<void>();
}
VMMR3DECL(void *) MMR3PageAllocLow(PVM pVM) { return MMR3PageAlloc(pVM); }
int MMR3ReserveHandyPages(PVM pVM, uint32_t cHandyPages)
{
Genode::log(__func__, " called");
return VINF_SUCCESS;
}
VMMDECL(void *) MMHyperHeapOffsetToPtr(PVM pVM, uint32_t offHeap)
{
if (sizeof(void*) == 8) {
uint64_t ptr = offHeap;
return reinterpret_cast<void *>(ptr);
}
return reinterpret_cast<void *>(offHeap);
}
VMMDECL(uint32_t) MMHyperHeapPtrToOffset(PVM pVM, void *pv)
{
Genode::addr_t offset = reinterpret_cast<Genode::addr_t>(pv);
Assert (reinterpret_cast<void *>(offset) == pv);
return offset;
}
extern "C" {
char * MMR3HeapAPrintf(PVM pVM, MMTAG enmTag, const char *pszFormat, ...)
{
va_list va;
va_start(va, pszFormat);
char *psz = MMR3HeapAPrintfVU(pVM->pUVM, enmTag, pszFormat, va);
va_end(va);
return psz;
}
}

View File

@ -0,0 +1,79 @@
/*
* \brief VirtualBox memory manager (MMR3)
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013-2016 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <rm_session/rm_session.h>
#include <rm_session/connection.h>
#include <region_map/client.h>
#include <util/retry.h>
/**
* Sub rm_session as backend for the Libc::Mem_alloc implementation.
* Purpose is that memory allocation by vbox of a specific type (MMTYP) are
* all located within a 2G virtual window. Reason is that virtualbox converts
* internally pointers at several places in base + offset, whereby offset is
* a int32_t type.
*/
class Sub_rm_connection : private Genode::Rm_connection,
public Genode::Region_map_client
{
private:
Genode::addr_t const _offset;
Genode::size_t const _size;
public:
Sub_rm_connection(Genode::size_t size)
:
Genode::Region_map_client(Rm_connection::create(size)),
_offset(Genode::env()->rm_session()->attach(dataspace())),
_size(size)
{ }
Local_addr attach(Genode::Dataspace_capability ds,
Genode::size_t size = 0, Genode::off_t offset = 0,
bool use_local_addr = false,
Local_addr local_addr = (void *)0,
bool executable = false) override
{
Local_addr addr = Genode::retry<Rm_session::Out_of_metadata>(
[&] () {
return Region_map_client::attach(ds, size, offset,
use_local_addr,
local_addr,
executable); },
[&] () {
char quota[] = "ram_quota=8192";
Genode::env()->parent()->upgrade(this->cap(), quota);
});
Genode::addr_t new_addr = addr;
new_addr += _offset;
return Local_addr(new_addr);
}
bool contains(void * ptr) const
{
Genode::addr_t addr = reinterpret_cast<Genode::addr_t>(ptr);
return (_offset <= addr && addr < _offset + _size);
}
bool contains(Genode::addr_t addr) const {
return (_offset <= addr && addr < _offset + _size); }
Genode::addr_t local_addr(Genode::addr_t addr) const {
return _offset + addr; }
};

View File

@ -0,0 +1,51 @@
--- a/src/app/virtualbox/src/VBox/VMM/VMMR3/DBGF.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMR3/DBGF.cpp
@@ -152,6 +152,7 @@
rc = dbgfR3RegInit(pUVM);
if (RT_SUCCESS(rc))
{
+#if 0
rc = dbgfR3AsInit(pUVM);
if (RT_SUCCESS(rc))
{
@@ -164,7 +165,9 @@
rc = dbgfR3PlugInInit(pUVM);
if (RT_SUCCESS(rc))
{
+#endif
return VINF_SUCCESS;
+#if 0
}
dbgfR3OSTerm(pUVM);
}
@@ -172,6 +175,7 @@
dbgfR3AsTerm(pUVM);
}
dbgfR3RegTerm(pUVM);
+#endif
}
dbgfR3TraceTerm(pVM);
}
@@ -190,10 +194,11 @@
VMMR3_INT_DECL(int) DBGFR3Term(PVM pVM)
{
PUVM pUVM = pVM->pUVM;
-
+#if 0
dbgfR3PlugInTerm(pUVM);
dbgfR3OSTerm(pUVM);
dbgfR3AsTerm(pUVM);
+#endif
dbgfR3RegTerm(pUVM);
dbgfR3TraceTerm(pVM);
dbgfR3InfoTerm(pUVM);
@@ -310,7 +315,9 @@
VMMR3_INT_DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta)
{
dbgfR3TraceRelocate(pVM);
+#if 0
dbgfR3AsRelocate(pVM->pUVM, offDelta);
+#endif
}

View File

@ -0,0 +1,137 @@
--- a/src/app/virtualbox/src/VBox/VMM/VMMR3/PGM.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMR3/PGM.cpp
@@ -2159,7 +2159,7 @@
VMMR3DECL(int) PGMR3InitFinalize(PVM pVM)
{
int rc;
-
+#if 0
/*
* Reserve space for the dynamic mappings.
* Initialize the dynamic mapping pages with dummy pages to simply the cache.
@@ -2180,6 +2180,7 @@
rc = PGMMap(pVM, pVM->pgm.s.pbDynPageMapBaseGC + offDynMap, HCPhysDummy, PAGE_SIZE, 0);
AssertRCReturn(rc, rc);
}
+#endif /* #if 0 */
/*
* Determine the max physical address width (MAXPHYADDR) and apply it to
@@ -2377,7 +2378,7 @@
* (One or more of them have changed, that's why we're here.)
*/
pVM->pgm.s.pMappingsRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pMappingsR3);
- for (PPGMMAPPING pCur = pVM->pgm.s.pMappingsR3; pCur->pNextR3; pCur = pCur->pNextR3)
+ for (PPGMMAPPING pCur = pVM->pgm.s.pMappingsR3; pCur && pCur->pNextR3; pCur = pCur->pNextR3)
pCur->pNextRC = MMHyperR3ToRC(pVM, pCur->pNextR3);
/* Relocate GC addresses of Page Tables. */
@@ -2390,6 +2391,7 @@
}
}
+#if 0
/*
* Dynamic page mapping area.
*/
@@ -2412,6 +2414,7 @@
paPages[iPage].uPte.pPae += offDelta;
}
}
+#endif /* #if 0 */
/*
* The Zero page.
--- a/src/app/virtualbox/src/VBox/VMM/VMMAll/PGMAllHandler.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMAll/PGMAllHandler.cpp
@@ -263,6 +263,9 @@
* @param pCur The physical handler.
* @param pRam The RAM range.
*/
+#include <base/log.h>
+extern "C" bool PGMUnmapMemoryGenode(void *, size_t size);
+
static int pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs(PVM pVM, PPGMPHYSHANDLER pCur, PPGMRAMRANGE pRam)
{
/*
@@ -298,6 +301,13 @@
i++;
}
+ if (pRam->pvR3 != 0) {
+ if (pCur->cPages != pRam->cb / 4096)
+ Genode::warning("dubious ? phys=", Genode::Hex(pRam->GCPhys));
+
+ PGMUnmapMemoryGenode(pRam->pvR3, pRam->cb);
+ }
+
if (fFlushTLBs)
{
PGM_INVL_ALL_VCPU_TLBS(pVM);
--- a/src/app/virtualbox/include/VBox/vmm/vm.h
+++ b/src/app/virtualbox/include/VBox/vmm/vm.h
@@ -1011,7 +1011,7 @@
#ifdef ___PGMInternal_h
struct PGM s;
#endif
- uint8_t padding[4096*2+6080]; /* multiple of 64 */
+ uint8_t padding[4096*4 + 6080]; /* multiple of 64 */
} pgm;
/** HM part. */
--- a/src/app/virtualbox/include/VBox/param.h
+++ b/src/app/virtualbox/include/VBox/param.h
@@ -92,13 +92,13 @@
*/
/** The number of handy pages.
* This should be a power of two. */
-#define PGM_HANDY_PAGES 128
+#define PGM_HANDY_PAGES 512
/** The threshold at which allocation of more handy pages is flagged. */
-#define PGM_HANDY_PAGES_SET_FF 32
+#define PGM_HANDY_PAGES_SET_FF 0
/** The threshold at which we will allocate more when in ring-3.
* This is must be smaller than both PGM_HANDY_PAGES_SET_FF and
* PGM_HANDY_PAGES_MIN. */
-#define PGM_HANDY_PAGES_R3_ALLOC 8
+#define PGM_HANDY_PAGES_R3_ALLOC 0
/** The threshold at which we will allocate more when in ring-0 or raw mode.
* The idea is that we should never go below this threshold while in ring-0 or
* raw mode because of PGM_HANDY_PAGES_RZ_TO_R3. However, should this happen and
@@ -107,16 +107,16 @@
*
* This is must be smaller than both PGM_HANDY_PAGES_SET_FF and
* PGM_HANDY_PAGES_MIN. */
-#define PGM_HANDY_PAGES_RZ_ALLOC 8
+#define PGM_HANDY_PAGES_RZ_ALLOC 0
/** The threshold at which we force return to R3 ASAP.
* The idea is that this should be large enough to get out of any code and up to
* the main EM loop when we are out of memory.
* This must be less or equal to PGM_HANDY_PAGES_MIN. */
-#define PGM_HANDY_PAGES_RZ_TO_R3 24
+#define PGM_HANDY_PAGES_RZ_TO_R3 0
/** The minimum number of handy pages (after allocation).
* This must be greater or equal to PGM_HANDY_PAGES_SET_FF.
* Another name would be PGM_HANDY_PAGES_EXTRA_RESERVATION or _PARANOIA. :-) */
-#define PGM_HANDY_PAGES_MIN 32
+#define PGM_HANDY_PAGES_MIN 0
/** @} */
--- a/src/app/virtualbox/src/VBox/VMM/VMMR3/PGMPhys.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMR3/PGMPhys.cpp
@@ -4518,6 +4518,14 @@
if (pVM->pgm.s.aHandyPages[i].idPage == idPage)
{
pVM->pgm.s.aHandyPages[i].idPage = NIL_GMM_PAGEID;
+ /**
+ * Required to avoid assertion during reboot of a VM on Genode.
+ * could be it solves the
+ * "todo re-test this later. Appeared to be a PGM init bug." in
+ * src/VBox/VMM/VMMR0/GMMR0.cpp of VBox 5.0.12
+ * - todo: send email to vbox mailing list about that
+ */
+ pVM->pgm.s.aHandyPages[i].HCPhysGCPhys = NIL_RTHCPHYS;
break;
}
if (pVM->pgm.s.aHandyPages[i].idSharedPage == idPage)

View File

@ -0,0 +1,9 @@
vbox_inc.patch
vbox_main.patch
vga_vbva.patch
vmmdev.patch
usb.patch
tm_smp.patch
vmm.patch
iem_wip.patch
dbg.patch

View File

@ -0,0 +1,35 @@
tm_smp.patch
diff --git a/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp b/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
index c3bc22d..33d705c 100644
--- a/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
@@ -210,7 +210,7 @@ VMM_INT_DECL(int) TMR3Init(PVM pVM)
pVM->tm.s.paTimerQueuesRC = MMHyperR3ToRC(pVM, pv);
pVM->tm.s.offVM = RT_OFFSETOF(VM, tm.s);
- pVM->tm.s.idTimerCpu = pVM->cCpus - 1; /* The last CPU. */
+ pVM->tm.s.idTimerCpu = 0; /* The first CPU. */
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].enmClock = TMCLOCK_VIRTUAL;
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].u64Expire = INT64_MAX;
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL_SYNC].enmClock = TMCLOCK_VIRTUAL_SYNC;
@@ -1901,10 +1901,18 @@ static DECLCALLBACK(void) tmR3TimerCallback(PRTTIMER pTimer, void *pvUser, uint6
AssertCompile(TMCLOCK_MAX == 4);
STAM_COUNTER_INC(&pVM->tm.s.StatTimerCallback);
+ if (VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER)) {
#ifdef DEBUG_Sander /* very annoying, keep it private. */
- if (VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER))
Log(("tmR3TimerCallback: timer event still pending!!\n"));
#endif
+ /*
+ * The VMCPU_FF_TIMER flag could have been set by a non-destination
+ * EMT thread without waking the destination EMT thread.
+ */
+ VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
+ return;
+ }
+
if ( !VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER)
&& ( pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL_SYNC].offSchedule /** @todo FIXME - reconsider offSchedule as a reason for running the timer queues. */
|| pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].offSchedule

View File

@ -0,0 +1,118 @@
usb.patch
diff --git a/src/app/virtualbox/src/VBox/Devices/USB/USBProxyDevice.cpp b/src/app/virtualbox/src/VBox/Devices/USB/USBProxyDevice.cpp
index a51bc36..bed42e8 100644
--- a/src/app/virtualbox/src/VBox/Devices/USB/USBProxyDevice.cpp
+++ b/src/app/virtualbox/src/VBox/Devices/USB/USBProxyDevice.cpp
@@ -843,10 +843,14 @@ static DECLCALLBACK(int) usbProxyConstruct(PPDMUSBINS pUsbIns, int iInstance, PC
/*
* Select backend and open the device.
*/
+
+ return PDMUSB_SET_ERROR(pUsbIns, VERR_NOT_SUPPORTED, N_("USBProxy: not supported on Genode"));
+#if 0
if (!fRemote)
pThis->pOps = &g_USBProxyDeviceHost;
else
pThis->pOps = &g_USBProxyDeviceVRDP;
+#endif /* if 0 */
pThis->pvInstanceDataR3 = RTMemAllocZ(pThis->pOps->cbBackend);
if (!pThis->pvInstanceDataR3)
diff --git a/src/app/virtualbox/src/VBox/Devices/USB/VUSBDevice.cpp b/src/app/virtualbox/src/VBox/Devices/USB/VUSBDevice.cpp
index 4790fcb..d649ad6 100644
--- a/src/app/virtualbox/src/VBox/Devices/USB/VUSBDevice.cpp
+++ b/src/app/virtualbox/src/VBox/Devices/USB/VUSBDevice.cpp
@@ -1134,7 +1143,7 @@ static DECLCALLBACK(int) vusbDevUrbIoThread(RTTHREAD hThread, void *pvUser)
vusbUrbDoReapAsyncDev(pDev, RT_INDEFINITE_WAIT);
/* Process any URBs waiting to be cancelled first. */
- int rc = RTReqQueueProcess(pDev->hReqQueueSync, 0); /* Don't wait if there is nothing to do. */
+ int rc = RTReqQueueProcess(pDev->hReqQueueSync, pDev->enmState == VUSB_DEVICE_STATE_RESET ? 5 : 0); /* if in reset state (takes 10ms) sleep a bit - otherwise this thread consumes in this loop a lot of cpu time */
Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
}
diff --git a/src/app/virtualbox/src/VBox/Devices/build/VBoxDD.cpp b/src/app/virtualbox/src/VBox/Devices/build/VBoxDD.cpp
index 3173a36..8105987 100644
--- a/src/app/virtualbox/src/VBox/Devices/build/VBoxDD.cpp
+++ b/src/app/virtualbox/src/VBox/Devices/build/VBoxDD.cpp
@@ -39,6 +39,7 @@ const void *g_apvVBoxDDDependencies[] =
NULL,
};
+#if 0
/**
* Register builtin devices.
@@ -329,6 +330,7 @@ extern "C" DECLEXPORT(int) VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_
return VINF_SUCCESS;
}
+#endif /* if 0 */
/**
* Register builtin USB device.
diff --git a/src/app/virtualbox/src/VBox/Main/include/Matching.h b/src/app/virtualbox/src/VBox/Main/include/Matching.h
index 2f01f69..9b13e37 100644
--- a/src/app/virtualbox/src/VBox/Main/include/Matching.h
+++ b/src/app/virtualbox/src/VBox/Main/include/Matching.h
@@ -291,10 +291,12 @@ public:
return mValueAny || mValue == aValue;
}
+#if 0
bool isMatch (const BOOL aValue) const
{
return isMatch (bool (aValue == TRUE));
}
+#endif /* if 0 */
private:
--- a/src/app/virtualbox/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/app/virtualbox/src/VBox/Main/src-server/MachineImpl.cpp
@@ -13219,6 +13225,7 @@
{
LogFlowThisFunc(("\n"));
+ return S_OK;
#ifdef VBOX_WITH_USB
HRESULT rc = mUSBDeviceFilters->i_notifyProxy(true /* aInsertFilters */);
AssertComRC(rc);
@@ -13246,6 +13253,7 @@
{
LogFlowThisFunc(("\n"));
+ return S_OK;
#ifdef VBOX_WITH_USB
HRESULT rc = mUSBDeviceFilters->i_notifyProxy(false /* aInsertFilters */);
AssertComRC(rc);
diff --git a/src/app/virtualbox/src/VBox/Main/src-server/USBDeviceFiltersImpl.cpp b/src/app/virtualbox/src/VBox/Main/src-server/USBDeviceFiltersImpl.cpp
index 09b42f5..c179ca6 100644
--- a/src/app/virtualbox/src/VBox/Main/src-server/USBDeviceFiltersImpl.cpp
+++ b/src/app/virtualbox/src/VBox/Main/src-server/USBDeviceFiltersImpl.cpp
@@ -1037,13 +1037,10 @@ HRESULT USBDeviceFilters::notifyProxy(bool aInsertFilters)
LogFlowThisFunc(("aInsertFilters=%RTbool\n", aInsertFilters));
AutoCaller autoCaller(this);
- AssertComRCReturn(autoCaller.rc(), false);
+ AssertComRCReturnRC(autoCaller.rc());
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
- USBProxyService *pProxySvc = m->pHost->i_usbProxyService();
- AssertReturn(pProxySvc, E_FAIL);
-
DeviceFilterList::const_iterator it = m->llDeviceFilters->begin();
while (it != m->llDeviceFilters->end())
{
@@ -1054,6 +1051,9 @@ HRESULT USBDeviceFilters::notifyProxy(bool aInsertFilters)
&& pFilter->getData().mRemote.isMatch(false) /* and if the filter is NOT remote */
)
{
+ USBProxyService *pProxySvc = m->pHost->i_usbProxyService();
+ AssertReturn(pProxySvc, E_FAIL);
+
if (aInsertFilters)
{
AssertReturn(pFilter->getId() == NULL, E_FAIL);

View File

@ -0,0 +1,47 @@
vbox_inc.patch
diff --git a/src/app/virtualbox/include/VBox/com/ErrorInfo.h b/src/app/virtualbox/include/VBox/com/ErrorInfo.h
index 869b998..c6adf70 100644
--- a/src/app/virtualbox/include/VBox/com/ErrorInfo.h
+++ b/src/app/virtualbox/include/VBox/com/ErrorInfo.h
@@ -31,8 +31,8 @@
* @{
*/
-COM_STRUCT_OR_CLASS(IProgress);
-COM_STRUCT_OR_CLASS(IVirtualBoxErrorInfo);
+//COM_STRUCT_OR_CLASS(IProgress);
+//COM_STRUCT_OR_CLASS(IVirtualBoxErrorInfo);
namespace com
{
diff --git a/src/app/virtualbox/include/VBox/com/array.h b/src/app/virtualbox/include/VBox/com/array.h
index 77f9d60..dcbad41 100644
--- a/src/app/virtualbox/include/VBox/com/array.h
+++ b/src/app/virtualbox/include/VBox/com/array.h
@@ -219,10 +219,10 @@ struct SafeArrayTraits
protected:
/** Initializes memory for aElem. */
- static void Init(T &aElem) { aElem = 0; }
+ static void Init(T &aElem) { /*aElem = 0; */ }
/** Initializes memory occupied by aElem. */
- static void Uninit(T &aElem) { aElem = 0; }
+ static void Uninit(T &aElem) { /* aElem = 0; */ }
/** Creates a deep copy of aFrom and stores it in aTo. */
static void Copy(const T &aFrom, T &aTo) { aTo = aFrom; }
diff --git a/src/app/virtualbox/include/VBox/com/string.h b/src/app/virtualbox/include/VBox/com/string.h
index 263dc40..768c336 100644
--- a/src/app/virtualbox/include/VBox/com/string.h
+++ b/src/app/virtualbox/include/VBox/com/string.h
@@ -247,7 +247,7 @@ public:
* returns a pointer to a global variable containing an empty BSTR with a proper zero
* length prefix so that Windows is happy.
*/
- CBSTR raw() const
+ BSTR raw() const
{
if (m_bstr)
return m_bstr;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
vga_vbva.patch
diff --git a/src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp b/src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
index 28ab4a8..1cc8e6b 100644
--- a/src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
+++ b/src/app/virtualbox/src/VBox/Devices/Graphics/DevVGA_VBVA.cpp
@@ -546,7 +546,8 @@ static int vbvaDisable (unsigned uScreenId, PVGASTATE pVGAState, VBVACONTEXT *pC
pVGAState->fGuestCaps = 0;
pVGAState->pDrv->pfnVBVAGuestCapabilityUpdate(pVGAState->pDrv, pVGAState->fGuestCaps);
}
- pVGAState->pDrv->pfnVBVADisable(pVGAState->pDrv, uScreenId);
+ if (pVGAState->pDrv->pfnVBVADisable)
+ pVGAState->pDrv->pfnVBVADisable(pVGAState->pDrv, uScreenId);
return VINF_SUCCESS;
}

View File

@ -0,0 +1,17 @@
--- a/src/app/virtualbox/src/VBox/VMM/VMMR3/EM.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMR3/EM.cpp
@@ -2211,10 +2227,11 @@
*/
case VINF_EM_RESCHEDULE_REM:
Assert(!pVM->em.s.fIemExecutesAll || pVCpu->em.s.enmState != EMSTATE_IEM);
- if (HMIsEnabled(pVM))
+ if (HMIsEnabled(pVM) &&
+ !(VM_FF_IS_PENDING(pVM, VM_FF_ALL_REM_MASK) || VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_ALL_REM_MASK)))
{
- Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_REM: %d -> %d (EMSTATE_IEM_THEN_REM)\n",
- enmOldState, EMSTATE_IEM_THEN_REM));
+ Log2(("EMR3ExecuteVM: VINF_EM_RESCHEDULE_REM: %d, %d -> %d (EMSTATE_IEM_THEN_REM)\n",
+ pVCpu->em.s.enmState, enmOldState, EMSTATE_IEM_THEN_REM));
if (pVCpu->em.s.enmState != EMSTATE_IEM_THEN_REM)
{
pVCpu->em.s.enmState = EMSTATE_IEM_THEN_REM;

View File

@ -0,0 +1,46 @@
vmmdev.patch
diff --git a/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDev.cpp b/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDev.cpp
index 8ce46a8..a6b84b0 100644
--- a/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDev.cpp
+++ b/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDev.cpp
@@ -2179,6 +2179,10 @@ static int vmmdevReqHandler_GetPageSharingStatus(PVMMDEV pThis, VMMDevRequestHea
("%u\n", pReq->header.size), VERR_INVALID_PARAMETER);
pReq->fEnabled = false;
+
+ if (!pThis || !pThis->pDrv || !pThis->pDrv->pfnIsPageFusionEnabled)
+ return VINF_SUCCESS;
+
int rc = pThis->pDrv->pfnIsPageFusionEnabled(pThis->pDrv, &pReq->fEnabled);
if (RT_FAILURE(rc))
pReq->fEnabled = false;
@@ -2404,7 +2408,6 @@ static int vmmdevReqDispatcher(PVMMDEV pThis, VMMDevRequestHeader *pReqHdr, RTGC
pReqHdr->rc = vmmdevReqHandler_HGCMCall(pThis, pReqHdr, GCPhysReqHdr);
*pfDelayedUnlock = true;
break;
-#endif /* VBOX_WITH_HGCM */
case VMMDevReq_HGCMCancel:
pReqHdr->rc = vmmdevReqHandler_HGCMCancel(pThis, pReqHdr, GCPhysReqHdr);
@@ -2414,6 +2417,7 @@ static int vmmdevReqDispatcher(PVMMDEV pThis, VMMDevRequestHeader *pReqHdr, RTGC
case VMMDevReq_HGCMCancel2:
pReqHdr->rc = vmmdevReqHandler_HGCMCancel2(pThis, pReqHdr);
break;
+#endif /* VBOX_WITH_HGCM */
case VMMDevReq_VideoAccelEnable:
pReqHdr->rc = vmmdevReqHandler_VideoAccelEnable(pThis, pReqHdr);
diff --git a/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp b/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
index d495599..21dfada 100644
--- a/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
+++ b/src/app/virtualbox/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
@@ -19,7 +19,7 @@
/*********************************************************************************************************************************
* Header Files *
*********************************************************************************************************************************/
-#define LOG_GROUP LOG_GROUP_DEV_VMM
+#define LOG_GROUP LOG_GROUP_HGCM
#include <iprt/alloc.h>
#include <iprt/asm.h>
#include <iprt/assert.h>

View File

@ -0,0 +1,58 @@
/*
* \brief VirtualBox page manager (PGM)
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <util/string.h>
/* VirtualBox includes */
#include <VBox/vmm/pgm.h>
static bool verbose = false;
int PGMMap(PVM pVM, RTGCUINTPTR GCPtr, RTHCPHYS HCPhys, uint32_t cbPages,
unsigned fFlags)
{
/* GCPtr steams from the #unimplemented# MMR3HyperReserve call, which
* returns a value - seems to be used solely in RC mode */
if (verbose)
Genode::log(__func__, ": GCPtr=", Genode::Hex(GCPtr), " "
"HCPHys=", Genode::Hex(HCPhys), " "
"cbPages=", Genode::Hex(cbPages), " , "
"flags=", Genode::Hex(fFlags), " "
"rip=", __builtin_return_address(0));
return VINF_SUCCESS;
}
int PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags)
{
if (verbose)
Genode::log(__func__, ": GCPtr=", Genode::Hex(GCPtr), " "
"cb=", Genode::Hex(cb), " "
"flags=", Genode::Hex(fFlags));
return VINF_SUCCESS;
}
int PGMR3MappingsSize(PVM pVM, uint32_t *pcb)
{
Genode::log(__func__, ": not implemented ", __builtin_return_address(0));
*pcb = 0;
return 0;
}

View File

@ -0,0 +1,209 @@
/*
* \brief Genode/Nova specific PGM code to resolve EPT faults
* \author Alexander Boettcher
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include "vcpu.h"
#include "PGMInline.h"
enum { VERBOSE_PGM = false };
int Vcpu_handler::map_memory(RTGCPHYS GCPhys, size_t cbWrite,
RTGCUINT vbox_fault_reason,
Genode::Flexpage_iterator &fli, bool &writeable)
{
using Genode::Flexpage_iterator;
using Genode::addr_t;
PVM pVM = _current_vm;
PVMCPU pVCpu = _current_vcpu;
_ept_fault_addr_type = PGMPAGETYPE_INVALID;
/* DON'T USE normal printf in this function - corrupts unsaved UTCB !!! */
PPGMRAMRANGE pRam = pgmPhysGetRangeAtOrAbove(pVM, GCPhys);
if (!pRam)
return VERR_PGM_DYNMAP_FAILED;
/* XXX pgmLock/pgmUnlock XXX */
RTGCPHYS off = GCPhys - pRam->GCPhys;
if (off >= pRam->cb)
return VERR_PGM_DYNMAP_FAILED;
unsigned iPage = off >> PAGE_SHIFT;
PPGMPAGE pPage = &pRam->aPages[iPage];
_ept_fault_addr_type = PGM_PAGE_GET_TYPE(pPage);
if (PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage) ||
PGM_PAGE_IS_SPECIAL_ALIAS_MMIO(pPage) ||
PGM_PAGE_IS_ZERO(pPage)) {
if (PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_MMIO &&
!PGM_PAGE_IS_ZERO(pPage)) {
Vmm::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " ",
PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage), " ",
PGM_PAGE_IS_SPECIAL_ALIAS_MMIO(pPage), " ",
PGM_PAGE_IS_ZERO(pPage), " "
" vbox_fault_reason=", Genode::Hex(vbox_fault_reason));
Vmm::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " "
"host=", Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), " "
"type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " "
"writeable=", writeable, " "
"state=", Genode::Hex(PGM_PAGE_GET_STATE(pPage)));
}
return VERR_PGM_DYNMAP_FAILED;
}
if (!PGM_PAGE_IS_ALLOCATED(pPage))
Vmm::log("unknown page state ", Genode::Hex(PGM_PAGE_GET_STATE(pPage)),
" GCPhys=", Genode::Hex(GCPhys));
Assert(PGM_PAGE_IS_ALLOCATED(pPage));
if (PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_RAM &&
PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_MMIO2 &&
PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_ROM)
{
if (VERBOSE_PGM)
Vmm::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " "
"vbox_fault_reason=", Genode::Hex(vbox_fault_reason), " "
"host=", Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), " "
"type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " "
"state=", Genode::Hex(PGM_PAGE_GET_STATE(pPage)));
return VERR_PGM_DYNMAP_FAILED;
}
Assert(!PGM_PAGE_IS_ZERO(pPage));
/* write fault on a ROM region */
if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM &&
vbox_fault_reason & VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE) {
Vmm::warning(__func__, " - write fault on ROM region!? gp=",
Genode::Hex(GCPhys));
return VERR_PGM_DYNMAP_FAILED;
}
/* nothing should be mapped - otherwise we get endless overmap loops */
Assert(!(vbox_fault_reason & VMX_EXIT_QUALIFICATION_EPT_ENTRY_PRESENT));
writeable = PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_ROM;
PPGMPHYSHANDLER handler = pgmHandlerPhysicalLookup(pVM, GCPhys);
if (VERBOSE_PGM && PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2 &&
!handler)
Vmm::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " ",
"type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " "
"state=", Genode::Hex(PGM_PAGE_GET_STATE(pPage)), " "
"- MMIO2 w/o handler");
if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2 && handler) {
PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(pVM, handler)->CTX_SUFF(pfnHandler);
if (!pfnHandler) {
Vmm::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " "
"type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)));
return VERR_PGM_DYNMAP_FAILED;
}
void *pvUser = handler->CTX_SUFF(pvUser);
if (!pvUser) {
Vmm::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " "
"type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)));
return VERR_PGM_DYNMAP_FAILED;
}
PGMACCESSTYPE access_type = (vbox_fault_reason & VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE) ? PGMACCESSTYPE_WRITE : PGMACCESSTYPE_READ;
VBOXSTRICTRC rcStrict = pfnHandler(pVM, pVCpu, GCPhys, nullptr, nullptr, 0, access_type, PGMACCESSORIGIN_HM, pvUser);
if (rcStrict != VINF_PGM_HANDLER_DO_DEFAULT) {
Vmm::log(__LINE__, " nodefault GCPhys=", Genode::Hex(GCPhys), " "
"type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " "
"pfnHandler=", pfnHandler);
return VERR_PGM_DYNMAP_FAILED;
}
}
/*
Vmm::printf("0x%lx->0x%lx type=%u state=0x%u pde=%u iPage=%u range_size=0x%lx pages=%u\n",
PGM_PAGE_GET_HCPHYS(pPage), GCPhys, PGM_PAGE_GET_TYPE(pPage),
PGM_PAGE_GET_STATE(pPage), PGM_PAGE_GET_PDE_TYPE(pPage),
iPage, pRam->cb, pRam->cb >> PAGE_SHIFT);
*/
if (PGM_PAGE_GET_PDE_TYPE(pPage) == PGM_PAGE_PDE_TYPE_PDE) {
Genode::addr_t const max_pages = pRam->cb >> PAGE_SHIFT;
Genode::addr_t const superpage_pages = (1 << 21) / 4096;
Genode::addr_t mask = (1 << 21) - 1;
Genode::addr_t super_gcphys = GCPhys & ~mask;
RTGCPHYS max_off = super_gcphys - pRam->GCPhys;
Assert (max_off < pRam->cb);
Genode::addr_t super_hcphys = PGM_PAGE_GET_HCPHYS(pPage) & ~mask;
unsigned const i_s = max_off >> PAGE_SHIFT;
Assert (i_s + superpage_pages <= max_pages);
if (VERBOSE_PGM)
Vmm::log(Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), "->",
Genode::Hex(GCPhys), " - iPage ", iPage, " [",
i_s, ",", i_s + superpage_pages, ")", " "
"range_size=", Genode::Hex(pRam->cb));
/* paranoia sanity checks */
for (Genode::addr_t i = i_s; i < i_s + superpage_pages; i++) {
PPGMPAGE page = &pRam->aPages[i];
Genode::addr_t gcpage = pRam->GCPhys + i << PAGE_SHIFT;
Assert(super_hcphys == (PGM_PAGE_GET_HCPHYS(page) & ~mask));
Assert(super_gcphys == (gcpage & ~mask));
Assert(PGM_PAGE_GET_PDE_TYPE(page) == PGM_PAGE_PDE_TYPE_PDE);
Assert(PGM_PAGE_GET_TYPE(page) == PGM_PAGE_GET_TYPE(pPage));
Assert(PGM_PAGE_GET_STATE(page) == PGM_PAGE_GET_STATE(pPage));
}
fli = Flexpage_iterator(super_hcphys, 1 << 21,
super_gcphys, 1 << 21, super_gcphys);
} else
fli = Flexpage_iterator(PGM_PAGE_GET_HCPHYS(pPage), 4096,
GCPhys & ~0xFFFUL, 4096, GCPhys & ~0xFFFUL);
return VINF_SUCCESS;
}
Genode::uint64_t * Vcpu_handler::pdpte_map(VM *pVM, RTGCPHYS cr3)
{
PPGMRAMRANGE pRam = pgmPhysGetRangeAtOrAbove(pVM, cr3);
Assert (pRam);
/* XXX pgmLock/pgmUnlock XXX */
RTGCPHYS off = cr3 - pRam->GCPhys;
Assert (off < pRam->cb);
unsigned iPage = off >> PAGE_SHIFT;
PPGMPAGE pPage = &pRam->aPages[iPage];
/*
Vmm::printf("%u gcphys=0x%lx host=0x%lx type=%lx state=0x%lx\n", __LINE__,
cr3, PGM_PAGE_GET_HCPHYS(pPage), PGM_PAGE_GET_TYPE(pPage), PGM_PAGE_GET_STATE(pPage));
*/
Genode::uint64_t *pdpte = reinterpret_cast<Genode::uint64_t*>(PGM_PAGE_GET_HCPHYS(pPage) + (cr3 & PAGE_OFFSET_MASK));
Assert(pdpte != 0);
return pdpte;
}

View File

@ -0,0 +1,570 @@
/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \author Norman Feske
* \author Christian Helmuth
*/
/*
* Copyright (C) 2013-2014 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <base/semaphore.h>
#include <util/flex_iterator.h>
#include <rom_session/connection.h>
#include <timer_session/connection.h>
#include <os/attached_rom_dataspace.h>
#include <os/attached_ram_dataspace.h>
#include <trace/timestamp.h>
#include <vmm/vcpu_thread.h>
#include <vmm/vcpu_dispatcher.h>
/* NOVA includes that come with Genode */
#include <nova/syscalls.h>
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "vcpu_svm.h"
#include "vcpu_vmx.h"
/* libc memory allocator */
#include <libc_mem_alloc.h>
#include "mm.h"
extern "C" bool PGMUnmapMemoryGenode(void *, size_t);
/* XXX does not work on 32bit host - since vm memory is from 0 - 4G and
* such large areas can't be attached to a process
* We need several sub_rm areas .... XXX
*/
static Sub_rm_connection vm_memory((sizeof(void *) == 4 ? 2UL : 4UL) * 1024 * 1024 * 1024);
static Genode::List<Vcpu_handler> &vcpu_handler_list()
{
static Genode::List<Vcpu_handler> _inst;
return _inst;
}
static Vcpu_handler *lookup_vcpu_handler(unsigned int cpu_id)
{
for (Vcpu_handler *vcpu_handler = vcpu_handler_list().first();
vcpu_handler;
vcpu_handler = vcpu_handler->next())
if (vcpu_handler->cpu_id() == cpu_id)
return vcpu_handler;
return 0;
}
/* Genode specific function */
static Genode::Attached_rom_dataspace hip_rom("hypervisor_info_page");
void SUPR3QueryHWACCLonGenodeSupport(VM * pVM)
{
try {
Nova::Hip * hip = hip_rom.local_addr<Nova::Hip>();
pVM->hm.s.svm.fSupported = hip->has_feature_svm();
pVM->hm.s.vmx.fSupported = hip->has_feature_vmx();
if (hip->has_feature_svm() || hip->has_feature_vmx()) {
Genode::log("Using ", hip->has_feature_svm() ? "SVM " : "VMX ",
"virtualization extension.");
return;
}
} catch (...) { /* if we get an exception let hardware support off */ }
Genode::warning("No virtualization hardware acceleration available");
}
/* VirtualBox SUPLib interface */
int SUPR3QueryVTxSupported(void) { return VINF_SUCCESS; }
int SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
{
switch (uOperation) {
case SUP_VMMR0_DO_HM_RUN:
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
return vcpu_handler->run_hw(pVMR0);
}
return VERR_INTERNAL_ERROR;
}
int SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages,
PRTR0PTR pR0Ptr, PSUPPAGE paPages)
{
Assert(ppvPages);
Assert(!fFlags);
Genode::log(__func__, " cPages ", cPages, " flags=", Genode::Hex(fFlags),
" r3=", ppvPages, " r0=", pR0Ptr);
using Genode::Attached_ram_dataspace;
Attached_ram_dataspace * ds = new Attached_ram_dataspace(Genode::env()->ram_session(), cPages * 4096); /* XXX PAGE_SIZE ? */
*ppvPages = ds->local_addr<void>();
Genode::log(__func__, " cPages ", cPages, " alloc=", *ppvPages, " done");
if (!paPages)
return VINF_SUCCESS;
for (unsigned iPage = 0; iPage < cPages; iPage++)
{
paPages[iPage].uReserved = 0;
paPages[iPage].Phys = reinterpret_cast<RTHCPHYS>(ds->local_addr<void>()) + iPage * 4096;
}
return VINF_SUCCESS;
}
int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
{
static unsigned long chunkid = 1500;
switch (uOperation) {
case VMMR0_DO_GVMM_CREATE_VM:
genode_VMMR0_DO_GVMM_CREATE_VM(pReqHdr);
return VINF_SUCCESS;
case VMMR0_DO_GVMM_REGISTER_VMCPU:
genode_VMMR0_DO_GVMM_REGISTER_VMCPU(pVMR0, idCpu);
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_HALT:
{
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
/*
char txt_name[32];
Genode::Thread_base::myself()->name(txt_name, sizeof(txt_name));
PINF("%s - halt - rip=%p", txt_name, __builtin_return_address(0));
*/
vcpu_handler->halt();
// PINF("%s - woken up", txt_name);
return VINF_SUCCESS;
}
case VMMR0_DO_GVMM_SCHED_WAKE_UP:
{
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
/*
char txt_name[32];
Genode::Thread_base::myself()->name(txt_name, sizeof(txt_name));
PINF("%s - wakeup - rip=%p", txt_name, __builtin_return_address(0));
*/
vcpu_handler->wake_up();
return VINF_SUCCESS;
}
/* called by 'vmR3HaltGlobal1Halt' */
case VMMR0_DO_GVMM_SCHED_POLL:
return VINF_SUCCESS;
case VMMR0_DO_VMMR0_INIT:
SUPR3QueryHWACCLonGenodeSupport(reinterpret_cast<VM *>(pVMR0));
return VINF_SUCCESS;
case VMMR0_DO_GVMM_DESTROY_VM:
case VMMR0_DO_VMMR0_TERM:
case VMMR0_DO_HM_SETUP_VM:
return VINF_SUCCESS;
case VMMR0_DO_HM_ENABLE:
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_POKE:
{
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
if (vcpu_handler)
vcpu_handler->recall();
return VINF_SUCCESS;
}
case VMMR0_DO_GMM_ALLOCATE_PAGES:
{
static_assert(PGM_HANDY_PAGES * 4096 == GMM_CHUNK_SIZE, "Don't do that - you're going to waste tons of memory");
Assert(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC);
/* XXX VMM/VMMR0/GMMR0.cpp check there XXX */
Genode::log("ALLOCATE_PAGES pReq ", pReqHdr);
PGMMALLOCATEPAGESREQ req = reinterpret_cast<PGMMALLOCATEPAGESREQ>(pReqHdr);
for (unsigned i = 0; i < req->cPages; i++) {
RTHCPHYS guest_addr = req->aPages[i].HCPhysGCPhys;
unsigned long chunkid = (req->aPages[i].HCPhysGCPhys / GMM_CHUNK_SIZE) + 1;
unsigned long pageidx = (req->aPages[i].HCPhysGCPhys % GMM_CHUNK_SIZE) / 4096;
Assert (pageidx <= GMM_PAGEID_IDX_MASK);
Assert (chunkid < 1500 || chunkid > 2047); /* XXX reserved at the moment */
req->aPages[i].idPage = (chunkid << GMM_CHUNKID_SHIFT) | pageidx;
req->aPages[i].HCPhysGCPhys = vm_memory.local_addr(req->aPages[i].HCPhysGCPhys);
Assert(vm_memory.contains(req->aPages[i].HCPhysGCPhys));
Genode::log("cPages ", Genode::Hex(req->cPages), " "
"chunkID=", req->aPages[i].idPage >> GMM_CHUNKID_SHIFT, " "
"pageIDX=", req->aPages[i].idPage & GMM_PAGEID_IDX_MASK, " "
"idPage=", Genode::Hex(req->aPages[i].idPage), " "
"GCPhys=", Genode::Hex(guest_addr), " "
"HCPhys=", Genode::Hex(req->aPages[i].HCPhysGCPhys), " "
"start_vm=", vm_memory.local_addr(0));
}
return VINF_SUCCESS;
}
case VMMR0_DO_GMM_MAP_UNMAP_CHUNK:
{
PGMMMAPUNMAPCHUNKREQ req = reinterpret_cast<PGMMMAPUNMAPCHUNKREQ>(pReqHdr);
Assert(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC);
// PINF("UNMAP_CHUNK map=%u unmap=%u pvR3=%p start", req->idChunkMap, req->idChunkUnmap, req->pvR3);
Assert(req->idChunkUnmap == NIL_GMM_CHUNKID);
Assert(req->idChunkMap != NIL_GMM_CHUNKID);
Genode::Ram_dataspace_capability ds = Genode::env()->ram_session()->alloc(GMM_CHUNK_SIZE);
Genode::addr_t local_addr_offset = (req->idChunkMap - 1) << GMM_CHUNK_SHIFT;
enum { OFFSET_DS = 0, USE_LOCAL_ADDR = true };
Genode::addr_t to = vm_memory.attach(ds, GMM_CHUNK_SIZE, OFFSET_DS,
USE_LOCAL_ADDR, local_addr_offset);
Assert(to == vm_memory.local_addr(local_addr_offset));
req->pvR3 = reinterpret_cast<RTR3PTR>(to);
// PINF("UNMAP_CHUNK map=%u unmap=%u pvR3=%p done", req->idChunkMap, req->idChunkUnmap, req->pvR3);
return VINF_SUCCESS;
}
case VMMR0_DO_GMM_QUERY_MEM_STATS:
{
PGMMMEMSTATSREQ req = reinterpret_cast<PGMMMEMSTATSREQ>(pReqHdr);
req->cAllocPages = 0;
req->cMaxPages = 0;
req->cBalloonedPages = 0;
return VINF_SUCCESS;
}
case VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES:
{
PVM pVM = reinterpret_cast<PVM>(pVMR0);
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - start */
uint32_t iFirst = pVM->pgm.s.cHandyPages;
uint32_t cPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages) - iFirst;
uint32_t cPagesToUpdate = cPages;
uint32_t cPagesToAlloc = cPages;
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - end */
/* based on GMMR0AllocateHandyPages in VMM/VMMR0/GMMR0.cpp - start */
unsigned iPage = 0;
for (; iPage < cPagesToUpdate; iPage++)
{
AssertMsgReturn( ( pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys <= GMM_GCPHYS_LAST
&& !(pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys & PAGE_OFFSET_MASK))
|| pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == NIL_RTHCPHYS
|| pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == GMM_GCPHYS_UNSHAREABLE,
("#%#x: %RHp\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys),
VERR_INVALID_PARAMETER);
AssertMsgReturn( pVM->pgm.s.aHandyPages[iFirst + iPage].idPage <= GMM_PAGEID_LAST
/*|| pVM->pgm.s.aHandyPages[iFirst + iPage].idPage == NIL_GMM_PAGEID*/,
("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idPage), VERR_INVALID_PARAMETER);
AssertMsgReturn( pVM->pgm.s.aHandyPages[iFirst + iPage].idPage <= GMM_PAGEID_LAST
/*|| pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage == NIL_GMM_PAGEID*/,
("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage), VERR_INVALID_PARAMETER);
}
for (; iPage < cPagesToAlloc; iPage++)
{
AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == NIL_RTHCPHYS, ("#%#x: %RHp\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys), VERR_INVALID_PARAMETER);
AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].idPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idPage), VERR_INVALID_PARAMETER);
AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage), VERR_INVALID_PARAMETER);
}
Assert (chunkid >= 1500 && chunkid <= 2047); /* XXX reserved at the moment */
if (cPagesToAlloc != GMM_CHUNK_SIZE / 4096)
Genode::log("special chunkid=", chunkid, " "
"toupdate=", cPagesToUpdate, " "
"toalloc=", cPagesToAlloc, " "
"virt=", Genode::Hex(vm_memory.local_addr(((chunkid - 1) << GMM_CHUNK_SHIFT))));
for (unsigned i = 0; i < cPagesToUpdate; i++) {
if (pVM->pgm.s.aHandyPages[iFirst + i].idPage != NIL_GMM_PAGEID)
{
pVM->pgm.s.aHandyPages[iFirst + i].idPage = NIL_GMM_PAGEID;
pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys = NIL_RTHCPHYS;
}
if (pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage != NIL_GMM_PAGEID)
AssertMsgReturn(false, ("%s %u - not implemented", __func__, __LINE__), VERR_GENERAL_FAILURE);
}
for (unsigned i = 0; i < cPagesToAlloc; i++)
{
Assert(pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys == NIL_RTHCPHYS);
Assert(pVM->pgm.s.aHandyPages[iFirst + i].idPage == NIL_GMM_PAGEID);
Assert(pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage == NIL_GMM_PAGEID);
}
for (unsigned i = 0; i < cPagesToUpdate; i++) {
unsigned reverse = i; //cPagesToUpdate - 1 - i;
Assert (pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys == NIL_RTHCPHYS);
{
pVM->pgm.s.aHandyPages[iFirst + i].idPage = (chunkid << GMM_CHUNKID_SHIFT) | (iFirst + reverse);
pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage = NIL_GMM_PAGEID;
pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys = vm_memory.local_addr(((chunkid - 1) << GMM_CHUNK_SHIFT) | ((iFirst + reverse) * 4096)); /* XXX PAGE_SIZE XXX */
}
}
/* based on GMMR0AllocateHandyPages in VMM/VMMR0/GMMR0.cpp - end */
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - start */
pVM->pgm.s.cHandyPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages);
for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
{
Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID);
Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST);
Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID);
Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS);
Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK));
}
/* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - end */
chunkid ++; /* XXX */
return VINF_SUCCESS;
}
case VMMR0_DO_PGM_ALLOCATE_LARGE_HANDY_PAGE:
{
PVM pVM = reinterpret_cast<PVM>(pVMR0);
Assert(pVM);
Assert(pVM->pgm.s.cLargeHandyPages == 0);
pVM->pgm.s.aLargeHandyPage[0].idPage = (chunkid << GMM_CHUNKID_SHIFT);
pVM->pgm.s.aLargeHandyPage[0].HCPhysGCPhys = vm_memory.local_addr(((chunkid - 1) << GMM_CHUNK_SHIFT));
pVM->pgm.s.cLargeHandyPages = 1;
chunkid ++; /* XXX */
return VINF_SUCCESS;
}
case VMMR0_DO_GMM_BALLOONED_PAGES:
{
/* during VM shutdown - ignore */
return VINF_SUCCESS;
}
case VMMR0_DO_GMM_RESET_SHARED_MODULES:
{
/* during VM shutdown - ignore */
return VINF_SUCCESS;
}
case VMMR0_DO_PGM_FLUSH_HANDY_PAGES:
{
/* during VM shutdown - ignore */
return VINF_SUCCESS;
}
case VMMR0_DO_GMM_FREE_PAGES:
{
if (u64Arg)
return VERR_INVALID_PARAMETER;
PVM pVM = reinterpret_cast<PVM>(pVMR0);
PGMMFREEPAGESREQ pReq = reinterpret_cast<PGMMFREEPAGESREQ>(pReqHdr);
AssertPtrReturn(pVM, VERR_INVALID_POINTER);
AssertPtrReturn(pReq, VERR_INVALID_POINTER);
AssertMsgReturn(pReq->Hdr.cbReq >= RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[0]),
("%#x < %#x\n", pReq->Hdr.cbReq, RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[0])),
VERR_INVALID_PARAMETER);
AssertMsgReturn(pReq->Hdr.cbReq == RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[pReq->cPages]),
("%#x != %#x\n", pReq->Hdr.cbReq, RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[pReq->cPages])),
VERR_INVALID_PARAMETER);
uint32_t cPages = pReq->cPages;
PGMMFREEPAGEDESC paPages = &pReq->aPages[0];
GMMACCOUNT enmAccount = pReq->enmAccount;
AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
AssertMsgReturn(enmAccount > GMMACCOUNT_INVALID && enmAccount < GMMACCOUNT_END, ("%d\n", enmAccount), VERR_INVALID_PARAMETER);
AssertMsgReturn(cPages > 0 && cPages < RT_BIT(32 - PAGE_SHIFT), ("%#x\n", cPages), VERR_INVALID_PARAMETER);
for (unsigned iPage = 0; iPage < cPages; iPage++)
AssertMsgReturn( paPages[iPage].idPage <= GMM_PAGEID_LAST
/*|| paPages[iPage].idPage == NIL_GMM_PAGEID*/,
("#%#x: %#x\n", iPage, paPages[iPage].idPage), VERR_INVALID_PARAMETER);
uint32_t fPage = (paPages[0].idPage >> GMM_CHUNKID_SHIFT);
void * vmm_local = reinterpret_cast<void *>(vm_memory.local_addr((fPage - 1) << GMM_CHUNK_SHIFT));
PGMUnmapMemoryGenode(vmm_local, GMM_CHUNK_SIZE);
uint32_t iPage;
for (iPage = 0; iPage < cPages; iPage++)
{
uint32_t idPage = paPages[iPage].idPage;
if ((idPage >> GMM_CHUNKID_SHIFT) != fPage) {
Genode::log(iPage, " idPage=", Genode::Hex(idPage), " "
"(id=", idPage >> GMM_CHUNKID_SHIFT, " "
"page=%u)", idPage & GMM_PAGEID_IDX_MASK, " "
"vm_memory.local=", Genode::Hex(vm_memory.local_addr((((idPage >>GMM_CHUNKID_SHIFT) - 1) << GMM_CHUNK_SHIFT))));
}
paPages[iPage].idPage = NIL_GMM_PAGEID;
}
return VINF_SUCCESS;
}
default:
Genode::error("SUPR3CallVMMR0Ex: unhandled uOperation ", uOperation,
" ", (int)VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES, " ",
(int)VMMR0_DO_GMM_QUERY_MEM_STATS);
return VERR_GENERAL_FAILURE;
}
}
/**
* Various support stuff - base-nova specific.
*/
uint64_t genode_cpu_hz()
{
static uint64_t cpu_freq = 0;
if (!cpu_freq) {
try {
using namespace Genode;
Rom_connection hip_rom("hypervisor_info_page");
Nova::Hip * const hip = env()->rm_session()->attach(hip_rom.dataspace());
cpu_freq = hip->tsc_freq * 1000;
} catch (...) {
Genode::error("could not read out CPU frequency.");
Genode::Lock lock;
lock.lock();
}
}
return cpu_freq;
}
void genode_update_tsc(void (*update_func)(void), unsigned long update_us)
{
using namespace Genode;
using namespace Nova;
enum { TSC_FACTOR = 1000ULL };
Genode::addr_t sem = Thread::myself()->native_thread().exc_pt_sel + Nova::SM_SEL_EC;
unsigned long tsc_khz = (genode_cpu_hz() / 1000) / TSC_FACTOR;
Trace::Timestamp us_64 = update_us;
for (;;) {
update_func();
Trace::Timestamp now = Trace::timestamp();
/* block until timeout fires or it gets canceled */
unsigned long long tsc_absolute = now + us_64 * tsc_khz;
Genode::uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, tsc_absolute);
if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT)
nova_die();
}
}
bool PGMUnmapMemoryGenode(void * vmm_local, size_t size)
{
Assert(vmm_local);
using namespace Genode;
Flexpage_iterator fli(reinterpret_cast<addr_t>(vmm_local), size, 0, ~0UL, 0);
Flexpage revoke_page = fli.page();
while (revoke_page.valid()) {
Assert(revoke_page.log2_order >= 12);
Assert(!(((1UL << revoke_page.log2_order) - 1) & revoke_page.addr));
using namespace Nova;
Rights const revoke_rwx(true, true, true);
Crd crd = Mem_crd(revoke_page.addr >> 12, revoke_page.log2_order - 12,
revoke_rwx);
revoke(crd, false);
/* request next page(s) to be revoked */
revoke_page = fli.page();
}
return true;
}
extern "C" void pthread_yield(void)
{
Nova::ec_ctrl(Nova::EC_YIELD);
}
void *operator new (Genode::size_t size, int log2_align)
{
static Libc::Mem_alloc_impl heap(Genode::env()->rm_session());
return heap.alloc(size, log2_align);
}
bool create_emt_vcpu(pthread_t * pthread, size_t stack,
const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg,
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location,
unsigned int cpu_id)
{
Nova::Hip * hip = hip_rom.local_addr<Nova::Hip>();
if (!hip->has_feature_vmx() && !hip->has_feature_svm())
return false;
Vcpu_handler *vcpu_handler = 0;
if (hip->has_feature_vmx())
vcpu_handler = new (0x10) Vcpu_handler_vmx(stack, attr, start_routine,
arg, cpu_session, location,
cpu_id);
if (hip->has_feature_svm())
vcpu_handler = new (0x10) Vcpu_handler_svm(stack, attr, start_routine,
arg, cpu_session, location,
cpu_id);
Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf));
vcpu_handler_list().insert(vcpu_handler);
*pthread = vcpu_handler;
return true;
}

View File

@ -0,0 +1,112 @@
/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Norman Feske
* \author Alexander Boettcher
*/
/*
* Copyright (C) 2013-2014 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__SPEC__NOVA__SVM_H_
#define _VIRTUALBOX__SPEC__NOVA__SVM_H_
/* based on HWSVMR0.h - adjusted to Genode/Nova */
#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 = utcb->REG.sel; \
pCtx->REG.ValidSel = utcb->REG.sel; \
pCtx->REG.fFlags = CPUMSELREG_FLAGS_VALID; \
pCtx->REG.u32Limit = utcb->REG.limit; \
pCtx->REG.u64Base = utcb->REG.base; \
pCtx->REG.Attr.u = sel_ar_conv_from_nova(utcb->REG.ar)
static inline bool svm_save_state(Nova::Utcb * utcb, 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); \
utcb->REG.sel = pCtx->REG.Sel; \
utcb->REG.limit = pCtx->REG.u32Limit; \
utcb->REG.base = pCtx->REG.u64Base; \
utcb->REG.ar = sel_ar_conv_to_nova(pCtx->REG.Attr.u)
static inline bool svm_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
#ifdef __x86_64__
utcb->mtd |= Nova::Mtd::EFER;
utcb->efer = pCtx->msrEFER | MSR_K6_EFER_SVME;
/* unimplemented */
if (CPUMIsGuestInLongModeEx(pCtx))
return false;
utcb->efer &= ~MSR_K6_EFER_LME;
#endif
utcb->mtd |= Nova::Mtd::ESDS;
GENODE_WRITE_SELREG(es);
GENODE_WRITE_SELREG(ds);
utcb->mtd |= Nova::Mtd::FSGS;
GENODE_WRITE_SELREG(fs);
GENODE_WRITE_SELREG(gs);
utcb->mtd |= Nova::Mtd::CSSS;
GENODE_WRITE_SELREG(cs);
GENODE_WRITE_SELREG(ss);
/* ldtr */
utcb->mtd |= Nova::Mtd::LDTR;
GENODE_WRITE_SELREG(ldtr);
/* tr */
utcb->mtd |= Nova::Mtd::TR;
GENODE_WRITE_SELREG(tr);
return true;
}
#undef GENODE_WRITE_SELREG
#endif /* _VIRTUALBOX__SPEC__NOVA__SVM_H_ */

View File

@ -0,0 +1,868 @@
/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \author Norman Feske
* \author Christian Helmuth
*/
/*
* Copyright (C) 2013-2016 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__SPEC__NOVA__VCPU_H_
#define _VIRTUALBOX__SPEC__NOVA__VCPU_H_
/* Genode includes */
#include <base/log.h>
#include <base/semaphore.h>
#include <util/flex_iterator.h>
#include <util/touch.h>
#include <rom_session/connection.h>
#include <timer_session/connection.h>
#include <vmm/vcpu_thread.h>
#include <vmm/vcpu_dispatcher.h>
#include <vmm/printf.h>
/* NOVA includes that come with Genode */
#include <nova/syscalls.h>
/* VirtualBox includes */
#include "PGMInternal.h" /* enable access to pgm.s.* */
#include "HMInternal.h" /* enable access to hm.s.* */
#include "CPUMInternal.h" /* enable access to cpum.s.* */
#include <VBox/vmm/vm.h>
#include <VBox/vmm/hm_svm.h>
#include <VBox/err.h>
#include <VBox/vmm/pdmapi.h>
/* Genode's VirtualBox includes */
#include "sup.h"
/* Genode libc pthread binding */
#include "thread.h"
/* LibC includes */
#include <setjmp.h>
#include <VBox/vmm/rem.h>
static bool debug_map_memory = false;
/*
* VirtualBox stores segment attributes in Intel format using a 32-bit
* value. NOVA represents the attributes in packed format using a 16-bit
* value.
*/
static inline Genode::uint16_t sel_ar_conv_to_nova(Genode::uint32_t v)
{
return (v & 0xff) | ((v & 0x1f000) >> 4);
}
static inline Genode::uint32_t sel_ar_conv_from_nova(Genode::uint16_t v)
{
return (v & 0xff) | (((uint32_t )v << 4) & 0x1f000);
}
class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
public Genode::List<Vcpu_handler>::Element
{
private:
X86FXSTATE _guest_fpu_state __attribute__((aligned(0x10)));
X86FXSTATE _emt_fpu_state __attribute__((aligned(0x10)));
Vmm::Vcpu_other_pd _vcpu;
Genode::addr_t _ec_sel;
bool _irq_win;
unsigned int _cpu_id;
Genode::Semaphore _halt_sem;
unsigned int _last_inj_info;
unsigned int _last_inj_error;
void fpu_save(char * data) {
Assert(!(reinterpret_cast<Genode::addr_t>(data) & 0xF));
asm volatile ("fxsave %0" : "=m" (*data));
}
void fpu_load(char * data) {
Assert(!(reinterpret_cast<Genode::addr_t>(data) & 0xF));
asm volatile ("fxrstor %0" : : "m" (*data));
}
enum {
NOVA_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
*/
BLOCKING_BY_STI = 1U << 0,
BLOCKING_BY_MOV_SS = 1U << 1,
ACTIVITY_STATE_ACTIVE = 0U,
INTERRUPT_STATE_NONE = 0U,
};
/*
* 'longjmp()' restores some FPU registers saved by 'setjmp()',
* so we need to save the guest FPU state before calling 'longjmp()'
*/
__attribute__((noreturn)) void _fpu_save_and_longjmp()
{
fpu_save(reinterpret_cast<char *>(&_guest_fpu_state));
longjmp(_env, 1);
}
int map_memory(RTGCPHYS GCPhys,
size_t cbWrite, RTGCUINT vbox_fault_reason,
Genode::Flexpage_iterator &fli, bool &writeable);
protected:
struct {
Nova::mword_t mtd;
unsigned intr_state;
unsigned ctrl[2];
} next_utcb;
PVM _current_vm;
PVMCPU _current_vcpu;
unsigned _ept_fault_addr_type;
void * _stack_reply;
jmp_buf _env;
Genode::uint64_t * pdpte_map(VM *pVM, RTGCPHYS cr3);
void switch_to_hw()
{
unsigned long value;
if (!setjmp(_env)) {
_stack_reply = reinterpret_cast<void *>(&value - 1);
Nova::reply(_stack_reply);
}
}
__attribute__((noreturn)) void _default_handler()
{
Nova::Utcb * utcb = reinterpret_cast<Nova::Utcb *>(Thread::utcb());
Assert(utcb->actv_state == ACTIVITY_STATE_ACTIVE);
Assert(!(utcb->inj_info & IRQ_INJ_VALID_MASK));
/* go back to VirtualBox */
_fpu_save_and_longjmp();
}
__attribute__((noreturn)) void _recall_handler()
{
Nova::Utcb * utcb = reinterpret_cast<Nova::Utcb *>(Thread::utcb());
Assert(utcb->actv_state == ACTIVITY_STATE_ACTIVE);
if (utcb->inj_info & IRQ_INJ_VALID_MASK) {
Assert(utcb->flags & X86_EFL_IF);
if (utcb->intr_state != INTERRUPT_STATE_NONE)
Vmm::log("intr state ", Genode::Hex(utcb->intr_state),
" ", Genode::Hex(utcb->intr_state & 0xf));
Assert(utcb->intr_state == INTERRUPT_STATE_NONE);
/*
if (!continue_hw_accelerated(utcb))
Vmm::log("WARNING - recall ignored during IRQ delivery");
*/
/* got recall during irq injection and the guest is ready for
* delivery of IRQ - just continue */
Nova::reply(_stack_reply);
}
/* are we forced to go back to emulation mode ? */
if (!continue_hw_accelerated(utcb)) {
/* go back to emulation mode */
_fpu_save_and_longjmp();
}
/* check whether we have to request irq injection window */
utcb->mtd = Nova::Mtd::FPU;
if (check_to_request_irq_window(utcb, _current_vcpu)) {
_irq_win = true;
Nova::reply(_stack_reply);
}
/* nothing to do at all - continue hardware accelerated */
Assert(!_irq_win);
/*
* Print a debug message if there actually IS something to do now.
* This can happen, for example, if one of the worker threads has
* set a flag in the meantime. Usually, setting a flag is followed
* by a recall request, but we haven't verified this for each flag
* yet.
*/
continue_hw_accelerated(utcb, true);
Nova::reply(_stack_reply);
}
template <unsigned NPT_EPT>
__attribute__((noreturn)) inline
void _exc_memory(Genode::Thread * myself, Nova::Utcb * utcb,
bool unmap, Genode::addr_t guest_fault,
RTGCUINT vbox_errorcode)
{
using namespace Nova;
using namespace Genode;
Assert(utcb->actv_state == ACTIVITY_STATE_ACTIVE);
if (unmap) {
Vmm::log("error: unmap not implemented");
Nova::reply(_stack_reply);
}
enum { MAP_SIZE = 0x1000UL };
bool writeable = true;
Flexpage_iterator fli;
Genode::addr_t gp_map_addr = guest_fault & ~((1UL << 12) - 1);
int res = map_memory(gp_map_addr, MAP_SIZE, vbox_errorcode,
fli, writeable);
/* emulator has to take over if fault region is not ram */
if (res != VINF_SUCCESS) {
/* see hmR0VmxExitEptViolation of VMM/VMMR0/HMVMXR0.cpp */
// PVMCPU pVCpu = &_current_vm->aCpus[_cpu_id];
// TRPMAssertXcptPF(pVCpu, guest_fault, vbox_errorcode);
/* event re-injection is not handled yet for this case */
Assert(!(utcb->inj_info & IRQ_INJ_VALID_MASK));
_fpu_save_and_longjmp();
}
/* fault region can be mapped - prepare utcb */
utcb->set_msg_word(0);
utcb->mtd = Mtd::FPU;
if (utcb->inj_info & IRQ_INJ_VALID_MASK) {
/*
* The EPT violation occurred during event injection,
* so the event needs to be injected again.
*/
utcb->mtd |= Mtd::INJ;
utcb->inj_info = _last_inj_info;
utcb->inj_error = _last_inj_error;
}
enum {
USER_PD = false, GUEST_PGT = true,
READABLE = true, EXECUTABLE = true
};
Rights permission(READABLE, writeable, EXECUTABLE);
/* add map items until no space is left on utcb anymore */
do {
Flexpage flexpage = fli.page();
if (!flexpage.valid() || flexpage.log2_order < 12)
break;
/* touch memory - otherwise no mapping will take place */
addr_t touch_me = flexpage.addr;
while (touch_me < flexpage.addr + (1UL << flexpage.log2_order)) {
touch_read(reinterpret_cast<unsigned char *>(touch_me));
touch_me += 0x1000UL;
}
Crd crd = Mem_crd(flexpage.addr >> 12, flexpage.log2_order - 12,
permission);
res = utcb->append_item(crd, flexpage.hotspot, USER_PD, GUEST_PGT);
if (debug_map_memory)
Vmm::log("map guest mem ", Genode::Hex(flexpage.addr),
"+", 1UL << flexpage.log2_order, " -> ",
Genode::Hex(flexpage.hotspot), " ",
"guestf fault at ", Genode::Hex(guest_fault));
} while (res);
Nova::reply(_stack_reply);
}
/**
* Shortcut for calling 'Vmm::Vcpu_dispatcher::register_handler'
* with 'Vcpu_dispatcher' as template argument
*/
template <unsigned EV, void (Vcpu_handler::*FUNC)()>
void _register_handler(Genode::addr_t exc_base, Nova::Mtd mtd)
{
if (!register_handler<EV, Vcpu_handler, FUNC>(exc_base, mtd))
Genode::error("could not register handler ",
Genode::Hex(exc_base + EV));
}
Vmm::Vcpu_other_pd &vcpu() { return _vcpu; }
inline bool vbox_to_utcb(Nova::Utcb * utcb, VM *pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
using namespace Nova;
utcb->mtd |= Mtd::EIP;
utcb->ip = pCtx->rip;
utcb->mtd |= Mtd::ESP;
utcb->sp = pCtx->rsp;
utcb->mtd |= Mtd::ACDB;
utcb->ax = pCtx->rax;
utcb->bx = pCtx->rbx;
utcb->cx = pCtx->rcx;
utcb->dx = pCtx->rdx;
utcb->mtd |= Mtd::EBSD;
utcb->bp = pCtx->rbp;
utcb->si = pCtx->rsi;
utcb->di = pCtx->rdi;
utcb->mtd |= Mtd::R8_R15;
utcb->write_r8(pCtx->r8);
utcb->write_r9(pCtx->r9);
utcb->write_r10(pCtx->r10);
utcb->write_r11(pCtx->r11);
utcb->write_r12(pCtx->r12);
utcb->write_r13(pCtx->r13);
utcb->write_r14(pCtx->r14);
utcb->write_r15(pCtx->r15);
utcb->mtd |= Mtd::EFL;
utcb->flags = pCtx->rflags.u;
utcb->mtd |= Mtd::SYS;
utcb->sysenter_cs = pCtx->SysEnter.cs;
utcb->sysenter_sp = pCtx->SysEnter.esp;
utcb->sysenter_ip = pCtx->SysEnter.eip;
utcb->mtd |= Mtd::DR;
utcb->dr7 = pCtx->dr[7];
utcb->mtd |= Mtd::CR;
utcb->cr0 = pCtx->cr0;
utcb->mtd |= Mtd::CR;
utcb->cr2 = pCtx->cr2;
utcb->mtd |= Mtd::CR;
utcb->cr3 = pCtx->cr3;
utcb->mtd |= Mtd::CR;
utcb->cr4 = pCtx->cr4;
utcb->mtd |= Mtd::IDTR;
utcb->idtr.limit = pCtx->idtr.cbIdt;
utcb->idtr.base = pCtx->idtr.pIdt;
utcb->mtd |= Mtd::GDTR;
utcb->gdtr.limit = pCtx->gdtr.cbGdt;
utcb->gdtr.base = pCtx->gdtr.pGdt;
utcb->mtd |= Mtd::EFER;
utcb->write_efer(CPUMGetGuestEFER(pVCpu));
/*
* Update the PDPTE registers if necessary
*
* Intel manual sections 4.4.1 of Vol. 3A and 26.3.2.4 of Vol. 3C
* indicate the conditions when this is the case. The following
* code currently does not check if the recompiler modified any
* CR registers, which means the update can happen more often
* than really necessary.
*/
if (pVM->hm.s.vmx.fSupported &&
CPUMIsGuestPagingEnabledEx(pCtx) &&
CPUMIsGuestInPAEModeEx(pCtx)) {
Genode::uint64_t *pdpte = pdpte_map(pVM, utcb->cr3);
utcb->mtd |= Mtd::PDPTE;
utcb->pdpte[0] = pdpte[0];
utcb->pdpte[1] = pdpte[1];
utcb->pdpte[2] = pdpte[2];
utcb->pdpte[3] = pdpte[3];
}
utcb->mtd |= Mtd::SYSCALL_SWAPGS;
utcb->write_star(pCtx->msrSTAR);
utcb->write_lstar(pCtx->msrLSTAR);
utcb->write_fmask(pCtx->msrSFMASK);
utcb->write_kernel_gs_base(pCtx->msrKERNELGSBASE);
/* from HMVMXR0.cpp */
bool interrupt_pending = false;
uint8_t tpr = 0;
uint8_t pending_interrupt = 0;
PDMApicGetTPR(pVCpu, &tpr, &interrupt_pending, &pending_interrupt);
utcb->mtd |= Mtd::TPR;
utcb->write_tpr(tpr);
utcb->write_tpr_threshold(0);
if (interrupt_pending) {
const uint8_t pending_priority = (pending_interrupt >> 4) & 0xf;
const uint8_t tpr_priority = (tpr >> 4) & 0xf;
if (pending_priority <= tpr_priority)
utcb->write_tpr_threshold(pending_priority);
else
utcb->write_tpr_threshold(tpr_priority);
}
Assert(!(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)));
return true;
}
inline bool utcb_to_vbox(Nova::Utcb * utcb, VM *pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
pCtx->rip = utcb->ip;
pCtx->rsp = utcb->sp;
pCtx->rax = utcb->ax;
pCtx->rbx = utcb->bx;
pCtx->rcx = utcb->cx;
pCtx->rdx = utcb->dx;
pCtx->rbp = utcb->bp;
pCtx->rsi = utcb->si;
pCtx->rdi = utcb->di;
pCtx->rflags.u = utcb->flags;
pCtx->r8 = utcb->read_r8();
pCtx->r9 = utcb->read_r9();
pCtx->r10 = utcb->read_r10();
pCtx->r11 = utcb->read_r11();
pCtx->r12 = utcb->read_r12();
pCtx->r13 = utcb->read_r13();
pCtx->r14 = utcb->read_r14();
pCtx->r15 = utcb->read_r15();
pCtx->dr[7] = utcb->dr7;
if (pCtx->SysEnter.cs != utcb->sysenter_cs)
CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_CS, utcb->sysenter_cs);
if (pCtx->SysEnter.esp != utcb->sysenter_sp)
CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_ESP, utcb->sysenter_sp);
if (pCtx->SysEnter.eip != utcb->sysenter_ip)
CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_EIP, utcb->sysenter_ip);
if (pCtx->idtr.cbIdt != utcb->idtr.limit ||
pCtx->idtr.pIdt != utcb->idtr.base)
CPUMSetGuestIDTR(pVCpu, utcb->idtr.base, utcb->idtr.limit);
if (pCtx->gdtr.cbGdt != utcb->gdtr.limit ||
pCtx->gdtr.pGdt != utcb->gdtr.base)
CPUMSetGuestGDTR(pVCpu, utcb->gdtr.base, utcb->gdtr.limit);
CPUMSetGuestEFER(pVCpu, utcb->read_efer());
if (pCtx->cr0 != utcb->cr0)
CPUMSetGuestCR0(pVCpu, utcb->cr0);
if (pCtx->cr2 != utcb->cr2)
CPUMSetGuestCR2(pVCpu, utcb->cr2);
if (pCtx->cr3 != utcb->cr3) {
CPUMSetGuestCR3(pVCpu, utcb->cr3);
VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
}
if (pCtx->cr4 != utcb->cr4)
CPUMSetGuestCR4(pVCpu, utcb->cr4);
if (pCtx->msrSTAR != utcb->read_star())
CPUMSetGuestMsr(pVCpu, MSR_K6_STAR, utcb->read_star());
if (pCtx->msrLSTAR != utcb->read_lstar())
CPUMSetGuestMsr(pVCpu, MSR_K8_LSTAR, utcb->read_lstar());
if (pCtx->msrSFMASK != utcb->read_fmask())
CPUMSetGuestMsr(pVCpu, MSR_K8_SF_MASK, utcb->read_fmask());
if (pCtx->msrKERNELGSBASE != utcb->read_kernel_gs_base())
CPUMSetGuestMsr(pVCpu, MSR_K8_KERNEL_GS_BASE, utcb->read_kernel_gs_base());
PDMApicSetTPR(pVCpu, utcb->read_tpr());
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
/* tell rem compiler that FPU register changed XXX optimizations ? */
CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM); /* redundant ? XXX */
pVCpu->cpum.s.fUseFlags |= (CPUM_USED_FPU | CPUM_USED_FPU_SINCE_REM); /* redundant ? XXX */
if (utcb->intr_state != 0) {
Assert(utcb->intr_state == BLOCKING_BY_STI ||
utcb->intr_state == BLOCKING_BY_MOV_SS);
EMSetInhibitInterruptsPC(pVCpu, pCtx->rip);
} else
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
return true;
}
inline bool check_to_request_irq_window(Nova::Utcb * utcb, PVMCPU pVCpu)
{
if (!TRPMHasTrap(pVCpu) &&
!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC |
VMCPU_FF_INTERRUPT_PIC)))
return false;
unsigned vector = 0;
utcb->inj_info = NOVA_REQ_IRQWIN_EXIT | vector;
utcb->mtd |= Nova::Mtd::INJ;
return true;
}
__attribute__((noreturn)) void _irq_window()
{
Nova::Utcb * utcb = reinterpret_cast<Nova::Utcb *>(Thread::utcb());
PVMCPU pVCpu = _current_vcpu;
Assert(utcb->intr_state == INTERRUPT_STATE_NONE);
Assert(utcb->flags & X86_EFL_IF);
Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS));
Assert(!(utcb->inj_info & IRQ_INJ_VALID_MASK));
Assert(_irq_win);
_irq_win = false;
if (!TRPMHasTrap(pVCpu)) {
bool res = VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
Assert(!res);
if (VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC |
VMCPU_FF_INTERRUPT_PIC))) {
uint8_t irq;
int rc = PDMGetInterrupt(pVCpu, &irq);
Assert(RT_SUCCESS(rc));
rc = TRPMAssertTrap(pVCpu, irq, TRPM_HARDWARE_INT);
Assert(RT_SUCCESS(rc));
}
}
/*
* If we have no IRQ for injection, something with requesting the
* IRQ window went wrong. Probably it was forgotten to be reset.
*/
Assert(TRPMHasTrap(pVCpu));
/* interrupt can be dispatched */
uint8_t u8Vector;
TRPMEVENT enmType;
SVMEVENT Event;
RTGCUINT u32ErrorCode;
RTGCUINTPTR GCPtrFaultAddress;
uint8_t cbInstr;
Event.u = 0;
/* If a new event is pending, then dispatch it now. */
int rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, 0, 0);
AssertRC(rc);
Assert(enmType == TRPM_HARDWARE_INT);
Assert(u8Vector != X86_XCPT_NMI);
/* Clear the pending trap. */
rc = TRPMResetTrap(pVCpu);
AssertRC(rc);
Event.n.u8Vector = u8Vector;
Event.n.u1Valid = 1;
Event.n.u32ErrorCode = u32ErrorCode;
Event.n.u3Type = SVM_EVENT_EXTERNAL_IRQ;
utcb->inj_info = Event.u;
utcb->inj_error = Event.n.u32ErrorCode;
_last_inj_info = utcb->inj_info;
_last_inj_error = utcb->inj_error;
/*
Vmm::log("type:info:vector ", Genode::Hex(Event.n.u3Type),
Genode::Hex(utcb->inj_info), Genode::Hex(u8Vector),
" intr:actv - ", Genode::Hex(utcb->intr_state),
Genode::Hex(utcb->actv_state), " mtd ",
Genode::Hex(utcb->mtd));
*/
utcb->mtd = Nova::Mtd::INJ | Nova::Mtd::FPU;
Nova::reply(_stack_reply);
}
inline bool continue_hw_accelerated(Nova::Utcb * utcb, bool verbose = false)
{
Assert(!(VMCPU_FF_IS_SET(_current_vcpu, VMCPU_FF_INHIBIT_INTERRUPTS)));
uint32_t check_vm = VM_FF_HM_TO_R3_MASK | VM_FF_REQUEST
| VM_FF_PGM_POOL_FLUSH_PENDING
| VM_FF_PDM_DMA;
uint32_t check_vcpu = VMCPU_FF_HM_TO_R3_MASK
| VMCPU_FF_PGM_SYNC_CR3
| VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL
| VMCPU_FF_REQUEST;
if (!VM_FF_IS_PENDING(_current_vm, check_vm) &&
!VMCPU_FF_IS_PENDING(_current_vcpu, check_vcpu))
return true;
Assert(!(VM_FF_IS_PENDING(_current_vm, VM_FF_PGM_NO_MEMORY)));
#define VERBOSE_VM(flag) \
do { \
if (VM_FF_IS_PENDING(_current_vm, flag)) \
Vmm::log("flag ", flag, " pending"); \
} while (0)
#define VERBOSE_VMCPU(flag) \
do { \
if (VMCPU_FF_IS_PENDING(_current_vcpu, flag)) \
Vmm::log("flag ", flag, " pending"); \
} while (0)
if (verbose) {
/*
* VM_FF_HM_TO_R3_MASK
*/
VERBOSE_VM(VM_FF_TM_VIRTUAL_SYNC);
VERBOSE_VM(VM_FF_PGM_NEED_HANDY_PAGES);
/* handled by the assertion above */
/* VERBOSE_VM(VM_FF_PGM_NO_MEMORY); */
VERBOSE_VM(VM_FF_PDM_QUEUES);
VERBOSE_VM(VM_FF_EMT_RENDEZVOUS);
VERBOSE_VM(VM_FF_REQUEST);
VERBOSE_VM(VM_FF_PGM_POOL_FLUSH_PENDING);
VERBOSE_VM(VM_FF_PDM_DMA);
/*
* VMCPU_FF_HM_TO_R3_MASK
*/
VERBOSE_VMCPU(VMCPU_FF_TO_R3);
/* when this flag gets set, a recall request follows */
/* VERBOSE_VMCPU(VMCPU_FF_TIMER); */
VERBOSE_VMCPU(VMCPU_FF_PDM_CRITSECT);
VERBOSE_VMCPU(VMCPU_FF_PGM_SYNC_CR3);
VERBOSE_VMCPU(VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
VERBOSE_VMCPU(VMCPU_FF_REQUEST);
}
#undef VERBOSE_VMCPU
#undef VERBOSE_VM
return false;
}
virtual bool hw_load_state(Nova::Utcb *, VM *, PVMCPU) = 0;
virtual bool hw_save_state(Nova::Utcb *, VM *, PVMCPU) = 0;
virtual int vm_exit_requires_instruction_emulation(PCPUMCTX) = 0;
public:
enum Exit_condition
{
SVM_NPT = 0xfc,
SVM_INVALID = 0xfd,
VCPU_STARTUP = 0xfe,
RECALL = 0xff,
};
Vcpu_handler(size_t stack_size, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location,
unsigned int cpu_id)
:
Vmm::Vcpu_dispatcher<pthread>(stack_size, *Genode::env()->pd_session(),
cpu_session, location,
attr ? *attr : 0, start_routine, arg),
_vcpu(cpu_session, location),
_ec_sel(Genode::cap_map()->insert()),
_irq_win(false),
_cpu_id(cpu_id)
{ }
unsigned int cpu_id() { return _cpu_id; }
void start() {
_vcpu.start(_ec_sel);
}
void recall()
{
using namespace Nova;
if (ec_ctrl(EC_RECALL, _ec_sel) != NOVA_OK) {
Genode::error("recall failed");
Genode::Lock lock(Genode::Lock::LOCKED);
lock.lock();
}
}
void halt()
{
_halt_sem.down();
}
void wake_up()
{
_halt_sem.up();
}
int run_hw(PVMR0 pVMR0)
{
VM * pVM = reinterpret_cast<VM *>(pVMR0);
PVMCPU pVCpu = &pVM->aCpus[_cpu_id];
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(Thread::utcb());
Assert(Thread::utcb() == Thread::myself()->utcb());
Genode::addr_t old = pCtx->rip;
/* take the utcb state prepared during the last exit */
utcb->mtd = next_utcb.mtd;
utcb->inj_info = IRQ_INJ_NONE;
utcb->intr_state = next_utcb.intr_state;
utcb->actv_state = ACTIVITY_STATE_ACTIVE;
utcb->ctrl[0] = next_utcb.ctrl[0];
utcb->ctrl[1] = next_utcb.ctrl[1];
using namespace Nova;
/* Transfer vCPU state from vBox to Nova format */
if (!vbox_to_utcb(utcb, pVM, pVCpu) ||
!hw_load_state(utcb, pVM, pVCpu)) {
Genode::error("loading vCPU state failed");
return VERR_INTERNAL_ERROR;
}
/* check whether to request interrupt window for injection */
_irq_win = check_to_request_irq_window(utcb, pVCpu);
/*
* Flag vCPU to be "pokeable" by external events such as interrupts
* from virtual devices. Only if this flag is set, the
* 'vmR3HaltGlobal1NotifyCpuFF' function calls 'SUPR3CallVMMR0Ex'
* with VMMR0_DO_GVMM_SCHED_POKE as argument to indicate such
* events. This function, in turn, will recall the vCPU.
*/
VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
/* save current FPU state */
fpu_save(reinterpret_cast<char *>(&_emt_fpu_state));
/* write FPU state from pCtx to FPU registers */
fpu_load(reinterpret_cast<char *>(pCtx->pXStateR3));
/* tell kernel to transfer current fpu registers to vCPU */
utcb->mtd |= Mtd::FPU;
_current_vm = pVM;
_current_vcpu = pVCpu;
/* switch to hardware accelerated mode */
switch_to_hw();
Assert(utcb->actv_state == ACTIVITY_STATE_ACTIVE);
_current_vm = 0;
_current_vcpu = 0;
/* write FPU state of vCPU (in current FPU registers) to pCtx */
Genode::memcpy(pCtx->pXStateR3, &_guest_fpu_state, sizeof(X86FXSTATE));
/* load saved FPU state of EMT thread */
fpu_load(reinterpret_cast<char *>(&_emt_fpu_state));
/* see hmR0VmxExitToRing3 - sync recompiler state */
CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR |
CPUM_CHANGED_LDTR | CPUM_CHANGED_GDTR |
CPUM_CHANGED_IDTR | CPUM_CHANGED_TR |
CPUM_CHANGED_HIDDEN_SEL_REGS |
CPUM_CHANGED_GLOBAL_TLB_FLUSH);
VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
/* Transfer vCPU state from Nova to vBox format */
if (!utcb_to_vbox(utcb, pVM, pVCpu) ||
!hw_save_state(utcb, pVM, pVCpu)) {
Genode::error("saving vCPU state failed");
return VERR_INTERNAL_ERROR;
}
/* reset message transfer descriptor for next invocation */
Assert (!(utcb->inj_info & IRQ_INJ_VALID_MASK));
/* Reset irq window next time if we are still requesting it */
next_utcb.mtd = _irq_win ? Mtd::INJ : 0;
next_utcb.intr_state = utcb->intr_state;
next_utcb.ctrl[0] = utcb->ctrl[0];
next_utcb.ctrl[1] = utcb->ctrl[1];
if (next_utcb.intr_state & 3) {
next_utcb.intr_state &= ~3U;
next_utcb.mtd |= Mtd::STA;
}
#ifdef VBOX_WITH_REM
/* XXX see VMM/VMMR0/HMVMXR0.cpp - not necessary every time ! XXX */
REMFlushTBs(pVM);
#endif
/* track guest mode changes - see VMM/VMMAll/IEMAllCImpl.cpp.h */
PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
int rc = vm_exit_requires_instruction_emulation(pCtx);
/* evaluated in VMM/include/EMHandleRCTmpl.h */
return rc;
}
};
#endif /* _VIRTUALBOX__SPEC__NOVA__VCPU_H_ */

View File

@ -0,0 +1,141 @@
/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \date 2013-11-18
*/
/*
* Copyright (C) 2013-2016 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__SPEC__NOVA__VCPU_SVM_H_
#define _VIRTUALBOX__SPEC__NOVA__VCPU_SVM_H_
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "svm.h"
class Vcpu_handler_svm : public Vcpu_handler
{
private:
__attribute__((noreturn)) void _svm_default() { _default_handler(); }
__attribute__((noreturn)) void _svm_vintr() { _irq_window(); }
__attribute__((noreturn)) void _svm_ioio()
{
using namespace Nova;
using namespace Genode;
Thread *myself = Thread::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
if (utcb->qual[0] & 0x4) {
unsigned ctrl0 = utcb->ctrl[0];
Vmm::warning("invalid gueststate");
utcb->ctrl[0] = ctrl0;
utcb->ctrl[1] = 0;
utcb->mtd = Mtd::CTRL;
Nova::reply(_stack_reply);
}
_default_handler();
}
template <unsigned X>
__attribute__((noreturn)) void _svm_npt()
{
using namespace Nova;
using namespace Genode;
Thread *myself = Thread::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
_exc_memory<X>(myself, utcb, utcb->qual[0] & 1,
utcb->qual[1], utcb->qual[0]);
}
__attribute__((noreturn)) void _svm_startup()
{
using namespace Nova;
/* enable VM exits for CPUID */
next_utcb.mtd = Nova::Mtd::CTRL;
next_utcb.ctrl[0] = SVM_CTRL1_INTERCEPT_CPUID;
next_utcb.ctrl[1] = 0;
void *exit_status = _start_routine(_arg);
pthread_exit(exit_status);
Nova::reply(nullptr);
}
__attribute__((noreturn)) void _svm_recall()
{
Vcpu_handler::_recall_handler();
}
public:
Vcpu_handler_svm(size_t stack_size, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location,
unsigned int cpu_id)
:
Vcpu_handler(stack_size, attr, start_routine, arg, cpu_session,
location, cpu_id)
{
using namespace Nova;
Genode::addr_t const exc_base = vcpu().exc_base();
typedef Vcpu_handler_svm This;
register_handler<RECALL, This,
&This::_svm_recall> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<SVM_EXIT_IOIO, This,
&This::_svm_ioio> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_VINTR, This,
&This::_svm_vintr> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_RDTSC, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_MSR, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_NPT, This,
&This::_svm_npt<SVM_NPT>> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_HLT, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_CPUID, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<VCPU_STARTUP, This,
&This::_svm_startup> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
start();
}
bool hw_save_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return svm_save_state(utcb, pVM, pVCpu);
}
bool hw_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return svm_load_state(utcb, pVM, pVCpu);
}
int vm_exit_requires_instruction_emulation(PCPUMCTX)
{
if (exit_reason == RECALL)
return VINF_SUCCESS;
return VINF_EM_RAW_EMULATE_INSTR;
}
};
#endif /* _VIRTUALBOX__SPEC__NOVA__VCPU_SVM_H_ */

View File

@ -0,0 +1,274 @@
/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \author Norman Feske
* \author Christian Helmuth
*/
/*
* Copyright (C) 2013-2016 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__SPEC__NOVA__VCPU_VMX_H_
#define _VIRTUALBOX__SPEC__NOVA__VCPU_VMX_H_
/* libc includes */
#include <stdlib.h>
/* VirtualBox includes */
#include <VBox/vmm/hm_vmx.h>
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "vmx.h"
class Vcpu_handler_vmx : public Vcpu_handler
{
private:
template <unsigned X>
__attribute__((noreturn)) void _vmx_ept()
{
using namespace Nova;
using namespace Genode;
Thread *myself = Thread::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
addr_t exit_qual = utcb->qual[0];
addr_t exit_addr = utcb->qual[1];
RTGCUINT vbox_errorcode = 0;
if (exit_qual & VMX_EXIT_QUALIFICATION_EPT_INSTR_FETCH)
vbox_errorcode |= X86_TRAP_PF_ID;
if (exit_qual & VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE)
vbox_errorcode |= X86_TRAP_PF_RW;
if (exit_qual & VMX_EXIT_QUALIFICATION_EPT_ENTRY_PRESENT)
vbox_errorcode |= X86_TRAP_PF_P;
_exc_memory<X>(myself, utcb, exit_qual & 0x38, exit_addr,
vbox_errorcode);
}
__attribute__((noreturn)) void _vmx_default() { _default_handler(); }
__attribute__((noreturn)) void _vmx_startup()
{
using namespace Nova;
Genode::Thread *myself = Genode::Thread::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
/* configure VM exits to get */
next_utcb.mtd = Nova::Mtd::CTRL;
/* from src/VBox/VMM/VMMR0/HWVMXR0.cpp of virtualbox sources */
next_utcb.ctrl[0] = VMX_VMCS_CTRL_PROC_EXEC_HLT_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_MOV_DR_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_UNCOND_IO_EXIT |
/* XXX commented out because TinyCore Linux won't run as guest otherwise
VMX_VMCS_CTRL_PROC_EXEC_MONITOR_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_MWAIT_EXIT |
*/
/* VMX_VMCS_CTRL_PROC_EXEC_CR8_LOAD_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_CR8_STORE_EXIT |*/
VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW |
VMX_VMCS_CTRL_PROC_EXEC_RDPMC_EXIT;
/* VMX_VMCS_CTRL_PROC_EXEC_PAUSE_EXIT | */
/*
* Disable trapping RDTSC for now as it creates a huge load with
* VM guests that execute it frequently.
*/
// VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT;
next_utcb.ctrl[1] = VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC |
VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT |
VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST |
VMX_VMCS_CTRL_PROC_EXEC2_VPID |
/* VMX_VMCS_CTRL_PROC_EXEC2_X2APIC | */
VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP |
VMX_VMCS_CTRL_PROC_EXEC2_EPT;
void *exit_status = _start_routine(_arg);
pthread_exit(exit_status);
Nova::reply(nullptr);
}
__attribute__((noreturn)) void _vmx_triple()
{
Vmm::error("triple fault - dead");
exit(-1);
}
__attribute__((noreturn)) void _vmx_irqwin() { _irq_window(); }
__attribute__((noreturn)) void _vmx_recall()
{
Vcpu_handler::_recall_handler();
}
__attribute__((noreturn)) void _vmx_invalid()
{
Genode::Thread *myself = Genode::Thread::myself();
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
unsigned const dubious = utcb->inj_info |
utcb->intr_state | utcb->actv_state;
if (dubious)
Vmm::warning(__func__, " - dubious -"
" inj_info=", Genode::Hex(utcb->inj_info),
" inj_error=", Genode::Hex(utcb->inj_error),
" intr_state=", Genode::Hex(utcb->intr_state),
" actv_state=", Genode::Hex(utcb->actv_state));
Vmm::error("invalid guest state - dead");
exit(-1);
}
/*
* This VM exit is in part handled by the NOVA kernel (writing the CR
* register) and in part by VirtualBox (updating the PDPTE registers,
* which requires access to the guest physical memory).
* Intel manual sections 4.4.1 of Vol. 3A and 26.3.2.4 of Vol. 3C
* indicate the conditions when the PDPTE registers need to get
* updated.
*/
__attribute__((noreturn)) void _vmx_mov_crx()
{
unsigned long value;
void *stack_reply = reinterpret_cast<void *>(&value - 1);
Genode::Thread *myself = Genode::Thread::myself();
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
unsigned int cr = utcb->qual[0] & 0xf;
if (cr == 8)
_default_handler();
Genode::uint64_t *pdpte = pdpte_map(_current_vm, utcb->cr3);
Assert(pdpte != 0);
utcb->pdpte[0] = pdpte[0];
utcb->pdpte[1] = pdpte[1];
utcb->pdpte[2] = pdpte[2];
utcb->pdpte[3] = pdpte[3];
utcb->mtd = Nova::Mtd::PDPTE | Nova::Mtd::FPU;
Nova::reply(stack_reply);
}
public:
Vcpu_handler_vmx(size_t stack_size, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location,
unsigned int cpu_id)
:
Vcpu_handler(stack_size, attr, start_routine, arg, cpu_session,
location, cpu_id)
{
using namespace Nova;
typedef Vcpu_handler_vmx This;
Genode::addr_t const exc_base = vcpu().exc_base();
register_handler<VMX_EXIT_TRIPLE_FAULT, This,
&This::_vmx_triple> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_INIT_SIGNAL, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_INT_WINDOW, This,
&This::_vmx_irqwin> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_TASK_SWITCH, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_CPUID, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_HLT, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
/* we don't support tsc offsetting for now - so let the rdtsc exit */
register_handler<VMX_EXIT_RDTSC, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_VMCALL, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_IO_INSTR, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_RDMSR, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_WRMSR, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_ERR_INVALID_GUEST_STATE, This,
&This::_vmx_invalid> (exc_base, Mtd::ALL | Mtd::FPU);
// register_handler<VMX_EXIT_PAUSE, This,
// &This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_WBINVD, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_MOV_CRX, This,
&This::_vmx_mov_crx> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_MOV_DRX, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_TPR_BELOW_THRESHOLD, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_EPT_VIOLATION, This,
&This::_vmx_ept<VMX_EXIT_EPT_VIOLATION>> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VCPU_STARTUP, This,
&This::_vmx_startup> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<RECALL, This,
&This::_vmx_recall> (exc_base, Mtd::ALL | Mtd::FPU);
start();
}
bool hw_save_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return vmx_save_state(utcb, pVM, pVCpu);
}
bool hw_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return vmx_load_state(utcb, pVM, pVCpu);
}
int vm_exit_requires_instruction_emulation(PCPUMCTX pCtx)
{
switch (exit_reason) {
case VMX_EXIT_HLT:
pCtx->rip++;
return VINF_EM_HALT;
case VMX_EXIT_IO_INSTR:
/* EMHandleRCTmpl.h does not distinguish READ/WRITE rc */
return VINF_IOM_R3_IOPORT_WRITE;
case VMX_EXIT_RDMSR:
return VINF_CPUM_R3_MSR_READ;
case VMX_EXIT_WRMSR:
return VINF_CPUM_R3_MSR_WRITE;
case VMX_EXIT_TPR_BELOW_THRESHOLD:
/* the instruction causing the exit has already been executed */
case RECALL:
return VINF_SUCCESS;
case VMX_EXIT_EPT_VIOLATION:
if (_ept_fault_addr_type == PGMPAGETYPE_MMIO)
/* EMHandleRCTmpl.h does not distinguish READ/WRITE rc */
return VINF_IOM_R3_MMIO_READ_WRITE;
case VMX_EXIT_MOV_DRX:
/* looks complicated in original R0 code -> emulate instead */
return VINF_EM_RAW_EMULATE_INSTR;
default:
if (exit_reason != VMX_EXIT_EPT_VIOLATION &&
exit_reason != VMX_EXIT_CPUID)
Genode::log("leave exit_reason=", exit_reason, " - "
"optimize ?");
return VINF_EM_RAW_EMULATE_INSTR;
}
}
};
#endif /* _VIRTUALBOX__SPEC__NOVA__VCPU_VMX_H_ */

View File

@ -0,0 +1,129 @@
/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Norman Feske
* \author Alexander Boettcher
*/
/*
* Copyright (C) 2013-2014 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__SPEC__NOVA__VMX_H_
#define _VIRTUALBOX__SPEC__NOVA__VMX_H_
#define GENODE_READ_SELREG_REQUIRED(REG) \
(pCtx->REG.Sel != utcb->REG.sel) || \
(pCtx->REG.ValidSel != utcb->REG.sel) || \
(pCtx->REG.fFlags != CPUMSELREG_FLAGS_VALID) || \
(pCtx->REG.u32Limit != utcb->REG.limit) || \
(pCtx->REG.u64Base != utcb->REG.base) || \
(pCtx->REG.Attr.u != sel_ar_conv_from_nova(utcb->REG.ar))
#define GENODE_READ_SELREG(REG) \
pCtx->REG.Sel = utcb->REG.sel; \
pCtx->REG.ValidSel = utcb->REG.sel; \
pCtx->REG.fFlags = CPUMSELREG_FLAGS_VALID; \
pCtx->REG.u32Limit = utcb->REG.limit; \
pCtx->REG.u64Base = utcb->REG.base; \
pCtx->REG.Attr.u = sel_ar_conv_from_nova(utcb->REG.ar)
static inline bool vmx_save_state(Nova::Utcb * utcb, 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); \
utcb->REG.sel = pCtx->REG.Sel; \
utcb->REG.limit = pCtx->REG.u32Limit; \
utcb->REG.base = pCtx->REG.u64Base; \
utcb->REG.ar = sel_ar_conv_to_nova(pCtx->REG.Attr.u ? : VMCS_SEG_UNUSABLE);
static inline bool vmx_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
{
utcb->mtd |= Nova::Mtd::ESDS;
GENODE_WRITE_SELREG(es);
GENODE_WRITE_SELREG(ds);
}
{
utcb->mtd |= Nova::Mtd::FSGS;
GENODE_WRITE_SELREG(fs);
GENODE_WRITE_SELREG(gs);
}
{
utcb->mtd |= Nova::Mtd::CSSS;
GENODE_WRITE_SELREG(cs);
GENODE_WRITE_SELREG(ss);
}
/* ldtr */
if (pCtx->ldtr.Sel == 0) {
{
utcb->mtd |= Nova::Mtd::LDTR;
utcb->ldtr.sel = 0;
utcb->ldtr.limit = 0;
utcb->ldtr.base = 0;
utcb->ldtr.ar = sel_ar_conv_to_nova(0x82);
}
} else {
{
utcb->mtd |= Nova::Mtd::LDTR;
utcb->ldtr.sel = pCtx->ldtr.Sel;
utcb->ldtr.limit = pCtx->ldtr.u32Limit;
utcb->ldtr.base = pCtx->ldtr.u64Base;
utcb->ldtr.ar = sel_ar_conv_to_nova(pCtx->ldtr.Attr.u);
}
}
/* tr */
Assert(pCtx->tr.Attr.u & X86_SEL_TYPE_SYS_TSS_BUSY_MASK);
{
utcb->mtd |= Nova::Mtd::TR;
utcb->tr.sel = pCtx->tr.Sel;
utcb->tr.limit = pCtx->tr.u32Limit;
utcb->tr.base = pCtx->tr.u64Base;
utcb->tr.ar = sel_ar_conv_to_nova(pCtx->tr.Attr.u);
}
return true;
}
#undef GENODE_WRITE_SELREG
#endif /* _VIRTUALBOX__SPEC__NOVA__VMX_H_ */

View File

@ -0,0 +1,332 @@
/*
* \brief VirtualBox SUPLib supplements
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <os/attached_ram_dataspace.h>
#include <base/semaphore.h>
#include <os/timed_semaphore.h>
#include <trace/timestamp.h>
/* Genode/Virtualbox includes */
#include "sup.h"
/* VirtualBox includes */
#include <iprt/semaphore.h>
#include <iprt/ldr.h>
#include <iprt/uint128.h>
#include <VBox/err.h>
/* libc memory allocator */
#include <libc_mem_alloc.h>
enum {
UPDATE_HZ = 1000,
UPDATE_US = 1000 * 1000 / UPDATE_HZ,
UPDATE_NS = UPDATE_US * 1000,
};
PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPage;
struct Periodic_gip : public Genode::Thread_deprecated<4096>
{
Periodic_gip() : Thread_deprecated("periodic_gip") { start(); }
static void update()
{
/**
* We're using rdtsc here since timer_session->elapsed_ms produces
* instable results when the timer service is using the Genode PIC
* driver as done for base-nova currently.
*/
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, 1000*1000*1000);
RTUInt128AssignMul(&nanots128, &multiplier);
RTUINT128U divisor;
RTUInt128AssignU64(&divisor, genode_cpu_hz());
RTUInt128AssignDiv(&nanots128, &divisor);
SUPGIPCPU *cpu = &g_pSUPGlobalInfoPage->aCPUs[0];
/*
* 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);
}
void entry() override { genode_update_tsc(update, UPDATE_US); }
};
struct Attached_gip : Genode::Attached_ram_dataspace
{
Attached_gip()
: Attached_ram_dataspace(Genode::env()->ram_session(), PAGE_SIZE)
{
g_pSUPGlobalInfoPage = local_addr<SUPGLOBALINFOPAGE>();
/* checked by TMR3Init */
g_pSUPGlobalInfoPage->u32Version = SUPGLOBALINFOPAGE_VERSION;
g_pSUPGlobalInfoPage->u32Magic = SUPGLOBALINFOPAGE_MAGIC;
g_pSUPGlobalInfoPage->u32Mode = SUPGIPMODE_SYNC_TSC;
g_pSUPGlobalInfoPage->cCpus = 1;
g_pSUPGlobalInfoPage->cPages = 1;
g_pSUPGlobalInfoPage->u32UpdateHz = UPDATE_HZ;
g_pSUPGlobalInfoPage->u32UpdateIntervalNS = UPDATE_NS;
g_pSUPGlobalInfoPage->cOnlineCpus = 0;
g_pSUPGlobalInfoPage->cPresentCpus = 0;
g_pSUPGlobalInfoPage->cPossibleCpus = 0;
g_pSUPGlobalInfoPage->idCpuMax = 0;
g_pSUPGlobalInfoPage->u64CpuHz = genode_cpu_hz();
/* evaluated by rtTimeNanoTSInternalRediscover in Runtime/common/time/timesup.cpp */
g_pSUPGlobalInfoPage->fGetGipCpu = SUPGIPGETCPU_APIC_ID;
SUPGIPCPU *cpu = &g_pSUPGlobalInfoPage->aCPUs[0];
cpu->u32TransactionId = 0;
cpu->u32UpdateIntervalTSC = genode_cpu_hz() / UPDATE_HZ;
cpu->u64NanoTS = 0ULL;
cpu->u64TSC = 0ULL;
cpu->u64CpuHz = genode_cpu_hz();
cpu->cErrors = 0;
cpu->iTSCHistoryHead = 0;
cpu->u32PrevUpdateIntervalNS = UPDATE_NS;
cpu->enmState = SUPGIPCPUSTATE_ONLINE;
cpu->idCpu = 0;
cpu->iCpuSet = 0;
cpu->idApic = 0;
/* schedule periodic call of GIP update function */
static Periodic_gip periodic_gip;
}
} static gip;
int SUPR3Init(PSUPDRVSESSION *ppSession)
{
return VINF_SUCCESS;
}
SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void)
{
return sizeof(void *) == 4 ? SUPPAGINGMODE_32_BIT : SUPPAGINGMODE_AMD64_NX;
}
int SUPR3Term(bool) { return VINF_SUCCESS; }
int SUPR3GipGetPhys(PRTHCPHYS pHCPhys)
{
/*
* Return VMM-local address as physical address. This address is
* then fed to MMR3HyperMapHCPhys. (TMR3Init)
*/
*pHCPhys = (RTHCPHYS)g_pSUPGlobalInfoPage;
return VINF_SUCCESS;
}
int SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod,
uint32_t fFlags, PRTERRINFO pErrInfo)
{
return RTLdrLoad(pszFilename, phLdrMod);
}
SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)
{
Genode::log(__func__, " pvPages=", pvPages, " pages=", cPages);
return VINF_SUCCESS;
}
uint32_t SUPSemEventMultiGetResolution(PSUPDRVSESSION)
{
return 100000*10; /* called by 'vmR3HaltGlobal1Init' */
}
int SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent)
{
*phEvent = (SUPSEMEVENT)new Genode::Semaphore();
return VINF_SUCCESS;
}
int SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
{
if (hEvent)
delete reinterpret_cast<Genode::Semaphore *>(hEvent);
return VINF_SUCCESS;
}
int SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
{
if (hEvent)
reinterpret_cast<Genode::Semaphore *>(hEvent)->up();
else
Genode::error(__FUNCTION__, " called - not implemented");
return VINF_SUCCESS;
}
int SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent,
uint32_t cMillies)
{
if (hEvent && cMillies == RT_INDEFINITE_WAIT)
reinterpret_cast<Genode::Semaphore *>(hEvent)->down();
else {
Genode::error(__FUNCTION__, " called millis=", cMillies,
" - not implemented");
reinterpret_cast<Genode::Semaphore *>(hEvent)->down();
}
return VINF_SUCCESS;
}
SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION,
PSUPSEMEVENTMULTI phEventMulti)
{
RTSEMEVENTMULTI sem;
/*
* Input validation.
*/
AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);
/*
* Create the event semaphore object.
*/
int rc = RTSemEventMultiCreate(&sem);
static_assert(sizeof(sem) == sizeof(*phEventMulti), "oi");
*phEventMulti = reinterpret_cast<SUPSEMEVENTMULTI>(sem);
return rc;
}
SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION, SUPSEMEVENTMULTI hEvMulti)
{
return RTSemEventMultiDestroy(reinterpret_cast<RTSEMEVENTMULTI>(hEvMulti));
}
int SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation,
void *pvArg)
{
if (uOperation == VMMR0_DO_CALL_HYPERVISOR) {
Genode::log(__func__, ": VMMR0_DO_CALL_HYPERVISOR - doing nothing");
return VINF_SUCCESS;
}
if (uOperation == VMMR0_DO_VMMR0_TERM) {
Genode::log(__func__, ": VMMR0_DO_VMMR0_TERM - doing nothing");
return VINF_SUCCESS;
}
if (uOperation == VMMR0_DO_GVMM_DESTROY_VM) {
Genode::log(__func__, ": VMMR0_DO_GVMM_DESTROY_VM - doing nothing");
return VINF_SUCCESS;
}
AssertMsg(uOperation != VMMR0_DO_VMMR0_TERM &&
uOperation != VMMR0_DO_CALL_HYPERVISOR &&
uOperation != VMMR0_DO_GVMM_DESTROY_VM,
("SUPR3CallVMMR0: unhandled uOperation %d", uOperation));
return VERR_GENERAL_FAILURE;
}
void genode_VMMR0_DO_GVMM_CREATE_VM(PSUPVMMR0REQHDR pReqHdr)
{
GVMMCREATEVMREQ &req = reinterpret_cast<GVMMCREATEVMREQ &>(*pReqHdr);
size_t const cCpus = req.cCpus;
/*
* Allocate and initialize VM struct
*
* The VM struct is followed by the variable-sizedA array of VMCPU
* objects. 'RT_UOFFSETOF' is used to determine the size including
* the VMCPU array.
*
* VM struct must be page-aligned, which is checked at least in
* PDMR3CritSectGetNop().
*/
size_t const cbVM = RT_UOFFSETOF(VM, aCpus[cCpus]);
VM *pVM = (VM *)Libc::mem_alloc()->alloc(cbVM, Genode::log2(PAGE_SIZE));
Genode::memset(pVM, 0, cbVM);
/*
* On Genode, VMMR0 and VMMR3 share a single address space. Hence, the
* same pVM pointer is valid as pVMR0 and pVMR3.
*/
pVM->enmVMState = VMSTATE_CREATING;
pVM->pVMR0 = (RTHCUINTPTR)pVM;
pVM->pVMRC = (RTGCUINTPTR)pVM;
pVM->pSession = req.pSession;
pVM->cbSelf = cbVM;
pVM->cCpus = cCpus;
pVM->uCpuExecutionCap = 100; /* expected by 'vmR3CreateU()' */
pVM->offVMCPU = RT_UOFFSETOF(VM, aCpus);
for (uint32_t i = 0; i < cCpus; i++) {
pVM->aCpus[i].pVMR0 = pVM->pVMR0;
pVM->aCpus[i].pVMR3 = pVM;
pVM->aCpus[i].idHostCpu = NIL_RTCPUID;
pVM->aCpus[i].hNativeThreadR0 = NIL_RTNATIVETHREAD;
}
pVM->aCpus[0].hNativeThreadR0 = RTThreadNativeSelf();
/* out parameters of the request */
req.pVMR0 = pVM->pVMR0;
req.pVMR3 = pVM;
}
void genode_VMMR0_DO_GVMM_REGISTER_VMCPU(PVMR0 pVMR0, VMCPUID idCpu)
{
PVM pVM = reinterpret_cast<PVM>(pVMR0);
pVM->aCpus[idCpu].hNativeThreadR0 = RTThreadNativeSelf();
}

View File

@ -0,0 +1,45 @@
/*
* \brief Common VirtualBox SUPLib supplements
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _SUP_H_
#define _SUP_H_
/* Genode includes */
#include <cpu_session/cpu_session.h>
/* VirtualBox includes */
#include <VBox/vmm/vm.h>
#include <VBox/vmm/gvmm.h>
#include <iprt/param.h>
/**
* Returns true if a vCPU could be started. If false we run without
* hardware acceleration support.
*/
bool create_emt_vcpu(pthread_t * pthread, size_t stack,
const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg,
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location,
unsigned int cpu_id);
uint64_t genode_cpu_hz();
void genode_update_tsc(void (*update_func)(void), unsigned long update_us);
Genode::Cpu_session * get_vcpu_cpu_session();
void genode_VMMR0_DO_GVMM_CREATE_VM(PSUPVMMR0REQHDR pReqHdr);
void genode_VMMR0_DO_GVMM_REGISTER_VMCPU(PVMR0 pVMR0, VMCPUID idCpu);
#endif /* _SUP_H_ */

View File

@ -0,0 +1,68 @@
REQUIRES = nova
VBOX_CC_OPT += -DVBOX_WITH_HARDENING
VBOX_CC_OPT += -DVBOX_WITH_GENERIC_SESSION_WATCHER
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
CC_WARN += -Wall
TARGET = virtualbox5
SRC_CC = frontend/main.cc frontend/console.cc \
frontend/VirtualBoxErrorInfoImpl.cpp \
devices.cc drivers.cc dummies.cc libc.cc \
logger.cc mm.cc pdm.cc pgm.cc rt.cc sup.cc \
hm.cc thread.cc dynlib.cc unimpl.cc
# use implementation of VBOX 4
vpath devices.cc $(REP_DIR)/src/virtualbox
vpath drivers.cc $(REP_DIR)/src/virtualbox
vpath dynlib.cc $(REP_DIR)/src/virtualbox
vpath libc.cc $(REP_DIR)/src/virtualbox
vpath logger.cc $(REP_DIR)/src/virtualbox
vpath pdm.cc $(REP_DIR)/src/virtualbox
vpath rt.cc $(REP_DIR)/src/virtualbox
vpath thread.cc $(REP_DIR)/src/virtualbox
LIBS += base
LIBS += config_args
LIBS += stdcxx
LIBS += virtualbox5-bios virtualbox5-recompiler virtualbox5-runtime \
virtualbox5-vmm virtualbox5-devices virtualbox5-drivers \
virtualbox5-storage virtualbox5-zlib virtualbox5-liblzf \
virtualbox5-xml virtualbox5-main virtualbox5-apiwrap \
virtualbox5-dis virtualbox5-hwaccl
LIBS += pthread libc_terminal libc_pipe libiconv
LIBS += qemu-usb
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(call select_from_repositories,src/lib/pthread)
INC_DIR += $(VBOX_DIR)/Runtime/include
SRC_CC += HostServices/SharedFolders/service.cpp
SRC_CC += HostServices/SharedFolders/mappings.cpp
SRC_CC += HostServices/SharedFolders/vbsf.cpp
SRC_CC += HostServices/SharedFolders/vbsfpath.cpp
SRC_CC += HostServices/SharedFolders/shflhandle.cpp
SRC_CC += HostServices/SharedClipboard/service.cpp
SRC_CC += frontend/dummy/errorinfo.cc frontend/dummy/virtualboxbase.cc
SRC_CC += frontend/dummy/autostart.cc frontend/dummy/rest.cc
SRC_CC += frontend/dummy/host.cc
INC_DIR += $(VBOX_DIR)/Main/include
INC_DIR += $(VBOX_DIR)/VMM/include
INC_DIR += $(REP_DIR)/src/virtualbox5/frontend
INC_DIR += $(VIRTUALBOX_DIR)/VBoxAPIWrap
INC_DIR += $(VBOX_DIR)/Main/xml
INC_DIR += $(VBOX_DIR)/HostServices
# search path to 'scan_code_set_2.h'
INC_DIR += $(call select_from_repositories,src/drivers/input/spec/ps2)

View File

@ -0,0 +1,215 @@
/*
* \brief Dummy implementations of symbols needed by VirtualBox
* \author Norman Feske
* \date 2013-08-22
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <iprt/assert.h>
extern "C" {
#define DUMMY(name) \
void name(void) { \
Genode::warning(__func__, ": " #name " called, not implemented, eip=", \
__builtin_return_address(0)); \
while (1) { Assert(!"not implemented"); } \
}
DUMMY(DBGFR3CoreWrite)
DUMMY(DBGCRegisterCommands)
DUMMY(DBGFR3LogModifyDestinations)
DUMMY(DBGFR3LogModifyFlags)
DUMMY(DBGFR3LogModifyGroups)
DUMMY(DBGFR3OSDetect)
DUMMY(DBGFR3OSQueryNameAndVersion)
DUMMY(DBGFR3OSQueryInterface)
DUMMY(DBGFR3PlugInLoad)
DUMMY(DBGFR3PlugInLoadAll)
DUMMY(DBGFR3StackWalkBegin)
DUMMY(DBGFR3StackWalkBeginEx)
DUMMY(DBGFR3StackWalkNext)
DUMMY(DBGFR3StackWalkEnd)
DUMMY(DBGFR3PlugInUnload)
DUMMY(DBGFR3PlugInUnloadAll)
DUMMY(HBDMgrDestroy)
DUMMY(HMGetPaePdpes)
DUMMY(HMInvalidatePage)
DUMMY(HMInvalidatePageOnAllVCpus)
DUMMY(HMInvalidatePhysPage)
DUMMY(HMSetSingleInstruction)
DUMMY(HMR3CheckError)
DUMMY(HMR3DisablePatching)
DUMMY(HMR3EnablePatching)
DUMMY(HMR3EmulateIoBlock)
DUMMY(HMR3IsEnabled)
DUMMY(HMR3IsNestedPagingActive)
DUMMY(HMR3IsUXActive)
DUMMY(HMR3IsVpidActive)
DUMMY(HMR3PatchTprInstr)
DUMMY(MMHyperR0ToCC)
DUMMY(MMHyperRCToCC)
DUMMY(MMR3HeapAPrintfV)
DUMMY(MMR3HyperRealloc)
DUMMY(MMR3LockCall)
DUMMY(MMR3PageDummyHCPhys)
DUMMY(MMR3UkHeapFree)
DUMMY(PDMR3AsyncCompletionBwMgrSetMaxForFile)
DUMMY(PDMR3LdrGetInterfaceSymbols)
DUMMY(PDMR3LdrQueryRCModFromPC)
DUMMY(PDMCritSectBothFF)
DUMMY(pgmMapActivateCR3)
DUMMY(pgmMapDeactivateCR3)
DUMMY(pgmMapResolveConflicts)
DUMMY(pgmR3SyncPTResolveConflict)
DUMMY(pgmR3SyncPTResolveConflictPAE)
DUMMY(PGMR3HandlerVirtualRegister)
DUMMY(DBGFR3PagingDumpEx)
DUMMY(MMPagePhys2PageEx)
DUMMY(PGMR3DbgR3Ptr2GCPhys)
DUMMY(PGMR3MappingsUnfix)
DUMMY(PGMR3MappingsFix)
DUMMY(PGMR3MappingsDisable)
DUMMY(PGMR3MapPT)
DUMMY(PGMR3SharedModuleCheckAll)
DUMMY(PGMR3SharedModuleUnregister)
DUMMY(PGMR3SharedModuleRegister)
DUMMY(pgmR3MapInfo)
DUMMY(RTTraceBufCarve)
DUMMY(RTTraceBufEnumEntries)
DUMMY(RTTraceBufGetEntryCount)
DUMMY(RTTraceBufGetEntrySize)
DUMMY(RTPoll)
DUMMY(RTPollSetAdd)
DUMMY(RTPollSetCreate)
DUMMY(RTPollSetEventsChange)
DUMMY(RTPollSetRemove)
DUMMY(RTPollSetDestroy)
DUMMY(RTProcCreate)
DUMMY(RTProcTerminate)
DUMMY(RTProcWait)
DUMMY(RTLdrGetSuff)
DUMMY(RTLdrLoadAppPriv)
DUMMY(RTPathAppend)
DUMMY(RTPathChangeToDosSlashes)
DUMMY(RTSemEventWaitEx)
DUMMY(RTSemPing)
DUMMY(RTSemPingWait)
DUMMY(RTMemDupExTag)
DUMMY(RTMemDupTag)
DUMMY(RTMemExecFree)
DUMMY(SELMR3GetSelectorInfo)
DUMMY(SELMR3GetShadowSelectorInfo)
DUMMY(SUPReadTscWithDelta)
DUMMY(SUPR3HardenedLdrLoadPlugIn)
DUMMY(SUPR3PageAlloc)
DUMMY(SUPR3PageFree)
DUMMY(SUPR3PageMapKernel)
DUMMY(SUPR3ReadTsc)
DUMMY(SUPGetCpuHzFromGipForAsyncMode)
DUMMY(SUPSemEventMultiSignal)
DUMMY(SUPSemEventMultiWaitNoResume)
DUMMY(SUPSemEventMultiReset)
DUMMY(VMMR3GetHostToGuestSwitcher)
DUMMY(RTHeapSimpleRelocate)
DUMMY(RTHeapSimpleAlloc)
DUMMY(RTHeapSimpleInit)
DUMMY(RTHeapSimpleFree)
DUMMY(RTAvloU32Remove)
DUMMY(RTAvloU32Get)
DUMMY(RTAvloU32GetBestFit)
DUMMY(RTAvloU32DoWithAll)
DUMMY(RTAvloU32Insert)
DUMMY(IOMInterpretOUT)
DUMMY(IOMInterpretOUTS)
DUMMY(IOMInterpretIN)
DUMMY(IOMInterpretINS)
DUMMY(DISInstrToStrWithReader)
DUMMY(DISInstrToStrEx)
DUMMY(RTFileQueryFsSizes)
DUMMY(RTAvlrFileOffsetGet)
DUMMY(RTAvlrFileOffsetGetBestFit)
DUMMY(RTAvlrFileOffsetInsert)
DUMMY(RTAvlrFileOffsetRemove)
DUMMY(RTAvlrU64Destroy)
DUMMY(RTAvlrU64DoWithAll)
DUMMY(RTAvlrU64GetBestFit)
DUMMY(RTAvlrU64Insert)
DUMMY(RTAvlrU64RangeGet)
DUMMY(RTAvlrU64RangeRemove)
DUMMY(RTAvlrU64Remove)
DUMMY(RTSocketToNative)
DUMMY(RTStrCat)
DUMMY(RTStrCatP)
DUMMY(RTStrStr)
DUMMY(RTTcpClientCloseEx)
DUMMY(RTTcpClientConnectEx)
DUMMY(RTTcpFlush)
DUMMY(RTTcpGetLocalAddress)
DUMMY(RTTcpGetPeerAddress)
DUMMY(RTTcpRead)
DUMMY(RTTcpReadNB)
DUMMY(RTTcpSelectOne)
DUMMY(RTTcpSelectOneEx)
DUMMY(RTTcpSetSendCoalescing)
DUMMY(RTTcpSgWrite)
DUMMY(RTTcpSgWriteNB)
DUMMY(RTTcpWrite)
DUMMY(RTTcpWriteNB)
DUMMY(RTTimeLocalExplode)
DUMMY(RTSymlinkCreate)
DUMMY(RTSymlinkRead)
DUMMY(RTSymlinkDelete)
DUMMY(RTNetIPv6PseudoChecksumEx)
DUMMY(pthread_mutex_timedlock)
DUMMY(pthread_kill)
DUMMY(RTZipXarFsStreamFromIoStream)
DUMMY(FTMR3CancelStandby)
DUMMY(FTMR3PowerOn)
DUMMY(GIMReadMsr)
DUMMY(GIMR3Term)
DUMMY(GIMWriteMsr)
} /* extern "C" */

View File

@ -0,0 +1,36 @@
/*
* \brief VirtualBox utilities
* \author Christian Helmuth
* \date 2013-08-28
*/
/*
* Copyright (C) 2013-2014 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>
/**
* 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_ */

View File

@ -48,6 +48,7 @@ rump_ext2
thread
pthread
vbox_auto_win7
vbox_auto_win7_vbox5
vbox_auto_win7_share
vbox_auto_win8
vbox_auto_win81_64