genode/repos/ports/include/vmm/vcpu_thread.h
Norman Feske 88b358c5ef Unification of native_capability.h
This patch establishes the sole use of generic headers across all
kernels. The common 'native_capability.h' is based on the version of
base-sel4. All traditional L4 kernels and Linux use the same
implementation of the capability-lifetime management. On base-hw, NOVA,
Fiasco.OC, and seL4, custom implementations (based on their original
mechanisms) are used, with the potential to unify them further in the
future.

This change achieves binary compatibility of dynamically linked programs
across all kernels.

Furthermore, the patch introduces a Native_capability::print method,
which allows the easy output of the kernel-specific capability
representation using the base/log.h API.

Issue #1993
2016-07-11 13:07:37 +02:00

162 lines
4.1 KiB
C++

/*
* \brief Utilities for implementing VMMs on Genode/NOVA
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__VMM__VCPU_THREAD_H_
#define _INCLUDE__VMM__VCPU_THREAD_H_
/* Genode includes */
#include <base/thread.h>
#include <cap_session/connection.h>
#include <cpu_session/connection.h>
#include <pd_session/connection.h>
#include <region_map/client.h>
#include <nova_native_cpu/client.h>
#include <cpu_thread/client.h>
/* NOVA includes */
#include <nova/native_thread.h>
#include <nova/cap_map.h>
namespace Vmm {
using namespace Genode;
class Vcpu_thread;
class Vcpu_other_pd;
class Vcpu_same_pd;
}
class Vmm::Vcpu_thread
{
public:
virtual Genode::addr_t exc_base() = 0;
virtual void start(Genode::addr_t) = 0;
};
class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
{
private:
Genode::Pd_connection _pd_session;
Genode::Affinity::Location _location;
Genode::Cpu_session *_cpu_session;
Genode::addr_t _exc_pt_sel;
public:
Vcpu_other_pd(Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
_pd_session("VM"), _location(location), _cpu_session(cpu_session),
_exc_pt_sel(Genode::cap_map()->insert(Nova::NUM_INITIAL_VCPU_PT_LOG2))
{ }
void start(Genode::addr_t sel_ec)
{
using namespace Genode;
Thread_capability vcpu_vm =
_cpu_session->create_thread(_pd_session, "vCPU",
_location, Cpu_session::Weight());
/* tell parent that this will be a vCPU */
Thread_state state;
state.sel_exc_base = Native_thread::INVALID_INDEX;
state.vcpu = true;
Cpu_thread_client cpu_thread(vcpu_vm);
cpu_thread.state(state);
/* obtain interface to NOVA-specific CPU session operations */
Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
/* create new pager object and assign it to the new thread */
Native_capability pager_cap = native_cpu.pager_cap(vcpu_vm);
/*
* Delegate parent the vCPU exception portals required during PD
* creation.
*/
delegate_vcpu_portals(pager_cap, exc_base());
/* start vCPU in separate PD */
cpu_thread.start(0, 0);
/*
* Request native EC thread cap and put it next to the
* SM cap - see Vcpu_dispatcher->sel_sm_ec description
*/
request_native_ec_cap(pager_cap, sel_ec);
}
Genode::addr_t exc_base() { return _exc_pt_sel; }
};
class Vmm::Vcpu_same_pd : public Vmm::Vcpu_thread, Genode::Thread
{
enum { WEIGHT = Genode::Cpu_session::Weight::DEFAULT_WEIGHT };
public:
Vcpu_same_pd(size_t stack_size, Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
Thread(WEIGHT, "vCPU", stack_size, Type::NORMAL, cpu_session, location)
{
/* release pre-allocated selectors of Thread */
Genode::cap_map()->remove(native_thread().exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2);
/* allocate correct number of selectors */
this->native_thread().exc_pt_sel = cap_map()->insert(Nova::NUM_INITIAL_VCPU_PT_LOG2);
/* tell generic thread code that this becomes a vCPU */
this->native_thread().vcpu = true;
}
~Vcpu_same_pd()
{
using namespace Nova;
revoke(Nova::Obj_crd(this->native_thread().exc_pt_sel, NUM_INITIAL_VCPU_PT_LOG2));
cap_map()->remove(this->native_thread().exc_pt_sel, NUM_INITIAL_VCPU_PT_LOG2, false);
/* allocate selectors for ~Thread */
this->native_thread().exc_pt_sel = cap_map()->insert(Nova::NUM_INITIAL_PT_LOG2);
}
addr_t exc_base() { return this->native_thread().exc_pt_sel; }
void start(Genode::addr_t sel_ec)
{
this->Thread::start();
/* obtain interface to NOVA-specific CPU session operations */
Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
/*
* Request native EC thread cap and put it next to the
* SM cap - see Vcpu_dispatcher->sel_sm_ec description
*/
Native_capability pager_cap = native_cpu.pager_cap(_thread_cap);
request_native_ec_cap(pager_cap, sel_ec);
}
void entry() { }
};
#endif /* _INCLUDE__VMM__VCPU_THREAD_H_ */