vbox5: remove VM generic version

Issue #4968
This commit is contained in:
Alexander Boettcher 2023-09-14 15:44:39 +02:00 committed by Christian Helmuth
parent 17a140db3d
commit 484bde4b4b
34 changed files with 7 additions and 3505 deletions

View File

@ -1,20 +0,0 @@
include $(REP_DIR)/lib/mk/virtualbox5-common.inc
LIBS += stdcxx
SRC_CC = sup.cc sup_vmm.cc
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(VIRTUALBOX_DIR)/VBoxAPIWrap
INC_DIR += $(VBOX_DIR)/Main/xml
INC_DIR += $(VBOX_DIR)/Main/include
INC_DIR += $(VBOX_DIR)/VMM/include
INC_DIR += $(REP_DIR)/src/virtualbox5
INC_DIR += $(REP_DIR)/src/virtualbox5/frontend
vpath sup_vmm.cc $(REP_DIR)/src/virtualbox5/generic
vpath sup.cc $(REP_DIR)/src/virtualbox5/generic
CC_CXX_WARN_STRICT =

View File

@ -1,2 +0,0 @@
VirtualBox runtime for hosting a large VM in the Sculpt scenario

View File

@ -1,10 +0,0 @@
_/src/vbox5
_/src/libc
_/src/init
_/src/posix
_/src/zlib
_/src/libiconv
_/src/libyuv
_/src/stdcxx
_/src/vfs
_/src/jpeg

View File

@ -1 +0,0 @@
2023-08-21 464b0638d93864d8748bfa61e6472f21d6f26788

View File

@ -1,90 +0,0 @@
<runtime ram="4300M" caps="2500" binary="init">
<requires>
<file_system label="vm"/>
<file_system label="shared"/>
<vm/>
<timer/>
<gui/>
<nic/>
<rom label="capslock"/>
<rom label="platform_info"/>
<report label="shape"/>
<report label="clipboard"/>
<rom label="clipboard"/>
<rm/>
<rtc/>
<rom label="usb_devices"/>
<usb/>
</requires>
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="VM"/>
<service name="Gui"/>
<service name="Timer"/>
<service name="Rtc"/>
<service name="Report"/>
<service name="File_system"/>
<service name="Usb"/>
<service name="Nic"/>
</parent-provides>
<default-route> <any-service> <parent/> <any-child/> </any-service> </default-route>
<default caps="100"/>
<start name="vbox" caps="2000">
<binary name="virtualbox5" />
<resource name="RAM" quantum="8G"/>
<exit propagate="yes"/>
<config vbox_file="machine.vbox" xhci="yes" vm_name="linux" capslock="ROM">
<vfs>
<dir name="dev">
<log/>
<rtc/>
</dir>
<dir name="shared"> <fs label="shared" writeable="yes"/> </dir>
<fs writeable="yes"/>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc"/>
</config>
<route>
<service name="Audio_out"> <parent/> </service>
<service name="File_system" label="shared"> <parent label="shared"/> </service>
<service name="File_system"> <parent label="vm"/> </service>
<service name="ROM" label="usb_devices"> <parent label="usb_devices"/> </service>
<service name="ROM" label="capslock"> <parent label="capslock"/> </service>
<service name="ROM" label="platform_info">
<parent label="platform_info"/> </service>
<service name="Nic"> <parent/> </service>
<service name="Report" label="shape"> <parent label="shape"/> </service>
<service name="ROM" label="clipboard"> <parent label="clipboard"/> </service>
<service name="Report" label="clipboard"> <parent label="clipboard"/> </service>
<service name="Gui"> <parent label=""/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
</config>
<content>
<rom label="ld.lib.so"/>
<rom label="init"/>
<rom label="virtualbox5"/>
<rom label="libc.lib.so"/>
<rom label="libm.lib.so"/>
<rom label="libiconv.lib.so"/>
<rom label="libyuv.lib.so"/>
<rom label="qemu-usb.lib.so"/>
<rom label="stdcxx.lib.so"/>
<rom label="vfs.lib.so"/>
<rom label="jpeg.lib.so"/>
</content>
</runtime>

View File

@ -12,11 +12,8 @@ content: $(MIRROR_FROM_REP_DIR)
$(MIRROR_FROM_REP_DIR): $(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir) $(mirror_from_rep_dir)
# omit virtualbox5-rem binary (12 MiB) from binary archive # disable debug assertions
content: disable_virtualbox_rem disable_assertions content: disable_assertions
disable_virtualbox_rem: $(MIRROR_FROM_REP_DIR)
rm src/virtualbox5/target.mk
disable_assertions: $(MIRROR_FROM_REP_DIR) disable_assertions: $(MIRROR_FROM_REP_DIR)
rm lib/mk/virtualbox5-debug.inc rm lib/mk/virtualbox5-debug.inc

View File

@ -1,84 +0,0 @@
LIB_MK_FILES := $(notdir $(wildcard $(REP_DIR)/lib/mk/virtualbox5*))
MIRROR_FROM_REP_DIR := src/virtualbox5 \
src/virtualbox5/network.cpp \
src/virtualbox5/include \
include/vmm \
$(addprefix lib/mk/,$(LIB_MK_FILES))
content: $(MIRROR_FROM_REP_DIR)
$(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir)
# omit virtualbox5-rem binary (12 MiB) from binary archive
content: disable_virtualbox_nova disable_assertions
disable_virtualbox_nova: $(MIRROR_FROM_REP_DIR)
rm src/virtualbox5/nova/target.mk
rmdir src/virtualbox5/nova
rm -r src/virtualbox5/spec
disable_assertions: $(MIRROR_FROM_REP_DIR)
rm lib/mk/virtualbox5-debug.inc
touch lib/mk/virtualbox5-debug.inc
PORT_DIR := $(call port_dir,$(REP_DIR)/ports/virtualbox5)
MIRROR_FROM_PORT_DIR := src/app/virtualbox src/app/virtualbox_sdk \
VBoxAPIWrap VirtualBox_stripped.xidl
content: $(MIRROR_FROM_PORT_DIR)
$(MIRROR_FROM_PORT_DIR):
mkdir -p $(dir $@)
cp -r $(PORT_DIR)/$@ $(dir $@)
MIRROR_FROM_LIBPORTS := lib/mk/libc-mem.mk \
lib/mk/libc-common.inc \
src/lib/libc/internal/init.h \
src/lib/libc/internal/mem_alloc.h \
src/lib/libc/internal/monitor.h \
src/lib/libc/internal/pthread.h \
src/lib/libc/internal/thread_create.h \
src/lib/libc/internal/timer.h \
src/lib/libc/internal/types.h \
src/lib/libc/libc_mem_alloc.cc \
lib/import/import-qemu-usb_include.mk \
lib/mk/qemu-usb_include.mk \
lib/mk/qemu-usb.inc \
lib/mk/spec/x86_32/qemu-usb.mk \
lib/mk/spec/x86_64/qemu-usb.mk \
include/qemu \
src/lib/qemu-usb \
content: $(MIRROR_FROM_LIBPORTS)
$(MIRROR_FROM_LIBPORTS):
mkdir -p $(dir $@)
cp -r $(GENODE_DIR)/repos/libports/$@ $(dir $@)
QEMU_USB_PORT_DIR := $(call port_dir,$(GENODE_DIR)/repos/libports/ports/qemu-usb)
MIRROR_FROM_QEMU_USB_PORT_DIR := src/lib/qemu
content: $(MIRROR_FROM_QEMU_USB_PORT_DIR)
$(MIRROR_FROM_QEMU_USB_PORT_DIR):
mkdir -p $(dir $@)
cp -r $(QEMU_USB_PORT_DIR)/$@ $(dir $@)
MIRROR_FROM_OS := src/drivers/ps2/scan_code_set_1.h \
include/pointer/shape_report.h \
content: $(MIRROR_FROM_OS)
$(MIRROR_FROM_OS):
mkdir -p $(dir $@)
cp -r $(GENODE_DIR)/repos/os/$@ $(dir $@)
content: LICENSE
LICENSE:
echo "GNU GPL version 2, see src/app/virtualbox/COPYING" > $@

View File

@ -1 +0,0 @@
2023-08-21 8bc399184344e122bbf80d7130e42fe63f91343c

View File

@ -1,23 +0,0 @@
audio_in_session
audio_out_session
base
capture_session
framebuffer_session
input_session
libc
libiconv
nic_session
gui_session
os
report_session
rtc_session
stdcxx
terminal_session
timer_session
usb_session
vfs
vm_session
nitpicker_gfx
blit
libyuv
format

View File

