mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-12 21:53:28 +00:00
base-hw: do direct syscall when run/pause a VCPU
Instead of calling core to run/pause a VCPU, go directly to the kernel. Apart from the performance win, it would otherwise involve a more complex protocol, when a VCPU on another core has to be removed from the scheduler. Core's entrypoint handling those request runs on the boot-cpu only. Ref #3926
This commit is contained in:
parent
40445d7011
commit
1d826a2c48
@ -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_ */
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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<Signal_receiver>(); 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<User_irq>(); return;
|
||||
|
@ -33,7 +33,7 @@ namespace Kernel
|
||||
}
|
||||
|
||||
|
||||
class Kernel::Vm : public Cpu_job
|
||||
class Kernel::Vm : private Kernel::Object, public Cpu_job
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -34,13 +34,31 @@ void Kernel::Thread::_call_delete_vm() { _call_delete<Vm>(); }
|
||||
|
||||
void Kernel::Thread::_call_run_vm()
|
||||
{
|
||||
reinterpret_cast<Vm*>(user_arg_1())->run();
|
||||
Object_identity_reference * ref = pd().cap_tree().find(user_arg_1());
|
||||
Vm * vm = ref ? ref->object<Vm>() : 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<Vm*>(user_arg_1())->pause();
|
||||
Object_identity_reference * ref = pd().cap_tree().find(user_arg_1());
|
||||
Vm * vm = ref ? ref->object<Vm>() : nullptr;
|
||||
|
||||
if (!vm) {
|
||||
Genode::raw("Invalid VM cap");
|
||||
user_arg_0(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
vm->pause();
|
||||
user_arg_0(0);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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::Native_vcpu> Vm_session_component::_native_vcpu(Vcpu_id id)
|
||||
|
74
repos/base-hw/src/lib/base/vm_session.cc
Normal file
74
repos/base-hw/src/lib/base/vm_session.cc
Normal file
@ -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 <base/allocator.h>
|
||||
#include <base/env.h>
|
||||
#include <base/registry.h>
|
||||
#include <base/internal/capability_space.h>
|
||||
#include <kernel/interface.h>
|
||||
#include <vm_session/client.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
struct Vcpu;
|
||||
|
||||
static Genode::Registry<Genode::Registered<Vcpu>> vcpus;
|
||||
|
||||
struct Vcpu {
|
||||
Vm_session_client::Vcpu_id const id;
|
||||
Capability<Vm_session::Native_vcpu> const cap;
|
||||
|
||||
Vcpu(Vm_session::Vcpu_id const id,
|
||||
Capability<Vm_session::Native_vcpu> 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<Rpc_create_vcpu>(reinterpret_cast<Thread *>(&handler._rpc_ep)->cap());
|
||||
call<Rpc_exception_handler>(handler._cap, id);
|
||||
Vcpu * vcpu = new (alloc) Registered<Vcpu> (vcpus, id, call<Rpc_native_vcpu>(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<Rpc_cpu_state>(vcpu_id);
|
||||
}
|
||||
|
||||
|
||||
Vm_session::~Vm_session()
|
||||
{ }
|
Loading…
x
Reference in New Issue
Block a user