ports: add VirtualBox as VMM for Genode

Fixes #1055
This commit is contained in:
Alexander Boettcher 2013-08-21 11:37:21 +02:00 committed by Christian Helmuth
parent 2e6f281cf0
commit d8c2a908b8
77 changed files with 6913 additions and 0 deletions

View File

@ -310,6 +310,7 @@ LIBC_IMPORT_INCLUDES += include/libc-i386/machine/_types.h \
include/libc-i386/machine/param.h \
include/libc-i386/machine/vm.h \
include/libc-i386/machine/specialreg.h \
include/libc-i386/machine/npx.h \
include/libc-i386/stdarg.h \
include/libc-i386/float.h
@ -326,6 +327,7 @@ LIBC_IMPORT_INCLUDES += include/libc-amd64/machine/_types.h \
include/libc-amd64/machine/param.h \
include/libc-amd64/machine/vm.h \
include/libc-amd64/machine/specialreg.h \
include/libc-amd64/machine/fpu.h \
include/libc-amd64/stdarg.h \
include/libc-amd64/float.h

View File

@ -0,0 +1 @@
include $(call select_from_repositories,lib/import/import-libc.mk)

View File

@ -0,0 +1,8 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
SRC_CC = sup.cc
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(REP_DIR)/src/virtualbox
vpath sup.cc $(REP_DIR)/src/virtualbox/accloff/

View File

@ -0,0 +1,8 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
SRC_CC = sup.cc
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(REP_DIR)/src/virtualbox
vpath sup.cc $(REP_DIR)/src/virtualbox/accloff/

View File

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

View File

@ -0,0 +1,8 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
SRC_CC = sup.cc
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(REP_DIR)/src/virtualbox
vpath sup.cc $(REP_DIR)/src/virtualbox/accloff/

View File

@ -0,0 +1,8 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
SRC_CC = sup.cc
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(REP_DIR)/src/virtualbox
vpath sup.cc $(REP_DIR)/src/virtualbox/accloff/

View File

@ -0,0 +1,37 @@
include $(REP_DIR)/lib/mk/virtualbox-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,66 @@
VBOX_MACH := $(filter $(SPECS), x86_32 x86_64)
VBOX_MACH_CC_OPT_x86_32 = -DRT_ARCH_X86 -D__X86__ -DHC_ARCH_BITS=32
VBOX_MACH_ASM_OPT_x86_32 = -f elf32
VBOX_MACH_CC_OPT_x86_64 = -DRT_ARCH_AMD64 -D__AMD64__ -DHC_ARCH_BITS=64
VBOX_MACH_ASM_OPT_x86_64 = -f elf64
include $(REP_DIR)/ports/virtualbox.inc
ifeq ($(shell which yasm),)
REQUIRES += installation_of_yasm
REQUIRES += installation_of_iasl
endif
VIRTUALBOX_DIR = $(REP_DIR)/contrib/$(VIRTUALBOX)
VBOX_DIR = $(VIRTUALBOX_DIR)/src/VBox
VBOX_CC_OPT += -DIN_RING3 -DVBOX -DVBOX_OSE \
-DGC_ARCH_BITS=64 \
-D_FILE_OFFSET_BITS=64 -DLOG_ENABLED
VBOX_CC_OPT += $(VBOX_MACH_CC_OPT_$(VBOX_MACH))
# Required if on a 32bit host 64bit VMs should be executed
# VBOX_CC_OPT += -DVBOX_WITH_64_BITS_GUESTS
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 += -DVBOXBFE_WITHOUT_COM
VBOX_CC_OPT += -DVBOX_WITHOUT_TESTING_FEATURES
VBOX_CC_OPT += -DUSE_SDL
VBOX_CC_OPT += -DRTLOG_REL_ENABLED -DRT_STRICT -DVBOX_STRICT
VBOX_CC_OPT += -DVBOX_VERSION_MAJOR=$(VIRTUALBOX_VERSION_MAJOR) \
-DVBOX_VERSION_MINOR=$(VIRTUALBOX_VERSION_MINOR) \
-DVBOX_VERSION_BUILD=$(VIRTUALBOX_VERSION_BUILD)
VBOX_CC_OPT += -DVBOX_HDD_NO_DYNAMIC_BACKENDS
CC_WARN += -Wno-trigraphs
CC_OPT += $(VBOX_CC_OPT)
LIBS += virtualbox_libc_support
INC_DIR += $(REP_DIR)/src/virtualbox/include
INC_DIR += $(VIRTUALBOX_DIR)/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,77 @@
include $(REP_DIR)/lib/mk/virtualbox-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/HGSMI/HGSMIHost.cpp
SRC_CC += Devices/Graphics/HGSMI/HGSMIHostHlp.cpp
SRC_CC += Devices/Graphics/HGSMI/SHGSMIHost.cpp
SRC_CC += Devices/Storage/DevATA.cpp
SRC_CC += Devices/Storage/Debug.cpp
SRC_CC += Devices/Storage/fdc.c
SRC_CC += Devices/Storage/DrvRawImage.cpp
SRC_CC += Devices/Network/DevPCNet.cpp
SRC_CC += Devices/VMMDev/VMMDev.cpp
SRC_CC += GuestHost/HGSMI/HGSMICommon.cpp
SRC_CC += Devices/Serial/DevSerial.cpp
SRC_CC += Devices/PC/DevIoApic.cpp
INC_DIR += $(VBOX_DIR)/Devices/build
INC_DIR += $(VBOX_DIR)/Devices/Bus
CC_WARN += -Wno-unused-but-set-variable
#
# Definitions needed to compile DevVGA.cpp
#
# VBOX_WITH_VDMA is needed because otherwise, the alignment of the
# VGASTATE::lock member would violate the assertion
# '!((uintptr_t)pvSample & 7)' in 'stamR3RegisterU'.
#
CC_OPT += -DVBOX_WITH_HGSMI -DVBOX_WITH_WDDM -DVBOX_WITH_VDMA
Devices/Graphics/DevVGA.cpp: vbetables.h
vbetables.h: vbetables-gen
$(MSG_CONVERT)$@
$(VERBOSE)./$^ > $@
vbetables-gen: Devices/Graphics/BIOS/vbetables-gen.c
$(MSG_BUILD)$@
$(VERBOSE)g++ $(VBOX_CC_OPT) $(addprefix -I,$(INC_DIR)) -o $@ $^
Devices/PC/ACPI/VBoxAcpi.cpp: 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 $< && \
iasl -tc -vs -p $@ $@.pre && \
mv $@ $@.tmp && \
sed "s/AmlCode/AmlCodeSsdtCpuHotPlug/g" <$@.tmp >$@ && \
rm $@.tmp $@.pre
vpath %.dsl $(VBOX_DIR)/Devices/PC

View File

@ -0,0 +1,15 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
SRC_CC += VMM/VMMR3/DBGFAddr.cpp
SRC_CC += VMM/VMMR3/DBGFDisas.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,16 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
SRC_CC += Devices/Input/DrvKeyboardQueue.cpp
SRC_CC += Devices/Input/DrvMouseQueue.cpp
SRC_CC += Devices/Storage/DrvBlock.cpp
SRC_CC += Devices/Storage/DrvMediaISO.cpp
SRC_CC += Devices/Storage/DrvVD.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 += Main/src-client/MouseImpl.cpp
# includes needed by 'MouseImpl.cpp'
INC_DIR += $(VBOX_DIR)/Main/include
INC_DIR += $(VBOX_DIR)/Frontends/VBoxBFE

View File

@ -0,0 +1,8 @@
include $(REP_DIR)/lib/mk/virtualbox-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,29 @@
include $(REP_DIR)/lib/mk/virtualbox-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,119 @@
include $(REP_DIR)/lib/mk/virtualbox-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.6
GENERIC_SRC_CC = $(notdir $(wildcard $(VBOX_DIR)/Runtime/generic/*.cpp))
FILTERED_OUT_SRC_CC = RTLogDefaultInit-generic.cpp \
RTTimeLocalExplode-generic.cpp \
semrw-lockless-generic.cpp \
tls-generic.cpp \
RTSemEventMultiWait-2-ex-generic.cpp \
RTLogWriteStdErr-generic.cpp \
RTLogWriteStdOut-generic.cpp \
RTMpGetDescription-generic-stub.cpp \
RTSemEventWait-2-ex-generic.cpp \
RTSemEventWait-generic.cpp \
RTSemEventWaitNoResume-2-ex-generic.cpp \
RTFileExists-generic.cpp \
RTSemMutexRequest-generic.cpp \
RTSemMutexRequestDebug-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/err/RTErrConvertFromErrno.cpp
SRC_CC += Runtime/common/alloc/memcache.cpp
SRC_CC += Runtime/common/checksum/md5.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/lockvalidator.cpp
SRC_CC += Runtime/common/misc/once.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/path/RTPathAbsDup.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/RTPathJoinA.cpp
SRC_CC += Runtime/common/path/RTPathParse.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/rand/rand.cpp
SRC_CC += Runtime/common/rand/randadv.cpp
SRC_CC += Runtime/common/rand/randparkmiller.cpp
SRC_CC += Runtime/common/zip/zip.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/RTStrNCmp.cpp
SRC_CC += Runtime/common/string/RTStrNLen.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/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/strstrip.cpp
SRC_CC += Runtime/common/string/strtonum.cpp
SRC_CC += Runtime/common/string/unidata.cpp
SRC_CC += Runtime/common/string/utf-16.cpp
SRC_CC += Runtime/common/string/utf-8-case.cpp
SRC_CC += Runtime/common/string/utf-8.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/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/r3/alloc.cpp
SRC_CC += Runtime/r3/fileio.cpp
SRC_CC += Runtime/r3/path.cpp
SRC_CC += Runtime/r3/generic/semspinmutex-r3-generic.cpp
SRC_CC += Runtime/r3/posix/env-posix.cpp
SRC_CC += Runtime/r3/posix/fileio-posix.cpp
SRC_CC += Runtime/r3/posix/pipe-posix.cpp
SRC_CC += Runtime/r3/posix/poll-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/process.cpp
SRC_CC += Runtime/r3/stream.cpp
SRC_CC += Runtime/VBox/log-vbox.cpp
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_CC += Runtime/common/err/errmsg.cpp
Runtime/common/err/errmsg.cpp: 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,16 @@
include $(REP_DIR)/lib/mk/virtualbox-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/VHD.cpp
SRC_CC += Storage/VHDX.cpp
SRC_CC += Storage/VMDK.cpp

View File

@ -0,0 +1,76 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
SRC_CC += VMM/VMMR3/VM.cpp
SRC_CC += VMM/VMMAll/VMAll.cpp
SRC_CC += VMM/VMMAll/VMMAll.cpp
SRC_CC += VMM/VMMR3/VMM.cpp
SRC_CC += VMM/VMMR3/STAM.cpp
SRC_CC += VMM/VMMR3/SSM.cpp
SRC_CC += VMM/VMMR3/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/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/VMMAll/CPUMAllRegs.cpp
SRC_CC += VMM/VMMR3/VMEmt.cpp
SRC_CC += VMM/VMMR3/VMReq.cpp
SRC_CC += VMM/VMMR3/DBGFInfo.cpp
SRC_CC += VMM/VMMR3/CPUM.cpp
SRC_CC += VMM/VMMAll/EMAll.cpp
SRC_CC += VMM/VMMR3/EM.cpp
SRC_CC += VMM/VMMR3/TRPM.cpp
SRC_CC += VMM/VMMAll/SELMAll.cpp
SRC_CC += VMM/VMMAll/PATMAll.cpp
SRC_CC += VMM/VMMR3/PATM.cpp
SRC_CC += VMM/VMMR3/PATMPatch.cpp
SRC_CC += VMM/VMMR3/PATMA.asm
SRC_CC += VMM/VMMR3/PATMSSM.cpp
SRC_CC += VMM/VMMR3/PATMGuest.cpp
SRC_CC += VMM/VMMAll/CSAMAll.cpp
SRC_CC += VMM/VMMR3/CSAM.cpp
SRC_CC += VMM/VMMR3/EMHwaccm.cpp
SRC_CC += VMM/VMMAll/REMAll.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,7 @@
include $(REP_DIR)/lib/mk/virtualbox-common.inc
ZLIB_DIR = $(VIRTUALBOX_DIR)/src/libs/zlib-1.2.6
INC_DIR += $(ZLIB_DIR)
SRC_C = $(notdir $(wildcard $(ZLIB_DIR)/*.c))
vpath % $(ZLIB_DIR)

View File

@ -0,0 +1,84 @@
# FreeBSD libc code
SRC_C += gen/ldexp.c
SRC_C += gen/usleep.c
SRC_C += stdio/ferror.c
SRC_C += stdio/fflush.c
SRC_C += stdio/fileno.c
SRC_C += stdio/findfp.c
SRC_C += stdio/stdio.c
SRC_C += string/memchr.c
SRC_C += string/strncmp.c
# Genode libc code
SRC_CC += libc/clock_gettime.cc
SRC_CC += libc/nanosleep.cc
SRC_CC += libc/file_operations.cc
SRC_CC += libc/plugin_registry.cc
SRC_CC += libc/fd_alloc.cc
SRC_CC += libc/libc_mem_alloc.cc
SRC_CC += libc/gettimeofday.cc
SRC_CC += libc/plugin.cc
SRC_CC += libc/select.cc
# Genode terminal plugin
SRC_CC += libc_terminal/plugin.cc
# Genode fs plugin
SRC_CC += libc_fs/plugin.cc
SRC_CC += libc/pread_pwrite.cc
# Genode lock pipe plugin (needed by VirtualBox "HostSerial" driver)
SRC_CC += libc_lock_pipe/plugin.cc
# Genode pthread code
SRC_CC += pthread/semaphore.cc
SRC_CC += pthread/thread.cc
LIBS += timed_semaphore
# setjmp/longjmp needed by recompiler
LIBS += libc-setjmp
INC_DIR += $(LIBC_REP_DIR)/src/lib/libc
vpath %.cc $(LIBC_REP_DIR)/src/lib
# FreeBSD libc FPU math
FPU_SRC_C = $(wildcard $(LIBC_DIR)/msun/src/*.c) \
$(wildcard $(LIBC_DIR)/msun/ld80/*.c) \
$(wildcard $(LIBC_DIR)/msun/bsdsrc/*.c)
SRC_C += $(filter-out e_rem_pio2.c e_rem_pio2f.c s_exp2l.c, $(notdir $(FPU_SRC_C)))
vpath %.c $(LIBC_DIR)/msun/src
vpath %.c $(LIBC_DIR)/msun/ld80
vpath %.c $(LIBC_DIR)/msun/bsdsrc
# Disable warnings for selected files, i.e., to suppress
# 'is static but used in inline function which is not static'
# messages
CC_OPT_s_tanf = -w
CC_OPT_s_tan = -w
CC_OPT_s_sin = -w
CC_OPT_s_cos = -w
CC_OPT_s_cosf = -w
CC_OPT_s_sinf = -w
CC_OPT_k_cosf = -w
CC_OPT_k_sinf = -w
CC_OPT_k_tanf = -w
# Work-around to get over doubly defined symbols produced by several sources
# that include 'e_rem_pio2.c' and 'e_rem_pio2f.c'. To avoid symbol clashes,
# we rename each occurrence by adding the basename of the compilation unit
# as suffix. (copied from libm.mk)
CC_OPT_s_sin += -D__ieee754_rem_pio2=__ieee754_rem_pio2_s_sin
CC_OPT_s_cos += -D__ieee754_rem_pio2=__ieee754_rem_pio2_s_cos
CC_OPT_s_tan += -D__ieee754_rem_pio2=__ieee754_rem_pio2_s_tan
CC_OPT_s_sinf += -D__ieee754_rem_pio2f=__ieee754_rem_pio2f_s_sinf
CC_OPT_s_sinf += -D__kernel_cosdf=__kernel_cosdf_sinf
CC_OPT_s_cosf += -D__ieee754_rem_pio2f=__ieee754_rem_pio2f_s_cosf
CC_OPT_s_cosf += -D__kernel_sindf=__kernel_sindf_cosf
CC_OPT_s_tanf += -D__ieee754_rem_pio2f=__ieee754_rem_pio2f_s_tanf
CC_OPT += -D__inline=inline
INC_DIR += $(LIBC_DIR)/msun/src $(LIBC_DIR)/msun/ld80 $(LIBC_DIR)/msun/bsdsrc
# vi: set ft=make :

View File

@ -0,0 +1,7 @@
include $(REP_DIR)/lib/mk/seoul_libc_support.mk
SRC_C += fenv.c
vpath fenv.c $(LIBC_DIR)/msun/i387
include $(REP_DIR)/lib/mk/virtualbox_libc_support.inc

View File

@ -0,0 +1,7 @@
include $(REP_DIR)/lib/mk/seoul_libc_support.mk
SRC_C += fenv.c
vpath fenv.c $(LIBC_DIR)/msun/amd64
include $(REP_DIR)/lib/mk/virtualbox_libc_support.inc

View File

@ -0,0 +1,5 @@
VIRTUALBOX_VERSION_MAJOR := 4
VIRTUALBOX_VERSION_MINOR := 2
VIRTUALBOX_VERSION_BUILD := 16
VIRTUALBOX = virtualbox-$(VIRTUALBOX_VERSION_MAJOR).$(VIRTUALBOX_VERSION_MINOR).$(VIRTUALBOX_VERSION_BUILD)

81
ports/ports/virtualbox.mk Normal file
View File

@ -0,0 +1,81 @@
include ports/virtualbox.inc
VIRTUALBOX = virtualbox-4.2.16
VIRTUALBOX_TBZ2 = VirtualBox-4.2.16.tar.bz2
VIRTUALBOX_URL = http://download.virtualbox.org/virtualbox/4.2.16/$(VIRTUALBOX_TBZ2)
VIRTUALBOX_MD5 = c4a36e2099a317f4715cd3861cdae238
VIRTUALBOX_CONTENT = src/VBox/VMM \
src/VBox/Devices \
src/VBox/Runtime \
src/VBox/GuestHost/HGSMI \
src/VBox/Frontends/VBoxBFE \
src/VBox/Storage \
src/VBox/Disassembler \
src/recompiler \
src/VBox/Main/include/MouseImpl.h \
src/VBox/Main/include/ConsoleEvents.h \
src/VBox/Main/src-client/MouseImpl.cpp \
src/libs/zlib-1.2.6 \
src/libs/liblzf-3.4 \
include/VBox/vmm \
include/iprt \
$(addprefix include/VBox/,types.h cdefs.h hgcmsvc.h \
err.h dis.h disopcode.h \
log.h sup.h pci.h param.h \
ostypes.h VMMDev.h VMMDev2.h \
vusb.h dbg.h version.h \
VBoxVideo.h Hardware bioslogo.h \
scsi.h HGSMI) \
include/VBox/msi.h \
include/VBox/DevPCNet.h \
include/VBox/asmdefs.mac \
include/VBox/err.mac \
include/VBox/vd.h \
include/VBox/vd-ifs.h \
include/VBox/vd-plugin.h \
include/VBox/vd-ifs-internal.h \
include/VBox/vd-cache-plugin.h
#
# Interface to top-level prepare Makefile
#
PORTS += $(VIRTUALBOX)
#
# Check for tools
#
$(call check_tool,iasl)
PATCHES := $(shell find $(CURDIR)/src/virtualbox/ -name "*.patch")
apply_patches:
$(VERBOSE)set -e; for p in $(PATCHES); do \
echo $$p; \
patch -p0 -N -d $(CONTRIB_DIR)/$(VIRTUALBOX) -i $$p; \
done
prepare:: $(CONTRIB_DIR)/$(VIRTUALBOX) apply_patches
#
# Port-specific local rules
#
$(DOWNLOAD_DIR)/$(VIRTUALBOX_TBZ2):
$(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(VIRTUALBOX_URL) && touch $@
$(DOWNLOAD_DIR)/$(VIRTUALBOX_SIG):
$(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(VIRTUALBOX_URL_SIG) && touch $@
$(DOWNLOAD_DIR)/$(VIRTUALBOX_TBZ2).verified: $(DOWNLOAD_DIR)/$(VIRTUALBOX_TBZ2)
$(VERBOSE)$(HASHVERIFIER) $(DOWNLOAD_DIR)/$(VIRTUALBOX_TBZ2) $(VIRTUALBOX_MD5) md5
$(VERBOSE)touch $@
$(CONTRIB_DIR)/$(VIRTUALBOX): $(DOWNLOAD_DIR)/$(VIRTUALBOX_TBZ2).verified
$(VERBOSE)tar xfj $(<:.verified=) \
--transform "s/$(VIRTUALBOX_TBZ2:.tar.bz2=)/$(VIRTUALBOX)/" \
-C $(CONTRIB_DIR) \
$(addprefix $(VIRTUALBOX_TBZ2:.tar.bz2=)/,$(VIRTUALBOX_CONTENT)) && \
rm $(CONTRIB_DIR)/$(VIRTUALBOX)/src/VBox/Frontends/VBoxBFE/SDLConsole.h && \
rm $(CONTRIB_DIR)/$(VIRTUALBOX)/src/VBox/Frontends/VBoxBFE/SDLFramebuffer.h; \
if [ $$? -ne 0 ]; then rm -r $(CONTRIB_DIR)/$(VIRTUALBOX); exit 1; fi

123
ports/run/virtualbox.run Normal file
View File

@ -0,0 +1,123 @@
set build_components {
core init virtualbox
server/ram_fs
drivers/input
drivers/framebuffer
drivers/timer
}
lappend_if [have_spec acpi] build_components drivers/acpi
lappend_if [have_spec pci] build_components drivers/pci
build $build_components
create_boot_directory
set config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service><parent/><any-child/></any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="ram_fs">
<resource name="RAM" quantum="256M"/>
<provides><service name="File_system"/></provides>
<config>
<content>
<dir name="iso">
<rom name="test.iso" />
</dir>
</content>
<policy label="" root="/" writeable="yes" />
</config>
</start>}
append_if [have_spec acpi] config {
<start name="acpi">
<resource name="RAM" quantum="5M"/>
<binary name="acpi_drv"/>
<provides>
<service name="PCI"/>
<service name="IRQ" />
</provides>
<route>
<service name="PCI"> <any-child /> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
</start>}
append_if [expr ![have_spec acpi] && [have_spec pci]] config {
<start name="pci_drv">
<resource name="RAM" quantum="2M"/>
<provides> <service name="PCI"/> </provides>
</start> }
append_if [have_spec ps2] config {
<start name="ps2_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="Input"/></provides>
</start> }
append_if [have_spec framebuffer] config {
<start name="fb_drv">
<resource name="RAM" quantum="4M"/>
<provides><service name="Framebuffer"/></provides>
</start>}
append_if [have_spec sdl] config {
<start name="fb_sdl">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Input"/>
<service name="Framebuffer"/>
</provides>
</start>}
append config {
<start name="virtualbox">
<resource name="RAM" quantum="1G"/>
<config>
<image type="iso" file="/iso/test.iso" />
</config>
<route>
<service name="File_system"> <child name="ram_fs"/> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
</start>
</config>
}
install_config $config
set boot_modules { core init timer virtualbox ram_fs test.iso }
# platform-specific modules
lappend_if [have_spec ps2] boot_modules ps2_drv
lappend_if [have_spec acpi] boot_modules acpi_drv
lappend_if [have_spec pci] boot_modules pci_drv
lappend_if [have_spec framebuffer] boot_modules fb_drv
lappend_if [have_spec linux] boot_modules fb_sdl
lappend_if [have_spec nova] boot_modules pci_device_pd
build_boot_image $boot_modules
append qemu_args " -m 512 "
append qemu_args " -cpu phenom "
run_genode_until forever

View File

@ -0,0 +1,97 @@
/*
* \brief Genode specific VirtualBox SUPLib supplements.
* File used by Genode platforms not supporting hardware
* virtualisation features.
* \author Alexander Boettcher
* \date 2013-11-18
*/
/*
* 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/printf.h>
#include <base/semaphore.h>
/* VirtualBox includes */
#include <VBox/vmm/vm.h>
#include <VBox/err.h>
/* Genode's VirtualBox includes */
#include "sup.h"
#include "vmm_memory.h"
/* VirtualBox SUPLib interface */
int SUPR3QueryVTxSupported(void)
{
return VERR_INTERNAL_ERROR;
}
int SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
{
return VERR_INTERNAL_ERROR;
}
static Genode::Semaphore *r0_halt_sem()
{
static Genode::Semaphore sem;
return &sem;
}
int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
{
switch(uOperation)
{
case VMMR0_DO_GVMM_CREATE_VM:
genode_VMMR0_DO_GVMM_CREATE_VM(pReqHdr);
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_HALT:
r0_halt_sem()->down();
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_WAKE_UP:
r0_halt_sem()->up();
return VINF_SUCCESS;
case VMMR0_DO_VMMR0_INIT:
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_POLL:
/* called by 'vmR3HaltGlobal1Halt' */
PDBG("SUPR3CallVMMR0Ex: VMMR0_DO_GVMM_SCHED_POLL");
return VINF_SUCCESS;
default:
PERR("SUPR3CallVMMR0Ex: unhandled uOperation %d", uOperation);
return VERR_GENERAL_FAILURE;
}
}
/**
* Dummies and unimplemented stuff.
*/
uint64_t genode_cpu_hz() {
return 1000000000ULL; /* XXX fixed 1GHz return value */
}
bool Vmm_memory::unmap_from_vm(RTGCPHYS GCPhys)
{
PWRN("%s unimplemented", __func__);
return false;
}
extern "C" int pthread_yield() {
PWRN("%s unimplemented", __func__);
return 0;
}

View File

@ -0,0 +1,37 @@
+++ src/VBox/Devices/PC/DevACPI.cpp
@@ -438,7 +438,9 @@
uint32_t u32GPE0BLK; /**< port addr of gen-purp event 0 regs block */
uint32_t u32GPE1BLK; /**< port addr of gen-purp event 1 regs block */
uint8_t u8PM1EVTLEN; /**< bytes decoded by PM1a_EVT_BLK. >= 4 */
+#define ACPI_PM1_EVT_LEN 0x4
uint8_t u8PM1CTLLEN; /**< bytes decoded by PM1b_CNT_BLK. >= 2 */
+#define ACPI_PM1_CNT_LEN 0x2
uint8_t u8PM2CTLLEN; /**< bytes decoded by PM2_CNT_BLK. >= 1 or 0 */
uint8_t u8PMTMLEN; /**< bytes decoded by PM_TMR_BLK. ==4 */
uint8_t u8GPE0BLKLEN; /**< bytes decoded by GPE0_BLK. %2==0 */
@@ -1842,10 +1844,10 @@
} while (0)
#define L (GPE0_BLK_LEN / 2)
- R(PM1a_EVT_OFFSET+2, 1, acpiPM1aEnWrite, acpiPm1aEnRead, "ACPI PM1a Enable");
- R(PM1a_EVT_OFFSET, 1, acpiPM1aStsWrite, acpiPm1aStsRead, "ACPI PM1a Status");
- R(PM1a_CTL_OFFSET, 1, acpiPM1aCtlWrite, acpiPm1aCtlRead, "ACPI PM1a Control");
- R(PM_TMR_OFFSET, 1, NULL, acpiPMTmrRead, "ACPI PM Timer");
+ R(PM1a_EVT_OFFSET+2, ACPI_PM1_EVT_LEN / 2, acpiPM1aEnWrite, acpiPm1aEnRead, "ACPI PM1a Enable");
+ R(PM1a_EVT_OFFSET, ACPI_PM1_EVT_LEN / 2, acpiPM1aStsWrite, acpiPm1aStsRead, "ACPI PM1a Status");
+ R(PM1a_CTL_OFFSET, ACPI_PM1_CNT_LEN, acpiPM1aCtlWrite, acpiPm1aCtlRead, "ACPI PM1a Control");
+ R(PM_TMR_OFFSET, 4, NULL, acpiPMTmrRead, "ACPI PM Timer");
R(GPE0_OFFSET + L, L, acpiGpe0EnWrite, acpiGpe0EnRead, "ACPI GPE0 Enable");
R(GPE0_OFFSET, L, acpiGpe0StsWrite, acpiGpe0StsRead, "ACPI GPE0 Status");
#undef L
@@ -2189,8 +2191,8 @@
fadt.u32PMTMRBLK = RT_H2LE_U32(acpiCalcPmPort(pThis, PM_TMR_OFFSET));
fadt.u32GPE0BLK = RT_H2LE_U32(acpiCalcPmPort(pThis, GPE0_OFFSET));
fadt.u32GPE1BLK = RT_H2LE_U32(acpiCalcPmPort(pThis, GPE1_OFFSET));
- fadt.u8PM1EVTLEN = 4;
- fadt.u8PM1CTLLEN = 2;
+ fadt.u8PM1EVTLEN = ACPI_PM1_EVT_LEN;
+ fadt.u8PM1CTLLEN = ACPI_PM1_CNT_LEN;
fadt.u8PM2CTLLEN = 0;
fadt.u8PMTMLEN = 4;
fadt.u8GPE0BLKLEN = GPE0_BLK_LEN;

View File

@ -0,0 +1,9 @@
+++ src/VBox/Devices/PC/DrvACPI.cpp
@@ -44,6 +44,7 @@
# include <IOKit/ps/IOPSKeys.h>
#endif
+#undef RT_OS_FREEBSD
#ifdef RT_OS_FREEBSD
# include <sys/ioctl.h>
# include <dev/acpica/acpiio.h>

View File

@ -0,0 +1,21 @@
+++ src/VBox/Devices/PC/DevACPI.cpp
@@ -3254,13 +3256,13 @@
} while (0)
R(SMI_CMD, 1, acpiSmiWrite, NULL, "ACPI SMI");
#ifdef DEBUG_ACPI
- R(DEBUG_HEX, 1, acpiDhexWrite, NULL, "ACPI Debug hex");
- R(DEBUG_CHR, 1, acpiDchrWrite, NULL, "ACPI Debug char");
+ R(DEBUG_HEX, 4, acpiDhexWrite, NULL, "ACPI Debug hex");
+// R(DEBUG_CHR, 1, acpiDchrWrite, NULL, "ACPI Debug char");
#endif
- R(BAT_INDEX, 1, acpiBatIndexWrite, NULL, "ACPI Battery status index");
- R(BAT_DATA, 1, NULL, acpiBatDataRead, "ACPI Battery status data");
- R(SYSI_INDEX, 1, acpiSysInfoIndexWrite, NULL, "ACPI system info index");
- R(SYSI_DATA, 1, acpiSysInfoDataWrite, acpiSysInfoDataRead, "ACPI system info data");
+ R(BAT_INDEX, 4, acpiBatIndexWrite, NULL, "ACPI Battery status index");
+ R(BAT_DATA, 4, NULL, acpiBatDataRead, "ACPI Battery status data");
+ R(SYSI_INDEX, 4, acpiSysInfoIndexWrite, NULL, "ACPI system info index");
+ R(SYSI_DATA, 4, acpiSysInfoDataWrite, acpiSysInfoDataRead, "ACPI system info data");
R(ACPI_RESET_BLK, 1, acpiResetWrite, NULL, "ACPI Reset");
#undef R