@ -25,7 +25,4 @@ set use_ps2 1
set use_vms 1 set use_vms 1
set use_cpu_load 1 set use_cpu_load 1
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -25,7 +25,4 @@ set use_ps2 1
set use_vms 1 set use_vms 1
set use_cpu_load 1 set use_cpu_load 1
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -1,35 +0,0 @@
#
# Ubuntu 16.04 32bit in VBox 5
#
assert_spec x86
if {(![have_spec nova] && ![have_spec foc])} {
puts "Platform is unsupported."
}
set flavor "ubuntu_16_04_32"
set vm_ram "1280M"
set use_vbox5 1
set use_rumpfs 1
# Write overlay only into ram
set use_ram_fs 1
# However read initial overlay from disk
set use_overlay_from_disk 1
set use_serial 1
set use_check_result 1
set use_usb [expr ![get_cmd_switch --autopilot]]
set use_ps2 1
set use_vms 1
set use_cpu_load 1
# use generic vbox5 VMM version
set use_vbox5_nova 0
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -1,31 +0,0 @@
#
# Ubuntu 16.04 64bit in VBox 5
#
assert_spec x86_64
assert_spec nova
set flavor "ubuntu_16_04_64"
set vm_ram "9460M"
set use_vbox5 1
set use_rumpfs 1
# Write overlay only into ram
set use_ram_fs 1
# However read initial overlay from disk
set use_overlay_from_disk 1
set use_serial 1
set use_check_result 1
set use_usb [expr ![get_cmd_switch --autopilot]]
set use_ps2 1
set use_vms 1
set use_cpu_load 1
# use generic vbox5 VMM version
set use_vbox5_nova 0
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -1,31 +0,0 @@
#
# Windows 10 in VirtualBox 5
#
assert_spec nova
assert_spec x86_64
set flavor "win10_64_1vcpu"
set vm_ram "8280M"
set use_vbox5 1
set use_rumpfs 1
# Write overlay only into ram
set use_ram_fs 1
# However read initial overlay from disk
set use_overlay_from_disk 1
set use_serial 0
set use_check_result 1
set use_usb [expr ![get_cmd_switch --autopilot]]
set use_ps2 1
set use_vms 1
set use_cpu_load 0
# use generic vbox5 VMM version
set use_vbox5_nova 0
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -1,31 +0,0 @@
#
# Windows 7 in VirtualBox 5
#
assert_spec x86
assert_spec nova
set flavor "win7"
set vm_ram "1280M"
set use_vbox5 1
set use_rumpfs 1
# Write overlay only into ram
set use_ram_fs 1
# However read initial overlay from disk
set use_overlay_from_disk 1
set use_serial 0
set use_check_result 1
set use_usb [expr ![get_cmd_switch --autopilot]]
set use_ps2 1
set use_vms 1
set use_cpu_load 0
# use generic vbox5 VMM version
set use_vbox5_nova 0
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -1,31 +0,0 @@
#
# Windows 7 64bit in VirtualBox
#
assert_spec x86_64
assert_spec nova
set flavor "win7_64_1vcpu"
set vm_ram "9480M"
set use_vbox5 1
set use_rumpfs 1
# Write overlay only into ram
set use_ram_fs 1
# However read initial overlay from disk
set use_overlay_from_disk 1
set use_serial 0
set use_check_result 1
set use_usb [expr ![get_cmd_switch --autopilot]]
set use_ps2 1
set use_vms 1
set use_cpu_load 0
# use generic vbox5 VMM version
set use_vbox5_nova 0
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -25,9 +25,6 @@ set use_ps2 1
set use_vms 1 set use_vms 1
set use_cpu_load 0 set use_cpu_load 0
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
set use_webcam 1 set use_webcam 1
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -25,7 +25,4 @@ set use_ps2 1
set use_vms 1 set use_vms 1
set use_cpu_load 0 set use_cpu_load 0
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -25,7 +25,4 @@ set use_ps2 1
set use_vms 1 set use_vms 1
set use_cpu_load 0 set use_cpu_load 0
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -37,7 +37,4 @@ set use_vms 6
set affinity_space_width 8 set affinity_space_width 8
set use_cpu_load 0 set use_cpu_load 0
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -24,7 +24,4 @@ set use_ps2 1
set use_vms 1 set use_vms 1
set use_cpu_load 0 set use_cpu_load 0
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -53,8 +53,7 @@ set boot_modules {
dynamic_rom dynamic_rom
} }
set virtualbox5_binary "virtualbox5" set virtualbox5_binary "virtualbox5-nova"
if {$use_vbox5_nova} { set virtualbox5_binary "virtualbox5-nova" }
set config_of_app { set config_of_app {
@ -83,7 +82,7 @@ set config_of_app {
Note: to get network access in the VM, the virtual network adapter Note: to get network access in the VM, the virtual network adapter
needs to be enabled in the .vbox file (disabled by default) needs to be enabled in the .vbox file (disabled by default)
--> -->
<start name="nic_drv" priority="-1"> <start name="nic_drv" caps="150" priority="-1">
<binary name="pc_nic_drv"/> <binary name="pc_nic_drv"/>
<resource name="RAM" quantum="8M" /> <resource name="RAM" quantum="8M" />
<route> <route>

View File

@ -1,10 +1,10 @@
assert_spec nova
set use_net 0 set use_net 0
set use_usb_qemu 0 set use_usb_qemu 0
set use_serial 1 set use_serial 1
set use_top 1 set use_top 1
set use_vbox5_nova 0
# use_gui starts two VMs # use_gui starts two VMs
set use_gui 0 set use_gui 0
@ -15,11 +15,7 @@ set build_components {
append build_components virtualbox5 append build_components virtualbox5
set virtualbox_binary "virtualbox5" set virtualbox_binary "virtualbox5-nova"
if {$use_vbox5_nova} {
set virtualbox_binary "virtualbox5-nova"
}
create_boot_directory create_boot_directory

View File

@ -31,27 +31,6 @@ set match_guest_log "\[init -\> log_terminal\]"
set match_boot_string "\[init -\> vbox.*\].*Using VMX virtualization extension" set match_boot_string "\[init -\> vbox.*\].*Using VMX virtualization extension"
#set match_guest_down #set match_guest_down
# use generic vbox5 VMM version
set use_vbox5_nova 0
set vmm_name "vbox5_gen"
set use_vcpus 1
lappend results_expected 1 3 23 79
lappend boottime_expected 54
source ${genode_dir}/repos/ports/run/vbox_win.inc
source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc
kill_spawned [output_spawn_id]
# set use_vcpus 2
# lappend results_expected 2 10 42 50
# lappend boottime_expected 21
# source ${genode_dir}/repos/ports/run/vbox_win.inc
# source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc
# kill_spawned [output_spawn_id]
if {[have_spec nova]} {
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
set vmm_name "vbox5_nova" set vmm_name "vbox5_nova"
set use_vcpus 1 set use_vcpus 1
@ -81,7 +60,6 @@ if {[have_spec nova]} {
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc
source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc
kill_spawned [output_spawn_id] kill_spawned [output_spawn_id]
}
# #
# Dump aggregated output of the several runs above # Dump aggregated output of the several runs above

View File

@ -31,27 +31,6 @@ set match_guest_log "\[init -\> log_terminal\]"
set match_boot_string "\[init -\> vbox.*\].*Using VMX virtualization extension" set match_boot_string "\[init -\> vbox.*\].*Using VMX virtualization extension"
#set match_guest_down #set match_guest_down
# use generic vbox5 VMM version
set use_vbox5_nova 0
set vmm_name "vbox5_gen"
set use_vcpus 1
lappend results_expected 1 2 25 78
lappend boottime_expected 24
source ${genode_dir}/repos/ports/run/vbox_win.inc
source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc
kill_spawned [output_spawn_id]
# set use_vcpus 2
# lappend results_expected 0 0 0 0
# lappend boottime_expected 35
# source ${genode_dir}/repos/ports/run/vbox_win.inc
# source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc
# kill_spawned [output_spawn_id]
if {[have_spec nova]} {
# use non-generic vbox5 VMM version
set use_vbox5_nova 1
set vmm_name "vbox5_nova" set vmm_name "vbox5_nova"
set use_vcpus 1 set use_vcpus 1
@ -81,7 +60,6 @@ if {[have_spec nova]} {
source ${genode_dir}/repos/ports/run/vbox_win.inc source ${genode_dir}/repos/ports/run/vbox_win.inc
source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc source ${genode_dir}/repos/ports/run/vmm_vm_stress.inc
kill_spawned [output_spawn_id] kill_spawned [output_spawn_id]
}
# #
# Dump aggregated output of the several runs above # Dump aggregated output of the several runs above

View File

@ -1,227 +0,0 @@
/*
* \brief VirtualBox SUPLib supplements
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/attached_ram_dataspace.h>
#include <trace/timestamp.h>
/* Genode/Virtualbox includes */
#include "sup.h"
#include "vmm.h"
/* VirtualBox includes */
#include <iprt/ldr.h>
#include <iprt/semaphore.h>
#include <VBox/err.h>
SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void)
{
return sizeof(void *) == 4 ? SUPPAGINGMODE_32_BIT : SUPPAGINGMODE_AMD64_NX;
}
int SUPR3Term(bool) { return VINF_SUCCESS; }
int SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod,
uint32_t fFlags, PRTERRINFO pErrInfo)
{
return RTLdrLoad(pszFilename, phLdrMod);
}
SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)
{
Genode::log(__func__, " pvPages=", pvPages, " pages=", cPages);
return VINF_SUCCESS;
}
int SUPR3QueryMicrocodeRev(uint32_t *puMicrocodeRev)
{
return E_FAIL;
}
uint32_t SUPSemEventMultiGetResolution(PSUPDRVSESSION)
{
return 100000*10; /* called by 'vmR3HaltGlobal1Init' */
}
int SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent)
{
return RTSemEventCreate((PRTSEMEVENT)phEvent);
}
int SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
{
Assert (hEvent);
return RTSemEventDestroy((RTSEMEVENT)hEvent);
}
int SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
{
Assert (hEvent);
return RTSemEventSignal((RTSEMEVENT)hEvent);
}
int SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent,
uint32_t cMillies)
{
Assert (hEvent);
return RTSemEventWaitNoResume((RTSEMEVENT)hEvent, cMillies);
}
int SUPSemEventMultiCreate(PSUPDRVSESSION, PSUPSEMEVENTMULTI phEventMulti)
{
RTSEMEVENTMULTI sem;
/*
* Input validation.
*/
AssertPtrReturn(phEventMulti, VERR_INVALID_POINTER);
/*
* Create the event semaphore object.
*/
int rc = RTSemEventMultiCreate(&sem);
static_assert(sizeof(sem) == sizeof(*phEventMulti), "oi");
*phEventMulti = reinterpret_cast<SUPSEMEVENTMULTI>(sem);
return rc;
}
int SUPSemEventMultiWaitNoResume(PSUPDRVSESSION, SUPSEMEVENTMULTI event,
uint32_t ms)
{
RTSEMEVENTMULTI const rtevent = reinterpret_cast<RTSEMEVENTMULTI>(event);
return RTSemEventMultiWait(rtevent, ms);
}
int SUPSemEventMultiSignal(PSUPDRVSESSION, SUPSEMEVENTMULTI event) {
return RTSemEventMultiSignal(reinterpret_cast<RTSEMEVENTMULTI>(event)); }
int SUPSemEventMultiReset(PSUPDRVSESSION, SUPSEMEVENTMULTI event) {
return RTSemEventMultiReset(reinterpret_cast<RTSEMEVENTMULTI>(event)); }
int SUPSemEventMultiClose(PSUPDRVSESSION, SUPSEMEVENTMULTI event) {
return RTSemEventMultiDestroy(reinterpret_cast<RTSEMEVENTMULTI>(event)); }
int SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation,
void *pvArg)
{
if (uOperation == VMMR0_DO_CALL_HYPERVISOR) {
Genode::log(__func__, ": VMMR0_DO_CALL_HYPERVISOR - doing nothing");
return VINF_SUCCESS;
}
if (uOperation == VMMR0_DO_VMMR0_TERM) {
Genode::log(__func__, ": VMMR0_DO_VMMR0_TERM - doing nothing");
return VINF_SUCCESS;
}
if (uOperation == VMMR0_DO_GVMM_DESTROY_VM) {
Genode::log(__func__, ": VMMR0_DO_GVMM_DESTROY_VM - doing nothing");
return VINF_SUCCESS;
}
AssertMsg(uOperation != VMMR0_DO_VMMR0_TERM &&
uOperation != VMMR0_DO_CALL_HYPERVISOR &&
uOperation != VMMR0_DO_GVMM_DESTROY_VM,
("SUPR3CallVMMR0: unhandled uOperation %d", uOperation));
return VERR_GENERAL_FAILURE;
}
void genode_VMMR0_DO_GVMM_CREATE_VM(PSUPVMMR0REQHDR pReqHdr)
{
GVMMCREATEVMREQ &req = reinterpret_cast<GVMMCREATEVMREQ &>(*pReqHdr);
size_t const cCpus = req.cCpus;
/*
* Allocate and initialize VM struct
*
* The VM struct is followed by the variable-sizedA array of VMCPU
* objects. 'RT_UOFFSETOF' is used to determine the size including
* the VMCPU array.
*
* VM struct must be page-aligned, which is checked at least in
* PDMR3CritSectGetNop().
*/
size_t const cbVM = RT_UOFFSETOF(VM, aCpus[cCpus]);
static Genode::Attached_ram_dataspace vm(genode_env().ram(),
genode_env().rm(),
cbVM);
Assert (vm.size() >= cbVM);
VM *pVM = vm.local_addr<VM>();
Genode::memset(pVM, 0, cbVM);
/*
* On Genode, VMMR0 and VMMR3 share a single address space. Hence, the
* same pVM pointer is valid as pVMR0 and pVMR3.
*/
pVM->enmVMState = VMSTATE_CREATING;
pVM->pVMR0 = (RTHCUINTPTR)pVM;
pVM->pVMRC = (RTGCUINTPTR)pVM;
pVM->pSession = req.pSession;
pVM->cbSelf = cbVM;
pVM->cCpus = cCpus;
pVM->uCpuExecutionCap = 100; /* expected by 'vmR3CreateU()' */
pVM->offVMCPU = RT_UOFFSETOF(VM, aCpus);
for (uint32_t i = 0; i < cCpus; i++) {
pVM->aCpus[i].pVMR0 = pVM->pVMR0;
pVM->aCpus[i].pVMR3 = pVM;
pVM->aCpus[i].idHostCpu = NIL_RTCPUID;
pVM->aCpus[i].hNativeThreadR0 = NIL_RTNATIVETHREAD;
}
pVM->aCpus[0].hNativeThreadR0 = RTThreadNativeSelf();
/* out parameters of the request */
req.pVMR0 = pVM->pVMR0;
req.pVMR3 = pVM;
}
void genode_VMMR0_DO_GVMM_REGISTER_VMCPU(PVMR0 pVMR0, VMCPUID idCpu)
{
PVM pVM = reinterpret_cast<PVM>(pVMR0);
pVM->aCpus[idCpu].hNativeThreadR0 = RTThreadNativeSelf();
}
HRESULT genode_check_memory_config(ComObjPtr<Machine>,
size_t const memory_vmm)
{
/* Request max available memory */
size_t const memory_available = genode_env().pd().avail_ram().value;
if (memory_vmm <= memory_available)
return S_OK;
Genode::error("Available memory too low to start the VM - available: ",
memory_available, " MB < ", memory_vmm, " MB requested");
return E_FAIL;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +0,0 @@
/*
* \brief Genode specific VirtualBox SUPLib supplements
* \author Norman Feske
* \author Alexander Boettcher
* \author Christian Helmuth
*/
/*
* Copyright (C) 2013-2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__SVM_H_
#define _VIRTUALBOX__SVM_H_
/* based on HWSVMR0.h - adjusted to Genode */
#define GENODE_SVM_ASSERT_SELREG(REG) \
AssertMsg(!pCtx->REG.Attr.n.u1Present || \
(pCtx->REG.Attr.n.u1Granularity \
? (pCtx->REG.u32Limit & 0xfffU) == 0xfffU \
: pCtx->REG.u32Limit <= 0xfffffU), \
("%u %u %#x %#x %#llx\n", pCtx->REG.Attr.n.u1Present, \
pCtx->REG.Attr.n.u1Granularity, pCtx->REG.u32Limit, \
pCtx->REG.Attr.u, pCtx->REG.u64Base))
#define GENODE_READ_SELREG(REG) \
pCtx->REG.Sel = state->REG.value().sel; \
pCtx->REG.ValidSel = state->REG.value().sel; \
pCtx->REG.fFlags = CPUMSELREG_FLAGS_VALID; \
pCtx->REG.u32Limit = state->REG.value().limit; \
pCtx->REG.u64Base = state->REG.value().base; \
pCtx->REG.Attr.u = sel_ar_conv_from_genode(state->REG.value().ar)
static inline bool svm_save_state(Genode::Vcpu_state * state, VM * pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
GENODE_READ_SELREG(cs);
GENODE_READ_SELREG(ds);
GENODE_READ_SELREG(es);
GENODE_READ_SELREG(fs);
GENODE_READ_SELREG(gs);
GENODE_READ_SELREG(ss);
if ( !pCtx->cs.Attr.n.u1Granularity
&& pCtx->cs.Attr.n.u1Present
&& pCtx->cs.u32Limit > UINT32_C(0xfffff))
{
Assert((pCtx->cs.u32Limit & 0xfff) == 0xfff);
pCtx->cs.Attr.n.u1Granularity = 1;
}
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);
CPUMSetGuestEFER(pVCpu, CPUMGetGuestEFER(pVCpu) & ~uint64_t(MSR_K6_EFER_SVME));
return true;
}
#undef GENODE_ASSERT_SELREG
#undef GENODE_READ_SELREG
#define GENODE_WRITE_SELREG(REG) \
Assert(pCtx->REG.fFlags & CPUMSELREG_FLAGS_VALID); \
Assert(pCtx->REG.ValidSel == pCtx->REG.Sel); \
state->REG.charge(Segment { .sel = pCtx->REG.Sel, \
.ar = sel_ar_conv_to_genode(pCtx->REG.Attr.u), \
.limit = pCtx->REG.u32Limit, \
.base = pCtx->REG.u64Base });
static inline bool svm_load_state(Genode::Vcpu_state * state, VM * pVM, PVMCPU pVCpu)
{
typedef Genode::Vcpu_state::Segment Segment;
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
state->efer.charge(state->efer.value() | MSR_K6_EFER_SVME);
GENODE_WRITE_SELREG(es);
GENODE_WRITE_SELREG(ds);
GENODE_WRITE_SELREG(fs);
GENODE_WRITE_SELREG(gs);
GENODE_WRITE_SELREG(cs);
GENODE_WRITE_SELREG(ss);
GENODE_WRITE_SELREG(ldtr);
GENODE_WRITE_SELREG(tr);
return true;
}
#undef GENODE_WRITE_SELREG
#endif /* _VIRTUALBOX__SVM_H_ */

