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
This commit is contained in:
Stanislav Shwartsman 2023-08-20 19:33:37 +03:00
parent 58c047c6d6
commit 6481d24e06
1 changed files with 19 additions and 13 deletions

View File

@ -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) {