diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index 24982a3ddf3..586793b50e5 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -522,6 +522,7 @@ enum vm_paging_mode { PAGING_MODE_32, PAGING_MODE_PAE, PAGING_MODE_64, + PAGING_MODE_64_LA57, }; struct vm_guest_paging { diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c index 3fc6ccf28b6..3269fd552c1 100644 --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -1940,14 +1940,18 @@ vmx_cpu_mode(void) static enum vm_paging_mode vmx_paging_mode(void) { + uint64_t cr4; if (!(vmcs_read(VMCS_GUEST_CR0) & CR0_PG)) return (PAGING_MODE_FLAT); - if (!(vmcs_read(VMCS_GUEST_CR4) & CR4_PAE)) + cr4 = vmcs_read(VMCS_GUEST_CR4); + if (!(cr4 & CR4_PAE)) return (PAGING_MODE_32); - if (vmcs_read(VMCS_GUEST_IA32_EFER) & EFER_LME) - return (PAGING_MODE_64); - else + if (vmcs_read(VMCS_GUEST_IA32_EFER) & EFER_LME) { + if (!(cr4 & CR4_LA57)) + return (PAGING_MODE_64); + return (PAGING_MODE_64_LA57); + } else return (PAGING_MODE_PAE); } diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c index 70d77186be9..ae022210893 100644 --- a/sys/amd64/vmm/vmm_instruction_emul.c +++ b/sys/amd64/vmm/vmm_instruction_emul.c @@ -2189,8 +2189,12 @@ restart: ptpphys = pte; nlevels = 2; - } else + } else if (paging->paging_mode == PAGING_MODE_64_LA57) { + nlevels = 5; + } else { nlevels = 4; + } + while (--nlevels >= 0) { /* Zero out the lower 12 bits and the upper 12 bits */ ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12; diff --git a/usr.sbin/bhyve/gdb.c b/usr.sbin/bhyve/gdb.c index 0539c461bdb..b0f0c034b2c 100644 --- a/usr.sbin/bhyve/gdb.c +++ b/usr.sbin/bhyve/gdb.c @@ -251,7 +251,8 @@ guest_paging_info(int vcpu, struct vm_guest_paging *paging) else if (!(regs[2] & CR4_PAE)) paging->paging_mode = PAGING_MODE_32; else if (regs[3] & EFER_LME) - paging->paging_mode = PAGING_MODE_64; + paging->paging_mode = (regs[2] & CR4_LA57) ? + PAGING_MODE_64_LA57 : PAGING_MODE_64; else paging->paging_mode = PAGING_MODE_PAE; return (0);