vbox: 64-bit guest support

Fixes #1791
This commit is contained in:
Christian Prochaska 2015-11-26 14:19:42 +01:00 committed by Christian Helmuth
parent 6bf4fd3340
commit 2c558de891
13 changed files with 304 additions and 94 deletions

View File

@ -50,6 +50,8 @@ class Vmm::Vcpu_dispatcher : public T
Genode::Thread_base *myself = Genode::Thread_base::myself();
DISPATCHER *vd = static_cast<DISPATCHER *>(myself);
vd->exit_reason = EV;
/* call event-specific handler function */
(vd->*FUNC)();
@ -59,6 +61,8 @@ class Vmm::Vcpu_dispatcher : public T
public:
unsigned int exit_reason = 0;
Vcpu_dispatcher(size_t stack_size, Cap_connection &cap,
Cpu_session * cpu_session,
Genode::Affinity::Location location)

View File

@ -1,8 +1,8 @@
VBOX_MACH := $(filter $(SPECS), x86_32 x86_64)
VBOX_MACH_CC_OPT_x86_32 = -DRT_ARCH_X86 -D__X86__ -DHC_ARCH_BITS=32
VBOX_MACH_CC_OPT_x86_32 = -DRT_ARCH_X86 -D__X86__
VBOX_MACH_ASM_OPT_x86_32 = -f elf32
VBOX_MACH_CC_OPT_x86_64 = -DRT_ARCH_AMD64 -D__AMD64__ -DHC_ARCH_BITS=64
VBOX_MACH_CC_OPT_x86_64 = -DRT_ARCH_AMD64 -D__AMD64__
VBOX_MACH_ASM_OPT_x86_64 = -f elf64
ifeq ($(shell which yasm),)
@ -16,13 +16,12 @@ VIRTUALBOX_SDK_DIR = $(call select_from_ports,virtualbox)/src/app/virtualbox_sdk
VBOX_DIR = $(VIRTUALBOX_DIR)/src/VBox
VBOX_CC_OPT += -DIN_RING3 -DVBOX -DVBOX_OSE \
-DGC_ARCH_BITS=64 \
-D_FILE_OFFSET_BITS=64 -DLOG_ENABLED
VBOX_CC_OPT += $(VBOX_MACH_CC_OPT_$(VBOX_MACH))
# Required if on a 32bit host 64bit VMs should be executed
# VBOX_CC_OPT += -DVBOX_WITH_64_BITS_GUESTS
VBOX_CC_OPT += -DVBOX_WITH_64_BITS_GUESTS
VBOX_CC_OPT += -DVBOX_WITH_NEW_MSR_CODE
VBOX_CC_OPT += -DIN_SUP_R3 -DIN_VMM_R3

View File

@ -61,6 +61,9 @@ CC_OPT += -DVBOX_WITH_WDDM -DVBOX_WITH_WDDM_W8 -DVBOXWDDM_WITH_VBVA
CC_OPT += -DVBOX_WITH_VDMA
CC_OPT += -DVBOX_WITH_VMSVGA
# found in src/VBox/Devices/Makefile.kmk
CC_OPT += -DVBOX_HGCM_HOST_CODE
Devices/Graphics/DevVGA.o: vbetables.h
vbetables.h: vbetables-gen

View File

@ -0,0 +1,15 @@
#
# Windows 8.1 (64 bit) in VirtualBox
#
assert_spec 64bit
set flavor "win81_64"
# Write overlay back to harddisk if set to 0
set use_ram_fs 0
set use_usb 1
set use_ps2 [have_spec ps2]
source ${genode_dir}/repos/ports/run/vbox_win.inc

View File

