2013-08-20 19:24:52 +00:00
|
|
|
/*
|
|
|
|
* \brief Utilities for implementing VMMs on Genode/NOVA
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2013-08-20
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 12:23:52 +00:00
|
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
2013-08-20 19:24:52 +00:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 12:23:52 +00:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2013-08-20 19:24:52 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _INCLUDE__VMM__VCPU_DISPATCHER_H_
|
|
|
|
#define _INCLUDE__VMM__VCPU_DISPATCHER_H_
|
|
|
|
|
2016-01-19 19:24:22 +00:00
|
|
|
/* Genode includes */
|
|
|
|
#include <util/retry.h>
|
|
|
|
#include <nova_native_pd/client.h>
|
2016-06-15 13:04:54 +00:00
|
|
|
#include <nova/capability_space.h>
|
2016-01-19 19:24:22 +00:00
|
|
|
|
2013-08-20 19:24:52 +00:00
|
|
|
namespace Vmm {
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
2014-04-17 12:00:58 +00:00
|
|
|
template <class T>
|
2013-08-20 19:24:52 +00:00
|
|
|
class Vcpu_dispatcher;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Thread that handles virtualization events of a 'Vmm::Vcpu_thread'
|
|
|
|
*/
|
2014-04-17 12:00:58 +00:00
|
|
|
template <class T>
|
|
|
|
class Vmm::Vcpu_dispatcher : public T
|
2013-08-20 19:24:52 +00:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2016-05-04 10:27:17 +00:00
|
|
|
enum { WEIGHT = Genode::Cpu_session::Weight::DEFAULT_WEIGHT };
|
2015-03-27 13:05:55 +00:00
|
|
|
|
2016-11-23 16:07:49 +00:00
|
|
|
Env &_env;
|
|
|
|
Nova_native_pd_client _native_pd { _env.pd().native_pd() };
|
2013-08-20 19:24:52 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Portal entry point entered on virtualization events
|
|
|
|
*
|
|
|
|
* For each event type used as argument of the 'register_handler'
|
|
|
|
* function template, the compiler automatically generates a separate
|
|
|
|
* instance of this function. The sole purpose of this function is to
|
|
|
|
* call the 'Vcpu' member function corresponding to the event type.
|
|
|
|
*/
|
|
|
|
template <unsigned EV, typename DISPATCHER, void (DISPATCHER::*FUNC)()>
|
|
|
|
static void _portal_entry()
|
|
|
|
{
|
|
|
|
/* obtain this pointer of the event handler */
|
2016-05-04 10:27:17 +00:00
|
|
|
Genode::Thread *myself = Genode::Thread::myself();
|
2013-08-20 19:24:52 +00:00
|
|
|
DISPATCHER *vd = static_cast<DISPATCHER *>(myself);
|
|
|
|
|
2015-11-26 13:19:42 +00:00
|
|
|
vd->exit_reason = EV;
|
|
|
|
|
2013-08-20 19:24:52 +00:00
|
|
|
/* call event-specific handler function */
|
|
|
|
(vd->*FUNC)();
|
|
|
|
|
|
|
|
/* continue execution of the guest */
|
|
|
|
Nova::reply(myself->stack_top());
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2015-11-26 13:19:42 +00:00
|
|
|
unsigned int exit_reason = 0;
|
|
|
|
|
2016-11-23 16:07:49 +00:00
|
|
|
Vcpu_dispatcher(Genode::Env &env, Genode::size_t stack_size,
|
2020-05-05 12:27:29 +00:00
|
|
|
Cpu_connection *,
|
2016-09-23 08:10:01 +00:00
|
|
|
Genode::Affinity::Location location,
|
|
|
|
const char * name = "vCPU dispatcher")
|
2013-08-20 19:24:52 +00:00
|
|
|
:
|
2016-11-23 16:07:49 +00:00
|
|
|
T(WEIGHT, name, stack_size, location), _env(env)
|
2013-08-20 19:24:52 +00:00
|
|
|
{
|
|
|
|
using namespace Genode;
|
|
|
|
|
2014-04-17 12:00:58 +00:00
|
|
|
/* request creation of a 'local' EC */
|
2016-03-11 16:32:43 +00:00
|
|
|
T::native_thread().ec_sel = Native_thread::INVALID_INDEX - 1;
|
2014-04-17 12:00:58 +00:00
|
|
|
T::start();
|
2013-08-20 19:24:52 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register virtualization event handler
|
|
|
|
*/
|
|
|
|
template <unsigned EV, typename DISPATCHER, void (DISPATCHER::*FUNC)()>
|
|
|
|
bool register_handler(addr_t exc_base, Nova::Mtd mtd)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Let the compiler generate an instance of a portal entry
|
|
|
|
*/
|
|
|
|
void (*entry)() = &_portal_entry<EV, DISPATCHER, FUNC>;
|
|
|
|
|
2016-06-15 13:04:54 +00:00
|
|
|
/* create the portal at the desired selector index (EV) */
|
|
|
|
Native_capability thread_cap =
|
|
|
|
Capability_space::import(T::native_thread().ec_sel);
|
2016-01-19 19:24:22 +00:00
|
|
|
|
|
|
|
Untyped_capability handler =
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 20:03:22 +00:00
|
|
|
retry<Genode::Out_of_ram>(
|
2016-01-19 19:24:22 +00:00
|
|
|
[&] () {
|
2016-06-15 13:04:54 +00:00
|
|
|
/* manually define selector used for RPC result */
|
|
|
|
Thread::myself()->native_thread().client_rcv_sel = exc_base + EV;
|
2016-01-19 19:24:22 +00:00
|
|
|
return _native_pd.alloc_rpc_cap(thread_cap, (addr_t)entry,
|
|
|
|
mtd.value());
|
|
|
|
},
|
|
|
|
[&] () {
|
2016-06-15 13:04:54 +00:00
|
|
|
Thread::myself()->native_thread().reset_client_rcv_sel();
|
2016-11-23 16:07:49 +00:00
|
|
|
_env.parent().upgrade(Parent::Env::pd(), "ram_quota=16K");
|
2016-01-19 19:24:22 +00:00
|
|
|
});
|
2013-08-20 19:24:52 +00:00
|
|
|
|
2016-06-15 13:04:54 +00:00
|
|
|
/* revert selector allocation to automatic mode of operation */
|
|
|
|
Thread::myself()->native_thread().reset_client_rcv_sel();
|
|
|
|
|
|
|
|
return handler.valid() && (exc_base + EV == (addr_t)handler.local_name());
|
2013-08-20 19:24:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-05-04 10:27:17 +00:00
|
|
|
* Unused member of the 'Thread' interface
|
2013-08-20 19:24:52 +00:00
|
|
|
*
|
|
|
|
* Similarly to how 'Rpc_entrypoints' are handled, a 'Vcpu_dispatcher'
|
|
|
|
* comes with a custom initialization procedure, which does not call
|
|
|
|
* the thread's normal entry function. Instead, the thread's EC gets
|
|
|
|
* associated with several portals, each for handling a specific
|
|
|
|
* virtualization event.
|
|
|
|
*/
|
2019-02-14 21:39:08 +00:00
|
|
|
void entry() override { }
|
2013-08-20 19:24:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* _INCLUDE__VMM__VCPU_DISPATCHER_H_ */
|