View File

@ -1,11 +0,0 @@
TARGET = virtualbox5
include $(REP_DIR)/src/virtualbox5/target.inc
LIBS += virtualbox5
LIBS += blit
vpath frontend/% $(REP_DIR)/src/virtualbox5/
vpath %.cc $(REP_DIR)/src/virtualbox5/
CC_CXX_WARN_STRICT =

View File

@ -1,862 +0,0 @@
/*
* \brief Genode VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \author Norman Feske
* \author Christian Helmuth
*/
/*
* Copyright (C) 2013-2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__VCPU_H_
#define _VIRTUALBOX__VCPU_H_
/* Genode includes */
#include <base/log.h>
#include <rom_session/connection.h>
#include <timer_session/connection.h>
#include <vm_session/connection.h>
#include <cpu/vcpu_state.h>
/* VirtualBox includes */
#include "PGMInternal.h" /* enable access to pgm.s.* */
#include "HMInternal.h" /* enable access to hm.s.* */
#include "CPUMInternal.h" /* enable access to cpum.s.* */
#include <VBox/vmm/vm.h>
#include <VBox/vmm/hm_svm.h>
#include <VBox/err.h>
#include <VBox/vmm/pdmapi.h>
#include <iprt/time.h>
/* Genode's VirtualBox includes */
#include "sup.h"
/* Genode libc pthread binding */
#include <internal/pthread.h>
#include <VBox/vmm/rem.h>
/*
* VirtualBox stores segment attributes in Intel format using a 32-bit
* value. Genode represents the attributes in packed format using a 16-bit
* value.
*/
static inline Genode::uint16_t sel_ar_conv_to_genode(Genode::uint32_t v)
{
return (v & 0xff) | ((v & 0x1f000) >> 4);
}
static inline Genode::uint32_t sel_ar_conv_from_genode(Genode::uint16_t v)
{
return (v & 0xff) | (((uint32_t )v << 4) & 0x1f000);
}
class Vcpu_handler : public Genode::List<Vcpu_handler>::Element
{
protected:
static Genode::Vm_connection::Exit_config const _exit_config;
Genode::Entrypoint _ep;
Genode::Blockade _blockade_emt { };
Genode::Semaphore _sem_handler;
Genode::Vcpu_state *_state { nullptr };
pthread_cond_t _cond_wait;
pthread_mutex_t _mutex;
/* information used for NPT/EPT handling */
Genode::addr_t npt_ept_exit_addr { 0 };
RTGCUINT npt_ept_errorcode { 0 };
bool npt_ept_unmap { false };
/* state machine between EMT and EP thread of a vCPU */
enum { RUNNING, PAUSED, IRQ_WIN, NPT_EPT } _vm_state { PAUSED };
enum { PAUSE_EXIT, RUN } _next_state { RUN };
private:
bool _irq_win = false;
unsigned const _cpu_id;
PVM _vm { nullptr };
PVMCPU _vcpu { nullptr };
unsigned int _last_inj_info = 0;
unsigned int _last_inj_error = 0;
enum {
REQ_IRQWIN_EXIT = 0x1000U,
IRQ_INJ_VALID_MASK = 0x80000000UL,
IRQ_INJ_NONE = 0U,
/*
* Intel® 64 and IA-32 Architectures Software Developers Manual
* Volume 3C, Chapter 24.4.2.
* May 2012
*/
BLOCKING_BY_STI = 1U << 0,
BLOCKING_BY_MOV_SS = 1U << 1,
ACTIVITY_STATE_ACTIVE = 0U,
INTERRUPT_STATE_NONE = 0U,
};
timespec add_timespec_ns(timespec a, uint64_t ns) const
{
enum { NSEC_PER_SEC = 1'000'000'000ull };
long sec = a.tv_sec;
while (a.tv_nsec >= NSEC_PER_SEC) {
a.tv_nsec -= NSEC_PER_SEC;
sec++;
}
while (ns >= NSEC_PER_SEC) {
ns -= NSEC_PER_SEC;
sec++;
}
long nsec = a.tv_nsec + ns;
while (nsec >= NSEC_PER_SEC) {
nsec -= NSEC_PER_SEC;
sec++;
}
return timespec { sec, nsec };
}
protected:
int map_memory(Genode::Vm_connection &vm_session,
RTGCPHYS GCPhys, RTGCUINT vbox_fault_reason);
Genode::addr_t _vm_exits = 0;
Genode::addr_t _recall_skip = 0;
Genode::addr_t _recall_req = 0;
Genode::addr_t _recall_inv = 0;
Genode::addr_t _recall_drop = 0;
Genode::addr_t _irq_request = 0;
Genode::addr_t _irq_inject = 0;
Genode::addr_t _irq_drop = 0;
struct {
unsigned ctrl[2];
} next_utcb;
unsigned _ept_fault_addr_type;
Genode::uint64_t * pdpte_map(VM *pVM, RTGCPHYS cr3);
void switch_to_hw(PCPUMCTX pCtx)
{
using Genode::Vcpu_state;
again:
/* write FPU state */
AssertCompile(sizeof(Vcpu_state::Fpu::State) >= sizeof(X86FXSTATE));
_state->fpu.charge([&] (Vcpu_state::Fpu::State &fpu) {
::memcpy(&fpu, pCtx->pXStateR3, sizeof(X86FXSTATE));
});
Assert(_vm_state == IRQ_WIN || _vm_state == PAUSED || _vm_state == NPT_EPT);
Assert(_next_state == PAUSE_EXIT || _next_state == RUN);
/* wake up vcpu ep handler */
_sem_handler.up();
/* wait for next exit */
_blockade_emt.block();
/* next time run - recall() may change this */
_next_state = RUN;
/* write FPU state of vCPU to pCtx */
_state->fpu.with_state([&] (Vcpu_state::Fpu::State const &fpu) {
::memcpy(pCtx->pXStateR3, &fpu, sizeof(X86FXSTATE));
});
_state->discharge();
if (_vm_state == IRQ_WIN) {
_irq_window_pthread();
goto again;
} else
if (_vm_state == NPT_EPT) {
if (npt_ept_unmap) {
Genode::error("NPT/EPT unmap not supported - stop");
while (true) {
_blockade_emt.block();
}
}
Genode::addr_t const gp_map_addr = npt_ept_exit_addr & ~((1UL << 12) - 1);
int res = attach_memory_to_vm(gp_map_addr, npt_ept_errorcode);
if (res == VINF_SUCCESS) {
goto again;
}
}
if (!(_vm_state == PAUSED || _vm_state == NPT_EPT))
Genode::error("which state we are ? ", (int)_vm_state, " ", Genode::Thread::myself()->name());
Assert(_vm_state == PAUSED || _vm_state == NPT_EPT);
}
void _default_handler()
{
if (_vm_state != RUNNING)
Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason));
Assert(_vm_state == RUNNING);
Assert(_state->actv_state.value() == ACTIVITY_STATE_ACTIVE);
Assert(!(_state->inj_info.value() & IRQ_INJ_VALID_MASK));
_vm_exits ++;
_vm_state = PAUSED;
_blockade_emt.wakeup();
}
bool _recall_handler()
{
if (_vm_state != RUNNING)
Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason));
Assert(_vm_state == RUNNING);
_vm_exits ++;
_recall_inv ++;
Assert(_state->actv_state.value() == ACTIVITY_STATE_ACTIVE);
if (_state->inj_info.value() & IRQ_INJ_VALID_MASK) {
Assert(_state->flags.value() & X86_EFL_IF);
if (_state->intr_state.value() != INTERRUPT_STATE_NONE)
Genode::log("intr state ", Genode::Hex(_state->intr_state.value()),
" ", Genode::Hex(_state->intr_state.value() & 0xf));
Assert(_state->intr_state.value() == INTERRUPT_STATE_NONE);
if (!continue_hw_accelerated())
_recall_drop ++;
/* got recall during irq injection and the guest is ready for
* delivery of IRQ - just continue */
return /* no-wait */ false;
}
/* are we forced to go back to emulation mode ? */
if (!continue_hw_accelerated()) {
/* go back to emulation mode */
_default_handler();
return /* wait */ true;
}
/* check whether we have to request irq injection window */
if (check_to_request_irq_window(_vcpu)) {
_state->discharge();
_state->inj_info.charge(_state->inj_info.value());
_irq_win = true;
return /* no-wait */ false;
}
_default_handler();
return /* wait */ true;
}
inline bool vbox_to_state(VM *pVM, PVMCPU pVCpu)
{
typedef Genode::Vcpu_state::Range Range;
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
_state->ip.charge(pCtx->rip);
_state->sp.charge(pCtx->rsp);
_state->ax.charge(pCtx->rax);
_state->bx.charge(pCtx->rbx);
_state->cx.charge(pCtx->rcx);
_state->dx.charge(pCtx->rdx);
_state->bp.charge(pCtx->rbp);
_state->si.charge(pCtx->rsi);
_state->di.charge(pCtx->rdi);
_state->r8.charge(pCtx->r8);
_state->r9.charge(pCtx->r9);
_state->r10.charge(pCtx->r10);
_state->r11.charge(pCtx->r11);
_state->r12.charge(pCtx->r12);
_state->r13.charge(pCtx->r13);
_state->r14.charge(pCtx->r14);
_state->r15.charge(pCtx->r15);
_state->flags.charge(pCtx->rflags.u);
_state->sysenter_cs.charge(pCtx->SysEnter.cs);
_state->sysenter_sp.charge(pCtx->SysEnter.esp);
_state->sysenter_ip.charge(pCtx->SysEnter.eip);
_state->dr7.charge(pCtx->dr[7]);
_state->cr0.charge(pCtx->cr0);
_state->cr2.charge(pCtx->cr2);
_state->cr3.charge(pCtx->cr3);
_state->cr4.charge(pCtx->cr4);
_state->idtr.charge(Range { .limit = pCtx->idtr.cbIdt,
.base = pCtx->idtr.pIdt });
_state->gdtr.charge(Range { .limit = pCtx->gdtr.cbGdt,
.base = pCtx->gdtr.pGdt });
_state->efer.charge(CPUMGetGuestEFER(pVCpu));
/*
* Update the PDPTE registers if necessary
*
* Intel manual sections 4.4.1 of Vol. 3A and 26.3.2.4 of Vol. 3C
* indicate the conditions when this is the case. The following
* code currently does not check if the recompiler modified any
* CR registers, which means the update can happen more often
* than really necessary.
*/
if (pVM->hm.s.vmx.fSupported &&
CPUMIsGuestPagingEnabledEx(pCtx) &&
CPUMIsGuestInPAEModeEx(pCtx)) {
Genode::uint64_t *pdpte = pdpte_map(pVM, pCtx->cr3);
_state->pdpte_0.charge(pdpte[0]);
_state->pdpte_1.charge(pdpte[1]);
_state->pdpte_2.charge(pdpte[2]);
_state->pdpte_3.charge(pdpte[3]);
}
_state->star.charge(pCtx->msrSTAR);
_state->lstar.charge(pCtx->msrLSTAR);
_state->cstar.charge(pCtx->msrCSTAR);
_state->fmask.charge(pCtx->msrSFMASK);
_state->kernel_gs_base.charge(pCtx->msrKERNELGSBASE);
/* from HMVMXR0.cpp */
bool interrupt_pending = false;
uint8_t tpr = 0;
uint8_t pending_interrupt = 0;
PDMApicGetTPR(pVCpu, &tpr, &interrupt_pending, &pending_interrupt);
_state->tpr.charge(tpr);
_state->tpr_threshold.charge(0);
if (interrupt_pending) {
const uint8_t pending_priority = (pending_interrupt >> 4) & 0xf;
const uint8_t tpr_priority = (tpr >> 4) & 0xf;
if (pending_priority <= tpr_priority)
_state->tpr_threshold.charge(pending_priority);
else
_state->tpr_threshold.charge(tpr_priority);
}
{
::uint64_t tsc_aux = 0;
auto const rcStrict = CPUMQueryGuestMsr(pVCpu, MSR_K8_TSC_AUX,
&tsc_aux);
Assert(rcStrict == VINF_SUCCESS);
if (rcStrict == VINF_SUCCESS)
_state->tsc_aux.charge(tsc_aux);
}
return true;
}
inline bool state_to_vbox(VM *pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
pCtx->rip = _state->ip.value();
pCtx->rsp = _state->sp.value();
pCtx->rax = _state->ax.value();
pCtx->rbx = _state->bx.value();
pCtx->rcx = _state->cx.value();
pCtx->rdx = _state->dx.value();
pCtx->rbp = _state->bp.value();
pCtx->rsi = _state->si.value();
pCtx->rdi = _state->di.value();
pCtx->rflags.u = _state->flags.value();
pCtx->r8 = _state->r8.value();
pCtx->r9 = _state->r9.value();
pCtx->r10 = _state->r10.value();
pCtx->r11 = _state->r11.value();
pCtx->r12 = _state->r12.value();
pCtx->r13 = _state->r13.value();
pCtx->r14 = _state->r14.value();
pCtx->r15 = _state->r15.value();
pCtx->dr[7] = _state->dr7.value();
if (pCtx->SysEnter.cs != _state->sysenter_cs.value())
CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_CS, _state->sysenter_cs.value());
if (pCtx->SysEnter.esp != _state->sysenter_sp.value())
CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_ESP, _state->sysenter_sp.value());
if (pCtx->SysEnter.eip != _state->sysenter_ip.value())
CPUMSetGuestMsr(pVCpu, MSR_IA32_SYSENTER_EIP, _state->sysenter_ip.value());
if (pCtx->idtr.cbIdt != _state->idtr.value().limit ||
pCtx->idtr.pIdt != _state->idtr.value().base)
CPUMSetGuestIDTR(pVCpu, _state->idtr.value().base, _state->idtr.value().limit);
if (pCtx->gdtr.cbGdt != _state->gdtr.value().limit ||
pCtx->gdtr.pGdt != _state->gdtr.value().base)
CPUMSetGuestGDTR(pVCpu, _state->gdtr.value().base, _state->gdtr.value().limit);
CPUMSetGuestEFER(pVCpu, _state->efer.value());
if (pCtx->cr0 != _state->cr0.value())
CPUMSetGuestCR0(pVCpu, _state->cr0.value());
if (pCtx->cr2 != _state->cr2.value())
CPUMSetGuestCR2(pVCpu, _state->cr2.value());
if (pCtx->cr3 != _state->cr3.value()) {
CPUMSetGuestCR3(pVCpu, _state->cr3.value());
VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
}
if (pCtx->cr4 != _state->cr4.value())
CPUMSetGuestCR4(pVCpu, _state->cr4.value());
if (pCtx->msrSTAR != _state->star.value())
CPUMSetGuestMsr(pVCpu, MSR_K6_STAR, _state->star.value());
if (pCtx->msrLSTAR != _state->lstar.value())
CPUMSetGuestMsr(pVCpu, MSR_K8_LSTAR, _state->lstar.value());
if (pCtx->msrCSTAR != _state->cstar.value())
CPUMSetGuestMsr(pVCpu, MSR_K8_CSTAR, _state->cstar.value());
if (pCtx->msrSFMASK != _state->fmask.value())
CPUMSetGuestMsr(pVCpu, MSR_K8_SF_MASK, _state->fmask.value());
if (pCtx->msrKERNELGSBASE != _state->kernel_gs_base.value())
CPUMSetGuestMsr(pVCpu, MSR_K8_KERNEL_GS_BASE, _state->kernel_gs_base.value());
const uint32_t tpr = _state->tpr.value();
/* reset message transfer descriptor for next invocation */
Assert (!(_state->inj_info.value() & IRQ_INJ_VALID_MASK));
next_utcb.ctrl[0] = _state->ctrl_primary.value();
next_utcb.ctrl[1] = _state->ctrl_secondary.value();
if (_state->intr_state.value() & 3) {
_state->intr_state.charge(_state->intr_state.value());
_state->actv_state.charge(ACTIVITY_STATE_ACTIVE);
}
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM);
pVCpu->cpum.s.fUseFlags |= (CPUM_USED_FPU_GUEST | CPUM_USED_FPU_SINCE_REM);
if (_state->intr_state.value() != 0) {
Assert(_state->intr_state.value() == BLOCKING_BY_STI ||
_state->intr_state.value() == BLOCKING_BY_MOV_SS);
EMSetInhibitInterruptsPC(pVCpu, pCtx->rip);
} else
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
PDMApicSetTPR(pVCpu, tpr);
return true;
}
inline bool check_to_request_irq_window(PVMCPU pVCpu)
{
if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
return false;
if (!TRPMHasTrap(pVCpu) &&
!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC |
VMCPU_FF_INTERRUPT_PIC)))
return false;
_irq_request++;
unsigned const vector = 0;
_state->inj_info.charge(REQ_IRQWIN_EXIT | vector);
return true;
}
void _irq_window()
{
if (_vm_state != RUNNING)
Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason));
Assert(_vm_state == RUNNING);
_vm_exits ++;
_vm_state = IRQ_WIN;
_blockade_emt.wakeup();
}
void _npt_ept()
{
if (_vm_state != RUNNING)
Genode::error(__func__, " _vm_state=", (int)_vm_state, " exit_reason=", Genode::Hex(_state->exit_reason));
Assert(_vm_state == RUNNING);
_vm_exits ++;
_vm_state = NPT_EPT;
_blockade_emt.wakeup();
}
void _irq_window_pthread()
{
PVMCPU pVCpu = _vcpu;
Assert(_state->flags.value() & X86_EFL_IF);
Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS));
Assert(!(_state->inj_info.value() & IRQ_INJ_VALID_MASK));
Assert(_irq_win);
_irq_win = false;
/* request current tpr state from guest, it may block IRQs */
PDMApicSetTPR(pVCpu, _state->tpr_threshold.value());
if (!TRPMHasTrap(pVCpu)) {
bool res = VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
if (res)
Genode::log("NMI was set");
if (VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC |
VMCPU_FF_INTERRUPT_PIC))) {
uint8_t irq;
int rc = PDMGetInterrupt(pVCpu, &irq);
Assert(RT_SUCCESS(rc));
rc = TRPMAssertTrap(pVCpu, irq, TRPM_HARDWARE_INT);
Assert(RT_SUCCESS(rc));
}
if (!TRPMHasTrap(pVCpu)) {
_irq_drop++;
/* happens if PDMApicSetTPR (see above) mask IRQ */
_state->inj_info.charge(IRQ_INJ_NONE);
Genode::error("virq window pthread aaaaaaa while loop");
return;
}
}
_irq_inject++;
/*
* If we have no IRQ for injection, something with requesting the
* IRQ window went wrong. Probably it was forgotten to be reset.
*/
Assert(TRPMHasTrap(pVCpu));
/* interrupt can be dispatched */
uint8_t u8Vector;
TRPMEVENT enmType;
SVMEVENT Event;
RTGCUINT u32ErrorCode;
RTGCUINTPTR GCPtrFaultAddress;
uint8_t cbInstr;
Event.u = 0;
/* If a new event is pending, then dispatch it now. */
int rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, 0, 0);
AssertRC(rc);
Assert(enmType == TRPM_HARDWARE_INT);
Assert(u8Vector != X86_XCPT_NMI);
/* Clear the pending trap. */
rc = TRPMResetTrap(pVCpu);
AssertRC(rc);
Event.n.u8Vector = u8Vector;
Event.n.u1Valid = 1;
Event.n.u32ErrorCode = u32ErrorCode;
Event.n.u3Type = SVM_EVENT_EXTERNAL_IRQ;
_state->inj_info.charge(Event.u);
_state->inj_error.charge(Event.n.u32ErrorCode);
_last_inj_info = _state->inj_info.value();
_last_inj_error = _state->inj_error.value();
/*
Genode::log("type:info:vector ", Genode::Hex(Event.n.u3Type),
Genode::Hex(utcb->inj_info), Genode::Hex(u8Vector),
" intr:actv - ", Genode::Hex(utcb->intr_state),
Genode::Hex(utcb->actv_state), " mtd ",
Genode::Hex(utcb->mtd));
*/
}
inline bool continue_hw_accelerated(bool verbose = false)
{
uint32_t check_vm = VM_FF_HM_TO_R3_MASK | VM_FF_REQUEST
| VM_FF_PGM_POOL_FLUSH_PENDING
| VM_FF_PDM_DMA;
uint32_t check_vcpu = VMCPU_FF_HM_TO_R3_MASK
| VMCPU_FF_PGM_SYNC_CR3
| VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL
| VMCPU_FF_REQUEST;
if (!VM_FF_IS_PENDING(_vm, check_vm) &&
!VMCPU_FF_IS_PENDING(_vcpu, check_vcpu))
return true;
Assert(!(VM_FF_IS_PENDING(_vm, VM_FF_PGM_NO_MEMORY)));
#define VERBOSE_VM(flag) \
do { \
if (VM_FF_IS_PENDING(_vm, flag)) \
Genode::log("flag ", flag, " pending"); \
} while (0)
#define VERBOSE_VMCPU(flag) \
do { \
if (VMCPU_FF_IS_PENDING(_vcpu, flag)) \
Genode::log("flag ", flag, " pending"); \
} while (0)
if (verbose) {
/*
* VM_FF_HM_TO_R3_MASK
*/
VERBOSE_VM(VM_FF_TM_VIRTUAL_SYNC);
VERBOSE_VM(VM_FF_PGM_NEED_HANDY_PAGES);
/* handled by the assertion above */
/* VERBOSE_VM(VM_FF_PGM_NO_MEMORY); */
VERBOSE_VM(VM_FF_PDM_QUEUES);
VERBOSE_VM(VM_FF_EMT_RENDEZVOUS);
VERBOSE_VM(VM_FF_REQUEST);
VERBOSE_VM(VM_FF_PGM_POOL_FLUSH_PENDING);
VERBOSE_VM(VM_FF_PDM_DMA);
/*
* VMCPU_FF_HM_TO_R3_MASK
*/
VERBOSE_VMCPU(VMCPU_FF_TO_R3);
/* when this flag gets set, a recall request follows */
/* VERBOSE_VMCPU(VMCPU_FF_TIMER); */
VERBOSE_VMCPU(VMCPU_FF_PDM_CRITSECT);
VERBOSE_VMCPU(VMCPU_FF_PGM_SYNC_CR3);
VERBOSE_VMCPU(VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
VERBOSE_VMCPU(VMCPU_FF_REQUEST);
}
#undef VERBOSE_VMCPU
#undef VERBOSE_VM
return false;
}
virtual bool hw_load_state(Genode::Vcpu_state *, VM *, PVMCPU) = 0;
virtual bool hw_save_state(Genode::Vcpu_state *, VM *, PVMCPU) = 0;
virtual int vm_exit_requires_instruction_emulation(PCPUMCTX) = 0;
virtual void pause_vm() = 0;
virtual int attach_memory_to_vm(RTGCPHYS const,
RTGCUINT vbox_fault_reason) = 0;
public:
enum Exit_condition
{
SVM_NPT = 0xfc,
SVM_INVALID = 0xfd,
VCPU_STARTUP = 0xfe,
RECALL = 0xff,
};
Vcpu_handler(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
unsigned int cpu_id)
:
_ep(env, stack_size,
Genode::String<12>("EP-EMT-", cpu_id).string(), location),
_cpu_id(cpu_id)
{
pthread_mutexattr_t _attr;
pthread_mutexattr_init(&_attr);
pthread_cond_init(&_cond_wait, nullptr);
pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&_mutex, &_attr);
}
unsigned int cpu_id() { return _cpu_id; }
void recall(PVM vm)
{
if (!_vm || !_vcpu) {
_vm = vm;
_vcpu = &vm->aCpus[_cpu_id];
}
if (_vm != vm || _vcpu != &vm->aCpus[_cpu_id])
Genode::error("wrong CPU !?");
_recall_req ++;
if (_irq_win) {
_recall_skip ++;
return;
}
asm volatile ("":::"memory");
if (_vm_state != PAUSED)
pause_vm();
_next_state = PAUSE_EXIT;
#if 0
if (_recall_req % 1000 == 0) {
using Genode::log;
while (other) {
log(other->_cpu_id, " exits=", other->_vm_exits,
" req:skip:drop,inv recall=", other->_recall_req, ":",
other->_recall_skip, ":", other->_recall_drop, ":",
other->_recall_inv, " req:inj:drop irq=",
other->_irq_request, ":", other->_irq_inject, ":",
other->_irq_drop);
other = other->next();
}
}
#endif
}
void halt(Genode::uint64_t const wait_ns)
{
/* calculate timeout */
timespec ts { 0, 0 };
clock_gettime(CLOCK_REALTIME, &ts);
ts = add_timespec_ns(ts, wait_ns);
/* wait for condition or timeout */
pthread_mutex_lock(&_mutex);
pthread_cond_timedwait(&_cond_wait, &_mutex, &ts);
pthread_mutex_unlock(&_mutex);
}
void wake_up()
{
pthread_mutex_lock(&_mutex);
pthread_cond_signal(&_cond_wait);
pthread_mutex_unlock(&_mutex);
}
int run_hw(PVMR0 pVMR0)
{
VM * pVM = reinterpret_cast<VM *>(pVMR0);
PVMCPU pVCpu = &pVM->aCpus[_cpu_id];
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
if (!_vm || !_vcpu) {
_vm = pVM;
_vcpu = &pVM->aCpus[_cpu_id];
}
if (_vm != pVM || _vcpu != &pVM->aCpus[_cpu_id])
Genode::error("wrong CPU !?");
/* take the utcb state prepared during the last exit */
_state->ctrl_primary.charge(next_utcb.ctrl[0]);
_state->ctrl_secondary.charge(next_utcb.ctrl[1]);
/* Transfer vCPU state from vbox to Genode format */
if (!vbox_to_state(pVM, pVCpu) ||
!hw_load_state(_state, pVM, pVCpu)) {
Genode::error("loading vCPU state failed");
return VERR_INTERNAL_ERROR;
}
/* check whether to request interrupt window for injection */
_irq_win = check_to_request_irq_window(pVCpu);
/*
* Flag vCPU to be "pokeable" by external events such as interrupts
* from virtual devices. Only if this flag is set, the
* 'vmR3HaltGlobal1NotifyCpuFF' function calls 'SUPR3CallVMMR0Ex'
* with VMMR0_DO_GVMM_SCHED_POKE as argument to indicate such
* events. This function, in turn, will recall the vCPU.
*/
VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
/* switch to hardware accelerated mode */
switch_to_hw(pCtx);
Assert(_state->actv_state.value() == ACTIVITY_STATE_ACTIVE);
/* see hmR0VmxExitToRing3 - sync recompiler state */
CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR |
CPUM_CHANGED_LDTR | CPUM_CHANGED_GDTR |
CPUM_CHANGED_IDTR | CPUM_CHANGED_TR |
CPUM_CHANGED_HIDDEN_SEL_REGS |
CPUM_CHANGED_GLOBAL_TLB_FLUSH);
VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
/* Transfer vCPU state from Genode to vbox format */
if (!state_to_vbox(pVM, pVCpu) ||
!hw_save_state(_state, pVM, pVCpu)) {
Genode::error("saving vCPU state failed");
return VERR_INTERNAL_ERROR;
}
#ifdef VBOX_WITH_REM
REMFlushTBs(pVM);
#endif
/* track guest mode changes - see VMM/VMMAll/IEMAllCImpl.cpp.h */
PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
int rc = vm_exit_requires_instruction_emulation(pCtx);
/* evaluated in VMM/include/EMHandleRCTmpl.h */
return rc;
}
};
#endif /* _VIRTUALBOX__VCPU_H_ */

