core: Introduce 'Address_space' interface
The new core-internal 'Address_space' interface enables cores RM service to flush mappings of a PD in which a given 'Rm_client' thread resides. Prior this patch, each platform invented their own way to flush mappings in the respective 'rm_session_support.cc' implementation. However, those implementations used to deal poorly with some corner cases. In particular, if a PD session was destroyed prior a RM session, the RM session would try to use no longer existing PD session. The new 'Address_space' uses the just added weak-pointer mechanism to deal with this issue. Furthermore, the generic 'Rm_session_component::detach' function has been improved to avoid duplicated unmap operations for platforms that implement the 'Address_space' interface. Therefore, it is related to issue #595. Right now, this is OKL4 only, but other platforms will follow.
This commit is contained in:
parent
352f58b94b
commit
21de42c45d
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
/* Codezero includes */
|
/* Codezero includes */
|
||||||
#include <codezero/syscalls.h>
|
#include <codezero/syscalls.h>
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
class Platform_pd
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -37,7 +38,6 @@ namespace Genode {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructors
|
* Constructors
|
||||||
*/
|
*/
|
||||||
|
@ -68,6 +68,13 @@ namespace Genode {
|
||||||
* Assign parent interface to protection domain
|
* Assign parent interface to protection domain
|
||||||
*/
|
*/
|
||||||
int assign_parent(Native_capability parent) { return 0; }
|
int assign_parent(Native_capability parent) { return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** Address-space interface **
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#include <base/thread_state.h>
|
#include <base/thread_state.h>
|
||||||
#include <base/native_types.h>
|
#include <base/native_types.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_pd;
|
class Platform_pd;
|
||||||
|
@ -30,19 +33,25 @@ namespace Genode {
|
||||||
|
|
||||||
enum { PD_NAME_MAX_LEN = 64 };
|
enum { PD_NAME_MAX_LEN = 64 };
|
||||||
|
|
||||||
unsigned _tid; /* global codezero thread ID */
|
unsigned _tid; /* global codezero thread ID */
|
||||||
unsigned _space_id;
|
unsigned _space_id;
|
||||||
addr_t _utcb;
|
Weak_ptr<Address_space> _address_space;
|
||||||
char _name[PD_NAME_MAX_LEN];
|
addr_t _utcb;
|
||||||
Pager_object *_pager;
|
char _name[PD_NAME_MAX_LEN];
|
||||||
|
Pager_object *_pager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign physical thread ID and UTCB address to thread
|
* Assign physical thread ID and UTCB address to thread
|
||||||
*
|
*
|
||||||
* This function is called from 'Platform_pd::bind_thread'.
|
* This function is called from 'Platform_pd::bind_thread'.
|
||||||
*/
|
*/
|
||||||
void _assign_physical_thread(unsigned tid, unsigned space_id, addr_t utcb) {
|
void _assign_physical_thread(unsigned tid, unsigned space_id,
|
||||||
_tid = tid; _space_id = space_id; _utcb = utcb; }
|
addr_t utcb,
|
||||||
|
Weak_ptr<Address_space> address_space)
|
||||||
|
{
|
||||||
|
_tid = tid; _space_id = space_id; _utcb = utcb;
|
||||||
|
_address_space = address_space;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -100,6 +109,11 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
Thread_state state();
|
Thread_state state();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Accessor functions **
|
** Accessor functions **
|
||||||
|
|
|
@ -67,7 +67,8 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_t utcb_addr = UTCB_VIRT_BASE + utcb_idx*sizeof(struct utcb);
|
addr_t utcb_addr = UTCB_VIRT_BASE + utcb_idx*sizeof(struct utcb);
|
||||||
thread->_assign_physical_thread(ids.tid, _space_id, utcb_addr);
|
thread->_assign_physical_thread(ids.tid, _space_id, utcb_addr,
|
||||||
|
this->Address_space::weak_ptr());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,12 @@ void Platform_thread::cancel_blocking()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
return _address_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(const char *name, unsigned, addr_t,
|
Platform_thread::Platform_thread(const char *name, unsigned, addr_t,
|
||||||
int thread_id)
|
int thread_id)
|
||||||
: _tid(THREAD_INVALID)
|
: _tid(THREAD_INVALID)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||||
|
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Fiasco {
|
namespace Fiasco {
|
||||||
#include <l4/sys/types.h>
|
#include <l4/sys/types.h>
|
||||||
|
@ -26,7 +27,7 @@ namespace Fiasco {
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
class Platform_pd
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -176,6 +177,17 @@ namespace Genode {
|
||||||
int assign_parent(Native_capability parent) { return 0; }
|
int assign_parent(Native_capability parent) { return 0; }
|
||||||
|
|
||||||
int pd_id() const { return _pd_id; }
|
int pd_id() const { return _pd_id; }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** Address-space interface **
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On L4/Fiasco, we don't use directed unmap but rely on the
|
||||||
|
* in-kernel mapping database. See 'rm_session_support.cc'.
|
||||||
|
*/
|
||||||
|
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
/* Fiasco includes */
|
/* Fiasco includes */
|
||||||
namespace Fiasco {
|
namespace Fiasco {
|
||||||
|
@ -122,6 +123,11 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
void affinity(unsigned) { }
|
void affinity(unsigned) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Accessor functions **
|
** Accessor functions **
|
||||||
|
|
|
@ -145,6 +145,12 @@ void Platform_thread::cancel_blocking()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
return _platform_pd->Address_space::weak_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(const char *name, unsigned, addr_t, int thread_id)
|
Platform_thread::Platform_thread(const char *name, unsigned, addr_t, int thread_id)
|
||||||
: _thread_id(thread_id), _l4_thread_id(L4_INVALID_ID), _pager(0)
|
: _thread_id(thread_id), _l4_thread_id(L4_INVALID_ID), _pager(0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <cap_mapping.h>
|
#include <cap_mapping.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
/* Fiasco.OC includes */
|
/* Fiasco.OC includes */
|
||||||
namespace Fiasco {
|
namespace Fiasco {
|
||||||
|
@ -36,7 +37,7 @@ namespace Fiasco {
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
class Platform_pd
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -97,11 +98,23 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
int assign_parent(Native_capability parent);
|
int assign_parent(Native_capability parent);
|
||||||
|
|
||||||
|
|
||||||
/*******************************
|
/*******************************
|
||||||
** Fiasco-specific Accessors **
|
** Fiasco-specific Accessors **
|
||||||
*******************************/
|
*******************************/
|
||||||
|
|
||||||
Native_capability native_task() { return _task.local; }
|
Native_capability native_task() { return _task.local; }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** Address-space interface **
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Fiasco.OC, we don't use directed unmap but rely on the
|
||||||
|
* in-kernel mapping database. See 'rm_session_support.cc'.
|
||||||
|
*/
|
||||||
|
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <cap_session_component.h>
|
#include <cap_session_component.h>
|
||||||
#include <cap_mapping.h>
|
#include <cap_mapping.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
|
@ -134,6 +135,11 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
void affinity(unsigned cpu);
|
void affinity(unsigned cpu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Accessor functions **
|
** Accessor functions **
|
||||||
|
|
|
@ -237,6 +237,12 @@ void Platform_thread::_finalize_construction(const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
return _platform_pd->Address_space::weak_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(const char *name,
|
Platform_thread::Platform_thread(const char *name,
|
||||||
unsigned prio)
|
unsigned prio)
|
||||||
: _core_thread(false),
|
: _core_thread(false),
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#include <base/thread_state.h>
|
#include <base/thread_state.h>
|
||||||
#include <base/native_types.h>
|
#include <base/native_types.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_pd;
|
class Platform_pd;
|
||||||
|
@ -80,6 +83,11 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
Thread_state state();
|
Thread_state state();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Accessor functions **
|
** Accessor functions **
|
||||||
|
|
|
@ -73,6 +73,13 @@ unsigned long Platform_thread::pager_object_badge() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
PWRN("not implemented");
|
||||||
|
return Weak_ptr<Address_space>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(const char *name, unsigned, addr_t,
|
Platform_thread::Platform_thread(const char *name, unsigned, addr_t,
|
||||||
int thread_id)
|
int thread_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
/* Core includes */
|
/* Core includes */
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -34,7 +35,7 @@ namespace Genode
|
||||||
/**
|
/**
|
||||||
* Platform specific part of a Genode protection domain
|
* Platform specific part of a Genode protection domain
|
||||||
*/
|
*/
|
||||||
class Platform_pd
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
unsigned _id; /* ID of our kernel object */
|
unsigned _id; /* ID of our kernel object */
|
||||||
Native_capability _parent; /* our parent interface */
|
Native_capability _parent; /* our parent interface */
|
||||||
|
@ -77,9 +78,9 @@ namespace Genode
|
||||||
{
|
{
|
||||||
/* annotate that we've got a main thread from now on */
|
/* annotate that we've got a main thread from now on */
|
||||||
_main_thread = t->id();
|
_main_thread = t->id();
|
||||||
return t->join_pd(_id, 1);
|
return t->join_pd(_id, 1, Address_space::weak_ptr());
|
||||||
}
|
}
|
||||||
return t->join_pd(_id, 0);
|
return t->join_pd(_id, 0, Address_space::weak_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,6 +99,13 @@ namespace Genode
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** Address-space interface **
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ namespace Genode {
|
||||||
Thread_base * _thread_base;
|
Thread_base * _thread_base;
|
||||||
size_t _stack_size;
|
size_t _stack_size;
|
||||||
unsigned _pd_id;
|
unsigned _pd_id;
|
||||||
|
Weak_ptr<Address_space> _address_space;
|
||||||
unsigned _id;
|
unsigned _id;
|
||||||
Rm_client * _rm_client;
|
Rm_client * _rm_client;
|
||||||
bool _main_thread;
|
bool _main_thread;
|
||||||
|
@ -91,7 +93,8 @@ namespace Genode {
|
||||||
* \retval 0 on success
|
* \retval 0 on success
|
||||||
* \retval <0 otherwise
|
* \retval <0 otherwise
|
||||||
*/
|
*/
|
||||||
int join_pd(unsigned const pd_id, bool const main_thread);
|
int join_pd(unsigned const pd_id, bool const main_thread,
|
||||||
|
Weak_ptr<Address_space> address_space);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run this thread
|
* Run this thread
|
||||||
|
@ -142,6 +145,11 @@ namespace Genode {
|
||||||
void affinity(unsigned cpu) {
|
void affinity(unsigned cpu) {
|
||||||
kernel_log() << __PRETTY_FUNCTION__ << ": not implemented\n"; };
|
kernel_log() << __PRETTY_FUNCTION__ << ": not implemented\n"; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
** Accessors **
|
** Accessors **
|
||||||
|
|
|
@ -32,6 +32,12 @@ bool Platform_thread::_attaches_utcb_by_itself()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
return _address_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::~Platform_thread()
|
Platform_thread::~Platform_thread()
|
||||||
{
|
{
|
||||||
/* detach UTCB if main thread outside core */
|
/* detach UTCB if main thread outside core */
|
||||||
|
@ -102,14 +108,16 @@ Platform_thread::Platform_thread(const char * name, unsigned int priority,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread)
|
int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread,
|
||||||
|
Weak_ptr<Address_space> address_space)
|
||||||
{
|
{
|
||||||
/* check if we're already in another PD */
|
/* check if we're already in another PD */
|
||||||
if (_pd_id && _pd_id != pd_id) return -1;
|
if (_pd_id && _pd_id != pd_id) return -1;
|
||||||
|
|
||||||
/* denote configuration for start method */
|
/* denote configuration for start method */
|
||||||
_pd_id = pd_id;
|
_pd_id = pd_id;
|
||||||
_main_thread = main_thread;
|
_main_thread = main_thread;
|
||||||
|
_address_space = address_space;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||||
|
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be initialized by the startup code,
|
* Must be initialized by the startup code,
|
||||||
|
@ -25,7 +26,7 @@ extern Genode::addr_t __core_pd_sel;
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
class Platform_pd
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -88,6 +89,17 @@ namespace Genode {
|
||||||
* \return PD selector
|
* \return PD selector
|
||||||
*/
|
*/
|
||||||
static addr_t pd_core_sel() { return __core_pd_sel; }
|
static addr_t pd_core_sel() { return __core_pd_sel; }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** Address-space interface **
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On NOVA, we don't use directed unmap but rely on the
|
||||||
|
* in-kernel mapping database. See 'rm_session_support.cc'.
|
||||||
|
*/
|
||||||
|
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
#include <base/pager.h>
|
#include <base/pager.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_pd;
|
class Platform_pd;
|
||||||
|
@ -98,6 +101,11 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
Thread_state state();
|
Thread_state state();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Accessor functions **
|
** Accessor functions **
|
||||||
|
|
|
@ -309,6 +309,12 @@ unsigned long Platform_thread::pager_object_badge() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
return _pd->Address_space::weak_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(const char *name, unsigned, int thread_id)
|
Platform_thread::Platform_thread(const char *name, unsigned, int thread_id)
|
||||||
:
|
:
|
||||||
_pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)),
|
_pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)),
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
#ifndef _CORE__INCLUDE__PLATFORM_PD_H_
|
#ifndef _CORE__INCLUDE__PLATFORM_PD_H_
|
||||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Okl4 { extern "C" {
|
namespace Okl4 { extern "C" {
|
||||||
#include <l4/types.h>
|
#include <l4/types.h>
|
||||||
|
@ -23,7 +25,7 @@ namespace Okl4 { extern "C" {
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
class Platform_pd
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -185,6 +187,13 @@ namespace Genode {
|
||||||
void space_pager(Platform_thread *pd);
|
void space_pager(Platform_thread *pd);
|
||||||
|
|
||||||
int pd_id() const { return _pd_id; }
|
int pd_id() const { return _pd_id; }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** Address-space interface **
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
void flush(addr_t, size_t);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
|
@ -110,6 +111,11 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
Thread_state state();
|
Thread_state state();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Accessor functions **
|
** Accessor functions **
|
||||||
|
|
|
@ -257,6 +257,69 @@ void Platform_pd::_setup_address_space()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const bool verbose_unmap = false;
|
||||||
|
|
||||||
|
|
||||||
|
static void unmap_log2_range(unsigned pd_id, addr_t base, size_t size_log2)
|
||||||
|
{
|
||||||
|
using namespace Okl4;
|
||||||
|
|
||||||
|
L4_Fpage_t fpage = L4_FpageLog2(base, size_log2);
|
||||||
|
L4_FpageAddRightsTo(&fpage, L4_FullyAccessible);
|
||||||
|
int ret = L4_UnmapFpage(L4_SpaceId(pd_id), fpage);
|
||||||
|
if (ret != 1)
|
||||||
|
PERR("could not unmap page at %p from space %x (Error Code %ld)",
|
||||||
|
(void *)base, pd_id, L4_ErrorCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Platform_pd::flush(addr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
using namespace Okl4;
|
||||||
|
|
||||||
|
L4_Word_t remaining_size = size;
|
||||||
|
L4_Word_t size_log2 = get_page_size_log2();
|
||||||
|
|
||||||
|
if (verbose_unmap)
|
||||||
|
printf("PD %d: unmap [%lx,%lx)\n", _pd_id, addr, addr + size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let unmap granularity ('size_log2') grow
|
||||||
|
*/
|
||||||
|
while (remaining_size >= (1UL << size_log2)) {
|
||||||
|
|
||||||
|
enum { SIZE_LOG2_MAX = 22 /* 4M */ };
|
||||||
|
|
||||||
|
/* issue 'unmap' for the current address if flexpage aligned */
|
||||||
|
if (addr & (1 << size_log2)) {
|
||||||
|
unmap_log2_range(_pd_id, addr, size_log2);
|
||||||
|
|
||||||
|
remaining_size -= 1 << size_log2;
|
||||||
|
addr += 1 << size_log2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increase flexpage size */
|
||||||
|
size_log2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let unmap granularity ('size_log2') shrink
|
||||||
|
*/
|
||||||
|
while (remaining_size > 0) {
|
||||||
|
|
||||||
|
if (remaining_size >= (1UL << size_log2)) {
|
||||||
|
unmap_log2_range(_pd_id, addr, size_log2);
|
||||||
|
|
||||||
|
remaining_size -= 1 << size_log2;
|
||||||
|
addr += 1 << size_log2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* decrease flexpage size */
|
||||||
|
size_log2--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_pd::Platform_pd(bool core)
|
Platform_pd::Platform_pd(bool core)
|
||||||
: _space_pager(0)
|
: _space_pager(0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -178,6 +178,12 @@ unsigned long Platform_thread::pager_object_badge() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
return _platform_pd->Address_space::weak_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int thread_id)
|
Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int thread_id)
|
||||||
: _thread_id(thread_id), _l4_thread_id(L4_nilthread), _platform_pd(0),
|
: _thread_id(thread_id), _l4_thread_id(L4_nilthread), _platform_pd(0),
|
||||||
_priority(prio), _pager(0)
|
_priority(prio), _pager(0)
|
||||||
|
|
|
@ -17,74 +17,13 @@
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <rm_session_component.h>
|
#include <rm_session_component.h>
|
||||||
|
|
||||||
/* OKL4 includes */
|
|
||||||
namespace Okl4 { extern "C" {
|
|
||||||
#include <l4/types.h>
|
|
||||||
#include <l4/space.h>
|
|
||||||
#include <l4/ipc.h>
|
|
||||||
} }
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
using namespace Okl4;
|
|
||||||
|
|
||||||
static const bool verbose_unmap = false;
|
|
||||||
|
|
||||||
|
|
||||||
static void unmap_log2_range(L4_SpaceId_t space_id, L4_Word_t base, L4_Word_t size_log2)
|
|
||||||
{
|
|
||||||
L4_Fpage_t fpage = L4_FpageLog2(base, size_log2);
|
|
||||||
L4_FpageAddRightsTo(&fpage, L4_FullyAccessible);
|
|
||||||
int ret = L4_UnmapFpage(space_id, fpage);
|
|
||||||
if (ret != 1)
|
|
||||||
PERR("could not unmap page at %p from space %lx (Error Code %ld)",
|
|
||||||
(void *)base, space_id.raw, L4_ErrorCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Rm_client::unmap(addr_t, addr_t virt_base, size_t size)
|
void Rm_client::unmap(addr_t, addr_t virt_base, size_t size)
|
||||||
{
|
{
|
||||||
L4_ThreadId_t tid = { raw : badge() };
|
Locked_ptr<Address_space> locked_address_space(_address_space);
|
||||||
L4_SpaceId_t space_id = { raw: L4_ThreadNo(tid) >> Thread_id_bits::THREAD };
|
|
||||||
L4_Word_t addr = virt_base;
|
|
||||||
L4_Word_t remaining_size = size;
|
|
||||||
L4_Word_t size_log2 = get_page_size_log2();
|
|
||||||
|
|
||||||
if (verbose_unmap)
|
if (locked_address_space.is_valid())
|
||||||
printf("RM client %p (%lx) unmap [%lx,%lx)\n",
|
locked_address_space->flush(virt_base, size);
|
||||||
this, badge(), virt_base, virt_base + size);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Let unmap granularity ('size_log2') grow
|
|
||||||
*/
|
|
||||||
while (remaining_size >= (1UL << size_log2)) {
|
|
||||||
|
|
||||||
enum { SIZE_LOG2_MAX = 22 /* 4M */ };
|
|
||||||
|
|
||||||
/* issue 'unmap' for the current address if flexpage aligned */
|
|
||||||
if (addr & (1 << size_log2)) {
|
|
||||||
unmap_log2_range(space_id, addr, size_log2);
|
|
||||||
|
|
||||||
remaining_size -= 1 << size_log2;
|
|
||||||
addr += 1 << size_log2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* increase flexpage size */
|
|
||||||
size_log2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Let unmap granularity ('size_log2') shrink
|
|
||||||
*/
|
|
||||||
while (remaining_size > 0) {
|
|
||||||
|
|
||||||
if (remaining_size >= (1UL << size_log2)) {
|
|
||||||
unmap_log2_range(space_id, addr, size_log2);
|
|
||||||
|
|
||||||
remaining_size -= 1 << size_log2;
|
|
||||||
addr += 1 << size_log2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* decrease flexpage size */
|
|
||||||
size_log2--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||||
|
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Pistachio {
|
namespace Pistachio {
|
||||||
#include <l4/types.h>
|
#include <l4/types.h>
|
||||||
|
@ -23,7 +24,7 @@ namespace Pistachio {
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
class Platform_pd
|
class Platform_pd : public Address_space
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -216,6 +217,17 @@ namespace Genode {
|
||||||
int assign_parent(Native_capability parent) { return 0; }
|
int assign_parent(Native_capability parent) { return 0; }
|
||||||
|
|
||||||
int pd_id() const { return _pd_id; }
|
int pd_id() const { return _pd_id; }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************
|
||||||
|
** Address-space interface **
|
||||||
|
*****************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Pistachio, we don't use directed unmap but rely on the
|
||||||
|
* in-kernel mapping database. See 'rm_session_support.cc'.
|
||||||
|
*/
|
||||||
|
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
/* Pistachio includes */
|
/* Pistachio includes */
|
||||||
namespace Pistachio {
|
namespace Pistachio {
|
||||||
|
@ -114,6 +115,11 @@ namespace Genode {
|
||||||
*/
|
*/
|
||||||
Thread_state state();
|
Thread_state state();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the address space to which the thread is bound
|
||||||
|
*/
|
||||||
|
Weak_ptr<Address_space> address_space();
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Accessor functions **
|
** Accessor functions **
|
||||||
|
|
|
@ -226,6 +226,12 @@ void Platform_thread::cancel_blocking()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> Platform_thread::address_space()
|
||||||
|
{
|
||||||
|
return _platform_pd->Address_space::weak_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int id)
|
Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int id)
|
||||||
: _thread_id(id), _l4_thread_id(L4_nilthread), _priority(prio), _pager(0)
|
: _thread_id(id), _l4_thread_id(L4_nilthread), _priority(prio), _pager(0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -100,6 +100,7 @@ namespace Genode {
|
||||||
class Out_of_metadata : public Attach_failed { };
|
class Out_of_metadata : public Attach_failed { };
|
||||||
|
|
||||||
class Invalid_thread : public Exception { };
|
class Invalid_thread : public Exception { };
|
||||||
|
class Unbound_thread : public Exception { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
|
@ -156,6 +157,7 @@ namespace Genode {
|
||||||
* \param thread thread that will be paged
|
* \param thread thread that will be paged
|
||||||
* \throw Invalid_thread
|
* \throw Invalid_thread
|
||||||
* \throw Out_of_metadata
|
* \throw Out_of_metadata
|
||||||
|
* \throw Unbound_thread
|
||||||
* \return capability to be used for handling page faults
|
* \return capability to be used for handling page faults
|
||||||
*
|
*
|
||||||
* This method must be called at least once to establish a valid
|
* This method must be called at least once to establish a valid
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* \brief Interface for flushing mapping from a protection domain
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2013-03-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 _CORE__INCLUDE__ADDRESS_SPACE_H_
|
||||||
|
#define _CORE__INCLUDE__ADDRESS_SPACE_H_
|
||||||
|
|
||||||
|
#include <base/stdint.h>
|
||||||
|
#include <lifetime.h>
|
||||||
|
|
||||||
|
namespace Genode { struct Address_space; }
|
||||||
|
|
||||||
|
struct Genode::Address_space : Genode::Volatile_object<Genode::Address_space>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Flush memory mappings of virtual address range
|
||||||
|
*
|
||||||
|
* \param virt_addr start address of range to flush
|
||||||
|
* \param size size of range in bytes, must be a multiple of page size
|
||||||
|
*/
|
||||||
|
virtual void flush(addr_t virt_addr, size_t size) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _CORE__INCLUDE__ADDRESS_SPACE_H_ */
|
|
@ -32,10 +32,10 @@
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <dataspace_component.h>
|
#include <dataspace_component.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
#include <address_space.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
|
|
||||||
class Dataspace_component;
|
class Dataspace_component;
|
||||||
class Rm_session_component;
|
class Rm_session_component;
|
||||||
class Rm_client;
|
class Rm_client;
|
||||||
|
@ -185,6 +185,10 @@ namespace Genode {
|
||||||
class Rm_client : public Pager_object, public Rm_member, public Rm_faulter,
|
class Rm_client : public Pager_object, public Rm_member, public Rm_faulter,
|
||||||
public List<Rm_client>::Element
|
public List<Rm_client>::Element
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Weak_ptr<Address_space> _address_space;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,8 +198,11 @@ namespace Genode {
|
||||||
* \param badge pager-object badge used of identifying the client
|
* \param badge pager-object badge used of identifying the client
|
||||||
* when a page-fault occurs
|
* when a page-fault occurs
|
||||||
*/
|
*/
|
||||||
Rm_client(Rm_session_component *session, unsigned long badge) :
|
Rm_client(Rm_session_component *session, unsigned long badge,
|
||||||
Pager_object(badge), Rm_member(session), Rm_faulter(this) { }
|
Weak_ptr<Address_space> &address_space)
|
||||||
|
:
|
||||||
|
Pager_object(badge), Rm_member(session), Rm_faulter(this),
|
||||||
|
_address_space(address_space) { }
|
||||||
|
|
||||||
int pager(Ipc_pager &pager);
|
int pager(Ipc_pager &pager);
|
||||||
|
|
||||||
|
@ -203,6 +210,11 @@ namespace Genode {
|
||||||
* Flush memory mappings for the specified virtual address range
|
* Flush memory mappings for the specified virtual address range
|
||||||
*/
|
*/
|
||||||
void unmap(addr_t core_local_base, addr_t virt_base, size_t size);
|
void unmap(addr_t core_local_base, addr_t virt_base, size_t size);
|
||||||
|
|
||||||
|
bool has_same_address_space(Rm_client const &other)
|
||||||
|
{
|
||||||
|
return other._address_space == _address_space;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -545,7 +545,9 @@ void Rm_session_component::detach(Local_addr local_addr)
|
||||||
* Go through all RM clients using the RM session. For each RM client, we
|
* Go through all RM clients using the RM session. For each RM client, we
|
||||||
* need to unmap the referred region from its virtual address space.
|
* need to unmap the referred region from its virtual address space.
|
||||||
*/
|
*/
|
||||||
for (Rm_client *rc = _clients.first(); rc; rc = rc->List<Rm_client>::Element::next()) {
|
Rm_client *prev_rc = 0;
|
||||||
|
Rm_client *rc = _clients.first();
|
||||||
|
for (; rc; rc = rc->List<Rm_client>::Element::next(), prev_rc = rc) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX Unmapping managed dataspaces on kernels, which take a core-
|
* XXX Unmapping managed dataspaces on kernels, which take a core-
|
||||||
|
@ -563,6 +565,23 @@ void Rm_session_component::detach(Local_addr local_addr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't unmap from the same address space twice. If multiple threads
|
||||||
|
* reside in one PD, each thread will have a corresponding 'Rm_client'
|
||||||
|
* object. Consequenlty, an unmap operation referring to the PD is
|
||||||
|
* issued multiple times, one time for each thread. By comparing the
|
||||||
|
* membership to the thread's respective address spaces, we reduce
|
||||||
|
* superfluous unmap operations.
|
||||||
|
*
|
||||||
|
* Note that the list of 'Rm_client' object may contain threads of
|
||||||
|
* different address spaces in any order. So superfluous unmap
|
||||||
|
* operations can still happen if 'Rm_client' objects of one PD are
|
||||||
|
* interleaved with 'Rm_client' objects of another PD. In practice,
|
||||||
|
* however, this corner case is rare.
|
||||||
|
*/
|
||||||
|
if (prev_rc && prev_rc->has_same_address_space(*rc))
|
||||||
|
continue;
|
||||||
|
|
||||||
rc->unmap(dsc->core_local_addr() + region->offset(),
|
rc->unmap(dsc->core_local_addr() + region->offset(),
|
||||||
region->base(), region->size());
|
region->base(), region->size());
|
||||||
}
|
}
|
||||||
|
@ -588,6 +607,7 @@ void Rm_session_component::detach(Local_addr local_addr)
|
||||||
Pager_capability Rm_session_component::add_client(Thread_capability thread)
|
Pager_capability Rm_session_component::add_client(Thread_capability thread)
|
||||||
{
|
{
|
||||||
unsigned long badge;
|
unsigned long badge;
|
||||||
|
Weak_ptr<Address_space> address_space;
|
||||||
|
|
||||||
{
|
{
|
||||||
/* lookup thread and setup correct parameters */
|
/* lookup thread and setup correct parameters */
|
||||||
|
@ -597,13 +617,17 @@ Pager_capability Rm_session_component::add_client(Thread_capability thread)
|
||||||
|
|
||||||
/* determine identification of client when faulting */
|
/* determine identification of client when faulting */
|
||||||
badge = cpu_thread->platform_thread()->pager_object_badge();
|
badge = cpu_thread->platform_thread()->pager_object_badge();
|
||||||
|
|
||||||
|
address_space = cpu_thread->platform_thread()->address_space();
|
||||||
|
if (!Locked_ptr<Address_space>(address_space).is_valid())
|
||||||
|
throw Unbound_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* serialize access */
|
/* serialize access */
|
||||||
Lock::Guard lock_guard(_lock);
|
Lock::Guard lock_guard(_lock);
|
||||||
|
|
||||||
Rm_client *cl;
|
Rm_client *cl;
|
||||||
try { cl = new(&_client_slab) Rm_client(this, badge); }
|
try { cl = new(&_client_slab) Rm_client(this, badge, address_space); }
|
||||||
catch (Allocator::Out_of_memory) { throw Out_of_metadata(); }
|
catch (Allocator::Out_of_memory) { throw Out_of_metadata(); }
|
||||||
catch (Cpu_session::Thread_creation_failed) { throw Out_of_metadata(); }
|
catch (Cpu_session::Thread_creation_failed) { throw Out_of_metadata(); }
|
||||||
catch (Thread_base::Stack_alloc_failed) { throw Out_of_metadata(); }
|
catch (Thread_base::Stack_alloc_failed) { throw Out_of_metadata(); }
|
||||||
|
|
Loading…
Reference in New Issue