From 8d5903cba93668e993b08a310e7380f95d3d7988 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 8 Oct 2021 11:43:33 +0200 Subject: [PATCH] vbox6: avoid unintended state transfer on hw enter intr_state and actv_state are now charged only if required and with valid values. Issue #4313 --- repos/ports/src/virtualbox6/sup_vcpu.cc | 22 +++++++++------------- repos/ports/src/virtualbox6/sup_vcpu_svm.h | 2 +- repos/ports/src/virtualbox6/sup_vcpu_vmx.h | 2 +- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/repos/ports/src/virtualbox6/sup_vcpu.cc b/repos/ports/src/virtualbox6/sup_vcpu.cc index c6839d6680..6075c11868 100644 --- a/repos/ports/src/virtualbox6/sup_vcpu.cc +++ b/repos/ports/src/virtualbox6/sup_vcpu.cc @@ -123,7 +123,6 @@ class Sup::Vcpu_impl : public Sup::Vcpu, Genode::Noncopyable }; struct { - unsigned intr_state = 0; unsigned ctrl_primary = VIRT::ctrl_primary(); unsigned ctrl_secondary = VIRT::ctrl_secondary(); } _cached_state; @@ -173,9 +172,6 @@ template void Sup::Vcpu_impl::_transfer_state_to_vcpu(CPUM Vcpu_state &state { _vcpu.state() }; /* transfer defaults and cached state */ - state.inj_info.charge(VMX_ENTRY_INT_INFO_NONE); /* XXX never injects events */ - state.intr_state.charge(_cached_state.intr_state); - state.actv_state.charge(VMX_VMCS_GUEST_ACTIVITY_ACTIVE); state.ctrl_primary.charge(_cached_state.ctrl_primary); /* XXX always updates ctrls */ state.ctrl_secondary.charge(_cached_state.ctrl_secondary); /* XXX always updates ctrls */ @@ -354,14 +350,14 @@ template void Sup::Vcpu_impl::_transfer_state_to_vbox(CPUM uint32_t const tpr = state.tpr.value(); /* update cached state */ - Assert(!VMX_ENTRY_INT_INFO_IS_VALID(state.inj_info.value())); - _cached_state.intr_state = state.intr_state.value(); _cached_state.ctrl_primary = state.ctrl_primary.value(); _cached_state.ctrl_secondary = state.ctrl_secondary.value(); /* clear blocking by MOV SS or STI bits */ - if (_cached_state.intr_state & 3) - _cached_state.intr_state &= ~3U; + if (_vcpu.state().intr_state.value() & 3) { + _vcpu.state().intr_state.charge(state.intr_state.value() & ~3U); + _vcpu.state().actv_state.charge(VMX_VMCS_GUEST_ACTIVITY_ACTIVE); + } VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3); @@ -491,7 +487,7 @@ typename Sup::Vcpu_impl::Current_state Sup::Vcpu_impl::_handle_paused() Assert(state.actv_state.value() == VMX_VMCS_GUEST_ACTIVITY_ACTIVE); - if (VMX_ENTRY_INT_INFO_IS_VALID(state.inj_info.value())) { + if (VMX_EXIT_INT_INFO_IS_VALID(state.inj_info.value())) { Assert(state.flags.value() & X86_EFL_IF); @@ -519,7 +515,6 @@ typename Sup::Vcpu_impl::Current_state Sup::Vcpu_impl::_handle_paused() /* check whether we have to request irq injection window */ if (_check_and_request_irq_window()) { - state.discharge(); state.inj_info.charge(state.inj_info.value()); _irq_window = true; return RUNNING; @@ -541,14 +536,12 @@ typename Sup::Vcpu_impl::Current_state Sup::Vcpu_impl::_handle_irq_window( { Vcpu_state &state { _vcpu.state() }; - state.discharge(); - PVMCPU pVCpu = &_vmcpu; Assert(state.intr_state.value() == VMX_VMCS_GUEST_INT_STATE_NONE); Assert(state.flags.value() & X86_EFL_IF); Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)); - Assert(!VMX_ENTRY_INT_INFO_IS_VALID(state.inj_info.value())); + Assert(!VMX_EXIT_INT_INFO_IS_VALID(state.inj_info.value())); Assert(_irq_window); _irq_window = false; @@ -638,6 +631,9 @@ template VBOXSTRICTRC Sup::Vcpu_impl::_switch_to_hw() result = VIRT::handle_exit(_vcpu.state()); + /* discharge by default */ + _vcpu.state().discharge(); + switch (result.state) { case Exit_state::STARTUP: diff --git a/repos/ports/src/virtualbox6/sup_vcpu_svm.h b/repos/ports/src/virtualbox6/sup_vcpu_svm.h index 5627b398ff..fe2dfc1bb4 100644 --- a/repos/ports/src/virtualbox6/sup_vcpu_svm.h +++ b/repos/ports/src/virtualbox6/sup_vcpu_svm.h @@ -193,7 +193,7 @@ Sup::Handle_exit_result Sup::Svm::handle_exit(Vcpu_state &state) case SVM_EXIT_RDTSCP: case SVM_EXIT_WBINVD: Assert(state.actv_state.value() == VMX_VMCS_GUEST_ACTIVITY_ACTIVE); - Assert(!VMX_ENTRY_INT_INFO_IS_VALID(state.inj_info.value())); + Assert(!VMX_EXIT_INT_INFO_IS_VALID(state.inj_info.value())); return { Exit_state::DEFAULT, VINF_EM_RAW_EMULATE_INSTR }; case SVM_EXIT_VINTR: diff --git a/repos/ports/src/virtualbox6/sup_vcpu_vmx.h b/repos/ports/src/virtualbox6/sup_vcpu_vmx.h index adfe9b1dfb..de9a760d5e 100644 --- a/repos/ports/src/virtualbox6/sup_vcpu_vmx.h +++ b/repos/ports/src/virtualbox6/sup_vcpu_vmx.h @@ -183,7 +183,7 @@ void Sup::Vmx::_handle_invalid(Vcpu_state const &state) void Sup::Vmx::_handle_default(Vcpu_state &state) { Assert(state.actv_state.value() == VMX_VMCS_GUEST_ACTIVITY_ACTIVE); - Assert(!VMX_ENTRY_INT_INFO_IS_VALID(state.inj_info.value())); + Assert(!VMX_EXIT_INT_INFO_IS_VALID(state.inj_info.value())); }