diff --git a/repos/base-hw/include/spec/imx53/vm_state.h b/repos/base-hw/include/spec/imx53/cpu/vm_state.h similarity index 100% rename from repos/base-hw/include/spec/imx53/vm_state.h rename to repos/base-hw/include/spec/imx53/cpu/vm_state.h diff --git a/repos/base-hw/src/core/kernel/vm.h b/repos/base-hw/src/core/kernel/vm.h index 83a706312..d13caa4fe 100644 --- a/repos/base-hw/src/core/kernel/vm.h +++ b/repos/base-hw/src/core/kernel/vm.h @@ -14,7 +14,7 @@ #ifndef _CORE__KERNEL__VM_H_ #define _CORE__KERNEL__VM_H_ -#include +#include /* core includes */ #include diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc index ae99993f7..ee148fb04 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc @@ -18,10 +18,9 @@ using namespace Genode; -void Vm_session_component::exception_handler(Signal_context_capability handler) +void Vm_session_component::_exception_handler(Signal_context_capability handler, Vcpu_id) { - if (!create((void*)_ds.core_local_addr(), Capability_space::capid(handler), - nullptr)) + if (!create(_ds_addr, Capability_space::capid(handler), nullptr)) { warning("Cannot instantiate vm kernel object twice," "or invalid signal context?"); @@ -29,21 +28,35 @@ void Vm_session_component::exception_handler(Signal_context_capability handler) } -Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep, - size_t ram_quota) -: _ds_ep(ds_ep), _ds(_ds_size(), _alloc_ds(ram_quota), UNCACHED, true, 0), - _ds_cap(static_cap_cast(_ds_ep->manage(&_ds))) +Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep, + Resources resources, + Label const &, + Diag, + Ram_allocator &ram_alloc, + Region_map ®ion_map) +: + Ram_quota_guard(resources.ram_quota), + Cap_quota_guard(resources.cap_quota), + _ds_ep(&ds_ep), + _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), + _region_map(region_map) { - _ds.assign_core_local_addr(core_env().rm_session()->attach(_ds_cap)); + _ds_cap = _constrained_md_ram_alloc.alloc(_ds_size(), Genode::Cache_attribute::UNCACHED); + + try { + _ds_addr = region_map.attach(_ds_cap); + } catch (...) { + _constrained_md_ram_alloc.free(_ds_cap); + throw; + } } Vm_session_component::~Vm_session_component() { - /* dissolve VM dataspace from service entry point */ - _ds_ep->dissolve(&_ds); - /* free region in allocator */ - core_env().rm_session()->detach(_ds.core_local_addr()); - platform().ram_alloc().free((void*)_ds.phys_addr()); + if (_ds_cap.valid()) { + _region_map.detach(_ds_addr); + _constrained_md_ram_alloc.free(_ds_cap); + } } diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h index 4571f629b..3459262b8 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h @@ -16,12 +16,11 @@ /* Genode includes */ #include -#include +#include #include #include /* Core includes */ -#include #include #include @@ -29,8 +28,12 @@ namespace Genode { class Vm_session_component; } -class Genode::Vm_session_component : public Genode::Rpc_object, - private Kernel_object +class Genode::Vm_session_component +: + private Ram_quota_guard, + private Cap_quota_guard, + public Rpc_object, + private Kernel_object { private: @@ -40,35 +43,41 @@ class Genode::Vm_session_component : public Genode::Rpc_object::cap; + + Vm_session_component(Rpc_entrypoint &, Resources, Label const &, + Diag, Ram_allocator &ram, Region_map &); ~Vm_session_component(); - using Rpc_object::cap; - - /************************** ** Vm session interface ** **************************/ - Dataspace_capability cpu_state(void) { return _ds_cap; } - void exception_handler(Signal_context_capability handler); - void run(void); - void pause(void); + Dataspace_capability _cpu_state(Vcpu_id) { return _ds_cap; } + void _exception_handler(Signal_context_capability handler, Vcpu_id); + void _run(Vcpu_id); + void _pause(Vcpu_id); void attach(Dataspace_capability, addr_t /* vm_addr */) { warning("Not implemented for TrustZone case"); } @@ -78,6 +87,7 @@ class Genode::Vm_session_component : public Genode::Rpc_object(platform().core_mem_alloc()); } -void Vm_session_component::exception_handler(Signal_context_capability handler) +void Vm_session_component::_exception_handler(Signal_context_capability handler, Vcpu_id) { - if (!create((void*)_ds.core_local_addr(), Capability_space::capid(handler), + if (!create(_ds_addr, Capability_space::capid(handler), cma().phys_addr(&_table))) Genode::warning("Cannot instantiate vm kernel object, invalid signal context?"); } @@ -93,26 +93,40 @@ void * Vm_session_component::_alloc_table() } -Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep, - size_t ram_quota) -: _ds_ep(ds_ep), _ds(_ds_size(), _alloc_ds(ram_quota), UNCACHED, true, 0), - _ds_cap(static_cap_cast(_ds_ep->manage(&_ds))), - _table(*construct_at(_alloc_table())), - _table_array(*(new (cma()) Array([this] (void * virt) { - return (addr_t)cma().phys_addr(virt);}))) +Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep, + Resources resources, + Label const &, + Diag, + Ram_allocator &ram_alloc, + Region_map ®ion_map) +: + Ram_quota_guard(resources.ram_quota), + Cap_quota_guard(resources.cap_quota), + _ds_ep(&ds_ep), + _constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()), + _region_map(region_map), + _table(*construct_at
(_alloc_table())), + _table_array(*(new (cma()) Array([this] (void * virt) { + return (addr_t)cma().phys_addr(virt);}))) { - _ds.assign_core_local_addr(core_env().rm_session()->attach(_ds_cap)); + _ds_cap = _constrained_md_ram_alloc.alloc(_ds_size(), Genode::Cache_attribute::UNCACHED); + + try { + _ds_addr = region_map.attach(_ds_cap); + } catch (...) { + _constrained_md_ram_alloc.free(_ds_cap); + throw; + } } Vm_session_component::~Vm_session_component() { - /* dissolve VM dataspace from service entry point */ - _ds_ep->dissolve(&_ds); - /* free region in allocator */ - core_env().rm_session()->detach(_ds.core_local_addr()); - platform().ram_alloc().free((void*)_ds.phys_addr()); + if (_ds_cap.valid()) { + _region_map.detach(_ds_addr); + _constrained_md_ram_alloc.free(_ds_cap); + } /* free guest-to-host page tables */ destroy(platform().core_mem_alloc(), &_table); diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h index c99a16882..f52844094 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h @@ -16,13 +16,12 @@ /* Genode includes */ #include -#include +#include #include #include #include /* Core includes */ -#include #include #include #include @@ -31,8 +30,12 @@ namespace Genode { class Vm_session_component; } -class Genode::Vm_session_component : public Genode::Rpc_object, - private Kernel_object +class Genode::Vm_session_component +: + private Ram_quota_guard, + private Cap_quota_guard, + public Rpc_object, + private Kernel_object { private: @@ -45,42 +48,50 @@ class Genode::Vm_session_component : public Genode::Rpc_object; - Rpc_entrypoint *_ds_ep; - Range_allocator *_ram_alloc = nullptr; - Dataspace_component _ds; - Dataspace_capability _ds_cap; - addr_t _ds_addr = 0; - Table &_table; - Array &_table_array; + Rpc_entrypoint *_ds_ep; + Constrained_ram_allocator _constrained_md_ram_alloc; + Region_map &_region_map; + Ram_dataspace_capability _ds_cap { }; + Region_map::Local_addr _ds_addr { 0 }; + Table &_table; + Array &_table_array; static size_t _ds_size() { return align_addr(sizeof(Cpu_state_modes), get_page_size_log2()); } - addr_t _alloc_ds(size_t &ram_quota); + addr_t _alloc_ds(); void * _alloc_table(); void _attach(addr_t phys_addr, addr_t vm_addr, size_t size); + protected: + + Ram_quota_guard &_ram_quota_guard() { return *this; } + Cap_quota_guard &_cap_quota_guard() { return *this; } + public: - Vm_session_component(Rpc_entrypoint *ds_ep, - size_t ram_quota); - ~Vm_session_component(); + using Ram_quota_guard::upgrade; + using Cap_quota_guard::upgrade; + using Rpc_object::cap; - using Rpc_object::cap; + Vm_session_component(Rpc_entrypoint &, Resources, Label const &, + Diag, Ram_allocator &ram, Region_map &); + ~Vm_session_component(); /************************** ** Vm session interface ** **************************/ - Dataspace_capability cpu_state(void) { return _ds_cap; } - void exception_handler(Signal_context_capability handler); - void run(void); - void pause(void); + Dataspace_capability _cpu_state(Vcpu_id) { return _ds_cap; } + void _exception_handler(Signal_context_capability, Vcpu_id); + void _run(Vcpu_id); + void _pause(Vcpu_id); void attach(Dataspace_capability ds_cap, addr_t vm_addr); void attach_pic(addr_t vm_addr); void detach(addr_t vm_addr, size_t size); + void _create_vcpu(Thread_capability) {} }; #endif /* _CORE__SPEC__ARM_V7__VIRTUALIZATION__VM_SESSION_COMPONENT_H_ */ diff --git a/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc index 0ce25f3f4..a2125e665 100644 --- a/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc @@ -18,26 +18,24 @@ using namespace Genode; -addr_t Vm_session_component::_alloc_ds(size_t &ram_quota) +addr_t Vm_session_component::_alloc_ds() { addr_t addr; - if (_ds_size() > ram_quota || - platform().ram_alloc().alloc_aligned(_ds_size(), (void**)&addr, + if (platform().ram_alloc().alloc_aligned(_ds_size(), (void**)&addr, get_page_size_log2()).error()) throw Insufficient_ram_quota(); - ram_quota -= _ds_size(); return addr; } -void Vm_session_component::run(void) +void Vm_session_component::_run(Vcpu_id) { if (Kernel_object::_cap.valid()) Kernel::run_vm(kernel_object()); } -void Vm_session_component::pause(void) +void Vm_session_component::_pause(Vcpu_id) { if (Kernel_object::_cap.valid()) Kernel::pause_vm(kernel_object()); diff --git a/repos/base-hw/src/core/spec/arndale/platform_services.cc b/repos/base-hw/src/core/spec/arndale/platform_services.cc index b34ad48bf..8750ab95b 100644 --- a/repos/base-hw/src/core/spec/arndale/platform_services.cc +++ b/repos/base-hw/src/core/spec/arndale/platform_services.cc @@ -18,6 +18,7 @@ /* core includes */ #include #include +#include #include #include #include @@ -38,6 +39,7 @@ void Genode::platform_add_local_services(Rpc_entrypoint &ep, Hw::Mm::hypervisor_exception_vector().base, 1, Hw::PAGE_FLAGS_KERN_TEXT); - static Vm_root vm_root(ep, sh); + static Vm_root vm_root(ep, sh, core_env().ram_allocator(), + core_env().local_rm()); static Core_service vm_service(services, vm_root); } diff --git a/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc b/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc index 19e0ddf98..6d6243e46 100644 --- a/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc +++ b/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc @@ -18,6 +18,7 @@ /* Core includes */ #include #include +#include #include #include #include @@ -35,6 +36,7 @@ void Genode::platform_add_local_services(Rpc_entrypoint &ep, Platform::core_phys_addr((addr_t)&monitor_mode_exception_vector); map_local(phys_base, Hw::Mm::system_exception_vector().base, 1, Hw::PAGE_FLAGS_KERN_TEXT); - static Vm_root vm_root(ep, sliced_heap); + static Vm_root vm_root(ep, sliced_heap, core_env().ram_allocator(), + core_env().local_rm()); static Core_service vm_service(local_services, vm_root); } diff --git a/repos/base-hw/src/core/spec/x86_64/muen/vm_state.h b/repos/base-hw/src/core/spec/x86_64/muen/cpu/vm_state.h similarity index 100% rename from repos/base-hw/src/core/spec/x86_64/muen/vm_state.h rename to repos/base-hw/src/core/spec/x86_64/muen/cpu/vm_state.h diff --git a/repos/base-hw/src/core/spec/x86_64/muen/platform_services.cc b/repos/base-hw/src/core/spec/x86_64/muen/platform_services.cc index 49c54d198..aa4ccaeee 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/platform_services.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/platform_services.cc @@ -28,7 +28,8 @@ void Genode::platform_add_local_services(Rpc_entrypoint &ep, Sliced_heap &sliced_heap, Registry &services) { - static Vm_root vm_root(ep, sliced_heap); + static Vm_root vm_root(ep, sliced_heap, core_env().ram_allocator(), + core_env().local_rm()); static Core_service vm_ls(services, vm_root); static Io_port_root io_port_root(*core_env().pd_session(), diff --git a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h index 938046c61..937ec57aa 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h +++ b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h @@ -30,8 +30,11 @@ namespace Genode { } class Genode::Vm_session_component -: public Genode::Rpc_object, - private Kernel_object +: + private Ram_quota_guard, + private Cap_quota_guard, + public Rpc_object, + private Kernel_object { private: @@ -39,32 +42,40 @@ class Genode::Vm_session_component public: - Vm_session_component(Rpc_entrypoint*, size_t) : _state() { } + Vm_session_component(Rpc_entrypoint &, Resources resources, + Label const &, Diag, Ram_allocator &, Region_map &) + : + Ram_quota_guard(resources.ram_quota), + Cap_quota_guard(resources.cap_quota), + _state() + { } + ~Vm_session_component() { } - using Genode::Rpc_object::cap; - + using Ram_quota_guard::upgrade; + using Cap_quota_guard::upgrade; + using Genode::Rpc_object::cap; /************************** ** Vm session interface ** **************************/ - Dataspace_capability cpu_state(void) { return Dataspace_capability(); } + Dataspace_capability _cpu_state(Vcpu_id) { return Dataspace_capability(); } - void exception_handler(Signal_context_capability handler) + void _exception_handler(Signal_context_capability handler, Vcpu_id) { if (!create(&_state, Capability_space::capid(handler), nullptr)) warning("Cannot instantiate vm kernel object, " "invalid signal context?"); } - void run(void) + void _run(Vcpu_id) { if (Kernel_object::_cap.valid()) Kernel::run_vm(kernel_object()); } - void pause(void) + void _pause(Vcpu_id) { if (Kernel_object::_cap.valid()) Kernel::pause_vm(kernel_object()); @@ -73,6 +84,7 @@ class Genode::Vm_session_component void attach(Dataspace_capability, addr_t) {} void attach_pic(addr_t) {} void detach(addr_t, size_t) {} + void _create_vcpu(Thread_capability) {} }; #endif /* _CORE__SPEC__X86_64__MUEN__VM_SESSION_COMPONENT_H_ */ diff --git a/repos/base-hw/include/spec/arndale/vm_state.h b/repos/base/include/spec/arndale/cpu/vm_state.h similarity index 100% rename from repos/base-hw/include/spec/arndale/vm_state.h rename to repos/base/include/spec/arndale/cpu/vm_state.h diff --git a/repos/base/include/vm_session/client.h b/repos/base/include/vm_session/client.h index e84906038..afa491151 100644 --- a/repos/base/include/vm_session/client.h +++ b/repos/base/include/vm_session/client.h @@ -16,9 +16,10 @@ /* Genode includes */ #include +#include #include -namespace Genode { struct Vm_session_client; } +namespace Genode { struct Vm_session_client; class Allocator; class Vm_state; } /** * Client-side VM session interface @@ -36,14 +37,10 @@ struct Genode::Vm_session_client : Rpc_client ** Vm_session interface ** **************************/ - Dataspace_capability cpu_state() { - return call(); } + Dataspace_capability cpu_state(Vcpu_id); - void exception_handler(Signal_context_capability handler) { - call(handler); } - - void run() { call(); } - void pause() { call(); } + void run(Vcpu_id); + void pause(Vcpu_id); void attach(Dataspace_capability ds,addr_t vm_addr) { call(ds, vm_addr); } @@ -53,6 +50,8 @@ struct Genode::Vm_session_client : Rpc_client void attach_pic(addr_t vm_addr) { call(vm_addr); } + + Vcpu_id create_vcpu(Allocator &, Env &, Vm_handler_base &); }; #endif /* _INCLUDE__VM_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/vm_session/connection.h b/repos/base/include/vm_session/connection.h index 31fa9b56b..2cb26375f 100644 --- a/repos/base/include/vm_session/connection.h +++ b/repos/base/include/vm_session/connection.h @@ -14,6 +14,7 @@ #ifndef _INCLUDE__VM_SESSION__CONNECTION_H_ #define _INCLUDE__VM_SESSION__CONNECTION_H_ +#include #include #include #include @@ -65,6 +66,19 @@ struct Genode::Vm_connection : Connection, Vm_session_client Connection(_session(*env_deprecated()->parent(), label, priority, affinity)), Vm_session_client(cap()) { } + + template + auto with_upgrade(FUNC func) -> decltype(func()) + { + return Genode::retry( + [&] () { + return Genode::retry( + [&] () { return func(); }, + [&] () { this->upgrade_caps(2); }); + }, + [&] () { this->upgrade_ram(4096); } + ); + } }; #endif /* _INCLUDE__VM_SESSION__CONNECTION_H_ */ diff --git a/repos/base/include/vm_session/handler.h b/repos/base/include/vm_session/handler.h new file mode 100644 index 000000000..ca7c4aed6 --- /dev/null +++ b/repos/base/include/vm_session/handler.h @@ -0,0 +1,103 @@ +/* + * \brief Client-side VM session exception handler + * \author Alexander Boettcher + * \date 2018-09-29 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _INCLUDE__VM_SESSION__HANDLER_H_ +#define _INCLUDE__VM_SESSION__HANDLER_H_ + +#include + +namespace Genode { + class Vm_state; + class Vm_handler_base; + template class Vm_handler; +} + +class Genode::Vm_handler_base : public Signal_dispatcher_base +{ + friend class Vm_session_client; + + protected: + + Rpc_entrypoint &_rpc_ep; + Signal_context_capability _cap {}; + Genode::Semaphore _done { 0 }; + + public: + + virtual bool config_vm_event(Genode::Vm_state &, unsigned) = 0; + + Vm_handler_base(Rpc_entrypoint &rpc) + : _rpc_ep(rpc) { } +}; + +template +class Genode::Vm_handler : public Vm_handler_base +{ + private: + + EP &_ep; + T &_obj; + void (T::*_member) (); + void (T::*_config) (Genode::Vm_state &, unsigned const); + + /* + * Noncopyable + */ + Vm_handler(Vm_handler const &); + Vm_handler &operator = (Vm_handler const &); + + public: + + /** + * Constructor + * + * \param obj,member object and method to call when + * the vm exception occurs + */ + Vm_handler(EP &ep, T &obj, void (T::*member)(), + void (T::*config)(Genode::Vm_state&, unsigned) = nullptr) + : + Vm_handler_base(ep.rpc_ep()), + _ep(ep), + _obj(obj), + _member(member), + _config(config) + { + _cap = ep.manage(*this); + } + + ~Vm_handler() { _ep.dissolve(*this); } + + /** + * Interface of Signal_dispatcher_base + */ + void dispatch(unsigned) override + { + (_obj.*_member)(); + _done.up(); + } + + bool config_vm_event(Genode::Vm_state &state, + unsigned const vm_event) override + { + if (!_config) + return false; + + (_obj.*_config)(state, vm_event); + return true; + } + + operator Capability() const { return _cap; } +}; + +#endif /* _INCLUDE__VM_SESSION__HANDLER_H_ */ diff --git a/repos/base/include/vm_session/vm_session.h b/repos/base/include/vm_session/vm_session.h index c45224480..c8df5101d 100644 --- a/repos/base/include/vm_session/vm_session.h +++ b/repos/base/include/vm_session/vm_session.h @@ -26,6 +26,8 @@ struct Genode::Vm_session : Session { static const char *service_name() { return "VM"; } + struct Vcpu_id { unsigned id; }; + enum { CAP_QUOTA = 3 }; class Invalid_dataspace : Exception { }; @@ -35,26 +37,6 @@ struct Genode::Vm_session : Session */ virtual ~Vm_session() { } - /** - * Get dataspace of the CPU state of the VM - */ - virtual Dataspace_capability cpu_state(void) = 0; - - /** - * Register signal handler for exceptions of the Vm - */ - virtual void exception_handler(Signal_context_capability handler) = 0; - - /** - * (Re-)Start execution of the VM - */ - virtual void run(void) {} - - /** - * Stop execution of the VM - */ - virtual void pause(void) {} - /** * Attach dataspace to the guest-physical memory address space * @@ -82,24 +64,27 @@ struct Genode::Vm_session : Session */ virtual void attach_pic(addr_t vm_addr) = 0; - /********************* ** RPC declaration ** *********************/ - GENODE_RPC(Rpc_cpu_state, Dataspace_capability, cpu_state); - GENODE_RPC(Rpc_exception_handler, void, exception_handler, - Signal_context_capability); - GENODE_RPC(Rpc_run, void, run); - GENODE_RPC(Rpc_pause, void, pause); + GENODE_RPC(Rpc_cpu_state, Dataspace_capability, _cpu_state, Vcpu_id); + GENODE_RPC(Rpc_exception_handler, void, _exception_handler, + Signal_context_capability, Vcpu_id); + GENODE_RPC(Rpc_run, void, _run, Vcpu_id); + GENODE_RPC(Rpc_pause, void, _pause, Vcpu_id); GENODE_RPC_THROW(Rpc_attach, void, attach, GENODE_TYPE_LIST(Invalid_dataspace), Dataspace_capability, addr_t); GENODE_RPC(Rpc_detach, void, detach, addr_t, size_t); GENODE_RPC(Rpc_attach_pic, void, attach_pic, addr_t); + GENODE_RPC_THROW(Rpc_create_vcpu, void, _create_vcpu, + GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), + Thread_capability); + GENODE_RPC_INTERFACE(Rpc_cpu_state, Rpc_exception_handler, Rpc_run, Rpc_pause, Rpc_attach, Rpc_detach, - Rpc_attach_pic); + Rpc_attach_pic, Rpc_create_vcpu); }; #endif /* _INCLUDE__VM_SESSION__VM_SESSION_H_ */ diff --git a/repos/base/lib/mk/base-common.inc b/repos/base/lib/mk/base-common.inc index ba2e87be2..637f31542 100644 --- a/repos/base/lib/mk/base-common.inc +++ b/repos/base/lib/mk/base-common.inc @@ -30,6 +30,7 @@ SRC_CC += stack_allocator.cc SRC_CC += trace.cc SRC_CC += root_proxy.cc SRC_CC += env_session_id_space.cc +SRC_CC += vm_session.cc INC_DIR += $(REP_DIR)/src/include $(BASE_DIR)/src/include diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 6117c6056..ca11a0c1a 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -171,6 +171,10 @@ _ZN6Genode17Rm_session_client6createEm T _ZN6Genode17Rm_session_client7destroyENS_10CapabilityINS_10Region_mapEEE T _ZN6Genode17Rm_session_clientC1ENS_10CapabilityINS_10Rm_sessionEEE T _ZN6Genode17Rm_session_clientC2ENS_10CapabilityINS_10Rm_sessionEEE T +_ZN6Genode17Vm_session_client11create_vcpuERNS_9AllocatorERNS_3EnvERNS_15Vm_handler_baseE T +_ZN6Genode17Vm_session_client3runENS_10Vm_session7Vcpu_idE T +_ZN6Genode17Vm_session_client5pauseENS_10Vm_session7Vcpu_idE T +_ZN6Genode17Vm_session_client9cpu_stateENS_10Vm_session7Vcpu_idE T _ZN6Genode18Allocator_avl_base10_add_blockEPNS0_5BlockEmmb T _ZN6Genode18Allocator_avl_base10alloc_addrEmm T _ZN6Genode18Allocator_avl_base12remove_rangeEmm T diff --git a/repos/base/src/core/include/vm_root.h b/repos/base/src/core/include/vm_root.h index 77721fd72..8125f7143 100644 --- a/repos/base/src/core/include/vm_root.h +++ b/repos/base/src/core/include/vm_root.h @@ -25,12 +25,27 @@ namespace Genode { class Vm_root; } class Genode::Vm_root : public Root_component { + private: + + Ram_allocator &_ram_allocator; + Region_map &_local_rm; + protected: Vm_session_component *_create_session(const char *args) { - size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0); - return new (md_alloc()) Vm_session_component(ep(), ram_quota); + return new (md_alloc()) + Vm_session_component(*ep(), + session_resources_from_args(args), + session_label_from_args(args), + session_diag_from_args(args), + _ram_allocator, _local_rm); + } + + void _upgrade_session(Vm_session_component *vm, const char *args) + { + vm->upgrade(ram_quota_from_args(args)); + vm->upgrade(cap_quota_from_args(args)); } public: @@ -41,9 +56,14 @@ class Genode::Vm_root : public Root_component * \param session_ep entrypoint managing vm_session components * \param md_alloc meta-data allocator to be used by root component */ - Vm_root(Rpc_entrypoint &session_ep, - Allocator &md_alloc) - : Root_component(&session_ep, &md_alloc) { } + Vm_root(Rpc_entrypoint &session_ep, + Allocator &md_alloc, + Ram_allocator &ram_alloc, + Region_map &local_rm) + : Root_component(&session_ep, &md_alloc), + _ram_allocator(ram_alloc), + _local_rm(local_rm) + { } }; #endif /* _CORE__INCLUDE__VM_ROOT_H_ */ diff --git a/repos/base/src/lib/base/vm_session.cc b/repos/base/src/lib/base/vm_session.cc new file mode 100644 index 000000000..ccd3c360a --- /dev/null +++ b/repos/base/src/lib/base/vm_session.cc @@ -0,0 +1,41 @@ +/* + * \brief Client-side VM session interface + * \author Alexander Boettcher + * \date 2018-08-27 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +using namespace Genode; + +Vm_session::Vcpu_id +Vm_session_client::create_vcpu(Allocator &, Env &, Vm_handler_base &handler) +{ + Vcpu_id vcpu_id { 0 }; + + call(Thread_capability()); + call(handler._cap, vcpu_id); + return vcpu_id; +} + +void Vm_session_client::run(Vcpu_id const vcpu_id) +{ + call(vcpu_id); +} + +void Vm_session_client::pause(Vcpu_id const vcpu_id) +{ + call(vcpu_id); +} + +Dataspace_capability Vm_session_client::cpu_state(Vcpu_id const vcpu_id) +{ + return call(vcpu_id); +} diff --git a/repos/os/src/server/tz_vmm/include/mmu.h b/repos/os/src/server/tz_vmm/include/mmu.h index d3717594c..f55103308 100644 --- a/repos/os/src/server/tz_vmm/include/mmu.h +++ b/repos/os/src/server/tz_vmm/include/mmu.h @@ -14,8 +14,10 @@ #ifndef _SRC__SERVER__VMM__INCLUDE__MMU_H_ #define _SRC__SERVER__VMM__INCLUDE__MMU_H_ +/* base includes */ +#include + /* local includes */ -#include #include class Mmu diff --git a/repos/os/src/server/tz_vmm/include/vm_base.h b/repos/os/src/server/tz_vmm/include/vm_base.h index a0f1f4ef0..7169f78dc 100644 --- a/repos/os/src/server/tz_vmm/include/vm_base.h +++ b/repos/os/src/server/tz_vmm/include/vm_base.h @@ -20,9 +20,9 @@ #include #include #include +#include /* local includes */ -#include #include namespace Genode @@ -70,8 +70,8 @@ class Genode::Vm_base : Noncopyable, Interface Board_revision const _board; Ram const _ram; Vm_connection _vm { _env }; - Vm_state &_state { *(Vm_state*)_env.rm() - .attach(_vm.cpu_state()) }; + Vm_session::Vcpu_id _vcpu_id; + Vm_state &_state { *(Vm_state*)_env.rm().attach(_vm.cpu_state(_vcpu_id)) }; void _load_kernel(); @@ -90,13 +90,12 @@ class Genode::Vm_base : Noncopyable, Interface size_t ram_size, off_t kernel_off, Machine_type machine, - Board_revision board); + Board_revision board, + Allocator &alloc, + Vm_handler_base &handler); - void exception_handler(Signal_context_capability handler) { - _vm.exception_handler(handler); } - - void run() { _vm.run(); } - void pause() { _vm.pause(); } + void run() { _vm.run(_vcpu_id); } + void pause() { _vm.pause(_vcpu_id); } void start(); void dump(); diff --git a/repos/os/src/server/tz_vmm/spec/imx53/main.cc b/repos/os/src/server/tz_vmm/spec/imx53/main.cc index 8c3887423..e6a210cbd 100644 --- a/repos/os/src/server/tz_vmm/spec/imx53/main.cc +++ b/repos/os/src/server/tz_vmm/spec/imx53/main.cc @@ -44,7 +44,7 @@ class Main Vm::Kernel_name const _kernel_name { "linux" }; Vm::Command_line const _cmd_line { "console=ttymxc0,115200" }; Attached_rom_dataspace _config { _env, "config" }; - Signal_handler
_exception_handler { _env.ep(), *this, + Vm_handler
_exception_handler { _env.ep(), *this, &Main::_handle_exception }; Heap _heap { &_env.ram(), &_env.rm() }; @@ -52,7 +52,8 @@ class Main Trustzone::NONSECURE_RAM_BASE, Trustzone::NONSECURE_RAM_SIZE, KERNEL_OFFSET, Machine_type(MACHINE_QSB), - Board_revision(BOARD_QSB) }; + Board_revision(BOARD_QSB), + _heap, _exception_handler }; M4if _m4if { _env, Imx53::M4IF_BASE, Imx53::M4IF_SIZE }; Serial_driver _serial { _env.ram() }; Block_driver _block { _env.ep(), _config.xml(), _heap, _vm }; @@ -106,7 +107,6 @@ class Main log("Start virtual machine ..."); _m4if.set_region0(Trustzone::SECURE_RAM_BASE, Trustzone::SECURE_RAM_SIZE); - _vm.exception_handler(_exception_handler); _vm.start(); _vm.run(); } diff --git a/repos/os/src/server/tz_vmm/spec/imx53_qsb/vm.h b/repos/os/src/server/tz_vmm/spec/imx53_qsb/vm.h index 247bbcf32..82437971d 100644 --- a/repos/os/src/server/tz_vmm/spec/imx53_qsb/vm.h +++ b/repos/os/src/server/tz_vmm/spec/imx53_qsb/vm.h @@ -46,8 +46,12 @@ class Genode::Vm : public Vm_base size_t ram_sz, off_t kernel_off, Machine_type mach, - Board_revision board) - : Vm_base(env, kernel, cmdl, ram, ram_sz, kernel_off, mach, board) { } + Board_revision board, + Allocator &alloc, + Vm_handler_base &handler) + : Vm_base(env, kernel, cmdl, ram, ram_sz, kernel_off, mach, board, + alloc, handler) + { } void on_vmm_exit() { } void on_vmm_entry() { }; diff --git a/repos/os/src/server/tz_vmm/spec/usb_armory/vm.h b/repos/os/src/server/tz_vmm/spec/usb_armory/vm.h index e904e76e4..7795272d1 100644 --- a/repos/os/src/server/tz_vmm/spec/usb_armory/vm.h +++ b/repos/os/src/server/tz_vmm/spec/usb_armory/vm.h @@ -50,8 +50,12 @@ class Genode::Vm : public Vm_base size_t ram_sz, off_t kernel_off, Machine_type mach, - Board_revision board) - : Vm_base(env, kernel, cmdl, ram, ram_sz, kernel_off, mach, board) { } + Board_revision board, + Allocator &alloc, + Vm_handler_base &handler) + : Vm_base(env, kernel, cmdl, ram, ram_sz, kernel_off, mach, board, + alloc, handler) + { } void on_vmm_exit() { _led.write(true); } void on_vmm_entry(); diff --git a/repos/os/src/server/tz_vmm/vm_base.cc b/repos/os/src/server/tz_vmm/vm_base.cc index a489a3b16..00e05bc97 100644 --- a/repos/os/src/server/tz_vmm/vm_base.cc +++ b/repos/os/src/server/tz_vmm/vm_base.cc @@ -38,10 +38,13 @@ Vm_base::Vm_base(Env &env, size_t ram_size, off_t kernel_off, Machine_type machine, - Board_revision board) + Board_revision board, + Allocator &alloc, + Vm_handler_base &handler) : _env(env), _kernel(kernel), _cmdline(cmdline), _kernel_off(kernel_off), - _machine(machine), _board(board), _ram(env, ram_base, ram_size) + _machine(machine), _board(board), _ram(env, ram_base, ram_size), + _vcpu_id(_vm.create_vcpu(alloc, env, handler)) { _state.irq_injection = 0; } diff --git a/repos/os/src/server/vmm/main.cc b/repos/os/src/server/vmm/main.cc index c17b643a8..24922741f 100644 --- a/repos/os/src/server/vmm/main.cc +++ b/repos/os/src/server/vmm/main.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,7 @@ #include #include -#include +#include #include @@ -119,11 +120,13 @@ class Vm { DTB_OFFSET = 64 * 1024 * 1024, }; - Genode::Vm_connection _vm_con; + Genode::Vm_connection _vm; Genode::Attached_rom_dataspace _kernel_rom; Genode::Attached_rom_dataspace _dtb_rom; Genode::Attached_ram_dataspace _vm_ram; Ram _ram; + Genode::Heap _heap; + Genode::Vm_session::Vcpu_id _vcpu_id; State & _state; bool _active = true; @@ -170,20 +173,21 @@ class Vm { Vm(const char *kernel, const char *dtb, Genode::size_t const ram_size, - Genode::Signal_context_capability sig_cap, Genode::Env & env) - : _vm_con(env), + Genode::Vm_handler_base &handler, Genode::Env & env) + : _vm(env), _kernel_rom(env, kernel), _dtb_rom(env, dtb), _vm_ram(env.ram(), env.rm(), ram_size, Genode::UNCACHED), _ram(RAM_ADDRESS, ram_size, (Genode::addr_t)_vm_ram.local_addr()), - _state(*((State*)env.rm().attach(_vm_con.cpu_state()))) + _heap(env.ram(), env.rm()), + _vcpu_id(_vm.create_vcpu(_heap, env, handler)), + _state(*((State*)env.rm().attach(_vm.cpu_state(_vcpu_id)))) { Genode::log("ram is at ", Genode::Hex(Genode::Dataspace_client(_vm_ram.cap()).phys_addr())); - _vm_con.exception_handler(sig_cap); - _vm_con.attach(_vm_ram.cap(), RAM_ADDRESS); - _vm_con.attach_pic(0x2C002000); + _vm.attach(_vm_ram.cap(), RAM_ADDRESS); + _vm.attach_pic(0x2C002000); } void start() @@ -209,8 +213,8 @@ class Vm { Genode::log("ready to run"); } - void run() { if (_active) _vm_con.run(); } - void pause() { _vm_con.pause(); } + void run() { if (_active) _vm.run(_vcpu_id); } + void pause() { _vm.pause(_vcpu_id); } void wait_for_interrupt() { _active = false; } void interrupt() { _active = true; } bool active() { return _active; } @@ -265,9 +269,9 @@ class Vmm private: template - struct Signal_handler : Genode::Signal_handler> + struct Signal_handler : Genode::Vm_handler> { - using Base = Genode::Signal_handler>; + using Base = Genode::Vm_handler>; Vmm & vmm; T & obj;