View File

@ -1,189 +0,0 @@
/*
* \brief Genode specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \author Norman Feske
* \author Christian Helmuth
* \date 2013-11-18
*/
/*
* Copyright (C) 2013-2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__VCPU_SVM_H_
#define _VIRTUALBOX__VCPU_SVM_H_
/* Genode includes */
#include <vm_session/handler.h>
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "svm.h"
class Vcpu_handler_svm : public Vcpu_handler
{
private:
Genode::Vcpu_handler<Vcpu_handler_svm> _handler;
Genode::Vm_connection &_vm_connection;
Genode::Vm_connection::Vcpu _vcpu;
void _svm_default() { _default_handler(); }
void _svm_vintr() { _irq_window(); }
template <unsigned X>
void _svm_npt()
{
bool const unmap = _state->qual_primary.value() & 1;
Genode::addr_t const exit_addr = _state->qual_secondary.value();
RTGCUINT const vbox_errorcode = _state->qual_primary.value();
npt_ept_exit_addr = exit_addr;
npt_ept_unmap = unmap;
npt_ept_errorcode = vbox_errorcode;
_npt_ept();
}
void _svm_startup()
{
/* enable VM exits */
next_utcb.ctrl[0] = SVM_CTRL1_INTERCEPT_INTR
| SVM_CTRL1_INTERCEPT_NMI
| SVM_CTRL1_INTERCEPT_INIT
| SVM_CTRL1_INTERCEPT_RDPMC
| SVM_CTRL1_INTERCEPT_CPUID
| SVM_CTRL1_INTERCEPT_RSM
| SVM_CTRL1_INTERCEPT_HLT
| SVM_CTRL1_INTERCEPT_INOUT_BITMAP
| SVM_CTRL1_INTERCEPT_MSR_SHADOW
| SVM_CTRL1_INTERCEPT_INVLPGA
| SVM_CTRL1_INTERCEPT_SHUTDOWN
| SVM_CTRL1_INTERCEPT_RDTSC
| SVM_CTRL1_INTERCEPT_FERR_FREEZE;
next_utcb.ctrl[1] = SVM_CTRL2_INTERCEPT_VMRUN
| SVM_CTRL2_INTERCEPT_VMMCALL
| SVM_CTRL2_INTERCEPT_VMLOAD
| SVM_CTRL2_INTERCEPT_VMSAVE
| SVM_CTRL2_INTERCEPT_STGI
| SVM_CTRL2_INTERCEPT_CLGI
| SVM_CTRL2_INTERCEPT_SKINIT
| SVM_CTRL2_INTERCEPT_WBINVD
| SVM_CTRL2_INTERCEPT_MONITOR
| SVM_CTRL2_INTERCEPT_RDTSCP
| SVM_CTRL2_INTERCEPT_MWAIT;
}
void _handle_exit()
{
unsigned const exit = _state->exit_reason;
bool recall_wait = true;
switch (exit) {
case SVM_EXIT_VINTR: _svm_vintr(); break;
case SVM_NPT: _svm_npt<SVM_NPT>(); break;
case SVM_EXIT_CPUID:
case SVM_EXIT_HLT:
case SVM_EXIT_INVLPGA:
case SVM_EXIT_IOIO:
case SVM_EXIT_MSR:
case SVM_EXIT_READ_CR0 ... SVM_EXIT_WRITE_CR15:
case SVM_EXIT_RDTSC:
case SVM_EXIT_RDTSCP:
case SVM_EXIT_WBINVD:
_svm_default();
break;
case SVM_INVALID:
Genode::warning("invalid svm ip=", _state->ip.value());
_svm_default();
break;
case SVM_EXIT_SHUTDOWN:
Genode::error("shutdown exit");
::exit(-1);
break;
case RECALL:
recall_wait = Vcpu_handler::_recall_handler();
break;
case VCPU_STARTUP:
_svm_startup();
_blockade_emt.wakeup();
/* pause - no resume */
break;
default:
Genode::error(__func__, " unknown exit - stop - ",
Genode::Hex(exit));
_vm_state = PAUSED;
return;
}
if (exit == RECALL && !recall_wait) {
_vm_state = RUNNING;
run_vm();
return;
}
/* wait until EMT thread wake's us up */
_sem_handler.down();
/* resume vCPU */
_vm_state = RUNNING;
if (_next_state == RUN)
run_vm();
else
pause_vm(); /* cause pause exit */
}
void run_vm() { _vcpu.run(); }
void pause_vm() { _vcpu.pause(); }
int attach_memory_to_vm(RTGCPHYS const gp_attach_addr,
RTGCUINT vbox_errorcode)
{
return map_memory(_vm_connection, gp_attach_addr, vbox_errorcode);
}
public:
Vcpu_handler_svm(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
unsigned int cpu_id,
Genode::Vm_connection &vm_connection,
Genode::Allocator &alloc)
:
Vcpu_handler(env, stack_size, location, cpu_id),
_handler(_ep, *this, &Vcpu_handler_svm::_handle_exit),
_vm_connection(vm_connection),
_vcpu(_vm_connection, alloc, _handler, _exit_config)
{
/* get state of vcpu */
_state = &_vcpu.state();
_vcpu.run();
/* sync with initial startup exception */
_blockade_emt.block();
}
bool hw_save_state(Genode::Vcpu_state *state, VM * pVM, PVMCPU pVCpu) {
return svm_save_state(state, pVM, pVCpu);
}
bool hw_load_state(Genode::Vcpu_state *state, VM * pVM, PVMCPU pVCpu) {
return svm_load_state(state, pVM, pVCpu);
}
int vm_exit_requires_instruction_emulation(PCPUMCTX)
{
if (_state->exit_reason == RECALL)
return VINF_SUCCESS;
return VINF_EM_RAW_EMULATE_INSTR;
}
};
#endif /* _VIRTUALBOX__VCPU_SVM_H_ */

