correctly report memory type for EPT page table accesses

TODO: support memory type for guest physical access under EPT
TODO: support memory type for SVM nested paging 
TODO: check what happens when PAT is not enabled in CPU configuration
This commit is contained in:
Stanislav Shwartsman 2015-03-23 20:27:36 +00:00
parent 7b33674a54
commit c360ddf60c
3 changed files with 16 additions and 9 deletions

View File

@ -4737,7 +4737,7 @@ public: // for now...
#endif
#if BX_SUPPORT_VMX >= 2
BX_SMF bx_phy_address translate_guest_physical(bx_phy_address guest_paddr, bx_address guest_laddr, bx_bool guest_laddr_valid, bx_bool is_page_walk, unsigned rw);
BX_SMF void update_ept_access_dirty(bx_phy_address *entry_addr, Bit64u *entry, unsigned leaf, unsigned write);
BX_SMF void update_ept_access_dirty(bx_phy_address *entry_addr, Bit64u *entry, BxMemtype eptptr_memtype, unsigned leaf, unsigned write);
BX_SMF bx_bool is_eptptr_valid(Bit64u eptptr);
#endif
#if BX_SUPPORT_SVM

View File

@ -1656,6 +1656,8 @@ bx_phy_address BX_CPU_C::nested_walk(bx_phy_address guest_paddr, unsigned rw, bx
#define BX_SUPPRESS_EPT_VIOLATION_EXCEPTION BX_CONST64(0x8000000000000000)
#define BX_VMX_EPT_ACCESS_DIRTY_ENABLED (BX_CPU_THIS_PTR vmcs.eptptr & 0x40)
// Format of a EPT Entry
// -----------------------------------------------------------
// 00 | Read access
@ -1664,7 +1666,9 @@ bx_phy_address BX_CPU_C::nested_walk(bx_phy_address guest_paddr, unsigned rw, bx
// 05-03 | EPT Memory type (for leaf entries, reserved otherwise)
// 06 | Ignore PAT memory type (for leaf entries, reserved otherwise)
// 07 | Page Size, must be 1 to indicate a Large Page
// 11-08 | (ignored)
// 08 | Accessed bit (if supported, ignored otherwise)
// 09 | Dirty bit (for leaf entries, if supported, ignored otherwise)
// 11-10 | (ignored)
// PA-12 | Physical address
// 51-PA | Reserved (must be zero)
// 63-52 | (ignored)
@ -1679,6 +1683,11 @@ bx_phy_address BX_CPU_C::translate_guest_physical(bx_phy_address guest_paddr, bx
Bit64u entry[4];
int leaf;
#if BX_SUPPORT_MEMTYPE
// The MTRRs have no effect on the memory type used for an access to an EPT paging structures.
BxMemtype eptptr_memtype = BX_CPU_THIS_PTR cr0.get_CD() ? (BX_MEMTYPE_UC) : BxMemtype(vm->eptptr & 0x7);
#endif
Bit32u combined_access = 0x7, access_mask = 0;
Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff);
@ -1697,7 +1706,7 @@ bx_phy_address BX_CPU_C::translate_guest_physical(bx_phy_address guest_paddr, bx
for (leaf = BX_LEVEL_PML4;; --leaf) {
entry_addr[leaf] = ppf + ((guest_paddr >> (9 + 9*leaf)) & 0xff8);
access_read_physical(entry_addr[leaf], 8, &entry[leaf]);
BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_MEMTYPE_INVALID, BX_READ, (BX_EPT_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf]));
BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, MEMTYPE(eptptr_memtype), BX_READ, (BX_EPT_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf]));
offset_mask >>= 9;
Bit64u curr_entry = entry[leaf];
@ -1787,7 +1796,7 @@ bx_phy_address BX_CPU_C::translate_guest_physical(bx_phy_address guest_paddr, bx
}
if (BX_VMX_EPT_ACCESS_DIRTY_ENABLED) {
update_ept_access_dirty(entry_addr, entry, leaf, rw & 1);
update_ept_access_dirty(entry_addr, entry, MEMTYPE(eptptr_memtype), leaf, rw & 1);
}
Bit32u page_offset = PAGE_OFFSET(guest_paddr);
@ -1795,14 +1804,14 @@ bx_phy_address BX_CPU_C::translate_guest_physical(bx_phy_address guest_paddr, bx
}
// Access bit 8, Dirty bit 9
void BX_CPU_C::update_ept_access_dirty(bx_phy_address *entry_addr, Bit64u *entry, unsigned leaf, unsigned write)
void BX_CPU_C::update_ept_access_dirty(bx_phy_address *entry_addr, Bit64u *entry, BxMemtype eptptr_memtype, unsigned leaf, unsigned write)
{
// Update A bit if needed
for (unsigned level=BX_LEVEL_PML4; level > leaf; level--) {
if (!(entry[level] & 0x100)) {
entry[level] |= 0x100;
access_write_physical(entry_addr[level], 8, &entry[level]);
BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[level], 8, BX_MEMTYPE_INVALID, BX_WRITE, (BX_EPT_PTE_ACCESS + level), (Bit8u*)(&entry[level]));
BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[level], 8, MEMTYPE(eptptr_memtype), BX_WRITE, (BX_EPT_PTE_ACCESS + level), (Bit8u*)(&entry[level]));
}
}
@ -1810,7 +1819,7 @@ void BX_CPU_C::update_ept_access_dirty(bx_phy_address *entry_addr, Bit64u *entry
if (!(entry[leaf] & 0x100) || (write && !(entry[leaf] & 0x200))) {
entry[leaf] |= (0x100 | (write<<9)); // Update A and possibly D bits
access_write_physical(entry_addr[leaf], 8, &entry[leaf]);
BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_MEMTYPE_INVALID, BX_WRITE, (BX_EPT_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf]));
BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, MEMTYPE(eptptr_memtype), BX_WRITE, (BX_EPT_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf]));
}
}

View File

@ -1056,8 +1056,6 @@ enum VMX_INVEPT_INVVPID_type {
#define VMX_MSR_VMX_EPT_VPID_CAP \
(BX_CPU_THIS_PTR vmx_cap.vmx_ept_vpid_cap_supported_bits)
#define BX_VMX_EPT_ACCESS_DIRTY_ENABLED (BX_CPU_THIS_PTR vmcs.eptptr & 0x40)
#endif
#endif // _BX_VMX_INTEL_H_