@ -0,0 +1,106 @@
<?xml version="1.0"?>
<!--
** DO NOT EDIT THIS FILE.
** If you make changes to this file while any VirtualBox related application
** is running, your changes will be overwritten later, without taking effect.
** Use VBoxManage or the VirtualBox Manager GUI to make changes.
-->
<VirtualBox xmlns="http://www.innotek.de/VirtualBox-settings" version="1.14-linux">
<Machine uuid="{179f623e-40a1-4827-995d-251537a53129}" name="Win81_64" OSType="Windows81_64" snapshotFolder="Snapshots" lastStateChange="2015-01-08T11:27:52Z">
<MediaRegistry>
<HardDisks>
<HardDisk uuid="{4def7eeb-7836-4f3e-9b6c-a850b307ef10}" location="/win81_64.vdi" format="VDI" type="Immutable">
<HardDisk uuid="{9d5f52e5-81ef-45ef-8334-5c644f5a4ef0}" location="/ram/overlay_win81_64.vdi" format="VDI" autoReset="true"/>
</HardDisk>
</HardDisks>
<DVDImages/>
<FloppyImages/>
</MediaRegistry>
<ExtraData>
<ExtraDataItem name="GUI/LastGuestSizeHint" value="1024,768"/>
<ExtraDataItem name="GUI/LastNormalWindowPosition" value="0,12,1439,863"/>
</ExtraData>
<Hardware version="2">
<CPU count="1" hotplug="false">
<HardwareVirtEx enabled="true"/>
<HardwareVirtExNestedPaging enabled="true"/>
<HardwareVirtExVPID enabled="true"/>
<HardwareVirtExUX enabled="true"/>
<PAE enabled="true"/>
<LongMode enabled="true"/>
<HardwareVirtExLargePages enabled="false"/>
<HardwareVirtForce enabled="false"/>
</CPU>
<Memory RAMSize="1024" PageFusion="false"/>
<HID Pointing="PS2Mouse" Keyboard="PS2Keyboard"/>
<HPET enabled="false"/>
<Chipset type="PIIX3"/>
<Boot>
<Order position="1" device="Floppy"/>
<Order position="2" device="DVD"/>
<Order position="3" device="HardDisk"/>
<Order position="4" device="None"/>
</Boot>
<Display VRAMSize="128" monitorCount="1" accelerate3D="false" accelerate2DVideo="false"/>
<VideoCapture enabled="false" screens="18446744073709551615" horzRes="1024" vertRes="768" rate="512" fps="25"/>
<RemoteDisplay enabled="false" authType="Null"/>
<BIOS>
<ACPI enabled="true"/>
<IOAPIC enabled="true"/>
<Logo fadeIn="true" fadeOut="true" displayTime="0"/>
<BootMenu mode="MessageAndMenu"/>
<TimeOffset value="0"/>
<PXEDebug enabled="false"/>
</BIOS>
<USB>
<Controllers>
<Controller name="OHCI" type="OHCI"/>
</Controllers>
<DeviceFilters/>
</USB>
<Network>
<Adapter slot="0" enabled="false" MACAddress="080027235455" cable="true" speed="0" type="82540EM">
<HostInterface/>
<DisabledModes/>
</Adapter>
</Network>
<UART>
<Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
<Port slot="1" enabled="false" IOBase="0x2f8" IRQ="3" hostMode="Disconnected"/>
</UART>
<LPT>
<Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
<Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
</LPT>
<AudioAdapter controller="HDA" driver="Pulse" enabled="true"/>
<RTC localOrUTC="UTC"/>
<SharedFolders/>
<Clipboard mode="Disabled"/>
<DragAndDrop mode="Disabled"/>
<IO>
<IoCache enabled="true" size="5"/>
<BandwidthGroups/>
</IO>
<HostPci>
<Devices/>
</HostPci>
<EmulatedUSB>
<CardReader enabled="false"/>
</EmulatedUSB>
<Guest memoryBalloonSize="0"/>
<GuestProperties>
<GuestProperty name="/VirtualBox/HostInfo/GUI/LanguageID" value="en_US" timestamp="1420716068888210000" flags=""/>
</GuestProperties>
</Hardware>
<StorageControllers>
<StorageController name="IDE" type="PIIX4" PortCount="2" useHostIOCache="true" Bootable="true">
<AttachedDevice type="HardDisk" port="0" device="0">
<Image uuid="{9d5f52e5-81ef-45ef-8334-5c644f5a4ef0}"/>
</AttachedDevice>
<AttachedDevice passthrough="false" type="DVD" port="1" device="0"/>
</StorageController>
<!--<StorageController name="SATA" type="AHCI" PortCount="1" useHostIOCache="false" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3">
</StorageController>-->
</StorageControllers>
</Machine>
</VirtualBox>

