From d86bf3db641ce014a500a8dd09e06cdf92a2571f Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Wed, 18 Sep 2013 13:12:32 +0200 Subject: [PATCH] hw: destruct protection domains ref #589 --- base-hw/include/kernel/syscalls.h | 32 +++++++++++----- base-hw/src/core/include/platform_pd.h | 23 +++++++++--- base-hw/src/core/kernel.cc | 51 +++++++++++++++++++++----- base-hw/src/core/kernel/pd.h | 5 +++ base-hw/src/core/platform_pd.cc | 16 +++----- base-hw/src/core/rm_session_support.cc | 17 +-------- 6 files changed, 94 insertions(+), 50 deletions(-) diff --git a/base-hw/include/kernel/syscalls.h b/base-hw/include/kernel/syscalls.h index 123da1bc8b..827f6ca04f 100644 --- a/base-hw/include/kernel/syscalls.h +++ b/base-hw/include/kernel/syscalls.h @@ -57,11 +57,12 @@ namespace Kernel REPLY = 9, WAIT_FOR_REQUEST = 10, - /* management of resource protection-domains */ + /* management of protection domains */ SET_PAGER = 11, UPDATE_PD = 12, UPDATE_REGION = 32, NEW_PD = 13, + KILL_PD = 34, /* interrupt handling */ 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 - * that is thereupon allocated to the kernel - * \param pd core local Platform_pd object + * \param p appropriate memory donation for the kernel object + * \param pd core local Platform_pd object * - * \retval >0 ID of the new PD - * \retval 0 if no new PD was created + * \retval >0 kernel name of the new protection domain + * \retval 0 failed * * Restricted to core threads. Regaining of the supplied memory is not * supported by now. */ - inline int new_pd(void * const dst, Platform_pd * const pd) { - return syscall(NEW_PD, (Syscall_arg)dst, (Syscall_arg)pd); } + inline unsigned new_pd(void * const dst, Platform_pd * const 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 diff --git a/base-hw/src/core/include/platform_pd.h b/base-hw/src/core/include/platform_pd.h index 95c14e8893..1e2d208d07 100644 --- a/base-hw/src/core/include/platform_pd.h +++ b/base-hw/src/core/include/platform_pd.h @@ -31,6 +31,18 @@ namespace Kernel 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; /** @@ -38,11 +50,11 @@ namespace Genode */ class Platform_pd : public Address_space { - unsigned _id; /* ID of our kernel object */ - Native_capability _parent; /* our parent interface */ - Native_thread_id _main_thread; /* the first thread that gets - * executed in this PD */ - char const * const _label; /* PD-connection label */ + unsigned _id; + Native_capability _parent; + Native_thread_id _main_thread; + char const * const _label; + Tlb * _tlb; public: @@ -67,6 +79,7 @@ namespace Genode PERR("failed to create kernel object"); throw Root::Unavailable(); } + _tlb = (Tlb *)kernel_pd; } /** diff --git a/base-hw/src/core/kernel.cc b/base-hw/src/core/kernel.cc index 5be3915ae8..2c36fdd5c6 100644 --- a/base-hw/src/core/kernel.cc +++ b/base-hw/src/core/kernel.cc @@ -238,19 +238,50 @@ namespace Kernel void do_new_pd(Thread * const user) { /* check permissions */ - assert(user->pd_id() == core_id()); - - /* create TLB and PD */ - void * dst = (void *)user->user_arg_1(); - Tlb * const tlb = new (dst) Tlb(); - dst = (void *)((addr_t)dst + sizeof(Tlb)); - Pd * const pd = new (dst) Pd(tlb, (Platform_pd *)user->user_arg_2()); - - /* return success */ + if (user->pd_id() != core_id()) { + PERR("not entitled to create protection domain"); + user->user_arg_0(0); + return; + } + /* create translation lookaside buffer and protection domain */ + void * p = (void *)user->user_arg_1(); + Tlb * const tlb = new (p) Tlb(); + 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()); } + /** + * 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' */ @@ -288,7 +319,6 @@ namespace Kernel thread->~Thread(); } - /** * 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 RUN_VM: do_run_vm(user); return; case PAUSE_VM: do_pause_vm(user); return; + case KILL_PD: do_kill_pd(user); return; default: PERR("invalid syscall"); user->crash(); diff --git a/base-hw/src/core/kernel/pd.h b/base-hw/src/core/kernel/pd.h index a0aaa8cd25..662d8d35fb 100644 --- a/base-hw/src/core/kernel/pd.h +++ b/base-hw/src/core/kernel/pd.h @@ -184,6 +184,11 @@ class Kernel::Pd : public Object } } + /** + * Destructor + */ + ~Pd() { } + /** * Let the CPU context 'c' join the PD */ diff --git a/base-hw/src/core/platform_pd.cc b/base-hw/src/core/platform_pd.cc index ca76841a46..8b9ce6995e 100644 --- a/base-hw/src/core/platform_pd.cc +++ b/base-hw/src/core/platform_pd.cc @@ -16,18 +16,12 @@ using namespace Genode; - -/***************** - ** Platform PD ** - *****************/ - Platform_pd::~Platform_pd() { - /* - * FIXME: throwing exceptions is not declared for - * 'Pd_root::close' wich is why we can only - * print an error - */ - PERR("not implemented"); + _tlb->remove_region(platform()->vm_start(), platform()->vm_size()); + regain_ram_from_tlb(_tlb); + if (Kernel::kill_pd(_id)) { + PERR("failed to destruct protection domain at kernel"); + } } diff --git a/base-hw/src/core/rm_session_support.cc b/base-hw/src/core/rm_session_support.cc index 3634d7b2fd..574410efec 100644 --- a/base-hw/src/core/rm_session_support.cc +++ b/base-hw/src/core/rm_session_support.cc @@ -17,31 +17,18 @@ /* core includes */ #include #include +#include #include #include 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 ** ***************/ - -void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size) +void Rm_client::unmap(addr_t, addr_t virt_base, size_t size) { /* get software TLB of the thread that we serve */ Platform_thread * const pt = Kernel::get_thread(badge());