vbox: update tpr register before requesting irq

- required by win7 64bit guest single vCPU

Fixes #2089
This commit is contained in:
Alexander Boettcher 2016-09-08 09:44:09 +02:00 committed by Christian Helmuth
parent 2147c42ec6
commit 8fb6f032d4
2 changed files with 49 additions and 19 deletions

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2013-2014 Genode Labs GmbH
* Copyright (C) 2013-2016 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
@ -325,6 +325,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
/* avoid utcb corruption by requesting tpr state early */
bool interrupt_pending = false;
uint8_t tpr = 0;
uint8_t pending_interrupt = 0;
PDMApicGetTPR(pVCpu, &tpr, &interrupt_pending, &pending_interrupt);
/* don't call function hereafter which may corrupt the utcb ! */
using namespace Nova;
utcb->mtd |= Mtd::EIP;
@ -421,10 +428,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
utcb->write_kernel_gs_base(pCtx->msrKERNELGSBASE);
/* from HMVMXR0.cpp */
bool interrupt_pending = false;
uint8_t tpr = 0;
uint8_t pending_interrupt = 0;
PDMApicGetTPR(pVCpu, &tpr, &interrupt_pending, &pending_interrupt);
utcb->mtd |= Mtd::TPR;
utcb->write_tpr(tpr);
utcb->write_tpr_threshold(0);
@ -437,8 +440,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
utcb->write_tpr_threshold(tpr_priority);
}
Assert(!(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)));
return true;
}
@ -514,7 +515,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
if (pCtx->msrKERNELGSBASE != utcb->read_kernel_gs_base())
CPUMSetGuestMsr(pVCpu, MSR_K8_KERNEL_GS_BASE, utcb->read_kernel_gs_base());
PDMApicSetTPR(pVCpu, utcb->read_tpr());
const uint32_t tpr = utcb->read_tpr();
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
@ -529,12 +530,18 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
} else
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
/* functions that corrupt utcb (e.g. when logging enabled) */
PDMApicSetTPR(pVCpu, tpr);
return true;
}
inline bool check_to_request_irq_window(Nova::Utcb * utcb, PVMCPU pVCpu)
{
if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
return false;
if (!TRPMHasTrap(pVCpu) &&
!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC |
VMCPU_FF_INTERRUPT_PIC)))
@ -562,6 +569,9 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
Assert(_irq_win);
_irq_win = false;
/* request current tpr state from guest, it may block IRQs */
PDMApicSetTPR(pVCpu, utcb->read_tpr());
if (!TRPMHasTrap(pVCpu)) {
bool res = VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
@ -577,6 +587,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
rc = TRPMAssertTrap(pVCpu, irq, TRPM_HARDWARE_INT);
Assert(RT_SUCCESS(rc));
}
if (!TRPMHasTrap(pVCpu)) {
/* happens if PDMApicSetTPR (see above) mask IRQ */
utcb->inj_info = IRQ_INJ_NONE;
utcb->mtd = Nova::Mtd::INJ | Nova::Mtd::FPU;
Nova::reply(_stack_reply);
}
}
/*
@ -631,8 +648,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
inline bool continue_hw_accelerated(Nova::Utcb * utcb, bool verbose = false)
{
Assert(!(VMCPU_FF_IS_SET(_current_vcpu, VMCPU_FF_INHIBIT_INTERRUPTS)));
uint32_t check_vm = VM_FF_HM_TO_R3_MASK | VM_FF_REQUEST
| VM_FF_PGM_POOL_FLUSH_PENDING
| VM_FF_PDM_DMA;

View File

@ -327,6 +327,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
/* avoid utcb corruption by requesting tpr state early */
bool interrupt_pending = false;
uint8_t tpr = 0;
uint8_t pending_interrupt = 0;
PDMApicGetTPR(pVCpu, &tpr, &interrupt_pending, &pending_interrupt);
/* don't call function hereafter which may corrupt the utcb ! */
using namespace Nova;
utcb->mtd |= Mtd::EIP;
@ -420,10 +427,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
utcb->write_kernel_gs_base(pCtx->msrKERNELGSBASE);
/* from HMVMXR0.cpp */
bool interrupt_pending = false;
uint8_t tpr = 0;
uint8_t pending_interrupt = 0;
PDMApicGetTPR(pVCpu, &tpr, &interrupt_pending, &pending_interrupt);
utcb->mtd |= Mtd::TPR;
utcb->write_tpr(tpr);
utcb->write_tpr_threshold(0);
@ -436,8 +439,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
utcb->write_tpr_threshold(tpr_priority);
}
Assert(!(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)));
return true;
}
@ -515,7 +516,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
if (pCtx->msrKERNELGSBASE != utcb->read_kernel_gs_base())
CPUMSetGuestMsr(pVCpu, MSR_K8_KERNEL_GS_BASE, utcb->read_kernel_gs_base());
PDMApicSetTPR(pVCpu, utcb->read_tpr());
const uint32_t tpr = utcb->read_tpr();
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
@ -530,12 +531,18 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
} else
VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
/* functions that corrupt utcb (e.g. when logging enabled) */
PDMApicSetTPR(pVCpu, tpr);
return true;
}
inline bool check_to_request_irq_window(Nova::Utcb * utcb, PVMCPU pVCpu)
{
if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
return false;
if (!TRPMHasTrap(pVCpu) &&
!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC |
VMCPU_FF_INTERRUPT_PIC)))
@ -563,6 +570,9 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
Assert(_irq_win);
_irq_win = false;
/* request current tpr state from guest, it may block IRQs */
PDMApicSetTPR(pVCpu, utcb->read_tpr());
if (!TRPMHasTrap(pVCpu)) {
bool res = VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
@ -578,6 +588,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
rc = TRPMAssertTrap(pVCpu, irq, TRPM_HARDWARE_INT);
Assert(RT_SUCCESS(rc));
}
if (!TRPMHasTrap(pVCpu)) {
/* happens if PDMApicSetTPR (see above) mask IRQ */
utcb->inj_info = IRQ_INJ_NONE;
utcb->mtd = Nova::Mtd::INJ | Nova::Mtd::FPU;
Nova::reply(_stack_reply);
}
}
/*
@ -632,8 +649,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
inline bool continue_hw_accelerated(Nova::Utcb * utcb, bool verbose = false)
{
Assert(!(VMCPU_FF_IS_SET(_current_vcpu, VMCPU_FF_INHIBIT_INTERRUPTS)));
uint32_t check_vm = VM_FF_HM_TO_R3_MASK | VM_FF_REQUEST
| VM_FF_PGM_POOL_FLUSH_PENDING
| VM_FF_PDM_DMA;