View File

@ -0,0 +1,32 @@
+++ src/VBox/Devices/Graphics/DevVGA.cpp
@@ -6024,10 +5984,10 @@
#endif /* VBOX_WITH_HGSMI */
#ifdef CONFIG_BOCHS_VBE
- rc = PDMDevHlpIOPortRegister(pDevIns, 0x1ce, 1, NULL, vgaIOPortWriteVBEIndex, vgaIOPortReadVBEIndex, NULL, NULL, "VGA/VBE - Index");
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x1ce, 2, NULL, vgaIOPortWriteVBEIndex, vgaIOPortReadVBEIndex, NULL, NULL, "VGA/VBE - Index");
if (RT_FAILURE(rc))
return rc;
- rc = PDMDevHlpIOPortRegister(pDevIns, 0x1cf, 1, NULL, vgaIOPortWriteVBEData, vgaIOPortReadVBEData, NULL, NULL, "VGA/VBE - Data");
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x1cf, 2, NULL, vgaIOPortWriteVBEData, vgaIOPortReadVBEData, NULL, NULL, "VGA/VBE - Data");
if (RT_FAILURE(rc))
return rc;
#endif /* CONFIG_BOCHS_VBE */
@@ -6470,7 +6430,7 @@
/*
* Register I/O Port for the VBE BIOS Extra Data.
*/
- rc = PDMDevHlpIOPortRegister(pDevIns, VBE_EXTRA_PORT, 1, NULL, vbeIOPortWriteVBEExtra, vbeIOPortReadVBEExtra, NULL, NULL, "VBE BIOS Extra Data");
+ rc = PDMDevHlpIOPortRegister(pDevIns, VBE_EXTRA_PORT, 2, NULL, vbeIOPortWriteVBEExtra, vbeIOPortReadVBEExtra, NULL, NULL, "VBE BIOS Extra Data");
if (RT_FAILURE(rc))
return rc;
#endif /* VBE_NEW_DYN_LIST */
@@ -6478,7 +6438,7 @@
/*
* Register I/O Port for the BIOS Logo.
*/
- rc = PDMDevHlpIOPortRegister(pDevIns, LOGO_IO_PORT, 1, NULL, vbeIOPortWriteCMDLogo, vbeIOPortReadCMDLogo, NULL, NULL, "BIOS Logo");
+ rc = PDMDevHlpIOPortRegister(pDevIns, LOGO_IO_PORT, 2, NULL, vbeIOPortWriteCMDLogo, vbeIOPortReadCMDLogo, NULL, NULL, "BIOS Logo");
if (RT_FAILURE(rc))
return rc;

View File

@ -0,0 +1,45 @@
/*
* \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.
*/
/* Genode includes */
#include <base/printf.h>
/* VirtualBox includes */
#include <VBox/vmm/vmapi.h>
#define CXX_DUMMY(retval, signature) \
int signature { \
PDBG( #signature " called, not implemented"); \
for (;;); \
return retval; \
}
#define CHECKED_CXX_DUMMY(retval, signature) \
int signature { \
PINF( #signature " called, not implemented"); \
return retval; \
}
CXX_DUMMY(-1, VMMR3InitCompleted(VM*, VMINITCOMPLETED))
CXX_DUMMY(-1, VMMR3InitR0(VM*))
CXX_DUMMY(-1, VMMR3InitRC(VM*))
CXX_DUMMY(-1, VMMR3Init(VM*))
CXX_DUMMY(-1, VMMR3Relocate(VM*, long long))
CXX_DUMMY(-1, VMMR3Term(VM*))
CXX_DUMMY(-1, PGMR3InitCompleted(VM*, VMINITCOMPLETED))
CXX_DUMMY(-1, PGMNotifyNxeChanged(VMCPU*, bool))
CXX_DUMMY(-1, VMMR3SendSipi(VM*, unsigned int, unsigned int))
CXX_DUMMY(-1, VMMR3SendInitIpi(VM*, unsigned int))
CXX_DUMMY(-1, VMMR3EmtRendezvousFF(VM*, VMCPU*))
CXX_DUMMY(-1, VMMR3YieldStop(VM*))
CXX_DUMMY(-1, VMMR3EmtRendezvousSetDisabled(VMCPU*, bool))

View File

@ -0,0 +1,23 @@
+++ src/VBox/Devices/Storage/DevATA.cpp 2014-01-28 15:13:14.903523393 +0100
@@ -4596,9 +4596,9 @@
if ((u64ResetTimeStop - pCtl->u64ResetTime) >= 10)
{
- LogRel(("PIIX3 ATA LUN#%d: Async I/O thread probably stuck in operation, interrupting\n", s->iLUN));
+ LogRel(("PIIX3 ATA LUN#%d: Async I/O thread probably stuck in operation, interrupting %llu %llu\n", s->iLUN, u64ResetTimeStop, pCtl->u64ResetTime));
pCtl->u64ResetTime = u64ResetTimeStop;
- RTThreadPoke(pCtl->AsyncIOThread);
+// RTThreadPoke(pCtl->AsyncIOThread);
}
}
#endif
@@ -4699,6 +4699,9 @@
/* Save the timestamp we started the reset. */
pCtl->u64ResetTime = RTTimeMilliTS();
+ LogRel(("PIIX3 ATA ------------------------------------ reset time %llu\n",
+ pCtl->u64ResetTime));
+
/* Issue the reset request now. */
ataAsyncIOPutRequest(pCtl, &g_ataResetARequest);
#else /* !IN_RING3 */

View File

@ -0,0 +1,119 @@
/*
* \brief VirtualBox device models
* \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/printf.h>
/* VirtualBox includes */
#include <VBoxDD.h>
#include <VBoxDD2.h>
extern "C" int VBoxDevicesRegister(PPDMDEVREGCB pCallbacks, uint32_t u32Version)
{
PDBG("VBoxDevicesRegister called");
int rc = 0;
/* pcarch */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DevicePcArch);
if (RT_FAILURE(rc))
return rc;
/* pcbios */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DevicePcBios);
if (RT_FAILURE(rc))
return rc;
/* pci */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DevicePCI);
if (RT_FAILURE(rc))
return rc;
/* pckbd */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DevicePS2KeyboardMouse);
if (RT_FAILURE(rc))
return rc;
/* i8254 */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceI8254);
if (RT_FAILURE(rc))
return rc;
/* i8259 */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceI8259);
if (RT_FAILURE(rc))
return rc;
/* mc146818 */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceMC146818);
if (RT_FAILURE(rc))
return rc;
/* vga */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceVga);
if (RT_FAILURE(rc))
return rc;
/* piix3ide */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DevicePIIX3IDE);
if (RT_FAILURE(rc))
return rc;
/* 8237A DMA */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceDMA);
if (RT_FAILURE(rc))
return rc;
/* Guest - VMM/Host communication */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceVMMDev);
if (RT_FAILURE(rc))
return rc;
/* ACPI missing */
/* APIC */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceAPIC);
if (RT_FAILURE(rc))
return rc;
/* i82078 */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceFloppyController);
if (RT_FAILURE(rc))
return rc;
/* Ethernet PCNet controller */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DevicePCNet);
if (RT_FAILURE(rc))
return rc;
/* Serial device */
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceSerialPort);
if (RT_FAILURE(rc))
return rc;
rc = pCallbacks->pfnRegister(pCallbacks, &g_DevicePCIBridge);
if (RT_FAILURE(rc))
return rc;
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceACPI);
if (RT_FAILURE(rc))
return rc;
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceIOAPIC);
if (RT_FAILURE(rc))
return rc;
return VINF_SUCCESS;
}

View File

@ -0,0 +1,10 @@
+++ src/VBox/Devices/Bus/DevPCI.cpp
@@ -2279,7 +2280,7 @@
/*
* Register I/O ports and save state.
*/
- rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cf8, 1, NULL, pciIOPortAddressWrite, pciIOPortAddressRead, NULL, NULL, "i440FX (PCI)");
+ rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cf8, 4, NULL, pciIOPortAddressWrite, pciIOPortAddressRead, NULL, NULL, "i440FX (PCI)");
if (RT_FAILURE(rc))
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x0cfc, 4, NULL, pciIOPortDataWrite, pciIOPortDataRead, NULL, NULL, "i440FX (PCI)");

View File

@ -0,0 +1,47 @@
/*
* \brief VirtualBox host drivers
* \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/printf.h>
/* VirtualBox includes */
#include <VBoxDD.h>
extern "C" int VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_t u32Version)
{
PDBG("VBoxDriversRegister called");
PDMDRVREG const *drvs[] = {
&g_DrvKeyboardQueue,
&g_DrvMouseQueue,
&g_DrvBlock,
&g_DrvMediaISO,
&g_DrvACPI,
&g_DrvChar,
&g_DrvRawImage,
&g_DrvRawFile,
&g_DrvHostSerial,
&g_DrvVD,
0
};
for (unsigned i = 0; drvs[i]; i++) {
int rc = pCallbacks->pfnRegister(pCallbacks, drvs[i]);
if (RT_FAILURE(rc))
return rc;
}
return VINF_SUCCESS;
}

View File

