diff --git a/repos/base-hw/include/kernel/interface.h b/repos/base-hw/include/kernel/interface.h index 02decc116f..b7c12a9607 100644 --- a/repos/base-hw/include/kernel/interface.h +++ b/repos/base-hw/include/kernel/interface.h @@ -42,6 +42,8 @@ namespace Kernel constexpr Call_arg call_id_timeout() { return 16; } constexpr Call_arg call_id_timeout_max_us() { return 17; } constexpr Call_arg call_id_time() { return 18; } + constexpr Call_arg call_id_run_vm() { return 19; } + constexpr Call_arg call_id_pause_vm() { return 20; } /***************************************************************** @@ -369,6 +371,28 @@ namespace Kernel { call(call_id_delete_cap(), cap); } + + + /** + * Execute a virtual-machine (again) + * + * \param vm pointer to vm kernel object + */ + inline void run_vm(capid_t const cap) + { + call(call_id_run_vm(), cap); + } + + + /** + * Stop execution of a virtual-machine + * + * \param vm pointer to vm kernel object + */ + inline void pause_vm(capid_t const cap) + { + call(call_id_pause_vm(), cap); + } } #endif /* _INCLUDE__KERNEL__INTERFACE_H_ */ diff --git a/repos/base-hw/src/core/kernel/core_interface.h b/repos/base-hw/src/core/kernel/core_interface.h index c069958555..b1b6f303ad 100644 --- a/repos/base-hw/src/core/kernel/core_interface.h +++ b/repos/base-hw/src/core/kernel/core_interface.h @@ -51,8 +51,6 @@ namespace Kernel constexpr Call_arg call_id_delete_signal_context() { return 112; } constexpr Call_arg call_id_delete_signal_receiver() { return 113; } constexpr Call_arg call_id_new_vm() { return 114; } - constexpr Call_arg call_id_run_vm() { return 115; } - constexpr Call_arg call_id_pause_vm() { return 116; } constexpr Call_arg call_id_delete_vm() { return 117; } constexpr Call_arg call_id_new_irq() { return 118; } constexpr Call_arg call_id_delete_irq() { return 119; } @@ -152,27 +150,6 @@ namespace Kernel } - /** - * Execute a virtual-machine (again) - * - * \param vm pointer to vm kernel object - */ - inline void run_vm(Vm & vm) - { - call(call_id_run_vm(), (Call_arg) &vm); - } - - - /** - * Stop execution of a virtual-machine - * - * \param vm pointer to vm kernel object - */ - inline void pause_vm(Vm & vm) - { - call(call_id_pause_vm(), (Call_arg) &vm); - } - /** * Acknowledge interrupt * diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index 32d403992e..944752d5e8 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -740,6 +740,8 @@ void Thread::_call() case call_id_timeout(): _call_timeout(); return; case call_id_timeout_max_us(): _call_timeout_max_us(); return; case call_id_time(): _call_time(); return; + case call_id_run_vm(): _call_run_vm(); return; + case call_id_pause_vm(): _call_pause_vm(); return; default: /* check wether this is a core thread */ if (!_core) { @@ -777,8 +779,6 @@ void Thread::_call() case call_id_delete_signal_receiver(): _call_delete(); return; case call_id_new_vm(): _call_new_vm(); return; case call_id_delete_vm(): _call_delete_vm(); return; - case call_id_run_vm(): _call_run_vm(); return; - case call_id_pause_vm(): _call_pause_vm(); return; case call_id_pause_thread(): _call_pause_thread(); return; case call_id_new_irq(): _call_new_irq(); return; case call_id_delete_irq(): _call_delete(); return; diff --git a/repos/base-hw/src/core/kernel/vm.h b/repos/base-hw/src/core/kernel/vm.h index a6de42846f..073510fe88 100644 --- a/repos/base-hw/src/core/kernel/vm.h +++ b/repos/base-hw/src/core/kernel/vm.h @@ -33,7 +33,7 @@ namespace Kernel } -class Kernel::Vm : public Cpu_job +class Kernel::Vm : private Kernel::Object, public Cpu_job { private: diff --git a/repos/base-hw/src/core/kernel/vm_thread_on.cc b/repos/base-hw/src/core/kernel/vm_thread_on.cc index 4407ea6189..34e2711d97 100644 --- a/repos/base-hw/src/core/kernel/vm_thread_on.cc +++ b/repos/base-hw/src/core/kernel/vm_thread_on.cc @@ -34,13 +34,31 @@ void Kernel::Thread::_call_delete_vm() { _call_delete(); } void Kernel::Thread::_call_run_vm() { - reinterpret_cast(user_arg_1())->run(); + Object_identity_reference * ref = pd().cap_tree().find(user_arg_1()); + Vm * vm = ref ? ref->object() : nullptr; + + if (!vm) { + Genode::raw("Invalid VM cap"); + user_arg_0(-1); + return; + } + + vm->run(); user_arg_0(0); } void Kernel::Thread::_call_pause_vm() { - reinterpret_cast(user_arg_1())->pause(); + Object_identity_reference * ref = pd().cap_tree().find(user_arg_1()); + Vm * vm = ref ? ref->object() : nullptr; + + if (!vm) { + Genode::raw("Invalid VM cap"); + user_arg_0(-1); + return; + } + + vm->pause(); user_arg_0(0); } diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc index 4d7957d0cd..67f295654a 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc @@ -24,7 +24,7 @@ Kernel::Vm::Vm(unsigned, Genode::Vm_state & state, Kernel::Signal_context & context, void * const) -: +: Kernel::Object { *this }, Cpu_job(Cpu_priority::MIN, 0), _state(state), _context(context), diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc index 9126c2bafb..e1d9c99a0b 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc @@ -112,7 +112,8 @@ Kernel::Vm::Vm(unsigned, /* FIXME: smp support */ Genode::Vm_state & state, Kernel::Signal_context & context, void * const table) -: Cpu_job(Cpu_priority::MIN, 0), +: Kernel::Object { *this }, + Cpu_job(Cpu_priority::MIN, 0), _id(alloc().alloc()), _state(state), _context(context), diff --git a/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc index 58810fcdb5..8d16e271d0 100644 --- a/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/kernel/vm.cc @@ -119,7 +119,8 @@ Vm::Vm(unsigned cpu, Genode::Vm_state & state, Kernel::Signal_context & context, void * const table) -: Cpu_job(Cpu_priority::MIN, 0), +: Kernel::Object { *this }, + Cpu_job(Cpu_priority::MIN, 0), _id(alloc().alloc()), _state(state), _context(context), diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc index 4f73871d27..43ac8c040b 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc @@ -22,7 +22,8 @@ Kernel::Vm::Vm(unsigned, Board::Vm_state & state, Kernel::Signal_context & context, void * const) -: Cpu_job(Cpu_priority::MIN, 0), +: Kernel::Object { *this }, + Cpu_job(Cpu_priority::MIN, 0), _state(state), _context(context), _table(nullptr), diff --git a/repos/base-hw/src/core/vm_session_component.cc b/repos/base-hw/src/core/vm_session_component.cc index 477d361842..d0117c065b 100644 --- a/repos/base-hw/src/core/vm_session_component.cc +++ b/repos/base-hw/src/core/vm_session_component.cc @@ -41,18 +41,10 @@ addr_t Vm_session_component::_alloc_ds() } -void Vm_session_component::_run(Vcpu_id id) -{ - if (_valid_id(id) && _vcpus[id.id].kobj.constructed()) - Kernel::run_vm(*_vcpus[id.id].kobj); -} +void Vm_session_component::_run(Vcpu_id) { } -void Vm_session_component::_pause(Vcpu_id id) -{ - if (_valid_id(id) && _vcpus[id.id].kobj.constructed()) - Kernel::pause_vm(*_vcpus[id.id].kobj); -} +void Vm_session_component::_pause(Vcpu_id) { } Capability Vm_session_component::_native_vcpu(Vcpu_id id) diff --git a/repos/base-hw/src/lib/base/vm_session.cc b/repos/base-hw/src/lib/base/vm_session.cc new file mode 100644 index 0000000000..c4a9cbfa22 --- /dev/null +++ b/repos/base-hw/src/lib/base/vm_session.cc @@ -0,0 +1,74 @@ +/* + * \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 +#include +#include +#include +#include +#include + +using namespace Genode; + +struct Vcpu; + +static Genode::Registry> vcpus; + +struct Vcpu { + Vm_session_client::Vcpu_id const id; + Capability const cap; + + Vcpu(Vm_session::Vcpu_id const id, + Capability const cap) + : id(id), cap(cap) {} + virtual ~Vcpu() {} +}; + + +Vm_session::Vcpu_id +Vm_session_client::create_vcpu(Allocator & alloc, Env &, Vm_handler_base & handler) +{ + Vcpu_id const id = + call(reinterpret_cast(&handler._rpc_ep)->cap()); + call(handler._cap, id); + Vcpu * vcpu = new (alloc) Registered (vcpus, id, call(id)); + return vcpu->id; +} + + +void Vm_session_client::run(Vcpu_id const vcpu_id) +{ + vcpus.for_each([&] (Vcpu & vcpu) { + if (vcpu.id.id != vcpu_id.id) { return; } + Kernel::run_vm(Capability_space::capid(vcpu.cap)); + }); +} + + +void Vm_session_client::pause(Vcpu_id const vcpu_id) +{ + vcpus.for_each([&] (Vcpu & vcpu) { + if (vcpu.id.id != vcpu_id.id) { return; } + Kernel::pause_vm(Capability_space::capid(vcpu.cap)); + }); +} + + +Dataspace_capability Vm_session_client::cpu_state(Vcpu_id const vcpu_id) +{ + return call(vcpu_id); +} + + +Vm_session::~Vm_session() +{ }