View File

@ -1,251 +0,0 @@
/*
* \brief Genode specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \author Norman Feske
* \author Christian Helmuth
* \date 2013-11-18
*/
/*
* Copyright (C) 2013-2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__VCPU_VMX_H_
#define _VIRTUALBOX__VCPU_VMX_H_
/* Genode includes */
#include <vm_session/handler.h>
/* libc includes */
#include <stdlib.h>
/* VirtualBox includes */
#include <VBox/vmm/hm_vmx.h>
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "vmx.h"
class Vcpu_handler_vmx : public Vcpu_handler
{
private:
Genode::Vcpu_handler<Vcpu_handler_vmx> _handler;
Genode::Vm_connection &_vm_connection;
Genode::Vm_connection::Vcpu _vcpu;
template <unsigned X>
void _vmx_ept()
{
Genode::addr_t const exit_qual = _state->qual_primary.value();
Genode::addr_t const exit_addr = _state->qual_secondary.value();
bool const unmap = exit_qual & 0x38;
RTGCUINT vbox_errorcode = 0;
if (exit_qual & VMX_EXIT_QUALIFICATION_EPT_INSTR_FETCH)
vbox_errorcode |= X86_TRAP_PF_ID;
if (exit_qual & VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE)
vbox_errorcode |= X86_TRAP_PF_RW;
if (exit_qual & VMX_EXIT_QUALIFICATION_EPT_ENTRY_PRESENT)
vbox_errorcode |= X86_TRAP_PF_P;
npt_ept_exit_addr = exit_addr;
npt_ept_unmap = unmap;
npt_ept_errorcode = vbox_errorcode;
_npt_ept();
}
void _vmx_default() { _default_handler(); }
void _vmx_startup()
{
/* configure VM exits to get */
/* from src/VBox/VMM/VMMR0/HWVMXR0.cpp of virtualbox sources */
next_utcb.ctrl[0] = VMX_VMCS_CTRL_PROC_EXEC_HLT_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_MOV_DR_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_UNCOND_IO_EXIT |
/*
VMX_VMCS_CTRL_PROC_EXEC_MONITOR_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_MWAIT_EXIT |
*/
/* VMX_VMCS_CTRL_PROC_EXEC_CR8_LOAD_EXIT |
VMX_VMCS_CTRL_PROC_EXEC_CR8_STORE_EXIT |*/
VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW |
VMX_VMCS_CTRL_PROC_EXEC_RDPMC_EXIT;
/* VMX_VMCS_CTRL_PROC_EXEC_PAUSE_EXIT | */
/*
* Disable trapping RDTSC for now as it creates a huge load with
* VM guests that execute it frequently.
*/
// VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT;
next_utcb.ctrl[1] = VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC |
VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT |
VMX_VMCS_CTRL_PROC_EXEC2_UNRESTRICTED_GUEST |
VMX_VMCS_CTRL_PROC_EXEC2_VPID |
VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP |
VMX_VMCS_CTRL_PROC_EXEC2_EPT |
VMX_VMCS_CTRL_PROC_EXEC2_INVPCID;
}
void _vmx_triple()
{
Genode::error("triple fault - dead");
exit(-1);
}
void _vmx_irqwin() { _irq_window(); }
__attribute__((noreturn)) void _vmx_invalid()
{
unsigned const dubious = _state->inj_info.value() |
_state->intr_state.value() |
_state->actv_state.value();
if (dubious)
Genode::warning(__func__, " - dubious -"
" inj_info=", Genode::Hex(_state->inj_info.value()),
" inj_error=", Genode::Hex(_state->inj_error.value()),
" intr_state=", Genode::Hex(_state->intr_state.value()),
" actv_state=", Genode::Hex(_state->actv_state.value()));
Genode::error("invalid guest state - dead");
exit(-1);
}
void _vmx_mov_crx() { _default_handler(); return; }
void _handle_exit()
{
unsigned const exit = _state->exit_reason;
bool recall_wait = true;
switch (exit) {
case VMX_EXIT_TRIPLE_FAULT: _vmx_triple(); break;
case VMX_EXIT_INIT_SIGNAL: _vmx_default(); break;
case VMX_EXIT_INT_WINDOW: _vmx_irqwin(); break;
case VMX_EXIT_TASK_SWITCH: _vmx_default(); break;
case VMX_EXIT_CPUID: _vmx_default(); break;
case VMX_EXIT_HLT: _vmx_default(); break;
/* we don't support tsc offsetting for now - so let the rdtsc exit */
case VMX_EXIT_RDTSC: _vmx_default(); break;
case VMX_EXIT_RDTSCP: _vmx_default(); break;
case VMX_EXIT_VMCALL: _vmx_default(); break;
case VMX_EXIT_IO_INSTR: _vmx_default(); break;
case VMX_EXIT_RDMSR: _vmx_default(); break;
case VMX_EXIT_WRMSR: _vmx_default(); break;
case VMX_EXIT_ERR_INVALID_GUEST_STATE: _vmx_invalid(); break;
case VMX_EXIT_PAUSE: _vmx_default(); break;
case VMX_EXIT_WBINVD: _vmx_default(); break;
case VMX_EXIT_MOV_CRX: _vmx_mov_crx(); break;
case VMX_EXIT_MOV_DRX: _vmx_default(); break;
case VMX_EXIT_XSETBV: _vmx_default(); break;
case VMX_EXIT_TPR_BELOW_THRESHOLD: _vmx_default(); break;
case VMX_EXIT_EPT_VIOLATION: _vmx_ept<VMX_EXIT_EPT_VIOLATION>(); break;
case RECALL:
recall_wait = Vcpu_handler::_recall_handler();
break;
case VCPU_STARTUP:
_vmx_startup();
_blockade_emt.wakeup();
/* pause - no resume */
break;
default:
Genode::error(__func__, " unknown exit - stop - ",
Genode::Hex(exit));
_vm_state = PAUSED;
return;
}
if (exit == RECALL && !recall_wait) {
_vm_state = RUNNING;
run_vm();
return;
}
/* wait until EMT thread wake's us up */
_sem_handler.down();
/* resume vCPU */
_vm_state = RUNNING;
if (_next_state == RUN)
run_vm();
else
pause_vm(); /* cause pause exit */
}
void run_vm() { _vcpu.run(); }
void pause_vm() { _vcpu.pause(); }
int attach_memory_to_vm(RTGCPHYS const gp_attach_addr,
RTGCUINT vbox_errorcode)
{
return map_memory(_vm_connection, gp_attach_addr, vbox_errorcode);
}
public:
Vcpu_handler_vmx(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
unsigned int cpu_id,
Genode::Vm_connection &vm_connection,
Genode::Allocator &alloc)
:
Vcpu_handler(env, stack_size, location, cpu_id),
_handler(_ep, *this, &Vcpu_handler_vmx::_handle_exit),
_vm_connection(vm_connection),
_vcpu(_vm_connection, alloc, _handler, _exit_config)
{
/* get state of vcpu */
_state = &_vcpu.state();
_vcpu.run();
/* sync with initial startup exception */
_blockade_emt.block();
}
bool hw_save_state(Genode::Vcpu_state *state, VM * pVM, PVMCPU pVCpu) {
return vmx_save_state(state, pVM, pVCpu);
}
bool hw_load_state(Genode::Vcpu_state * state, VM * pVM, PVMCPU pVCpu) {
return vmx_load_state(state, pVM, pVCpu);
}
int vm_exit_requires_instruction_emulation(PCPUMCTX pCtx)
{
switch (_state->exit_reason) {
case VMX_EXIT_HLT:
pCtx->rip++;
return VINF_EM_HALT;
case VMX_EXIT_IO_INSTR:
/* EMHandleRCTmpl.h does not distinguish READ/WRITE rc */
return VINF_IOM_R3_IOPORT_WRITE;
case VMX_EXIT_RDMSR:
return VINF_CPUM_R3_MSR_READ;
case VMX_EXIT_WRMSR:
return VINF_CPUM_R3_MSR_WRITE;
case VMX_EXIT_TPR_BELOW_THRESHOLD:
/* the instruction causing the exit has already been executed */
case RECALL:
return VINF_SUCCESS;
case VMX_EXIT_EPT_VIOLATION:
if (_ept_fault_addr_type == PGMPAGETYPE_MMIO)
/* EMHandleRCTmpl.h does not distinguish READ/WRITE rc */
return VINF_IOM_R3_MMIO_READ_WRITE;
case VMX_EXIT_MOV_DRX:
/* looks complicated in original R0 code -> emulate instead */
return VINF_EM_RAW_EMULATE_INSTR;
default:
return VINF_EM_RAW_EMULATE_INSTR;
}
}
};
#endif /* _VIRTUALBOX__VCPU_VMX_H_ */

