mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 03:45:24 +00:00
parent
f596595c98
commit
c9b5dcafbd
@ -124,22 +124,37 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
INTERRUPT_STATE_NONE = 0U,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
void _fpu_save()
|
||||
{
|
||||
fpu_save(reinterpret_cast<char *>(&_guest_fpu_state));
|
||||
}
|
||||
|
||||
void _fpu_load()
|
||||
{
|
||||
fpu_load(reinterpret_cast<char *>(&_guest_fpu_state));
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _longjmp()
|
||||
{
|
||||
longjmp(_env, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* 'longjmp()' restores some FPU registers saved by 'setjmp()',
|
||||
* so we need to save the guest FPU state before calling 'longjmp()'
|
||||
*/
|
||||
__attribute__((noreturn)) void _fpu_save_and_longjmp()
|
||||
{
|
||||
fpu_save(reinterpret_cast<char *>(&_guest_fpu_state));
|
||||
longjmp(_env, 1);
|
||||
_fpu_save();
|
||||
_longjmp();
|
||||
}
|
||||
|
||||
int map_memory(RTGCPHYS GCPhys,
|
||||
size_t cbWrite, RTGCUINT vbox_fault_reason,
|
||||
Genode::Flexpage_iterator &fli, bool &writeable);
|
||||
|
||||
protected:
|
||||
|
||||
Genode::addr_t _vm_exits = 0;
|
||||
Genode::addr_t _recall_skip = 0;
|
||||
Genode::addr_t _recall_req = 0;
|
||||
@ -170,6 +185,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
if (!setjmp(_env)) {
|
||||
_stack_reply = reinterpret_cast<void *>(
|
||||
Abi::stack_align(reinterpret_cast<Genode::addr_t>(&value)));
|
||||
_fpu_load();
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
}
|
||||
@ -211,19 +227,21 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
|
||||
/* got recall during irq injection and the guest is ready for
|
||||
* delivery of IRQ - just continue */
|
||||
_fpu_load();
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
|
||||
/* are we forced to go back to emulation mode ? */
|
||||
if (!continue_hw_accelerated(utcb)) {
|
||||
/* go back to emulation mode */
|
||||
_fpu_save_and_longjmp();
|
||||
_longjmp();
|
||||
}
|
||||
|
||||
/* check whether we have to request irq injection window */
|
||||
utcb->mtd = Nova::Mtd::FPU;
|
||||
if (check_to_request_irq_window(utcb, _current_vcpu)) {
|
||||
_irq_win = true;
|
||||
_fpu_load();
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
|
||||
@ -239,8 +257,10 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
|
||||
utcb->mtd = Nova::Mtd::FPU;
|
||||
_irq_win = check_to_request_irq_window(utcb, _current_vcpu);
|
||||
if (_irq_win)
|
||||
if (_irq_win) {
|
||||
_fpu_load();
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
}
|
||||
|
||||
/* nothing to do at all - continue hardware accelerated */
|
||||
@ -262,6 +282,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
utcb->mtd |= Nova::Mtd::INJ;
|
||||
}
|
||||
|
||||
_fpu_load();
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
|
||||
@ -281,6 +302,8 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
|
||||
_fpu_save();
|
||||
|
||||
enum { MAP_SIZE = 0x1000UL };
|
||||
|
||||
bool writeable = true;
|
||||
@ -298,7 +321,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
|
||||
/* event re-injection is not handled yet for this case */
|
||||
Assert(!(utcb->inj_info & IRQ_INJ_VALID_MASK));
|
||||
_fpu_save_and_longjmp();
|
||||
_longjmp();
|
||||
}
|
||||
|
||||
/* fault region can be mapped - prepare utcb */
|
||||
@ -347,6 +370,8 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
"guestf fault at ", Genode::Hex(guest_fault));
|
||||
} while (res);
|
||||
|
||||
_fpu_load();
|
||||
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
|
||||
@ -656,6 +681,8 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
/* happens if PDMApicSetTPR (see above) mask IRQ */
|
||||
utcb->inj_info = IRQ_INJ_NONE;
|
||||
utcb->mtd = Nova::Mtd::INJ | Nova::Mtd::FPU;
|
||||
|
||||
_fpu_load();
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
}
|
||||
@ -707,6 +734,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
Genode::Hex(utcb->mtd));
|
||||
*/
|
||||
utcb->mtd = Nova::Mtd::INJ | Nova::Mtd::FPU;
|
||||
_fpu_load();
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
|
||||
@ -911,7 +939,7 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
/* save current FPU state */
|
||||
fpu_save(reinterpret_cast<char *>(&_emt_fpu_state));
|
||||
/* write FPU state from pCtx to FPU registers */
|
||||
fpu_load(reinterpret_cast<char *>(pCtx->pXStateR3));
|
||||
memcpy(&_guest_fpu_state, pCtx->pXStateR3, sizeof(_guest_fpu_state));
|
||||
/* tell kernel to transfer current fpu registers to vCPU */
|
||||
utcb->mtd |= Mtd::FPU;
|
||||
|
||||
|
@ -24,7 +24,11 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
|
||||
__attribute__((noreturn)) void _svm_default() { _default_handler(); }
|
||||
|
||||
__attribute__((noreturn)) void _svm_vintr() { _irq_window(); }
|
||||
__attribute__((noreturn)) void _svm_vintr()
|
||||
{
|
||||
_fpu_save();
|
||||
_irq_window();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _svm_ioio()
|
||||
{
|
||||
@ -79,6 +83,7 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
|
||||
__attribute__((noreturn)) void _svm_recall()
|
||||
{
|
||||
_fpu_save();
|
||||
Vcpu_handler::_recall_handler();
|
||||
}
|
||||
|
||||
|
@ -105,10 +105,15 @@ class Vcpu_handler_vmx : public Vcpu_handler
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _vmx_irqwin() { _irq_window(); }
|
||||
__attribute__((noreturn)) void _vmx_irqwin()
|
||||
{
|
||||
_fpu_save();
|
||||
_irq_window();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _vmx_recall()
|
||||
{
|
||||
_fpu_save();
|
||||
Vcpu_handler::_recall_handler();
|
||||
}
|
||||
|
||||
@ -140,8 +145,7 @@ class Vcpu_handler_vmx : public Vcpu_handler
|
||||
*/
|
||||
__attribute__((noreturn)) void _vmx_mov_crx()
|
||||
{
|
||||
unsigned long value;
|
||||
void *stack_reply = reinterpret_cast<void *>(&value - 1);
|
||||
_fpu_save();
|
||||
|
||||
Genode::Thread *myself = Genode::Thread::myself();
|
||||
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
|
||||
@ -149,7 +153,7 @@ class Vcpu_handler_vmx : public Vcpu_handler
|
||||
unsigned int cr = utcb->qual[0] & 0xf;
|
||||
|
||||
if (cr == 8)
|
||||
_default_handler();
|
||||
_longjmp();
|
||||
|
||||
_vm_exits ++;
|
||||
|
||||
@ -164,7 +168,9 @@ class Vcpu_handler_vmx : public Vcpu_handler
|
||||
|
||||
utcb->mtd = Nova::Mtd::PDPTE | Nova::Mtd::FPU;
|
||||
|
||||
Nova::reply(stack_reply);
|
||||
_fpu_load();
|
||||
|
||||
Nova::reply(_stack_reply);
|
||||
}
|
||||
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user