@ -0,0 +1,317 @@
/*
* \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/printf.h>
#include <base/thread.h>
#include <stddef.h>
#include <time.h>
extern "C" {
typedef long DUMMY;
#define DUMMY(retval, name) \
DUMMY name(void) { \
PDBG( #name " called, not implemented, eip=%p", __builtin_return_address(0)); \
for (;;); \
return retval; \
}
#define CHECKED_DUMMY(retval, name) \
DUMMY name(void) { \
PINF( #name " called, not implemented, eip=%p", __builtin_return_address(0)); \
return retval; \
}
CHECKED_DUMMY( 0, cpumR3DbgInit)
CHECKED_DUMMY( 0, DBGFR3Init) /* debugger */
DUMMY(-1, DBGFR3CoreWrite)
CHECKED_DUMMY( 0, FTMR3Init) /* fault tolerance manager */
CHECKED_DUMMY( 0, pdmR3LdrInitU) /* module loader of pluggable device manager */
CHECKED_DUMMY( 0, PDMR3LdrLoadVMMR0U) /* pretend to have successfully loaded the r0 module */
CHECKED_DUMMY( 0, pdmR3LoadR3U)
CHECKED_DUMMY( 0, pthread_atfork)
CHECKED_DUMMY( 0, pthread_attr_setdetachstate)
CHECKED_DUMMY( 0, pthread_attr_setstacksize)
CHECKED_DUMMY( 0, RTMemProtect)
CHECKED_DUMMY( 0, SELMR3Init) /* selector manager - GDT handling */
CHECKED_DUMMY( 0, sigfillset)
CHECKED_DUMMY( 0, vmmR3SwitcherInit) /* world switcher */
CHECKED_DUMMY(-1, atexit)
CHECKED_DUMMY(-1, getpid)
CHECKED_DUMMY(-1, pdmR3FileR3)
CHECKED_DUMMY(-1, setlocale)
CHECKED_DUMMY(-1, sigaddset)
CHECKED_DUMMY(-1, sigemptyset)
CHECKED_DUMMY(-1, siginterrupt)
CHECKED_DUMMY(-1, sysctl)
DUMMY( 0, RTErrCOMGet)
void CPUMPushHyper() { } /* called by 'VMMR3InitRC', but we don't use GC */
DUMMY(-1, DBGCRegisterCommands)
DUMMY(-1, DBGFR3Event)
DUMMY(-1, DBGFR3EventAssertion)
DUMMY(-1, DBGFR3EventBreakpoint)
DUMMY(-1, DBGFR3EventSrc)
CHECKED_DUMMY( 0, DBGFR3EventSrcV)
void DBGFR3Relocate() { }
DUMMY(-1, DBGFR3Term)
DUMMY(-1, DBGFR3VMMForcedAction)
CHECKED_DUMMY(-4, DBGFR3AsSymbolByAddr) /* -4 == VERR_INVALID_HANDLE */
DUMMY(-1, _flockfile)
int FTMR3SetCheckpoint() { return -1; }
DUMMY(-1, FTMR3Term)
int FTMSetCheckpoint() { return 0; }
DUMMY(-1, _funlockfile)
DUMMY(-1, _fwalk)
DUMMY(-1, HWACCMInvalidatePage)
DUMMY(-1, HWACCMFlushTLB)
DUMMY(-1, HWACCMR3EmulateIoBlock)
DUMMY(-1, HWACCMR3PatchTprInstr)
DUMMY(-1, HWACCMR3CheckError)
DUMMY(-1, HWACCMR3RestartPendingIOInstr)
void HWACCMR3Relocate() { }
DUMMY(-1, HWACCMR3Reset)
DUMMY(-1, HWACCMR3Term)
DUMMY(-1, HWACMMR3EnablePatching)
DUMMY(-1, HWACMMR3DisablePatching)
CHECKED_DUMMY( 0, IEMR3Init) /* interpreted execution manager (seems to be just a skeleton) */
void IEMR3Relocate() { }
DUMMY(-1, IEMR3Term)
DUMMY(-1, MMHyperR0ToCC)
DUMMY(-1, MMHyperR0ToR3)
DUMMY(-1, MMHyperRCToCC)
DUMMY(-1, MMHyperRCToR3)
CHECKED_DUMMY(0, MMHyperGetArea)
DUMMY(-1, MMR3HeapAPrintfV)
CHECKED_DUMMY( 0, MMR3HyperInitFinalize)
CHECKED_DUMMY( 0, MMR3HyperSetGuard)
DUMMY(-1, MMR3LockCall)
DUMMY(-1, MMR3Term)
DUMMY(-1, MMR3TermUVM)
DUMMY(-1, PDMR3AsyncCompletionTemplateCreateDriver)
DUMMY(-1, PDMR3LdrGetInterfaceSymbols)
CHECKED_DUMMY( 0, PDMR3LdrRelocateU)
DUMMY(-1, pdmR3LdrTermU)
DUMMY(-1, PGMNotifyNxeChanged)
DUMMY(-1, PGMPhysGCPtr2GCPhys)
DUMMY(-1, PGMPhysSimpleReadGCPhys)
DUMMY(-1, PGMPhysSimpleReadGCPtr)
DUMMY(-1, PGMPhysSimpleWriteGCPtr)
DUMMY(-1, PGMSyncCR3)
CHECKED_DUMMY( 0, PGMR3CheckIntegrity)
CHECKED_DUMMY( 0, PGMR3FinalizeMappings)
CHECKED_DUMMY( 0, PGMR3InitCompleted)
CHECKED_DUMMY( 0, PGMR3InitDynMap) /* reserve space for "dynamic mappings" */
CHECKED_DUMMY( 0, PGMR3InitFinalize)
DUMMY(-1, PGMR3SharedModuleCheckAll)
DUMMY(-1, PGMR3SharedModuleUnregister)
DUMMY(-1, PGMR3SharedModuleRegister)
DUMMY(-1, PGMR3MappingsSize)
DUMMY(-1, PGMR3MappingsUnfix)
DUMMY(-1, PGMR3PhysChangeMemBalloon)
DUMMY(-1, PGMR3MappingsFix)
CHECKED_DUMMY( 0, PGMR3MappingsDisable)
DUMMY(-1, PGMR3LockCall)
DUMMY(-1, PGMR3PhysAllocateHandyPages)
DUMMY(-1, PGMR3PhysAllocateLargeHandyPage)
DUMMY(-1, PGMR3PhysChunkMap)
DUMMY(-1, PGMR3PhysGCPhys2CCPtrExternal)
DUMMY(-1, PGMR3PhysGCPhys2CCPtrReadOnlyExternal)
DUMMY(-1, PGMR3PhysMMIO2Deregister)
DUMMY(-1, PGMR3PhysMMIO2MapKernel)
DUMMY(-1, PGMR3PhysReadU16)
DUMMY(-1, PGMR3PhysReadU64)
DUMMY(-1, PGMR3PhysRomProtect)
DUMMY(-1, PGMR3PoolGrow)
void PGMR3Relocate() {}
DUMMY(-1, PGMR3ResetCpu)
DUMMY(-1, PGMR3Term)
DUMMY(-1, PGMPrefetchPage)
DUMMY(-1, PGMGstGetPage)
DUMMY(-1, PGMGstIsPagePresent)
DUMMY(-1, PGMShwMakePageReadonly)
DUMMY(-1, PGMShwMakePageNotPresent)
DUMMY(-1, PGMPhysIsGCPhysNormal)
DUMMY(-1, PGMHandlerVirtualChangeInvalidateCallback)
DUMMY(-1, PGMSetLargePageUsage)
DUMMY(-1, PGMPhysSimpleDirtyWriteGCPtr)
DUMMY(-1, PGMGetShadowMode)
DUMMY(-1, PGMGetHostMode)
CHECKED_DUMMY(0, poll) /* needed by 'DrvHostSerial.cpp' */
DUMMY(-1, printf)
DUMMY(-1, pthread_key_delete)
DUMMY(-1, reallocf)
DUMMY(-1, RTCrc32);
DUMMY(-1, RTCrc32Start)
DUMMY(-1, RTCrc32Finish)
DUMMY(-1, RTCrc32Process)
DUMMY(-1, RTMemExecFree)
DUMMY(-1, RTMemPageFree)
DUMMY(-1, RTPathHasPath)
DUMMY(-1, RTPathAppend)
DUMMY(-1, rtPathPosixRename)
CHECKED_DUMMY(0, rtProcInitExePath)
DUMMY(-1, RTSemEventWaitEx)
CHECKED_DUMMY( 0, SELMR3InitFinalize)
void SELMR3Relocate() { }
CHECKED_DUMMY( 0, SELMR3DisableMonitoring)
DUMMY(-1, SELMR3Reset)
DUMMY(-1, SELMR3Term)
DUMMY(-1, SELMR3GetSelectorInfo)
DUMMY(-1, libc_select_notify) /* needed for libc_terminal plugin */
DUMMY(-1, strdup)
DUMMY(-1, DISInstrToStrEx)
CHECKED_DUMMY(-1, signal)
DUMMY(-1, strcat)
DUMMY(-1, strerror)
DUMMY(-1, strpbrk)
CHECKED_DUMMY( 0, SUPR3SetVMForFastIOCtl)
DUMMY(-1, SUPR3HardenedLdrLoadPlugIn)
DUMMY(-1, SUPR3Term)
CHECKED_DUMMY(100000*10, SUPSemEventMultiGetResolution) /* called by 'vmR3HaltGlobal1Init' */
CHECKED_DUMMY(-1, __swsetup)
DUMMY(-1, VMMR3FatalDump)
void vmmR3SwitcherRelocate() { }
CHECKED_DUMMY( 0, VMMR3DisableSwitcher)
DUMMY(-1, VMMR3GetHostToGuestSwitcher)
DUMMY(-1, pthread_kill)
DUMMY(-1, sscanf)
DUMMY(-1, RTHeapSimpleRelocate)
DUMMY(-1, RTHeapOffsetInit)
DUMMY(-1, RTHeapSimpleInit)
DUMMY(-1, RTHeapOffsetFree)
DUMMY(-1, RTHeapSimpleFree)
DUMMY(-1, RTAvloU32Get)
DUMMY(-1, RTAvloU32Remove)
DUMMY(-1, RTAvloU32GetBestFit)
CHECKED_DUMMY(0, RTAvloU32RemoveBestFit)
DUMMY(-1, RTAvlU32Destroy)
DUMMY(-1, RTAvlU32GetBestFit)
DUMMY(-1, RTAvloU32DoWithAll)
DUMMY(-1, RTAvloU32Insert)
DUMMY(-1, RTAvlU32Get)
DUMMY(-1, RTAvlU32DoWithAll)
DUMMY(-1, RTAvlU32Insert)
CHECKED_DUMMY( 0, IOMR3Init)
int IOMR3IOPortRegisterR0() { return 0; }
int IOMR3IOPortRegisterRC() { return 0; }
DUMMY(-1, IOMR3MmioDeregister)
CHECKED_DUMMY( 0, IOMR3MmioRegisterR0)
CHECKED_DUMMY( 0, IOMR3MmioRegisterRC)
void IOMR3Relocate() { }
DUMMY(-1, IOMR3Reset)
DUMMY(-1, IOMR3Term)
DUMMY(-1, IOMInterpretOUT)
DUMMY(-1, IOMInterpretOUTS)
DUMMY(-1, IOMInterpretIN)
DUMMY(-1, IOMInterpretINS)
DUMMY(-1, DISInstrToStrWithReader)
DUMMY(0, RTPathQueryInfoEx)
DUMMY(-1, RTFileQueryFsSizes)
time_t mktime(tm *) {
PERR("mktime not implemented, return 0");
return 0;
}
DUMMY(-1, pthread_mutex_timedlock)
CHECKED_DUMMY( 0, PGMHandlerVirtualDeregister) /* XXX */
CHECKED_DUMMY( 0, PGMR3HandlerVirtualRegister) /* XXX */
/*
* Dummies added for storage
*/
DUMMY(-1, closedir)
DUMMY(-1, readdir_r)
DUMMY(-1, RTAvlrFileOffsetDestroy)
DUMMY(-1, RTAvlrFileOffsetGet)
DUMMY(-1, RTAvlrFileOffsetGetBestFit)
DUMMY(-1, RTAvlrFileOffsetInsert)
DUMMY(-1, RTAvlrFileOffsetRemove)
DUMMY(-1, RTAvlrU64Destroy)
DUMMY(-1, RTAvlrU64DoWithAll)
DUMMY(-1, RTAvlrU64GetBestFit)
DUMMY(-1, RTAvlrU64Insert)
DUMMY(-1, RTAvlrU64RangeGet)
DUMMY(-1, RTAvlrU64RangeRemove)
DUMMY(-1, RTAvlrU64Remove)
DUMMY(-1, RTDirOpenFiltered)
DUMMY(-1, RTDirReadEx)
DUMMY(-1, RTDirClose)
DUMMY(-1, RTLdrClose)
DUMMY(-1, RTLdrGetSymbol)
DUMMY(-1, RTMemDupExTag)
DUMMY(-1, RTPathQueryInfo)
DUMMY(-1, rtPathRootSpecLen)
DUMMY(-1, RTPathStartsWithRoot)
DUMMY(-1, RTSocketToNative)
DUMMY(-1, RTStrCatP)
DUMMY(-1, RTTcpClientCloseEx)
DUMMY(-1, RTTcpClientConnect)
DUMMY(-1, RTTcpFlush)
DUMMY(-1, RTTcpGetLocalAddress)
DUMMY(-1, RTTcpGetPeerAddress)
DUMMY(-1, RTTcpRead)
DUMMY(-1, RTTcpReadNB)
DUMMY(-1, RTTcpSelectOne)
DUMMY(-1, RTTcpSelectOneEx)
DUMMY(-1, RTTcpSetSendCoalescing)
DUMMY(-1, RTTcpSgWrite)
DUMMY(-1, RTTcpSgWriteNB)
DUMMY(-1, RTTcpWrite)
DUMMY(-1, RTTcpWriteNB)
DUMMY(-1, strncat)
int __isthreaded;
int sigprocmask() { return 0; }
int _sigprocmask() { return 0; }
int PGMFlushTLB() { return 0; }
int PGMInvalidatePage() { return 0; } /* seems to be needed on raw mode only */
int PGMHandlerPhysicalPageTempOff() { return 0; }
int PGMIsLockOwner() { return 0; } /* assertion in EMRemLock */
bool IOMIsLockOwner() { return 0; } /* XXX */
int MMHyperIsInsideArea() { return 0; } /* used by dbgfR3DisasInstrRead */
int PGMPhysReleasePageMappingLock() { return 0; }
} /* extern "C" */

View File

@ -0,0 +1,20 @@
+++ src/VBox/Devices/Graphics/DevVGA.cpp 2013-12-09 10:33:02.168894689 +0100
@@ -5885,7 +5889,7 @@
vgaR3Reset(pDevIns);
/* The PCI devices configuration. */
- PCIDevSetVendorId( &pThis->Dev, 0x80ee); /* PCI vendor, just a free bogus value */
+ PCIDevSetVendorId( &pThis->Dev, 0x80ef); /* PCI vendor, just a free bogus value */
PCIDevSetDeviceId( &pThis->Dev, 0xbeef);
PCIDevSetClassSub( &pThis->Dev, 0x00); /* VGA controller */
PCIDevSetClassBase( &pThis->Dev, 0x03);
+++ src/VBox/Devices/VMMDev/VMMDev.cpp 2013-12-09 10:33:15.164894199 +0100
@@ -3429,7 +3431,7 @@
pThis->pDevIns = pDevIns;
/* PCI vendor, just a free bogus value */
- PCIDevSetVendorId(&pThis->dev, 0x80ee);
+ PCIDevSetVendorId(&pThis->dev, 0x80ef);
/* device ID */
PCIDevSetDeviceId(&pThis->dev, 0xcafe);
/* class sub code (other type of system peripheral) */

View File

@ -0,0 +1,357 @@
/*
* \brief Registry of known guest-physical memory regions
* \author Norman Feske
* \date 2013-09-02
*
* Contains the mapping of guest-phyiscal to VMM-local addresses.
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _GUEST_MEMORY_H_
#define _GUEST_MEMORY_H_
/*
* Work-around for a naming conflict between the enum definition of PAGE_SIZE
* in 'os/attached_ram_dataspace.h' and the VirtualBox #define with the same
* name.
*/
#define BACKUP_PAGESIZE PAGE_SIZE
#undef PAGE_SIZE
/* Genode includes */
#include <base/printf.h>
#include <base/env.h>
#include <base/lock.h>
#include <base/flex_iterator.h>
#include <util/list.h>
#include <os/attached_ram_dataspace.h>
/* VirtualBox includes */
#include <VBox/vmm/pgm.h>
#include <VBox/vmm/iom.h>
#include <VBox/vmm/pdmdev.h>
#define PAGE_SIZE BACKUP_PAGESIZE
class Guest_memory
{
struct Region;
/*
* XXX Use AVL tree instead of a linked list
*/
typedef Genode::List<Region> Region_list;
typedef Genode::Lock Lock;
typedef Genode::addr_t addr_t;
private:
struct Region : Region_list::Element
{
RTGCPHYS const _GCPhys; /* guest-physical address */
RTGCPHYS const _cb; /* size */
void * const _pv; /* VMM-local address */
/*
* MMIO-specific members
*/
PPDMDEVINS const _pDevIns;
RTHCPTR const _pvUser;
PFNIOMMMIOWRITE const _pfnWriteCallback;
PFNIOMMMIOREAD const _pfnReadCallback;
PFNIOMMMIOFILL const _pfnFillCallback;
uint32_t const _fFlags;
Region(RTGCPHYS const GCPhys, RTGCPHYS const cb, void *const pv,
PPDMDEVINS pDevIns,
RTHCPTR pvUser,
PFNIOMMMIOWRITE pfnWriteCallback,
PFNIOMMMIOREAD pfnReadCallback,
PFNIOMMMIOFILL pfnFillCallback,
uint32_t fFlags)
:
_GCPhys(GCPhys), _cb(cb), _pv(pv),
_pDevIns (pDevIns),
_pvUser (pvUser),
_pfnWriteCallback (pfnWriteCallback),
_pfnReadCallback (pfnReadCallback),
_pfnFillCallback (pfnFillCallback),
_fFlags (fFlags)
{ }
/**
* Return true if region contains specified guest-physical area
*/
bool contains(RTGCPHYS GCPhys, size_t size) const
{
return (_GCPhys <= GCPhys) && (GCPhys < _GCPhys + _cb) &&
(_GCPhys + _cb - GCPhys >= size);
}
/**
* Return true if region is disjunct to specified guest-physical area
*/
bool disjunct(RTGCPHYS GCPhys, size_t size) const
{
return (GCPhys + size - 1 < _GCPhys) ||
(_GCPhys + _cb - 1 < GCPhys);
}
/**
* Return guest-physical base address
*/
RTGCPHYS GCPhys() const { return _GCPhys; }
/**
* Return VMM-local base address
*/
void *pv() const { return _pv; }
void dump() const
{
Genode::printf("phys [0x%16lx-0x%16lx] -> virt [0x%16lx-0x%16lx] (dev='%s')\n",
(long)_GCPhys, (long)_GCPhys + (long)_cb - 1,
(long)_pv, (long)_pv + (long)_cb - 1,
_pDevIns && _pDevIns->pReg ? _pDevIns->pReg->szName : 0);
}
void *pv_at_offset(addr_t offset)
{
if (_pv)
return (void *)((addr_t)_pv + (addr_t)offset);
return 0;
}
int mmio_write(RTGCPHYS GCPhys, void const *pv, unsigned cb)
{
if (!_pfnWriteCallback)
return VERR_IOM_MMIO_RANGE_NOT_FOUND;
// PDBG("mmio_write(GCPhys=0x%lx, cb=%u)", GCPhys, cb);
return _pfnWriteCallback(_pDevIns, _pvUser, GCPhys, pv, cb);
}
int mmio_read(RTGCPHYS GCPhys, void *pv, unsigned cb)
{
if (!_pfnReadCallback)
return VERR_IOM_MMIO_RANGE_NOT_FOUND;
// PDBG("mmio_read(GCPhys=0x%lx, cb=%u)", GCPhys, cb);
return _pfnReadCallback(_pDevIns, _pvUser, GCPhys, pv, cb);
}
};
Lock _lock;
Region_list _ram_regions;
Region_list _rom_regions;
Region_list _mmio_regions;
static Region *_lookup(RTGCPHYS GCPhys, Region_list &regions, size_t size)
{
using Genode::addr_t;
for (Region *r = regions.first(); r; r = r->next())
if (r->contains(GCPhys, size))
return r;
return 0;
}
static bool _overlap(RTGCPHYS GCPhys, size_t size,
Region_list &regions)
{
using Genode::addr_t;
for (Region *r = regions.first(); r; r = r->next())
{
if (r->disjunct(GCPhys, size))
continue;
return true;
}
return false;
}
/**
* \return looked-up region, or 0 if lookup failed
*/
Region *_lookup(RTGCPHYS GCPhys, size_t size)
{
using Genode::addr_t;
/*
* ROM regions may alias RAM regions. For the lookup, always
* consider ROM regions first.
*/
if (Region *r = _lookup(GCPhys, _rom_regions, size))
return r;
if (Region *r = _lookup(GCPhys, _mmio_regions, size))
return r;
if (Region *r = _lookup(GCPhys, _ram_regions, size))
return r;
return 0;
}
public:
class Region_conflict { };
/**
* \throw Region_conflict
*/
void add_ram_mapping(RTGCPHYS const GCPhys, RTGCPHYS const cb, void * const pv)
{
/*
* XXX check for overlapping regions
*/
_ram_regions.insert(new (Genode::env()->heap())
Region(GCPhys, cb, pv, 0, 0, 0, 0, 0, 0));
}
/**
* \throw Region_conflict
*/
void add_rom_mapping(RTGCPHYS const GCPhys, RTGCPHYS const cb,
void const * const pv, PPDMDEVINS pDevIns)
{
/*
* XXX check for overlapping regions
*/
_rom_regions.insert(new (Genode::env()->heap())
Region(GCPhys, cb,
(void *)pv, pDevIns, 0, 0, 0, 0, 0));
}
/**
* \throw Region_conflict
*/
void add_mmio_mapping(RTGCPHYS const GCPhys, RTGCPHYS const cb,
PPDMDEVINS pDevIns,
RTHCPTR pvUser,
PFNIOMMMIOWRITE pfnWriteCallback,
PFNIOMMMIOREAD pfnReadCallback,
PFNIOMMMIOFILL pfnFillCallback,
uint32_t fFlags)
{
/*
* XXX check for overlapping regions
*/
_mmio_regions.insert(new (Genode::env()->heap())
Region(GCPhys, cb, 0,
pDevIns, pvUser, pfnWriteCallback,
pfnReadCallback, pfnFillCallback, fFlags));
}
void dump() const
{
Genode::printf("guest-physical to VMM-local RAM mappings:\n");
for (Region const *r = _ram_regions.first(); r; r = r->next())
r->dump();
Genode::printf("guest-physical to VMM-local ROM mappings:\n");
for (Region const *r = _rom_regions.first(); r; r = r->next())
r->dump();
Genode::printf("guest-physical MMIO regions:\n");
for (Region const *r = _mmio_regions.first(); r; r = r->next())
r->dump();
}
/**
* \return looked-up VMM-local address, or 0 if lookup failed
*/
void *lookup(RTGCPHYS GCPhys, size_t size)
{
Region *r = _lookup(GCPhys, size);
if (!r)
return 0;
return r->pv_at_offset(GCPhys - r->GCPhys());
}
/**
* \return looked-up VMM-local address if Guest address is RAM
*/
void *lookup_ram(RTGCPHYS const GCPhys, size_t size,
Genode::Flexpage_iterator &it)
{
if (_overlap(GCPhys, size, _rom_regions))
return 0;
if (_overlap(GCPhys, size, _mmio_regions))
return 0;
if (!_overlap(GCPhys, size, _ram_regions))
return 0;
Region *r = _lookup(GCPhys, _ram_regions, size);
if (!r)
return 0;
void * vmm_local = lookup_ram(GCPhys & ~(size * 2UL - 1), size * 2UL, it);
if (vmm_local)
return vmm_local;
it = Genode::Flexpage_iterator((addr_t)r->pv_at_offset(GCPhys - r->GCPhys()), size, GCPhys, size, GCPhys - r->GCPhys());
return r->pv_at_offset(GCPhys - r->GCPhys());
}
/**
* \return VirtualBox return code
*/
int mmio_write(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
{
Region *r = _lookup(GCPhys, cbValue);
if (!r) {
PERR("Guest_memory::mmio_write: lookup failed");
PERR("GCPhys=0x%x, u32Value=0x%x, cbValue=%zd",
GCPhys, u32Value, cbValue);
return VERR_IOM_MMIO_RANGE_NOT_FOUND;
}
return r->mmio_write(GCPhys, &u32Value, cbValue);
}
/**
* \return VirtualBox return code
*/
int mmio_read(PVM pVM, RTGCPHYS GCPhys, uint32_t *u32Value, size_t cbValue)
{
Region *r = _lookup(GCPhys, cbValue);
if (!r) {
PERR("Guest_memory::mmio_read: lookup failed");
PERR("GCPhys=0x%x, u32Value=0x%x, cbValue=%zd",
GCPhys, u32Value, cbValue);
return VERR_IOM_MMIO_RANGE_NOT_FOUND;
}
return r->mmio_read(GCPhys, u32Value, cbValue);
}
};
/**
* Return pointer to singleton instance
*/
Guest_memory *guest_memory();
#endif /* _GUEST_MEMORY_H_ */

View File

@ -0,0 +1,53 @@
+++ src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp
@@ -158,6 +160,7 @@
static bool g_fReleaseLog = true; /**< Set if we should open the release. */
const char *g_pszProgressString;
unsigned g_uProgressPercent = ~0U;
+static bool g_fOverlay= false;
/**
@@ -715,6 +718,8 @@
g_fCSAM = false;
#endif /* VBOXSDL_ADVANCED_OPTIONS */
/* just show the help screen */
+ else if (strcmp(pszArg, "-overlay") == 0)
+ g_fOverlay = true;
else
{
SyntaxError("unrecognized argument '%s'\n", pszArg);
@@ -1532,7 +1550,7 @@
rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
rc = CFGMR3InsertString(pDrv, "Driver", "VD"); UPDATE_RC();
rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
- rc = CFGMR3InsertString(pCfg, "Path", g_pszHdaFile); UPDATE_RC();
+ rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); UPDATE_RC();
if (g_fHdaSpf)
{
@@ -1541,13 +1559,23 @@
else
{
char *pcExt = RTPathExt(g_pszHdaFile);
- if ((pcExt) && (!strcmp(pcExt, ".vdi")))
+ if ((pcExt) && (!strcmp(pcExt, ".vdi") && !g_fOverlay))
{
rc = CFGMR3InsertString(pCfg, "Format", "VDI"); UPDATE_RC();
+ rc = CFGMR3InsertString(pCfg, "Path", g_pszHdaFile); UPDATE_RC();
}
else
{
- rc = CFGMR3InsertString(pCfg, "Format", "VMDK"); UPDATE_RC();
+ /*
+ * Use the overlay.vdi file to store differential changes.
+ * Leave the VMDK file passed as argument unchanged.
+ */
+ PCFGMNODE pParent = 0;
+ rc = CFGMR3InsertString(pCfg, "Format", "VDI"); UPDATE_RC();
+ rc = CFGMR3InsertString(pCfg, "Path", "/ram/overlay.vdi"); UPDATE_RC();
+ rc = CFGMR3InsertNode(pCfg, "Parent", &pParent); UPDATE_RC();
+ rc = CFGMR3InsertString(pParent, "Format", "VDI"); UPDATE_RC();
+ rc = CFGMR3InsertString(pParent, "Path", g_pszHdaFile); UPDATE_RC();
}
}
}

View File

@ -0,0 +1,16 @@
+++ src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp
@@ -1273,6 +1279,14 @@
rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); UPDATE_RC();
#endif
+ /* enable HW virtualization support */
+
+ PCFGMNODE pHWVirtExt = NULL;
+
+ rc = CFGMR3InsertNode(pRoot, "HWVirtExt", &pHWVirtExt); UPDATE_RC();
+ rc = CFGMR3InsertInteger(pHWVirtExt, "Enabled", 1); UPDATE_RC();
+ rc = CFGMR3InsertInteger(pHWVirtExt, "64bitEnabled", 0); UPDATE_RC();
+
/*
* PDM.
*/

View File

