diff --git a/repos/ports/lib/mk/virtualbox5.mk b/repos/ports/lib/mk/virtualbox5.mk deleted file mode 100644 index ad406d8b8e..0000000000 --- a/repos/ports/lib/mk/virtualbox5.mk +++ /dev/null @@ -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 = diff --git a/repos/ports/recipes/pkg/vbox5/README b/repos/ports/recipes/pkg/vbox5/README deleted file mode 100644 index 65e2382a96..0000000000 --- a/repos/ports/recipes/pkg/vbox5/README +++ /dev/null @@ -1,2 +0,0 @@ - - VirtualBox runtime for hosting a large VM in the Sculpt scenario diff --git a/repos/ports/recipes/pkg/vbox5/archives b/repos/ports/recipes/pkg/vbox5/archives deleted file mode 100644 index 275e89bc58..0000000000 --- a/repos/ports/recipes/pkg/vbox5/archives +++ /dev/null @@ -1,10 +0,0 @@ -_/src/vbox5 -_/src/libc -_/src/init -_/src/posix -_/src/zlib -_/src/libiconv -_/src/libyuv -_/src/stdcxx -_/src/vfs -_/src/jpeg diff --git a/repos/ports/recipes/pkg/vbox5/hash b/repos/ports/recipes/pkg/vbox5/hash deleted file mode 100644 index f0e236b8bc..0000000000 --- a/repos/ports/recipes/pkg/vbox5/hash +++ /dev/null @@ -1 +0,0 @@ -2023-08-21 464b0638d93864d8748bfa61e6472f21d6f26788 diff --git a/repos/ports/recipes/pkg/vbox5/runtime b/repos/ports/recipes/pkg/vbox5/runtime deleted file mode 100644 index d9ef6dc178..0000000000 --- a/repos/ports/recipes/pkg/vbox5/runtime +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/ports/recipes/src/vbox5-nova/content.mk b/repos/ports/recipes/src/vbox5-nova/content.mk index ccd65f7321..e4bb050cad 100644 --- a/repos/ports/recipes/src/vbox5-nova/content.mk +++ b/repos/ports/recipes/src/vbox5-nova/content.mk @@ -12,11 +12,8 @@ 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_rem disable_assertions - -disable_virtualbox_rem: $(MIRROR_FROM_REP_DIR) - rm src/virtualbox5/target.mk +# disable debug assertions +content: disable_assertions disable_assertions: $(MIRROR_FROM_REP_DIR) rm lib/mk/virtualbox5-debug.inc diff --git a/repos/ports/recipes/src/vbox5/content.mk b/repos/ports/recipes/src/vbox5/content.mk deleted file mode 100644 index 4cf6d3a45a..0000000000 --- a/repos/ports/recipes/src/vbox5/content.mk +++ /dev/null @@ -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" > $@ - diff --git a/repos/ports/recipes/src/vbox5/hash b/repos/ports/recipes/src/vbox5/hash deleted file mode 100644 index 02b6c093b0..0000000000 --- a/repos/ports/recipes/src/vbox5/hash +++ /dev/null @@ -1 +0,0 @@ -2023-08-21 8bc399184344e122bbf80d7130e42fe63f91343c diff --git a/repos/ports/recipes/src/vbox5/used_apis b/repos/ports/recipes/src/vbox5/used_apis deleted file mode 100644 index ff57e13e44..0000000000 --- a/repos/ports/recipes/src/vbox5/used_apis +++ /dev/null @@ -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 diff --git a/repos/ports/run/vbox5_ubuntu_16_04_32.run b/repos/ports/run/vbox5_ubuntu_16_04_32.run index 1c9a15e0d5..2a57e0da96 100644 --- a/repos/ports/run/vbox5_ubuntu_16_04_32.run +++ b/repos/ports/run/vbox5_ubuntu_16_04_32.run @@ -25,7 +25,4 @@ set use_ps2 1 set use_vms 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 diff --git a/repos/ports/run/vbox5_ubuntu_16_04_64.run b/repos/ports/run/vbox5_ubuntu_16_04_64.run index b893e98f23..7baa7e8e8a 100644 --- a/repos/ports/run/vbox5_ubuntu_16_04_64.run +++ b/repos/ports/run/vbox5_ubuntu_16_04_64.run @@ -25,7 +25,4 @@ set use_ps2 1 set use_vms 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 diff --git a/repos/ports/run/vbox5_vm_ubuntu_16_04_32.run b/repos/ports/run/vbox5_vm_ubuntu_16_04_32.run deleted file mode 100644 index 369cad5067..0000000000 --- a/repos/ports/run/vbox5_vm_ubuntu_16_04_32.run +++ /dev/null @@ -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 diff --git a/repos/ports/run/vbox5_vm_ubuntu_16_04_64.run b/repos/ports/run/vbox5_vm_ubuntu_16_04_64.run deleted file mode 100644 index 843593253a..0000000000 --- a/repos/ports/run/vbox5_vm_ubuntu_16_04_64.run +++ /dev/null @@ -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 diff --git a/repos/ports/run/vbox5_vm_win10_64.run b/repos/ports/run/vbox5_vm_win10_64.run deleted file mode 100644 index 27cf1baeaf..0000000000 --- a/repos/ports/run/vbox5_vm_win10_64.run +++ /dev/null @@ -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 diff --git a/repos/ports/run/vbox5_vm_win7_32.run b/repos/ports/run/vbox5_vm_win7_32.run deleted file mode 100644 index ebbf6ecc2d..0000000000 --- a/repos/ports/run/vbox5_vm_win7_32.run +++ /dev/null @@ -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 diff --git a/repos/ports/run/vbox5_vm_win7_64.run b/repos/ports/run/vbox5_vm_win7_64.run deleted file mode 100644 index 54b70a1c25..0000000000 --- a/repos/ports/run/vbox5_vm_win7_64.run +++ /dev/null @@ -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 diff --git a/repos/ports/run/vbox5_win10_64.run b/repos/ports/run/vbox5_win10_64.run index 6e3a6cf71a..7f406d41b4 100644 --- a/repos/ports/run/vbox5_win10_64.run +++ b/repos/ports/run/vbox5_win10_64.run @@ -25,9 +25,6 @@ set use_ps2 1 set use_vms 1 set use_cpu_load 0 -# use non-generic vbox5 VMM version -set use_vbox5_nova 1 - set use_webcam 1 source ${genode_dir}/repos/ports/run/vbox_win.inc diff --git a/repos/ports/run/vbox5_win7_32.run b/repos/ports/run/vbox5_win7_32.run index b66f5b11f4..d478f18a8c 100644 --- a/repos/ports/run/vbox5_win7_32.run +++ b/repos/ports/run/vbox5_win7_32.run @@ -25,7 +25,4 @@ set use_ps2 1 set use_vms 1 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 diff --git a/repos/ports/run/vbox5_win7_64.run b/repos/ports/run/vbox5_win7_64.run index f6f85b6214..e993df149a 100644 --- a/repos/ports/run/vbox5_win7_64.run +++ b/repos/ports/run/vbox5_win7_64.run @@ -25,7 +25,4 @@ set use_ps2 1 set use_vms 1 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 diff --git a/repos/ports/run/vbox5_win7_64_multiple.run b/repos/ports/run/vbox5_win7_64_multiple.run index 9e36342a36..c03e276cb9 100644 --- a/repos/ports/run/vbox5_win7_64_multiple.run +++ b/repos/ports/run/vbox5_win7_64_multiple.run @@ -37,7 +37,4 @@ set use_vms 6 set affinity_space_width 8 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 diff --git a/repos/ports/run/vbox5_win7_64_raw.run b/repos/ports/run/vbox5_win7_64_raw.run index 29ecf9d7af..cc288b56ec 100644 --- a/repos/ports/run/vbox5_win7_64_raw.run +++ b/repos/ports/run/vbox5_win7_64_raw.run @@ -24,7 +24,4 @@ set use_ps2 1 set use_vms 1 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 diff --git a/repos/ports/run/vbox_win.inc b/repos/ports/run/vbox_win.inc index 52de7ecde1..fe3516c32a 100644 --- a/repos/ports/run/vbox_win.inc +++ b/repos/ports/run/vbox_win.inc @@ -53,8 +53,7 @@ set boot_modules { dynamic_rom } -set virtualbox5_binary "virtualbox5" -if {$use_vbox5_nova} { set virtualbox5_binary "virtualbox5-nova" } +set virtualbox5_binary "virtualbox5-nova" set config_of_app { @@ -83,7 +82,7 @@ set config_of_app { Note: to get network access in the VM, the virtual network adapter needs to be enabled in the .vbox file (disabled by default) --> - + diff --git a/repos/ports/run/virtualbox.run b/repos/ports/run/virtualbox.run index 0ad3d5b678..9749b0ec35 100644 --- a/repos/ports/run/virtualbox.run +++ b/repos/ports/run/virtualbox.run @@ -1,10 +1,10 @@ +assert_spec nova + set use_net 0 set use_usb_qemu 0 set use_serial 1 set use_top 1 -set use_vbox5_nova 0 - # use_gui starts two VMs set use_gui 0 @@ -15,11 +15,7 @@ set build_components { append build_components virtualbox5 -set virtualbox_binary "virtualbox5" - -if {$use_vbox5_nova} { - set virtualbox_binary "virtualbox5-nova" -} +set virtualbox_binary "virtualbox5-nova" create_boot_directory diff --git a/repos/ports/run/vm_stress_vbox5-debian32.run b/repos/ports/run/vm_stress_vbox5-debian32.run index 74230769d0..ba41d5d9e1 100644 --- a/repos/ports/run/vm_stress_vbox5-debian32.run +++ b/repos/ports/run/vm_stress_vbox5-debian32.run @@ -31,27 +31,6 @@ set match_guest_log "\[init -\> log_terminal\]" set match_boot_string "\[init -\> vbox.*\].*Using VMX virtualization extension" #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 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/vmm_vm_stress.inc kill_spawned [output_spawn_id] -} # # Dump aggregated output of the several runs above diff --git a/repos/ports/run/vm_stress_vbox5-debian64.run b/repos/ports/run/vm_stress_vbox5-debian64.run index f29da65ad9..077c668cc2 100644 --- a/repos/ports/run/vm_stress_vbox5-debian64.run +++ b/repos/ports/run/vm_stress_vbox5-debian64.run @@ -31,27 +31,6 @@ set match_guest_log "\[init -\> log_terminal\]" set match_boot_string "\[init -\> vbox.*\].*Using VMX virtualization extension" #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 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/vmm_vm_stress.inc kill_spawned [output_spawn_id] -} # # Dump aggregated output of the several runs above diff --git a/repos/ports/src/virtualbox5/generic/sup.cc b/repos/ports/src/virtualbox5/generic/sup.cc deleted file mode 100644 index b54d7548f0..0000000000 --- a/repos/ports/src/virtualbox5/generic/sup.cc +++ /dev/null @@ -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 -#include - -/* Genode/Virtualbox includes */ -#include "sup.h" -#include "vmm.h" - -/* VirtualBox includes */ -#include -#include -#include - - -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(sem); - return rc; -} - - -int SUPSemEventMultiWaitNoResume(PSUPDRVSESSION, SUPSEMEVENTMULTI event, - uint32_t ms) -{ - RTSEMEVENTMULTI const rtevent = reinterpret_cast(event); - return RTSemEventMultiWait(rtevent, ms); -} - -int SUPSemEventMultiSignal(PSUPDRVSESSION, SUPSEMEVENTMULTI event) { - return RTSemEventMultiSignal(reinterpret_cast(event)); } - -int SUPSemEventMultiReset(PSUPDRVSESSION, SUPSEMEVENTMULTI event) { - return RTSemEventMultiReset(reinterpret_cast(event)); } - -int SUPSemEventMultiClose(PSUPDRVSESSION, SUPSEMEVENTMULTI event) { - return RTSemEventMultiDestroy(reinterpret_cast(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(*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(); - 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(pVMR0); - pVM->aCpus[idCpu].hNativeThreadR0 = RTThreadNativeSelf(); -} - - -HRESULT genode_check_memory_config(ComObjPtr, - 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; -} diff --git a/repos/ports/src/virtualbox5/generic/sup_vmm.cc b/repos/ports/src/virtualbox5/generic/sup_vmm.cc deleted file mode 100644 index d73d2c3d93..0000000000 --- a/repos/ports/src/virtualbox5/generic/sup_vmm.cc +++ /dev/null @@ -1,1270 +0,0 @@ -/* - * \brief Genode specific VirtualBox SUPLib supplements - * \author Alexander Boettcher - * \author Norman Feske - * \author Christian Helmuth - */ - -/* - * Copyright (C) 2006-2013 Oracle Corporation - * Copyright (C) 2013-2021 Genode Labs GmbH - * - * This file is distributed under the terms of the GNU General Public License - * version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Genode's VirtualBox includes */ -#include "EMInternal.h" /* enable access to em.s.* */ -#include "vmm.h" -#include "vcpu.h" -#include "vcpu_svm.h" -#include "vcpu_vmx.h" - -/* libc memory allocator */ -#include - -/* Genode libc pthread binding */ -#include - -/* libc */ -#include -#include /* sched_yield */ - -#include "mm.h" - -/* VirtualBox includes */ -#include -#include - -extern "C" void PGMUnmapMemoryGenode(void *, RTGCPHYS, ::size_t); -extern "C" void PGMFlushVMMemory(); - -enum { VERBOSE_PGM = false }; - -/* - * Tracking required to fulfill VMM allocation requests of VM memory - */ -enum { - CHUNKID_PAGE_START = 1, - CHUNKID_PAGE_END = 2, - CHUNKID_START = CHUNKID_PAGE_END + 1, - - ONE_PAGE_SIZE = 4096, - PAGES_SUPERPAGE = GMM_CHUNK_SIZE / ONE_PAGE_SIZE, - HANDY_PAGES = PAGES_SUPERPAGE * (CHUNKID_PAGE_END - CHUNKID_PAGE_START + 1), - - MAX_VM_MEMORY = 16ULL * 1024 * 1024 * 1024, /* 16 Gb */ - MAX_CHUNK_IDS = MAX_VM_MEMORY / GMM_CHUNK_SIZE, -}; - -typedef Genode::Bit_allocator Page_ids; -typedef Genode::Bit_array Free_ids; - -class Chunk_ids: public Genode::Bit_allocator -{ - public: - - void reserve(Genode::addr_t bit_start, size_t const num) { - _reserve(bit_start, num); }; -}; - -static Page_ids page_ids; -static Chunk_ids chunk_ids; - -struct Region : Genode::List::Element -{ - Genode::uint64_t vmm_local; - Genode::uint64_t size; - Genode::Ram_dataspace_capability cap; - - Region(uint64_t gp, uint64_t gs, Genode::Ram_dataspace_capability c) - : vmm_local(gp), size(gs), cap(c) { } - - bool contains(Genode::uint64_t p) - { - return (vmm_local <= p) && (p < vmm_local + size); - } -}; - -static Genode::List regions; - -static Genode::Allocator & heap() -{ - static Genode::Heap heap(genode_env().ram(), genode_env().rm()); - return heap; -} - - -static Sub_rm_connection &vm_memory(Genode::uint64_t vm_size = 0) -{ - /* memory used by the VM in any order as the VMM asks for allocations */ - static Sub_rm_connection vm_memory(genode_env(), vm_size); - - if (!vm_size) - return vm_memory; - - using namespace Genode; - - /* create iterator for aligned allocation and attachment of memory */ - addr_t const vmm_local = vm_memory.local_addr(0); - Flexpage_iterator fli(vmm_local, vm_size, 0, ~0UL, 0); - - /* start iteration */ - Flexpage memory = fli.page(); - while (memory.valid()) { - addr_t const memory_size = 1UL << memory.log2_order; - addr_t allocated = 0; - - addr_t alloc_size = 128 * 1024 * 1024; - if (alloc_size > memory_size) - alloc_size = memory_size; - - while (allocated < memory_size) { - Ram_dataspace_capability ds = genode_env().ram().alloc(alloc_size); - - addr_t to = vm_memory.attach_rwx(ds, memory.addr + allocated - vmm_local, - alloc_size); - Assert(to == vm_memory.local_addr(memory.addr + allocated - vmm_local)); - allocated += alloc_size; - - regions.insert(new (heap()) Region(to, alloc_size, ds)); - - if (memory_size - allocated < alloc_size) - alloc_size = memory_size - allocated; - } - - /* request next aligned memory range to be allocated and attached */ - memory = fli.page(); - } - - /* reserve chunkids which are special or unused */ - chunk_ids.reserve(0, CHUNKID_START); - addr_t const unused_id = CHUNKID_START + vm_size / GMM_CHUNK_SIZE; - addr_t const unused_count = MAX_CHUNK_IDS - unused_id - 1; - chunk_ids.reserve(unused_id, unused_count); - - return vm_memory; -} - - -static Genode::Vm_connection &vm_connection(long prio = 0) -{ - static Genode::Vm_connection vm_session(genode_env(), "VBox vCPUs", prio); - return vm_session; -} - - -/* - * VCPU handling - */ - -static Genode::List &vcpu_handler_list() -{ - static Genode::List _inst; - return _inst; -} - - -static Vcpu_handler *lookup_vcpu_handler(unsigned int cpu_id) -{ - for (Vcpu_handler *vcpu_handler = vcpu_handler_list().first(); - vcpu_handler; - vcpu_handler = vcpu_handler->next()) - if (vcpu_handler->cpu_id() == cpu_id) - return vcpu_handler; - - return 0; -} - - -HRESULT genode_setup_machine(ComObjPtr machine) -{ - ULONG memory_vbox; - HRESULT rc = machine->COMGETTER(MemorySize)(&memory_vbox); - if (FAILED(rc)) - return rc; - - /* - * Extra memory because of: - * - first chunkid (0) can't be used (VBox don't like chunkid 0) - * - second chunkid (1..2) is reserved for handy pages allocation - * - another chunkid is used additional for handy pages but as large page - */ - size_t const vmm_memory = 1024ULL * 1024 * (memory_vbox + 16) + - (CHUNKID_START + 1) * GMM_CHUNK_SIZE; - HRESULT ret = genode_check_memory_config(machine, vmm_memory); - if (ret == VINF_SUCCESS) - vm_memory(vmm_memory); - - return ret; -}; - - -/* Genode specific function */ - -Genode::Xml_node platform_rom() -{ - static Genode::Attached_rom_dataspace const platform(genode_env(), - "platform_info"); - return platform.xml().sub_node("hardware"); -} - - -void SUPR3QueryHWACCLonGenodeSupport(VM * pVM) -{ - try { - Genode::Xml_node const features = platform_rom().sub_node("features"); - pVM->hm.s.svm.fSupported = features.attribute_value("svm", false); - pVM->hm.s.vmx.fSupported = features.attribute_value("vmx", false); - - if (pVM->hm.s.svm.fSupported || pVM->hm.s.vmx.fSupported) { - Genode::log("Using ", pVM->hm.s.svm.fSupported ? "SVM" : "VMX", - " virtualization extension."); - return; - } - } catch (...) { /* if we get an exception let hardware support off */ } - - Genode::warning("No virtualization hardware acceleration available"); -} - - -/* VirtualBox SUPLib interface */ -int SUPR3QueryVTxSupported(void) { return VINF_SUCCESS; } - - -int SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu) -{ - switch (uOperation) { - case SUP_VMMR0_DO_HM_RUN: - Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu); - Assert(vcpu_handler); - return vcpu_handler->run_hw(pVMR0); - } - return VERR_INTERNAL_ERROR; -} - -int SUPR3PageAllocEx(::size_t cPages, uint32_t fFlags, void **ppvPages, - PRTR0PTR pR0Ptr, PSUPPAGE paPages) -{ - Assert(ppvPages); - Assert(!fFlags); - - using Genode::Attached_ram_dataspace; - Attached_ram_dataspace * ds = new (heap()) Attached_ram_dataspace(genode_env().ram(), - genode_env().rm(), - cPages * ONE_PAGE_SIZE); - - Genode::addr_t const vmm_local = reinterpret_cast(ds->local_addr()); - - regions.insert(new (heap()) Region(vmm_local, cPages * ONE_PAGE_SIZE, ds->cap())); - - *ppvPages = ds->local_addr(); - if (pR0Ptr) - *pR0Ptr = vmm_local; - - if (!paPages) - return VINF_SUCCESS; - - for (unsigned iPage = 0; iPage < cPages; iPage++) - { - paPages[iPage].uReserved = 0; - paPages[iPage].Phys = vmm_local + iPage * ONE_PAGE_SIZE; - } - - return VINF_SUCCESS; -} - -enum { MAX_TRACKING = 4 }; -static struct { - Free_ids free; - unsigned freed; - unsigned chunkid; -} track_free[MAX_TRACKING]; - -static void partial_free_large_page(unsigned chunkid, unsigned page_id) -{ - unsigned pos = 0; - - /* lookup if already exist */ - for (; pos < MAX_TRACKING; pos++) - { - if (track_free[pos].chunkid == chunkid) - break; - } - - /* if not exist find free place */ - if (pos >= MAX_TRACKING) { - for (int i = 0; i < MAX_TRACKING; i++) { - if (track_free[i].chunkid) - continue; - - track_free[i].chunkid = chunkid; - track_free[i].freed = 0; - pos = i; - break; - } - - /* too many chunkids in use ? */ - Assert (pos < MAX_TRACKING); - if (pos >= MAX_TRACKING) - return; - } - - try { - /* mark as in use */ - track_free[pos].free.set(page_id, 1); - track_free[pos].freed += 1; - - if (track_free[pos].freed >= 512) { - /* slow ? optimize ? XXX */ - for (unsigned i = 0; i < 512; i++) { - if (!track_free[pos].free.get(i, 1)) - throw 1; - track_free[pos].free.clear(i, 1); - } - - track_free[pos].chunkid = 0; - track_free[pos].freed = 0; - - chunk_ids.free(chunkid); - } - } catch (...) { - Genode::error(__func__," ", __LINE__, " allocation failed ", pos, ":", - chunkid, ":", page_id); - throw; - } -} - -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); - - GVMMCREATEVMREQ &req = reinterpret_cast(*pReqHdr); - SUPR3QueryHWACCLonGenodeSupport(reinterpret_cast(req.pVMR3)); - - return VINF_SUCCESS; - } - case VMMR0_DO_GVMM_REGISTER_VMCPU: - genode_VMMR0_DO_GVMM_REGISTER_VMCPU(pVMR0, idCpu); - return VINF_SUCCESS; - - case VMMR0_DO_GVMM_SCHED_HALT: - { - uint64_t const u64NowGip = RTTimeNanoTS(); - uint64_t const ns_diff = u64Arg > u64NowGip ? u64Arg - u64NowGip : 0; - - if (!ns_diff) - return VINF_SUCCESS; - - using namespace Genode; - - if (ns_diff > RT_NS_1SEC) - warning(" more than 1 sec vcpu halt ", ns_diff, " ns"); - - ::Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu); - Assert(vcpu_handler); - vcpu_handler->halt(ns_diff); - - return VINF_SUCCESS; - } - - case VMMR0_DO_GVMM_SCHED_WAKE_UP: - { - Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu); - Assert(vcpu_handler); - - vcpu_handler->wake_up(); - return VINF_SUCCESS; - } - - /* called by 'vmR3HaltGlobal1Halt' */ - case VMMR0_DO_GVMM_SCHED_POLL: - return VINF_SUCCESS; - - case VMMR0_DO_VMMR0_INIT: - return VINF_SUCCESS; - - case VMMR0_DO_GVMM_DESTROY_VM: - case VMMR0_DO_VMMR0_TERM: - case VMMR0_DO_HM_SETUP_VM: - return VINF_SUCCESS; - - case VMMR0_DO_HM_ENABLE: - return VINF_SUCCESS; - - case VMMR0_DO_GVMM_SCHED_POKE: - { - PVM pVM = reinterpret_cast(pVMR0); - Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu); - Assert(vcpu_handler); - if (vcpu_handler) - vcpu_handler->recall(pVM); - return VINF_SUCCESS; - } - case VMMR0_DO_GMM_ALLOCATE_PAGES: - { - /* - * VMM is asking for some host virtual memory pages without - * allocating the backing store actually. The backing store allocation - * takes place via VMMR0_DO_GMM_MAP_UNMAP_CHUNK. The assignment of the - * guest addresses is known at this point. - */ - - static_assert(PGM_HANDY_PAGES * ONE_PAGE_SIZE == GMM_CHUNK_SIZE, - "Don't do that - you're going to waste tons of memory"); - Assert(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC); - - /* XXX VMM/VMMR0/GMMR0.cpp check there XXX */ - - PGMMALLOCATEPAGESREQ req = reinterpret_cast(pReqHdr); - - for (unsigned i = 0; i < req->cPages; i++) { - RTHCPHYS guest_addr = req->aPages[i].HCPhysGCPhys; - unsigned long page_idx = 0; - unsigned long chunk_id = 0; - - try { - page_idx = page_ids.alloc(); - chunk_id = CHUNKID_PAGE_START + page_idx / PAGES_SUPERPAGE; - } catch (...) { - Genode::error(__func__," ", __LINE__, " allocation failed"); - throw; - } - - Assert (page_idx <= GMM_PAGEID_IDX_MASK); - - req->aPages[i].idPage = (chunk_id << GMM_CHUNKID_SHIFT) | page_idx; - req->aPages[i].HCPhysGCPhys = vm_memory().local_addr((chunk_id * GMM_CHUNK_SIZE) | (page_idx * ONE_PAGE_SIZE)); - Assert(vm_memory().contains(req->aPages[i].HCPhysGCPhys)); - - #if 0 - Genode::log("cPages ", Genode::Hex(req->cPages), " " - "chunkID=", req->aPages[i].idPage >> GMM_CHUNKID_SHIFT, " " - "pageIDX=", req->aPages[i].idPage & GMM_PAGEID_IDX_MASK, " " - "idPage=", Genode::Hex(req->aPages[i].idPage), " " - "GCPhys=", Genode::Hex(guest_addr), " " - "HCPhys=", Genode::Hex(req->aPages[i].HCPhysGCPhys), " " - "(", Genode::Hex(chunk_id * GMM_CHUNK_SIZE), " " - "| ", Genode::Hex(page_idx * ONE_PAGE_SIZE), ") pageidx=", page_idx, " " - "start_vm=", vm_memory().local_addr(0)); - #endif - - } - - return VINF_SUCCESS; - } - case VMMR0_DO_GMM_MAP_UNMAP_CHUNK: - { - PGMMMAPUNMAPCHUNKREQ req = reinterpret_cast(pReqHdr); - - Assert(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC); - Assert(req->idChunkUnmap == NIL_GMM_CHUNKID); - Assert(req->idChunkMap != NIL_GMM_CHUNKID); - - Genode::addr_t local_addr_offset = (uintptr_t)req->idChunkMap << GMM_CHUNK_SHIFT; - Genode::addr_t to = vm_memory().local_addr(local_addr_offset); - - req->pvR3 = reinterpret_cast(to); - - return VINF_SUCCESS; - } - case VMMR0_DO_GMM_QUERY_MEM_STATS: - { - PGMMMEMSTATSREQ req = reinterpret_cast(pReqHdr); - req->cAllocPages = 0; - req->cMaxPages = 0; - req->cBalloonedPages = 0; - return VINF_SUCCESS; - } - case VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES: - { - /* - * VMM is asking for some host virtual memory pages without - * allocating the backing store actually. The backing store allocation - * takes place via VMMR0_DO_GMM_MAP_UNMAP_CHUNK. The assignment of the - * guest addresses to these host pages is unknown at this point. - */ - - PVM pVM = reinterpret_cast(pVMR0); - - /* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - start */ - uint32_t iFirst = pVM->pgm.s.cHandyPages; - uint32_t cPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages) - iFirst; - uint32_t cPagesToUpdate = cPages; - uint32_t cPagesToAlloc = cPages; - /* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - end */ - - /* based on GMMR0AllocateHandyPages in VMM/VMMR0/GMMR0.cpp - start */ - unsigned iPage = 0; - for (; iPage < cPagesToUpdate; iPage++) - { - AssertMsgReturn( ( pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys <= GMM_GCPHYS_LAST - && !(pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys & PAGE_OFFSET_MASK)) - || pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == NIL_RTHCPHYS - || pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == GMM_GCPHYS_UNSHAREABLE, - ("#%#x: %RHp\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys), - VERR_INVALID_PARAMETER); - AssertMsgReturn( pVM->pgm.s.aHandyPages[iFirst + iPage].idPage <= GMM_PAGEID_LAST - /*|| pVM->pgm.s.aHandyPages[iFirst + iPage].idPage == NIL_GMM_PAGEID*/, - ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idPage), VERR_INVALID_PARAMETER); - AssertMsgReturn( pVM->pgm.s.aHandyPages[iFirst + iPage].idPage <= GMM_PAGEID_LAST - /*|| pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage == NIL_GMM_PAGEID*/, - ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage), VERR_INVALID_PARAMETER); - } - - for (; iPage < cPagesToAlloc; iPage++) - { - AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys == NIL_RTHCPHYS, ("#%#x: %RHp\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].HCPhysGCPhys), VERR_INVALID_PARAMETER); - AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].idPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idPage), VERR_INVALID_PARAMETER); - AssertMsgReturn(pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iFirst + iPage, pVM->pgm.s.aHandyPages[iFirst + iPage].idSharedPage), VERR_INVALID_PARAMETER); - } - - Genode::uint64_t chunkid = 0; - - try { - chunkid = chunk_ids.alloc(); - } catch (...) { - Genode::error(__func__," ", __LINE__, " allocation failed"); - throw; - } - - if (cPagesToAlloc != GMM_CHUNK_SIZE / ONE_PAGE_SIZE) - Genode::log("special chunkid=", chunkid, " " - "toupdate=", cPagesToUpdate, " " - "toalloc=", cPagesToAlloc, " " - "virt=", Genode::Hex(vm_memory().local_addr(chunkid << GMM_CHUNK_SHIFT))); - - for (unsigned i = 0; i < cPagesToUpdate; i++) { - if (pVM->pgm.s.aHandyPages[iFirst + i].idPage != NIL_GMM_PAGEID) - { - pVM->pgm.s.aHandyPages[iFirst + i].idPage = NIL_GMM_PAGEID; - pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys = NIL_RTHCPHYS; - } - - if (pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage != NIL_GMM_PAGEID) - AssertMsgReturn(false, ("%s %u - not implemented", __func__, __LINE__), VERR_GENERAL_FAILURE); - } - - for (unsigned i = 0; i < cPagesToAlloc; i++) - { - Assert(pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys == NIL_RTHCPHYS); - Assert(pVM->pgm.s.aHandyPages[iFirst + i].idPage == NIL_GMM_PAGEID); - Assert(pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage == NIL_GMM_PAGEID); - } - - for (unsigned i = 0; i < cPagesToUpdate; i++) { - unsigned reverse = i; //cPagesToUpdate - 1 - i; - Assert (pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys == NIL_RTHCPHYS); - { - pVM->pgm.s.aHandyPages[iFirst + i].idPage = (chunkid << GMM_CHUNKID_SHIFT) | (iFirst + reverse); - pVM->pgm.s.aHandyPages[iFirst + i].idSharedPage = NIL_GMM_PAGEID; - - pVM->pgm.s.aHandyPages[iFirst + i].HCPhysGCPhys = vm_memory().local_addr((chunkid << GMM_CHUNK_SHIFT) | ((iFirst + reverse) * ONE_PAGE_SIZE)); - } - } - /* based on GMMR0AllocateHandyPages in VMM/VMMR0/GMMR0.cpp - end */ - - /* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - start */ - pVM->pgm.s.cHandyPages = RT_ELEMENTS(pVM->pgm.s.aHandyPages); - - for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++) - { - Assert(pVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID); - Assert(pVM->pgm.s.aHandyPages[i].idPage <= GMM_PAGEID_LAST); - Assert(pVM->pgm.s.aHandyPages[i].idSharedPage == NIL_GMM_PAGEID); - Assert(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys != NIL_RTHCPHYS); - Assert(!(pVM->pgm.s.aHandyPages[i].HCPhysGCPhys & ~X86_PTE_PAE_PG_MASK)); - } - /* based on PGMR0PhysAllocateHandyPages() in VMM/VMMR0/PGMR0.cpp - end */ - - return VINF_SUCCESS; - } - case VMMR0_DO_PGM_ALLOCATE_LARGE_HANDY_PAGE: - { - /* - * VMM is asking for some host large virtual memory pages without - * allocating the backing store actually. The backing store allocation - * takes place via VMMR0_DO_GMM_MAP_UNMAP_CHUNK. The assignment of the - * guest addresses to these host pages is unknown at this point. - */ - - PVM pVM = reinterpret_cast(pVMR0); - - Assert(pVM); - Assert(pVM->pgm.s.cLargeHandyPages == 0); - - try { - Genode::uint64_t chunkid = chunk_ids.alloc(); - - pVM->pgm.s.aLargeHandyPage[0].idPage = (chunkid << GMM_CHUNKID_SHIFT); - pVM->pgm.s.aLargeHandyPage[0].HCPhysGCPhys = vm_memory().local_addr(chunkid << GMM_CHUNK_SHIFT); - - pVM->pgm.s.cLargeHandyPages = 1; - } catch (...) { - Genode::error(__func__," ", __LINE__, " allocation failed"); - throw; - } - - return VINF_SUCCESS; - } - case VMMR0_DO_GMM_BALLOONED_PAGES: - case VMMR0_DO_GMM_RESET_SHARED_MODULES: - case VMMR0_DO_PGM_FLUSH_HANDY_PAGES: - { - PVM const pVM = reinterpret_cast(pVMR0); - PVMCPU const pVCpu = &pVM->aCpus[idCpu]; - - /* if not in VM shutdown - complain - bug ahead */ - if (pVCpu->em.s.enmState != EMSTATE_TERMINATING) - Genode::error("unexpected call of type ", uOperation, ", " - "em state=", (int)pVCpu->em.s.enmState); - - return VINF_SUCCESS; - } - case VMMR0_DO_GMM_FREE_PAGES: - { - if (u64Arg) - return VERR_INVALID_PARAMETER; - - PVM pVM = reinterpret_cast(pVMR0); - PGMMFREEPAGESREQ pReq = reinterpret_cast(pReqHdr); - - AssertPtrReturn(pVM, VERR_INVALID_POINTER); - AssertPtrReturn(pReq, VERR_INVALID_POINTER); - AssertMsgReturn(pReq->Hdr.cbReq >= RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[0]), - ("%#x < %#x\n", pReq->Hdr.cbReq, RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[0])), - VERR_INVALID_PARAMETER); - AssertMsgReturn(pReq->Hdr.cbReq == RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[pReq->cPages]), - ("%#x != %#x\n", pReq->Hdr.cbReq, RT_UOFFSETOF(GMMFREEPAGESREQ, aPages[pReq->cPages])), - VERR_INVALID_PARAMETER); - - uint32_t cPages = pReq->cPages; - PGMMFREEPAGEDESC paPages = &pReq->aPages[0]; - GMMACCOUNT enmAccount = pReq->enmAccount; - - AssertPtrReturn(paPages, VERR_INVALID_PARAMETER); - AssertMsgReturn(enmAccount > GMMACCOUNT_INVALID && enmAccount < GMMACCOUNT_END, ("%d\n", enmAccount), VERR_INVALID_PARAMETER); - AssertMsgReturn(cPages > 0 && cPages < RT_BIT(32 - PAGE_SHIFT), ("%#x\n", cPages), VERR_INVALID_PARAMETER); - - for (unsigned iPage = 0; iPage < cPages; iPage++) - AssertMsgReturn( paPages[iPage].idPage <= GMM_PAGEID_LAST - /*|| paPages[iPage].idPage == NIL_GMM_PAGEID*/, - ("#%#x: %#x\n", iPage, paPages[iPage].idPage), VERR_INVALID_PARAMETER); - - for (uint32_t last_chunk = ~0U, iPage = 0; iPage < cPages; iPage++) - { - uint32_t const idPage = paPages[iPage].idPage; - uint32_t const page_idx = idPage & GMM_PAGEID_IDX_MASK; - uint32_t const chunkid = idPage >> GMM_CHUNKID_SHIFT; - - if (last_chunk != chunkid) { - /* revoke mapping from guest VM */ - PGMUnmapMemoryGenode(nullptr, (0UL + chunkid) << GMM_CHUNK_SHIFT, GMM_CHUNK_SIZE); - - last_chunk = chunkid; - } - - if (CHUNKID_PAGE_START <= chunkid && chunkid <= CHUNKID_PAGE_END) { - try { - page_ids.free((chunkid - CHUNKID_PAGE_START) * PAGES_SUPERPAGE + page_idx); - } catch (...) { - Genode::error(__func__," ", __LINE__, " clearing failed"); - throw; - } - } - - partial_free_large_page(chunkid, page_idx); - - paPages[iPage].idPage = NIL_GMM_PAGEID; - } - - return VINF_SUCCESS; - } - case VMMR0_DO_GMM_INITIAL_RESERVATION: - return VINF_SUCCESS; - case VMMR0_DO_GMM_UPDATE_RESERVATION: - return VINF_SUCCESS; - default: - Genode::error("SUPR3CallVMMR0Ex: unhandled uOperation ", uOperation, - " ", (int)VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES, " ", - (int)VMMR0_DO_GMM_QUERY_MEM_STATS); - return VERR_GENERAL_FAILURE; - } -} - - -/** - * Various support stuff. - */ -uint64_t genode_cpu_hz() -{ - static uint64_t cpu_freq = 0; - - if (!cpu_freq) { - try { - platform_rom().with_optional_sub_node("tsc", [&] (Genode::Xml_node const &tsc) { - cpu_freq = tsc.attribute_value("freq_khz", cpu_freq); }); - cpu_freq *= 1000ULL; - } catch (...) { } - - if (cpu_freq == 0) { - Genode::error("could not read out CPU frequency"); - Genode::sleep_forever(); - } - } - - return cpu_freq; -} - - -void PGMUnmapMemoryGenode(void *, RTGCPHYS guest_phys, ::size_t size) -{ - vm_connection().detach(guest_phys, size); -} - -extern "C" void PGMFlushVMMemory() -{ - /* XXX PGMUnmapMemoryGenode on vm_session does not flush all caps */ - PGMUnmapMemoryGenode(nullptr, 0, MAX_VM_MEMORY); -} - - -extern "C" int sched_yield(void) -{ - static unsigned long counter = 0; - - if (++counter % 50000 == 0) - Genode::warning(__func__, " called ", counter, " times"); - - return -1; -} - - -bool create_emt_vcpu(pthread_t * thread, ::size_t stack_size, - void *(*start_routine)(void *), void *arg, - Genode::Cpu_connection * cpu_connection, - Genode::Affinity::Location location, - unsigned int cpu_id, const char * name, long prio) -{ - Genode::Xml_node const features = platform_rom().sub_node("features"); - bool const svm = features.attribute_value("svm", false); - bool const vmx = features.attribute_value("vmx", false); - - if (!svm && !vmx) - return false; - - Vcpu_handler *vcpu_handler = 0; - - if (vmx) - vcpu_handler = new (heap()) Vcpu_handler_vmx(genode_env(), - stack_size, - location, - cpu_id, - vm_connection(prio), - heap()); - - if (svm) - vcpu_handler = new (heap()) Vcpu_handler_svm(genode_env(), - stack_size, - location, - cpu_id, - vm_connection(prio), - heap()); - - vcpu_handler_list().insert(vcpu_handler); - - Libc::pthread_create_from_session(thread, start_routine, arg, - stack_size, name, cpu_connection, location); - - return true; -} - -static int _map_memory(Genode::Vm_connection &vm_session, - RTGCPHYS const GCPhys, - RTHCPHYS const vmm_local, - size_t const mapping_size, - bool writeable) -{ - for (Region *region = regions.first(); region; region = region->next()) - { - if (!region->contains(vmm_local)) - continue; - - bool retry = false; - - do { - Genode::addr_t const offset = vmm_local - region->vmm_local; - - try { - vm_session.with_upgrade([&]() { - vm_session.attach(region->cap, GCPhys, - { .offset = offset, - .size = mapping_size, - .executable = true, - .writeable = writeable }); - }); - } catch (Genode::Vm_session::Region_conflict) { - /* XXX PGMUnmapMemoryGenode on vm_session does not flush caps */ - vm_session.detach(GCPhys, mapping_size); - if (retry) { - Genode::log("region conflict - ", Genode::Hex(GCPhys), - " ", Genode::Hex(mapping_size), " vmm_local=", - Genode::Hex(vmm_local), " ", region->cap, - " region=", Genode::Hex(region->vmm_local), - "+", Genode::Hex(region->size)); - - size_t detach_size = mapping_size; - while (detach_size) { - size_t const size = 4096; - vm_session.detach(GCPhys + (mapping_size - detach_size), size); - detach_size -= detach_size > size ? size : detach_size; - } - - return VERR_PGM_DYNMAP_FAILED; - } - - if (!retry) { - retry = true; - continue; - } - } - retry = false; - } while (retry); - - return VINF_SUCCESS; - } - Genode::error(" no mapping ?"); - return VERR_PGM_DYNMAP_FAILED; -} - -class Pgm_guard -{ - private: - VM &_vm; - - public: - Pgm_guard(VM &vm) : _vm(vm) { pgmLock(&_vm); } - ~Pgm_guard() { pgmUnlock(&_vm); } -}; - -#include "PGMInline.h" - -Genode::Vm_connection::Exit_config const Vcpu_handler::_exit_config { /* ... */ }; - -int Vcpu_handler::map_memory(Genode::Vm_connection &vm_session, - RTGCPHYS const GCPhys, RTGCUINT vbox_fault_reason) -{ - _ept_fault_addr_type = PGMPAGETYPE_INVALID; - - PPGMRAMRANGE const pRam = pgmPhysGetRangeAtOrAbove(_vm, GCPhys); - if (!pRam) - return VERR_PGM_DYNMAP_FAILED; - - RTGCPHYS off = GCPhys - pRam->GCPhys; - if (off >= pRam->cb) - return VERR_PGM_DYNMAP_FAILED; - - unsigned iPage = off >> PAGE_SHIFT; - PPGMPAGE pPage = &pRam->aPages[iPage]; - - _ept_fault_addr_type = PGM_PAGE_GET_TYPE(pPage); - - /* - * If page is not allocated (== zero page) and no MMIO or active page, allocate and map it - * immediately. Important do not do this if A20 gate is disabled, A20 gate - * is handled by IEM/REM in this case. - */ - if (PGM_PAGE_IS_ZERO(pPage) - && !PGM_PAGE_IS_ALLOCATED(pPage) - && !PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage) - && !PGM_PAGE_IS_SPECIAL_ALIAS_MMIO(pPage) - && PGM_A20_IS_ENABLED(_vcpu)) - { - Pgm_guard guard(*_vm); - pgmPhysPageMakeWritable(_vm, pPage, GCPhys); - } - - if (PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage) || - PGM_PAGE_IS_SPECIAL_ALIAS_MMIO(pPage) || - PGM_PAGE_IS_ZERO(pPage)) { - - if (PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_MMIO && - !PGM_PAGE_IS_ZERO(pPage)) { - - Genode::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " ", - PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage), " ", - PGM_PAGE_IS_SPECIAL_ALIAS_MMIO(pPage), " ", - PGM_PAGE_IS_ZERO(pPage), " " - " vbox_fault_reason=", Genode::Hex(vbox_fault_reason)); - Genode::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " " - "host=", Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), " " - "type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " " - "writeable=true " - "state=", Genode::Hex(PGM_PAGE_GET_STATE(pPage))); - } - return VERR_PGM_DYNMAP_FAILED; - } - - if (!PGM_PAGE_IS_ALLOCATED(pPage)) - Genode::log("unknown page state ", Genode::Hex(PGM_PAGE_GET_STATE(pPage)), - " GCPhys=", Genode::Hex(GCPhys)); - Assert(PGM_PAGE_IS_ALLOCATED(pPage)); - - if (PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_RAM && - PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_MMIO2 && - PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_ROM) - { - if (VERBOSE_PGM) - Genode::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " " - "vbox_fault_reason=", Genode::Hex(vbox_fault_reason), " " - "host=", Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), " " - "type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " " - "state=", Genode::Hex(PGM_PAGE_GET_STATE(pPage))); - return VERR_PGM_DYNMAP_FAILED; - } - - Assert(!PGM_PAGE_IS_ZERO(pPage)); - - /* write fault on a ROM region */ - if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM && - vbox_fault_reason & VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE) { - Genode::warning(__func__, " - write fault on ROM region!? gp=", - Genode::Hex(GCPhys)); - return VERR_PGM_DYNMAP_FAILED; - } - - /* nothing should be mapped - otherwise we get endless overmap loops */ - Assert(!(vbox_fault_reason & VMX_EXIT_QUALIFICATION_EPT_ENTRY_PRESENT)); - - bool const writeable = PGM_PAGE_GET_TYPE(pPage) != PGMPAGETYPE_ROM; - - PPGMPHYSHANDLER handler = pgmHandlerPhysicalLookup(_vm, GCPhys); - - if (VERBOSE_PGM && PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2 && - !handler) - Genode::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " ", - "type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " " - "state=", Genode::Hex(PGM_PAGE_GET_STATE(pPage)), " " - "- MMIO2 w/o handler"); - - if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO2 && handler) { - PFNPGMPHYSHANDLER pfnHandler = PGMPHYSHANDLER_GET_TYPE(_vm, handler)->CTX_SUFF(pfnHandler); - if (!pfnHandler) { - Genode::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " " - "type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage))); - return VERR_PGM_DYNMAP_FAILED; - } - void *pvUser = handler->CTX_SUFF(pvUser); - if (!pvUser) { - Genode::log(__LINE__, " GCPhys=", Genode::Hex(GCPhys), " " - "type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage))); - return VERR_PGM_DYNMAP_FAILED; - } - - PGMACCESSTYPE access_type = (vbox_fault_reason & VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE) ? PGMACCESSTYPE_WRITE : PGMACCESSTYPE_READ; - - VBOXSTRICTRC rcStrict = pfnHandler(_vm, _vcpu, GCPhys, nullptr, nullptr, 0, access_type, PGMACCESSORIGIN_HM, pvUser); - if (rcStrict != VINF_PGM_HANDLER_DO_DEFAULT) { - Genode::log(__LINE__, " nodefault GCPhys=", Genode::Hex(GCPhys), " " - "type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), " " - "pfnHandler=", pfnHandler); - return VERR_PGM_DYNMAP_FAILED; - } - } - -/* - if (VERBOSE_PGM) - Genode::log(Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), - "->", Genode::Hex(GCPhys), - " type=", PGM_PAGE_GET_TYPE(pPage), - " state=", PGM_PAGE_GET_STATE(pPage), - " pde_type=", PGM_PAGE_GET_PDE_TYPE(pPage), - PGM_PAGE_GET_PDE_TYPE(pPage) == PGM_PAGE_PDE_TYPE_PDE ? "(is pde)" : "(not pde)", - " iPage=", iPage, - " range_start=", Genode::Hex(pRam->GCPhys), - " range_size=", Genode::Hex(pRam->cb), - " pages=", pRam->cb >> PAGE_SHIFT - ); -*/ - - if (PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE) - return _map_memory(vm_session, GCPhys, PGM_PAGE_GET_HCPHYS(pPage), 4096, writeable); /* one page mapping */ - - Genode::addr_t const superpage_log2 = 21; - Genode::addr_t const max_pages = pRam->cb >> PAGE_SHIFT; - Genode::addr_t const superpage_pages = (1UL << superpage_log2) / 4096; - Genode::addr_t const mask = (1UL << superpage_log2) - 1; - Genode::addr_t const super_gcphys = GCPhys & ~mask; - - RTGCPHYS max_off = super_gcphys - pRam->GCPhys; - if (max_off > pRam->cb) - return _map_memory(vm_session, GCPhys, PGM_PAGE_GET_HCPHYS(pPage), 4096, writeable); /* one page mapping */ - - Genode::addr_t const super_hcphys = PGM_PAGE_GET_HCPHYS(pPage) & ~mask; - - unsigned const i_s = max_off >> PAGE_SHIFT; - - if (i_s + superpage_pages > max_pages) - return _map_memory(vm_session, GCPhys, PGM_PAGE_GET_HCPHYS(pPage), 4096, writeable); /* one page mapping */ - - if (VERBOSE_PGM) - Genode::log(Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), "->", - Genode::Hex(GCPhys), " - iPage ", iPage, " [", - i_s, ",", i_s + superpage_pages, ")", " " - "range_size=", Genode::Hex(pRam->cb)); - - /* paranoia sanity checks */ - for (Genode::addr_t i = i_s; i < i_s + superpage_pages; i++) { - PPGMPAGE page = &pRam->aPages[i]; - - Genode::addr_t const gcpage = pRam->GCPhys + (i << PAGE_SHIFT); - - if (!(super_hcphys == (PGM_PAGE_GET_HCPHYS(page) & ~mask)) || - !(super_gcphys == (gcpage & ~mask)) || - !(PGM_PAGE_GET_PDE_TYPE(page) == PGM_PAGE_PDE_TYPE_PDE) || - !(PGM_PAGE_GET_TYPE(page) == PGM_PAGE_GET_TYPE(pPage)) || - !(PGM_PAGE_GET_STATE(page) == PGM_PAGE_GET_STATE(pPage))) - { - if (VERBOSE_PGM) - Genode::error(Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), "->", - Genode::Hex(GCPhys), " - iPage ", iPage, " i ", i, " [", - i_s, ",", i_s + superpage_pages, ")", " " - "range_size=", Genode::Hex(pRam->cb), " " - "super_hcphys=", Genode::Hex(super_hcphys), "?=", Genode::Hex((PGM_PAGE_GET_HCPHYS(page) & ~mask)), " " - "super_gcphys=", Genode::Hex(super_gcphys), "?=", Genode::Hex((gcpage & ~mask)), " ", - (int)(PGM_PAGE_GET_PDE_TYPE(page)), "?=", (int)PGM_PAGE_PDE_TYPE_PDE, " ", - (int)(PGM_PAGE_GET_TYPE(page)), "?=", (int)PGM_PAGE_GET_TYPE(pPage), " ", - (int)(PGM_PAGE_GET_STATE(page)), "?=", (int)PGM_PAGE_GET_STATE(pPage)); - return _map_memory(vm_session, GCPhys, PGM_PAGE_GET_HCPHYS(pPage), 4096, writeable); /* one page mapping */ - } - } - - /* XXX revoke of old mappings required ? */ - /* super page mapping */ - return _map_memory(vm_session, super_gcphys, super_hcphys, 1UL << superpage_log2, writeable); -} - - -Genode::uint64_t * Vcpu_handler::pdpte_map(VM *pVM, RTGCPHYS cr3) -{ - Pgm_guard guard(*_vm); - - PPGMRAMRANGE pRam = pgmPhysGetRangeAtOrAbove(pVM, cr3); - Assert (pRam); - - RTGCPHYS off = cr3 - pRam->GCPhys; - Assert (off < pRam->cb); - - unsigned iPage = off >> PAGE_SHIFT; - PPGMPAGE pPage = &pRam->aPages[iPage]; - -/* - if (VERBOSE_PGM) - Genode::log(__LINE__, " gcphys=", Genode::Hex(cr3), - " host=", Genode::Hex(PGM_PAGE_GET_HCPHYS(pPage)), - " type=", Genode::Hex(PGM_PAGE_GET_TYPE(pPage)), - " state=",Genode::Hex(PGM_PAGE_GET_STATE(pPage))); -*/ - - Genode::uint64_t *pdpte = reinterpret_cast(PGM_PAGE_GET_HCPHYS(pPage) + (cr3 & PAGE_OFFSET_MASK)); - - Assert(pdpte != 0); - - return pdpte; -} - -static PFNRTTIMER rttimer_func = nullptr; -static void * rttimer_obj = nullptr; - -enum { - UPDATE_HZ = 1000, - UPDATE_US = 1000 * 1000 / UPDATE_HZ, - UPDATE_NS = UPDATE_US * 1000, -}; - - -PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPage; - - -class Periodic_gip -{ - private : - - void update() - { - /** - * We're using rdtsc here since timer_session->elapsed_ms produces - * instable results when the timer service is using the Genode PIC - * driver. - */ - - Genode::uint64_t tsc_current = Genode::Trace::timestamp(); - - /* - * Convert tsc to nanoseconds. - * - * There is no 'uint128_t' type on x86_32, so we use the 128-bit type - * and functions provided by VirtualBox. - * - * nanots128 = tsc_current * 1000*1000*1000 / genode_cpu_hz() - * - */ - - RTUINT128U nanots128; - RTUInt128AssignU64(&nanots128, tsc_current); - - RTUINT128U multiplier; - RTUInt128AssignU32(&multiplier, 1000*1000*1000); - RTUInt128AssignMul(&nanots128, &multiplier); - - RTUINT128U divisor; - RTUInt128AssignU64(&divisor, genode_cpu_hz()); - RTUInt128AssignDiv(&nanots128, &divisor); - - SUPGIPCPU *cpu = &g_pSUPGlobalInfoPage->aCPUs[0]; - - /* - * Transaction id must be incremented before and after update, - * read struct SUPGIPCPU description for more details. - */ - ASMAtomicIncU32(&cpu->u32TransactionId); - - cpu->u64TSC = tsc_current; - cpu->u64NanoTS = nanots128.s.Lo; - - /* - * Transaction id must be incremented before and after update, - * read struct SUPGIPCPU description for more details. - */ - ASMAtomicIncU32(&cpu->u32TransactionId); - - /* call the timer function of the RTTimerCreate call */ - if (rttimer_func) { - Libc::with_libc([&] () { - rttimer_func(nullptr, rttimer_obj, 0); }); - } - } - - public: - - Timer::Connection _timer; - Genode::Signal_handler _timer_handler; - - Periodic_gip(Genode::Env &env) - : - _timer(env), - _timer_handler(env.ep(), *this, &Periodic_gip::update) - { - _timer.sigh(_timer_handler); - _timer.trigger_periodic(UPDATE_US); - } -}; - - -struct Attached_gip : Genode::Attached_ram_dataspace -{ - Attached_gip() - : Attached_ram_dataspace(genode_env().ram(), genode_env().rm(), PAGE_SIZE) - { - g_pSUPGlobalInfoPage = local_addr(); - - /* checked by TMR3Init */ - g_pSUPGlobalInfoPage->u32Version = SUPGLOBALINFOPAGE_VERSION; - g_pSUPGlobalInfoPage->u32Magic = SUPGLOBALINFOPAGE_MAGIC; - g_pSUPGlobalInfoPage->u32Mode = SUPGIPMODE_SYNC_TSC; - g_pSUPGlobalInfoPage->cCpus = 1; - g_pSUPGlobalInfoPage->cPages = 1; - g_pSUPGlobalInfoPage->u32UpdateHz = UPDATE_HZ; - g_pSUPGlobalInfoPage->u32UpdateIntervalNS = UPDATE_NS; - g_pSUPGlobalInfoPage->cOnlineCpus = 0; - g_pSUPGlobalInfoPage->cPresentCpus = 0; - g_pSUPGlobalInfoPage->cPossibleCpus = 0; - g_pSUPGlobalInfoPage->idCpuMax = 0; - g_pSUPGlobalInfoPage->u64CpuHz = genode_cpu_hz(); - /* evaluated by rtTimeNanoTSInternalRediscover in Runtime/common/time/timesup.cpp */ - g_pSUPGlobalInfoPage->fGetGipCpu = SUPGIPGETCPU_APIC_ID; - - SUPGIPCPU *cpu = &g_pSUPGlobalInfoPage->aCPUs[0]; - - cpu->u32TransactionId = 0; - cpu->u32UpdateIntervalTSC = genode_cpu_hz() / UPDATE_HZ; - cpu->u64NanoTS = 0ULL; - cpu->u64TSC = 0ULL; - cpu->u64CpuHz = genode_cpu_hz(); - cpu->cErrors = 0; - cpu->iTSCHistoryHead = 0; - cpu->u32PrevUpdateIntervalNS = UPDATE_NS; - cpu->enmState = SUPGIPCPUSTATE_ONLINE; - cpu->idCpu = 0; - cpu->iCpuSet = 0; - cpu->idApic = 0; - - /* schedule periodic call of GIP update function */ - static Periodic_gip periodic_gip(genode_env()); - } -}; - - -int RTTimerCreate(PRTTIMER *pptimer, unsigned ms, PFNRTTIMER func, void *obj) -{ - if (pptimer) - *pptimer = NULL; - - /* used solely at one place in TM.cpp */ - Assert(!rttimer_func); - - /* - * Ignore (10) ms which is too high for audio. Instead the callback - * handler will run at UPDATE_HZ rate. - */ - rttimer_func = func; - rttimer_obj = obj; - - return VINF_SUCCESS; -} - - -int RTTimerDestroy(PRTTIMER) -{ - rttimer_obj = nullptr; - rttimer_func = nullptr; - return VINF_SUCCESS; -} - - -int SUPR3Init(PSUPDRVSESSION *ppSession) -{ - static Attached_gip gip; - - 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; -} diff --git a/repos/ports/src/virtualbox5/svm.h b/repos/ports/src/virtualbox5/svm.h deleted file mode 100644 index a9813df069..0000000000 --- a/repos/ports/src/virtualbox5/svm.h +++ /dev/null @@ -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_ */ diff --git a/repos/ports/src/virtualbox5/target.mk b/repos/ports/src/virtualbox5/target.mk deleted file mode 100644 index f7bd54b51f..0000000000 --- a/repos/ports/src/virtualbox5/target.mk +++ /dev/null @@ -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 = diff --git a/repos/ports/src/virtualbox5/vcpu.h b/repos/ports/src/virtualbox5/vcpu.h deleted file mode 100644 index 7032a742ce..0000000000 --- a/repos/ports/src/virtualbox5/vcpu.h +++ /dev/null @@ -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 -#include -#include -#include -#include - -/* 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 -#include -#include - -#include - -#include - -/* Genode's VirtualBox includes */ -#include "sup.h" - -/* Genode libc pthread binding */ -#include - -#include - -/* - * 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::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 Developer’s 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(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_ */ diff --git a/repos/ports/src/virtualbox5/vcpu_svm.h b/repos/ports/src/virtualbox5/vcpu_svm.h deleted file mode 100644 index d0124f9a27..0000000000 --- a/repos/ports/src/virtualbox5/vcpu_svm.h +++ /dev/null @@ -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 - -/* Genode's VirtualBox includes */ -#include "vcpu.h" -#include "svm.h" - -class Vcpu_handler_svm : public Vcpu_handler -{ - private: - - Genode::Vcpu_handler _handler; - - Genode::Vm_connection &_vm_connection; - Genode::Vm_connection::Vcpu _vcpu; - - void _svm_default() { _default_handler(); } - void _svm_vintr() { _irq_window(); } - - template - 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(); 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_ */ diff --git a/repos/ports/src/virtualbox5/vcpu_vmx.h b/repos/ports/src/virtualbox5/vcpu_vmx.h deleted file mode 100644 index aa90e1d4dc..0000000000 --- a/repos/ports/src/virtualbox5/vcpu_vmx.h +++ /dev/null @@ -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 - -/* libc includes */ -#include - -/* VirtualBox includes */ -#include - -/* Genode's VirtualBox includes */ -#include "vcpu.h" -#include "vmx.h" - - -class Vcpu_handler_vmx : public Vcpu_handler -{ - private: - - Genode::Vcpu_handler _handler; - - Genode::Vm_connection &_vm_connection; - Genode::Vm_connection::Vcpu _vcpu; - - template - 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(); 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_ */ diff --git a/repos/ports/src/virtualbox5/vmx.h b/repos/ports/src/virtualbox5/vmx.h deleted file mode 100644 index bd8798218e..0000000000 --- a/repos/ports/src/virtualbox5/vmx.h +++ /dev/null @@ -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_ */ diff --git a/tool/autopilot.list b/tool/autopilot.list index 0d13efe99a..8f0c4d2b50 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -84,11 +84,6 @@ usb_hid_reconnect vbox5_genode_usb_hid_raw vbox5_ubuntu_16_04_32 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_win7_32 vbox5_win7_64