View File

@ -122,7 +122,7 @@ HRESULT Host::GetProcessorFeature(ProcessorFeature_T feature, BOOL *supported)
*supported = true;
break;
case ProcessorFeature_LongMode:
*supported = false;
*supported = (sizeof(void *) > 4);
break;
case ProcessorFeature_NestedPaging:
*supported = true;

View File

@ -348,7 +348,7 @@ class Guest_memory
if (vmm_local)
return vmm_local;
it = Genode::Flexpage_iterator((addr_t)r->pv_at_offset(GCPhys - r->GCPhys()), size, GCPhys, size, GCPhys - r->GCPhys());
it = Genode::Flexpage_iterator((addr_t)r->pv_at_offset(GCPhys - r->GCPhys()), size, GCPhys, size, GCPhys);
return r->pv_at_offset(GCPhys - r->GCPhys());
}

View File

@ -23,8 +23,9 @@
#include "sup.h"
static bool enabled_hm = true;
static bool enable_pae_nx = false;
static bool enabled_hm = true;
static bool enable_pae_nx = false;
static bool enable_64bit = false;
VMMR3DECL(int) HMR3Init(PVM pVM)
{
@ -40,6 +41,10 @@ VMMR3DECL(int) HMR3Init(PVM pVM)
false);
AssertRCReturn(rc, rc);
/* check whether to enable long-mode bit - in 64bit host mode */
rc = CFGMR3QueryBoolDef(pCfgHM, "64bitEnabled", &enable_64bit, false);
AssertRCReturn(rc, rc);
/*
* We always set the fHMEnabled flag. Otherwise, the EM won't
* consult us for taking scheduling decisions. The actual switch to
@ -80,6 +85,11 @@ VMMR3_INT_DECL(int) HMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE);
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX);
}
if (sizeof(void *) > 4 && enable_64bit) {
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LONG_MODE);
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_SYSCALL);
CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_LAHF);
}
}
return rc;

View File

@ -51,7 +51,7 @@ static bool debug_map_memory = false;
/*
* VirtualBox stores segment attributes in Intel format using a 32-bit
* value. NOVA represents the attributes in packet format using a 16-bit
* value. NOVA represents the attributes in packed format using a 16-bit
* value.
*/
static inline Genode::uint16_t sel_ar_conv_to_nova(Genode::uint32_t v)
@ -140,8 +140,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
void * _stack_reply;
jmp_buf _env;
bool _last_exit_was_recall;
void switch_to_hw()
{
unsigned long value;
@ -159,7 +157,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
Assert(utcb->actv_state == ACTIVITY_STATE_ACTIVE);
Assert(!(utcb->inj_info & IRQ_INJ_VALID_MASK));
/* go back to re-compiler */
/* go back to VirtualBox */
_fpu_save_and_longjmp();
}
@ -189,7 +187,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
/* are we forced to go back to emulation mode ? */
if (!continue_hw_accelerated(utcb)) {
_last_exit_was_recall = true;
/* go back to emulation mode */
_fpu_save_and_longjmp();
}
@ -317,82 +314,115 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
using namespace Nova;
utcb->mtd |= Mtd::EIP;
utcb->ip = pCtx->rip;
utcb->mtd |= Mtd::EIP;
utcb->ip = pCtx->rip;
utcb->mtd |= Mtd::ESP;
utcb->sp = pCtx->rsp;
utcb->mtd |= Mtd::ESP;
utcb->sp = pCtx->rsp;
utcb->mtd |= Mtd::ACDB;
utcb->ax = pCtx->rax;
utcb->bx = pCtx->rbx;
utcb->cx = pCtx->rcx;
utcb->dx = pCtx->rdx;
utcb->mtd |= Mtd::ACDB;
utcb->ax = pCtx->rax;
utcb->bx = pCtx->rbx;
utcb->cx = pCtx->rcx;
utcb->dx = pCtx->rdx;
utcb->mtd |= Mtd::EBSD;
utcb->bp = pCtx->rbp;
utcb->si = pCtx->rsi;
utcb->di = pCtx->rdi;
utcb->mtd |= Mtd::EBSD;
utcb->bp = pCtx->rbp;
utcb->si = pCtx->rsi;
utcb->di = pCtx->rdi;
utcb->mtd |= Mtd::EFL;
utcb->flags = pCtx->rflags.u;
utcb->mtd |= Mtd::R8_R15;
utcb->write_r8(pCtx->r8);
utcb->write_r9(pCtx->r9);
utcb->write_r10(pCtx->r10);
utcb->write_r11(pCtx->r11);
utcb->write_r12(pCtx->r12);
utcb->write_r13(pCtx->r13);
utcb->write_r14(pCtx->r14);
utcb->write_r15(pCtx->r15);
utcb->mtd |= Mtd::SYS;
utcb->sysenter_cs = pCtx->SysEnter.cs;
utcb->sysenter_sp = pCtx->SysEnter.esp;
utcb->sysenter_ip = pCtx->SysEnter.eip;
utcb->mtd |= Mtd::EFL;
utcb->flags = pCtx->rflags.u;
utcb->mtd |= Mtd::DR;
utcb->dr7 = pCtx->dr[7];
utcb->mtd |= Mtd::SYS;
utcb->sysenter_cs = pCtx->SysEnter.cs;
utcb->sysenter_sp = pCtx->SysEnter.esp;
utcb->sysenter_ip = pCtx->SysEnter.eip;
utcb->mtd |= Mtd::CR;
utcb->cr0 = pCtx->cr0;
utcb->mtd |= Mtd::DR;
utcb->dr7 = pCtx->dr[7];
utcb->mtd |= Mtd::CR;
utcb->cr2 = pCtx->cr2;
utcb->mtd |= Mtd::CR;
utcb->cr0 = pCtx->cr0;
utcb->mtd |= Mtd::CR;
utcb->cr3 = pCtx->cr3;
utcb->mtd |= Mtd::CR;
utcb->cr2 = pCtx->cr2;
utcb->mtd |= Mtd::CR;
utcb->cr4 = pCtx->cr4;
utcb->mtd |= Mtd::CR;
utcb->cr3 = pCtx->cr3;
utcb->mtd |= Mtd::IDTR;
utcb->idtr.limit = pCtx->idtr.cbIdt;
utcb->idtr.base = pCtx->idtr.pIdt;
utcb->mtd |= Mtd::CR;
utcb->cr4 = pCtx->cr4;
utcb->mtd |= Mtd::GDTR;
utcb->gdtr.limit = pCtx->gdtr.cbGdt;
utcb->gdtr.base = pCtx->gdtr.pGdt;
utcb->mtd |= Mtd::IDTR;
utcb->idtr.limit = pCtx->idtr.cbIdt;
utcb->idtr.base = pCtx->idtr.pIdt;
utcb->mtd |= Mtd::EFER;
utcb->write_efer(CPUMGetGuestEFER(pVCpu));
utcb->mtd |= Mtd::GDTR;
utcb->gdtr.limit = pCtx->gdtr.cbGdt;
utcb->gdtr.base = pCtx->gdtr.pGdt;
/*
* 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)) {
utcb->mtd |= Mtd::EFER;
utcb->write_efer(CPUMGetGuestEFER(pVCpu));
utcb->mtd |= Mtd::PDPTE;
/*
* 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 = (Genode::uint64_t*)
guest_memory()->lookup(utcb->cr3, sizeof(utcb->pdpte));
utcb->mtd |= Mtd::PDPTE;
Assert(pdpte != 0);
Genode::uint64_t *pdpte = (Genode::uint64_t*)
guest_memory()->lookup(utcb->cr3, sizeof(utcb->pdpte));
utcb->pdpte[0] = pdpte[0];
utcb->pdpte[1] = pdpte[1];
utcb->pdpte[2] = pdpte[2];
utcb->pdpte[3] = pdpte[3];
}
Assert(pdpte != 0);
utcb->pdpte[0] = pdpte[0];
utcb->pdpte[1] = pdpte[1];
utcb->pdpte[2] = pdpte[2];
utcb->pdpte[3] = pdpte[3];
}
utcb->mtd |= Mtd::SYSCALL_SWAPGS;
utcb->write_star(pCtx->msrSTAR);
utcb->write_lstar(pCtx->msrLSTAR);
utcb->write_fmask(pCtx->msrSFMASK);
utcb->write_kernel_gs_base(pCtx->msrKERNELGSBASE);
/* from HMVMXR0.cpp */
bool interrupt_pending = false;
uint8_t tpr = 0;
uint8_t pending_interrupt = 0;
PDMApicGetTPR(pVCpu, &tpr, &interrupt_pending, &pending_interrupt);
utcb->mtd |= Mtd::TPR;
utcb->write_tpr(tpr);
utcb->write_tpr_threshold(0);
if (interrupt_pending) {
const uint8_t pending_priority = (pending_interrupt >> 4) & 0xf;
const uint8_t tpr_priority = (tpr >> 4) & 0xf;
if (pending_priority <= tpr_priority)
utcb->write_tpr_threshold(pending_priority);
else
utcb->write_tpr_threshold(tpr_priority);
}
Assert(!(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)));
@ -417,6 +447,15 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
pCtx->rdi = utcb->di;
pCtx->rflags.u = utcb->flags;
pCtx->r8 = utcb->read_r8();
pCtx->r9 = utcb->read_r9();
pCtx->r10 = utcb->read_r10();
pCtx->r11 = utcb->read_r11();
pCtx->r12 = utcb->read_r12();
pCtx->r13 = utcb->read_r13();
pCtx->r14 = utcb->read_r14();
pCtx->r15 = utcb->read_r15();
pCtx->dr[7] = utcb->dr7;
if (pCtx->SysEnter.cs != utcb->sysenter_cs)
@ -450,6 +489,20 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
if (pCtx->cr4 != utcb->cr4)
CPUMSetGuestCR4(pVCpu, utcb->cr4);
if (pCtx->msrSTAR != utcb->read_star())
CPUMSetGuestMsr(pVCpu, MSR_K6_STAR, utcb->read_star());
if (pCtx->msrLSTAR != utcb->read_lstar())
CPUMSetGuestMsr(pVCpu, MSR_K8_LSTAR, utcb->read_lstar());
if (pCtx->msrSFMASK != utcb->read_fmask())
CPUMSetGuestMsr(pVCpu, MSR_K8_SF_MASK, utcb->read_fmask());
if (pCtx->msrKERNELGSBASE != utcb->read_kernel_gs_base())
CPUMSetGuestMsr(pVCpu, MSR_K8_KERNEL_GS_BASE, utcb->read_kernel_gs_base());
PDMApicSetTPR(pVCpu, utcb->read_tpr());
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
/* tell rem compiler that FPU register changed XXX optimizations ? */
@ -623,6 +676,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
virtual bool hw_load_state(Nova::Utcb *, VM *, PVMCPU) = 0;
virtual bool hw_save_state(Nova::Utcb *, VM *, PVMCPU) = 0;
virtual bool vm_exit_requires_instruction_emulation() = 0;
public:
@ -812,8 +866,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
_current_vm = pVM;
_current_vcpu = pVCpu;
_last_exit_was_recall = false;
/* switch to hardware accelerated mode */
switch_to_hw();
@ -859,7 +911,8 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
REMFlushTBs(pVM);
#endif
return _last_exit_was_recall ? VINF_SUCCESS : VINF_EM_RAW_EMULATE_INSTR;
return vm_exit_requires_instruction_emulation() ? VINF_EM_RAW_EMULATE_INSTR
: VINF_SUCCESS;
}
};