@ -0,0 +1,129 @@
/*
* \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/printf.h>
/* VirtualBox includes */
#include "HWACCMInternal.h" /* enable access to hwaccm.s.* */
#include <VBox/vmm/hwaccm.h>
#include <VBox/vmm/vm.h>
/* Genode's VirtualBox includes */
#include "sup.h"
static bool enabled = true;
VMMR3DECL(int) HWACCMR3Init(PVM pVM)
{
/*
* We always set the fHWACCMEnabled 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
* HWACCMR3CanExecuteGuest function.
*/
pVM->fHWACCMEnabled = true;
for (VMCPUID i = 0; i < pVM->cCpus; i++)
pVM->aCpus[i].hwaccm.s.fActive = false;
return VINF_SUCCESS;
}
VMMR3_INT_DECL(int) HWACCMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
{
enabled = pVM->hwaccm.s.svm.fSupported || pVM->hwaccm.s.vmx.fSupported;
if (!enabled || enmWhat != VMINITCOMPLETED_RING0)
return VINF_SUCCESS;
int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
return rc;
}
VMMR3DECL(bool) HWACCMR3IsVmxPreemptionTimerUsed(PVM pVM)
{
PLOG("HWACCMR3IsVmxPreemptionTimerUsed");
return false;
}
VMMR3DECL(bool) HWACCMR3IsActive(PVMCPU pVCpu)
{
return pVCpu->hwaccm.s.fActive;
}
VMMR3DECL(bool) HWACCMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx)
{
/* no re-schedule on AMD-V required - just works */
/*
if (pVM->hwaccm.s.svm.fSupported)
return false;
*/
bool reschedule = !CPUMIsGuestInPagedProtectedModeEx(pCtx);
// PLOG("reschedule %u %u %lx", reschedule, HWACCMR3CanExecuteGuest(pVM, pCtx), pCtx->cr0);
return reschedule;
}
void HWACCMR3PagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode,
PGMMODE enmGuestMode)
{
// PLOG("HWACCMR3PagingModeChanged: enmShadowMode=%d enmGuestMode=%d",
// enmShadowMode, enmGuestMode);
}
VMMR3DECL(bool) HWACCMR3IsEventPending(PVMCPU pVCpu)
{
// PLOG("HWACCMR3IsEventPending false");
return false;
}
VMMR3DECL(bool) HWACCMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx)
{
PVMCPU pVCpu = VMMGetCpu(pVM);
/* AMD-V just works */
/*
if (pVM->hwaccm.s.svm.fSupported) {
pVCpu->hwaccm.s.fActive = true;
return true;
}
*/
if (!enabled)
return false;
/* enable H/W acceleration in protected mode only */
bool res = (pCtx->cr0 & 1) && (pCtx->cr0 & 0x80000000);
/*
static bool on = false;
if (res)
on = true;
if (on)
PLOG("executeguest %lx -> %x", pCtx->cr0, res);
*/
pVCpu->hwaccm.s.fActive = res;
return res;
}

View File

@ -0,0 +1,246 @@
/*
* \brief Console implementation of VirtualBox for Genode
* \author Alexander Boettcher
* \date 2013-10-16
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <input/event.h>
#include <input/keycodes.h>
#include <input_session/connection.h>
#include <timer_session/connection.h>
/* included from os/src/drivers/input/ps2 */
#include <scan_code_set_1.h>
/* VirtualBox includes */
#include <ConsoleImpl.h>
#include <base/printf.h>
/* XXX */
enum { KMOD_RCTRL = 0, SDLK_RCTRL = 0 };
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 is_normal() const { return converter().scan_code[_keycode]; }
bool is_ext() const { return converter().scan_code_ext[_keycode]; }
bool valid() const
{
return is_normal() || is_ext();
}
unsigned char code() const
{
return converter().scan_code[_keycode];
}
unsigned char ext() const
{
return converter().scan_code_ext[_keycode];
}
};
class SDLConsole : public Console {
private:
Timer::Connection timer;
Input::Connection input;
Input::Event *_ev_buf;
unsigned _ax, _ay;
bool _key_status[Input::KEY_MAX + 1];
static bool _is_mouse_button(Input::Keycode keycode)
{
return keycode == Input::BTN_LEFT
|| keycode == Input::BTN_RIGHT
|| keycode == Input::BTN_MIDDLE;
}
public:
SDLConsole()
:
Console(),
_ev_buf(static_cast<Input::Event *>(Genode::env()->rm_session()->attach(input.dataspace()))),
_ax(0), _ay(0)
{
for (unsigned i = 0; i <= Input::KEY_MAX; i++)
_key_status[i] = 0;
if (FAILED(gMouse->init(this))) {
PERR("mouse init failed");
return;
}
mfInitialized = true;
}
void updateTitlebar()
{
PERR("%s:%s called", __FILE__, __FUNCTION__);
}
void updateTitlebarProgress(const char *, int)
{
PERR("%s:%s called", __FILE__, __FUNCTION__);
}
void inputGrabStart()
{
PERR("%s:%s called", __FILE__, __FUNCTION__);
}
void inputGrabEnd()
{
PERR("%s:%s called", __FILE__, __FUNCTION__);
}
void mouseSendEvent(int)
{
PERR("%s:%s called", __FILE__, __FUNCTION__);
}
void onMousePointerShapeChange(bool, bool, uint32_t, uint32_t,
uint32_t, uint32_t, void *)
{
PERR("%s:%s called", __FILE__, __FUNCTION__);
}
void progressInfo(PVM, unsigned, void *)
{
PERR("%s:%s called", __FILE__, __FUNCTION__);
}
CONEVENT eventWait()
{
while (!input.is_pending()) { timer.msleep(50); }
for (int i = 0, num_ev = input.flush(); i < num_ev; ++i) {
Input::Event &ev = _ev_buf[i];
bool const is_press = ev.type() == Input::Event::PRESS;
bool const is_release = ev.type() == Input::Event::RELEASE;
bool const is_key = is_press || is_release;
bool const is_motion = ev.type() == Input::Event::MOTION;
if (is_key) {
Scan_code scan_code(ev.keycode());
unsigned char const release_bit =
(ev.type() == Input::Event::RELEASE) ? 0x80 : 0;
if (scan_code.is_normal())
gKeyboard->PutScancode(scan_code.code() | release_bit);
if (scan_code.is_ext()) {
gKeyboard->PutScancode(0xe0);
gKeyboard->PutScancode(scan_code.ext() | release_bit);
}
}
/*
* Track press/release status of keys and buttons. Currently,
* only the mouse-button states are actually used.
*/
if (is_press)
_key_status[ev.keycode()] = true;
if (is_release)
_key_status[ev.keycode()] = false;
bool const is_mouse_button_event =
is_key && _is_mouse_button(ev.keycode());
bool const is_mouse_event = is_mouse_button_event || is_motion;
if (is_mouse_event) {
unsigned const buttons = (_key_status[Input::BTN_LEFT] ? 0x1 : 0)
| (_key_status[Input::BTN_RIGHT] ? 0x2 : 0)
| (_key_status[Input::BTN_MIDDLE] ? 0x4 : 0);
if (ev.is_absolute_motion()) {
int const rx = ev.ax() - _ax; _ax = ev.ax();
int const ry = ev.ay() - _ay; _ay = ev.ay();
gMouse->PutMouseEvent(rx, ry, 0, 0, buttons);
gMouse->PutMouseEventAbsolute(ev.ax(), ev.ay(), 0, 0, buttons);
} else if (ev.is_relative_motion())
gMouse->PutMouseEvent(ev.rx(), ev.ry(), 0, 0, buttons);
/* only the buttons changed */
else
gMouse->PutMouseEvent(0, 0, 0, 0, buttons);
}
}
return CONEVENT_NONE;
}
void eventQuit() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
void resetKeys(void) { PERR("%s:%s called", __FILE__, __FUNCTION__); }
VMMDev *getVMMDev() { /*PERR("%s:%s called", __FILE__, __FUNCTION__);*/ return 0; }
Display *getDisplay() { return gDisplay; }
};

View File

@ -0,0 +1,110 @@
/*
* \brief Framebuffer implementation of VirtualBox for Genode
* \author Alexander Boettcher
* \date 2013-10-16
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#define Framebuffer FramebufferGenode
#include <framebuffer_session/connection.h>
#undef Framebuffer
/* VirtualBox includes */
#include "Framebuffer.h"
#include <base/printf.h>
class SDLFramebuffer : public Framebuffer
{
private:
FramebufferGenode::Connection _fb;
FramebufferGenode::Mode const _fb_mode;
void * _fb_base;
RTCRITSECT mUpdateLock;
public:
SDLFramebuffer ()
:
_fb_mode(_fb.mode()),
_fb_base(Genode::env()->rm_session()->attach(_fb.dataspace()))
{
int rc = RTCritSectInit(&mUpdateLock);
if (rc != VINF_SUCCESS)
PERR("Lock could not be initalized");
}
HRESULT getWidth(ULONG * width)
{
*width = _fb_mode.width();
return S_OK;
}
HRESULT getHeight(ULONG * height)
{
*height = _fb_mode.height();
return S_OK;
}
HRESULT Lock() { return RTCritSectEnter(&mUpdateLock); }
HRESULT Unlock() { return RTCritSectLeave(&mUpdateLock); }
HRESULT getAddress(uintptr_t * addr)
{
*addr = reinterpret_cast<uintptr_t>(_fb_base);
return S_OK;
}
HRESULT getBitsPerPixel(ULONG * bits)
{
*bits = _fb_mode.bytes_per_pixel() * 8;
return S_OK;
}
HRESULT getLineSize(ULONG * line)
{
*line = _fb_mode.width() * _fb_mode.bytes_per_pixel();
return S_OK;
}
HRESULT NotifyUpdate(ULONG x, ULONG y, ULONG w, ULONG h)
{
_fb.refresh(x, y, w, h);
return S_OK;
}
HRESULT RequestResize(ULONG x, ULONG y, BOOL * finished)
{
PERR("ignore resize request to %lux%lu", x, y);
Genode::size_t const num_pixels = _fb_mode.width()*_fb_mode.height();
Genode::memset(_fb_base, 0, num_pixels*_fb_mode.bytes_per_pixel());
_fb.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
*finished = true;
return S_OK;
}
HRESULT GetVisibleRegion(BYTE *, ULONG, ULONG *) { PERR("%s:%s called", __FILE__, __FUNCTION__); return E_NOTIMPL; }
HRESULT SetVisibleRegion(BYTE *, ULONG) { PERR("%s:%s called", __FILE__, __FUNCTION__); return E_NOTIMPL; }
HRESULT ProcessVHWACommand(BYTE *) { PERR("%s:%s called", __FILE__, __FUNCTION__); return E_NOTIMPL; }
void repaint() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
void resize() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
void update(int, int, int, int) { PERR("%s:%s called", __FILE__, __FUNCTION__); }
bool getFullscreen() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
void setFullscreen(bool) { PERR("%s:%s called", __FILE__, __FUNCTION__); }
int getYOffset() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
int getHostXres() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
int getHostYres() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
int getHostBitsPerPixel() { PERR("%s:%s called", __FILE__, __FUNCTION__); }
};

View File

@ -0,0 +1,15 @@
/*
* \brief Dummy stubs needed by 'PDMAll.cpp'
* \author Norman Feske
* \date 2013-08-25
*/
#ifndef _DTRACE__VBOXVMM_H_
#define _DTRACE__VBOXVMM_H_
#define VBOXVMM_PDM_IRQ_GET(...) do { } while (0)
#define VBOXVMM_PDM_IRQ_HIGH(...) do { } while (0)
#define VBOXVMM_PDM_IRQ_LOW(...) do { } while (0)
#define VBOXVMM_PDM_IRQ_HILO(...) do { } while (0)
#endif /* _DTRACE__VBOXVMM_H_ */

View File

@ -0,0 +1,4 @@
/*
* \brief Dummy stubs needed by 'src/VBox/Frontends/VBoxBFE/VirtualBoxBase.h'
* \author Alexander Boettcher
*/

View File

@ -0,0 +1,4 @@
/*
* \brief Dummy stubs needed by 'src/VBox/Frontends/VBoxBFE/VirtualBoxBase.h'
* \author Alexander Boettcher
*/

View File

@ -0,0 +1,10 @@
#ifndef ___product_generated_h___
#define ___product_generated_h___
#define VBOX_VENDOR "Oracle Corporation"
#define VBOX_VENDOR_SHORT "Oracle"
#define VBOX_PRODUCT "Oracle VM VirtualBox"
#define VBOX_BUILD_PUBLISHER "_OSE"
#define VBOX_C_YEAR "2013"
#endif

View File

@ -0,0 +1,11 @@
#ifndef ___version_generated_h___
#define ___version_generated_h___
#define VBOX_VERSION_MAJOR 4
#define VBOX_VERSION_MINOR 2
#define VBOX_VERSION_BUILD 16
#define VBOX_VERSION_STRING_RAW "4.2.16"
#define VBOX_VERSION_STRING "4.2.16_OSE"
#define VBOX_API_VERSION_STRING "4_2"
#endif

View File

@ -0,0 +1,76 @@
/*
* \brief VirtualBox Memory-mapped I/O monitor
* \author Norman Feske
* \date 2013-09-02
*/
/*
* 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/printf.h>
/* VirtualBox includes */
#include <VBox/vmm/iom.h>
#include <VBox/vmm/rem.h>
/* local includes */
#include "guest_memory.h"
int IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart,
uint32_t cbRange, RTHCPTR pvUser,
R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback,
R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,
R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback,
uint32_t fFlags, const char *pszDesc)
{
PLOG("IOMR3MmioRegisterR3: GCPhys=0x%lx cb=0x%zx pszDesc=%s rd=%p wr=%p fl=%p",
(long)GCPhysStart, (size_t)cbRange, pszDesc,
pfnWriteCallback, pfnReadCallback, pfnFillCallback);
REMR3NotifyHandlerPhysicalRegister(pVM, PGMPHYSHANDLERTYPE_MMIO,
GCPhysStart, cbRange, true);
guest_memory()->add_mmio_mapping(GCPhysStart, cbRange,
pDevIns, pvUser, pfnWriteCallback,
pfnReadCallback, pfnFillCallback, fFlags);
return VINF_SUCCESS;
}
VBOXSTRICTRC IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
{
// PDBG("GCPhys=0x%x, u32Value=0x%x, cbValue=%zd", GCPhys, u32Value, cbValue);
return guest_memory()->mmio_write(pVM, GCPhys, u32Value, cbValue);
}
VBOXSTRICTRC IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value,
size_t cbValue)
{
// PDBG("GCPhys=0x%x, cbValue=%zd", GCPhys, cbValue);
return guest_memory()->mmio_read(pVM, GCPhys, pu32Value, cbValue);
}
int IOMMMIOMapMMIO2Page(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped,
uint64_t fPageFlags)
{
PDBG("called - %lx %lx", GCPhys, GCPhysRemapped);
return VINF_SUCCESS;
}
int IOMMMIOResetRegion(PVM pVM, RTGCPHYS GCPhys)
{
PDBG("called - %lx", GCPhys);
return VINF_SUCCESS;
}

View File

@ -0,0 +1,273 @@
/*
* \brief VirtualBox I/O port monitor
* \author Norman Feske
* \date 2013-09-02
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <util/list.h>
#include <base/printf.h>
#include <base/lock.h>
#include <base/env.h>
/* VirtualBox includes */
#include <VBox/vmm/iom.h>
#include <VBox/err.h>
#include <VBox/vmm/pdmdev.h>
class Guest_ioports
{
struct Range;
/*
* XXX Use AVL tree instead of a linked list
*/
typedef Genode::List<Range> Range_list;
typedef Genode::Lock Lock;
private:
struct Range : Range_list::Element
{
PPDMDEVINS _pDevIns;
RTIOPORT _PortStart;
RTUINT _cPorts;
RTHCPTR _pvUser;
PFNIOMIOPORTOUT _pfnOutCallback;
PFNIOMIOPORTIN _pfnInCallback;
PFNIOMIOPORTOUTSTRING _pfnOutStringCallback;
PFNIOMIOPORTINSTRING _pfnInStringCallback;
/**
* Return true if range contains specified subrange
*/
bool contains(RTIOPORT PortStart, RTUINT cPorts) const
{
return (PortStart >= _PortStart)
&& (PortStart + cPorts - 1 <= _PortStart + _cPorts - 1);
}
bool partof(RTIOPORT PortStart, RTUINT cPorts) const
{
return (PortStart <= _PortStart)
&& (PortStart + cPorts - 1 >= _PortStart + _cPorts - 1);
}
Range(PPDMDEVINS pDevIns,
RTIOPORT PortStart,
RTUINT cPorts,
RTHCPTR pvUser,
PFNIOMIOPORTOUT pfnOutCallback,
PFNIOMIOPORTIN pfnInCallback,
PFNIOMIOPORTOUTSTRING pfnOutStringCallback,
PFNIOMIOPORTINSTRING pfnInStringCallback)
:
_pDevIns (pDevIns),
_PortStart (PortStart),
_cPorts (cPorts),
_pvUser (pvUser),
_pfnOutCallback (pfnOutCallback),
_pfnInCallback (pfnInCallback),
_pfnOutStringCallback (pfnOutStringCallback),
_pfnInStringCallback (pfnInStringCallback)
{ }
VBOXSTRICTRC write(RTIOPORT port, uint32_t u32Value, unsigned cb)
{
if (!_pfnOutCallback)
return VINF_IOM_R3_IOPORT_WRITE;
// PDBG("IOPORT write Port=0x%lx", (long)port);
VBOXSTRICTRC rc = PDMCritSectEnter(_pDevIns->CTX_SUFF(pCritSectRo),
VINF_IOM_R3_IOPORT_WRITE);
if (rc != VINF_SUCCESS)
return rc;
rc = _pfnOutCallback(_pDevIns, _pvUser, port, u32Value, cb);
PDMCritSectLeave(_pDevIns->CTX_SUFF(pCritSectRo));
return rc;
}
VBOXSTRICTRC read(RTIOPORT port, uint32_t *pu32Value, unsigned cb)
{
if (!_pfnInCallback)
return VINF_IOM_R3_IOPORT_READ;
VBOXSTRICTRC rc = PDMCritSectEnter(_pDevIns->CTX_SUFF(pCritSectRo),
VINF_IOM_R3_IOPORT_READ);
if (rc != VINF_SUCCESS)
return rc;
rc = _pfnInCallback(_pDevIns, _pvUser, port, pu32Value, cb);
if (rc != VINF_SUCCESS)
PDBG("IOPORT read port=0x%x failed - callback %p eip %p",
port, _pfnInCallback, __builtin_return_address(0));
PDMCritSectLeave(_pDevIns->CTX_SUFF(pCritSectRo));
return rc;
}
};
Lock _lock;
Range_list _ranges;
Range *_lookup(RTIOPORT PortStart, RTUINT cPorts)
{
for (Range *r = _ranges.first(); r; r = r->next())
if (r->contains(PortStart, cPorts))
return r;
return 0;
}
public:
int add_range(PPDMDEVINS pDevIns,
RTIOPORT PortStart, RTUINT cPorts, RTHCPTR pvUser,
R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback,
R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStringCallback,
R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStringCallback)
{
Range *r = _lookup(PortStart, cPorts);
if (r)
return VERR_GENERAL_FAILURE;
_ranges.insert(new (Genode::env()->heap())
Range(pDevIns, PortStart, cPorts, pvUser,
pfnOutCallback, pfnInCallback,
pfnOutStringCallback, pfnInStringCallback));
return VINF_SUCCESS;
}
int remove_range(PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts)
{
bool deleted = false;
for (Range *r = _ranges.first(); r;)
{
if (!r->partof(PortStart, cPorts)) {
r = r->next();
continue;
}
deleted = true;
PERR("delete %x+%x", r->_PortStart, r->_cPorts);
Range *s = r;
r = r->next();
_ranges.remove(s);
}
return deleted ? VINF_SUCCESS : VERR_GENERAL_FAILURE;
}
VBOXSTRICTRC write(RTIOPORT Port, uint32_t u32Value, size_t cbValue)
{
Range *r = _lookup(Port, cbValue);
if (r)
return r->write(Port, u32Value, cbValue);
char c = u32Value & 0xff;
// PWRN("attempted to write to non-existing port 0x%lx+%u %c (%02x)", Port, cbValue,
// c >= 32 && c <= 176 ? c : '.', c);
return VINF_SUCCESS;
// return VERR_GENERAL_FAILURE; /* recompiler does not like this */
}
VBOXSTRICTRC read(RTIOPORT port, uint32_t *pu32Value, unsigned cbValue)
{
Range *r = _lookup(port, cbValue);
if (r) {
VBOXSTRICTRC err = r->read(port, pu32Value, cbValue);
if (err != VERR_IOM_IOPORT_UNUSED)
return err;
}
// PWRN("attempted to read from non-existing port 0x%x+%u %p", port, cbValue, r);
switch (cbValue)
{
case 1:
*reinterpret_cast<uint8_t *>(pu32Value) = 0xFFU;
break;
case 2:
*reinterpret_cast<uint16_t *>(pu32Value) = 0xFFFFU;
break;
case 4:
*reinterpret_cast<uint32_t *>(pu32Value) = 0xFFFFFFFFU;
break;
default:
PERR("Invalid I/O port (%x) access of size (%x)", port, cbValue);
return VERR_IOM_INVALID_IOPORT_SIZE;
}
return VINF_SUCCESS;
// return VERR_IOM_IOPORT_UNUSED; /* recompiler does not like this */
}
};
/**
* Return pointer to singleton instance
*/
Guest_ioports *guest_ioports()
{
static Guest_ioports inst;
return &inst;
}
int
IOMR3IOPortRegisterR3(PVM pVM, PPDMDEVINS pDevIns,
RTIOPORT PortStart, RTUINT cPorts, RTHCPTR pvUser,
R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback,
R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStringCallback,
R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStringCallback,
const char *pszDesc)
{
PLOG("register I/O port range 0x%x-0x%x '%s'",
PortStart, PortStart + cPorts - 1, pszDesc);
return guest_ioports()->add_range(pDevIns, PortStart, cPorts, pvUser,
pfnOutCallback, pfnInCallback,
pfnOutStringCallback, pfnInStringCallback);
}
int IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart,
RTUINT cPorts)
{
PLOG("deregister I/O port range 0x%x-0x%x",
PortStart, PortStart + cPorts - 1);
return guest_ioports()->remove_range(pDevIns, PortStart, cPorts);
}
VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value,
size_t cbValue)
{
// PDBG("IOMIOPortWrite Port=0x%lx cbValue=%zd", (long)Port, cbValue);
return guest_ioports()->write(Port, u32Value, cbValue);
}
VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value,
size_t cbValue)
{
return guest_ioports()->read(Port, pu32Value, cbValue);
}

View File

@ -0,0 +1,127 @@
/*
* \brief VirtualBox runtime (RT)
* \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/printf.h>
#include <util/string.h>
/* libc includes */
#include <stdlib.h>
#include <signal.h>
/* libc memory allocator */
#include <libc_mem_alloc.h>
/* VirtualBox includes */
#include <iprt/mem.h>
using Genode::size_t;
/*
* We cannot use the libc's version of malloc because it does not satisfies
* the alignment constraints asserted by 'Runtime/r3/alloc.cpp'.
*/
extern "C" void *malloc(size_t size)
{
return Libc::mem_alloc()->alloc(size, Genode::log2(RTMEM_ALIGNMENT));
}
extern "C" void *calloc(size_t nmemb, size_t size)
{
void *ret = malloc(nmemb*size);
Genode::memset(ret, 0, nmemb*size);
return ret;
}
extern "C" void free(void *ptr)
{
Libc::mem_alloc()->free(ptr);
}
extern "C" void *realloc(void *ptr, Genode::size_t size)
{
if (!ptr)
return malloc(size);
if (!size) {
free(ptr);
return 0;
}
/* determine size of old block content (without header) */
unsigned long old_size = Libc::mem_alloc()->size_at(ptr);
/* do not reallocate if new size is less than the current size */
if (size <= old_size)
return ptr;
/* allocate new block */
void *new_addr = malloc(size);
/* copy content from old block into new block */
if (new_addr)
Genode::memcpy(new_addr, ptr, Genode::min(old_size, (unsigned long)size));
/* free old block */
free(ptr);
return new_addr;
}
extern "C" char *getenv(const char *name)
{
/*
* Logging to the pseudo file '/log' is done via the libc plugin provided
* by 'logging.cc'.
*/
if (Genode::strcmp(name, "VBOX_LOG_DEST") == 0 ||
Genode::strcmp(name, "VBOX_RELEASE_LOG_DEST") == 0)
return (char *)"file=log";
if (Genode::strcmp(name, "VBOX_LOG") == 0 ||
Genode::strcmp(name, "VBOX_RELEASE_LOG") == 0)
return (char *)"+rem_dias.e.l.f"
"+rem_printf.e.l.f"
// "+rem_run.e.l.f"
// "+pgm.e.l.f"
"+pdm"
// "+dev_pic.e.l.f"
// "+dev_apic.e.l.f"
;
if (Genode::strcmp(name, "VBOX_LOG_FLAGS") == 0 ||
Genode::strcmp(name, "VBOX_RELEASE_LOG_FLAGS") == 0)
return (char *)"thread";
PWRN("getenv called for non-existent variable \"%s\"", name);
return 0;
}
extern "C" int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact)
{
/*
* Break infinite loop at 'VBox/Runtime/r3/init.cpp' :451
*/;
if (oldact)
oldact->sa_flags = SA_SIGINFO;
return 0;
}

