From 9c31e18a4f84f48032bf72bafae1aeb5ae5dd695 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 26 Nov 2015 17:25:45 +0100 Subject: [PATCH] vbox: handle EPT violation during event delivery If the injection of an event causes an EPT violation, the event must be injected again. This commit implements the reinjection for the case that the EPT violation can be resolved without involving the recompiler. Fixes #1798 --- repos/ports/src/virtualbox/spec/nova/vcpu.h | 27 ++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/repos/ports/src/virtualbox/spec/nova/vcpu.h b/repos/ports/src/virtualbox/spec/nova/vcpu.h index 705478e3c..524d86f7c 100644 --- a/repos/ports/src/virtualbox/spec/nova/vcpu.h +++ b/repos/ports/src/virtualbox/spec/nova/vcpu.h @@ -91,6 +91,9 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher, unsigned int _cpu_id; Genode::Semaphore _halt_sem; + unsigned int _last_inj_info; + unsigned int _last_inj_error; + void fpu_save(char * data) { Assert(!(reinterpret_cast(data) & 0xF)); asm volatile ("fxsave %0" : "=m" (*data)); @@ -224,11 +227,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher, Assert(utcb->actv_state == ACTIVITY_STATE_ACTIVE); - if (utcb->inj_info & IRQ_INJ_VALID_MASK) - Vmm::printf("inj_info %x\n", utcb->inj_info); - - Assert(!(utcb->inj_info & IRQ_INJ_VALID_MASK)); - if (unmap) { PERR("unmap not implemented\n"); Nova::reply(_stack_reply); @@ -252,12 +250,26 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher, } /* emulator has to take over if fault region is not ram */ - if (!pv) + if (!pv) { + /* event re-injection is not handled yet for this case */ + Assert(!(utcb->inj_info & IRQ_INJ_VALID_MASK)); _fpu_save_and_longjmp(); + } /* fault region can be mapped - prepare utcb */ utcb->set_msg_word(0); utcb->mtd = Mtd::FPU; + + if (utcb->inj_info & IRQ_INJ_VALID_MASK) { + /* + * The EPT violation occurred during event injection, + * so the event needs to be injected again. + */ + utcb->mtd |= Mtd::INJ; + utcb->inj_info = _last_inj_info; + utcb->inj_error = _last_inj_error; + } + enum { USER_PD = false, GUEST_PGT = true, READABLE = true, EXECUTABLE = true @@ -601,6 +613,9 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher, utcb->inj_info = Event.u; utcb->inj_error = Event.n.u32ErrorCode; + _last_inj_info = utcb->inj_info; + _last_inj_error = utcb->inj_error; + /* Vmm::printf("type:info:vector %x:%x:%x intr:actv - %x:%x mtd %x\n", Event.n.u3Type, utcb->inj_info, u8Vector, utcb->intr_state, utcb->actv_state, utcb->mtd);