View File

@ -128,6 +128,14 @@ class Vcpu_handler_svm : public Vcpu_handler
bool hw_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return svm_load_state(utcb, pVM, pVCpu);
}
bool vm_exit_requires_instruction_emulation()
{
if (exit_reason == RECALL)
return false;
return true;
}
};
#endif /* _VIRTUALBOX__SPEC__NOVA__VCPU_SVM_H_ */

View File

@ -15,6 +15,9 @@
#ifndef _VIRTUALBOX__SPEC__NOVA__VCPU_VMX_H_
#define _VIRTUALBOX__SPEC__NOVA__VCPU_VMX_H_
/* libc includes */
#include <stdlib.h>
/* VirtualBox includes */
#include <VBox/vmm/hm_vmx.h>
@ -61,8 +64,9 @@ class Vcpu_handler_vmx : public Vcpu_handler
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_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 | */
/*
@ -87,12 +91,8 @@ class Vcpu_handler_vmx : public Vcpu_handler
__attribute__((noreturn)) void _vmx_triple()
{
Genode::Thread_base *myself = Genode::Thread_base::myself();
using namespace Nova;
Vmm::printf("triple fault - dead\n");
_default_handler();
exit(-1);
}
__attribute__((noreturn)) void _vmx_irqwin() { _irq_window(); }
@ -115,7 +115,8 @@ class Vcpu_handler_vmx : public Vcpu_handler
utcb->inj_info, utcb->inj_error,
utcb->intr_state, utcb->actv_state);
Vcpu_handler::_default_handler();
Vmm::printf("invalid guest state - dead\n");
exit(-1);
}
/*
@ -134,6 +135,11 @@ class Vcpu_handler_vmx : public Vcpu_handler
Genode::Thread_base *myself = Genode::Thread_base::myself();
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
unsigned int cr = utcb->qual[0] & 0xf;
if (cr == 8)
_default_handler();
Genode::uint64_t *pdpte = (Genode::uint64_t*)
guest_memory()->lookup(utcb->cr3, sizeof(utcb->pdpte));
@ -201,6 +207,8 @@ class Vcpu_handler_vmx : public Vcpu_handler
&This::_vmx_mov_crx> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_MOV_DRX, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_TPR_BELOW_THRESHOLD, This,
&This::_vmx_default> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VMX_EXIT_EPT_VIOLATION, This,
&This::_vmx_ept<VMX_EXIT_EPT_VIOLATION>> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<VCPU_STARTUP, This,
@ -218,6 +226,19 @@ class Vcpu_handler_vmx : public Vcpu_handler
bool hw_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return vmx_load_state(utcb, pVM, pVCpu);
}
bool vm_exit_requires_instruction_emulation()
{
if (exit_reason == VMX_EXIT_TPR_BELOW_THRESHOLD) {
/* the instruction causing the exit has already been executed */
return false;
}
if (exit_reason == RECALL)
return false;
return true;
}
};
#endif /* _VIRTUALBOX__SPEC__NOVA__VCPU_VMX_H_ */

