nova: re-/store ep fpu state in vm_session

Fixes #3913
This commit is contained in:
Alexander Boettcher
2020-10-13 11:37:21 +02:00
committed by Christian Helmuth
parent 20606bc6de
commit 0aaed47652

View File

@ -41,6 +41,9 @@ struct Vcpu {
void *_ep_handler { nullptr }; void *_ep_handler { nullptr };
void *_dispatching { nullptr }; void *_dispatching { nullptr };
bool _block { true }; bool _block { true };
bool _use_guest_fpu { false };
uint8_t _fpu_ep[512] __attribute__((aligned(0x10)));
enum Remote_state_requested { enum Remote_state_requested {
NONE = 0, NONE = 0,
@ -48,7 +51,7 @@ struct Vcpu {
RUN = 2 RUN = 2
} _remote { NONE }; } _remote { NONE };
static void _read_nova_state(Nova::Utcb &utcb, Vm_state &state, void _read_nova_state(Nova::Utcb &utcb, Vm_state &state,
unsigned exit_reason) unsigned exit_reason)
{ {
typedef Genode::Vm_state::Segment Segment; typedef Genode::Vm_state::Segment Segment;
@ -59,10 +62,12 @@ struct Vcpu {
if (utcb.mtd & Nova::Mtd::FPU) { if (utcb.mtd & Nova::Mtd::FPU) {
state.fpu.value([&] (uint8_t *fpu, size_t const) { state.fpu.value([&] (uint8_t *fpu, size_t const) {
asm volatile ("fxsave %0" : "=m" (*fpu)); asm volatile ("fxsave %0" : "=m" (*fpu) :: "memory");
}); });
asm volatile ("fxrstor %0" : : "m" (*_fpu_ep) : "memory");
} }
if (utcb.mtd & Nova::Mtd::ACDB) { if (utcb.mtd & Nova::Mtd::ACDB) {
state.ax.value(utcb.ax); state.ax.value(utcb.ax);
state.cx.value(utcb.cx); state.cx.value(utcb.cx);
@ -197,7 +202,7 @@ struct Vcpu {
} }
static void _write_nova_state(Nova::Utcb &utcb, Vm_state &state) void _write_nova_state(Nova::Utcb &utcb, Vm_state &state)
{ {
utcb.items = 0; utcb.items = 0;
utcb.mtd = 0; utcb.mtd = 0;
@ -394,9 +399,13 @@ struct Vcpu {
utcb.write_tpr_threshold(state.tpr_threshold.value()); utcb.write_tpr_threshold(state.tpr_threshold.value());
} }
if (_use_guest_fpu || state.fpu.valid())
asm volatile ("fxsave %0" : "=m" (*_fpu_ep) :: "memory");
if (state.fpu.valid()) { if (state.fpu.valid()) {
state.fpu.value([&] (uint8_t *fpu, size_t const) { state.fpu.value([&] (uint8_t *fpu, size_t const) {
asm volatile ("fxrstor %0" : : "m" (*fpu)); asm volatile ("fxrstor %0" : : "m" (*fpu) : "memory");
}); });
} }
} }
@ -471,7 +480,7 @@ struct Vcpu {
Vm_state &state = *reinterpret_cast<Vm_state *>(vcpu->_state); Vm_state &state = *reinterpret_cast<Vm_state *>(vcpu->_state);
/* transform state from NOVA to Genode */ /* transform state from NOVA to Genode */
if (exit_reason != VM_EXIT_RECALL || !previous_blocked) if (exit_reason != VM_EXIT_RECALL || !previous_blocked)
_read_nova_state(utcb, state, exit_reason); vcpu->_read_nova_state(utcb, state, exit_reason);
if (exit_reason == VM_EXIT_RECALL) { if (exit_reason == VM_EXIT_RECALL) {
if (previous_blocked) if (previous_blocked)
@ -498,7 +507,7 @@ struct Vcpu {
if (previous_blocked) { if (previous_blocked) {
/* resume vCPU - with vCPU state update */ /* resume vCPU - with vCPU state update */
vcpu->_block = false; vcpu->_block = false;
_write_nova_state(utcb, state); vcpu->_write_nova_state(utcb, state);
Nova::reply(myself.stack_top()); Nova::reply(myself.stack_top());
} }
} }
@ -514,7 +523,7 @@ struct Vcpu {
} }
/* reply to NOVA and transfer vCPU state */ /* reply to NOVA and transfer vCPU state */
_write_nova_state(utcb, state); vcpu->_write_nova_state(utcb, state);
Nova::reply(myself.stack_top()); Nova::reply(myself.stack_top());
} }
@ -671,8 +680,10 @@ struct Vcpu {
if (state.qual_primary.valid() || state.qual_secondary.valid()) if (state.qual_primary.valid() || state.qual_secondary.valid())
mtd |= Nova::Mtd::QUAL; mtd |= Nova::Mtd::QUAL;
if (state.fpu.valid()) if (state.fpu.valid()) {
_use_guest_fpu = true;
mtd |= Nova::Mtd::FPU; mtd |= Nova::Mtd::FPU;
}
state = Vm_state {}; state = Vm_state {};