vm_session: add fpu state for x86

Issue #3111
This commit is contained in:
Alexander Boettcher 2019-05-20 15:36:47 +02:00 committed by Christian Helmuth
parent 5673c163fb
commit ab6315d6b4
5 changed files with 45 additions and 5 deletions

View File

@ -87,7 +87,7 @@ Vcpu::Vcpu(Constrained_ram_allocator &ram_alloc,
{ {
try { try {
/* create ds for vCPU state */ /* create ds for vCPU state */
_ds_cap = _ram_alloc.alloc(4096, Cache_attribute::CACHED); _ds_cap = _ram_alloc.alloc(0x1000, Cache_attribute::CACHED);
} catch (...) { } catch (...) {
throw; throw;
} }

View File

@ -13,6 +13,7 @@
/* Base includes */ /* Base includes */
#include <base/cache.h> #include <base/cache.h>
#include <cpu/vm_state.h>
#include <util/list.h> #include <util/list.h>
#include <util/flex_iterator.h> #include <util/flex_iterator.h>
@ -65,7 +66,8 @@ Vm_session_component::Vcpu::Vcpu(Constrained_ram_allocator &ram_alloc,
try { try {
/* create ds for vCPU state */ /* create ds for vCPU state */
_ds_cap = _ram_alloc.alloc(4096, Cache_attribute::CACHED); _ds_cap = _ram_alloc.alloc(align_addr(sizeof(Genode::Vm_state), 12),
Cache_attribute::CACHED);
} catch (...) { } catch (...) {
_cap_alloc.replenish(Cap_quota{CAP_RANGE}); _cap_alloc.replenish(Cap_quota{CAP_RANGE});
cap_map().remove(_sel_sm_ec_sc, CAP_RANGE_LOG2); cap_map().remove(_sel_sm_ec_sc, CAP_RANGE_LOG2);

View File

@ -58,6 +58,12 @@ struct Vcpu {
state = Vm_state {}; state = Vm_state {};
state.exit_reason = exit_reason; state.exit_reason = exit_reason;
if (utcb.mtd & Nova::Mtd::FPU) {
state.fpu.value([&] (uint8_t *fpu, size_t const) {
asm volatile ("fxsave %0" : "=m" (*fpu));
});
}
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);
@ -190,7 +196,6 @@ struct Vcpu {
state.tpr_threshold.value(utcb.read_tpr_threshold()); state.tpr_threshold.value(utcb.read_tpr_threshold());
} }
/* XXX FPU state missing */
} }
static void _write_nova_state(Nova::Utcb &utcb, Vm_state &state) static void _write_nova_state(Nova::Utcb &utcb, Vm_state &state)
@ -389,6 +394,12 @@ struct Vcpu {
utcb.write_tpr(state.tpr.value()); utcb.write_tpr(state.tpr.value());
utcb.write_tpr_threshold(state.tpr_threshold.value()); utcb.write_tpr_threshold(state.tpr_threshold.value());
} }
if (state.fpu.valid()) {
state.fpu.value([&] (uint8_t *fpu, size_t const) {
asm volatile ("fxrstor %0" : : "m" (*fpu));
});
}
} }
void _dispatch() void _dispatch()
@ -655,7 +666,8 @@ 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;
/* XXX FPU missing */ if (state.fpu.valid())
mtd |= Nova::Mtd::FPU;
state = Vm_state {}; state = Vm_state {};

View File

@ -13,6 +13,7 @@
/* base includes */ /* base includes */
#include <util/flex_iterator.h> #include <util/flex_iterator.h>
#include <cpu/vm_state.h>
/* core includes */ /* core includes */
#include <core_env.h> #include <core_env.h>
@ -45,7 +46,8 @@ Vm_session_component::Vcpu::Vcpu(Constrained_ram_allocator &ram_alloc,
seL4_Untyped const service) seL4_Untyped const service)
: :
_ram_alloc(ram_alloc), _ram_alloc(ram_alloc),
_ds_cap (_ram_alloc.alloc(4096, Cache_attribute::CACHED)), _ds_cap (_ram_alloc.alloc(align_addr(sizeof(Genode::Vm_state), 12),
Cache_attribute::CACHED)),
_vcpu_id(vcpu_id) _vcpu_id(vcpu_id)
{ {
try { try {

View File

@ -141,6 +141,30 @@ struct Genode::Vm_state
Register<uint32_t> tpr_threshold; Register<uint32_t> tpr_threshold;
unsigned exit_reason; unsigned exit_reason;
class Fpu {
private :
uint8_t _value[512] { };
bool _valid { false };
public:
bool valid() const { return _valid; }
void invalid() { _valid = false; }
template <typename FUNC>
void value(FUNC const &fn) {
_valid = true;
fn(_value, sizeof(_value));
};
Fpu &operator = (Fpu const &)
{
_valid = false;
return *this;
}
} fpu __attribute__((aligned(16)));
}; };
#endif /* _INCLUDE__SPEC__X86__CPU__VM_STATE_H_ */ #endif /* _INCLUDE__SPEC__X86__CPU__VM_STATE_H_ */