paging redo - step2

This commit is contained in:
Stanislav Shwartsman 2010-04-01 11:53:22 +00:00
parent 3a2fbd0aae
commit 6f7b68e1ca

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: paging.cc,v 1.200 2010-04-01 05:26:20 sshwarts Exp $
// $Id: paging.cc,v 1.201 2010-04-01 11:53:22 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2010 The Bochs Project
@ -791,110 +791,78 @@ static const char *bx_paging_level[4] = { "PTE", "PDE", "PDPE", "PML4" };
// Translate a linear address to a physical address in long mode
bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, bx_address &lpf_mask, Bit32u &combined_access, unsigned curr_pl, unsigned rw)
{
bx_phy_address entry_addr[4], ppf;
bx_phy_address entry_addr[4], ppf, pbase = BX_CPU_THIS_PTR cr3_masked;
Bit64u entry[4];
unsigned priv_index;
bx_bool nx_fault = 0, isWrite = (rw & 1); // write or r-m-w
bx_bool nx_fault = 0;
unsigned pl = (curr_pl == 3);
int fault, level, leaf = BX_LEVEL_PTE;
int level, leaf = BX_LEVEL_PTE;
combined_access = 0x06;
// Get PML4 entry
entry_addr[BX_LEVEL_PML4] = (bx_phy_address)(BX_CPU_THIS_PTR cr3_masked |
((laddr & BX_CONST64(0x0000ff8000000000)) >> 36));
access_read_physical(entry_addr[BX_LEVEL_PML4], 8, &entry[BX_LEVEL_PML4]);
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, entry_addr[BX_LEVEL_PML4], 8, BX_READ, (Bit8u*)(&entry[BX_LEVEL_PML4]));
for (level = BX_LEVEL_PML4;; --level) {
entry_addr[level] = pbase + 8 * ((laddr >> (12 + 9*level)) & 511);
access_read_physical(entry_addr[level], 8, &entry[level]);
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, entry_addr[level], 8, BX_READ, (Bit8u*)(&entry[level]));
fault = check_entry_PAE("PML4", entry[BX_LEVEL_PML4], PAGING_PAE_PML4_RESERVED_BITS, rw, &nx_fault);
if (fault >= 0)
page_fault(fault, laddr, pl, rw);
Bit64u curr_entry = entry[level];
combined_access &= entry[BX_LEVEL_PML4] & 0x06; // U/S and R/W
int fault = check_entry_PAE(bx_paging_level[level], curr_entry, BX_PAGING_PHY_ADDRESS_RESERVED_BITS, rw, &nx_fault);
if (fault >= 0)
page_fault(fault, laddr, pl, rw);
entry_addr[BX_LEVEL_PDPE] = (bx_phy_address)((entry[BX_LEVEL_PML4] & BX_CONST64(0x000ffffffffff000)) |
((laddr & BX_CONST64(0x0000007fc0000000)) >> 27));
combined_access &= curr_entry & 0x06; // U/S and R/W
access_read_physical(entry_addr[BX_LEVEL_PDPE], 8, &entry[BX_LEVEL_PDPE]);
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, entry_addr[BX_LEVEL_PDPE], 8, BX_READ, (Bit8u*)(&entry[BX_LEVEL_PDPE]));
pbase = curr_entry & BX_CONST64(0x000ffffffffff000);
fault = check_entry_PAE("PDPE", entry[BX_LEVEL_PDPE], BX_PAGING_PHY_ADDRESS_RESERVED_BITS, rw, &nx_fault);
if (fault >= 0)
page_fault(fault, laddr, pl, rw);
if (level == BX_LEVEL_PTE) {
// Make up the physical page frame address.
ppf = (bx_phy_address)(curr_entry & BX_CONST64(0x000ffffffffff000));
break;
}
combined_access &= entry[BX_LEVEL_PDPE] & 0x06; // U/S and R/W
if (curr_entry & 0x80) {
if (level == BX_LEVEL_PML4) {
BX_DEBUG(("PML4: PS bit set !"));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, rw);
}
if (level == BX_LEVEL_PDPE) {
#if BX_SUPPORT_1G_PAGES
if (entry[BX_LEVEL_PDPE] & 0x80) {
if (entry[BX_LEVEL_PDPE] & PAGING_PAE_PDPTE1G_RESERVED_BITS) {
BX_DEBUG(("PAE 1G PDPE: reserved bit is set: PDPE=%08x:%08x", GET32H(entry[BX_LEVEL_PDPE]), GET32L(entry[BX_LEVEL_PDPE])));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, rw);
}
if (curr_entry & PAGING_PAE_PDPTE1G_RESERVED_BITS) {
BX_DEBUG(("PAE 1G PDPE: reserved bit is set: PDPE=%08x:%08x", GET32H(curr_entry), GET32L(curr_entry)));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, rw);
}
// Make up the physical page frame address.
ppf = (bx_phy_address)((entry[BX_LEVEL_PDPE] & BX_CONST64(0x000fffffc0000000)) | (laddr & 0x3ffff000));
lpf_mask = 0x3fffffff;
leaf = BX_LEVEL_PDPE;
goto paging_long_mode_leaf_entry;
}
// Make up the physical page frame address.
ppf = (bx_phy_address)((curr_entry & BX_CONST64(0x000fffffc0000000)) | (laddr & 0x3ffff000));
lpf_mask = 0x3fffffff;
leaf = level;
break;
#else
if (entry[BX_LEVEL_PDPE] & 0x80) {
BX_DEBUG(("PAE PDPE: page size bit set when reserved"));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, rw);
}
BX_DEBUG(("PAE PDPE: page size bit set when reserved"));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, rw);
#endif
}
entry_addr[BX_LEVEL_PDE] = (bx_phy_address)((entry[BX_LEVEL_PDPE] & BX_CONST64(0x000ffffffffff000))
| ((laddr & 0x3fe00000) >> 18));
if (level == BX_LEVEL_PDE) {
if (curr_entry & PAGING_PAE_PDE2M_RESERVED_BITS) {
BX_DEBUG(("PAE PDE2M: reserved bit is set PDE=%08x:%08x", GET32H(curr_entry), GET32L(curr_entry)));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, rw);
}
access_read_physical(entry_addr[BX_LEVEL_PDE], 8, &entry[BX_LEVEL_PDE]);
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, entry_addr[BX_LEVEL_PDE], 8, BX_READ, (Bit8u*)(&entry[BX_LEVEL_PDE]));
fault = check_entry_PAE("PDE", entry[BX_LEVEL_PDE], PAGING_PAE_PDE_RESERVED_BITS, rw, &nx_fault);
if (fault >= 0)
page_fault(fault, laddr, pl, rw);
combined_access &= entry[BX_LEVEL_PDE] & 0x06; // U/S and R/W
// Ignore CR4.PSE in PAE mode
if (entry[BX_LEVEL_PDE] & 0x80) {
if (entry[BX_LEVEL_PDE] & PAGING_PAE_PDE2M_RESERVED_BITS) {
BX_DEBUG(("PAE PDE2M: reserved bit is set PDE=%08x:%08x", GET32H(entry[BX_LEVEL_PDE]), GET32L(entry[BX_LEVEL_PDE])));
page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, pl, rw);
// Make up the physical page frame address.
ppf = (bx_phy_address)((curr_entry & BX_CONST64(0x000fffffffe00000)) | (laddr & 0x001ff000));
lpf_mask = 0x1fffff;
leaf = level;
break;
}
}
// Make up the physical page frame address.
ppf = (bx_phy_address)((entry[BX_LEVEL_PDE] & BX_CONST64(0x000fffffffe00000)) | (laddr & 0x001ff000));
lpf_mask = 0x1fffff;
leaf = BX_LEVEL_PDE;
goto paging_long_mode_leaf_entry;
}
// 4k pages, Get page table entry
entry_addr[BX_LEVEL_PTE] = (bx_phy_address)((entry[BX_LEVEL_PDE] & BX_CONST64(0x000ffffffffff000)) |
((laddr & 0x001ff000) >> 9));
access_read_physical(entry_addr[BX_LEVEL_PTE], 8, &entry[BX_LEVEL_PTE]);
BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, entry_addr[BX_LEVEL_PTE], 8, BX_READ, (Bit8u*)(&entry[BX_LEVEL_PTE]));
bx_bool isWrite = (rw & 1); // write or r-m-w
fault = check_entry_PAE("PTE", entry[BX_LEVEL_PTE], PAGING_PAE_PTE_RESERVED_BITS, rw, &nx_fault);
if (fault >= 0)
page_fault(fault, laddr, pl, rw);
combined_access &= entry[BX_LEVEL_PTE] & 0x06; // U/S and R/W
// Make up the physical page frame address.
ppf = (bx_phy_address)(entry[BX_LEVEL_PTE] & BX_CONST64(0x000ffffffffff000));
paging_long_mode_leaf_entry:
priv_index =
(BX_CPU_THIS_PTR cr0.get_WP() << 4) | // bit 4
(pl<<3) | // bit 3
(combined_access | isWrite); // bit 2,1,0
unsigned priv_index = (BX_CPU_THIS_PTR cr0.get_WP() << 4) | // bit 4
(pl<<3) | // bit 3
(combined_access | isWrite); // bit 2,1,0
if (!priv_check[priv_index] || nx_fault)
page_fault(ERROR_PROTECTION, laddr, pl, rw);
@ -911,7 +879,7 @@ paging_long_mode_leaf_entry:
}
}
// Update PTE A/D bits if needed.
// Update A/D bits if needed.
if (!(entry[leaf] & 0x20) || (isWrite && !(entry[leaf] & 0x40))) {
entry[leaf] |= (0x20 | (isWrite<<6)); // Update A and possibly D bits
access_write_physical(entry_addr[leaf], 8, &entry[leaf]);