nova: use 'Native_cpu' component for thread initialization

Pass the thread type and exception base to core with a 'Native_cpu'
component instead of enhancing the 'Thread_state' class.

Fixes #2298
This commit is contained in:
Christian Prochaska 2017-02-27 19:54:03 +01:00 committed by Christian Helmuth
parent fbdfbc2476
commit ca2871e2e4
18 changed files with 413 additions and 103 deletions

View File

@ -1,33 +0,0 @@
/*
* \brief Thread state
* \author Alexander Boettcher
* \date 2012-08-09
*
* This file contains the NOVA specific thread state.
*/
/*
* Copyright (C) 2012-2017 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__BASE__THREAD_STATE_H_
#define _INCLUDE__BASE__THREAD_STATE_H_
#include <base/thread_state_base.h>
namespace Genode { struct Thread_state; }
struct Genode::Thread_state : Thread_state_base
{
bool vcpu;
addr_t sel_exc_base;
bool global_thread;
Thread_state() : vcpu(false), sel_exc_base(~0UL), global_thread(true) { }
};
#endif /* _INCLUDE__BASE__THREAD_STATE_H_ */

View File

@ -0,0 +1,33 @@
/*
* \brief Client-side NOVA-specific CPU session interface
* \author Norman Feske
* \date 2016-04-21
*/
/*
* Copyright (C) 2016-2017 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__NOVA_NATIVE_CPU__CLIENT_H_
#define _INCLUDE__NOVA_NATIVE_CPU__CLIENT_H_
#include <nova_native_cpu/nova_native_cpu.h>
#include <base/rpc_client.h>
namespace Genode { struct Nova_native_cpu_client; }
struct Genode::Nova_native_cpu_client : Rpc_client<Nova_native_cpu>
{
explicit Nova_native_cpu_client(Capability<Native_cpu> cap)
: Rpc_client<Nova_native_cpu>(static_cap_cast<Nova_native_cpu>(cap)) { }
void thread_type(Thread_capability thread_cap, Thread_type thread_type,
Exception_base exception_base) {
call<Rpc_thread_type>(thread_cap, thread_type, exception_base); }
};
#endif /* _INCLUDE__NOVA_NATIVE_CPU__CLIENT_H_ */

View File

@ -0,0 +1,45 @@
/*
* \brief NOVA-specific part of the CPU session interface
* \author Norman Feske
* \date 2016-04-21
*/
/*
* Copyright (C) 2016-2017 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__NOVA_NATIVE_CPU__FOC_NATIVE_CPU_H_
#define _INCLUDE__NOVA_NATIVE_CPU__FOC_NATIVE_CPU_H_
#include <base/rpc.h>
#include <cpu_session/cpu_session.h>
namespace Genode { struct Nova_native_cpu; }
struct Genode::Nova_native_cpu : Cpu_session::Native_cpu
{
enum Thread_type { GLOBAL, LOCAL, VCPU };
/*
* Exception base of thread in caller protection domain - not in core!
*/
struct Exception_base { addr_t exception_base; };
virtual void thread_type(Thread_capability, Thread_type, Exception_base) = 0;
/*********************
** RPC declaration **
*********************/
GENODE_RPC(Rpc_thread_type, void, thread_type, Thread_capability,
Thread_type, Exception_base );
GENODE_RPC_INTERFACE(Rpc_thread_type);
};
#endif /* _INCLUDE__NOVA_NATIVE_CPU__FOC_NATIVE_CPU_H_ */

View File

@ -23,6 +23,7 @@ SRC_CC += stack_area.cc \
main.cc \
pager.cc \
pd_session_component.cc \
native_cpu_component.cc \
native_pd_component.cc \
pd_upgrade_ram_quota.cc \
pd_assign_pci.cc \

View File

@ -0,0 +1,44 @@
/*
* \brief Kernel-specific part of the CPU-session interface
* \author Norman Feske
* \date 2016-04-21
*/
/*
* Copyright (C) 2016-2017 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 _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_
#define _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_
/* Genode includes */
#include <base/rpc_server.h>
#include <nova_native_cpu/nova_native_cpu.h>
namespace Genode {
class Cpu_session_component;
class Native_cpu_component;
}
class Genode::Native_cpu_component : public Rpc_object<Nova_native_cpu,
Native_cpu_component>
{
private:
Cpu_session_component &_cpu_session;
Rpc_entrypoint &_thread_ep;
public:
Native_cpu_component(Cpu_session_component &, char const *);
~Native_cpu_component();
void thread_type(Thread_capability, Thread_type, Exception_base) override;
};
#endif /* _CORE__INCLUDE__NATIVE_CPU_COMPONENT_H_ */

