implement pdptr checks in legacy PAE mode
This commit is contained in:
parent
222129db4b
commit
03ba2ec988
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.600 2009-05-30 15:09:38 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.601 2009-05-31 07:49:03 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -3095,7 +3095,7 @@ public: // for now...
|
||||
BX_SMF void pagingCR0Changed(Bit32u oldCR0, Bit32u newCR0) BX_CPP_AttrRegparmN(2);
|
||||
BX_SMF void pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4) BX_CPP_AttrRegparmN(2);
|
||||
#if BX_SUPPORT_PAE
|
||||
BX_SMF bx_bool CheckPDPTR(bx_bool pg, bx_bool pae, bx_address cr3_val);
|
||||
BX_SMF bx_bool CheckPDPTR(Bit32u cr3_val) BX_CPP_AttrRegparmN(1);
|
||||
#endif
|
||||
|
||||
BX_SMF void reset(unsigned source);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: paging.cc,v 1.175 2009-05-30 15:09:38 sshwarts Exp $
|
||||
// $Id: paging.cc,v 1.176 2009-05-31 07:49:04 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -448,8 +448,7 @@ BX_CPU_C::pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4)
|
||||
#endif
|
||||
}
|
||||
|
||||
void BX_CPP_AttrRegparmN(1)
|
||||
BX_CPU_C::SetCR3(bx_address val)
|
||||
void BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR3(bx_address val)
|
||||
{
|
||||
// flush TLB even if value does not change
|
||||
#if BX_SUPPORT_GLOBAL_PAGES
|
||||
@ -478,7 +477,9 @@ BX_CPU_C::SetCR3(bx_address val)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
BX_CPU_THIS_PTR cr3_masked = val & 0xffffffe0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -488,26 +489,28 @@ BX_CPU_C::SetCR3(bx_address val)
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_PAE
|
||||
bx_bool BX_CPU_C::CheckPDPTR(bx_bool pg, bx_bool pae, bx_address cr3_val)
|
||||
bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::CheckPDPTR(Bit32u cr3_val)
|
||||
{
|
||||
if (pg && pae && !long_mode())
|
||||
{
|
||||
cr3_val &= 0xffffffe0;
|
||||
cr3_val &= 0xffffffe0;
|
||||
|
||||
for (int n=0; n<4; n++) {
|
||||
Bit64u pdptr;
|
||||
// read PDPE cache entry
|
||||
bx_phy_address entry_pdpe_addr = (bx_phy_address) (cr3_val | (n << 3));
|
||||
access_read_physical(entry_pdpe_addr, 8, (Bit8u*)(&pdptr));
|
||||
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, entry_pdpe_addr, 8, BX_READ, (Bit8u*)(&pdptr));
|
||||
for (int n=0; n<4; n++) {
|
||||
// read PDPE cache entry
|
||||
bx_phy_address entry_pdpe_addr = (bx_phy_address) (cr3_val | (n << 3));
|
||||
access_read_physical(entry_pdpe_addr, 8, &(BX_CPU_THIS_PTR PDPE_CACHE.entry[n]));
|
||||
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, entry_pdpe_addr, 8,
|
||||
BX_READ, (Bit8u*)(&BX_CPU_THIS_PTR PDPE_CACHE.entry[n]));
|
||||
|
||||
if (pdptr & 0x1) {
|
||||
if (pdptr & PAGING_PAE_PDPE_RESERVED_BITS)
|
||||
return 0;
|
||||
Bit64u pdptr = BX_CPU_THIS_PTR PDPE_CACHE.entry[n];
|
||||
if (pdptr & 0x1) {
|
||||
if (pdptr & PAGING_PAE_PDPE_RESERVED_BITS) {
|
||||
BX_CPU_THIS_PTR PDPE_CACHE.valid = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BX_CPU_THIS_PTR PDPE_CACHE.valid = 1;
|
||||
|
||||
return 1; /* PDPTRs are fine */
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: proc_ctrl.cc,v 1.297 2009-05-30 15:09:38 sshwarts Exp $
|
||||
// $Id: proc_ctrl.cc,v 1.298 2009-05-31 07:49:04 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -650,7 +650,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_CR3_Write(i, val_32);
|
||||
#endif
|
||||
// Reserved bits take on value of MOV instruction
|
||||
if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) {
|
||||
if (! CheckPDPTR(val_32)) {
|
||||
BX_ERROR(("SetCR3(): PDPTR check failed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
}
|
||||
SetCR3(val_32);
|
||||
BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR3, val_32);
|
||||
break;
|
||||
@ -659,6 +664,12 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
|
||||
#if BX_SUPPORT_VMX
|
||||
val_32 = VMexit_CR4_Write(i, val_32);
|
||||
#endif
|
||||
if (BX_CPU_THIS_PTR cr0.get_PG() && (val_32 & (1<<5)) != 0 /* PAE */ && !long_mode()) {
|
||||
if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) {
|
||||
BX_ERROR(("SetCR4(): PDPTR check failed !"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
}
|
||||
// Protected mode: #GP(0) if attempt to write a 1 to
|
||||
// any reserved bit of CR4
|
||||
if (! SetCR4(val_32))
|
||||
@ -759,7 +770,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
|
||||
#if BX_SUPPORT_VMX
|
||||
VMexit_CR3_Write(i, val_64);
|
||||
#endif
|
||||
// Reserved bits take on value of MOV instruction
|
||||
// no PDPTR checks in long mode
|
||||
SetCR3(val_64);
|
||||
BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR3, val_64);
|
||||
break;
|
||||
@ -768,6 +779,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
|
||||
val_64 = VMexit_CR4_Write(i, val_64);
|
||||
#endif
|
||||
BX_DEBUG(("MOV_CqRq: write to CR4 of %08x:%08x", GET32H(val_64), GET32L(val_64)));
|
||||
// no PDPTR checks in long mode
|
||||
if (! SetCR4(val_64))
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
break;
|
||||
@ -1352,6 +1364,14 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR0(bx_address val)
|
||||
}
|
||||
BX_CPU_THIS_PTR efer.set_LMA(1);
|
||||
}
|
||||
#if BX_SUPPORT_PAE
|
||||
if (BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) {
|
||||
if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) {
|
||||
BX_ERROR(("SetCR0(): PDPTR check failed !"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (prev_pg==1 && ! pg) {
|
||||
if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
|
||||
@ -1474,7 +1494,7 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR4(bx_address val)
|
||||
// need to GP(0) if LMA=1 and PAE=1->0
|
||||
if (BX_CPU_THIS_PTR efer.get_LMA()) {
|
||||
if(!(val & (1<<5)) && BX_CPU_THIS_PTR cr4.get_PAE()) {
|
||||
BX_ERROR(("SetCR4: attempt to change PAE when EFER.LMA=1"));
|
||||
BX_ERROR(("SetCR4(): attempt to change PAE when EFER.LMA=1"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1482,7 +1502,7 @@ bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR4(bx_address val)
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
if (!(val & (1 << 13)) && BX_CPU_THIS_PTR in_vmx) {
|
||||
BX_ERROR(("Attempt to clear CR4.VMXE in vmx mode"));
|
||||
BX_ERROR(("SetCR4(): Attempt to clear CR4.VMXE in vmx mode"));
|
||||
exception(BX_GP_EXCEPTION, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: vmx.cc,v 1.18 2009-05-30 15:09:38 sshwarts Exp $
|
||||
// $Id: vmx.cc,v 1.19 2009-05-31 07:49:04 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2009 Stanislav Shwartsman
|
||||
@ -1165,6 +1165,17 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
}
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_PAE
|
||||
if (! x86_64_guest && (guest.cr4 & (1 << 5)) != 0 /* PAE */) {
|
||||
// CR0.PG is always set in VMX mode
|
||||
if (! CheckPDPTR(guest.cr3)) {
|
||||
*qualification = VMENTER_ERR_GUEST_STATE_PDPTR_LOADING;
|
||||
BX_ERROR(("VMENTER: Guest State PDPTRs Checks Failed"));
|
||||
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Load Guest State -> VMENTER
|
||||
//
|
||||
@ -1185,10 +1196,10 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
if (!SetCR0((old_cr0 & VMX_KEEP_CR0_BITS) | (guest.cr0 & ~VMX_KEEP_CR0_BITS))) {
|
||||
BX_PANIC(("VMENTER CR0 is broken !"));
|
||||
}
|
||||
SetCR3(guest.cr3);
|
||||
if (!SetCR4(guest.cr4)) { // improssible if CR4 checks were correct
|
||||
if (!SetCR4(guest.cr4)) { // cannot fail if CR4 checks were correct
|
||||
BX_PANIC(("VMENTER CR4 is broken !"));
|
||||
}
|
||||
SetCR3(guest.cr3);
|
||||
|
||||
if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS) {
|
||||
// always clear bits 15:14 and set bit 10
|
||||
@ -1487,10 +1498,10 @@ void BX_CPU_C::VMexitLoadHostState(void)
|
||||
if (!SetCR0((old_cr0 & VMX_KEEP_CR0_BITS) | (host_state->cr0 & ~VMX_KEEP_CR0_BITS))) {
|
||||
BX_PANIC(("VMEXIT CR0 is broken !"));
|
||||
}
|
||||
SetCR3(host_state->cr3);
|
||||
if (!SetCR4(host_state->cr4)) {
|
||||
BX_PANIC(("VMEXIT CR4 is broken !"));
|
||||
}
|
||||
SetCR3(host_state->cr3);
|
||||
|
||||
BX_CPU_THIS_PTR dr7 = 0x00000400;
|
||||
|
||||
@ -1960,13 +1971,6 @@ void BX_CPU_C::VMLAUNCH(bxInstruction_c *i)
|
||||
VMexit(0, state_load_error | (1 << 31), qualification);
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_PAE
|
||||
if (! CheckPDPTR(BX_CPU_THIS_PTR cr0.get_PG(), BX_CPU_THIS_PTR cr4.get_PAE(), BX_CPU_THIS_PTR cr3)) {
|
||||
BX_ERROR(("VMEXIT: Guest State PDPTRs Checks Failed"));
|
||||
VMexit(0, VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE | (1 << 31), VMENTER_ERR_GUEST_STATE_PDPTR_LOADING);
|
||||
}
|
||||
#endif
|
||||
|
||||
Bit32u msr = LoadMSRs(BX_CPU_THIS_PTR vmcs.vmentry_msr_load_cnt, BX_CPU_THIS_PTR vmcs.vmentry_msr_load_addr);
|
||||
if (msr) {
|
||||
BX_ERROR(("VMEXIT: Error when loading guest MSR 0x%08x", msr));
|
||||
|
Loading…
Reference in New Issue
Block a user