2013-11-14 12:29:47 +00:00
|
|
|
/*
|
|
|
|
* \brief Paging framework
|
|
|
|
* \author Martin Stein
|
|
|
|
* \date 2013-11-07
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 _BASE__PAGER_H_
|
|
|
|
#define _BASE__PAGER_H_
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <base/thread.h>
|
|
|
|
#include <base/object_pool.h>
|
|
|
|
#include <base/signal.h>
|
|
|
|
#include <pager/capability.h>
|
|
|
|
|
2013-12-06 18:06:32 +00:00
|
|
|
/* base-hw includes */
|
|
|
|
#include <placement_new.h>
|
|
|
|
|
2013-11-14 12:29:47 +00:00
|
|
|
namespace Genode
|
|
|
|
{
|
|
|
|
class Cap_session;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Translation of a virtual page frame
|
|
|
|
*/
|
|
|
|
struct Mapping;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interface between the generic paging system and the base-hw backend
|
|
|
|
*/
|
|
|
|
class Ipc_pager;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a faulter and its paging context
|
|
|
|
*/
|
|
|
|
class Pager_object;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Paging entry point that manages a pool of pager objects
|
|
|
|
*/
|
|
|
|
class Pager_entrypoint;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A thread that processes one page fault of a pager object at a time
|
|
|
|
*/
|
|
|
|
class Pager_activation_base;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pager-activation base with custom stack size
|
|
|
|
*/
|
|
|
|
template <unsigned STACK_SIZE> class Pager_activation;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Genode::Mapping
|
|
|
|
{
|
|
|
|
addr_t virt_address;
|
|
|
|
addr_t phys_address;
|
|
|
|
bool write_combined;
|
|
|
|
bool io_mem;
|
|
|
|
unsigned size_log2;
|
|
|
|
bool writable;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor for invalid mappings
|
|
|
|
*/
|
|
|
|
Mapping();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor for valid mappings
|
|
|
|
*/
|
|
|
|
Mapping(addr_t const va, addr_t const pa, bool const wc,
|
|
|
|
bool const io, unsigned const sl2, bool const w);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepare for the application of the mapping
|
|
|
|
*/
|
|
|
|
void prepare_map_operation();
|
|
|
|
};
|
|
|
|
|
|
|
|
class Genode::Ipc_pager
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Page-fault data that is read from the faulters thread registers
|
|
|
|
*/
|
|
|
|
struct Fault_thread_regs
|
|
|
|
{
|
|
|
|
addr_t tlb;
|
|
|
|
addr_t ip;
|
|
|
|
addr_t addr;
|
|
|
|
addr_t writes;
|
|
|
|
addr_t signal;
|
|
|
|
};
|
|
|
|
|
|
|
|
Fault_thread_regs _fault;
|
|
|
|
Mapping _mapping;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Instruction pointer of current page fault
|
|
|
|
*/
|
|
|
|
addr_t fault_ip() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Faulter-local fault address of current page fault
|
|
|
|
*/
|
|
|
|
addr_t fault_addr() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Access direction of current page fault
|
|
|
|
*/
|
|
|
|
bool is_write_fault() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Input mapping data as reply to current page fault
|
|
|
|
*/
|
|
|
|
void set_reply_mapping(Mapping m);
|
|
|
|
};
|
|
|
|
|
|
|
|
class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
|
|
|
|
public Signal_context
|
|
|
|
{
|
|
|
|
friend class Pager_entrypoint;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Signal_context_capability _signal_context_cap;
|
|
|
|
Thread_capability _thread_cap;
|
2013-12-06 18:06:32 +00:00
|
|
|
bool _signal_valid;
|
2013-11-14 12:29:47 +00:00
|
|
|
char _signal_buf[sizeof(Signal)];
|
2013-11-15 12:47:55 +00:00
|
|
|
unsigned const _badge;
|
2013-11-14 12:29:47 +00:00
|
|
|
|
2013-12-06 18:06:32 +00:00
|
|
|
/**
|
|
|
|
* 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(); }
|
|
|
|
}
|
|
|
|
|
2013-11-14 12:29:47 +00:00
|
|
|
|
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
|
|
|
|
|
|
|
Signal * _signal() const;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
2013-11-15 12:47:55 +00:00
|
|
|
* \param badge user identifaction of pager object
|
2013-11-14 12:29:47 +00:00
|
|
|
*/
|
2013-11-15 12:47:55 +00:00
|
|
|
Pager_object(unsigned const badge, Affinity::Location);
|
2013-11-14 12:29:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The faulter has caused a fault and awaits paging
|
|
|
|
*
|
|
|
|
* \param s signal that communicated the fault
|
|
|
|
*/
|
2013-12-06 18:06:32 +00:00
|
|
|
void fault_occured(Signal const & s) { _take_fault(s); }
|
2013-11-14 12:29:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Current fault has been resolved so resume faulter
|
|
|
|
*/
|
2013-12-06 18:06:32 +00:00
|
|
|
void fault_resolved() { _end_fault(); }
|
2013-11-14 12:29:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* User identification of pager object
|
|
|
|
*/
|
2013-12-06 18:06:32 +00:00
|
|
|
unsigned badge() const { return _badge; }
|
2013-11-14 12:29:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Resume faulter
|
|
|
|
*/
|
|
|
|
void wake_up();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unnecessary as base-hw doesn't use exception handlers
|
|
|
|
*/
|
|
|
|
void exception_handler(Signal_context_capability);
|
|
|
|
|
2013-12-06 18:06:32 +00:00
|
|
|
/**
|
|
|
|
* Install information that is necessary to handle page faults
|
|
|
|
*
|
|
|
|
* \param c linkage between signal context and a signal receiver
|
|
|
|
* \param p linkage between pager object and a pager entry-point
|
|
|
|
*/
|
|
|
|
void start_paging(Signal_context_capability const & c,
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2013-11-14 12:29:47 +00:00
|
|
|
|
|
|
|
/******************
|
|
|
|
** Pure virtual **
|
|
|
|
******************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Request a mapping that resolves a fault directly
|
|
|
|
*
|
|
|
|
* \param p offers the fault data and receives mapping data
|
|
|
|
*
|
|
|
|
* \retval 0 succeeded
|
|
|
|
* \retval !=0 fault can't be received directly
|
|
|
|
*/
|
|
|
|
virtual int pager(Ipc_pager & p) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
|
|
|
|
|
|
|
Thread_capability thread_cap() const;
|
|
|
|
|
|
|
|
void thread_cap(Thread_capability const & c);
|
|
|
|
|
|
|
|
unsigned signal_context_id() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Genode::Pager_activation_base : public Thread_base,
|
|
|
|
public Signal_receiver,
|
|
|
|
public Ipc_pager
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Native_capability _cap;
|
|
|
|
Lock _cap_valid;
|
|
|
|
Pager_entrypoint * _ep;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* \param name name of the new thread
|
|
|
|
* \param stack_size stack size of the new thread
|
|
|
|
*/
|
|
|
|
Pager_activation_base(char const * const name,
|
|
|
|
size_t const stack_size);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Bring current mapping data into effect
|
|
|
|
*
|
|
|
|
* \retval 0 succeeded
|
|
|
|
* \retval -1 failed
|
|
|
|
*/
|
|
|
|
int apply_mapping();
|
|
|
|
|
|
|
|
|
|
|
|
/**********************
|
|
|
|
** Thread interface **
|
|
|
|
**********************/
|
|
|
|
|
|
|
|
void entry();
|
|
|
|
|
|
|
|
|
|
|
|
/***************
|
|
|
|
** Accessors **
|
|
|
|
***************/
|
|
|
|
|
|
|
|
Native_capability cap();
|
|
|
|
|
|
|
|
void ep(Pager_entrypoint * const ep);
|
|
|
|
};
|
|
|
|
|
|
|
|
class Genode::Pager_entrypoint : public Object_pool<Pager_object>
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
Pager_activation_base * const _activation;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* \param a activation that shall handle the objects of the entrypoint
|
|
|
|
*/
|
|
|
|
Pager_entrypoint(Cap_session *, Pager_activation_base * const a);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Associate pager object 'obj' with entry point
|
|
|
|
*/
|
|
|
|
Pager_capability manage(Pager_object * const obj);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dissolve pager object 'obj' from entry point
|
|
|
|
*/
|
|
|
|
void dissolve(Pager_object * const obj);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <unsigned STACK_SIZE>
|
|
|
|
class Genode::Pager_activation : public Pager_activation_base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
|
|
|
Pager_activation()
|
|
|
|
:
|
|
|
|
Pager_activation_base("pager_activation", STACK_SIZE)
|
|
|
|
{
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* _BASE__PAGER_H_ */
|