View File

@ -0,0 +1,149 @@
/*
* \brief Redirect VirtualBox LOG output to Genode LOG
* \author Norman Feske
* \date 2013-08-23
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* libc plugin interface */
#include <libc-plugin/plugin.h>
#include <libc-plugin/fd_alloc.h>
/* libc includes */
#include <errno.h>
#include <fcntl.h>
#include <string.h>
/* interface to 'log_console' */
extern "C" int stdout_write(const char *);
namespace {
struct Plugin_context : Libc::Plugin_context { };
class Plugin : public Libc::Plugin
{
private:
Plugin_context _context;
Libc::File_descriptor *_fd;
char const *log_file_name() const { return "/log"; }
bool _match(char const *name) const
{
return strcmp(name, log_file_name()) == 0;
}
public:
Plugin() :
_fd(Libc::file_descriptor_allocator()->alloc(this, &_context))
{ }
bool supports_stat(const char *path)
{
return _match(path);
}
bool supports_open(const char *path, int flags)
{
return _match(path);
}
int stat(const char *path, struct stat *buf)
{
bool const match = _match(path);
if (buf && match) {
Genode::memset(buf, 0, sizeof(struct stat));
buf->st_mode = S_IFCHR;
}
errno = match ? 0 : ENOENT;
return match ? 0 : -1;
}
Libc::File_descriptor *open(const char *pathname, int flags)
{
return _match(pathname) ? _fd : 0;
}
int fcntl(Libc::File_descriptor *fd, int cmd, long arg)
{
switch (cmd) {
case F_GETFL: return O_WRONLY;
default: PERR("fcntl(): command %d not supported", cmd); return -1;
}
}
int fstat(Libc::File_descriptor *, struct stat *buf)
{
/*
* The following values were obtained with small test program that
* calls fstat for stdout on linux.
*/
buf->st_dev = 11;
buf->st_ino = 4;
buf->st_mode = 8592;
buf->st_nlink = 1;
buf->st_uid = 0;
buf->st_gid = 0;
buf->st_rdev = 34818;
buf->st_size = 0;
buf->st_blksize = 1024;
buf->st_blocks = 0;
return 0;
}
ssize_t write(Libc::File_descriptor *fd, const void *buf, ::size_t count)
{
if (fd != _fd) {
errno = EBADF;
return -1;
}
char *src = (char *)buf;
/* count does not include the trailing '\0' */
int orig_count = count;
while (count > 0) {
char tmp[128];
int curr_count= count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count;
strncpy(tmp, src, curr_count);
tmp[curr_count > 0 ? curr_count : 0] = 0;
stdout_write(tmp);
count -= curr_count;
src += curr_count;
}
return orig_count;
}
int ioctl(Libc::File_descriptor *, int request, char *)
{
/*
* Some programs or libraries use to perform 'TIOCGETA'
* operations on stdout, in particular the termios module of
* Python. Those programs may break if 'tcgetattr' return with
* an error. We pretend to be more successful than we really
* are to make them happy.
*/
return 0;
}
};
} /* unnamed namespace */
void __attribute__((constructor)) init_libc_log(void)
{
static Plugin plugin;
}

View File

@ -0,0 +1,214 @@
/*
* \brief Port of VirtualBox to Genode
* \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/env.h>
#include <base/printf.h>
#include <os/config.h>
#include <base/snprintf.h>
/* libc includes */
#include <stdio.h>
/* Virtualbox includes of VBoxBFE */
#include <iprt/initterm.h>
#include <iprt/err.h>
void *operator new (Genode::size_t size) {
return Genode::env()->heap()->alloc(size); }
void operator delete(void * p) {
if (Genode::env()->heap()->need_size_for_free()) {
PERR("leaking memory - delete operator is missing size information");
return;
}
Genode::env()->heap()->free(p, 0);
}
extern "C" {
/* string conversion function currently does not convert ... */
int RTStrCurrentCPToUtf8Tag(char **ppszString, char *pszString,
const char *pszTag)
{
/* dangerous */
*ppszString = pszString;
return 0;
}
/* don't use 'Runtime/r3/posix/utf8-posix.cpp' because it depends on libiconv */
int RTStrUtf8ToCurrentCPTag(char **ppszString, char *pszString,
const char *pszTag)
{
/* dangerous */
*ppszString = pszString;
return 0;
}
char * RTPathRealDup(const char *pszPath)
{
/* dangerous */
return (char *)pszPath;
}
bool RTPathExists(const char *pszPath)
{
return true;
}
/* make output of Virtualbox visible */
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (!stream || !ptr ||
!(fileno(stdout) == fileno(stream) || fileno(stderr) == fileno(stream)))
return EOF;
char const * cptr = reinterpret_cast<const char *>(ptr);
for (size_t j = 0; j < nmemb; j++)
for (size_t i = 0; i < size; i++)
Genode::printf("%c", cptr[j * size + i]);
return nmemb;
}
int fprintf(FILE *stream, const char *format, ...) /* called by RTAssertMsg1 */
{
if (!stream ||
!(fileno(stdout) == fileno(stream) || fileno(stderr) == fileno(stream)))
return EOF;
va_list list;
va_start(list, format);
Genode::vprintf(format, list);
va_end(list);
return 0;
}
int fputs(const char *s, FILE *stream) /* called by RTAssertMsg2Weak */
{
if (!stream ||
!(fileno(stdout) == fileno(stream) || fileno(stderr) == fileno(stream)))
return EOF;
fwrite(s, Genode::strlen(s), 1, stream);
}
/* our libc provides a _nanosleep function */
int _nanosleep(const struct timespec *req, struct timespec *rem);
int nanosleep(const struct timespec *req, struct timespec *rem) {
return _nanosleep(req, rem); }
/*
* Genode way of using a configuration. Wrap VBox main until we throught it
* out eventually.
*/
/* main function of VBox is in Frontends/VBoxBFE/VBoxBFE.cpp */
extern "C" DECLEXPORT(int) TrustedMain (int argc, char **argv, char **envp);
int main(int, char **)
{
static char c_mem[16];
static char c_type[4];
static char c_file[128];
static bool bOverlay = false;
int argc = 9;
char * argv[argc + 1];
/* request max available memory */
size_t vm_size = Genode::env()->ram_session()->avail();
enum { VMM_MEMORY = 64 * 1024 * 1024 /* let a bit memory for the VMM */ };
if (vm_size < VMM_MEMORY) {
PERR("not enough memory available - need %u, available only %zu "
"- exit", VMM_MEMORY, vm_size);
return 1;
}
vm_size -= VMM_MEMORY;
try {
using namespace Genode;
Xml_node node = config()->xml_node().sub_node("image");
Xml_node::Attribute type = node.attribute("type");
Xml_node::Attribute file = node.attribute("file");
try {
Xml_node::Attribute overlay = node.attribute("overlay");
overlay.value(c_type, sizeof(c_type));
if (!strcmp(c_type, "yes"))
bOverlay = true;
} catch (...) { }
type.value(c_type, sizeof(c_type));
file.value(c_file, sizeof(c_file));
} catch (...) {
PERR("C++ exception during xml parsing");
return 2;
}
argv[0] = (char *)"virtualbox";
argv[1] = (char *)"-m";
Genode::snprintf(c_mem, sizeof(c_mem), "%u", vm_size / 1024 / 1024);
argv[2] = c_mem;
argv[3] = (char *)"-boot";
if (!Genode::strcmp(c_type, "iso")) {
argv[4] = (char *)"d";
argv[5] = (char *)"-cdrom";
} else
if (!Genode::strcmp(c_type, "vdi")) {
argv[4] = (char *)"c";
argv[5] = (char *)"-hda";
} else {
PERR("invalid configuration - abort");
return 3;
}
argv[6] = c_file;
argv[7] = (char *)"-ioapic";
if (9 > argc + 1) {
PERR("argc argv misconfiguration - abort");
return 4;
}
if (bOverlay)
argv[8] = (char *)"-overlay";
else {
argc -= 1;
argv[8] = 0;
}
argv[9] = 0;
PINF("start %s image '%s' with %zu MB Guest memory=%zu",
c_type, c_file, vm_size / 1024 / 1024,
Genode::env()->ram_session()->avail());
if (RT_FAILURE(RTR3InitExe(argc, (char ***)&argv, 0))) {
PERR("Intialization of VBox Runtime failed.");
return 5;
}
return TrustedMain(argc, argv, NULL);
}
} /* EXTERN "C" */

313
ports/src/virtualbox/mm.cc Normal file
View File

