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:
parent
112afe5693
commit
0ae5e67894
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user