apic virtualization + vmx fixes
This commit is contained in:
parent
b8dfe6d9b1
commit
79466dffe2
@ -4,6 +4,7 @@ Brief summary :
|
||||
- Major configure/cpu rework allowing to enable/disable CPU options at runtime
|
||||
through .bochsrc (Stanislav)
|
||||
- Bugfixes for CPU emulation correctness and stability
|
||||
- Implemented VMX Apic Virtualization
|
||||
- Implemented PCLMULQDQ AES instruction
|
||||
- Extended Bochs internal debugger functionality
|
||||
- USB HP DeskJet 920C printer device emulation (Ben Lunt)
|
||||
@ -35,6 +36,10 @@ Detailed change log :
|
||||
|
||||
- CPU
|
||||
- Implemented PCLMULQDQ AES instruction
|
||||
- VMX: Enabled secondary proc-based vmexec controls
|
||||
- Implemented APIC virtualization
|
||||
- Implemented WBINVD VMEXIT control
|
||||
- Implemented RDTSCP VMEXIT control
|
||||
- Bugfixes for CPU emulation correctness
|
||||
- Fixed Bochs crash when accessing the first byte above emulated memory size
|
||||
|
||||
@ -61,6 +66,7 @@ Detailed change log :
|
||||
[2908481] USB Printer by Ben Lunt
|
||||
|
||||
- these S.F. bugs were closed/fixed
|
||||
[2964824] bad newline sequence in aspi-win32.h
|
||||
[913419] configure options and build process needs some work
|
||||
[2938398] gdbstub compile error with x86_64 enabled
|
||||
[2374455] shutdown/reset type 05 should reinit the PICs
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.cc,v 1.306 2010-03-14 15:51:26 sshwarts Exp $
|
||||
// $Id: cpu.cc,v 1.307 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -749,8 +749,7 @@ void BX_CPU_C::prefetch(void)
|
||||
BX_CPU_THIS_PTR eipFetchPtr = fetchPtr;
|
||||
}
|
||||
else {
|
||||
BX_CPU_THIS_PTR eipFetchPtr = BX_MEM(0)->getHostMemAddr(BX_CPU_THIS,
|
||||
BX_CPU_THIS_PTR pAddrPage, BX_EXECUTE);
|
||||
BX_CPU_THIS_PTR eipFetchPtr = (const Bit8u*) getHostMemAddr(BX_CPU_THIS_PTR pAddrPage, BX_EXECUTE);
|
||||
|
||||
// Sanity checks
|
||||
if (! BX_CPU_THIS_PTR eipFetchPtr) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.653 2010-03-15 14:18:35 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.654 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -922,6 +922,8 @@ public: // for now...
|
||||
bx_bool in_event;
|
||||
bx_bool in_vmx;
|
||||
bx_bool in_vmx_guest;
|
||||
bx_bool in_smm_vmx; // save in_vmx and in_vmx_guest flags when in SMM mode
|
||||
bx_bool in_smm_vmx_guest;
|
||||
bx_bool vmx_interrupt_window;
|
||||
Bit64u vmcsptr;
|
||||
bx_hostpageaddr_t vmcshostptr;
|
||||
@ -3091,6 +3093,8 @@ public: // for now...
|
||||
BX_SMF void access_read_physical(bx_phy_address paddr, unsigned len, void *data);
|
||||
BX_SMF void access_write_physical(bx_phy_address paddr, unsigned len, void *data);
|
||||
|
||||
BX_SMF bx_hostpageaddr_t getHostMemAddr(bx_phy_address addr, unsigned rw);
|
||||
|
||||
// linear address for translate_linear expected to be canonical !
|
||||
BX_SMF bx_phy_address translate_linear(bx_address laddr, unsigned curr_pl, unsigned rw);
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
@ -3386,11 +3390,12 @@ public: // for now...
|
||||
BX_SMF void set_VMCSPTR(Bit64u vmxptr);
|
||||
BX_SMF void init_VMCS(void);
|
||||
BX_SMF void register_vmx_state(bx_param_c *parent);
|
||||
BX_SMF bx_bool is_virtual_apic_page(bx_phy_address paddr) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF Bit64s VMX_TSC_Offset(void);
|
||||
BX_SMF Bit32u VMX_Read_TPR_Shadow(void);
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_SMF Bit32u VMX_Read_VTPR(void);
|
||||
BX_SMF void VMX_Write_TPR_Shadow(Bit8u tpr_shadow);
|
||||
#endif
|
||||
BX_SMF void VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *data);
|
||||
BX_SMF void VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *data);
|
||||
// vmexit reasons
|
||||
BX_SMF void VMexit_Instruction(bxInstruction_c *i, Bit32u reason) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF void VMexit_Event(bxInstruction_c *i, unsigned type, unsigned vector,
|
||||
@ -3404,6 +3409,7 @@ public: // for now...
|
||||
BX_SMF void VMexit_INVLPG(bxInstruction_c *i, bx_address laddr) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF void VMexit_RDTSC(bxInstruction_c *i) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF void VMexit_RDPMC(bxInstruction_c *i) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF void VMexit_WBINVD(bxInstruction_c *i) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF bx_bool VMexit_CLTS(bxInstruction_c *i) BX_CPP_AttrRegparmN(1);
|
||||
BX_SMF void VMexit_MSR(bxInstruction_c *i, unsigned op, Bit32u msr) BX_CPP_AttrRegparmN(3);
|
||||
BX_SMF void VMexit_IO(bxInstruction_c *i, unsigned port, unsigned len) BX_CPP_AttrRegparmN(3);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: init.cc,v 1.231 2010-03-06 16:59:05 sshwarts Exp $
|
||||
// $Id: init.cc,v 1.232 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -1026,6 +1026,7 @@ void BX_CPU_C::reset(unsigned source)
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
BX_CPU_THIS_PTR in_vmx = BX_CPU_THIS_PTR in_vmx_guest = 0;
|
||||
BX_CPU_THIS_PTR in_smm_vmx = BX_CPU_THIS_PTR in_smm_vmx_guest = 0;
|
||||
BX_CPU_THIS_PTR in_event = 0;
|
||||
BX_CPU_THIS_PTR vmx_interrupt_window = 0;
|
||||
BX_CPU_THIS_PTR vmcsptr = BX_CPU_THIS_PTR vmxonptr = BX_INVALID_VMCSPTR;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: paging.cc,v 1.192 2010-03-14 15:51:26 sshwarts Exp $
|
||||
// $Id: paging.cc,v 1.193 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -1353,8 +1353,7 @@ bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned curr_pl, un
|
||||
// Attempt to get a host pointer to this physical page. Put that
|
||||
// pointer in the TLB cache. Note if the request is vetoed, NULL
|
||||
// will be returned, and it's OK to OR zero in anyways.
|
||||
tlbEntry->hostPageAddr = (bx_hostpageaddr_t) BX_MEM(0)->getHostMemAddr(BX_CPU_THIS, ppf, rw);
|
||||
|
||||
tlbEntry->hostPageAddr = BX_CPU_THIS_PTR getHostMemAddr(ppf, rw);
|
||||
if (tlbEntry->hostPageAddr) {
|
||||
// All access allowed also via direct pointer
|
||||
#if BX_X86_DEBUGGER
|
||||
@ -1551,9 +1550,7 @@ void BX_CPU_C::access_write_linear(bx_address laddr, unsigned len, unsigned curr
|
||||
// We haven't seen this page, or it's been bumped before.
|
||||
|
||||
// Request a direct write pointer so we can do either R or W.
|
||||
bx_hostpageaddr_t hostPageAddr = (bx_hostpageaddr_t)
|
||||
BX_MEM(0)->getHostMemAddr(BX_CPU_THIS, lpf, BX_WRITE);
|
||||
|
||||
bx_hostpageaddr_t hostPageAddr = BX_CPU_THIS_PTR getHostMemAddr(lpf, BX_WRITE);
|
||||
if (hostPageAddr) {
|
||||
tlbEntry->lpf = lpf; // Got direct write pointer OK
|
||||
tlbEntry->ppf = (bx_phy_address) lpf;
|
||||
@ -1714,9 +1711,7 @@ void BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_
|
||||
// We haven't seen this page, or it's been bumped before.
|
||||
|
||||
// Request a direct write pointer so we can do either R or W.
|
||||
bx_hostpageaddr_t hostPageAddr = (bx_hostpageaddr_t)
|
||||
BX_MEM(0)->getHostMemAddr(BX_CPU_THIS, lpf, BX_READ);
|
||||
|
||||
bx_hostpageaddr_t hostPageAddr = BX_CPU_THIS_PTR getHostMemAddr(lpf, BX_READ);
|
||||
if (hostPageAddr) {
|
||||
tlbEntry->lpf = lpf; // Got direct read pointer OK.
|
||||
tlbEntry->ppf = (bx_phy_address) lpf;
|
||||
@ -1784,6 +1779,13 @@ void BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_
|
||||
|
||||
void BX_CPU_C::access_write_physical(bx_phy_address paddr, unsigned len, void *data)
|
||||
{
|
||||
#if BX_SUPPORT_VMX
|
||||
if (is_virtual_apic_page(paddr)) {
|
||||
VMX_Virtual_Apic_Write(paddr, len, data);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
if (BX_CPU_THIS_PTR lapic.is_selected(paddr)) {
|
||||
BX_CPU_THIS_PTR lapic.write(paddr, data, len);
|
||||
@ -1796,6 +1798,13 @@ void BX_CPU_C::access_write_physical(bx_phy_address paddr, unsigned len, void *d
|
||||
|
||||
void BX_CPU_C::access_read_physical(bx_phy_address paddr, unsigned len, void *data)
|
||||
{
|
||||
#if BX_SUPPORT_VMX
|
||||
if (is_virtual_apic_page(paddr)) {
|
||||
VMX_Virtual_Apic_Read(paddr, len, data);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
if (BX_CPU_THIS_PTR lapic.is_selected(paddr)) {
|
||||
BX_CPU_THIS_PTR lapic.read(paddr, data, len);
|
||||
@ -1805,3 +1814,18 @@ void BX_CPU_C::access_read_physical(bx_phy_address paddr, unsigned len, void *da
|
||||
|
||||
BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, paddr, len, data);
|
||||
}
|
||||
|
||||
bx_hostpageaddr_t BX_CPU_C::getHostMemAddr(bx_phy_address ppf, unsigned rw)
|
||||
{
|
||||
#if BX_SUPPORT_VMX
|
||||
if (is_virtual_apic_page(ppf))
|
||||
return 0; // Do not allow direct access to virtual apic page
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
if (BX_CPU_THIS_PTR lapic.is_selected(ppf))
|
||||
return 0; // Vetoed! APIC address space
|
||||
#endif
|
||||
|
||||
return (bx_hostpageaddr_t) BX_MEM(0)->getHostMemAddr(BX_CPU_THIS, ppf, rw);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.323 2010-03-15 15:48:01 sshwarts Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.324 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -179,12 +179,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WBINVD(bxInstruction_c *i)
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
if (BX_CPU_THIS_PTR in_vmx_guest) {
|
||||
if (! SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: WBINVD in VMX non-root operation"));
|
||||
VMexit(i, VMX_VMEXIT_WBINVD, 0);
|
||||
}
|
||||
}
|
||||
VMexit_WBINVD(i);
|
||||
#endif
|
||||
|
||||
invalidate_prefetch_q();
|
||||
@ -853,7 +848,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RqCq(bxInstruction_c *i)
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_CR8_Read(i);
|
||||
if (BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW)) {
|
||||
val_64 = VMX_Read_TPR_Shadow();
|
||||
val_64 = (VMX_Read_VTPR() >> 4) & 0xf;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -1495,9 +1490,17 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR4(bx_address val)
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
if (!(val & (1 << 13)) && BX_CPU_THIS_PTR in_vmx) {
|
||||
BX_ERROR(("SetCR4(): Attempt to clear CR4.VMXE in vmx mode"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
if (!(val & (1 << 13))) {
|
||||
if (BX_CPU_THIS_PTR in_vmx) {
|
||||
BX_ERROR(("SetCR4(): Attempt to clear CR4.VMXE in vmx mode"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (BX_CPU_THIS_PTR in_smm) {
|
||||
BX_ERROR(("SetCR4(): Attempt to set CR4.VMXE in smm mode"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: smm.cc,v 1.64 2010-03-15 22:58:41 sshwarts Exp $
|
||||
// $Id: smm.cc,v 1.65 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2006-2009 Stanislav Shwartsman
|
||||
@ -121,6 +121,36 @@ void BX_CPU_C::enter_system_management_mode(void)
|
||||
|
||||
// debug(BX_CPU_THIS_PTR prev_rip);
|
||||
|
||||
//
|
||||
// Processors that support VMX operation perform SMI delivery as follows:
|
||||
//
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
// Enter SMM
|
||||
// save the following internal to the processor:
|
||||
// * CR4.VMXE
|
||||
// * an indication of whether the logical processor was in VMX operation (root or non-root)
|
||||
// IF the logical processor is in VMX operation
|
||||
// THEN
|
||||
// leave VMX operation;
|
||||
// save VMX-critical state defined below;
|
||||
// preserve current VMCS pointer as noted below;
|
||||
// FI;
|
||||
// CR4.VMXE = 0;
|
||||
|
||||
BX_CPU_THIS_PTR cr4.set_VMXE(0);
|
||||
BX_CPU_THIS_PTR in_smm_vmx = BX_CPU_THIS_PTR in_vmx;
|
||||
BX_CPU_THIS_PTR in_smm_vmx_guest = BX_CPU_THIS_PTR in_vmx_guest;
|
||||
BX_CPU_THIS_PTR in_vmx = 0;
|
||||
BX_CPU_THIS_PTR in_vmx_guest = 0;
|
||||
|
||||
BX_INFO(("enter_system_management_mode: temporary disable VMX while in SMM mode"));
|
||||
|
||||
// perform ordinary SMI delivery:
|
||||
// * save processor state in SMRAM;
|
||||
// * set processor state to standard SMM values
|
||||
#endif
|
||||
|
||||
BX_CPU_THIS_PTR in_smm = 1;
|
||||
BX_CPU_THIS_PTR disable_NMI = 1;
|
||||
|
||||
@ -470,6 +500,47 @@ bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state)
|
||||
Bit32u temp_cr0 = SMRAM_FIELD(saved_state, SMRAM_FIELD_CR0);
|
||||
Bit32u temp_eflags = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFLAGS);
|
||||
Bit32u temp_efer = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFER);
|
||||
Bit32u temp_cr4 = SMRAM_FIELD(saved_state, SMRAM_FIELD_CR4);
|
||||
|
||||
// Processors that support VMX operation perform RSM as follows:
|
||||
#if BX_SUPPORT_VMX
|
||||
// IF VMXE=1 in CR4 image in SMRAM
|
||||
// THEN
|
||||
// fail and enter shutdown state;
|
||||
|
||||
if (temp_cr4 & (1 << 13)) {
|
||||
BX_PANIC(("SMM restore: CR4.VMXE is set in restore image !"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// restore state normally from SMRAM;
|
||||
// CR4.VMXE = value stored internally;
|
||||
// IF internal storage indicates that the logical processor had been in VMX operation (root or non-root)
|
||||
// THEN
|
||||
// enter VMX operation (root or non-root);
|
||||
// restore VMX-critical state
|
||||
// set CR0.PE, CR0.NE, and CR0.PG to 1;
|
||||
// IF RFLAGS.VM = 0
|
||||
// THEN
|
||||
// CS.RPL = SS.DPL;
|
||||
// SS.RPL = SS.DPL;
|
||||
// FI;
|
||||
// If necessary, restore current VMCS pointer;
|
||||
// Leave SMM; Deassert SMMEM on subsequent bus transactions;
|
||||
// IF logical processor will be in VMX operation after RSM
|
||||
// THEN
|
||||
// block A20M and leave A20M mode;
|
||||
// FI;
|
||||
|
||||
if (BX_CPU_THIS_PTR in_smm_vmx) {
|
||||
BX_CPU_THIS_PTR in_vmx = 1;
|
||||
BX_CPU_THIS_PTR in_vmx_guest = BX_CPU_THIS_PTR in_smm_vmx_guest;
|
||||
BX_INFO(("SMM Restore: enable VMX %s mode", BX_CPU_THIS_PTR in_vmx_guest ? "guest" : "host"));
|
||||
temp_cr4 |= (1<<13); /* set VMXE */
|
||||
temp_cr0 |= (1<<31) /* PG */ | (1 << 5) /* NE */ | 0x1 /* PE */;
|
||||
// block and disable A20M;
|
||||
}
|
||||
#endif
|
||||
|
||||
bx_bool pe = (temp_cr0 & 0x1);
|
||||
bx_bool nw = (temp_cr0 >> 29) & 0x1;
|
||||
@ -488,7 +559,7 @@ bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state)
|
||||
}
|
||||
|
||||
// shutdown if write to reserved CR4 bits
|
||||
if (! SetCR4(SMRAM_FIELD(saved_state, SMRAM_FIELD_CR4))) {
|
||||
if (! SetCR4(temp_cr4)) {
|
||||
BX_PANIC(("SMM restore: incorrect CR4 state !"));
|
||||
return 0;
|
||||
}
|
||||
|
@ -47,8 +47,7 @@ TODO (know issues in CPU model):
|
||||
[!] VMX:
|
||||
|
||||
- Dual-monitor treatment of SMIs and SMM not implemented yet
|
||||
- NMI virtualization, APIC virtualization not implemented yet
|
||||
- VMENTER to not-active state not supported yet
|
||||
- No advanced features like Extended Page Tables (EPT) or VPID
|
||||
|
||||
[!] SSE4A, SSE5A, SMX, SVM, AVX
|
||||
[!] SSE4A, SMX, SVM, AVX
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: vmexit.cc,v 1.16 2010-03-13 21:06:56 sshwarts Exp $
|
||||
// $Id: vmexit.cc,v 1.17 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009 Stanislav Shwartsman
|
||||
@ -131,8 +131,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_HLT(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_HLT_VMEXIT))
|
||||
{
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_HLT_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: HLT"));
|
||||
VMexit(i, VMX_VMEXIT_HLT, 0);
|
||||
}
|
||||
@ -142,8 +141,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_PAUSE(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_PAUSE_VMEXIT))
|
||||
{
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_PAUSE_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: PAUSE"));
|
||||
VMexit(i, VMX_VMEXIT_PAUSE, 0);
|
||||
}
|
||||
@ -153,8 +151,7 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_INVLPG(bxInstruction_c *i, bx_addre
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_INVLPG_VMEXIT))
|
||||
{
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_INVLPG_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: INVLPG 0x" FMT_ADDRX, laddr));
|
||||
VMexit(i, VMX_VMEXIT_INVLPG, laddr);
|
||||
}
|
||||
@ -175,8 +172,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_RDTSC(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_RDTSC_VMEXIT))
|
||||
{
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_RDTSC_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: RDTSC"));
|
||||
VMexit(i, VMX_VMEXIT_RDTSC, 0);
|
||||
}
|
||||
@ -186,8 +182,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_RDPMC(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_RDPMC_VMEXIT))
|
||||
{
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_RDPMC_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: RDPMC"));
|
||||
VMexit(i, VMX_VMEXIT_RDPMC, 0);
|
||||
}
|
||||
@ -198,8 +193,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_MONITOR(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_MONITOR_VMEXIT))
|
||||
{
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_MONITOR_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: MONITOR"));
|
||||
VMexit(i, VMX_VMEXIT_MONITOR, 0);
|
||||
}
|
||||
@ -209,10 +203,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_MWAIT(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_MWAIT_VMEXIT))
|
||||
{
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_MWAIT_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: MWAIT"));
|
||||
VMexit(i, VMX_VMEXIT_MWAIT, 0);
|
||||
VMexit(i, VMX_VMEXIT_MWAIT, BX_CPU_THIS_PTR monitor.armed);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -673,27 +666,23 @@ void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_DR_Access(bxInstruction_c *i, unsig
|
||||
}
|
||||
}
|
||||
|
||||
Bit32u BX_CPU_C::VMX_Read_TPR_Shadow(void)
|
||||
Bit32u BX_CPU_C::VMX_Read_VTPR(void)
|
||||
{
|
||||
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr + 0x80;
|
||||
Bit8u tpr_shadow;
|
||||
|
||||
access_read_physical(pAddr, 1, &tpr_shadow);
|
||||
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 1, BX_READ, &tpr_shadow);
|
||||
|
||||
return (tpr_shadow >> 4) & 0xF;
|
||||
Bit32u vtpr;
|
||||
access_read_physical(pAddr, 4, &vtpr);
|
||||
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 4, BX_READ, &vtpr);
|
||||
return vtpr;
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
|
||||
void BX_CPU_C::VMX_Write_TPR_Shadow(Bit8u tpr_shadow)
|
||||
{
|
||||
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
|
||||
bx_phy_address pAddr = vm->virtual_apic_page_addr + 0x80;
|
||||
Bit8u field = tpr_shadow << 4;
|
||||
Bit32u field32 = tpr_shadow << 4;
|
||||
|
||||
access_write_physical(pAddr, 1, &field);
|
||||
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 1, BX_WRITE, &field);
|
||||
access_write_physical(pAddr, 4, &field32);
|
||||
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, pAddr, 4, BX_WRITE, &field32);
|
||||
|
||||
if (tpr_shadow < vm->vm_tpr_threshold) {
|
||||
// commit current instruction to produce trap-like VMexit
|
||||
@ -702,6 +691,68 @@ void BX_CPU_C::VMX_Write_TPR_Shadow(Bit8u tpr_shadow)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::is_virtual_apic_page(bx_phy_address paddr)
|
||||
{
|
||||
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
|
||||
if (BX_CPU_THIS_PTR in_vmx_guest) {
|
||||
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES))
|
||||
if (LPFOf(paddr) == LPFOf(vm->apic_access_page)) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BX_CPU_C::VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *data)
|
||||
{
|
||||
BX_ASSERT(SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES));
|
||||
|
||||
Bit32u offset = PAGE_OFFSET(paddr);
|
||||
|
||||
// access is not instruction fetch because cpu::prefetch will crash them
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == 0x80 && len <= 4) {
|
||||
// VTPR access
|
||||
Bit32u vtpr = VMX_Read_VTPR();
|
||||
if (len == 1)
|
||||
*((Bit8u *) data) = vtpr & 0xff;
|
||||
else if (len == 2)
|
||||
*((Bit16u *) data) = vtpr & 0xffff;
|
||||
else if (len == 4)
|
||||
*((Bit32u *) data) = vtpr;
|
||||
else
|
||||
BX_PANIC(("PANIC: Unsupported Virtual APIC access len = 3 !"));
|
||||
return;
|
||||
}
|
||||
|
||||
Bit32u qualification = offset |
|
||||
(BX_CPU_THIS_PTR in_event) ? VMX_APIC_ACCESS_DURING_EVENT_DELIVERY : VMX_APIC_READ_INSTRUCTION_EXECUTION;
|
||||
VMexit(0, VMX_VMEXIT_APIC_ACCESS, qualification);
|
||||
}
|
||||
|
||||
void BX_CPU_C::VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *data)
|
||||
{
|
||||
BX_ASSERT(SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES));
|
||||
|
||||
Bit32u offset = PAGE_OFFSET(paddr);
|
||||
|
||||
if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == 0x80 && len <= 4) {
|
||||
// VTPR access
|
||||
VMX_Write_TPR_Shadow(*((Bit8u *) data));
|
||||
return;
|
||||
}
|
||||
|
||||
Bit32u qualification = offset |
|
||||
(BX_CPU_THIS_PTR in_event) ? VMX_APIC_ACCESS_DURING_EVENT_DELIVERY : VMX_APIC_WRITE_INSTRUCTION_EXECUTION;
|
||||
VMexit(0, VMX_VMEXIT_APIC_ACCESS, qualification);
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_WBINVD(bxInstruction_c *i)
|
||||
{
|
||||
if (! BX_CPU_THIS_PTR in_vmx_guest) return;
|
||||
|
||||
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT)) {
|
||||
BX_ERROR(("VMEXIT: WBINVD in VMX non-root operation"));
|
||||
VMexit(i, VMX_VMEXIT_WBINVD, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BX_SUPPORT_VMX
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: vmx.cc,v 1.39 2010-03-15 22:58:41 sshwarts Exp $
|
||||
// $Id: vmx.cc,v 1.40 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009 Stanislav Shwartsman
|
||||
@ -81,7 +81,7 @@ void BX_CPU_C::set_VMCSPTR(Bit64u vmxptr)
|
||||
BX_CPU_THIS_PTR vmcsptr = vmxptr;
|
||||
|
||||
if (vmxptr != BX_INVALID_VMCSPTR)
|
||||
BX_CPU_THIS_PTR vmcshostptr = (bx_hostpageaddr_t) BX_MEM(0)->getHostMemAddr(BX_CPU_THIS, vmxptr, BX_WRITE);
|
||||
BX_CPU_THIS_PTR vmcshostptr = BX_CPU_THIS_PTR getHostMemAddr(vmxptr, BX_WRITE);
|
||||
else
|
||||
BX_CPU_THIS_PTR vmcshostptr = 0;
|
||||
}
|
||||
@ -305,6 +305,7 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
|
||||
vm->vm_tpr_threshold = VMread32(VMCS_32BIT_CONTROL_TPR_THRESHOLD);
|
||||
vm->virtual_apic_page_addr = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR);
|
||||
vm->executive_vmcsptr = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR);
|
||||
vm->apic_access_page = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR);
|
||||
|
||||
//
|
||||
// Check VM-execution control fields
|
||||
@ -385,41 +386,21 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
|
||||
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
|
||||
}
|
||||
|
||||
if (vm->vm_tpr_threshold > VMX_Read_TPR_Shadow()) {
|
||||
BX_ERROR(("VMFAIL: VMCS EXEC CTRL: TPR threshold > TPR shadow"));
|
||||
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
|
||||
if (! (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)) {
|
||||
Bit8u tpr_shadow = (VMX_Read_VTPR() >> 4) & 0xf;
|
||||
if (vm->vm_tpr_threshold > tpr_shadow) {
|
||||
BX_ERROR(("VMFAIL: VMCS EXEC CTRL: TPR threshold > TPR shadow"));
|
||||
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
VM entries perform the following checks on the VM-execution control fields:
|
||||
|
||||
If the "use TPR shadow" VM-execution control is 1, the virtual-APIC address must
|
||||
satisfy the following checks:
|
||||
The following items describe the treatment of bytes 81H-83H on the virtual-
|
||||
APIC page (see Section 20.6.8) if all of the above checks are satisfied and the
|
||||
"use TPR shadow" VM-execution control is 1, treatment depends upon the
|
||||
setting of the "virtualize APIC accesses" VM-execution control:2
|
||||
- If the "virtualize APIC accesses" VM-execution control is 0, the bytes may be
|
||||
cleared. (If the bytes are not cleared, they are left unmodified.)
|
||||
- If the "virtualize APIC accesses" VM-execution control is 1, the bytes are
|
||||
cleared.
|
||||
- Any clearing of the bytes occurs even if the VM entry subsequently fails.
|
||||
If the "use TPR shadow" VM-execution control is 1, bits 31:4 of the TPR threshold
|
||||
VM-execution control field must be 0.
|
||||
The following check is performed if the "use TPR shadow" VM-execution control is
|
||||
1 and the "virtualize APIC accesses" VM-execution control is 0: the value of
|
||||
bits 3:0 of the TPR threshold VM-execution control field should not be greater
|
||||
than the value of bits 7:4 in byte 80H on the virtual-APIC page (see Section
|
||||
20.6.8).
|
||||
If the "virtualize APIC-accesses" VM-execution control is 1, the APIC-access
|
||||
address must satisfy the following checks:
|
||||
- Bits 11:0 of the address must be 0.
|
||||
- On processors that support Intel 64 architecture, the address should not set
|
||||
any bits beyond the processor's physical-address width.
|
||||
- On processors that support the IA-32 architecture, the address should not set
|
||||
any bits in the range 63:32.
|
||||
*/
|
||||
if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES) {
|
||||
if ((vm->apic_access_page & 0xfff) != 0 || ! IsValidPhyAddr(vm->apic_access_page)) {
|
||||
BX_ERROR(("VMFAIL: VMCS EXEC CTRL: apic access page phy addr malformed"));
|
||||
return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Load VM-exit control fields to VMCS Cache
|
||||
@ -1300,6 +1281,9 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
}
|
||||
SetCR3(guest.cr3);
|
||||
|
||||
// flush TLB to invalidate possible APIC ACCESS PAGE caching by host
|
||||
TLB_flush();
|
||||
|
||||
if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS) {
|
||||
// always clear bits 15:14 and set bit 10
|
||||
BX_CPU_THIS_PTR dr7 = (guest.dr7 & ~0xc000) | 0400;
|
||||
@ -1892,8 +1876,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXON(bxInstruction_c *i)
|
||||
}
|
||||
else {
|
||||
// in VMX root operation mode
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMXON with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
VMfail(VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
|
||||
}
|
||||
@ -1914,8 +1900,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXOFF(bxInstruction_c *i)
|
||||
VMexit_Instruction(i, VMX_VMEXIT_VMXOFF);
|
||||
}
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMXOFF with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
if dual-monitor treatment of SMIs and SMM is active
|
||||
@ -1952,8 +1940,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCALL(bxInstruction_c *i)
|
||||
if (BX_CPU_THIS_PTR get_VM() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT)
|
||||
exception(BX_UD_EXCEPTION, 0);
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMCALL with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
if (BX_CPU_THIS_PTR in_smm /*||
|
||||
(the logical processor does not support the dual-monitor treatment of SMIs and SMM) ||
|
||||
@ -2032,8 +2022,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLAUNCH(bxInstruction_c *i)
|
||||
VMexit_Instruction(i, vmlaunch ? VMX_VMEXIT_VMLAUNCH : VMX_VMEXIT_VMRESUME);
|
||||
}
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMLAUNCH/VMRESUME with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
if (! VMCSPTR_VALID()) {
|
||||
BX_ERROR(("VMFAIL: VMLAUNCH with invalid VMCS ptr !"));
|
||||
@ -2183,8 +2175,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPTRLD(bxInstruction_c *i)
|
||||
VMexit_Instruction(i, VMX_VMEXIT_VMPTRLD);
|
||||
}
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMPTRLD with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
||||
Bit64u pAddr = read_virtual_qword(i->seg(), eaddr); // keep 64-bit
|
||||
@ -2226,8 +2220,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPTRST(bxInstruction_c *i)
|
||||
VMexit_Instruction(i, VMX_VMEXIT_VMPTRST);
|
||||
}
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMPTRST with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
||||
write_virtual_qword(i->seg(), eaddr, BX_CPU_THIS_PTR vmcsptr);
|
||||
@ -2249,8 +2245,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMREAD(bxInstruction_c *i)
|
||||
VMexit_Instruction(i, VMX_VMEXIT_VMREAD);
|
||||
}
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMREAD with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
if (! VMCSPTR_VALID()) {
|
||||
BX_ERROR(("VMFAIL: VMREAD with invalid VMCS ptr !"));
|
||||
@ -2529,8 +2527,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMWRITE(bxInstruction_c *i)
|
||||
VMexit_Instruction(i, VMX_VMEXIT_VMWRITE);
|
||||
}
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMWRITE with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
if (! VMCSPTR_VALID()) {
|
||||
BX_ERROR(("VMFAIL: VMWRITE with invalid VMCS ptr !"));
|
||||
@ -2821,8 +2821,10 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCLEAR(bxInstruction_c *i)
|
||||
VMexit_Instruction(i, VMX_VMEXIT_VMCLEAR);
|
||||
}
|
||||
|
||||
if (CPL != 0)
|
||||
if (CPL != 0) {
|
||||
BX_ERROR(("VMCLEAR with CPL!=0 will cause #GP(0)"));
|
||||
exception(BX_GP_EXCEPTION, 0);
|
||||
}
|
||||
|
||||
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
|
||||
Bit64u pAddr = read_virtual_qword(i->seg(), eaddr); // keep 64-bit
|
||||
@ -2863,12 +2865,14 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCLEAR(bxInstruction_c *i)
|
||||
void BX_CPU_C::register_vmx_state(bx_param_c *parent)
|
||||
{
|
||||
// register VMX state for save/restore param tree
|
||||
bx_list_c *vmx = new bx_list_c(parent, "VMX", 6);
|
||||
bx_list_c *vmx = new bx_list_c(parent, "VMX", 8);
|
||||
|
||||
BXRS_HEX_PARAM_FIELD(vmx, vmcsptr, BX_CPU_THIS_PTR vmcsptr);
|
||||
BXRS_HEX_PARAM_FIELD(vmx, vmxonptr, BX_CPU_THIS_PTR vmxonptr);
|
||||
BXRS_PARAM_BOOL(vmx, in_vmx, BX_CPU_THIS_PTR in_vmx);
|
||||
BXRS_PARAM_BOOL(vmx, in_vmx_guest, BX_CPU_THIS_PTR in_vmx_guest);
|
||||
BXRS_PARAM_BOOL(vmx, in_smm_vmx, BX_CPU_THIS_PTR in_smm_vmx);
|
||||
BXRS_PARAM_BOOL(vmx, in_smm_vmx_guest, BX_CPU_THIS_PTR in_smm_vmx_guest);
|
||||
BXRS_PARAM_BOOL(vmx, vmx_interrupt_window, BX_CPU_THIS_PTR vmx_interrupt_window);
|
||||
|
||||
bx_list_c *vmcache = new bx_list_c(vmx, "VMCS_CACHE", 5);
|
||||
@ -2877,7 +2881,7 @@ void BX_CPU_C::register_vmx_state(bx_param_c *parent)
|
||||
// VM-Execution Control Fields
|
||||
//
|
||||
|
||||
bx_list_c *vmexec_ctrls = new bx_list_c(vmcache, "VMEXEC_CTRLS", 22);
|
||||
bx_list_c *vmexec_ctrls = new bx_list_c(vmcache, "VMEXEC_CTRLS", 23);
|
||||
|
||||
BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vmexec_ctrls1, BX_CPU_THIS_PTR vmcs.vmexec_ctrls1);
|
||||
BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vmexec_ctrls2, BX_CPU_THIS_PTR vmcs.vmexec_ctrls2);
|
||||
@ -2900,6 +2904,7 @@ void BX_CPU_C::register_vmx_state(bx_param_c *parent)
|
||||
BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr3_target_value4, BX_CPU_THIS_PTR vmcs.vm_cr3_target_value[3]);
|
||||
BXRS_HEX_PARAM_FIELD(vmexec_ctrls, virtual_apic_page_addr, BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr);
|
||||
BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_tpr_threshold, BX_CPU_THIS_PTR vmcs.vm_tpr_threshold);
|
||||
BXRS_HEX_PARAM_FIELD(vmexec_ctrls, apic_access_page, BX_CPU_THIS_PTR vmcs.apic_access_page);
|
||||
BXRS_HEX_PARAM_FIELD(vmexec_ctrls, executive_vmcsptr, BX_CPU_THIS_PTR vmcs.executive_vmcsptr);
|
||||
|
||||
//
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: vmx.h,v 1.14 2010-03-15 15:49:55 sshwarts Exp $
|
||||
// $Id: vmx.h,v 1.15 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009 Stanislav Shwartsman
|
||||
@ -153,6 +153,12 @@ enum VMX_vmabort_code {
|
||||
VMABORT_VMEXIT_MACHINE_CHECK_ERROR
|
||||
};
|
||||
|
||||
// VMX APIC ACCESS VMEXIT qualification
|
||||
#define VMX_APIC_READ_INSTRUCTION_EXECUTION 0x0000
|
||||
#define VMX_APIC_WRITE_INSTRUCTION_EXECUTION 0x1000
|
||||
#define VMX_APIC_INSTRUCTION_FETCH 0x2000 /* won't happen because cpu::prefetch will crash */
|
||||
#define VMX_APIC_ACCESS_DURING_EVENT_DELIVERY 0x3000
|
||||
|
||||
// =============
|
||||
// VMCS fields
|
||||
// =============
|
||||
@ -573,7 +579,8 @@ typedef struct bx_VMCS
|
||||
#else // only really supported features
|
||||
|
||||
#define VMX_VM_EXEC_CTRL3_SUPPORTED_BITS \
|
||||
(VMX_VM_EXEC_CTRL3_RDTSCP | \
|
||||
(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES | \
|
||||
VMX_VM_EXEC_CTRL3_RDTSCP | \
|
||||
VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT)
|
||||
|
||||
#endif
|
||||
@ -599,6 +606,7 @@ typedef struct bx_VMCS
|
||||
|
||||
bx_phy_address virtual_apic_page_addr;
|
||||
Bit32u vm_tpr_threshold;
|
||||
bx_phy_address apic_access_page;
|
||||
|
||||
Bit64u executive_vmcsptr;
|
||||
|
||||
@ -889,7 +897,7 @@ enum VMX_Activity_State {
|
||||
// 63:10 reserved, must be zero
|
||||
//
|
||||
|
||||
#define VMX_HIGHEST_VMCS_ENCODING 0x2A
|
||||
#define VMX_HIGHEST_VMCS_ENCODING 0x2C
|
||||
|
||||
#define VMX_MSR_VMCS_ENUM_LO (VMX_HIGHEST_VMCS_ENCODING)
|
||||
#define VMX_MSR_VMCS_ENUM_HI (0x00000000)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: misc_mem.cc,v 1.143 2010-03-07 09:16:24 sshwarts Exp $
|
||||
// $Id: misc_mem.cc,v 1.144 2010-03-16 14:51:20 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2009 The Bochs Project
|
||||
@ -73,7 +73,7 @@ void BX_MEM_C::init_memory(Bit64u guest, Bit64u host)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.143 2010-03-07 09:16:24 sshwarts Exp $"));
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.144 2010-03-16 14:51:20 sshwarts Exp $"));
|
||||
|
||||
// accept only memory size which is multiply of 1M
|
||||
BX_ASSERT((host & 0xfffff) == 0);
|
||||
@ -572,13 +572,6 @@ Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw)
|
||||
if (a20addr > BX_CONST64(0xffffffff)) is_bios = 0;
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
if (cpu != NULL) {
|
||||
if (cpu->lapic.is_selected(a20addr))
|
||||
return(NULL); // Vetoed! APIC address space
|
||||
}
|
||||
#endif
|
||||
|
||||
bx_bool write = rw & 1;
|
||||
|
||||
// allow direct access to SMRAM memory space for code and veto data
|
||||
@ -592,7 +585,7 @@ Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address addr, unsigned rw)
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_MONITOR_MWAIT
|
||||
if (write && BX_MEM_THIS is_monitor(a20addr & ~0xfff, 0x1000)) {
|
||||
if (write && BX_MEM_THIS is_monitor(a20addr & ~((bx_phy_address)(0xfff)), 0xfff)) {
|
||||
// Vetoed! Write monitored page !
|
||||
return(NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user