@ -0,0 +1,313 @@
/*
* \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/printf.h>
#include <util/string.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"
int MMR3Init(PVM pVM)
{
PDBG("MMR3Init called, not implemented");
return VINF_SUCCESS;
}
int MMR3InitUVM(PUVM pUVM)
{
PDBG("MMR3InitUVM called, not implemented");
return VINF_SUCCESS;
}
void *MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
{
return Libc::mem_alloc()->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_PDM_DEVICE:
case MM_TAG_PDM_DEVICE_USER:
return 12;
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);
void *ret = Libc::mem_alloc()->alloc(rounded_size, align_by_mmtag(enmTag));
// PINF("MMR3HeapAlloc: enmTag=%d cbSize=0x%zx -> 0x%p (0x%zx)",
// enmTag, cbSize, ret, rounded_size);
return ret;
}
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;
}
int MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
{
*ppv = MMR3HeapAllocZ(pVM, enmTag, cbSize);
return VINF_SUCCESS;
}
int MMR3HyperAllocOnceNoRel(PVM pVM, size_t cb, unsigned uAlignment,
MMTAG enmTag, void **ppv)
{
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 = Libc::mem_alloc()->alloc(rounded_size, align_log2);
if (ret)
Genode::memset(ret, 0, cb);
PINF("MMR3HyperAllocOnceNoRel: enmTag=%d align_log2=%u cb=0x%zx -> 0x%p",
enmTag, align_log2, cb, ret);
*ppv = ret;
return VINF_SUCCESS;
}
int MMR3HyperAllocOnceNoRelEx(PVM pVM, size_t cb, uint32_t uAlignment,
MMTAG enmTag, uint32_t fFlags, void **ppv)
{
return MMR3HyperAllocOnceNoRel(pVM, cb, uAlignment, enmTag, ppv);
}
int MMHyperAlloc(PVM pVM, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv)
{
AssertRelease(align_by_mmtag(enmTag) >= uAlignment);
*ppv = MMR3HeapAllocZ(pVM, enmTag, cb);
return VINF_SUCCESS;
}
int MMHyperFree(PVM pVM, void *pv)
{
Libc::mem_alloc()->free(pv);
return VINF_SUCCESS;
}
void MMR3HeapFree(void *pv) { Libc::mem_alloc()->free(pv); }
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); }
uint64_t MMR3PhysGetRamSize(PVM pVM)
{
PDBG("MMR3PhysGetRamSize called, return 0");
/* 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)
{
PDBG("pszDesc=%s", pszDesc);
*pGCPtr = (RTGCPTR)HCPhys;
return VINF_SUCCESS;
}
int MMR3HyperReserve(PVM pVM, unsigned cb, const char *pszDesc, PRTGCPTR pGCPtr)
{
PINF("MMR3HyperReserve: cb=0x%x, pszDesc=%s", cb, pszDesc);
return VINF_SUCCESS;
}
int MMR3HyperMapMMIO2(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
RTGCPHYS off, RTGCPHYS cb, const char *pszDesc,
PRTRCPTR pRCPtr)
{
PLOG("MMR3HyperMapMMIO2: pszDesc=%s iRegion=%u off=0x%lx cb=0x%zx",
pszDesc, iRegion, (long)off, (size_t)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.
*/
PDBG("GMMR3InitialReservation missing");
/*
* 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 * MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz)
{
size_t cch = strlen(psz) + 1;
char *pszDup = (char *)MMR3HeapAllocU(pVM->pUVM, enmTag, cch);
if (pszDup)
memcpy(pszDup, psz, cch);
return pszDup;
}
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);
return pszRet;
}
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,234 @@
/*
* \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/printf.h>
#include <base/semaphore.h>
#include <base/flex_iterator.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 "HWACCMInternal.h" /* enable access to hwaccm.s.* */
#include "CPUMInternal.h" /* enable access to cpum.s.* */
#include <VBox/vmm/vm.h>
#include <VBox/vmm/hwacc_svm.h>
#include <VBox/err.h>
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "vcpu_svm.h"
#include "vcpu_vmx.h"
static Vcpu_handler *vcpu_handler = 0;
static Genode::Semaphore *r0_halt_sem()
{
static Genode::Semaphore sem;
return &sem;
}
/* Genode specific function */
void SUPR3QueryHWACCLonGenodeSupport(VM * pVM) {
try {
using namespace Genode;
Rom_connection hip_rom("hypervisor_info_page");
Nova::Hip * const hip = env()->rm_session()->attach(hip_rom.dataspace());
if (!hip)
return;
pVM->hwaccm.s.svm.fSupported = hip->has_feature_svm();
pVM->hwaccm.s.vmx.fSupported = hip->has_feature_vmx();
} catch (...) {
PWRN("No hardware acceleration available - execution will be slow!");
} /* if we get an exception let hardware support off */
}
void SUPR3QueryHWACCLonGenodeCreateVM(VM * pVM)
{
bool svm = pVM->hwaccm.s.svm.fSupported;
if (!svm && !pVM->hwaccm.s.vmx.fSupported) {
PERR("SVM nor VMX supported by hardware accelerated code called !");
return;
}
Assert(!vcpu_handler);
if (svm)
vcpu_handler = new Vcpu_handler_svm();
else
vcpu_handler = new Vcpu_handler_vmx();
}
/* VirtualBox SUPLib interface */
int SUPR3QueryVTxSupported(void)
{
return VINF_SUCCESS;
}
int SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
{
switch (uOperation)
{
case SUP_VMMR0_DO_HWACC_RUN:
{
VM * pVM = reinterpret_cast<VM *>(pVMR0);
PVMCPU pVCpu = &pVM->aCpus[idCpu];
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
return vcpu_handler->run_hw(pVMR0, idCpu);
}
default:
break;
}
return VERR_INTERNAL_ERROR;
}
int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
{
static unsigned counter = 0;
switch(uOperation)
{
case VMMR0_DO_GVMM_CREATE_VM:
genode_VMMR0_DO_GVMM_CREATE_VM(pReqHdr);
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_HALT:
// counter ++;
// PERR("halt %u", counter);
r0_halt_sem()->down();
// PERR("halt - done");
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_WAKE_UP:
// counter ++;
// PERR("sched wake up %u", counter);
r0_halt_sem()->up();
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_POLL:
/* called by 'vmR3HaltGlobal1Halt' */
// PDBG("SUPR3CallVMMR0Ex: VMMR0_DO_GVMM_SCHED_POLL");
return VINF_SUCCESS;
case VMMR0_DO_VMMR0_INIT:
{
VM * pVM = reinterpret_cast<VM *>(pVMR0);
SUPR3QueryHWACCLonGenodeSupport(pVM);
return VINF_SUCCESS;
}
case VMMR0_DO_HWACC_SETUP_VM:
{
VM * pVM = reinterpret_cast<VM *>(pVMR0);
SUPR3QueryHWACCLonGenodeCreateVM(pVM);
return VINF_SUCCESS;
}
case VMMR0_DO_HWACC_ENABLE:
return VINF_SUCCESS;
case VMMR0_DO_GVMM_SCHED_POKE:
{
/* XXX only do one of it - either recall or up - not both XXX */
vcpu_handler->recall();
r0_halt_sem()->up();
return VINF_SUCCESS;
}
default:
PERR("SUPR3CallVMMR0Ex: unhandled uOperation %d", uOperation);
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 (...) {
PERR("could not read out CPU frequency.");
Genode::Lock lock;
lock.lock();
}
}
return cpu_freq;
}
extern "C" int pthread_yield() {
Nova::ec_ctrl(Nova::EC_YIELD);
return 0;
}
bool Vmm_memory::unmap_from_vm(RTGCPHYS GCPhys)
{
size_t const size = 1;
Region *r = _lookup_unsynchronized(GCPhys, size);
if (!r) return false;
using Genode::addr_t;
addr_t const vmm_local = (addr_t)r->local_addr<addr_t>();
Assert(vmm_local);
Assert(!((r->size() - 1) & vmm_local));
using namespace Nova;
unsigned const order = Genode::log2(r->size() >> PAGE_SIZE_LOG2);
Rights rwx(true, true, true);
revoke(Mem_crd(vmm_local >> PAGE_SIZE_LOG2, order, rwx), false);
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 _GENODE_VIRTUALBOX_SVM__H_
#define _GENODE_VIRTUALBOX_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 /* _GENODE_VIRTUALBOX_SVM__H_ */

View File

@ -0,0 +1,756 @@
/*
* \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.
*/
#ifndef _VCPU_H__
#define _VCPU_H__
/* Genode includes */
#include <base/printf.h>
#include <base/semaphore.h>
#include <base/flex_iterator.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 <VBox/vmm/vm.h>
#include <VBox/err.h>
#include <VBox/vmm/pdmapi.h>
/* Genode's VirtualBox includes */
#include "sup.h"
#include "guest_memory.h"
#include "vmm_memory.h"
/*
* VirtualBox stores segment attributes in Intel format using a 32-bit
* value. NOVA represents the attributes in packet 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);
}
extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite);
class Vcpu_handler : public Vmm::Vcpu_dispatcher
{
private:
enum { STACK_SIZE = 4096 };
Genode::Cap_connection _cap_connection;
Vmm::Vcpu_other_pd _vcpu;
Genode::addr_t _ec_sel = 0;
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));
}
protected:
/* unlocked by first startup exception */
Genode::Lock _lock_startup;
Genode::Lock _signal_vcpu;
Genode::Lock _signal_emt;
PVM _current_vm;
PVMCPU _current_vcpu;
unsigned _current_exit_cond;
__attribute__((noreturn)) void _default_handler(unsigned cond)
{
using namespace Nova;
using namespace Genode;
Thread_base *myself = Thread_base::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
/* tell caller what happened */
_current_exit_cond = cond;
PVMCPU pVCpu = _current_vcpu;
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
fpu_save(reinterpret_cast<char *>(&pCtx->fpu));
/* unblock caller */
_signal_emt.unlock();
/* block myself */
_signal_vcpu.lock();
fpu_load(reinterpret_cast<char *>(&pCtx->fpu));
utcb->mtd |= Mtd::FPU;
Nova::reply(myself->stack_top());
}
template <unsigned NPT_EPT>
__attribute__((noreturn)) inline
void _exc_memory(Genode::Thread_base * myself, Nova::Utcb * utcb,
bool unmap, Genode::addr_t reason)
{
using namespace Nova;
using namespace Genode;
if (unmap) {
PERR("unmap not implemented\n");
/* deadlock until implemented */
_signal_vcpu.lock();
Nova::reply(myself->stack_top());
}
Flexpage_iterator fli;
void *pv = guest_memory()->lookup_ram(reason, 0x1000UL, fli);
if (!pv) {
pv = vmm_memory()->lookup(reason, 0x1000UL);
if (pv) { /* XXX */
fli = Genode::Flexpage_iterator((addr_t)pv, 0x1000UL,
reason, 0x1000UL, reason);
int res = MMIO2_MAPPED_SYNC(_current_vm, reason, 0x1);
/*
Genode::addr_t fb_phys = 0xf0000000UL;
Genode::addr_t fb_size = 0x00400000UL;
pv = vmm_memory()->lookup(fb_phys, fb_size);
fli = Genode::Flexpage_iterator((addr_t)pv, fb_size,
fb_phys, fb_size, fb_phys);
int res = MMIO2_MAPPED_SYNC(_current_vm, fb_phys, fb_size);
*/
}
}
/* emulator has to take over if fault region is not ram */
if (!pv) {
/* tell caller what happened */
_current_exit_cond = NPT_EPT;
PVMCPU pVCpu = _current_vcpu;
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
fpu_save(reinterpret_cast<char *>(&pCtx->fpu));
/* unblock caller */
_signal_emt.unlock();
/* block myself */
_signal_vcpu.lock();
fpu_load(reinterpret_cast<char *>(&pCtx->fpu));
utcb->mtd |= Mtd::FPU;
Nova::reply(myself->stack_top());
}
/* fault region is ram - so map it */
enum {
USER_PD = false, GUEST_PGT = true,
READABLE = true, WRITEABLE = true, EXECUTABLE = true
};
Rights const permission(READABLE, WRITEABLE, EXECUTABLE);
/* prepare utcb */
utcb->set_msg_word(0);
utcb->mtd = 0;
/* add map items until no space is left on utcb anymore */
bool res;
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);
} while (res);
Nova::reply(myself->stack_top());
}
/**
* 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))
PERR("could not register handler %lx", 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;
if (utcb->ip != pCtx->rip) {
utcb->mtd |= Mtd::EIP;
utcb->ip = pCtx->rip;
}
if (utcb->sp != pCtx->rsp) {
utcb->mtd |= Mtd::ESP;
utcb->sp = pCtx->rsp;
}
if (utcb->ax != pCtx->rax || utcb->bx != pCtx->rbx ||
utcb->cx != pCtx->rcx || utcb->dx != pCtx->rdx)
{
utcb->mtd |= Mtd::ACDB;
utcb->ax = pCtx->rax;
utcb->bx = pCtx->rbx;
utcb->cx = pCtx->rcx;
utcb->dx = pCtx->rdx;
}
if (utcb->bp != pCtx->rbp || utcb->si != pCtx->rsi ||
utcb->di != pCtx->rdi)
{
utcb->mtd |= Mtd::EBSD;
utcb->bp = pCtx->rbp;
utcb->si = pCtx->rsi;
utcb->di = pCtx->rdi;
}
if (utcb->flags != pCtx->rflags.u) {
utcb->mtd |= Mtd::EFL;
utcb->flags = pCtx->rflags.u;
}
if (utcb->sysenter_cs != pCtx->SysEnter.cs ||
utcb->sysenter_sp != pCtx->SysEnter.esp ||
utcb->sysenter_ip != pCtx->SysEnter.eip)
{
utcb->mtd |= Mtd::SYS;
utcb->sysenter_cs = pCtx->SysEnter.cs;
utcb->sysenter_sp = pCtx->SysEnter.esp;
utcb->sysenter_ip = pCtx->SysEnter.eip;
}
if (utcb->dr7 != pCtx->dr[7]) {
utcb->mtd |= Mtd::DR;
utcb->dr7 = pCtx->dr[7];
}
if (utcb->cr0 != pCtx->cr0) {
utcb->mtd |= Mtd::CR;
utcb->cr0 = pCtx->cr0;
}
if (utcb->cr2 != pCtx->cr2) {
utcb->mtd |= Mtd::CR;
utcb->cr2 = pCtx->cr2;
}
if (utcb->cr3 != pCtx->cr3) {
utcb->mtd |= Mtd::CR;
utcb->cr3 = pCtx->cr3;
}
if (utcb->cr4 != pCtx->cr4) {
utcb->mtd |= Mtd::CR;
utcb->cr4 = pCtx->cr4;
}
if (utcb->idtr.limit != pCtx->idtr.cbIdt ||
utcb->idtr.base != pCtx->idtr.pIdt)
{
utcb->mtd |= Mtd::IDTR;
utcb->idtr.limit = pCtx->idtr.cbIdt;
utcb->idtr.base = pCtx->idtr.pIdt;
}
if (utcb->gdtr.limit != pCtx->gdtr.cbGdt ||
utcb->gdtr.base != pCtx->gdtr.pGdt)
{
utcb->mtd |= Mtd::GDTR;
utcb->gdtr.limit = pCtx->gdtr.cbGdt;
utcb->gdtr.base = pCtx->gdtr.pGdt;
}
if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) {
if (pCtx->rip != EMGetInhibitInterruptsPC(pVCpu)) {
PERR("intr_state nothing !=");
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
utcb->intr_state = 0;
while (1) {}
}
}
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->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);
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);
if (pCtx->cr4 != utcb->cr4)
CPUMSetGuestCR4(pVCpu, utcb->cr4);
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)
EMSetInhibitInterruptsPC(pVCpu, pCtx->rip);
else
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
return true;
}
inline void inj_event(Nova::Utcb * utcb, PVMCPU pVCpu)
{
PCPUMCTX const pCtx = CPUMQueryGuestCtxPtr(pVCpu);
if (!TRPMHasTrap(pVCpu)) {
if (VMCPU_FF_TESTANDCLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI)) {
PDBG("%u hoho", __LINE__);
while (1) {}
}
if (VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC))) {
if (!(utcb->flags & X86_EFL_IF)) {
unsigned vector = 0;
utcb->inj_info = 0x1000 | vector;
utcb->mtd |= Nova::Mtd::INJ;
} else
if (!VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) {
uint8_t irq;
int rc = PDMGetInterrupt(pVCpu, &irq);
Assert(RT_SUCCESS(rc));
rc = TRPMAssertTrap(pVCpu, irq, TRPM_HARDWARE_INT);
Assert(RT_SUCCESS(rc));
} else
PWRN("pending interrupt blocked due to INHIBIT flag");
}
}
/* can an interrupt be dispatched ? */
if (!TRPMHasTrap(pVCpu) || !(utcb->flags & X86_EFL_IF) ||
VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
return;
#ifdef VBOX_STRICT
if (TRPMHasTrap(pVCpu)) {
uint8_t u8Vector;
int const rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, 0, 0);
AssertRC(rc);
}
#endif
/* interrupt can be dispatched */
uint8_t u8Vector;
TRPMEVENT enmType;
SVM_EVENT Event;
RTGCUINT u32ErrorCode;
Event.au64[0] = 0;
/* If a new event is pending, then dispatch it now. */
int rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, 0);
AssertRC(rc);
Assert(pCtx->eflags.Bits.u1IF == 1 || enmType == TRPM_TRAP);
Assert(enmType != TRPM_SOFTWARE_INT);
/* Clear the pending trap. */
rc = TRPMResetTrap(pVCpu);
AssertRC(rc);
Event.n.u8Vector = u8Vector;
Event.n.u1Valid = 1;
Event.n.u32ErrorCode = u32ErrorCode;
Assert(enmType == TRPM_HARDWARE_INT);
Event.n.u3Type = SVM_EVENT_EXTERNAL_IRQ;
utcb->inj_info = Event.au64[0];
utcb->inj_error = Event.n.u32ErrorCode;
utcb->mtd |= Nova::Mtd::INJ;
/*
PDBG("type:info:vector %x:%x:%x",
Event.n.u3Type, utcb->inj_info, u8Vector);
*/
}
inline void irq_win(Nova::Utcb * utcb, PVMCPU pVCpu)
{
Assert(utcb->flags & X86_EFL_IF);
Nova::mword_t const mtd = Nova::Mtd::INJ;
utcb->mtd = ~mtd;
}
virtual bool hw_load_state(Nova::Utcb *, VM *, PVMCPU) = 0;
virtual bool hw_save_state(Nova::Utcb *, VM *, PVMCPU) = 0;
public:
enum Exit_condition
{
SVM_NPT = 0xfc,
SVM_INVALID = 0xfd,
VCPU_STARTUP = 0xfe,
RECALL = 0xff,
EMULATE_INSTR = 0x100
};
Vcpu_handler()
:
Vmm::Vcpu_dispatcher(STACK_SIZE, _cap_connection),
_ec_sel(Genode::cap_map()->insert()),
_lock_startup(Genode::Lock::LOCKED),
_signal_emt(Genode::Lock::LOCKED),
_signal_vcpu(Genode::Lock::LOCKED)
{ }
void start() {
_vcpu.start(_ec_sel);
/* wait until vCPU thread is up */
_lock_startup.lock();
}
void recall()
{
using namespace Nova;
if (ec_ctrl(EC_RECALL, _ec_sel) != NOVA_OK) {
PERR("recall failed");
Genode::Lock lock(Genode::Lock::LOCKED);
lock.lock();
}
}
inline void dump_register_state(PCPUMCTX pCtx)
{
PINF("pCtx");
PLOG("ip:sp:efl ax:bx:cx:dx:si:di %llx:%llx:%llx"
" %llx:%llx:%llx:%llx:%llx:%llx",
pCtx->rip, pCtx->rsp, pCtx->rflags.u, pCtx->rax, pCtx->rbx,
pCtx->rcx, pCtx->rdx, pCtx->rsi, pCtx->rdi);
PLOG("cs.attr.n.u4LimitHigh=0x%x", pCtx->cs.Attr.n.u4LimitHigh);
PLOG("cs base:limit:sel:ar %llx:%x:%x:%x", pCtx->cs.u64Base,
pCtx->cs.u32Limit, pCtx->cs.Sel, pCtx->cs.Attr.u);
PLOG("ds base:limit:sel:ar %llx:%x:%x:%x", pCtx->ds.u64Base,
pCtx->ds.u32Limit, pCtx->ds.Sel, pCtx->ds.Attr.u);
PLOG("es base:limit:sel:ar %llx:%x:%x:%x", pCtx->es.u64Base,
pCtx->es.u32Limit, pCtx->es.Sel, pCtx->es.Attr.u);
PLOG("fs base:limit:sel:ar %llx:%x:%x:%x", pCtx->fs.u64Base,
pCtx->fs.u32Limit, pCtx->fs.Sel, pCtx->fs.Attr.u);
PLOG("gs base:limit:sel:ar %llx:%x:%x:%x", pCtx->gs.u64Base,
pCtx->gs.u32Limit, pCtx->gs.Sel, pCtx->gs.Attr.u);
PLOG("ss base:limit:sel:ar %llx:%x:%x:%x", pCtx->ss.u64Base,
pCtx->ss.u32Limit, pCtx->ss.Sel, pCtx->ss.Attr.u);
PLOG("cr0:cr2:cr3:cr4 %llx:%llx:%llx:%llx",
pCtx->cr0, pCtx->cr2, pCtx->cr3, pCtx->cr4);
PLOG("ldtr base:limit:sel:ar %llx:%x:%x:%x", pCtx->ldtr.u64Base,
pCtx->ldtr.u32Limit, pCtx->ldtr.Sel, pCtx->ldtr.Attr.u);
PLOG("tr base:limit:sel:ar %llx:%x:%x:%x", pCtx->tr.u64Base,
pCtx->tr.u32Limit, pCtx->tr.Sel, pCtx->tr.Attr.u);
PLOG("gdtr base:limit %llx:%x", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt);
PLOG("idtr base:limit %llx:%x", pCtx->idtr.pIdt, pCtx->idtr.cbIdt);
PLOG("dr 0:1:2:3:4:5:6:7 %llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx",
pCtx->dr[0], pCtx->dr[1], pCtx->dr[2], pCtx->dr[3],
pCtx->dr[4], pCtx->dr[5], pCtx->dr[6], pCtx->dr[7]);
PLOG("sysenter cs:eip:esp %llx %llx %llx", pCtx->SysEnter.cs,
pCtx->SysEnter.eip, pCtx->SysEnter.esp);
}
inline void dump_register_state(Nova::Utcb * utcb)
{
PINF("utcb");
PLOG("ip:sp:efl ax:bx:cx:dx:si:di %lx:%lx:%lx"
" %lx:%lx:%lx:%lx:%lx:%lx",
utcb->ip, utcb->sp, utcb->flags, utcb->ax, utcb->bx,
utcb->cx, utcb->dx, utcb->si, utcb->di);
PLOG("cs base:limit:sel:ar %lx:%x:%x:%x", utcb->cs.base,
utcb->cs.limit, utcb->cs.sel, utcb->cs.ar);
PLOG("ds base:limit:sel:ar %lx:%x:%x:%x", utcb->ds.base,
utcb->ds.limit, utcb->ds.sel, utcb->ds.ar);
PLOG("es base:limit:sel:ar %lx:%x:%x:%x", utcb->es.base,
utcb->es.limit, utcb->es.sel, utcb->es.ar);
PLOG("fs base:limit:sel:ar %lx:%x:%x:%x", utcb->fs.base,
utcb->fs.limit, utcb->fs.sel, utcb->fs.ar);
PLOG("gs base:limit:sel:ar %lx:%x:%x:%x", utcb->gs.base,
utcb->gs.limit, utcb->gs.sel, utcb->gs.ar);
PLOG("ss base:limit:sel:ar %lx:%x:%x:%x", utcb->ss.base,
utcb->ss.limit, utcb->ss.sel, utcb->ss.ar);
PLOG("cr0:cr2:cr3:cr4 %lx:%lx:%lx:%lx",
utcb->cr0, utcb->cr2, utcb->cr3, utcb->cr4);
PLOG("ldtr base:limit:sel:ar %lx:%x:%x:%x", utcb->ldtr.base,
utcb->ldtr.limit, utcb->ldtr.sel, utcb->ldtr.ar);
PLOG("tr base:limit:sel:ar %lx:%x:%x:%x", utcb->tr.base,
utcb->tr.limit, utcb->tr.sel, utcb->tr.ar);
PLOG("gdtr base:limit %lx:%x", utcb->gdtr.base, utcb->gdtr.limit);
PLOG("idtr base:limit %lx:%x", utcb->idtr.base, utcb->idtr.limit);
PLOG("dr 7 %lx", utcb->dr7);
PLOG("sysenter cs:eip:esp %lx %lx %lx", utcb->sysenter_cs,
utcb->sysenter_ip, utcb->sysenter_sp);
PLOG("%x %x %x", utcb->intr_state, utcb->actv_state, utcb->mtd);
}
int run_hw(PVMR0 pVMR0, VMCPUID idCpu)
{
VM * pVM = reinterpret_cast<VM *>(pVMR0);
PVMCPU pVCpu = &pVM->aCpus[idCpu];
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(Thread_base::utcb());
using namespace Nova;
Genode::Thread_base *myself = Genode::Thread_base::myself();
/* Transfer vCPU state from vBox to Nova format */
if (!vbox_to_utcb(utcb, pVM, pVCpu) ||
!hw_load_state(utcb, pVM, pVCpu)) {
PERR("loading vCPU state failed");
/* deadlock here */
_signal_emt.lock();
}
/* check whether to inject interrupts */
inj_event(utcb, pVCpu);
ResumeExecution:
/*
* 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);
this->_current_vm = pVM;
this->_current_vcpu = pVCpu;
/* let vCPU run */
_signal_vcpu.unlock();
/* waiting to be woken up */
_signal_emt.lock();
this->_current_vm = 0;
this->_current_vcpu = 0;
// CPUMSetChangedFlags(pVCpu, 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)) {
PERR("saving vCPU state failed");
/* deadlock here */
_signal_emt.lock();
}
/* reset message transfer descriptor for next invocation */
utcb->mtd = 0;
if (utcb->intr_state & 3) {
/*
PDBG("reset intr_state - exit reason %u", _current_exit_cond);
*/
utcb->intr_state &= ~3;
utcb->mtd |= Mtd::STA;
}
switch (_current_exit_cond)
{
case RECALL:
case VMX_EXIT_EPT_VIOLATION:
case VMX_EXIT_PORT_IO:
case VMX_EXIT_ERR_INVALID_GUEST_STATE:
case VMX_EXIT_HLT:
case SVM_EXIT_IOIO:
case SVM_NPT:
case SVM_EXIT_HLT:
case SVM_INVALID:
case SVM_EXIT_MSR:
case EMULATE_INSTR:
return VINF_EM_RAW_EMULATE_INSTR;
case SVM_EXIT_VINTR:
case VMX_EXIT_IRQ_WINDOW:
{
if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) {
if (pCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
PERR("inhibit interrupts %x %x", pCtx->rip, EMGetInhibitInterruptsPC(pVCpu));
}
uint32_t check_vm = VM_FF_HWACCM_TO_R3_MASK | VM_FF_REQUEST
| VM_FF_PGM_POOL_FLUSH_PENDING
| VM_FF_PDM_DMA;
uint32_t check_vcpu = VMCPU_FF_HWACCM_TO_R3_MASK
| VMCPU_FF_PGM_SYNC_CR3
| VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL
| VMCPU_FF_REQUEST;
if (VM_FF_ISPENDING(pVM, check_vm)
|| VMCPU_FF_ISPENDING(pVCpu, check_vcpu))
{
Assert(VM_FF_ISPENDING(pVM, VM_FF_HWACCM_TO_R3_MASK) ||
VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_HWACCM_TO_R3_MASK));
if (RT_UNLIKELY(VM_FF_ISPENDING(pVM, VM_FF_PGM_NO_MEMORY)))
{
PERR(" no memory");
while (1) {}
}
// PERR(" em raw to r3");
return VINF_EM_RAW_TO_R3;
}
if ((utcb->intr_state & 3))
PERR("irq window with intr_state %x", utcb->intr_state);
irq_win(utcb, pVCpu);
goto ResumeExecution;
}
default:
PERR("unknown exit cond:ip:qual[0],[1] %lx:%lx:%llx:%llx",
_current_exit_cond, utcb->ip, utcb->qual[0], utcb->qual[1]);
while (1) {}
}
return VERR_INTERNAL_ERROR;
}
};
#endif /* _VCPU_H__ */

View File

