mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-18 17:00:26 +00:00
parent
2e6f281cf0
commit
d8c2a908b8
@ -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
|
||||
|
||||
|
1
ports/lib/import/import-virtualbox_libc_support.mk
Normal file
1
ports/lib/import/import-virtualbox_libc_support.mk
Normal file
@ -0,0 +1 @@
|
||||
include $(call select_from_repositories,lib/import/import-libc.mk)
|
8
ports/lib/mk/foc/virtualbox-hwaccl.mk
Normal file
8
ports/lib/mk/foc/virtualbox-hwaccl.mk
Normal 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/
|
8
ports/lib/mk/linux/virtualbox-hwaccl.mk
Normal file
8
ports/lib/mk/linux/virtualbox-hwaccl.mk
Normal 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/
|
10
ports/lib/mk/nova/virtualbox-hwaccl.mk
Normal file
10
ports/lib/mk/nova/virtualbox-hwaccl.mk
Normal 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/
|
8
ports/lib/mk/okl4/virtualbox-hwaccl.mk
Normal file
8
ports/lib/mk/okl4/virtualbox-hwaccl.mk
Normal 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/
|
8
ports/lib/mk/pistachio/virtualbox-hwaccl.mk
Normal file
8
ports/lib/mk/pistachio/virtualbox-hwaccl.mk
Normal 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/
|
37
ports/lib/mk/virtualbox-bios.mk
Normal file
37
ports/lib/mk/virtualbox-bios.mk
Normal 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)
|
66
ports/lib/mk/virtualbox-common.inc
Normal file
66
ports/lib/mk/virtualbox-common.inc
Normal 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 :
|
77
ports/lib/mk/virtualbox-devices.mk
Normal file
77
ports/lib/mk/virtualbox-devices.mk
Normal 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
|
15
ports/lib/mk/virtualbox-dis.mk
Normal file
15
ports/lib/mk/virtualbox-dis.mk
Normal 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
|
16
ports/lib/mk/virtualbox-drivers.mk
Normal file
16
ports/lib/mk/virtualbox-drivers.mk
Normal 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
|
8
ports/lib/mk/virtualbox-liblzf.mk
Normal file
8
ports/lib/mk/virtualbox-liblzf.mk
Normal 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)
|
29
ports/lib/mk/virtualbox-recompiler.mk
Normal file
29
ports/lib/mk/virtualbox-recompiler.mk
Normal 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
|
119
ports/lib/mk/virtualbox-runtime.mk
Normal file
119
ports/lib/mk/virtualbox-runtime.mk
Normal 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 $^ > $@
|
||||
|
16
ports/lib/mk/virtualbox-storage.mk
Normal file
16
ports/lib/mk/virtualbox-storage.mk
Normal 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
|
76
ports/lib/mk/virtualbox-vmm.mk
Normal file
76
ports/lib/mk/virtualbox-vmm.mk
Normal 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
|
7
ports/lib/mk/virtualbox-zlib.mk
Normal file
7
ports/lib/mk/virtualbox-zlib.mk
Normal 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)
|
84
ports/lib/mk/virtualbox_libc_support.inc
Normal file
84
ports/lib/mk/virtualbox_libc_support.inc
Normal 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 :
|
7
ports/lib/mk/x86_32/virtualbox_libc_support.mk
Normal file
7
ports/lib/mk/x86_32/virtualbox_libc_support.mk
Normal 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
|
7
ports/lib/mk/x86_64/virtualbox_libc_support.mk
Normal file
7
ports/lib/mk/x86_64/virtualbox_libc_support.mk
Normal 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
|
5
ports/ports/virtualbox.inc
Normal file
5
ports/ports/virtualbox.inc
Normal 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
81
ports/ports/virtualbox.mk
Normal 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
123
ports/run/virtualbox.run
Normal 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
|
97
ports/src/virtualbox/accloff/sup.cc
Normal file
97
ports/src/virtualbox/accloff/sup.cc
Normal 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;
|
||||
}
|
37
ports/src/virtualbox/acpi.patch
Normal file
37
ports/src/virtualbox/acpi.patch
Normal 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;
|
9
ports/src/virtualbox/acpi_drv.patch
Normal file
9
ports/src/virtualbox/acpi_drv.patch
Normal 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>
|
21
ports/src/virtualbox/acpi_more.patch
Normal file
21
ports/src/virtualbox/acpi_more.patch
Normal 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
|
||||
|
32
ports/src/virtualbox/bios_logo.patch
Normal file
32
ports/src/virtualbox/bios_logo.patch
Normal 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;
|
||||
|
45
ports/src/virtualbox/cxx_dummies.cc
Normal file
45
ports/src/virtualbox/cxx_dummies.cc
Normal 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))
|
23
ports/src/virtualbox/devata.patch
Normal file
23
ports/src/virtualbox/devata.patch
Normal 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 */
|
119
ports/src/virtualbox/devices.cc
Normal file
119
ports/src/virtualbox/devices.cc
Normal 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;
|
||||
}
|
||||
|
10
ports/src/virtualbox/devpci.patch
Normal file
10
ports/src/virtualbox/devpci.patch
Normal 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)");
|
47
ports/src/virtualbox/drivers.cc
Normal file
47
ports/src/virtualbox/drivers.cc
Normal 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;
|
||||
}
|
||||
|
317
ports/src/virtualbox/dummies.cc
Normal file
317
ports/src/virtualbox/dummies.cc
Normal 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" */
|
||||
|
20
ports/src/virtualbox/fake_pci_vendor.patch
Normal file
20
ports/src/virtualbox/fake_pci_vendor.patch
Normal 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) */
|
357
ports/src/virtualbox/guest_memory.h
Normal file
357
ports/src/virtualbox/guest_memory.h
Normal 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 ®ions, 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 ®ions)
|
||||
{
|
||||
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_ */
|
53
ports/src/virtualbox/hda.patch
Normal file
53
ports/src/virtualbox/hda.patch
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
16
ports/src/virtualbox/hwacc.patch
Normal file
16
ports/src/virtualbox/hwacc.patch
Normal 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.
|
||||
*/
|
129
ports/src/virtualbox/hwaccm.cc
Normal file
129
ports/src/virtualbox/hwaccm.cc
Normal 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;
|
||||
}
|
246
ports/src/virtualbox/include/SDLConsole.h
Normal file
246
ports/src/virtualbox/include/SDLConsole.h
Normal 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; }
|
||||
};
|
110
ports/src/virtualbox/include/SDLFramebuffer.h
Normal file
110
ports/src/virtualbox/include/SDLFramebuffer.h
Normal 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__); }
|
||||
};
|
15
ports/src/virtualbox/include/dtrace/VBoxVMM.h
Normal file
15
ports/src/virtualbox/include/dtrace/VBoxVMM.h
Normal 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_ */
|
4
ports/src/virtualbox/include/list
Normal file
4
ports/src/virtualbox/include/list
Normal file
@ -0,0 +1,4 @@
|
||||
/*
|
||||
* \brief Dummy stubs needed by 'src/VBox/Frontends/VBoxBFE/VirtualBoxBase.h'
|
||||
* \author Alexander Boettcher
|
||||
*/
|
4
ports/src/virtualbox/include/map
Normal file
4
ports/src/virtualbox/include/map
Normal file
@ -0,0 +1,4 @@
|
||||
/*
|
||||
* \brief Dummy stubs needed by 'src/VBox/Frontends/VBoxBFE/VirtualBoxBase.h'
|
||||
* \author Alexander Boettcher
|
||||
*/
|
10
ports/src/virtualbox/include/product-generated.h
Normal file
10
ports/src/virtualbox/include/product-generated.h
Normal 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
|
11
ports/src/virtualbox/include/version-generated.h
Normal file
11
ports/src/virtualbox/include/version-generated.h
Normal 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
|
76
ports/src/virtualbox/iommio.cc
Normal file
76
ports/src/virtualbox/iommio.cc
Normal 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;
|
||||
}
|
273
ports/src/virtualbox/ioport.cc
Normal file
273
ports/src/virtualbox/ioport.cc
Normal 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);
|
||||
}
|
127
ports/src/virtualbox/libc.cc
Normal file
127
ports/src/virtualbox/libc.cc
Normal 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;
|
||||
}
|
149
ports/src/virtualbox/logger.cc
Normal file
149
ports/src/virtualbox/logger.cc
Normal 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;
|
||||
}
|
214
ports/src/virtualbox/main.cc
Normal file
214
ports/src/virtualbox/main.cc
Normal 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
313
ports/src/virtualbox/mm.cc
Normal 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;
|
||||
}
|
||||
|
||||
}
|
234
ports/src/virtualbox/nova/sup.cc
Normal file
234
ports/src/virtualbox/nova/sup.cc
Normal 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;
|
||||
}
|
112
ports/src/virtualbox/nova/svm.h
Normal file
112
ports/src/virtualbox/nova/svm.h
Normal 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_ */
|
756
ports/src/virtualbox/nova/vcpu.h
Normal file
756
ports/src/virtualbox/nova/vcpu.h
Normal 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__ */
|
134
ports/src/virtualbox/nova/vcpu_svm.h
Normal file
134
ports/src/virtualbox/nova/vcpu_svm.h
Normal 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);
|
||||
}
|
||||
};
|
187
ports/src/virtualbox/nova/vcpu_vmx.h
Normal file
187
ports/src/virtualbox/nova/vcpu_vmx.h
Normal 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);
|
||||
}
|
||||
};
|
172
ports/src/virtualbox/nova/vmx.h
Normal file
172
ports/src/virtualbox/nova/vmx.h
Normal 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
127
ports/src/virtualbox/pdm.cc
Normal 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;
|
||||
}
|
||||
|
||||
|
10
ports/src/virtualbox/pdm_queue_irqs.patch
Normal file
10
ports/src/virtualbox/pdm_queue_irqs.patch
Normal 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
583
ports/src/virtualbox/pgm.cc
Normal 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
107
ports/src/virtualbox/rt.cc
Normal 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;
|
||||
}
|
||||
|
13
ports/src/virtualbox/serial.patch
Normal file
13
ports/src/virtualbox/serial.patch
Normal 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
210
ports/src/virtualbox/sup.cc
Normal 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 (;;);
|
||||
}
|
76
ports/src/virtualbox/sup.h
Normal file
76
ports/src/virtualbox/sup.h
Normal 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_ */
|
34
ports/src/virtualbox/target.mk
Normal file
34
ports/src/virtualbox/target.mk
Normal 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)
|
10
ports/src/virtualbox/timer.patch
Normal file
10
ports/src/virtualbox/timer.patch
Normal 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);
|
||||
}
|
||||
}
|
39
ports/src/virtualbox/util.h
Normal file
39
ports/src/virtualbox/util.h
Normal 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_ */
|
20
ports/src/virtualbox/vbetables-gen.patch
Normal file
20
ports/src/virtualbox/vbetables-gen.patch
Normal 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, },
|
||||
};
|
||||
|
47
ports/src/virtualbox/vboxbfe.patch
Normal file
47
ports/src/virtualbox/vboxbfe.patch
Normal 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
|
12
ports/src/virtualbox/vga.patch
Normal file
12
ports/src/virtualbox/vga.patch
Normal 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);
|
||||
}
|
18
ports/src/virtualbox/vga_fb.patch
Normal file
18
ports/src/virtualbox/vga_fb.patch
Normal 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));
|
17
ports/src/virtualbox/vmdk.patch
Normal file
17
ports/src/virtualbox/vmdk.patch
Normal 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
|
||||
{
|
202
ports/src/virtualbox/vmm_memory.h
Normal file
202
ports/src/virtualbox/vmm_memory.h
Normal 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_ */
|
28
ports/src/virtualbox/vmmdev.patch
Normal file
28
ports/src/virtualbox/vmmdev.patch
Normal 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.
|
63
ports/src/virtualbox/vmx_c++.patch
Normal file
63
ports/src/virtualbox/vmx_c++.patch
Normal 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)
|
Loading…
x
Reference in New Issue
Block a user