View File

@ -19,6 +19,7 @@
#include <thread/capability.h>
#include <base/thread_state.h>
#include <base/thread.h>
#include <nova_native_cpu/nova_native_cpu.h>
/* base-internal includes */
#include <base/internal/stack.h>
@ -145,6 +146,12 @@ namespace Genode {
** Accessor functions **
************************/
/**
* Set thread type and exception portal base
*/
void thread_type(Nova_native_cpu::Thread_type thread_type,
Nova_native_cpu::Exception_base exception_base);
/**
* Set pager
*/

View File

@ -0,0 +1,49 @@
/*
* \brief Core implementation of the CPU session interface extension
* \author Norman Feske
* \date 2016-04-21
*/
/*
* Copyright (C) 2016-2017 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.
*/
/* Genode includes */
#include <base/stdint.h>
/* core-local includes */
#include <native_cpu_component.h>
#include <cpu_session_component.h>
using namespace Genode;
void Native_cpu_component::thread_type(Thread_capability thread_cap,
Thread_type thread_type,
Exception_base exception_base)
{
auto lambda = [&] (Cpu_thread_component *thread) {
if (!thread)
return;
thread->platform_thread().thread_type(thread_type, exception_base);
};
_thread_ep.apply(thread_cap, lambda);
}
Native_cpu_component::Native_cpu_component(Cpu_session_component &cpu_session, char const *)
:
_cpu_session(cpu_session), _thread_ep(*_cpu_session._thread_ep)
{
_thread_ep.manage(this);
}
Genode::Native_cpu_component::~Native_cpu_component()
{
_thread_ep.dissolve(this);
}

View File

@ -267,37 +267,13 @@ Thread_state Platform_thread::state()
void Platform_thread::state(Thread_state s)
{
if (_sel_exc_base == Native_thread::INVALID_INDEX) {
if (!_pager) throw Cpu_thread::State_access_failed();
/* you can do it only once */
if (!_pager->copy_thread_state(s))
throw Cpu_thread::State_access_failed();
/*
* s.sel_exc_base exception base of thread in caller
* protection domain - not in Core !
* s.is_vcpu If true it will run as vCPU,
* otherwise it will be a thread.
*/
if (!main_thread() || s.vcpu)
_sel_exc_base = s.sel_exc_base;
if (!s.global_thread)
_features |= WORKER;
if (!s.vcpu)
return;
_features |= VCPU;
} else {
if (!_pager) throw Cpu_thread::State_access_failed();
if (!_pager->copy_thread_state(s))
throw Cpu_thread::State_access_failed();
/* the new state is transferred to the kernel by the recall handler */
_pager->client_recall(false);
}
/* the new state is transferred to the kernel by the recall handler */
_pager->client_recall(false);
}
@ -352,6 +328,23 @@ void Platform_thread::pager(Pager_object *pager)
}
void Platform_thread::thread_type(Nova_native_cpu::Thread_type thread_type,
Nova_native_cpu::Exception_base exception_base)
{
/* you can do it only once */
if (_sel_exc_base != Native_thread::INVALID_INDEX)
return;
if (!main_thread() || (thread_type == Nova_native_cpu::Thread_type::VCPU))
_sel_exc_base = exception_base.exception_base;
if (thread_type == Nova_native_cpu::Thread_type::LOCAL)
_features |= WORKER;
else if (thread_type == Nova_native_cpu::Thread_type::VCPU)
_features |= VCPU;
}
Platform_thread::Platform_thread(size_t, const char *name, unsigned prio,
Affinity::Location affinity, int thread_id)
:

View File

@ -21,6 +21,7 @@
#include <base/rpc_client.h>
#include <session/session.h>
#include <cpu_thread/client.h>
#include <nova_native_cpu/client.h>
/* base-internal includes */
#include <base/internal/stack.h>
@ -148,18 +149,27 @@ void Thread::start()
using namespace Genode;
/* create EC at core */
Thread_state state;
state.sel_exc_base = native_thread().exc_pt_sel;
state.vcpu = native_thread().vcpu;
state.global_thread = global;
try {
Nova_native_cpu::Thread_type thread_type;
if (native_thread().vcpu)
thread_type = Nova_native_cpu::Thread_type::VCPU;
else if (global)
thread_type = Nova_native_cpu::Thread_type::GLOBAL;
else
thread_type = Nova_native_cpu::Thread_type::LOCAL;
Nova_native_cpu::Exception_base exception_base { native_thread().exc_pt_sel };
Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
native_cpu.thread_type(_thread_cap, thread_type, exception_base);
} catch (...) { throw Cpu_session::Thread_creation_failed(); }
/* local thread have no start instruction pointer - set via portal entry */
addr_t thread_ip = global ? reinterpret_cast<addr_t>(_thread_start) : native_thread().initial_ip;
Cpu_thread_client cpu_thread(_thread_cap);
try { cpu_thread.state(state); }
catch (...) { throw Cpu_session::Thread_creation_failed(); }
cpu_thread.start(thread_ip, _stack->top());
/* request native EC thread cap */

