From 6481d24e06f8deb3bdfc11a12a35e533f92793f5 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Sun, 20 Aug 2023 19:33:37 +0300 Subject: [PATCH] Another cleaner way to implemented fix by rei141 from Fixes in VM Entry Checks for Guest Segment Registers #51 Correction in checks for Code Segment (CS): Previously, the DPL of CS was incorrectly compared with its own RPL. According to Intel SDM, Vol. 3C, Chapter 27.3.1.2, for non-conforming code segments (type 9 or 11), the DPL of CS should be equal to the DPL of SS. And for conforming code segments (type 13 or 15), the DPL of CS cannot be greater than the DPL of SS. This way VMCS is not accessed multiple times which is important for some usages --- bochs/cpu/vmx.cc | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/bochs/cpu/vmx.cc b/bochs/cpu/vmx.cc index 793349e9f..c0aaefc6b 100644 --- a/bochs/cpu/vmx.cc +++ b/bochs/cpu/vmx.cc @@ -1572,20 +1572,9 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification) // CS checks switch (guest.sregs[BX_SEG_REG_CS].cache.type) { case BX_CODE_EXEC_ONLY_ACCESSED: - case BX_CODE_EXEC_READ_ACCESSED: - // non-conforming segment - if (guest.sregs[BX_SEG_REG_CS].selector.rpl != guest.sregs[BX_SEG_REG_CS].cache.dpl) { - BX_ERROR(("VMENTER FAIL: VMCS guest non-conforming CS.RPL <> CS.DPL")); - return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; - } - break; + case BX_CODE_EXEC_READ_ACCESSED: // non-conforming segment case BX_CODE_EXEC_ONLY_CONFORMING_ACCESSED: - case BX_CODE_EXEC_READ_CONFORMING_ACCESSED: - // conforming segment - if (guest.sregs[BX_SEG_REG_CS].selector.rpl < guest.sregs[BX_SEG_REG_CS].cache.dpl) { - BX_ERROR(("VMENTER FAIL: VMCS guest non-conforming CS.RPL < CS.DPL")); - return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; - } + case BX_CODE_EXEC_READ_CONFORMING_ACCESSED: // conforming segment break; #if BX_SUPPORT_VMX >= 2 case BX_DATA_READ_WRITE_ACCESSED: @@ -1649,6 +1638,23 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification) } } + switch (guest.sregs[BX_SEG_REG_CS].cache.type) { + case BX_CODE_EXEC_ONLY_ACCESSED: + case BX_CODE_EXEC_READ_ACCESSED: // non-conforming segment + if (guest.sregs[BX_SEG_REG_CS].cache.dpl != guest.sregs[BX_SEG_REG_SS].cache.dpl) { + BX_ERROR(("VMENTER FAIL: VMCS guest non-conforming CS.DPL <> SS.DPL")); + return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; + } + break; + case BX_CODE_EXEC_ONLY_CONFORMING_ACCESSED: + case BX_CODE_EXEC_READ_CONFORMING_ACCESSED: // conforming segment + if (guest.sregs[BX_SEG_REG_CS].cache.dpl > guest.sregs[BX_SEG_REG_SS].cache.dpl) { + BX_ERROR(("VMENTER FAIL: VMCS guest non-conforming CS.DPL > SS.DPL")); + return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; + } + break; + } + if (! v8086_guest) { if (! (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST)) { if (guest.sregs[BX_SEG_REG_SS].selector.rpl != guest.sregs[BX_SEG_REG_CS].selector.rpl) {