Fix that the blocking by SMI bit maybe set when a VM-exit ends outside SMM (#15)

* Fix that the blocking by SMI bit is set

The blocking by SMI bit of the guest interruptibility state VMCS should
not be set unless the VM-exit ends in SMM. This only happens under the
dual-monitor treatment, which is not implemented in Bochs.

* Remove trailing whitespaces
This commit is contained in:
Satoshi Tanda 2022-07-23 09:36:31 -07:00 committed by GitHub
parent 112afe5693
commit 0ae5e67894
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -962,7 +962,7 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
if (! BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET)) {
if (vector == BX_CP_EXCEPTION) push_error_reference = false;
}
#endif
#endif
if (vm->vmentry_interr_info & 0x7ffff000) {
BX_ERROR(("VMFAIL: VMENTRY broken interruption info field"));
@ -999,7 +999,7 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void)
case BX_SOFTWARE_INTERRUPT:
case BX_PRIVILEGED_SOFTWARE_INTERRUPT:
case BX_SOFTWARE_EXCEPTION:
if ((vm->vmentry_instr_length == 0 && !BX_SUPPORT_VMX_EXTENSION(BX_VMX_SW_INTERRUPT_INJECTION_ILEN_0)) ||
if ((vm->vmentry_instr_length == 0 && !BX_SUPPORT_VMX_EXTENSION(BX_VMX_SW_INTERRUPT_INJECTION_ILEN_0)) ||
vm->vmentry_instr_length > 15)
{
BX_ERROR(("VMFAIL: VMENTRY bad injected event instr length"));
@ -1691,7 +1691,7 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
Bit32u ldtr_ar = VMread32(VMCS_32BIT_GUEST_LDTR_ACCESS_RIGHTS);
ldtr_ar = vmx_unpack_ar_field(ldtr_ar, BX_CPU_THIS_PTR vmcs_map->get_access_rights_format());
bool ldtr_invalid = (ldtr_ar >> 16) & 1;
if (set_segment_ar_data(&guest.ldtr, !ldtr_invalid,
if (set_segment_ar_data(&guest.ldtr, !ldtr_invalid,
(Bit16u) ldtr_selector, ldtr_base, ldtr_limit, (Bit16u)(ldtr_ar)))
{
// ldtr is valid
@ -1741,7 +1741,7 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
}
#endif
set_segment_ar_data(&guest.tr, !tr_invalid,
set_segment_ar_data(&guest.tr, !tr_invalid,
(Bit16u) tr_selector, tr_base, tr_limit, (Bit16u)(tr_ar));
if (tr_invalid) {
@ -2085,7 +2085,7 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled > guest.sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
BX_CPU_THIS_PTR iCache.flushICacheEntries();
#endif
for(unsigned segreg=0; segreg<6; segreg++)
BX_CPU_THIS_PTR sregs[segreg] = guest.sregs[segreg];
@ -2429,7 +2429,7 @@ void BX_CPU_C::VMexitSaveGuestState(void)
VMwrite32(VMCS_32BIT_GUEST_ACTIVITY_STATE, BX_ACTIVITY_STATE_ACTIVE);
else
VMwrite32(VMCS_32BIT_GUEST_ACTIVITY_STATE, BX_CPU_THIS_PTR activity_state);
Bit32u interruptibility_state = 0;
if (interrupts_inhibited(BX_INHIBIT_INTERRUPTS)) {
if (interrupts_inhibited(BX_INHIBIT_DEBUG))
@ -2438,9 +2438,11 @@ void BX_CPU_C::VMexitSaveGuestState(void)
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_BY_STI;
}
if (is_masked_event(BX_EVENT_SMI))
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED;
// Do not set BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED (as the dual-monitor
// treatment is unimplemented).
// "VM exits that end outside system-management mode (SMM) save bit 2 (blocking by SMI)
// as 0 regardless of the state of such blocking before the VM exit."
if (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_VIRTUAL_NMI) {
if (is_masked_event(BX_EVENT_VMX_VIRTUAL_NMI))
interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED;
@ -2454,13 +2456,13 @@ void BX_CPU_C::VMexitSaveGuestState(void)
#if BX_SUPPORT_VMX >= 2
if (VMX_MSR_MISC & VMX_MISC_STORE_LMA_TO_X86_64_GUEST_VMENTRY_CONTROL) {
// VMEXITs store the value of EFER.LMA into the x86-64 guest" VMENTRY control
// VMEXITs store the value of EFER.LMA into the x86-64 guest VMENTRY control
// must be set if unrestricted guest is supported
if (long_mode())
vm->vmentry_ctrls |= VMX_VMENTRY_CTRL1_X86_64_GUEST;
else
vm->vmentry_ctrls &= ~VMX_VMENTRY_CTRL1_X86_64_GUEST;
VMwrite32(VMCS_32BIT_CONTROL_VMENTRY_CONTROLS, vm->vmentry_ctrls);
}
@ -2607,7 +2609,7 @@ void BX_CPU_C::VMexitLoadHostState(void)
}
}
// SS.DPL always clear
// SS.DPL always clear
BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 0;
if (x86_64_host || BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid)
@ -2743,7 +2745,7 @@ void BX_CPU_C::VMexit(Bit32u reason, Bit64u qualification)
VMexitSaveGuestState();
Bit32u msr = StoreMSRs(vm->vmexit_msr_store_cnt, vm->vmexit_msr_store_addr);
if (msr) {
if (msr) {
BX_ERROR(("VMABORT: Error when saving guest MSR number %d", msr));
VMabort(VMABORT_SAVING_GUEST_MSRS_FAILURE);
}
@ -2810,7 +2812,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXON(bxInstruction_c *i)
exception(BX_UD_EXCEPTION, 0);
if (! BX_CPU_THIS_PTR in_vmx) {
if (CPL != 0 || ! BX_CPU_THIS_PTR cr0.get_NE() ||
if (CPL != 0 || ! BX_CPU_THIS_PTR cr0.get_NE() ||
! (BX_CPU_THIS_PTR cr0.get_PE()) || BX_GET_ENABLE_A20() == 0 ||
! (BX_CPU_THIS_PTR msr.ia32_feature_ctrl & BX_IA32_FEATURE_CONTROL_LOCK_BIT) ||
! (BX_CPU_THIS_PTR msr.ia32_feature_ctrl & BX_IA32_FEATURE_CONTROL_VMX_ENABLE_BIT))
@ -2834,7 +2836,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXON(bxInstruction_c *i)
VMfailInvalid();
BX_NEXT_INSTR(i);
}
BX_CPU_THIS_PTR vmcsptr = BX_INVALID_VMCSPTR;
BX_CPU_THIS_PTR vmcshostptr = 0;
BX_CPU_THIS_PTR vmxonptr = pAddr;
@ -2860,7 +2862,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXON(bxInstruction_c *i)
VMfail(VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
}
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -2895,7 +2897,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXOFF(bxInstruction_c *i)
#endif
VMsucceed();
}
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -2918,7 +2920,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCALL(bxInstruction_c *i)
exception(BX_GP_EXCEPTION, 0);
}
if (BX_CPU_THIS_PTR in_smm /*||
if (BX_CPU_THIS_PTR in_smm /*||
(the logical processor does not support the dual-monitor treatment of SMIs and SMM) ||
(the valid bit in the IA32_SMM_MONITOR_CTL MSR is clear)*/)
{
@ -2967,7 +2969,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCALL(bxInstruction_c *i)
FI;
FI;
*/
#endif
#endif
BX_NEXT_TRACE(i);
}
@ -3066,7 +3068,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLAUNCH(bxInstruction_c *i)
///////////////////////////////////////////////////////
// STEP 6: Update VMCS 'launched' state
///////////////////////////////////////////////////////
if (vmlaunch) VMwrite32(VMCS_LAUNCH_STATE_FIELD_ENCODING, VMCS_STATE_LAUNCHED);
/*
@ -3197,7 +3199,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPTRLD(bxInstruction_c *i)
VMsucceed();
}
}
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -3220,7 +3222,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPTRST(bxInstruction_c *i)
bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
write_virtual_qword(i->seg(), eaddr, BX_CPU_THIS_PTR vmcsptr);
VMsucceed();
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -3398,9 +3400,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMREAD_EdGd(bxInstruction_c *i)
Bit32u eaddr = (Bit32u) BX_CPU_RESOLVE_ADDR(i);
write_virtual_dword_32(i->seg(), eaddr, field_32);
}
VMsucceed();
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -3463,9 +3465,9 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMREAD_EqGq(bxInstruction_c *i)
Bit64u eaddr = BX_CPU_RESOLVE_ADDR(i);
write_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr), field_64);
}
VMsucceed();
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -3535,7 +3537,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMWRITE_GdEd(bxInstruction_c *i)
vmwrite(encoding, (Bit64u) val_32);
VMsucceed();
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -3611,7 +3613,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMWRITE_GqEq(bxInstruction_c *i)
vmwrite(encoding, val_64);
VMsucceed();
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -3666,7 +3668,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCLEAR(bxInstruction_c *i)
VMsucceed();
}
#endif
#endif
BX_NEXT_INSTR(i);
}
@ -3789,7 +3791,7 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::INVVPID(bxInstruction_c *i)
case BX_INVEPT_INVVPID_ALL_CONTEXT_INVALIDATION:
TLB_flush(); // invalidate all mappings tagged with VPID <> 0
break;
case BX_INVEPT_INVVPID_SINGLE_CONTEXT_NON_GLOBAL_INVALIDATION:
TLB_flushNonGlobal(); // invalidate all mappings tagged with VPID except globals
break;
@ -4027,7 +4029,7 @@ void BX_CPU_C::register_vmx_state(bx_param_c *parent)
//
bx_list_c *vmentry_ctrls = new bx_list_c(vmcache, "VMENTRY_CTRLS");
BXRS_HEX_PARAM_FIELD(vmentry_ctrls, vmentry_ctrls, BX_CPU_THIS_PTR vmcs.vmentry_ctrls);
BXRS_DEC_PARAM_FIELD(vmentry_ctrls, vmentry_msr_load_cnt, BX_CPU_THIS_PTR vmcs.vmentry_msr_load_cnt);
BXRS_HEX_PARAM_FIELD(vmentry_ctrls, vmentry_msr_load_addr, BX_CPU_THIS_PTR vmcs.vmentry_msr_load_addr);