@ -0,0 +1,134 @@
/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \date 2013-11-18
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "svm.h"
class Vcpu_handler_svm : public Vcpu_handler
{
private:
__attribute__((noreturn)) void _svm_vintr() {
_default_handler(SVM_EXIT_VINTR);
}
__attribute__((noreturn)) void _svm_rdtsc() {
_default_handler(SVM_EXIT_RDTSC);
}
__attribute__((noreturn)) void _svm_msr() {
_default_handler(SVM_EXIT_MSR);
}
__attribute__((noreturn)) void _svm_recall()
{
_default_handler(SVM_INVALID);
}
__attribute__((noreturn)) void _svm_halt()
{
_default_handler(SVM_EXIT_HLT);
}
__attribute__((noreturn)) void _svm_ioio()
{
using namespace Nova;
using namespace Genode;
Thread_base *myself = Thread_base::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
if (utcb->qual[0] & 0x4) {
unsigned ctrl0 = utcb->ctrl[0];
PERR("invalid gueststate");
/* deadlock here */
_signal_vcpu.lock();
utcb->ctrl[0] = ctrl0;
utcb->ctrl[1] = 0;
utcb->mtd = Mtd::CTRL;
Nova::reply(myself->stack_top());
}
_default_handler(SVM_EXIT_IOIO);
}
template <unsigned X>
__attribute__((noreturn)) void _svm_npt()
{
using namespace Nova;
using namespace Genode;
Thread_base *myself = Thread_base::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
_exc_memory<X>(myself, utcb, utcb->qual[0] & 1,
utcb->qual[1] & ~((1UL << 12) - 1));
}
__attribute__((noreturn)) void _svm_startup()
{
using namespace Nova;
Genode::Thread_base *myself = Genode::Thread_base::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
/* we are ready, unlock our creator */
_lock_startup.unlock();
/* wait until EMT thread say so */
_signal_vcpu.lock();
Nova::reply(myself->stack_top());
}
public:
Vcpu_handler_svm()
{
using namespace Nova;
typedef Vcpu_handler_svm This;
register_handler<RECALL, This,
&This::_svm_recall>(vcpu().exc_base(), Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_IOIO, This,
&This::_svm_ioio> (vcpu().exc_base(), Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_VINTR, This,
&This::_svm_vintr> (vcpu().exc_base(), Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_RDTSC, This,
&This::_svm_rdtsc> (vcpu().exc_base(), Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_MSR, This,
&This::_svm_msr> (vcpu().exc_base(), Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_NPT, This,
&This::_svm_npt<SVM_NPT>>(vcpu().exc_base(), Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_HLT, This,
&This::_svm_halt>(vcpu().exc_base(), Mtd(Mtd::ALL | Mtd::FPU));
register_handler<VCPU_STARTUP, This,
&This::_svm_startup>(vcpu().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);
}
};

View File

@ -0,0 +1,187 @@
/*
* \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.
*/
/* VirtualBox includes */
#include <VBox/vmm/hwacc_vmx.h>
#include "vmm_memory.h"
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "vmx.h"
extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite);
class Vcpu_handler_vmx : public Vcpu_handler
{
private:
template <unsigned X>
__attribute__((noreturn)) void _vmx_ept()
{
using namespace Nova;
using namespace Genode;
Thread_base *myself = Thread_base::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
_exc_memory<X>(myself, utcb, utcb->qual[0] & 0x38,
utcb->qual[1] & ~((1UL << 12) - 1));
}
__attribute__((noreturn)) void _vmx_startup()
{
Vmm::printf("%s\n", __func__);
using namespace Nova;
Genode::Thread_base *myself = Genode::Thread_base::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
/* we are ready, unlock our creator */
_lock_startup.unlock();
/* wait until EMT thread say so */
_signal_vcpu.lock();
/* avoid as many as possible VM exits */
utcb->mtd |= Mtd::CTRL;
utcb->ctrl[0] = 0;
utcb->ctrl[1] = 0;
Nova::reply(myself->stack_top());
}
__attribute__((noreturn)) void _vmx_recall()
{
_default_handler(RECALL);
}
__attribute__((noreturn)) void _vmx_pause()
{
_default_handler(EMULATE_INSTR);
}
__attribute__((noreturn)) void _vmx_triple()
{
Genode::Thread_base *myself = Genode::Thread_base::myself();
using namespace Nova;
Vmm::printf("triple fault - dead\n");
_signal_vcpu.lock();
_default_handler(EMULATE_INSTR);
}
__attribute__((noreturn)) void _vmx_msr_write()
{
_default_handler(EMULATE_INSTR);
}
__attribute__((noreturn)) void _vmx_msr_read()
{
_default_handler(EMULATE_INSTR);
}
__attribute__((noreturn)) void _vmx_ioio()
{
_default_handler(VMX_EXIT_PORT_IO);
}
__attribute__((noreturn)) void _vmx_invalid()
{
_default_handler(VMX_EXIT_ERR_INVALID_GUEST_STATE);
}
__attribute__((noreturn)) void _vmx_init()
{
_default_handler(EMULATE_INSTR);
}
__attribute__((noreturn)) void _vmx_irqwin()
{
_default_handler(VMX_EXIT_IRQ_WINDOW);
}
__attribute__((noreturn)) void _vmx_hlt()
{
_default_handler(VMX_EXIT_HLT);
}
__attribute__((noreturn)) void _vmx_cpuid()
{
_default_handler(EMULATE_INSTR);
}
__attribute__((noreturn)) void _vmx_rdtsc()
{
_default_handler(EMULATE_INSTR);
}
__attribute__((noreturn)) void _vmx_vmcall()
{
_default_handler(EMULATE_INSTR);
}
public:
Vcpu_handler_vmx()
{
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_init> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_IRQ_WINDOW, This,
&This::_vmx_irqwin> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_CPUID, This,
&This::_vmx_cpuid> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_HLT, This,
&This::_vmx_hlt> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_RDTSC, This,
&This::_vmx_rdtsc> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_VMCALL, This,
&This::_vmx_vmcall> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_PORT_IO, This,
&This::_vmx_ioio> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_RDMSR, This,
&This::_vmx_msr_read> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_WRMSR, This,
&This::_vmx_msr_write> (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_pause> (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);
}
};

View File

@ -0,0 +1,172 @@
/*
* \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 _GENODE_VIRTUALBOX_VMX__H_
#define _GENODE_VIRTUALBOX_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_REQUIRED(REG) \
(utcb->REG.sel != pCtx->REG.Sel) || \
(utcb->REG.limit != pCtx->REG.u32Limit) || \
(utcb->REG.base != pCtx->REG.u64Base) || \
((( pCtx->REG.Sel \
|| !CPUMIsGuestInPagedProtectedModeEx(pCtx) \
|| (!pCtx->cs.Attr.n.u1DefBig && !CPUMIsGuestIn64BitCodeEx(pCtx))) \
&& pCtx->REG.Attr.n.u1Present == 1) ? \
utcb->REG.ar != sel_ar_conv_to_nova(pCtx->REG.Attr.u | X86_SEL_TYPE_ACCESSED) : \
utcb->REG.ar != sel_ar_conv_to_nova(VMCS_SEG_UNUSABLE) \
)
#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; \
\
/* attribute fixup according to 'VMX_WRITE_SELREG' in 'HWVMXR0.h' */ \
if (( pCtx->REG.Sel \
|| !CPUMIsGuestInPagedProtectedModeEx(pCtx) \
|| (!pCtx->cs.Attr.n.u1DefBig && !CPUMIsGuestIn64BitCodeEx(pCtx))) \
&& pCtx->REG.Attr.n.u1Present == 1) \
{ \
utcb->REG.ar = sel_ar_conv_to_nova(pCtx->REG.Attr.u | X86_SEL_TYPE_ACCESSED); \
} else { \
utcb->REG.ar = sel_ar_conv_to_nova(VMCS_SEG_UNUSABLE); \
}
static inline bool vmx_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
if ((GENODE_WRITE_SELREG_REQUIRED(es)) ||
(GENODE_WRITE_SELREG_REQUIRED(ds)))
{
utcb->mtd |= Nova::Mtd::ESDS;
GENODE_WRITE_SELREG(es);
GENODE_WRITE_SELREG(ds);
}
if ((GENODE_WRITE_SELREG_REQUIRED(fs)) ||
(GENODE_WRITE_SELREG_REQUIRED(gs)))
{
utcb->mtd |= Nova::Mtd::FSGS;
GENODE_WRITE_SELREG(fs);
GENODE_WRITE_SELREG(gs);
}
if ((GENODE_WRITE_SELREG_REQUIRED(cs)) ||
(GENODE_WRITE_SELREG_REQUIRED(ss)))
{
utcb->mtd |= Nova::Mtd::CSSS;
GENODE_WRITE_SELREG(cs);
GENODE_WRITE_SELREG(ss);
}
/* ldtr */
if (pCtx->ldtr.Sel == 0) {
if (utcb->ldtr.sel != 0 ||
utcb->ldtr.limit != 0 ||
utcb->ldtr.base != 0 ||
utcb->ldtr.ar != sel_ar_conv_to_nova(0x82))
{
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 {
if (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))
{
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);
Assert(!CPUMIsGuestInRealModeEx(pCtx));
if (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))
{
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
#undef GENODE_WRITE_SELREG_REQUIRED
#endif /* _GENODE_VIRTUALBOX_VMX__H_ */

127
ports/src/virtualbox/pdm.cc Normal file
View File

@ -0,0 +1,127 @@
/*
* \brief VirtualBox pluggable device manager (PDM)
* \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/printf.h>
#include <util/string.h>
/* VirtualBox includes */
#include <VBox/vmm/pdmapi.h>
#include <VBox/vmm/pdmdrv.h>
#include <VBox/vmm/pdmdev.h>
#include "util.h"
static void RCSymbolDummy()
{
PDBG("unexpected call of RC symbol");
for (;;);
}
int PDMR3LdrGetSymbolRC(PVM pVM, const char *pszModule, const char *pszSymbol,
PRTRCPTR pRCPtrValue)
{
*pRCPtrValue = to_rtrcptr(RCSymbolDummy);
return VINF_SUCCESS;
}
int PDMR3LdrGetSymbolRCLazy(PVM pVM, const char *pszModule,
const char *pszSearchPath, const char *pszSymbol,
PRTRCPTR pRCPtrValue)
{
*pRCPtrValue = to_rtrcptr(RCSymbolDummy);
return VINF_SUCCESS;
}
static void R0SymbolDummy()
{
PDBG("unexpected call of R0 symbol");
for (;;);
}
int PDMR3LdrGetSymbolR0(PVM pVM, const char *pszModule, const char *pszSymbol,
PRTR0PTR ppvValue)
{
*ppvValue = (RTR0PTR)R0SymbolDummy;
return VINF_SUCCESS;
}
int PDMR3LdrGetSymbolR0Lazy(PVM pVM, const char *pszModule,
const char *pszSearchPath, const char *pszSymbol,
PRTR0PTR ppvValue)
{
*ppvValue = (RTR0PTR)R0SymbolDummy;
return VINF_SUCCESS;
}
extern "C" int VBoxDriversRegister(PCPDMDRVREGCB, uint32_t);
extern "C" int VBoxDevicesRegister(PPDMDEVREGCB, uint32_t);
static int dummy_VBoxDriversRegister(PCPDMDRVREGCB, uint32_t) { return VINF_SUCCESS; }
static int dummy_VBoxDevicesRegister(PPDMDEVREGCB, uint32_t) { return VINF_SUCCESS; }
int PDMR3LdrGetSymbolR3(PVM pVM, const char *pszModule, const char *pszSymbol,
void **ppvValue)
{
/*
* This function is called at initialization time via
* PDMR3Init -> pdmR3DrvInit -> pdmR3DrvLoad -> PDMR3LdrGetSymbolR3
*
* In this case, it is expected to return the pointer to the symbol
* called 'VBoxDriversRegister', which is normally contained in the
* dynamically loaded VBoxDD module. However, we link the driver
* statically to the binary. So we return the local pointer.
*/
if (Genode::strcmp(pszModule, "VBoxDD") == 0) {
if (Genode::strcmp(pszSymbol, "VBoxDriversRegister") == 0) {
*ppvValue = (void *)VBoxDriversRegister;
PDBG("return VBoxDriversRegister pointer");
return VINF_SUCCESS;
}
if (Genode::strcmp(pszSymbol, "VBoxDevicesRegister") == 0) {
*ppvValue = (void *)VBoxDevicesRegister;
PDBG("return VBoxDevicesRegister pointer");
return VINF_SUCCESS;
}
}
if (Genode::strcmp(pszModule, "VBoxDD2") == 0) {
if (Genode::strcmp(pszSymbol, "VBoxDriversRegister") == 0) {
*ppvValue = (void *)dummy_VBoxDriversRegister;
return VINF_SUCCESS;
}
if (Genode::strcmp(pszSymbol, "VBoxDevicesRegister") == 0) {
*ppvValue = (void *)dummy_VBoxDevicesRegister;
return VINF_SUCCESS;
}
}
PDBG("pszModule=%s pszSymbol=%s", pszModule, pszSymbol);
return VERR_SYMBOL_NOT_FOUND;
}

View File

@ -0,0 +1,10 @@
+++ src/VBox/VMM/VMMAll/PDMAllQueue.cpp
@@ -106,7 +106,7 @@
# ifdef VBOX_WITH_REM
REMR3NotifyQueuePending(pVM); /** @todo r=bird: we can remove REMR3NotifyQueuePending and let VMR3NotifyFF do the work. */
# endif
- VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM);
+ VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM | VMNOTIFYFF_FLAGS_POKE);
#endif
}
STAM_REL_COUNTER_INC(&pQueue->StatInsert);

583
ports/src/virtualbox/pgm.cc Normal file
View File

@ -0,0 +1,583 @@
/*
* \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/printf.h>
#include <util/string.h>
/* VirtualBox includes */
#include "PGMInternal.h" /* enable access to pgm.s.* */
#include <VBox/vmm/mm.h>
#include <VBox/vmm/vm.h>
#include <VBox/vmm/pgm.h>
#include <VBox/vmm/rem.h>
#include <iprt/err.h>
/* local includes */
#include "util.h"
#include "vmm_memory.h"
#include "guest_memory.h"
using Genode::Ram_session;
using Genode::Rm_session;
Vmm_memory *vmm_memory()
{
static Vmm_memory inst(*Genode::env()->ram_session());
return &inst;
}
Guest_memory *guest_memory()
{
static Guest_memory inst;
return &inst;
}
int PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys,
RTGCPHYS cb, const void *pvBinary, uint32_t cbBinary,
uint32_t fFlags, const char *pszDesc)
{
PLOG("PGMR3PhysRomRegister: GCPhys=0x%lx cb=0x%zx pvBinary=0x%p",
(long)GCPhys, (size_t)cb, pvBinary);
try {
guest_memory()->add_rom_mapping(GCPhys, cb, pvBinary, pDevIns);
guest_memory()->dump();
/*
* XXX Try to understand the fShadowed condition
* (see pgmR3PhysRomRegister)
*/
REMR3NotifyPhysRomRegister(pVM, GCPhys, cb, NULL, false /* fShadowed */);
} catch (Guest_memory::Region_conflict) {
return VERR_PGM_MAPPING_CONFLICT; }
return VINF_SUCCESS;
}
int PGMPhysWrite(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
{
void *pv = guest_memory()->lookup(GCPhys, cbWrite);
/*
PLOG("PGMPhysWrite: GCPhys=0x%lx pvBuf=0x%p cbWrite=0x%zx pv=%p",
(long)GCPhys, pvBuf, cbWrite, pv);
*/
if (pv) {
memcpy(pv, pvBuf, cbWrite);
return VINF_SUCCESS;
}
PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0;
void *pvUserR3 = 0;
pv = vmm_memory()->lookup(GCPhys, cbWrite, &pfnHandlerR3, &pvUserR3);
if (!pv || !pfnHandlerR3 || !pvUserR3) {
PERR("PGMPhysWrite skipped: GCPhys=0x%lx pvBuf=0x%p cbWrite=0x%zx",
GCPhys, pvBuf, cbWrite);
return VERR_GENERAL_FAILURE;
}
int rc = pfnHandlerR3(pVM, GCPhys, 0, 0, cbWrite, PGMACCESSTYPE_WRITE,
pvUserR3);
if (rc == VINF_PGM_HANDLER_DO_DEFAULT) {
memcpy(pv, pvBuf, cbWrite);
return VINF_SUCCESS;
}
PERR("unexpected %s return code %d", __FUNCTION__, rc);
return VERR_GENERAL_FAILURE;
}
int PGMR3PhysWriteExternal(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf,
size_t cbWrite, const char *pszWho)
{
// PDBG("GCPhys=0x%llx pvBuf=0x%p cbWrite=0x%zx - '%s'",
// GCPhys, pvBuf, cbWrite, pszWho);
return PGMPhysWrite(pVM, GCPhys, pvBuf, cbWrite);
}
int PGMPhysRead(PVM pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
{
void *pv = guest_memory()->lookup(GCPhys, cbRead);
// PLOG("PGMPhysRead: GCPhys=0x%x pvBuf=0x%p cbRead=0x%zx pv=%p",
// GCPhys, pvBuf, cbRead, pv);
if (pv) {
memcpy(pvBuf, pv, cbRead);
return VINF_SUCCESS;
}
PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0;
void *pvUserR3 = 0;
pv = vmm_memory()->lookup(GCPhys, cbRead, &pfnHandlerR3, &pvUserR3);
if (!pv || !pfnHandlerR3 || !pvUserR3) {
PERR("PGMPhysRead skipped: GCPhys=0x%lx pvBuf=0x%p cbRead=0x%zx",
GCPhys, pvBuf, cbRead);
return VERR_GENERAL_FAILURE;
}
memcpy(pvBuf, pv, cbRead);
return VINF_SUCCESS;
}
int PGMR3PhysReadExternal(PVM pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
{
void *pv = guest_memory()->lookup(GCPhys, cbRead);
// PLOG("PGMPhysReadExternal: GCPhys=0x%x pvBuf=0x%p cbRead=0x%zx pv=%p",
// GCPhys, pvBuf, cbRead, pv);
return PGMPhysRead(pVM, GCPhys, pvBuf, cbRead);
}
int PGMR3PhysMMIO2Register(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
RTGCPHYS cb, uint32_t fFlags, void **ppv, const char
*pszDesc)
{
*ppv = vmm_memory()->alloc((size_t)cb, pDevIns, iRegion);
PLOG("PGMR3PhysMMIO2Register: pszDesc=%s iRegion=%u cb=0x%zx -> 0x%p",
pszDesc, iRegion, (size_t)cb, *ppv);
return VINF_SUCCESS;
}
int PGMR3PhysMMIO2Map(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
RTGCPHYS GCPhys)
{
size_t cb = vmm_memory()->map_to_vm(pDevIns, iRegion, GCPhys);
if (cb == 0) {
PERR("PGMR3PhysMMIO2Map: lookup for pDevIns=%p iRegion=%u failed\n",
pDevIns, iRegion);
for (;;);
}
PLOG("PGMR3PhysMMIO2Map: pDevIns=%p iRegion=%u cb=0x%zx GCPhys=0x%lx\n",
pDevIns, iRegion, cb, (long)GCPhys);
REMR3NotifyPhysRamRegister(pVM, GCPhys, cb, REM_NOTIFY_PHYS_RAM_FLAGS_MMIO2);
return VINF_SUCCESS;
}
int PGMR3PhysMMIO2Unmap(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion,
RTGCPHYS GCPhys)
{
PDBG("called %x %x", GCPhys, iRegion);
vmm_memory()->map_to_vm(pDevIns, iRegion, 0);
return VINF_SUCCESS;
}
bool PGMR3PhysMMIO2IsBase(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
{
bool res = vmm_memory()->lookup(GCPhys, 1);
PDBG("called %x %u", GCPhys, res);
return res;
}
int PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType,
RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
PFNPGMR3PHYSHANDLER pfnHandlerR3,
void *pvUserR3, const char *pszModR0,
const char *pszHandlerR0, RTR0PTR pvUserR0,
const char *pszModRC,
const char *pszHandlerRC,
RTRCPTR pvUserRC, const char *pszDesc)
{
PLOG("PGMR3HandlerPhysicalRegister: pszDesc=%s %u GCPhys=0x%lx GCPhysLast=0x%lx r3=0x%p\n",
pszDesc, enmType, (long)GCPhys, (long)GCPhysLast, (void *)pfnHandlerR3);
REMR3NotifyHandlerPhysicalRegister(pVM, enmType, GCPhys, GCPhysLast - GCPhys + 1, !!pfnHandlerR3);
vmm_memory()->add_handler(GCPhys, GCPhysLast - GCPhys + 1, pfnHandlerR3,
pvUserR3);
return VINF_SUCCESS;
}
int PGMHandlerPhysicalDeregister(PVM pVM, RTGCPHYS GCPhys)
{
PDBG("called %x", GCPhys);
/*
for(;;);
pgmHandlerPhysicalResetRamFlags(pVM, pCur);
REMR3NotifyHandlerPhysicalDeregister(pVM, pCur->enmType, GCPhysStart, GCPhysLast - GCPhysStart + 1, !!pCur->pfnHandlerR3, fRestoreAsRAM);
*/
vmm_memory()->add_handler(GCPhys, GCPhys + 1, 0, 0);
return VINF_SUCCESS;
return VERR_PGM_HANDLER_NOT_FOUND;
}
int PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb,
const char *pszDesc)
{
PLOG("PGMR3PhysRegisterRam: GCPhys=0x%lx, cb=0x%zx, pszDesc=%s",
(long)GCPhys, (size_t)cb, pszDesc);
try {
/*
* XXX Is this function the right place for the allocation?
* The lack of allocation-related VERR_PGM_ error codes suggests
* so.
*/
void *pv = vmm_memory()->alloc_ram((size_t)cb);
guest_memory()->add_ram_mapping(GCPhys, cb, pv);
guest_memory()->dump();
REMR3NotifyPhysRamRegister(pVM, GCPhys, cb, REM_NOTIFY_PHYS_RAM_FLAGS_RAM);
}
catch (Guest_memory::Region_conflict) {
return VERR_PGM_MAPPING_CONFLICT; }
catch (Ram_session::Alloc_failed) {
return VERR_PGM_MAPPING_CONFLICT; /* XXX use a better error code? */ }
catch (Rm_session::Attach_failed) {
return VERR_PGM_MAPPING_CONFLICT; /* XXX use a better error code? */ }
return VINF_SUCCESS;
}
int PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags)
{
PLOG("PGMMapSetPage: GCPtr=0x%lx cb=0x%lx, flags=0x%lx",
(long)GCPtr, (long)cb, (long)fFlags);
return VINF_SUCCESS;
}
RTHCPHYS PGMGetHyperCR3(PVMCPU pVCpu)
{
// PDBG("%s %lx", __func__, CPUMGetHyperCR3(pVCpu));
return 1;
}
int PGMR3Init(PVM pVM)
{
/*
* Satisfy assertion in VMMR3Init. Normally called via:
*
* PGMR3Init -> pgmR3InitPaging -> pgmR3ModeDataInit -> InitData -> MapCR3
*/
for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) {
PVMCPU pVCpu = &pVM->aCpus[idCpu];
CPUMSetHyperCR3(pVCpu, PGMGetHyperCR3(pVCpu));
pVCpu->pgm.s.fA20Enabled = true;
pVCpu->pgm.s.GCPhysA20Mask = ~((RTGCPHYS)!pVCpu->pgm.s.fA20Enabled << 20);
}
return VINF_SUCCESS;
}
int PGMR3PhysTlbGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, void **ppv)
{
void *pv = guest_memory()->lookup(GCPhys, 1);
if (!pv) {
PERR("PGMR3PhysTlbGCPhys2Ptr: lookup for GCPhys=0x%lx failed", (long)GCPhys);
guest_memory()->dump();
return VERR_PGM_PHYS_TLB_UNASSIGNED;
}
*ppv = pv;
// PLOG("PGMR3PhysTlbGCPhys2Ptr: GCPhys=0x%lx -> pv=%p", (long)GCPhys, pv);
return VINF_SUCCESS;
}
void PGMR3PhysSetA20(PVMCPU pVCpu, bool fEnable)
{
if (!pVCpu->pgm.s.fA20Enabled != fEnable) {
pVCpu->pgm.s.fA20Enabled = fEnable;
REMR3A20Set(pVCpu->pVMR3, pVCpu, fEnable);
}
return;
}
bool PGMPhysIsA20Enabled(PVMCPU pVCpu)
{
return pVCpu->pgm.s.fA20Enabled;
}
void PGMR3PhysWriteU8(PVM pVM, RTGCPHYS GCPhys, uint8_t value)
{
void *pv = guest_memory()->lookup(GCPhys, sizeof(value));
if (!pv) {
PDBG("invalid write attempt");
return;
}
*reinterpret_cast<uint8_t *>(pv) = value;
}
void PGMR3PhysWriteU16(PVM pVM, RTGCPHYS GCPhys, uint16_t value)
{
void *pv = guest_memory()->lookup(GCPhys, sizeof(value));
if (!pv) {
PDBG("invalid write attempt");
return;
}
*reinterpret_cast<uint16_t *>(pv) = value;
}
void PGMR3PhysWriteU32(PVM pVM, RTGCPHYS GCPhys, uint32_t value)
{
void *pv = guest_memory()->lookup(GCPhys, sizeof(value));
if (!pv) {
PDBG("invalid write attempt");
return;
}
*reinterpret_cast<uint32_t *>(pv) = value;
}
uint32_t PGMR3PhysReadU32(PVM pVM, RTGCPHYS GCPhys)
{
void *pv = guest_memory()->lookup(GCPhys, 4);
if (!pv) {
PDBG("invalid read attempt");
return 0;
}
return *reinterpret_cast<uint32_t *>(pv);
}
int PGMPhysGCPtr2CCPtrReadOnly(PVMCPU pVCpu, RTGCPTR GCPtr, void const **ppv,
PPGMPAGEMAPLOCK pLock)
{
PDBG("not implemented");
while (1) {}
return VINF_SUCCESS;
}
int PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode) {
// Assert(pVCpu->pgm.s.enmShadowMode == PGMMODE_EPT);
// PDBG("not implemented %x %x", pVCpu->pgm.s.enmShadowMode, PGMMODE_EPT);
pVCpu->pgm.s.enmGuestMode = enmGuestMode;
HWACCMR3PagingModeChanged(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
return VINF_SUCCESS;
}
int PGMChangeMode(PVMCPU pVCpu, uint64_t cr0, uint64_t cr4, uint64_t efer)
{
PGMMODE enmGuestMode;
VMCPU_ASSERT_EMT(pVCpu);
/*
* Calc the new guest mode.
*/
if (!(cr0 & X86_CR0_PE))
enmGuestMode = PGMMODE_REAL;
else if (!(cr0 & X86_CR0_PG))
enmGuestMode = PGMMODE_PROTECTED;
else if (!(cr4 & X86_CR4_PAE))
{
bool const fPse = !!(cr4 & X86_CR4_PSE);
if (pVCpu->pgm.s.fGst32BitPageSizeExtension != fPse)
Log(("PGMChangeMode: CR4.PSE %d -> %d\n", pVCpu->pgm.s.fGst32BitPageSizeExtension, fPse));
pVCpu->pgm.s.fGst32BitPageSizeExtension = fPse;
enmGuestMode = PGMMODE_32_BIT;
}
else if (!(efer & MSR_K6_EFER_LME))
{
if (!(efer & MSR_K6_EFER_NXE))
enmGuestMode = PGMMODE_PAE;
else
enmGuestMode = PGMMODE_PAE_NX;
}
else
{
if (!(efer & MSR_K6_EFER_NXE))
enmGuestMode = PGMMODE_AMD64;
else
enmGuestMode = PGMMODE_AMD64_NX;
}
/*
* Did it change?
*/
if (pVCpu->pgm.s.enmGuestMode == enmGuestMode)
return VINF_SUCCESS;
/* Flush the TLB */
// PGM_INVL_VCPU_TLBS(pVCpu);
VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
// PDBG("not implemented %x %x before", enmGuestMode, pVCpu->pgm.s.enmGuestMode);
int rc = PGMR3ChangeMode(pVCpu->CTX_SUFF(pVM), pVCpu, enmGuestMode);
// PDBG("not implemented %x %x out %p", enmGuestMode, pVCpu->pgm.s.enmGuestMode, __builtin_return_address(0));
// return VINF_PGM_CHANGE_MODE;
return rc;
}
/*
* Copied from src/VBox/VMM/VMMAll/PGMAll.cpp
*/
PGMMODE PGMGetGuestMode(PVMCPU pVCpu) { return pVCpu->pgm.s.enmGuestMode; }
VMMDECL(const char *) PGMGetModeName(PGMMODE enmMode)
{
switch (enmMode)
{
case PGMMODE_REAL: return "Real";
case PGMMODE_PROTECTED: return "Protected";
case PGMMODE_32_BIT: return "32-bit";
case PGMMODE_PAE: return "PAE";
case PGMMODE_PAE_NX: return "PAE+NX";
case PGMMODE_AMD64: return "AMD64";
case PGMMODE_AMD64_NX: return "AMD64+NX";
case PGMMODE_NESTED: return "Nested";
case PGMMODE_EPT: return "EPT";
default: return "unknown mode value";
}
}
int PGMPhysGCPhys2CCPtrReadOnly(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock)
{
void *pv = guest_memory()->lookup(GCPhys, 0x1000);
if (!pv) {
PDBG("unknown address pv=%p ppv=%p GCPhys=%llx", pv, ppv, GCPhys);
guest_memory()->dump();
return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
}
*ppv = pv;
PVMCPU pVCpu = VMMGetCpu(pVM);
return VINF_SUCCESS;
}
int PGMHandlerPhysicalReset(PVM, RTGCPHYS GCPhys)
{
if (!vmm_memory()->unmap_from_vm(GCPhys))
PWRN("%s: unbacked region - GCPhys %lx", __func__, GCPhys);
return VINF_SUCCESS;
}
extern "C" int MMIO2_MAPPED_SYNC(PVM pVM, RTGCPHYS GCPhys, size_t cbWrite)
{
PFNPGMR3PHYSHANDLER pfnHandlerR3 = 0;
void *pvUserR3 = 0;
void * pv = vmm_memory()->lookup(GCPhys, cbWrite, &pfnHandlerR3, &pvUserR3);
if (!pv || !pfnHandlerR3 || !pvUserR3) {
PERR("%s: GCPhys=0x%lx cbWrite=0x%zx", __func__,
GCPhys, cbWrite);
return VERR_GENERAL_FAILURE;
}
int rc = pfnHandlerR3(pVM, GCPhys, 0, 0, cbWrite, PGMACCESSTYPE_WRITE,
pvUserR3);
if (rc == VINF_PGM_HANDLER_DO_DEFAULT) {
// PERR("%s: ok %p %lx+%zx", __func__, pfnHandlerR3, GCPhys, cbWrite);
return VINF_SUCCESS;
}
PERR("unexpected %s return code %d", __FUNCTION__, rc);
return VERR_GENERAL_FAILURE;
}
void PGMR3Reset(PVM pVM)
{
VM_ASSERT_EMT(pVM);
for (VMCPUID i = 0; i < pVM->cCpus; i++)
{
int rc = PGMR3ChangeMode(pVM, &pVM->aCpus[i], PGMMODE_REAL);
AssertRC(rc);
}
for (VMCPUID i = 0; i < pVM->cCpus; i++)
{
PVMCPU pVCpu = &pVM->aCpus[i];
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
if (!pVCpu->pgm.s.fA20Enabled)
{
pVCpu->pgm.s.fA20Enabled = true;
pVCpu->pgm.s.GCPhysA20Mask = ~((RTGCPHYS)!pVCpu->pgm.s.fA20Enabled << 20);
#ifdef PGM_WITH_A20
pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
HWACCMFlushTLB(pVCpu);
#endif
}
}
PERR("clearing ram and rom areas missing !!!!!!!");
}

107
ports/src/virtualbox/rt.cc Normal file
View File

@ -0,0 +1,107 @@
/*
* \brief VirtualBox runtime (RT)
* \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/printf.h>
#include <base/env.h>
/* VirtualBox includes */
#include <iprt/initterm.h>
#include <iprt/mem.h>
#include <iprt/err.h>
#include <iprt/semaphore.h>
#include <iprt/time.h>
#include <internal/iprt.h>
/*
* Called by the recompiler to allocate executable RAM
*/
void *RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
{
PDBG("size=0x%zx, tag=%s", cb, pszTag);
/*
* XXX error handling is missing
*/
using namespace Genode;
Ram_dataspace_capability ds = env()->ram_session()->alloc(cb);
size_t const whole_size = 0;
Genode::off_t const offset = 0;
bool const executable = true;
bool const any_addr = false;
void *local_addr =
env()->rm_session()->attach(ds, whole_size, offset,
any_addr, (void *)0, executable);
return local_addr;
}
void *RTMemPageAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW
{
/*
* The RAM dataspace freshly allocated by 'RTMemExecAllocTag' is zeroed
* already.
*/
return RTMemExecAllocTag(cb, pszTag);
}
void *RTMemPageAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
{
return RTMemPageAllocZTag(cb, pszTag);
}
#include <iprt/buildconfig.h>
uint32_t RTBldCfgVersionMajor(void) { return VBOX_VERSION_MAJOR; }
uint32_t RTBldCfgVersionMinor(void) { return VBOX_VERSION_MINOR; }
uint32_t RTBldCfgVersionBuild(void) { return VBOX_VERSION_BUILD; }
uint32_t RTBldCfgRevision(void) { return ~0; }
/*
* Copied from 'Runtime/r3/posix/timelocal-posix.cpp'
*/
static int64_t rtTimeLocalUTCOffset(PCRTTIMESPEC pTime, bool fCurrentTime)
{
PDBG("rtTimeLocalUTCOffset called - not implemented");
return 0;
}
RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec)
{
RTTIMESPEC LocalTime = *pTimeSpec;
RTTimeSpecAddNano(&LocalTime, rtTimeLocalUTCOffset(&LocalTime, true /* current time, skip fallback */));
pTime = RTTimeExplode(pTime, &LocalTime);
if (pTime)
pTime->fFlags = (pTime->fFlags & ~RTTIME_FLAGS_TYPE_MASK) | RTTIME_FLAGS_TYPE_LOCAL;
return pTime;
}
extern "C" RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cchAbsPath)
{
Genode::strncpy(pszAbsPath, pszPath, cchAbsPath);
return 0;
}

View File

@ -0,0 +1,13 @@
+++ src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp
@@ -1481,6 +1489,11 @@
rc = CFGMR3InsertInteger(pCfg, "IRQ", 4); UPDATE_RC();
rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f8); UPDATE_RC();
+/* rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
+ rc = CFGMR3InsertString(pLunL0, "Driver", "Host Serial"); UPDATE_RC();
+ rc = CFGMR3InsertNode(pLunL0, "Config", &pLunL1); UPDATE_RC();
+ rc = CFGMR3InsertString(pLunL1, "DevicePath", "/dev/terminal"); UPDATE_RC();
+*/
rc = CFGMR3InsertNode(pDev, "1", &pInst); UPDATE_RC();
rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
rc = CFGMR3InsertInteger(pCfg, "IRQ", 3); UPDATE_RC();