View File

@ -0,0 +1,9 @@
REQUIRES = nova
INC_DIR = $(REP_DIR)/src/server/cpu_sampler
SRC_CC = native_cpu.cc
SHARED_LIB = yes
vpath %.cc $(REP_DIR)/src/lib/cpu_sampler_platform-nova

View File

@ -12,8 +12,8 @@ set build_components {
test/cpu_sampler
}
if {[have_spec foc]} {
lappend build_components lib/cpu_sampler_platform-foc
if {[have_spec foc] || [have_spec nova]} {
lappend build_components lib/cpu_sampler_platform-$::env(KERNEL)
} else {
lappend build_components lib/cpu_sampler_platform-generic
}
@ -68,8 +68,8 @@ install_config {
# evaluated by the run tool
proc binary_name_cpu_sampler_platform_lib_so { } {
if {[have_spec foc]} {
return "cpu_sampler_platform-foc.lib.so"
if {[have_spec foc] || [have_spec nova]} {
return "cpu_sampler_platform-$::env(KERNEL).lib.so"
} else {
return "cpu_sampler_platform-generic.lib.so"
}

View File

@ -15,8 +15,8 @@ set build_components {
test/cpu_sampler
}
if {[have_spec foc]} {
lappend build_components lib/cpu_sampler_platform-foc
if {[have_spec foc] || [have_spec nova]} {
lappend build_components lib/cpu_sampler_platform-$::env(KERNEL)
} else {
lappend build_components lib/cpu_sampler_platform-generic
}
@ -222,8 +222,8 @@ install_config $config
# evaluated by the run tool
proc binary_name_cpu_sampler_platform_lib_so { } {
if {[have_spec foc]} {
return "cpu_sampler_platform-foc.lib.so"
if {[have_spec foc] || [have_spec nova]} {
return "cpu_sampler_platform-$::env(KERNEL).lib.so"
} else {
return "cpu_sampler_platform-generic.lib.so"
}

View File

@ -0,0 +1,86 @@
/*
* \brief NOVA-specific 'Native_cpu' setup
* \author Christian Prochaska
* \date 2016-05-13
*/
/*
* Copyright (C) 2016-2017 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.
*/
/* Genode includes */
#include <nova_native_cpu/client.h>
/* Cpu_sampler includes */
#include "cpu_session_component.h"
#include "cpu_thread_component.h"
namespace Cpu_sampler {
class Native_cpu_component;
}
using namespace Genode;
class Cpu_sampler::Native_cpu_component : public Rpc_object<Nova_native_cpu,
Native_cpu_component>
{
private:
Cpu_session_component &_cpu_session_component;
Nova_native_cpu_client _nova_native_cpu;
public:
Native_cpu_component(Cpu_session_component &cpu_session_component)
: _cpu_session_component(cpu_session_component),
_nova_native_cpu(_cpu_session_component.parent_cpu_session().native_cpu())
{
_cpu_session_component.thread_ep().manage(this);
}
~Native_cpu_component()
{
_cpu_session_component.thread_ep().dissolve(this);
}
void thread_type(Thread_capability thread_cap,
Nova_native_cpu::Thread_type thread_type,
Nova_native_cpu::Exception_base exception_base) override
{
auto lambda = [&] (Cpu_sampler::Cpu_thread_component *cpu_thread) {
_nova_native_cpu.thread_type(cpu_thread->parent_thread(),
thread_type, exception_base);
};
_cpu_session_component.thread_ep().apply(thread_cap, lambda);
}
};
Capability<Cpu_session::Native_cpu>
Cpu_sampler::Cpu_session_component::_setup_native_cpu()
{
Native_cpu_component *native_cpu_component =
new (_md_alloc) Native_cpu_component(*this);
return native_cpu_component->cap();
}
void Cpu_sampler::Cpu_session_component::_cleanup_native_cpu()
{
Native_cpu_component *native_cpu_component = nullptr;
_thread_ep.apply(_native_cpu_cap,
[&] (Native_cpu_component *c) { native_cpu_component = c; });
if (!native_cpu_component) return;
destroy(_md_alloc, native_cpu_component);
}

View File

@ -0,0 +1,2 @@
TARGET = cpu_sampler_platform-nova
LIBS = cpu_sampler_platform-nova

View File

@ -20,6 +20,7 @@
#include <pd_session/connection.h>
#include <region_map/client.h>
#include <cpu_thread/client.h>
#include <nova_native_cpu/client.h>
/* NOVA includes */
#include <nova/native_thread.h>
@ -72,12 +73,12 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
_location, Cpu_session::Weight());
/* tell parent that this will be a vCPU */
Thread_state state;
state.sel_exc_base = _exc_pt_sel;
state.vcpu = true;
Nova_native_cpu::Thread_type thread_type { Nova_native_cpu::Thread_type::VCPU };
Nova_native_cpu::Exception_base exception_base { _exc_pt_sel };
Nova_native_cpu_client native_cpu(_cpu_session->native_cpu());
native_cpu.thread_type(vcpu_vm, thread_type, exception_base);
Cpu_thread_client cpu_thread(vcpu_vm);
cpu_thread.state(state);
/*
* Translate vcpu_vm thread cap via current executing thread,

View File

@ -141,6 +141,7 @@ _ZN6Genode8ipc_callENS_17Native_capabilityERNS_11Msgbuf_baseES2_m U
_ZNK6Genode17Native_capability10local_nameEv U
_ZnwjRN6Genode9AllocatorE U
_ZSt9terminatev U
_ZTIN11Gdb_monitor20Cpu_thread_componentE U
_ZTVN10__cxxabiv117__class_type_infoE U
_ZTVN10__cxxabiv120__si_class_type_infoE U
_ZTVN10__cxxabiv121__vmi_class_type_infoE U

View File

@ -0,0 +1,84 @@
/*
* \brief NOVA-specific 'Native_cpu' setup
* \author Christian Prochaska
* \date 2016-05-13
*/
/*
* Copyright (C) 2016-2017 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.
*/
/* Genode includes */
#include <nova_native_cpu/client.h>
/* GDB monitor includes */
#include "cpu_session_component.h"
#include "cpu_thread_component.h"
namespace Gdb_monitor {
class Native_cpu_component;
}
using namespace Genode;
class Gdb_monitor::Native_cpu_component : public Rpc_object<Nova_native_cpu,
Native_cpu_component>
{
private:
Cpu_session_component &_cpu_session_component;
Nova_native_cpu_client _nova_native_cpu;
public:
Native_cpu_component(Cpu_session_component &cpu_session_component)
: _cpu_session_component(cpu_session_component),
_nova_native_cpu(_cpu_session_component.parent_cpu_session().native_cpu())
{
_cpu_session_component.thread_ep().manage(this);
}
~Native_cpu_component()
{
_cpu_session_component.thread_ep().dissolve(this);
}
void thread_type(Thread_capability thread_cap,
Nova_native_cpu::Thread_type thread_type,
Nova_native_cpu::Exception_base exception_base) override
{
auto lambda = [&] (Cpu_thread_component *cpu_thread) {
_nova_native_cpu.thread_type(cpu_thread->parent_thread_cap(),
thread_type, exception_base);
};
_cpu_session_component.thread_ep().apply(thread_cap, lambda);
}
};
Capability<Cpu_session::Native_cpu>
Gdb_monitor::Cpu_session_component::_setup_native_cpu()
{
Native_cpu_component *native_cpu_component =
new (_md_alloc) Native_cpu_component(*this);
return native_cpu_component->cap();
}
void Gdb_monitor::Cpu_session_component::_cleanup_native_cpu()
{
Native_cpu_component *native_cpu_component = nullptr;
_ep.apply(_native_cpu_cap, [&] (Native_cpu_component *c) { native_cpu_component = c; });
if (!native_cpu_component) return;
destroy(_md_alloc, native_cpu_component);
}

View File

@ -1,22 +0,0 @@
/*
* \brief Generic dummy 'Native_cpu' setup
* \author Christian Prochaska
* \date 2016-05-13
*/
/*
* Copyright (C) 2016-2017 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.
*/
/* GDB monitor includes */
#include "cpu_session_component.h"
Genode::Capability<Genode::Cpu_session::Native_cpu>
Gdb_monitor::Cpu_session_component::_setup_native_cpu() {
return Genode::Capability<Genode::Cpu_session::Native_cpu>(); }
void Gdb_monitor::Cpu_session_component::_cleanup_native_cpu() { }