View File

@ -65,17 +65,7 @@ enum { VMCS_SEG_UNUSABLE = 0x10000 };
utcb->REG.sel = pCtx->REG.Sel; \
utcb->REG.limit = pCtx->REG.u32Limit; \
utcb->REG.base = pCtx->REG.u64Base; \
\
/* attribute fixup according to 'VMX_WRITE_SELREG' in 'HWVMXR0.h' */ \
if (( pCtx->REG.Sel \
|| !CPUMIsGuestInPagedProtectedModeEx(pCtx) \
|| (!pCtx->cs.Attr.n.u1DefBig && !CPUMIsGuestIn64BitCodeEx(pCtx))) \
&& pCtx->REG.Attr.n.u1Present == 1) \
{ \
utcb->REG.ar = sel_ar_conv_to_nova(pCtx->REG.Attr.u | X86_SEL_TYPE_ACCESSED); \
} else { \
utcb->REG.ar = sel_ar_conv_to_nova(VMCS_SEG_UNUSABLE); \
}
utcb->REG.ar = sel_ar_conv_to_nova(pCtx->REG.Attr.u ? : VMCS_SEG_UNUSABLE);
static inline bool vmx_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu)
{

View File

@ -49,6 +49,7 @@ pthread
vbox_auto_win7
vbox_auto_win7_share
vbox_auto_win8
vbox_auto_win81_64
tz_vmm
vmm
bomb