hw: destruct protection domains

ref #589
This commit is contained in:
Martin Stein 2013-09-18 13:12:32 +02:00 committed by Norman Feske
parent a4f52bec19
commit d86bf3db64
6 changed files with 94 additions and 50 deletions

View File

@ -57,11 +57,12 @@ namespace Kernel
REPLY = 9, REPLY = 9,
WAIT_FOR_REQUEST = 10, WAIT_FOR_REQUEST = 10,
/* management of resource protection-domains */ /* management of protection domains */
SET_PAGER = 11, SET_PAGER = 11,
UPDATE_PD = 12, UPDATE_PD = 12,
UPDATE_REGION = 32, UPDATE_REGION = 32,
NEW_PD = 13, NEW_PD = 13,
KILL_PD = 34,
/* interrupt handling */ /* interrupt handling */
ALLOCATE_IRQ = 14, ALLOCATE_IRQ = 14,
@ -144,21 +145,34 @@ namespace Kernel
/** /**
* Create a new PD * Create a protection domain
* *
* \param dst physical base of an appropriate portion of memory * \param p appropriate memory donation for the kernel object
* that is thereupon allocated to the kernel
* \param pd core local Platform_pd object * \param pd core local Platform_pd object
* *
* \retval >0 ID of the new PD * \retval >0 kernel name of the new protection domain
* \retval 0 if no new PD was created * \retval 0 failed
* *
* Restricted to core threads. Regaining of the supplied memory is not * Restricted to core threads. Regaining of the supplied memory is not
* supported by now. * supported by now.
*/ */
inline int new_pd(void * const dst, Platform_pd * const pd) { inline unsigned new_pd(void * const dst, Platform_pd * const pd)
return syscall(NEW_PD, (Syscall_arg)dst, (Syscall_arg)pd); } {
return syscall(NEW_PD, (Syscall_arg)dst, (Syscall_arg)pd);
}
/**
* Destruct a protection domain
*
* \param pd kernel name of the targeted protection domain
*
* \retval 0 succeeded
* \retval -1 failed
*/
inline int kill_pd(unsigned const pd)
{
return syscall(KILL_PD, pd);
}
/** /**
* Propagate changes in PD configuration * Propagate changes in PD configuration

View File

@ -31,6 +31,18 @@ namespace Kernel
namespace Genode namespace Genode
{ {
/**
* Regain all administrative memory that isn't used anymore by 'tlb'
*/
inline void regain_ram_from_tlb(Tlb * tlb)
{
size_t s;
void * base;
while (tlb->regain_memory(base, s)) {
platform()->ram_alloc()->free(base, s);
}
}
class Platform_thread; class Platform_thread;
/** /**
@ -38,11 +50,11 @@ namespace Genode
*/ */
class Platform_pd : public Address_space class Platform_pd : public Address_space
{ {
unsigned _id; /* ID of our kernel object */ unsigned _id;
Native_capability _parent; /* our parent interface */ Native_capability _parent;
Native_thread_id _main_thread; /* the first thread that gets Native_thread_id _main_thread;
* executed in this PD */ char const * const _label;
char const * const _label; /* PD-connection label */ Tlb * _tlb;
public: public:
@ -67,6 +79,7 @@ namespace Genode
PERR("failed to create kernel object"); PERR("failed to create kernel object");
throw Root::Unavailable(); throw Root::Unavailable();
} }
_tlb = (Tlb *)kernel_pd;
} }
/** /**

View File

@ -238,19 +238,50 @@ namespace Kernel
void do_new_pd(Thread * const user) void do_new_pd(Thread * const user)
{ {
/* check permissions */ /* check permissions */
assert(user->pd_id() == core_id()); if (user->pd_id() != core_id()) {
PERR("not entitled to create protection domain");
/* create TLB and PD */ user->user_arg_0(0);
void * dst = (void *)user->user_arg_1(); return;
Tlb * const tlb = new (dst) Tlb(); }
dst = (void *)((addr_t)dst + sizeof(Tlb)); /* create translation lookaside buffer and protection domain */
Pd * const pd = new (dst) Pd(tlb, (Platform_pd *)user->user_arg_2()); void * p = (void *)user->user_arg_1();
Tlb * const tlb = new (p) Tlb();
/* return success */ p = (void *)((addr_t)p + sizeof(Tlb));
Pd * const pd = new (p) Pd(tlb, (Platform_pd *)user->user_arg_2());
user->user_arg_0(pd->id()); user->user_arg_0(pd->id());
} }
/**
* Do specific syscall for 'user', for details see 'syscall.h'
*/
void do_kill_pd(Thread * const user)
{
/* check permissions */
if (user->pd_id() != core_id()) {
PERR("not entitled to destruct protection domain");
user->user_arg_0(-1);
return;
}
/* lookup protection domain */
unsigned id = user->user_arg_1();
Pd * const pd = Pd::pool()->object(id);
if (!pd) {
PERR("unknown protection domain");
user->user_arg_0(-1);
return;
}
/* destruct translation lookaside buffer and protection domain */
Tlb * const tlb = pd->tlb();
pd->~Pd();
tlb->~Tlb();
/* clean up buffers of memory management */
Cpu::flush_tlb_by_pid(pd->id());
user->user_arg_0(0);
}
/** /**
* Do specific syscall for 'user', for details see 'syscall.h' * Do specific syscall for 'user', for details see 'syscall.h'
*/ */
@ -288,7 +319,6 @@ namespace Kernel
thread->~Thread(); thread->~Thread();
} }
/** /**
* Do specific syscall for 'user', for details see 'syscall.h' * Do specific syscall for 'user', for details see 'syscall.h'
*/ */
@ -866,6 +896,7 @@ namespace Kernel
case NEW_VM: do_new_vm(user); return; case NEW_VM: do_new_vm(user); return;
case RUN_VM: do_run_vm(user); return; case RUN_VM: do_run_vm(user); return;
case PAUSE_VM: do_pause_vm(user); return; case PAUSE_VM: do_pause_vm(user); return;
case KILL_PD: do_kill_pd(user); return;
default: default:
PERR("invalid syscall"); PERR("invalid syscall");
user->crash(); user->crash();