View File

@ -1,110 +0,0 @@
/*
* \brief Genode specific VirtualBox SUPLib supplements
* \author Norman Feske
* \author Alexander Boettcher
* \author Christian Helmuth
*/
/*
* Copyright (C) 2013-2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__VMX_H_
#define _VIRTUALBOX__VMX_H_
#define GENODE_READ_SELREG_REQUIRED(REG) \
(pCtx->REG.Sel != state->REG.value().sel) || \
(pCtx->REG.ValidSel != state->REG.value().sel) || \
(pCtx->REG.fFlags != CPUMSELREG_FLAGS_VALID) || \
(pCtx->REG.u32Limit != state->REG.value().limit) || \
(pCtx->REG.u64Base != state->REG.value().base) || \
(pCtx->REG.Attr.u != sel_ar_conv_from_genode(state->REG.value().ar))
#define GENODE_READ_SELREG(REG) \
pCtx->REG.Sel = state->REG.value().sel; \
pCtx->REG.ValidSel = state->REG.value().sel; \
pCtx->REG.fFlags = CPUMSELREG_FLAGS_VALID; \
pCtx->REG.u32Limit = state->REG.value().limit; \
pCtx->REG.u64Base = state->REG.value().base; \
pCtx->REG.Attr.u = sel_ar_conv_from_genode(state->REG.value().ar)
static inline bool vmx_save_state(Genode::Vcpu_state * state, VM * pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
GENODE_READ_SELREG(cs);
GENODE_READ_SELREG(ds);
GENODE_READ_SELREG(es);
GENODE_READ_SELREG(fs);
GENODE_READ_SELREG(gs);
GENODE_READ_SELREG(ss);
if (GENODE_READ_SELREG_REQUIRED(ldtr)) {
GENODE_READ_SELREG(ldtr);
CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_LDTR);
}
if (GENODE_READ_SELREG_REQUIRED(tr)) {
GENODE_READ_SELREG(tr);
CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_TR);
}
return true;
}
#undef GENODE_READ_SELREG_REQUIRED
#undef GENODE_READ_SELREG
enum { VMCS_SEG_UNUSABLE = 0x10000 };
#define GENODE_WRITE_SELREG(REG) \
Assert(pCtx->REG.fFlags & CPUMSELREG_FLAGS_VALID); \
Assert(pCtx->REG.ValidSel == pCtx->REG.Sel); \
state->REG.charge( Segment{ .sel = pCtx->REG.Sel, \
.ar = sel_ar_conv_to_genode(pCtx->REG.Attr.u ? : VMCS_SEG_UNUSABLE), \
.limit = pCtx->REG.u32Limit, \
.base = pCtx->REG.u64Base });
static inline bool vmx_load_state(Genode::Vcpu_state * state, VM * pVM, PVMCPU pVCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
typedef Genode::Vcpu_state::Segment Segment;
GENODE_WRITE_SELREG(es);
GENODE_WRITE_SELREG(ds);
GENODE_WRITE_SELREG(fs);
GENODE_WRITE_SELREG(gs);
GENODE_WRITE_SELREG(cs);
GENODE_WRITE_SELREG(ss);
/* ldtr */
if (pCtx->ldtr.Sel == 0) {
state->ldtr.charge(Segment { .sel = 0,
.ar = sel_ar_conv_to_genode(0x82),
.limit = 0,
.base = 0 });
} else {
state->ldtr.charge(Segment { .sel = pCtx->ldtr.Sel,
.ar = sel_ar_conv_to_genode(pCtx->ldtr.Attr.u),
.limit = pCtx->ldtr.u32Limit,
.base = pCtx->ldtr.u64Base });
}
/* tr */
state->tr.charge(Segment { .sel = pCtx->tr.Sel,
.ar = sel_ar_conv_to_genode(pCtx->tr.Attr.u),
.limit = pCtx->tr.u32Limit,
.base = pCtx->tr.u64Base });
return true;
}
#undef GENODE_WRITE_SELREG
#endif /* _VIRTUALBOX__VMX_H_ */

View File

@ -84,11 +84,6 @@ usb_hid_reconnect
vbox5_genode_usb_hid_raw vbox5_genode_usb_hid_raw
vbox5_ubuntu_16_04_32 vbox5_ubuntu_16_04_32
vbox5_ubuntu_16_04_64 vbox5_ubuntu_16_04_64
vbox5_vm_ubuntu_16_04_32
vbox5_vm_ubuntu_16_04_64
vbox5_vm_win10_64
vbox5_vm_win7_32
vbox5_vm_win7_64
vbox5_win10_64 vbox5_win10_64
vbox5_win7_32 vbox5_win7_32
vbox5_win7_64 vbox5_win7_64