From ab6315d6b4f9158ee9458d9e9393000943526b2e Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 20 May 2019 15:36:47 +0200 Subject: [PATCH] vm_session: add fpu state for x86 Issue #3111 --- .../base-foc/src/core/vm_session_component.cc | 2 +- .../src/core/vm_session_component.cc | 4 +++- repos/base-nova/src/lib/base/vm_session.cc | 16 +++++++++++-- .../src/core/spec/x86/vm_session_component.cc | 4 +++- repos/base/include/spec/x86/cpu/vm_state.h | 24 +++++++++++++++++++ 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/repos/base-foc/src/core/vm_session_component.cc b/repos/base-foc/src/core/vm_session_component.cc index 3847c8edb..7e9cbe7fb 100644 --- a/repos/base-foc/src/core/vm_session_component.cc +++ b/repos/base-foc/src/core/vm_session_component.cc @@ -87,7 +87,7 @@ Vcpu::Vcpu(Constrained_ram_allocator &ram_alloc, { try { /* create ds for vCPU state */ - _ds_cap = _ram_alloc.alloc(4096, Cache_attribute::CACHED); + _ds_cap = _ram_alloc.alloc(0x1000, Cache_attribute::CACHED); } catch (...) { throw; } diff --git a/repos/base-nova/src/core/vm_session_component.cc b/repos/base-nova/src/core/vm_session_component.cc index 94aa97693..55f6c91f2 100644 --- a/repos/base-nova/src/core/vm_session_component.cc +++ b/repos/base-nova/src/core/vm_session_component.cc @@ -13,6 +13,7 @@ /* Base includes */ #include +#include #include #include @@ -65,7 +66,8 @@ Vm_session_component::Vcpu::Vcpu(Constrained_ram_allocator &ram_alloc, try { /* 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 (...) { _cap_alloc.replenish(Cap_quota{CAP_RANGE}); cap_map().remove(_sel_sm_ec_sc, CAP_RANGE_LOG2); diff --git a/repos/base-nova/src/lib/base/vm_session.cc b/repos/base-nova/src/lib/base/vm_session.cc index 0abeccdf3..fc1a4da3f 100644 --- a/repos/base-nova/src/lib/base/vm_session.cc +++ b/repos/base-nova/src/lib/base/vm_session.cc @@ -58,6 +58,12 @@ struct Vcpu { state = Vm_state {}; 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) { state.ax.value(utcb.ax); state.cx.value(utcb.cx); @@ -190,7 +196,6 @@ struct Vcpu { state.tpr_threshold.value(utcb.read_tpr_threshold()); } - /* XXX FPU state missing */ } 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_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() @@ -655,7 +666,8 @@ struct Vcpu { if (state.qual_primary.valid() || state.qual_secondary.valid()) mtd |= Nova::Mtd::QUAL; - /* XXX FPU missing */ + if (state.fpu.valid()) + mtd |= Nova::Mtd::FPU; state = Vm_state {}; diff --git a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc index b674e827e..642fd288a 100644 --- a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc +++ b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc @@ -13,6 +13,7 @@ /* base includes */ #include +#include /* core includes */ #include @@ -45,7 +46,8 @@ Vm_session_component::Vcpu::Vcpu(Constrained_ram_allocator &ram_alloc, seL4_Untyped const service) : _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) { try { diff --git a/repos/base/include/spec/x86/cpu/vm_state.h b/repos/base/include/spec/x86/cpu/vm_state.h index 1018b44ae..291120ad4 100644 --- a/repos/base/include/spec/x86/cpu/vm_state.h +++ b/repos/base/include/spec/x86/cpu/vm_state.h @@ -141,6 +141,30 @@ struct Genode::Vm_state Register tpr_threshold; unsigned exit_reason; + + class Fpu { + private : + + uint8_t _value[512] { }; + bool _valid { false }; + + public: + + bool valid() const { return _valid; } + void invalid() { _valid = false; } + + template + 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_ */