Fixed setting of reserved bits in CR3 register

This commit is contained in:
Stanislav Shwartsman 2008-05-11 19:36:06 +00:00
parent 8a94fc2315
commit 4a76bd2169
6 changed files with 60 additions and 39 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.475 2008-05-10 20:35:03 sshwarts Exp $
// $Id: cpu.h,v 1.476 2008-05-11 19:36:06 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -805,7 +805,7 @@ public: // for now...
bx_cr0_t cr0;
Bit32u cr1;
bx_address cr2;
bx_phy_address cr3, cr3_masked;
bx_address cr3, cr3_masked;
#if BX_CPU_LEVEL >= 4
bx_cr4_t cr4;
#endif
@ -2952,7 +2952,7 @@ public: // for now...
BX_SMF int int_number(bx_segment_reg_t *seg);
BX_SMF int int_number(unsigned s);
BX_SMF void SetCR0(Bit32u val_32) BX_CPP_AttrRegparmN(1);
BX_SMF void CR3_change(bx_phy_address value) BX_CPP_AttrRegparmN(1);
BX_SMF void SetCR3(bx_address value) BX_CPP_AttrRegparmN(1);
#if BX_CPU_LEVEL >= 4
BX_SMF bx_bool SetCR4(bx_address val) BX_CPP_AttrRegparmN(1);
#endif

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: init.cc,v 1.169 2008-04-27 19:48:58 sshwarts Exp $
// $Id: init.cc,v 1.170 2008-05-11 19:36:06 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -646,7 +646,7 @@ Bit64s BX_CPU_C::param_restore(bx_param_c *param, Bit64s val)
void BX_CPU_C::after_restore_state(void)
{
SetCR0(cr0.val32);
CR3_change(cr3);
SetCR3(cr3);
TLB_flush(1);
assert_checks();
invalidate_prefetch_q();

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.128 2008-05-10 22:11:48 sshwarts Exp $
// $Id: paging.cc,v 1.129 2008-05-11 19:36:06 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -409,8 +409,12 @@ static unsigned tlbNonGlobalFlushes=0;
#define InstrTLB_Increment(v)
#endif
// ==============================================================
#define BX_PHY_ADDRESS_MASK ((((Bit64u)(1)) << BX_PHY_ADDRESS_WIDTH) - 1)
#define BX_PHY_ADDRESS_RESERVED_BITS \
(~BX_PHY_ADDRESS_MASK & BX_CONST64(0xfffffffffffff))
// ==============================================================
void BX_CPP_AttrRegparmN(2)
BX_CPU_C::pagingCR0Changed(Bit32u oldCR0, Bit32u newCR0)
@ -446,22 +450,36 @@ BX_CPU_C::pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4)
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::CR3_change(bx_phy_address value)
BX_CPU_C::SetCR3(bx_address val)
{
if (bx_dbg.paging) {
BX_DEBUG(("CR3_change(): flush TLB cache"));
BX_DEBUG(("Page Directory Base: 0x" FMT_PHY_ADDRX, value));
BX_DEBUG(("SetCR3(): flush TLB cache"));
BX_DEBUG(("Page Directory Base: 0x" FMT_PHY_ADDRX, val));
}
// flush TLB even if value does not change
TLB_flush(0); // 0 = Don't flush Global entries.
BX_CPU_THIS_PTR cr3 = value;
#if BX_SUPPORT_PAE
if (BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode())
BX_CPU_THIS_PTR cr3_masked = value & 0xffffffe0;
if (BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) {
BX_CPU_THIS_PTR cr3_masked = val & 0xffffffe0;
BX_CPU_THIS_PTR cr3 = val & 0xffffffff;
}
else
#endif
BX_CPU_THIS_PTR cr3_masked = value & BX_CONST64(0x000ffffffffff000);
{
#if BX_PHY_ADDRESS_WIDTH == 32
if (val & BX_CONST64(0x000fffff00000000)) {
BX_PANIC(("SetCR3() 0x%08x%08x: Only 32 bit physical address space is emulated !", GET32H(val), GET32L(val)));
}
#endif
if (val & BX_PHY_ADDRESS_RESERVED_BITS) {
BX_ERROR(("SetCR3(): Attempt to write to reserved bits of CR3"));
exception(BX_GP_EXCEPTION, 0, 0);
}
BX_CPU_THIS_PTR cr3_masked = val & BX_CONST64(0x000ffffffffff000);
BX_CPU_THIS_PTR cr3 = val;
}
}
// Called to initialize the TLB upon startup.
@ -598,27 +616,23 @@ void BX_CPU_C::page_fault(unsigned fault, bx_address laddr, unsigned user, unsig
exception(BX_PF_EXCEPTION, error_code, 0);
}
#define BX_PHY_ADDRESS_MASK ~((((Bit64u)(1)) << BX_PHY_ADDRESS_WIDTH) - 1)
/* PAE PML4: bits [51 .. physical address width], [7] */
#define PAGING_PAE_PML4_RESERVED_BITS \
(BX_PHY_ADDRESS_MASK & BX_CONST64(0x000FFFFFFFFFFFFF) | BX_CONST64(0x00000080))
(BX_PHY_ADDRESS_RESERVED_BITS | BX_CONST64(0x00000080))
/* PAE PDPE: bits [51 .. physical address width], [7] - not support 1G paging */
#define PAGING_PAE_PDPE_RESERVED_BITS \
(BX_PHY_ADDRESS_MASK & BX_CONST64(0x000FFFFFFFFFFFFF) | BX_CONST64(0x00000080))
(BX_PHY_ADDRESS_RESERVED_BITS | BX_CONST64(0x00000080))
/* PAE PDE: bits [51 .. physical address width] */
#define PAGING_PAE_PDE_RESERVED_BITS \
(BX_PHY_ADDRESS_MASK & BX_CONST64(0x000FFFFFFFFFFFFF))
#define PAGING_PAE_PDE_RESERVED_BITS (BX_PHY_ADDRESS_RESERVED_BITS)
/* PAE PDE4M: bits [51 .. physical address width], [20:13] */
#define PAGING_PAE_PDE4M_RESERVED_BITS \
(PAGING_PAE_PDE_RESERVED_BITS | BX_CONST64(0x001FE000))
/* PAE PTE: bits [51 .. physical address width] */
#define PAGING_PAE_PTE_RESERVED_BITS \
(BX_PHY_ADDRESS_MASK & BX_CONST64(0x000FFFFFFFFFFFFF))
#define PAGING_PAE_PTE_RESERVED_BITS (BX_PHY_ADDRESS_RESERVED_BITS)
#define PAGE_DIRECTORY_NX_BIT (BX_CONST64(0x8000000000000000))
@ -683,9 +697,11 @@ bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned curr_pl, un
BX_DEBUG(("PML4: entry not present"));
page_fault(ERROR_NOT_PRESENT, laddr, pl, isWrite, access_type);
}
#if BX_PHY_ADDRESS_WIDTH == 32
if (pml4 & BX_CONST64(0x000fffff00000000)) {
BX_PANIC(("PML4 0x%08x%08x: Only 32 bit physical address space is emulated !", GET32H(pml4), GET32L(pml4)));
}
#endif
if (pml4 & PAGING_PAE_PML4_RESERVED_BITS) {
BX_DEBUG(("PML4: reserved bit is set PML4=%08x:%08x", GET32H(pml4), GET32L(pml4)));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, isWrite, access_type);
@ -723,9 +739,11 @@ bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned curr_pl, un
BX_DEBUG(("PAE PDPE: entry not present"));
page_fault(ERROR_NOT_PRESENT, laddr, pl, isWrite, access_type);
}
#if BX_PHY_ADDRESS_WIDTH == 32
if (pdpe & BX_CONST64(0x000fffff00000000)) {
BX_PANIC(("PAE PDPE 0x%08x%08x: Only 32 bit physical address space is emulated !", GET32H(pdpe), GET32L(pdpe)));
}
#endif
if (pdpe & PAGING_PAE_PDPE_RESERVED_BITS) {
BX_DEBUG(("PAE PDPE: reserved bit is set: PDPE=%08x:%08x", GET32H(pdpe), GET32L(pdpe)));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, isWrite, access_type);
@ -752,9 +770,11 @@ bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned curr_pl, un
BX_DEBUG(("PAE PDE: entry not present"));
page_fault(ERROR_NOT_PRESENT, laddr, pl, isWrite, access_type);
}
#if BX_PHY_ADDRESS_WIDTH == 32
if (pde & BX_CONST64(0x000fffff00000000)) {
BX_PANIC(("PAE PDE 0x%08x%08x: Only 32 bit physical address space is emulated !", GET32H(pde), GET32L(pde)));
}
#endif
if (pde & PAGING_PAE_PDE_RESERVED_BITS) {
BX_DEBUG(("PAE PDE: reserved bit is set PDE=%08x:%08x", GET32H(pde), GET32L(pde)));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, isWrite, access_type);
@ -833,9 +853,11 @@ bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned curr_pl, un
BX_DEBUG(("PAE PTE: entry not present"));
page_fault(ERROR_NOT_PRESENT, laddr, pl, isWrite, access_type);
}
#if BX_PHY_ADDRESS_WIDTH == 32
if (pte & BX_CONST64(0x000fffff00000000)) {
BX_PANIC(("PAE PTE 0x%08x%08x: Only 32 bit physical address space is emulated !", GET32H(pte), GET32L(pte)));
}
#endif
if (pte & PAGING_PAE_PTE_RESERVED_BITS) {
BX_DEBUG(("PAE PTE: reserved bit is set PTE=%08x:%08x", GET32H(pte), GET32L(pte)));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, isWrite, access_type);
@ -923,11 +945,11 @@ bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned curr_pl, un
{
// Note: when the PSE and PAE flags in CR4 are set, the
// processor generates a PF if the reserved bits are not zero.
#if BX_PHY_ADDRESS_WIDTH == 32
if (pde & 0x0001e000) {
BX_PANIC(("PSE PDE 0x%08x: Only 32 bit physical address space is emulated !", pde));
}
#endif
// Combined access is just access from the pde (no pte involved).
combined_access = pde & 0x06; // U/S and R/W
@ -1103,7 +1125,7 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, pt_address, 8, &pte);
if(!(pte & 1))
goto page_fault;
if ((pte & BX_PHY_ADDRESS_MASK & BX_CONST64(0x000fffffffffffff)))
if (pte & BX_PHY_ADDRESS_RESERVED_BITS)
goto page_fault;
pt_address = bx_phy_address(pte & BX_CONST64(0x000ffffffffff000));
if (level == 1 && (pte & 0x80)) { // PSE page

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.229 2008-05-10 18:10:53 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.230 2008-05-11 19:36:06 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -624,7 +624,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CdRd(bxInstruction_c *i)
case 3: // CR3
BX_DEBUG(("MOV_CdRd:CR3 = %08x", val_32));
// Reserved bits take on value of MOV instruction
CR3_change(val_32);
SetCR3(val_32);
BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR3, val_32);
break;
case 4: // CR4
@ -676,7 +676,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RdCd(bxInstruction_c *i)
break;
case 3: // CR3
BX_DEBUG(("MOV_RdCd: reading CR3"));
val_32 = BX_CPU_THIS_PTR cr3;
val_32 = (Bit32u) BX_CPU_THIS_PTR cr3;
break;
case 4: // CR4
#if BX_CPU_LEVEL < 4
@ -733,16 +733,13 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CqRq(bxInstruction_c *i)
break;
case 3: // CR3
BX_DEBUG(("MOV_CqRq: write to CR3 of %08x:%08x", GET32H(val_64), GET32L(val_64)));
if (val_64 & BX_CONST64(0xffffffff00000000)) {
BX_PANIC(("CR3 write: Only 32 bit physical address space is emulated !"));
}
// Reserved bits take on value of MOV instruction
CR3_change((bx_phy_address) val_64);
SetCR3(val_64);
BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR3, val_64);
break;
case 4: // CR4
// Protected mode: #GP(0) if attempt to write a 1 to
// any reserved bit of CR4
// Protected mode: #GP(0) if attempt to write a 1 to
// any reserved bit of CR4
BX_DEBUG(("MOV_CqRq: write to CR4 of %08x:%08x", GET32H(val_64), GET32L(val_64)));
if (! SetCR4(val_64))
exception(BX_GP_EXCEPTION, 0, 0);
@ -1817,9 +1814,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i)
if (BX_CPU_THIS_PTR msr.apicbase & 0x800) {
BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", EDX, EAX));
BX_CPU_THIS_PTR msr.apicbase = EAX; /* ignore the high 32bits */
#if BX_PHY_ADDRESS_WIDTH == 32
if (EDX != 0) {
BX_PANIC(("MSR_APICBASE: Only 32 bit physical address space is emulated !"));
}
#endif
BX_CPU_THIS_PTR local_apic.set_base(BX_CPU_THIS_PTR msr.apicbase);
// TLB flush is required for emulation correctness
TLB_flush(1); // don't care about performance of apic relocation

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: smm.cc,v 1.38 2008-04-27 19:49:02 sshwarts Exp $
// $Id: smm.cc,v 1.39 2008-05-11 19:36:06 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006 Stanislav Shwartsman
@ -395,7 +395,7 @@ bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state)
setEFlags(temp_eflags);
bx_phy_address temp_cr3 = SMRAM_FIELD(saved_state, SMRAM_OFFSET_CR3);
CR3_change(temp_cr3);
SetCR3(temp_cr3);
RAX = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RAX_HI32, SMRAM_OFFSET_RAX_LO32);
RBX = SMRAM_FIELD64(saved_state, SMRAM_OFFSET_RBX_HI32, SMRAM_OFFSET_RBX_LO32);
@ -658,7 +658,7 @@ bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state)
}
SetCR0(temp_cr0);
CR3_change(temp_cr3);
SetCR3(temp_cr3);
setEFlags(temp_eflags);
#if BX_CPU_LEVEL >= 4

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: tasking.cc,v 1.58 2008-05-09 22:33:36 sshwarts Exp $
// $Id: tasking.cc,v 1.59 2008-05-11 19:36:06 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -420,7 +420,7 @@ void BX_CPU_C::task_switch(bx_selector_t *tss_selector,
if ((tss_descriptor->type >= 9) && BX_CPU_THIS_PTR cr0.get_PG()) {
// change CR3 only if it actually modified
if (newCR3 != BX_CPU_THIS_PTR cr3) {
CR3_change(newCR3); // Tell paging unit about new cr3 value
SetCR3(newCR3); // Tell paging unit about new cr3 value
BX_DEBUG (("task_switch changing CR3 to 0x" FMT_PHY_ADDRX, newCR3));
BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_TASKSWITCH, newCR3);
}