Fixed CR3 masking in long mode

Added PANIC assertion of 32-bit physical address in PAE mode
cleanup
This commit is contained in:
Stanislav Shwartsman 2006-10-04 19:08:40 +00:00
parent 4df1ef8af5
commit 6c63e84d23
9 changed files with 87 additions and 86 deletions

View File

@ -1,5 +1,5 @@
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// $Id: call_far.cc,v 1.12 2006-06-12 16:58:26 sshwarts Exp $ // $Id: call_far.cc,v 1.13 2006-10-04 19:08:39 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -121,7 +121,7 @@ BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
} }
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
if (IsLongMode()) { if (long_mode()) {
if (gate_descriptor.type != BX_386_CALL_GATE) { if (gate_descriptor.type != BX_386_CALL_GATE) {
BX_ERROR(("call_protected: gate type %u unsupported in long mode", (unsigned) gate_descriptor.type)); BX_ERROR(("call_protected: gate type %u unsupported in long mode", (unsigned) gate_descriptor.type));
exception(BX_GP_EXCEPTION, cs_raw & 0xfffc, 0); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc, 0);

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.303 2006-08-25 19:56:03 sshwarts Exp $ // $Id: cpu.h,v 1.304 2006-10-04 19:08:39 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -331,11 +331,9 @@ const char* cpu_mode_string(unsigned cpu_mode);
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
#define Is64BitMode() (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) #define Is64BitMode() (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)
#define StackAddrSize64() (Is64BitMode()) #define StackAddrSize64() (Is64BitMode())
#define IsLongMode() (BX_CPU_THIS_PTR msr.lma)
#else #else
#define Is64BitMode() (0) #define Is64BitMode() (0)
#define StackAddrSize64() (0) #define StackAddrSize64() (0)
#define IsLongMode() (0)
#endif #endif
#if BX_SUPPORT_APIC #if BX_SUPPORT_APIC
@ -443,7 +441,7 @@ typedef struct {
set_VM(0); \ set_VM(0); \
} \ } \
BX_CPP_INLINE void BX_CPU_C::set_VM(Bit32u val) { \ BX_CPP_INLINE void BX_CPU_C::set_VM(Bit32u val) { \
if (IsLongMode()) return; \ if (long_mode()) return; \
if (val) { \ if (val) { \
BX_CPU_THIS_PTR eflags.val32 |= (1<<bitnum); \ BX_CPU_THIS_PTR eflags.val32 |= (1<<bitnum); \
BX_CPU_THIS_PTR eflags.VM_cached = 1; \ BX_CPU_THIS_PTR eflags.VM_cached = 1; \
@ -2917,6 +2915,7 @@ public: // for now...
BX_SMF BX_CPP_INLINE bx_bool smm_mode(void); BX_SMF BX_CPP_INLINE bx_bool smm_mode(void);
BX_SMF BX_CPP_INLINE bx_bool protected_mode(void); BX_SMF BX_CPP_INLINE bx_bool protected_mode(void);
BX_SMF BX_CPP_INLINE bx_bool v8086_mode(void); BX_SMF BX_CPP_INLINE bx_bool v8086_mode(void);
BX_SMF BX_CPP_INLINE bx_bool long_mode(void);
BX_SMF BX_CPP_INLINE unsigned get_cpu_mode(void); BX_SMF BX_CPP_INLINE unsigned get_cpu_mode(void);
#if BX_CPU_LEVEL >= 5 #if BX_CPU_LEVEL >= 5
@ -3096,6 +3095,15 @@ BX_CPP_INLINE bx_bool BX_CPU_C::protected_mode(void)
return (BX_CPU_THIS_PTR cpu_mode >= BX_MODE_IA32_PROTECTED); return (BX_CPU_THIS_PTR cpu_mode >= BX_MODE_IA32_PROTECTED);
} }
BX_CPP_INLINE unsigned BX_CPU_C::long_mode(void)
{
#if BX_SUPPORT_X86_64
return BX_CPU_THIS_PTR msr.lma;
#else
return 0;
#endif
}
BX_CPP_INLINE unsigned BX_CPU_C::get_cpu_mode(void) BX_CPP_INLINE unsigned BX_CPU_C::get_cpu_mode(void)
{ {
return (BX_CPU_THIS_PTR cpu_mode); return (BX_CPU_THIS_PTR cpu_mode);

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: exception.cc,v 1.85 2006-09-26 19:16:10 sshwarts Exp $ // $Id: exception.cc,v 1.86 2006-10-04 19:08:40 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -789,11 +789,11 @@ void BX_CPU_C::interrupt(Bit8u vector, bx_bool is_INT, bx_bool is_error_code, Bi
BX_CPU_THIS_PTR save_esp = RSP; BX_CPU_THIS_PTR save_esp = RSP;
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR msr.lma) { if (long_mode()) {
long_mode_int(vector, is_INT, is_error_code, error_code); long_mode_int(vector, is_INT, is_error_code, error_code);
return; return;
} }
#endif // #if BX_SUPPORT_X86_64 #endif
if(real_mode()) { if(real_mode()) {
real_mode_int(vector, is_INT, is_error_code, error_code); real_mode_int(vector, is_INT, is_error_code, error_code);

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: flag_ctrl_pro.cc,v 1.24 2006-04-05 17:31:31 sshwarts Exp $ // $Id: flag_ctrl_pro.cc,v 1.25 2006-10-04 19:08:40 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -35,7 +35,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::setEFlags(Bit32u val)
{ {
// VM flag could not be set from long mode // VM flag could not be set from long mode
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
if (IsLongMode()) { if (long_mode()) {
if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("VM is set in long mode !")); if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("VM is set in long mode !"));
val &= ~EFlagsVMMask; val &= ~EFlagsVMMask;
} }

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: init.cc,v 1.124 2006-09-20 17:02:20 sshwarts Exp $ // $Id: init.cc,v 1.125 2006-10-04 19:08:40 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -1168,7 +1168,7 @@ void BX_CPU_C::assert_checks(void)
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
// VM should be OFF in long mode // VM should be OFF in long mode
if (IsLongMode()) { if (long_mode()) {
if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("assert_checks: VM is set in long mode !")); if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("assert_checks: VM is set in long mode !"));
} }

View File

@ -1,5 +1,5 @@
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// $Id: jmp_far.cc,v 1.7 2006-06-12 16:58:27 sshwarts Exp $ // $Id: jmp_far.cc,v 1.8 2006-10-04 19:08:40 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -84,7 +84,7 @@ BX_CPU_C::jump_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp)
} }
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
if (IsLongMode()) { if (long_mode()) {
if (descriptor.type != BX_386_CALL_GATE) { if (descriptor.type != BX_386_CALL_GATE) {
BX_ERROR(("jump_protected: gate type %u unsupported in long mode", (unsigned) descriptor.type)); BX_ERROR(("jump_protected: gate type %u unsupported in long mode", (unsigned) descriptor.type));
exception(BX_GP_EXCEPTION, cs_raw & 0xfffc, 0); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc, 0);

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.77 2006-09-20 17:02:20 sshwarts Exp $ // $Id: paging.cc,v 1.78 2006-10-04 19:08:40 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -437,7 +437,7 @@ BX_CPU_C::pagingCR4Changed(Bit32u oldCR4, Bit32u newCR4)
#if BX_SUPPORT_PAE #if BX_SUPPORT_PAE
if ((oldCR4 & 0x00000020) != (newCR4 & 0x00000020)) { if ((oldCR4 & 0x00000020) != (newCR4 & 0x00000020)) {
if (BX_CPU_THIS_PTR cr4.get_PAE()) if (BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode())
BX_CPU_THIS_PTR cr3_masked = BX_CPU_THIS_PTR cr3 & 0xffffffe0; BX_CPU_THIS_PTR cr3_masked = BX_CPU_THIS_PTR cr3 & 0xffffffe0;
else else
BX_CPU_THIS_PTR cr3_masked = BX_CPU_THIS_PTR cr3 & 0xfffff000; BX_CPU_THIS_PTR cr3_masked = BX_CPU_THIS_PTR cr3 & 0xfffff000;
@ -457,7 +457,7 @@ BX_CPU_C::CR3_change(bx_phy_address value)
TLB_flush(0); // 0 = Don't flush Global entries. TLB_flush(0); // 0 = Don't flush Global entries.
BX_CPU_THIS_PTR cr3 = value; BX_CPU_THIS_PTR cr3 = value;
#if BX_SUPPORT_PAE #if BX_SUPPORT_PAE
if (BX_CPU_THIS_PTR cr4.get_PAE()) if (BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode())
BX_CPU_THIS_PTR cr3_masked = value & 0xffffffe0; BX_CPU_THIS_PTR cr3_masked = value & 0xffffffe0;
else else
#endif #endif
@ -557,20 +557,11 @@ void BX_CPU_C::INVLPG(bxInstruction_c* i)
UndefinedOpcode(i); UndefinedOpcode(i);
} }
// Can not be executed in v8086 mode if (!real_mode() && CPL!=0) {
if (v8086_mode()) { BX_ERROR(("INVLPG: priveledge check failed, generate #GP(0)"));
BX_ERROR(("INVLPG: cannot be executed in v8086 mode"));
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);
} }
// Protected instruction: CPL0 only
if (BX_CPU_THIS_PTR cr0.pe) {
if (CPL!=0) {
BX_ERROR(("INVLPG: #GP(0) in protected mode with CPL != 0"));
exception(BX_GP_EXCEPTION, 0, 0);
}
}
#if BX_USE_TLB #if BX_USE_TLB
bx_address laddr = BX_CPU_THIS_PTR get_segment_base(i->seg()) + RMAddr(i); bx_address laddr = BX_CPU_THIS_PTR get_segment_base(i->seg()) + RMAddr(i);
TLB_invlpg(laddr); TLB_invlpg(laddr);
@ -612,7 +603,7 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
#if BX_SUPPORT_PAE #if BX_SUPPORT_PAE
if (BX_CPU_THIS_PTR cr4.get_PAE()) if (BX_CPU_THIS_PTR cr4.get_PAE())
{ {
bx_address pde, pdp; Bit64u pde, pdp, pte;
bx_phy_address pde_addr; bx_phy_address pde_addr;
bx_phy_address pdp_addr; bx_phy_address pdp_addr;
@ -641,16 +632,15 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
InstrTLB_Increment(tlbMisses); InstrTLB_Increment(tlbMisses);
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR msr.lma) if (long_mode())
{ {
Bit64u pml4; Bit64u pml4;
// Get PML4 entry // Get PML4 entry
bx_phy_address pml4_addr = BX_CPU_THIS_PTR cr3_masked | bx_phy_address pml4_addr = BX_CPU_THIS_PTR cr3_masked |
((laddr & BX_CONST64(0x0000ff8000000000)) >> 36); ((laddr & BX_CONST64(0x0000ff8000000000)) >> 36);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pml4_addr, 8, &pml4); BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pml4_addr, 8, &pml4);
if ( !(pml4 & 0x01) ) { if (!(pml4 & 0x01)) {
goto page_fault_not_present; // PML4 Entry NOT present goto page_fault_not_present; // PML4 Entry NOT present
} }
if (pml4 & PAGE_DIRECTORY_NX_BIT) { if (pml4 & PAGE_DIRECTORY_NX_BIT) {
@ -659,25 +649,29 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
else if (access_type == CODE_ACCESS) else if (access_type == CODE_ACCESS)
goto page_fault_access; goto page_fault_access;
} }
if ( !(pml4 & 0x20) ) if (!(pml4 & 0x20))
{ {
pml4 |= 0x20; pml4 |= 0x20;
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pml4_addr, 8, &pml4); BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pml4_addr, 8, &pml4);
} }
if (pml4 & BX_CONST64(0x7fffffff00000000)) {
BX_PANIC(("PML4: Only 32 bit physical address space is emulated !"));
}
// Get PDP entry // Get PDP entry
pdp_addr = (pml4 & 0xfffff000) | pdp_addr = (pml4 & 0xfffff000) +
((laddr & BX_CONST64(0x0000007fc0000000)) >> 27); ((laddr & BX_CONST64(0x0000007fc0000000)) >> 27);
} }
else else
#endif #endif
{ {
pdp_addr = BX_CPU_THIS_PTR cr3_masked | ((laddr & 0xc0000000) >> 27); pdp_addr = BX_CPU_THIS_PTR cr3_masked + ((laddr & 0xc0000000) >> 27);
} }
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pdp_addr, sizeof(bx_address), &pdp); BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pdp_addr, 8, &pdp);
if ( !(pdp & 0x01) ) { if (!(pdp & 0x01)) {
goto page_fault_not_present; // PDP Entry NOT present goto page_fault_not_present; // PDP Entry NOT present
} }
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
@ -691,17 +685,21 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
} }
} }
#endif #endif
if ( !(pdp & 0x20) ) { if (!(pdp & 0x20)) {
pdp |= 0x20; pdp |= 0x20;
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pdp_addr, sizeof(bx_address), &pdp); BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pdp_addr, 8, &pdp);
}
if (pdp & BX_CONST64(0x7fffffff00000000)) {
BX_PANIC(("PAE PDP: Only 32 bit physical address space is emulated !"));
} }
// Get page dir entry // Get page dir entry
pde_addr = (pdp & 0xfffff000) | ((laddr & 0x3fe00000) >> 18); pde_addr = (pdp & 0xfffff000) + ((laddr & 0x3fe00000) >> 18);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pde_addr, sizeof(bx_address), &pde); BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pde_addr, 8, &pde);
if ( !(pde & 0x01) ) { if (!(pde & 0x01)) {
goto page_fault_not_present; // Page Directory Entry NOT present goto page_fault_not_present; // Page Directory Entry NOT present
} }
@ -714,16 +712,19 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
} }
#endif #endif
if (pde & BX_CONST64(0x7fffffff00000000)) {
BX_PANIC(("PAE PDE: Only 32 bit physical address space is emulated !"));
}
#if BX_SUPPORT_4MEG_PAGES #if BX_SUPPORT_4MEG_PAGES
// (KPL) Weird. I would think the processor would consult CR.PSE? // Ignore CR4.PSE in PAE mode
// if ((pde & 0x80) && (BX_CPU_THIS_PTR cr4.get_PSE())) {}
if (pde & 0x80) { if (pde & 0x80) {
// 4M pages are enabled, and this is a 4Meg page. // 4M pages are enabled, and this is a 4Meg page.
// Combined access is just access from the pde (no pte involved). // Combined access is just access from the pde (no pte involved).
combined_access = pde & 0x06; // U/S and R/W combined_access = pde & 0x06; // U/S and R/W
// Make up the physical page frame address. // Make up the physical page frame address.
ppf = (pde & 0xffe00000) | (laddr & 0x001ff000); ppf = (pde & 0xffe00000) + (laddr & 0x001ff000);
#if BX_SUPPORT_GLOBAL_PAGES #if BX_SUPPORT_GLOBAL_PAGES
if (BX_CPU_THIS_PTR cr4.get_PGE()) { // PGE==1 if (BX_CPU_THIS_PTR cr4.get_PGE()) { // PGE==1
@ -742,23 +743,20 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
if (!priv_check[priv_index]) goto page_fault_access; if (!priv_check[priv_index]) goto page_fault_access;
// Update PDE if A/D bits if needed. // Update PDE if A/D bits if needed.
if ( ((pde & 0x20)==0) || (isWrite && ((pde&0x40)==0)) ) if (((pde & 0x20)==0) || (isWrite && ((pde&0x40)==0)))
{ {
pde |= (0x20 | (isWrite<<6)); // Update A and possibly D bits pde |= (0x20 | (isWrite<<6)); // Update A and possibly D bits
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, sizeof(bx_address), &pde); BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, 8, &pde);
} }
} }
else else
#endif #endif
{ // 4k pages. { // 4k pages, Get page table entry
bx_address pte; bx_phy_address pte_addr = (pde & 0xfffff000) + ((laddr & 0x001ff000) >> 9);
// Get page table entry BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pte_addr, 8, &pte);
bx_phy_address pte_addr = (pde & 0xfffff000) | ((laddr & 0x001ff000) >> 9);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pte_addr, sizeof(bx_address), &pte); if (!(pte & 0x01)) {
if ( !(pte & 0x01) ) {
goto page_fault_not_present; goto page_fault_not_present;
} }
@ -771,6 +769,10 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
} }
#endif #endif
if (pte & BX_CONST64(0x7fffffff00000000)) {
BX_PANIC(("PAE PTE: Only 32 bit physical address space is emulated !"));
}
combined_access = (pde & pte) & 0x06; // U/S and R/W combined_access = (pde & pte) & 0x06; // U/S and R/W
// Make up the physical page frame address. // Make up the physical page frame address.
@ -793,16 +795,16 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
if (!priv_check[priv_index]) goto page_fault_access; if (!priv_check[priv_index]) goto page_fault_access;
// Update PDE A bit if needed. // Update PDE A bit if needed.
if ( (pde & 0x20)==0 ) { if (!(pde & 0x20)) {
pde |= 0x20; // Update A bit. pde |= 0x20; // Update A bit.
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, sizeof(bx_address), &pde); BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, 8, &pde);
} }
// Update PTE A/D bits if needed. // Update PTE A/D bits if needed.
if (((pte & 0x20)==0) || (isWrite && ((pte&0x40)==0))) if (((pte & 0x20)==0) || (isWrite && ((pte&0x40)==0)))
{ {
pte |= (0x20 | (isWrite<<6)); // Update A and possibly D bits pte |= (0x20 | (isWrite<<6)); // Update A and possibly D bits
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pte_addr, sizeof(bx_address), &pte); BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pte_addr, 8, &pte);
} }
} }
} }
@ -835,15 +837,15 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
InstrTLB_Increment(tlbMisses); InstrTLB_Increment(tlbMisses);
Bit32u pde; Bit32u pde, pte;
bx_phy_address pde_addr; bx_phy_address pde_addr;
// Get page dir entry // Get page dir entry
pde_addr = BX_CPU_THIS_PTR cr3_masked | ((laddr & 0xffc00000) >> 20); pde_addr = BX_CPU_THIS_PTR cr3_masked + ((laddr & 0xffc00000) >> 20);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pde_addr, 4, &pde); BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pde_addr, 4, &pde);
if ( !(pde & 0x01) ) { if (!(pde & 0x01)) {
goto page_fault_not_present; // Page Directory Entry NOT present goto page_fault_not_present; // Page Directory Entry NOT present
} }
@ -859,7 +861,7 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
// Combined access is just access from the pde (no pte involved). // Combined access is just access from the pde (no pte involved).
combined_access = pde & 0x006; // {US,RW} combined_access = pde & 0x006; // {US,RW}
// make up the physical frame number // make up the physical frame number
ppf = (pde & 0xFFC00000) | (laddr & 0x003FF000); ppf = (pde & 0xffc00000) + (laddr & 0x003ff000);
#if BX_SUPPORT_GLOBAL_PAGES #if BX_SUPPORT_GLOBAL_PAGES
if (BX_CPU_THIS_PTR cr4.get_PGE()) { // PGE==1 if (BX_CPU_THIS_PTR cr4.get_PGE()) { // PGE==1
@ -884,25 +886,21 @@ BX_CPU_C::translate_linear(bx_address laddr, unsigned pl, unsigned rw, unsigned
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, 4, &pde); BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, 4, &pde);
} }
} }
else // Else normal 4Kbyte page... else // else normal 4K page...
#endif #endif
{ {
Bit32u pte;
#if (BX_CPU_LEVEL < 6)
// update PDE if A bit was not set before // update PDE if A bit was not set before
if ( !(pde & 0x20) ) { if (!(pde & 0x20)) {
pde |= 0x20; pde |= 0x20;
BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, 4, &pde); BX_CPU_THIS_PTR mem->writePhysicalPage(BX_CPU_THIS, pde_addr, 4, &pde);
} }
#endif
// Get page table entry // Get page table entry
bx_phy_address pte_addr = (pde & 0xfffff000) | ((laddr & 0x003ff000) >> 10); bx_phy_address pte_addr = (pde & 0xfffff000) + ((laddr & 0x003ff000) >> 10);
BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pte_addr, 4, &pte); BX_CPU_THIS_PTR mem->readPhysicalPage(BX_CPU_THIS, pte_addr, 4, &pte);
if ( !(pte & 0x01) ) { if (!(pte & 0x01)) {
goto page_fault_not_present; // Page Table Entry NOT present goto page_fault_not_present; // Page Table Entry NOT present
} }
@ -1082,7 +1080,7 @@ bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy)
Bit64u pt_address; Bit64u pt_address;
int levels = 3; int levels = 3;
#if BX_SUPPORT_X86_64 #if BX_SUPPORT_X86_64
if (BX_CPU_THIS_PTR msr.lme) if (long_mode())
levels = 4; levels = 4;
#endif #endif
pt_address = BX_CPU_THIS_PTR cr3_masked; pt_address = BX_CPU_THIS_PTR cr3_masked;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.159 2006-09-10 16:56:55 sshwarts Exp $ // $Id: proc_ctrl.cc,v 1.160 2006-10-04 19:08:40 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -142,12 +142,9 @@ void BX_CPU_C::INVD(bxInstruction_c *i)
#if BX_CPU_LEVEL >= 4 #if BX_CPU_LEVEL >= 4
invalidate_prefetch_q(); invalidate_prefetch_q();
// protected or v8086 mode if (!real_mode() && CPL!=0) {
if (BX_CPU_THIS_PTR cr0.pe) { BX_ERROR(("INVD: priveledge check failed, generate #GP(0)"));
if (CPL!=0) { exception(BX_GP_EXCEPTION, 0, 0);
BX_ERROR(("INVD: priveledge check failed, generate #GP(0)"));
exception(BX_GP_EXCEPTION, 0, 0);
}
} }
BX_DEBUG(("INVD: Flush caches and TLB !")); BX_DEBUG(("INVD: Flush caches and TLB !"));
@ -168,11 +165,9 @@ void BX_CPU_C::WBINVD(bxInstruction_c *i)
#if BX_CPU_LEVEL >= 4 #if BX_CPU_LEVEL >= 4
invalidate_prefetch_q(); invalidate_prefetch_q();
if (BX_CPU_THIS_PTR cr0.pe) { if (!real_mode() && CPL!=0) {
if (CPL!=0) { BX_ERROR(("WBINVD: priveledge check failed, generate #GP(0)"));
BX_ERROR(("WBINVD: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0, 0);
exception(BX_GP_EXCEPTION, 0, 0);
}
} }
BX_DEBUG(("WBINVD: Flush caches and TLB !")); BX_DEBUG(("WBINVD: Flush caches and TLB !"));

View File

@ -1,5 +1,5 @@
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// $Id: ret_far.cc,v 1.7 2006-06-12 16:58:27 sshwarts Exp $ // $Id: ret_far.cc,v 1.8 2006-10-04 19:08:40 sshwarts Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2001 MandrakeSoft S.A. // Copyright (C) 2001 MandrakeSoft S.A.
@ -233,7 +233,7 @@ BX_CPU_C::return_protected(bxInstruction_c *i, Bit16u pop_bytes)
parse_selector(raw_ss_selector, &ss_selector); parse_selector(raw_ss_selector, &ss_selector);
if ((raw_ss_selector & 0xfffc) == 0) { if ((raw_ss_selector & 0xfffc) == 0) {
if (IsLongMode()) { if (long_mode()) {
if (! IS_LONG64_SEGMENT(cs_descriptor) || (cs_selector.rpl == 3)) { if (! IS_LONG64_SEGMENT(cs_descriptor) || (cs_selector.rpl == 3)) {
BX_ERROR(("return_protected: SS selector null")); BX_ERROR(("return_protected: SS selector null"));
exception(BX_GP_EXCEPTION, 0, 0); exception(BX_GP_EXCEPTION, 0, 0);