mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
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 */
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
/* Codezero includes */
|
||||
#include <codezero/syscalls.h>
|
||||
@ -23,7 +24,7 @@
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
class Platform_pd
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
private:
|
||||
|
||||
@ -37,7 +38,6 @@ namespace Genode {
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Constructors
|
||||
*/
|
||||
@ -68,6 +68,13 @@ namespace Genode {
|
||||
* Assign parent interface to protection domain
|
||||
*/
|
||||
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/native_types.h>
|
||||
|
||||
/* core includes */
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Platform_pd;
|
||||
@ -30,19 +33,25 @@ namespace Genode {
|
||||
|
||||
enum { PD_NAME_MAX_LEN = 64 };
|
||||
|
||||
unsigned _tid; /* global codezero thread ID */
|
||||
unsigned _space_id;
|
||||
addr_t _utcb;
|
||||
char _name[PD_NAME_MAX_LEN];
|
||||
Pager_object *_pager;
|
||||
unsigned _tid; /* global codezero thread ID */
|
||||
unsigned _space_id;
|
||||
Weak_ptr<Address_space> _address_space;
|
||||
addr_t _utcb;
|
||||
char _name[PD_NAME_MAX_LEN];
|
||||
Pager_object *_pager;
|
||||
|
||||
/**
|
||||
* Assign physical thread ID and UTCB address to thread
|
||||
*
|
||||
* This function is called from 'Platform_pd::bind_thread'.
|
||||
*/
|
||||
void _assign_physical_thread(unsigned tid, unsigned space_id, addr_t utcb) {
|
||||
_tid = tid; _space_id = space_id; _utcb = utcb; }
|
||||
void _assign_physical_thread(unsigned tid, unsigned space_id,
|
||||
addr_t utcb,
|
||||
Weak_ptr<Address_space> address_space)
|
||||
{
|
||||
_tid = tid; _space_id = space_id; _utcb = utcb;
|
||||
_address_space = address_space;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@ -100,6 +109,11 @@ namespace Genode {
|
||||
*/
|
||||
Thread_state state();
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/************************
|
||||
** 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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
int thread_id)
|
||||
: _tid(THREAD_INVALID)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/types.h>
|
||||
@ -26,7 +27,7 @@ namespace Fiasco {
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
class Platform_pd
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
private:
|
||||
|
||||
@ -176,6 +177,17 @@ namespace Genode {
|
||||
int assign_parent(Native_capability parent) { return 0; }
|
||||
|
||||
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 */
|
||||
#include <platform_pd.h>
|
||||
#include <address_space.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
namespace Fiasco {
|
||||
@ -122,6 +123,11 @@ namespace Genode {
|
||||
*/
|
||||
void affinity(unsigned) { }
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/************************
|
||||
** 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)
|
||||
: _thread_id(thread_id), _l4_thread_id(L4_INVALID_ID), _pager(0)
|
||||
{
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <cap_mapping.h>
|
||||
#include <address_space.h>
|
||||
|
||||
/* Fiasco.OC includes */
|
||||
namespace Fiasco {
|
||||
@ -36,7 +37,7 @@ namespace Fiasco {
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
class Platform_pd
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
private:
|
||||
|
||||
@ -97,11 +98,23 @@ namespace Genode {
|
||||
*/
|
||||
int assign_parent(Native_capability parent);
|
||||
|
||||
|
||||
/*******************************
|
||||
** Fiasco-specific Accessors **
|
||||
*******************************/
|
||||
|
||||
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 <cap_session_component.h>
|
||||
#include <cap_mapping.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
@ -134,6 +135,11 @@ namespace Genode {
|
||||
*/
|
||||
void affinity(unsigned cpu);
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/************************
|
||||
** 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,
|
||||
unsigned prio)
|
||||
: _core_thread(false),
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <base/thread_state.h>
|
||||
#include <base/native_types.h>
|
||||
|
||||
/* core includes */
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Platform_pd;
|
||||
@ -80,6 +83,11 @@ namespace Genode {
|
||||
*/
|
||||
Thread_state state();
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/************************
|
||||
** 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,
|
||||
int thread_id)
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
/* Core includes */
|
||||
#include <platform.h>
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@ -34,7 +35,7 @@ namespace Genode
|
||||
/**
|
||||
* Platform specific part of a Genode protection domain
|
||||
*/
|
||||
class Platform_pd
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
unsigned _id; /* ID of our kernel object */
|
||||
Native_capability _parent; /* our parent interface */
|
||||
@ -77,9 +78,9 @@ namespace Genode
|
||||
{
|
||||
/* annotate that we've got a main thread from now on */
|
||||
_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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
** Address-space interface **
|
||||
*****************************/
|
||||
|
||||
void flush(addr_t, size_t) { PDBG("not implemented"); }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
@ -43,6 +44,7 @@ namespace Genode {
|
||||
Thread_base * _thread_base;
|
||||
size_t _stack_size;
|
||||
unsigned _pd_id;
|
||||
Weak_ptr<Address_space> _address_space;
|
||||
unsigned _id;
|
||||
Rm_client * _rm_client;
|
||||
bool _main_thread;
|
||||
@ -91,7 +93,8 @@ namespace Genode {
|
||||
* \retval 0 on success
|
||||
* \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
|
||||
@ -142,6 +145,11 @@ namespace Genode {
|
||||
void affinity(unsigned cpu) {
|
||||
kernel_log() << __PRETTY_FUNCTION__ << ": not implemented\n"; };
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/***************
|
||||
** 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()
|
||||
{
|
||||
/* 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 */
|
||||
if (_pd_id && _pd_id != pd_id) return -1;
|
||||
|
||||
/* denote configuration for start method */
|
||||
_pd_id = pd_id;
|
||||
_main_thread = main_thread;
|
||||
_pd_id = pd_id;
|
||||
_main_thread = main_thread;
|
||||
_address_space = address_space;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
/*
|
||||
* Must be initialized by the startup code,
|
||||
@ -25,7 +26,7 @@ extern Genode::addr_t __core_pd_sel;
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
class Platform_pd
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
private:
|
||||
|
||||
@ -88,6 +89,17 @@ namespace Genode {
|
||||
* \return PD selector
|
||||
*/
|
||||
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/pager.h>
|
||||
|
||||
/* core includes */
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Platform_pd;
|
||||
@ -98,6 +101,11 @@ namespace Genode {
|
||||
*/
|
||||
Thread_state state();
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/************************
|
||||
** 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)
|
||||
:
|
||||
_pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)),
|
||||
|
@ -14,7 +14,9 @@
|
||||
#ifndef _CORE__INCLUDE__PLATFORM_PD_H_
|
||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Okl4 { extern "C" {
|
||||
#include <l4/types.h>
|
||||
@ -23,7 +25,7 @@ namespace Okl4 { extern "C" {
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
class Platform_pd
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
private:
|
||||
|
||||
@ -185,6 +187,13 @@ namespace Genode {
|
||||
void space_pager(Platform_thread *pd);
|
||||
|
||||
int pd_id() const { return _pd_id; }
|
||||
|
||||
|
||||
/*****************************
|
||||
** Address-space interface **
|
||||
*****************************/
|
||||
|
||||
void flush(addr_t, size_t);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <platform_pd.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
@ -110,6 +111,11 @@ namespace Genode {
|
||||
*/
|
||||
Thread_state state();
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/************************
|
||||
** 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)
|
||||
: _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)
|
||||
: _thread_id(thread_id), _l4_thread_id(L4_nilthread), _platform_pd(0),
|
||||
_priority(prio), _pager(0)
|
||||
|
@ -17,74 +17,13 @@
|
||||
/* core includes */
|
||||
#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 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)
|
||||
{
|
||||
L4_ThreadId_t tid = { raw : badge() };
|
||||
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();
|
||||
Locked_ptr<Address_space> locked_address_space(_address_space);
|
||||
|
||||
if (verbose_unmap)
|
||||
printf("RM client %p (%lx) unmap [%lx,%lx)\n",
|
||||
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--;
|
||||
}
|
||||
if (locked_address_space.is_valid())
|
||||
locked_address_space->flush(virt_base, size);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define _CORE__INCLUDE__PLATFORM_PD_H_
|
||||
|
||||
#include <platform_thread.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Pistachio {
|
||||
#include <l4/types.h>
|
||||
@ -23,7 +24,7 @@ namespace Pistachio {
|
||||
namespace Genode {
|
||||
|
||||
class Platform_thread;
|
||||
class Platform_pd
|
||||
class Platform_pd : public Address_space
|
||||
{
|
||||
private:
|
||||
|
||||
@ -216,6 +217,17 @@ namespace Genode {
|
||||
int assign_parent(Native_capability parent) { return 0; }
|
||||
|
||||
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 */
|
||||
#include <platform_pd.h>
|
||||
#include <address_space.h>
|
||||
|
||||
/* Pistachio includes */
|
||||
namespace Pistachio {
|
||||
@ -114,6 +115,11 @@ namespace Genode {
|
||||
*/
|
||||
Thread_state state();
|
||||
|
||||
/**
|
||||
* Return the address space to which the thread is bound
|
||||
*/
|
||||
Weak_ptr<Address_space> address_space();
|
||||
|
||||
|
||||
/************************
|
||||
** 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)
|
||||
: _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 Invalid_thread : public Exception { };
|
||||
class Unbound_thread : public Exception { };
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
@ -156,6 +157,7 @@ namespace Genode {
|
||||
* \param thread thread that will be paged
|
||||
* \throw Invalid_thread
|
||||
* \throw Out_of_metadata
|
||||
* \throw Unbound_thread
|
||||
* \return capability to be used for handling page faults
|
||||
*
|
||||
* This method must be called at least once to establish a valid
|
||||
|
33
base/src/core/include/address_space.h
Normal file
33
base/src/core/include/address_space.h
Normal file
@ -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 <dataspace_component.h>
|
||||
#include <util.h>
|
||||
#include <address_space.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
|
||||
class Dataspace_component;
|
||||
class Rm_session_component;
|
||||
class Rm_client;
|
||||
@ -185,6 +185,10 @@ namespace Genode {
|
||||
class Rm_client : public Pager_object, public Rm_member, public Rm_faulter,
|
||||
public List<Rm_client>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Weak_ptr<Address_space> _address_space;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -194,8 +198,11 @@ namespace Genode {
|
||||
* \param badge pager-object badge used of identifying the client
|
||||
* when a page-fault occurs
|
||||
*/
|
||||
Rm_client(Rm_session_component *session, unsigned long badge) :
|
||||
Pager_object(badge), Rm_member(session), Rm_faulter(this) { }
|
||||
Rm_client(Rm_session_component *session, unsigned long badge,
|
||||
Weak_ptr<Address_space> &address_space)
|
||||
:
|
||||
Pager_object(badge), Rm_member(session), Rm_faulter(this),
|
||||
_address_space(address_space) { }
|
||||
|
||||
int pager(Ipc_pager &pager);
|
||||
|
||||
@ -203,6 +210,11 @@ namespace Genode {
|
||||
* Flush memory mappings for the specified virtual address range
|
||||
*/
|
||||
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
|
||||
* 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-
|
||||
@ -563,6 +565,23 @@ void Rm_session_component::detach(Local_addr local_addr)
|
||||
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(),
|
||||
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)
|
||||
{
|
||||
unsigned long badge;
|
||||
Weak_ptr<Address_space> address_space;
|
||||
|
||||
{
|
||||
/* 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 */
|
||||
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 */
|
||||
Lock::Guard lock_guard(_lock);
|
||||
|
||||
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 (Cpu_session::Thread_creation_failed) { throw Out_of_metadata(); }
|
||||
catch (Thread_base::Stack_alloc_failed) { throw Out_of_metadata(); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user