View File

@ -184,6 +184,11 @@ class Kernel::Pd : public Object<Pd, MAX_PDS>
} }
} }
/**
* Destructor
*/
~Pd() { }
/** /**
* Let the CPU context 'c' join the PD * Let the CPU context 'c' join the PD
*/ */

View File

@ -16,18 +16,12 @@
using namespace Genode; using namespace Genode;
/*****************
** Platform PD **
*****************/
Platform_pd::~Platform_pd() Platform_pd::~Platform_pd()
{ {
/* _tlb->remove_region(platform()->vm_start(), platform()->vm_size());
* FIXME: throwing exceptions is not declared for regain_ram_from_tlb(_tlb);
* 'Pd_root::close' wich is why we can only if (Kernel::kill_pd(_id)) {
* print an error PERR("failed to destruct protection domain at kernel");
*/ }
PERR("not implemented");
} }

View File

@ -17,31 +17,18 @@
/* core includes */ /* core includes */
#include <rm_session_component.h> #include <rm_session_component.h>
#include <platform.h> #include <platform.h>
#include <platform_pd.h>
#include <platform_thread.h> #include <platform_thread.h>
#include <tlb.h> #include <tlb.h>
using namespace Genode; using namespace Genode;
/**
* Try to regain administrative memory that isn't used anymore from 'tlb'
*/
static void regain_ram_from_tlb(Tlb * tlb)
{
size_t s;
void * base;
while (tlb->regain_memory(base, s)) {
platform()->ram_alloc()->free(base, s);
}
}
/*************** /***************
** Rm_client ** ** Rm_client **
***************/ ***************/
void Rm_client::unmap(addr_t, addr_t virt_base, size_t size)
void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size)
{ {
/* get software TLB of the thread that we serve */ /* get software TLB of the thread that we serve */
Platform_thread * const pt = Kernel::get_thread(badge()); Platform_thread * const pt = Kernel::get_thread(badge());