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 */