210
ports/src/virtualbox/sup.cc Normal file
View File

@ -0,0 +1,210 @@
/*
* \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>
/* Genode/Virtualbox includes */
#include "sup.h"
/* VirtualBox includes */
#include <VBox/sup.h>
#include <VBox/vmm/vm.h>
#include <VBox/vmm/vmm.h>
#include <VBox/err.h>
#include <iprt/param.h>
#include <iprt/err.h>
#include <iprt/timer.h>
using Genode::Semaphore;
#define B(x) "\033[00;44m" x "\033[0m"
struct Attached_gip : Genode::Attached_ram_dataspace
{
Attached_gip()
: Attached_ram_dataspace(Genode::env()->ram_session(), PAGE_SIZE)
{ }
};
enum {
UPDATE_HZ = 250, /* Hz */
UPDATE_MS = 1000 / UPDATE_HZ,
UPDATE_NS = UPDATE_MS * 1000 * 1000,
};
PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPage;
static void _update_tick(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
{
/**
* 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.
*/
static unsigned long long tsc_last = 0;
unsigned now_low, now_high;
asm volatile("rdtsc" : "=a"(now_low), "=d"(now_high) : : "memory");
unsigned long long tsc_current = now_high;
tsc_current <<= 32;
tsc_current |= now_low;
unsigned long long elapsed_tsc = tsc_current - tsc_last;
unsigned long elapsed_ms = elapsed_tsc * 1000 / genode_cpu_hz();
unsigned long long elapsed_nanots = 1000ULL * 1000 * elapsed_ms;
tsc_last = tsc_current;
SUPGIPCPU *cpu = &g_pSUPGlobalInfoPage->aCPUs[0];
cpu->u32TransactionId++;
cpu->u64NanoTS += elapsed_nanots;
cpu->u64TSC += elapsed_tsc;
cpu->u32TransactionId++;
asm volatile ("":::"memory");
}
int SUPR3Init(PSUPDRVSESSION *ppSession)
{
static bool initialized(false);
if (initialized) return VINF_SUCCESS;
static Attached_gip gip;
g_pSUPGlobalInfoPage = gip.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->u64NanoTSLastUpdateHz =
// g_pSUPGlobalInfoPage->OnlineCpuSet =
// g_pSUPGlobalInfoPage->PresentCpuSet =
// g_pSUPGlobalInfoPage->PossibleCpuSet =
g_pSUPGlobalInfoPage->cOnlineCpus = 0;
g_pSUPGlobalInfoPage->cPresentCpus = 0;
g_pSUPGlobalInfoPage->cPossibleCpus = 0;
g_pSUPGlobalInfoPage->idCpuMax = 0;
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->au32TSCHistory[8] =
cpu->u32PrevUpdateIntervalNS = UPDATE_NS;
cpu->enmState = SUPGIPCPUSTATE_ONLINE;
cpu->idCpu = 0;
cpu->iCpuSet = 0;
cpu->idApic = 0;
PRTTIMER pTimer;
RTTimerCreate(&pTimer, UPDATE_MS, _update_tick, 0);
RTTimerStart(pTimer, 0);
initialized = true;
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 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
PERR("%s called %lx", __FUNCTION__, hEvent);
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 {
PERR("%s called %lx millis=%u - not implemented", __FUNCTION__, hEvent, cMillies);
reinterpret_cast<Genode::Semaphore *>(hEvent)->down();
}
return VINF_SUCCESS;
}
int SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation,
void *pvArg)
{
PDBG("SUPR3CallVMMR0 called uOperation=%d", uOperation);
if (uOperation == VMMR0_DO_CALL_HYPERVISOR) {
PDBG("VMMR0_DO_CALL_HYPERVISOR - doing nothing");
return VINF_SUCCESS;
}
PDBG("SUPR3CallVMMR0Ex: unhandled uOperation %d", uOperation);
for (;;);
}

View File

@ -0,0 +1,76 @@
/*
* \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 "util/misc_math.h"
#include "util/string.h"
/* VirtualBox includes */
#include <VBox/vmm/vm.h>
#include <VBox/vmm/gvmm.h>
#include <iprt/param.h>
/* libc memory allocator */
#include <libc_mem_alloc.h>
uint64_t genode_cpu_hz();
void inline 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;
}
/* out parameters of the request */
req.pVMR0 = pVM->pVMR0;
req.pVMR3 = pVM;
}
#endif /* _SUP_H_ */

View File

@ -0,0 +1,34 @@
VBOX_CC_OPT += -DVBOX_WITH_HARDENING
include $(REP_DIR)/lib/mk/virtualbox-common.inc
TARGET = virtualbox
SRC_CC = main.cc cxx_dummies.cc devices.cc drivers.cc dummies.cc libc.cc \
logger.cc mm.cc pdm.cc pgm.cc rt.cc sup.cc iommio.cc ioport.cc \
hwaccm.cc
LIBS += base
LIBS += config_args
LIBS += virtualbox-bios virtualbox-recompiler virtualbox-runtime \
virtualbox-vmm virtualbox-devices virtualbox-drivers \
virtualbox-storage virtualbox-zlib virtualbox-liblzf \
virtualbox-hwaccl virtualbox-dis
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(VBOX_DIR)/Runtime/include
INC_DIR += $(VBOX_DIR)/Frontends/VBoxBFE
SRC_CC += Frontends/VBoxBFE/VBoxBFE.cpp
SRC_CC += Frontends/VBoxBFE/DisplayImpl.cpp
SRC_CC += Frontends/VBoxBFE/VMMDevInterface.cpp
SRC_CC += Frontends/VBoxBFE/KeyboardImpl.cpp
SRC_CC += Frontends/VBoxBFE/MachineDebuggerImpl.cpp
SRC_CC += Frontends/VBoxBFE/StatusImpl.cpp
INC_DIR += $(VBOX_DIR)/Main/include
INC_DIR += $(VBOX_DIR)/VMM/include
# search path to 'scan_code_set_2.h'
INC_DIR += $(call select_from_repositories,src/drivers/input/ps2)

View File

@ -0,0 +1,10 @@
+++ src/VBox/VMM/VMMR3/TM.cpp 2014-01-15 16:40:35
@@ -1901,7 +1901,7 @@
#ifdef VBOX_WITH_REM
REMR3NotifyTimerPending(pVM, pVCpuDst);
#endif
- VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM /** @todo | VMNOTIFYFF_FLAGS_POKE ?*/);
+ VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM | VMNOTIFYFF_FLAGS_POKE);
STAM_COUNTER_INC(&pVM->tm.s.StatTimerCallbackSetFF);
}
}

View File

@ -0,0 +1,39 @@
/*
* \brief VirtualBox utilities
* \author Christian Helmuth
* \date 2013-08-28
*/
/*
* Copyright (C) 2013 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)
{
return (RTRCPTR)((long)ptr & 0xffffffff);
}
/**
* 64bit-aware cast of RTRCPTR (uint32_t) to pointer
*/
template <typename T>
T* from_rtrcptr(RTRCPTR rcptr)
{
return (T*)(rcptr | 0L);
}
#endif /* _UTIL_H_ */

View File

@ -0,0 +1,20 @@
--- src/VBox/Devices/Graphics/BIOS/vbetables-gen.c.orig 2013-11-19 16:09:24.844195101 +0100
+++ src/VBox/Devices/Graphics/BIOS/vbetables-gen.c 2013-11-19 16:09:38.288364715 +0100
@@ -13,6 +13,7 @@
ModeInfo modes[] = {
/* standard VESA modes */
+#if 0
{ 640, 400, 8 , 0x100},
{ 640, 480, 8 , 0x101},
{ 800, 600, 4 , 0x102},
@@ -57,6 +58,9 @@
{ 1152, 864, 16 , 0x14a},
{ 1152, 864, 24 , 0x14b},
{ 1152, 864, 32 , 0x14c},
+#else
+{ 800, 600, 16 , 0x111},
+#endif
{ 0, },
};

View File

@ -0,0 +1,47 @@
+++ src/VBox/Frontends/VBoxBFE/VirtualBoxBase.h
@@ -24,10 +24,9 @@
# include <iprt/uuid.h>
#else
# include <VBox/com/defs.h>
+# include <VBox/com/assert.h> // For the AssertComRC macro
#endif
-#include <VBox/com/assert.h> // For the AssertComRC macro
-
#include <iprt/alloc.h>
#include <iprt/assert.h>
#include <iprt/critsect.h>
+++ src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp
@@ -1765,19 +1779,19 @@
/*
* VMM Device
*/
- rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); UPDATE_RC();
- rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
- rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
- rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
- rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); UPDATE_RC();
- rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
- rc = CFGMR3InsertInteger(pCfg, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
-
- /* the VMM device's Main driver */
- rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
- rc = CFGMR3InsertString(pLunL0, "Driver", "HGCM"); UPDATE_RC();
- rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
- rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gVMMDev); UPDATE_RC();
+// rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); UPDATE_RC();
+// rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
+// rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
+// rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
+// rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); UPDATE_RC();
+// rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
+// rc = CFGMR3InsertInteger(pCfg, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
+//
+// /* the VMM device's Main driver */
+// rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
+// rc = CFGMR3InsertString(pLunL0, "Driver", "HGCM"); UPDATE_RC();
+// rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
+// rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gVMMDev); UPDATE_RC();
/*
* AC'97 ICH audio

View File

@ -0,0 +1,12 @@
+++ src/VBox/Devices/Graphics/DevVGA.cpp
@@ -1845,6 +1846,10 @@
dup9 = 0;
if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
dup9 = 1;
+
+ if (bgcol == fgcol && fgcol == 0) {
+ fgcol = ~0U;
+ }
vga_draw_glyph9(d1, linesize,
font_ptr, cheight, fgcol, bgcol, dup9);
}

View File

@ -0,0 +1,18 @@
+++ src/VBox/Devices/Graphics/DevVGA.cpp
@@ -3468,9 +3475,15 @@
int rc;
Assert(pThis);
Assert(GCPhys >= pThis->GCPhysVRAM);
+ Assert(GCPhys - pThis->GCPhysVRAM + cbBuf <= pThis->vram_size);
NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType);
- rc = vgaLFBAccess(pVM, pThis, GCPhys, 0);
+ rc = VINF_SUCCESS;
+ size_t offset = 0;
+ while (RT_SUCCESS(rc) && offset < cbBuf) {
+ rc = vgaLFBAccess(pVM, pThis, GCPhys + offset, 0);
+ offset += 1UL << PAGE_SHIFT;
+ }
if (RT_SUCCESS(rc))
return VINF_PGM_HANDLER_DO_DEFAULT;
AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));

View File

@ -0,0 +1,17 @@
+++ src/VBox/Storage/VMDK.cpp 2013-11-25 14:15:48.171143505 +0100
@@ -6114,7 +6114,6 @@
}
pExtent->uGrainSectorAbs = uSectorExtentAbs;
pExtent->uGrain = uSectorExtentRel / pExtent->cSectorsPerGrain;
- Assert(uLBA == uSectorExtentRel);
}
memcpy(pvBuf, (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), cbToRead);
}
@@ -6258,7 +6257,6 @@
* which is somewhere between expensive and impossible. */
rc = VERR_VD_VMDK_INVALID_STATE;
pExtent->uGrainSectorAbs = 0;
- AssertRC(rc);
}
else
{

View File

@ -0,0 +1,202 @@
/*
* \brief Registry of VMM-local memory regions
* \author Norman Feske
* \date 2013-09-02
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VMM_MEMORY_H_
#define _VMM_MEMORY_H_
/*
* Work-around for a naming conflict between the enum definition of PAGE_SIZE
* in 'os/attached_ram_dataspace.h' and the VirtualBox #define with the same
* name.
*/
#define BACKUP_PAGESIZE PAGE_SIZE
#undef PAGE_SIZE
/* Genode includes */
#include <base/env.h>
#include <base/lock.h>
#include <util/list.h>
#include <os/attached_ram_dataspace.h>
#define PAGE_SIZE BACKUP_PAGESIZE
/* VirtualBox includes */
#include <VBox/vmm/pgm.h>
class Vmm_memory
{
struct Region;
typedef Genode::Ram_session Ram_session;
typedef Genode::Rm_session Rm_session;
typedef Genode::size_t size_t;
typedef Genode::Lock Lock;
typedef Genode::Attached_ram_dataspace Attached_ram_dataspace;
typedef Genode::List<Region> Region_list;
private:
struct Region : Region_list::Element, Attached_ram_dataspace
{
PPDMDEVINS pDevIns;
unsigned const iRegion;
RTGCPHYS vm_phys;
PFNPGMR3PHYSHANDLER pfnHandlerR3;
void *pvUserR3;
Region(Ram_session &ram, size_t size, PPDMDEVINS pDevIns,
unsigned iRegion)
:
Attached_ram_dataspace(&ram, size),
pDevIns(pDevIns),
iRegion(iRegion),
vm_phys(0), pfnHandlerR3(0), pvUserR3(0)
{ }
};
Lock _lock;
Region_list _regions;
/**
* Backing store
*/
Genode::Ram_session &_ram;
Region *_lookup_unsynchronized(PPDMDEVINS pDevIns, unsigned iRegion)
{
for (Region *r = _regions.first(); r; r = r->next())
if (r->pDevIns == pDevIns && r->iRegion == iRegion)
return r;
return 0;
}
Region *_lookup_unsynchronized(RTGCPHYS vm_phys, size_t size)
{
for (Region *r = _regions.first(); r; r = r->next())
if (r->vm_phys && r->vm_phys <= vm_phys
&& vm_phys - r->vm_phys < r->size()
&& r->size() - (vm_phys - r->vm_phys) >= size)
return r;
return 0;
}
public:
Vmm_memory(Ram_session &ram) : _ram(ram) { }
/**
* \throw Ram_session::Alloc_failed
* \throw Rm_session::Attach_failed
*/
void *alloc(size_t cb, PPDMDEVINS pDevIns, unsigned iRegion)
{
Lock::Guard guard(_lock);
try {
Region *r = new (Genode::env()->heap())
Region(_ram, cb, pDevIns, iRegion);
_regions.insert(r);
return r->local_addr<void>();
} catch (Ram_session::Alloc_failed) {
PERR("Vmm_memory::alloc(0x%zx): RAM allocation failed", cb);
throw;
} catch (Rm_session::Attach_failed) {
PERR("Vmm_memory::alloc(0x%zx): RM attach failed", cb);
throw;
}
return 0;
}
void *alloc_ram(size_t cb)
{
return alloc(cb, 0, 0);
}
size_t map_to_vm(PPDMDEVINS pDevIns, unsigned iRegion, RTGCPHYS GCPhys)
{
Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(pDevIns, iRegion);
if (r) r->vm_phys = GCPhys;
return r ? r->size() : 0;
}
void add_handler(RTGCPHYS vm_phys, size_t size,
PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3)
{
Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(vm_phys, size);
if (!r) return;
r->pfnHandlerR3 = pfnHandlerR3;
r->pvUserR3 = pvUserR3;
}
void * lookup(RTGCPHYS vm_phys, size_t size,
PFNPGMR3PHYSHANDLER *ppfnHandlerR3 = 0, void **ppvUserR3 = 0)
{
Lock::Guard guard(_lock);
Region *r = _lookup_unsynchronized(vm_phys, size);
if (!r) return 0;
if (ppfnHandlerR3) *ppfnHandlerR3 = r->pfnHandlerR3;
if (ppvUserR3) *ppvUserR3 = r->pvUserR3;
return reinterpret_cast<void *>(r->local_addr<uint8_t>() +
(vm_phys - r->vm_phys));
}
bool unmap_from_vm(RTGCPHYS GCPhys);
/*
{
size_t const size = 1;
Region *r = _lookup_unsynchronized(GCPhys, size);
if (!r) return false;
using Genode::addr_t;
addr_t const vmm_local = (addr_t)r->local_addr<addr_t>();
Assert(vmm_local);
Assert(!((r->size() - 1) & vmm_local));
using namespace Nova;
unsigned const order = Genode::log2(r->size() >> PAGE_SIZE_LOG2);
Rights rwx(true, true, true);
revoke(Mem_crd(vmm_local >> PAGE_SIZE_LOG2, order, rwx), false);
return true;
}
*/
};
/**
* Return pointer to singleton instance
*/
Vmm_memory *vmm_memory();
#endif /* _VMM_MEMORY_H_ */

View File

@ -0,0 +1,28 @@
+++ src/VBox/Devices/VMMDev/VMMDev.cpp 2013-10-17 13:02:16.787071776 +0200
@@ -1854,7 +1854,6 @@
}
break;
}
-#endif /* VBOX_WITH_HGCM */
case VMMDevReq_HGCMCancel:
{
@@ -1899,6 +1898,7 @@
}
break;
}
+#endif /* VBOX_WITH_HGCM */
case VMMDevReq_VideoAccelEnable:
{
@@ -3341,8 +3341,10 @@
/* disabled statistics updating */
pThis->u32LastStatIntervalSize = 0;
+#ifdef VBOX_WITH_HGCM
/* Clear the "HGCM event enabled" flag so the event can be automatically reenabled. */
pThis->u32HGCMEnabled = 0;
+#endif
/*
* Clear the event variables.

View File

@ -0,0 +1,63 @@
+++ include/VBox/vmm/hwacc_vmx.h
@@ -1338,10 +1338,10 @@
".byte 0xF3, 0x0F, 0xC7, 0x34, 0x24 # VMXON [esp] \n\t"
"ja 2f \n\t"
"je 1f \n\t"
- "movl $"STR(VERR_VMX_INVALID_VMXON_PTR)", %0 \n\t"
+ "movl $" STR(VERR_VMX_INVALID_VMXON_PTR)", %0 \n\t"
"jmp 2f \n\t"
"1: \n\t"
- "movl $"STR(VERR_VMX_GENERIC)", %0 \n\t"
+ "movl $" STR(VERR_VMX_GENERIC)", %0 \n\t"
"2: \n\t"
"add $8, %%esp \n\t"
:"=rm"(rc)
@@ -1418,7 +1418,7 @@
"push %2 \n\t"
".byte 0x66, 0x0F, 0xC7, 0x34, 0x24 # VMCLEAR [esp] \n\t"
"jnc 1f \n\t"
- "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "movl $" STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
"1: \n\t"
"add $8, %%esp \n\t"
:"=rm"(rc)
@@ -1466,7 +1466,7 @@
"push %2 \n\t"
".byte 0x0F, 0xC7, 0x34, 0x24 # VMPTRLD [esp] \n\t"
"jnc 1f \n\t"
- "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "movl $" STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
"1: \n\t"
"add $8, %%esp \n\t"
:"=rm"(rc)
@@ -1520,10 +1520,10 @@
".byte 0x0F, 0x79, 0xC2 # VMWRITE eax, edx \n\t"
"ja 2f \n\t"
"je 1f \n\t"
- "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "movl $" STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
"jmp 2f \n\t"
"1: \n\t"
- "movl $"STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "movl $" STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
"2: \n\t"
:"=rm"(rc)
:"0"(VINF_SUCCESS),
@@ -1607,14 +1607,14 @@
int rc = VINF_SUCCESS;
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ (
- "movl $"STR(VINF_SUCCESS)", %0 \n\t"
+ "movl $" STR(VINF_SUCCESS)", %0 \n\t"
".byte 0x0F, 0x78, 0xc2 # VMREAD eax, edx \n\t"
"ja 2f \n\t"
"je 1f \n\t"
- "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "movl $" STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
"jmp 2f \n\t"
"1: \n\t"
- "movl $"STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "movl $" STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
"2: \n\t"
:"=&r"(rc),
"=d"(*pData)