mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +00:00
hw: use kernel signal API for page-fault signals
Instead of using the Genode user-level signal API to signal page-faults to a page-fault handler, use the kernel API directly. Thereby the accounting of signal contexts needed for each paging subject can be done easily. Fix #956
This commit is contained in:
parent
57e2f3affc
commit
f5d5ed9637
@ -270,7 +270,7 @@ class Kernel::Signal_context : public Kernel::Object
|
|||||||
*/
|
*/
|
||||||
static capid_t syscall_create(void * p,
|
static capid_t syscall_create(void * p,
|
||||||
Signal_receiver * const receiver,
|
Signal_receiver * const receiver,
|
||||||
unsigned const imprint)
|
addr_t const imprint)
|
||||||
{
|
{
|
||||||
return call(call_id_new_signal_context(), (Call_arg)p,
|
return call(call_id_new_signal_context(), (Call_arg)p,
|
||||||
(Call_arg)receiver, (Call_arg)imprint);
|
(Call_arg)receiver, (Call_arg)imprint);
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include <base/signal.h>
|
#include <base/signal.h>
|
||||||
#include <pager/capability.h>
|
#include <pager/capability.h>
|
||||||
#include <unmanaged_singleton.h>
|
#include <unmanaged_singleton.h>
|
||||||
|
#include <kernel/signal_receiver.h>
|
||||||
|
#include <object.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
@ -124,54 +126,17 @@ class Genode::Ipc_pager
|
|||||||
void set_reply_mapping(Mapping m);
|
void set_reply_mapping(Mapping m);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
|
class Genode::Pager_object
|
||||||
public Signal_context
|
: public Object_pool<Pager_object>::Entry,
|
||||||
|
public Genode::Kernel_object<Kernel::Signal_context>
|
||||||
{
|
{
|
||||||
friend class Pager_entrypoint;
|
friend class Pager_entrypoint;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Signal_context_capability _signal_context_cap;
|
|
||||||
Thread_capability _thread_cap;
|
Thread_capability _thread_cap;
|
||||||
bool _signal_valid;
|
|
||||||
char _signal_buf[sizeof(Signal)];
|
|
||||||
unsigned long const _badge;
|
unsigned long const _badge;
|
||||||
|
|
||||||
/**
|
|
||||||
* Remember an incoming fault for handling
|
|
||||||
*
|
|
||||||
* \param s fault signal
|
|
||||||
*/
|
|
||||||
void _take_fault(Signal const & s)
|
|
||||||
{
|
|
||||||
new (_signal_buf) Signal(s);
|
|
||||||
_signal_valid = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End handling of current fault
|
|
||||||
*/
|
|
||||||
void _end_fault()
|
|
||||||
{
|
|
||||||
_signal()->~Signal();
|
|
||||||
_signal_valid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End handling of current fault if there is one
|
|
||||||
*/
|
|
||||||
void _end_fault_if_pending()
|
|
||||||
{
|
|
||||||
if (_signal_valid) { _end_fault(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************
|
|
||||||
** Accessors **
|
|
||||||
***************/
|
|
||||||
|
|
||||||
Signal * _signal() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,18 +146,6 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
|
|||||||
*/
|
*/
|
||||||
Pager_object(unsigned const badge, Affinity::Location);
|
Pager_object(unsigned const badge, Affinity::Location);
|
||||||
|
|
||||||
/**
|
|
||||||
* The faulter has caused a fault and awaits paging
|
|
||||||
*
|
|
||||||
* \param s signal that communicated the fault
|
|
||||||
*/
|
|
||||||
void fault_occured(Signal const & s) { _take_fault(s); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current fault has been resolved so resume faulter
|
|
||||||
*/
|
|
||||||
void fault_resolved() { _end_fault(); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User identification of pager object
|
* User identification of pager object
|
||||||
*/
|
*/
|
||||||
@ -211,25 +164,9 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
|
|||||||
/**
|
/**
|
||||||
* Install information that is necessary to handle page faults
|
* Install information that is necessary to handle page faults
|
||||||
*
|
*
|
||||||
* \param c linkage between signal context and a signal receiver
|
* \param receiver signal receiver that receives the page faults
|
||||||
* \param p linkage between pager object and a pager entry-point
|
|
||||||
*/
|
*/
|
||||||
void start_paging(Signal_context_capability const & c,
|
void start_paging(Kernel::Signal_receiver * receiver);
|
||||||
Pager_capability const & p)
|
|
||||||
{
|
|
||||||
_signal_context_cap = c;
|
|
||||||
Object_pool<Pager_object>::Entry::cap(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uninstall paging information and cancel unresolved faults
|
|
||||||
*/
|
|
||||||
void stop_paging()
|
|
||||||
{
|
|
||||||
Object_pool<Pager_object>::Entry::cap(Native_capability());
|
|
||||||
_signal_context_cap = Signal_context_capability();
|
|
||||||
_end_fault_if_pending();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a page-fault finally could not be resolved
|
* Called when a page-fault finally could not be resolved
|
||||||
@ -259,18 +196,16 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
|
|||||||
Thread_capability thread_cap() const;
|
Thread_capability thread_cap() const;
|
||||||
|
|
||||||
void thread_cap(Thread_capability const & c);
|
void thread_cap(Thread_capability const & c);
|
||||||
|
|
||||||
unsigned signal_context_id() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Genode::Pager_activation_base : public Thread_base,
|
class Genode::Pager_activation_base
|
||||||
public Signal_receiver,
|
: public Thread_base,
|
||||||
|
public Kernel_object<Kernel::Signal_receiver>,
|
||||||
public Ipc_pager
|
public Ipc_pager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Native_capability _cap;
|
Lock _startup_lock;
|
||||||
Lock _cap_valid;
|
|
||||||
Pager_entrypoint * _ep;
|
Pager_entrypoint * _ep;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -304,8 +239,6 @@ class Genode::Pager_activation_base : public Thread_base,
|
|||||||
** Accessors **
|
** Accessors **
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
Native_capability cap();
|
|
||||||
|
|
||||||
void ep(Pager_entrypoint * const ep);
|
void ep(Pager_entrypoint * const ep);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,9 +66,20 @@ Thread_capability Pager_object::thread_cap() const { return _thread_cap; }
|
|||||||
|
|
||||||
void Pager_object::thread_cap(Thread_capability const & c) { _thread_cap = c; }
|
void Pager_object::thread_cap(Thread_capability const & c) { _thread_cap = c; }
|
||||||
|
|
||||||
Signal * Pager_object::_signal() const { return (Signal *)_signal_buf; }
|
void Pager_object::wake_up()
|
||||||
|
{
|
||||||
|
using Object = Kernel_object<Kernel::Signal_context>;
|
||||||
|
Kernel::ack_signal(Object::_cap.dst());
|
||||||
|
}
|
||||||
|
|
||||||
void Pager_object::wake_up() { fault_resolved(); }
|
void Pager_object::start_paging(Kernel::Signal_receiver * receiver)
|
||||||
|
{
|
||||||
|
using Object = Kernel_object<Kernel::Signal_context>;
|
||||||
|
using Entry = Object_pool<Pager_object>::Entry;
|
||||||
|
|
||||||
|
create(receiver, (unsigned long)this);
|
||||||
|
Entry::cap(Object::_cap);
|
||||||
|
}
|
||||||
|
|
||||||
void Pager_object::exception_handler(Signal_context_capability) { }
|
void Pager_object::exception_handler(Signal_context_capability) { }
|
||||||
|
|
||||||
@ -81,18 +92,11 @@ void Pager_object::unresolved_page_fault_occurred()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Pager_object::Pager_object(unsigned const badge, Affinity::Location)
|
Pager_object::Pager_object(unsigned const badge, Affinity::Location)
|
||||||
:
|
: Object_pool<Pager_object>::Entry(Kernel_object<Kernel::Signal_context>::_cap),
|
||||||
_signal_valid(0),
|
|
||||||
_badge(badge)
|
_badge(badge)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
unsigned Pager_object::signal_context_id() const
|
|
||||||
{
|
|
||||||
return _signal_context_cap.dst();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
** Pager_activation_base **
|
** Pager_activation_base **
|
||||||
***************************/
|
***************************/
|
||||||
@ -102,18 +106,12 @@ void Pager_activation_base::ep(Pager_entrypoint * const ep) { _ep = ep; }
|
|||||||
|
|
||||||
Pager_activation_base::Pager_activation_base(char const * const name,
|
Pager_activation_base::Pager_activation_base(char const * const name,
|
||||||
size_t const stack_size)
|
size_t const stack_size)
|
||||||
:
|
: Thread_base(0, name, stack_size),
|
||||||
Thread_base(0, name, stack_size), _cap_valid(Lock::LOCKED), _ep(0)
|
Kernel_object<Kernel::Signal_receiver>(true),
|
||||||
|
_startup_lock(Lock::LOCKED), _ep(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
Native_capability Pager_activation_base::cap()
|
|
||||||
{
|
|
||||||
if (!_cap.valid()) { _cap_valid.lock(); }
|
|
||||||
return _cap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
** Pager_entrypoint **
|
** Pager_entrypoint **
|
||||||
**********************/
|
**********************/
|
||||||
@ -121,25 +119,18 @@ Native_capability Pager_activation_base::cap()
|
|||||||
void Pager_entrypoint::dissolve(Pager_object * const o)
|
void Pager_entrypoint::dissolve(Pager_object * const o)
|
||||||
{
|
{
|
||||||
remove_locked(o);
|
remove_locked(o);
|
||||||
o->stop_paging();
|
|
||||||
_activation->Signal_receiver::dissolve(o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Pager_entrypoint::Pager_entrypoint(Cap_session *,
|
Pager_entrypoint::Pager_entrypoint(Cap_session *,
|
||||||
Pager_activation_base * const activation)
|
Pager_activation_base * const activation)
|
||||||
:
|
: _activation(activation) {
|
||||||
_activation(activation)
|
_activation->ep(this); }
|
||||||
{
|
|
||||||
_activation->ep(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Pager_capability Pager_entrypoint::manage(Pager_object * const o)
|
Pager_capability Pager_entrypoint::manage(Pager_object * const o)
|
||||||
{
|
{
|
||||||
Signal_context_capability scc = _activation->Signal_receiver::manage(o);
|
o->start_paging(_activation->kernel_object());
|
||||||
Pager_capability p = reinterpret_cap_cast<Pager_object>(scc);
|
|
||||||
o->start_paging(scc, p);
|
|
||||||
insert(o);
|
insert(o);
|
||||||
return p;
|
return reinterpret_cap_cast<Pager_object>(o->cap());
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ void Platform_thread::pager(Pager_object * const pager)
|
|||||||
{
|
{
|
||||||
typedef Kernel::Thread_event_id Event_id;
|
typedef Kernel::Thread_event_id Event_id;
|
||||||
if (pager) {
|
if (pager) {
|
||||||
unsigned const sc_id = pager->signal_context_id();
|
unsigned const sc_id = pager->cap().dst();
|
||||||
if (sc_id) {
|
if (sc_id) {
|
||||||
if (!Kernel::route_thread_event(kernel_object(), Event_id::FAULT,
|
if (!Kernel::route_thread_event(kernel_object(), Event_id::FAULT,
|
||||||
sc_id)) {
|
sc_id)) {
|
||||||
|
@ -57,13 +57,13 @@ int Pager_activation_base::apply_mapping()
|
|||||||
void Pager_activation_base::entry()
|
void Pager_activation_base::entry()
|
||||||
{
|
{
|
||||||
/* get ready to receive faults */
|
/* get ready to receive faults */
|
||||||
_cap = Thread_base::myself()->tid().cap;
|
_startup_lock.unlock();
|
||||||
_cap_valid.unlock();
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* receive fault */
|
/* receive fault */
|
||||||
Signal s = Signal_receiver::wait_for_signal();
|
if (Kernel::await_signal(_cap.dst())) continue;
|
||||||
Pager_object * po = static_cast<Pager_object *>(s.context());
|
Pager_object * po =
|
||||||
|
*(Pager_object**)Thread_base::myself()->utcb()->base();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Synchronize access and ensure that the object is still managed
|
* Synchronize access and ensure that the object is still managed
|
||||||
@ -74,9 +74,6 @@ void Pager_activation_base::entry()
|
|||||||
Object_pool<Pager_object>::Guard pog(_ep->lookup_and_lock(pon));
|
Object_pool<Pager_object>::Guard pog(_ep->lookup_and_lock(pon));
|
||||||
if (!pog) continue;
|
if (!pog) continue;
|
||||||
|
|
||||||
/* let pager object go to fault state */
|
|
||||||
pog->fault_occured(s);
|
|
||||||
|
|
||||||
/* fetch fault data */
|
/* fetch fault data */
|
||||||
Platform_thread * const pt = (Platform_thread *)pog->badge();
|
Platform_thread * const pt = (Platform_thread *)pog->badge();
|
||||||
if (!pt) {
|
if (!pt) {
|
||||||
@ -104,6 +101,6 @@ void Pager_activation_base::entry()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* let pager object go back to no-fault state */
|
/* let pager object go back to no-fault state */
|
||||||
pog->fault_resolved();
|
pog->wake_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user