Implement support for LA57 and 5-level paging
This commit is contained in:
parent
157d3a9189
commit
e3612c30f8
@ -8,9 +8,10 @@ Brief summary :
|
||||
! Implemented VMX MBE (Mode Based Execution Control) emulation required for Windows 11 guest
|
||||
! Implemented Posted-Interrupt Processing VMX extension emulation
|
||||
! Implemented Linear Address Separation (LASS) extension
|
||||
! Implemented 57-bit Linear Address and 5-Level Paging support
|
||||
! Implemented User-Level Interrupt (UINTR) extension
|
||||
! Implemented recently published Intel instruction sets:
|
||||
- MOVDIRI/MOVDIR64B, AVX512 BF16, AVX IFMA52, VNNI-INT8/VNNI-INT16, AVX-NE-CONVERT, CMPCCXADD, SM3, SM4, SHA512, WRMSRNS, MSRLIST, WAITPKG, SERIALIZE
|
||||
- MOVDIRI/MOVDIR64B, AVX512 BF16, AVX IFMA52, VNNI-INT8/VNNI-INT16, AVX-NE-CONVERT, CMPCCXADD, SM3/SM4, SHA512, WRMSRNS, MSRLIST, WAITPKG, SERIALIZE
|
||||
- Improved 64-bit guest support in Bochs internal debugger, added new internal debugger commands
|
||||
- Bochs debugger enhanced with new commands (setpmem, loadmem, deref, ...)
|
||||
Enhanced magic breakpoint capabilities. Refer to user documentation for more details.
|
||||
@ -35,9 +36,10 @@ Detailed change log :
|
||||
- Implemented VMX MBE (Mode Based Execution Control) emulation required for Windows 11 guest
|
||||
- Implemented Posted-Interrupt Processing VMX extension emulation
|
||||
- Implemented Linear Address Separation (LASS) extension
|
||||
- Implemented 57-bit Linear Address and 5-Level Paging support
|
||||
- Implemented User-Level Interrupt (UINTR) extension
|
||||
- Implemented recently published Intel instruction sets:
|
||||
- MOVDIRI/MOVDIR64B, AVX512 BF16, AVX IFMA52, VNNI-INT8/VNNI-INT16, AVX-NE-CONVERT, CMPCCXADD, SM3, SM4, SHA512, WRMSRNS, MSRLIST, WAITPKG, SERIALIZE
|
||||
- MOVDIRI/MOVDIR64B, AVX512 BF16, AVX IFMA52, VNNI-INT8/VNNI-INT16, AVX-NE-CONVERT, CMPCCXADD, SM3/SM4, SHA512, WRMSRNS, MSRLIST, WAITPKG, SERIALIZE
|
||||
|
||||
- Bochs Debugger and Instrumentation
|
||||
- Updated Bochs instrumentation examples for new disassembler introduced in Bochs 2.7 release.
|
||||
|
@ -717,10 +717,12 @@ void bx_dbg_phy_memory_access(unsigned cpu, bx_phy_address phy, unsigned len, un
|
||||
"PDE",
|
||||
"PDPTE",
|
||||
"PML4E",
|
||||
"PML5E",
|
||||
"EPT PTE",
|
||||
"EPT PDE",
|
||||
"EPT PDPTE",
|
||||
"EPT PML4E",
|
||||
"EPT PML5E", // place holder
|
||||
"EPT SPP PTE",
|
||||
"EPT SPP PDE",
|
||||
"EPT SPP PDPTE",
|
||||
|
@ -475,12 +475,6 @@ typedef Bit32u bx_address;
|
||||
// define physical and linear address types
|
||||
typedef bx_address bx_lin_address;
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
#define BX_LIN_ADDRESS_WIDTH 48
|
||||
#else
|
||||
#define BX_LIN_ADDRESS_WIDTH 32
|
||||
#endif
|
||||
|
||||
#if BX_PHY_ADDRESS_LONG
|
||||
typedef Bit64u bx_phy_address;
|
||||
#if BX_CPU_LEVEL == 5
|
||||
|
@ -284,10 +284,12 @@ enum AccessReason {
|
||||
BX_PDE_ACCESS,
|
||||
BX_PDTE_ACCESS,
|
||||
BX_PML4E_ACCESS,
|
||||
BX_PML5E_ACCESS,
|
||||
BX_EPT_PTE_ACCESS,
|
||||
BX_EPT_PDE_ACCESS,
|
||||
BX_EPT_PDTE_ACCESS,
|
||||
BX_EPT_PML4E_ACCESS,
|
||||
BX_EPT_PML5E_ACCESS, // place holder
|
||||
BX_EPT_SPP_PTE_ACCESS,
|
||||
BX_EPT_SPP_PDE_ACCESS,
|
||||
BX_EPT_SPP_PDTE_ACCESS,
|
||||
@ -357,10 +359,13 @@ const unsigned BX_MSR_MAX_INDEX = 0x1000;
|
||||
extern const char* cpu_mode_string(unsigned cpu_mode);
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_CPP_INLINE bool IsCanonical(bx_address offset)
|
||||
BX_CPP_INLINE bool IsCanonicalToWidth(bx_address addr, unsigned LIN_ADDRESS_WIDTH)
|
||||
{
|
||||
return ((Bit64u)((((Bit64s)(offset)) >> (BX_LIN_ADDRESS_WIDTH-1)) + 1) < 2);
|
||||
return ((Bit64u)((((Bit64s)(addr)) >> (LIN_ADDRESS_WIDTH-1)) + 1) < 2);
|
||||
}
|
||||
|
||||
BX_CPP_INLINE bool IsCanonical48(bx_address addr) { return IsCanonicalToWidth(addr, 48); }
|
||||
BX_CPP_INLINE bool IsCanonical57(bx_address addr) { return IsCanonicalToWidth(addr, 57); }
|
||||
#endif
|
||||
|
||||
BX_CPP_INLINE bool IsValidPhyAddr(bx_phy_address addr)
|
||||
@ -944,6 +949,9 @@ public: // for now...
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
bx_cr4_t cr4;
|
||||
Bit32u cr4_suppmask;
|
||||
#if BX_SUPPORT_X86_64
|
||||
unsigned linaddr_width;
|
||||
#endif
|
||||
|
||||
bx_efer_t efer;
|
||||
Bit32u efer_suppmask;
|
||||
@ -4147,6 +4155,10 @@ public: // for now...
|
||||
BX_CPU_THIS_PTR espPageWindowSize = 0;
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_SMF BX_CPP_INLINE bool IsCanonical(bx_address addr) { return IsCanonicalToWidth(addr, BX_CPU_THIS_PTR linaddr_width); }
|
||||
#endif
|
||||
|
||||
BX_SMF bool write_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned len, bool align = false) BX_CPP_AttrRegparmN(4);
|
||||
BX_SMF bool read_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned len, bool align = false) BX_CPP_AttrRegparmN(4);
|
||||
BX_SMF bool execute_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned len) BX_CPP_AttrRegparmN(3);
|
||||
|
@ -927,7 +927,13 @@ Bit32u bx_cpuid_t::get_std_cpuid_leaf_7_ecx(Bit32u extra) const
|
||||
#endif
|
||||
|
||||
// [15:15] reserved
|
||||
// [16:16] LA57: LA57 and 5-level paging - not supported
|
||||
|
||||
// [16:16] LA57: LA57 and 5-level paging
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (is_cpu_extension_supported(BX_ISA_LA57))
|
||||
ecx |= BX_CPUID_STD7_SUBLEAF0_ECX_LA57;
|
||||
#endif
|
||||
|
||||
// [17:17] reserved
|
||||
// [18:18] reserved
|
||||
// [19:19] reserved
|
||||
@ -1152,7 +1158,8 @@ void bx_cpuid_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const
|
||||
// virtual & phys address size in low 2 bytes of EAX.
|
||||
// TODO: physical address width should be 32-bit when no PSE-36 is supported
|
||||
Bit32u phy_addr_width = BX_PHY_ADDRESS_WIDTH;
|
||||
Bit32u lin_addr_width = is_cpu_extension_supported(BX_ISA_LONG_MODE) ? BX_LIN_ADDRESS_WIDTH : 32;
|
||||
Bit32u lin_addr_width = is_cpu_extension_supported(BX_ISA_LONG_MODE) ?
|
||||
(is_cpu_extension_supported(BX_ISA_LA57) ? 57 : 48) : 32;
|
||||
|
||||
leaf->eax = phy_addr_width | (lin_addr_width << 8);
|
||||
|
||||
|
@ -1152,6 +1152,10 @@ bool BX_CPU_C::SetCR0(bxInstruction_c *i, bx_address val)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_CPU_THIS_PTR linaddr_width = BX_CPU_THIS_PTR cr4.get_LA57() ? 57 : 48;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1177,7 +1181,7 @@ Bit32u BX_CPU_C::get_cr4_allow_mask(void)
|
||||
// [15] Reserved, Must be Zero
|
||||
// [14] SMXE: SMX Extensions R/W
|
||||
// [13] VMXE: VMX Extensions R/W
|
||||
// [12] Reserved, Must be Zero
|
||||
// [12] LA57, 57-bit Linear Address and 5-level paging
|
||||
// [11] UMIP: User Mode Instruction Prevention R/W
|
||||
// [10] OSXMMEXCPT: Operating System Unmasked Exception Support R/W
|
||||
// [9] OSFXSR: Operating System FXSAVE/FXRSTOR Support R/W
|
||||
@ -1260,6 +1264,11 @@ Bit32u BX_CPU_C::get_cr4_allow_mask(void)
|
||||
if (is_cpu_extension_supported(BX_ISA_UMIP))
|
||||
allowMask |= BX_CR4_UMIP_MASK;
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (is_cpu_extension_supported(BX_ISA_LA57))
|
||||
allowMask |= BX_CR4_LA57_MASK;
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_CET
|
||||
if (is_cpu_extension_supported(BX_ISA_CET))
|
||||
allowMask |= BX_CR4_CET_MASK;
|
||||
@ -1299,6 +1308,11 @@ bool BX_CPP_AttrRegparmN(1) BX_CPU_C::check_CR4(bx_address cr4_val)
|
||||
BX_ERROR(("check_CR4(): attempt to clear CR4.PAE when EFER.LMA=1"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(! temp_cr4.get_LA57()) {
|
||||
BX_ERROR(("check_CR4(): attempt to clear CR4.LA57 when EFER.LMA=1"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (temp_cr4.get_PCIDE()) {
|
||||
@ -1388,6 +1402,10 @@ bool BX_CPU_C::SetCR4(bxInstruction_c *i, bx_address val)
|
||||
set_PKeys(BX_CPU_THIS_PTR pkru, BX_CPU_THIS_PTR pkrs);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_CPU_THIS_PTR linaddr_width = BX_CPU_THIS_PTR cr4.get_LA57() ? 57 : 48;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // BX_CPU_LEVEL >= 5
|
||||
|
@ -153,7 +153,7 @@ struct bx_cr4_t {
|
||||
BX_CPP_INLINE void set32(Bit32u val) { val32 = val; }
|
||||
};
|
||||
|
||||
const Bit32u BX_CR4_FLUSH_TLB_MASK = (BX_CR4_PSE_MASK | BX_CR4_PAE_MASK | BX_CR4_PGE_MASK | BX_CR4_PCIDE_MASK | BX_CR4_SMEP_MASK | BX_CR4_SMAP_MASK | BX_CR4_PKE_MASK | BX_CR4_CET_MASK | BX_CR4_PKS_MASK | BX_CR4_LASS_MASK);
|
||||
const Bit32u BX_CR4_FLUSH_TLB_MASK = (BX_CR4_PSE_MASK | BX_CR4_PAE_MASK | BX_CR4_PGE_MASK | BX_CR4_LA57_MASK | BX_CR4_PCIDE_MASK | BX_CR4_SMEP_MASK | BX_CR4_SMAP_MASK | BX_CR4_PKE_MASK | BX_CR4_CET_MASK | BX_CR4_PKS_MASK | BX_CR4_LASS_MASK);
|
||||
|
||||
#endif // #if BX_CPU_LEVEL >= 5
|
||||
|
||||
@ -398,7 +398,7 @@ typedef struct msr {
|
||||
switch(type) {
|
||||
#if BX_SUPPORT_X86_64
|
||||
case BX_LIN_ADDRESS_MSR:
|
||||
if (! IsCanonical(new_val)) return 0;
|
||||
if (! IsCanonical48(new_val)) return 0;
|
||||
break;
|
||||
#endif
|
||||
case BX_PHY_ADDRESS_MSR:
|
||||
|
@ -140,6 +140,7 @@ x86_feature(BX_ISA_WRMSRNS, "wrmsrns") /* Non-S
|
||||
x86_feature(BX_ISA_CMPCCXADD, "cmpccxadd") /* CMPccXADD instructions */
|
||||
x86_feature(BX_ISA_SERIALIZE, "serialize") /* SERIALIZE instruction */
|
||||
x86_feature(BX_ISA_LASS, "lass") /* Linear Address Space Separation support */
|
||||
x86_feature(BX_ISA_LA57, "la57") /* 57-bit Virtual Address and 5-level paging support */
|
||||
x86_feature(BX_ISA_UINTR, "uintr") /* User Level Interrupts support */
|
||||
x86_feature(BX_ISA_MOVDIRI, "movdiri") /* MOVDIRI instruction support */
|
||||
x86_feature(BX_ISA_MOVDIR64B, "movdir64b") /* MOVDIR64B instruction support */
|
||||
|
@ -688,6 +688,10 @@ void BX_CPU_C::after_restore_state(void)
|
||||
set_PKeys(BX_CPU_THIS_PTR pkru, BX_CPU_THIS_PTR pkrs);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_CPU_THIS_PTR linaddr_width = BX_CPU_THIS_PTR cr4.get_LA57() ? 57 : 48;
|
||||
#endif
|
||||
|
||||
handleCpuContextChange();
|
||||
|
||||
assert_checks();
|
||||
@ -895,6 +899,9 @@ void BX_CPU_C::reset(unsigned source)
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
BX_CPU_THIS_PTR cr4.set32(0);
|
||||
BX_CPU_THIS_PTR cr4_suppmask = get_cr4_allow_mask();
|
||||
#if BX_SUPPORT_X86_64
|
||||
BX_CPU_THIS_PTR linaddr_width = 48;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
|
@ -533,13 +533,14 @@ void BX_CPU_C::page_fault(unsigned fault, bx_address laddr, unsigned user, unsig
|
||||
}
|
||||
|
||||
enum {
|
||||
BX_LEVEL_PML5 = 4,
|
||||
BX_LEVEL_PML4 = 3,
|
||||
BX_LEVEL_PDPTE = 2,
|
||||
BX_LEVEL_PDE = 1,
|
||||
BX_LEVEL_PTE = 0
|
||||
};
|
||||
|
||||
static const char *bx_paging_level[4] = { "PTE", "PDE", "PDPE", "PML4" }; // keep it 4 letters
|
||||
static const char *bx_paging_level[5] = { "PTE", "PDE", "PDPE", "PML4", "PML5" }; // keep it 4 letters
|
||||
|
||||
// combined_access legend:
|
||||
// -----------------------
|
||||
@ -697,9 +698,8 @@ bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, Bit32u &lp
|
||||
BxMemtype entry_memtype[4] = { 0 };
|
||||
|
||||
bool nx_fault = false;
|
||||
int leaf;
|
||||
|
||||
Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff);
|
||||
Bit64u offset_mask = ((BX_CONST64(1) << BX_CPU_THIS_PTR linaddr_width) - 1);
|
||||
lpf_mask = 0xfff;
|
||||
Bit32u combined_access = (BX_COMBINED_ACCESS_WRITE | BX_COMBINED_ACCESS_USER);
|
||||
Bit64u curr_entry = BX_CPU_THIS_PTR cr3;
|
||||
@ -708,7 +708,9 @@ bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, Bit32u &lp
|
||||
if (! BX_CPU_THIS_PTR efer.get_NXE())
|
||||
reserved |= PAGE_DIRECTORY_NX_BIT;
|
||||
|
||||
for (leaf = BX_LEVEL_PML4;; --leaf) {
|
||||
int start_leaf = BX_CPU_THIS_PTR cr4.get_LA57() ? BX_LEVEL_PML5 : BX_LEVEL_PML4, leaf = start_leaf;
|
||||
|
||||
for (;; --leaf) {
|
||||
entry_addr[leaf] = ppf + ((laddr >> (9 + 9*leaf)) & 0xff8);
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
if (BX_CPU_THIS_PTR in_vmx_guest) {
|
||||
@ -854,7 +856,7 @@ bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, Bit32u &lp
|
||||
#endif
|
||||
|
||||
// Update A/D bits if needed
|
||||
update_access_dirty_PAE(entry_addr, entry, entry_memtype, BX_LEVEL_PML4, leaf, isWrite);
|
||||
update_access_dirty_PAE(entry_addr, entry, entry_memtype, start_leaf, leaf, isWrite);
|
||||
|
||||
return (ppf | combined_access);
|
||||
}
|
||||
@ -1654,19 +1656,20 @@ bx_phy_address BX_CPU_C::nested_walk_long_mode(bx_phy_address guest_paddr, unsig
|
||||
Bit64u entry[4];
|
||||
BxMemtype entry_memtype[4] = { BX_MEMTYPE_INVALID };
|
||||
bool nx_fault = false;
|
||||
int leaf;
|
||||
|
||||
SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls;
|
||||
SVM_HOST_STATE *host_state = &BX_CPU_THIS_PTR vmcb.host_state;
|
||||
bx_phy_address ppf = ctrls->ncr3 & BX_CR3_PAGING_MASK;
|
||||
Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff);
|
||||
Bit64u offset_mask = ((BX_CONST64(1) << BX_CPU_THIS_PTR linaddr_width) - 1);
|
||||
unsigned combined_access = BX_COMBINED_ACCESS_WRITE | BX_COMBINED_ACCESS_USER;
|
||||
|
||||
Bit64u reserved = PAGING_PAE_RESERVED_BITS;
|
||||
if (! host_state->efer.get_NXE())
|
||||
reserved |= PAGE_DIRECTORY_NX_BIT;
|
||||
|
||||
for (leaf = BX_LEVEL_PML4;; --leaf) {
|
||||
int start_leaf = BX_CPU_THIS_PTR cr4.get_LA57() ? BX_LEVEL_PML5 : BX_LEVEL_PML4, leaf = start_leaf;
|
||||
|
||||
for (;; --leaf) {
|
||||
entry_addr[leaf] = ppf + ((guest_paddr >> (9 + 9*leaf)) & 0xff8);
|
||||
entry[leaf] = read_physical_qword(entry_addr[leaf], BX_MEMTYPE_INVALID, AccessReason(BX_PTE_ACCESS + leaf));
|
||||
offset_mask >>= 9;
|
||||
@ -1705,7 +1708,7 @@ bx_phy_address BX_CPU_C::nested_walk_long_mode(bx_phy_address guest_paddr, unsig
|
||||
nested_page_fault(ERROR_PROTECTION, guest_paddr, rw, is_page_walk);
|
||||
|
||||
// Update A/D bits if needed
|
||||
update_access_dirty_PAE(entry_addr, entry, entry_memtype, BX_LEVEL_PML4, leaf, isWrite);
|
||||
update_access_dirty_PAE(entry_addr, entry, entry_memtype, start_leaf, leaf, isWrite);
|
||||
|
||||
// Make up the physical page frame address
|
||||
return ppf | (bx_phy_address)(guest_paddr & offset_mask);
|
||||
@ -2268,7 +2271,7 @@ bool BX_CPU_C::dbg_translate_guest_physical_ept(bx_phy_address guest_paddr, bx_p
|
||||
bx_phy_address pt_address = LPFOf(vm->eptptr);
|
||||
Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff);
|
||||
|
||||
for (int level = 3; level >= 0; --level) {
|
||||
for (int level = BX_LEVEL_PML4; level >= 0; --level) {
|
||||
Bit64u pte;
|
||||
pt_address += ((guest_paddr >> (9 + 9*level)) & 0xff8);
|
||||
offset_mask >>= 9;
|
||||
@ -2335,9 +2338,8 @@ bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy, bx_ad
|
||||
|
||||
#if BX_CPU_LEVEL >= 6
|
||||
if (BX_CPU_THIS_PTR cr4.get_PAE()) {
|
||||
offset_mask = BX_CONST64(0x0000ffffffffffff);
|
||||
|
||||
int level = 3;
|
||||
int level = BX_CPU_THIS_PTR cr4.get_LA57() ? BX_LEVEL_PML5 : BX_LEVEL_PML4;
|
||||
offset_mask = ((BX_CONST64(1) << BX_CPU_THIS_PTR linaddr_width) - 1);
|
||||
if (! long_mode()) {
|
||||
pt_address = BX_CPU_THIS_PTR PDPTR_CACHE.entry[(laddr >> 30) & 3];
|
||||
if (! (pt_address & 0x1)) {
|
||||
@ -2346,7 +2348,7 @@ bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy, bx_ad
|
||||
}
|
||||
offset_mask >>= 18;
|
||||
pt_address &= BX_CONST64(0x000ffffffffff000);
|
||||
level = 1;
|
||||
level = BX_LEVEL_PDE;
|
||||
}
|
||||
|
||||
for (; level >= 0; --level) {
|
||||
@ -2394,7 +2396,7 @@ bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy, bx_ad
|
||||
#endif
|
||||
{
|
||||
offset_mask = 0xfff;
|
||||
for (int level = 1; level >= 0; --level) {
|
||||
for (int level = BX_LEVEL_PDE; level >= 0; --level) {
|
||||
Bit32u pte;
|
||||
pt_address += ((laddr >> (10 + 10*level)) & 0xffc);
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
|
Loading…
Reference in New Issue
Block a user