From 5a05521e0f5cc2e540dfd136a01c4550f556ef25 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 12 May 2015 12:48:03 +0200 Subject: [PATCH] sel4: bootstrap of init and page-fault handling --- .../base-sel4/include/pd_session/connection.h | 37 ++++ repos/base-sel4/lib/mk/base-common.inc | 3 +- repos/base-sel4/lib/mk/core.mk | 3 +- repos/base-sel4/src/base/ipc/pager.cc | 44 ---- repos/base-sel4/src/base/pager/pager.cc | 61 ------ .../src/core/include/install_mapping.h | 26 +++ .../src/core/include/kernel_object.h | 7 + repos/base-sel4/src/core/include/map_local.h | 2 +- .../base-sel4/src/core/include/platform_pd.h | 50 +++++ .../src/core/include/platform_thread.h | 35 ++- .../base-sel4/src/core/include/thread_sel4.h | 110 ++++++++++ repos/base-sel4/src/core/include/vm_space.h | 18 +- repos/base-sel4/src/core/pager.cc | 202 ++++++++++++++++++ repos/base-sel4/src/core/platform.cc | 4 +- repos/base-sel4/src/core/platform_pd.cc | 89 +++++++- repos/base-sel4/src/core/platform_thread.cc | 114 +++++++++- repos/base-sel4/src/core/thread_start.cc | 95 ++------ 17 files changed, 692 insertions(+), 208 deletions(-) create mode 100644 repos/base-sel4/include/pd_session/connection.h delete mode 100644 repos/base-sel4/src/base/ipc/pager.cc delete mode 100644 repos/base-sel4/src/base/pager/pager.cc create mode 100644 repos/base-sel4/src/core/include/install_mapping.h create mode 100644 repos/base-sel4/src/core/include/thread_sel4.h create mode 100644 repos/base-sel4/src/core/pager.cc diff --git a/repos/base-sel4/include/pd_session/connection.h b/repos/base-sel4/include/pd_session/connection.h new file mode 100644 index 0000000000..ca210a62ab --- /dev/null +++ b/repos/base-sel4/include/pd_session/connection.h @@ -0,0 +1,37 @@ +/* + * \brief Connection to PD service + * \author Norman Feske + * \date 2008-08-22 + */ + +/* + * Copyright (C) 2008-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 _INCLUDE__PD_SESSION__CONNECTION_H_ +#define _INCLUDE__PD_SESSION__CONNECTION_H_ + +#include +#include + +namespace Genode { struct Pd_connection; } + + +struct Genode::Pd_connection : Connection, Pd_session_client +{ + /** + * Constructor + * + * \param label session label + */ + Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0) + : + Connection(session("ram_quota=64K, label=\"%s\"", label)), + Pd_session_client(cap()) + { } +}; + +#endif /* _INCLUDE__PD_SESSION__CONNECTION_H_ */ diff --git a/repos/base-sel4/lib/mk/base-common.inc b/repos/base-sel4/lib/mk/base-common.inc index 3962cd305b..6c91736fc3 100644 --- a/repos/base-sel4/lib/mk/base-common.inc +++ b/repos/base-sel4/lib/mk/base-common.inc @@ -6,7 +6,7 @@ LIBS += cxx startup syscall -SRC_CC += ipc/ipc.cc ipc/pager.cc +SRC_CC += ipc/ipc.cc SRC_CC += avl_tree/avl_tree.cc SRC_CC += allocator/slab.cc SRC_CC += allocator/allocator_avl.cc @@ -18,7 +18,6 @@ SRC_CC += elf/elf_binary.cc SRC_CC += lock/lock.cc SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc SRC_CC += server/server.cc server/common.cc -SRC_CC += pager/pager.cc pager/common.cc SRC_CC += thread/thread.cc SRC_CC += thread/trace.cc SRC_CC += thread/myself.cc diff --git a/repos/base-sel4/lib/mk/core.mk b/repos/base-sel4/lib/mk/core.mk index cd1d61af4e..bdea0a7b60 100644 --- a/repos/base-sel4/lib/mk/core.mk +++ b/repos/base-sel4/lib/mk/core.mk @@ -29,7 +29,8 @@ SRC_CC += \ core_mem_alloc.cc \ dump_alloc.cc \ context_area.cc \ - capability_space.cc + capability_space.cc \ + pager.cc LIBS += core_printf base-common syscall diff --git a/repos/base-sel4/src/base/ipc/pager.cc b/repos/base-sel4/src/base/ipc/pager.cc deleted file mode 100644 index 3a07a45602..0000000000 --- a/repos/base-sel4/src/base/ipc/pager.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * \brief Pager support for seL4 - * \author Norman Feske - * \date 2014-10-14 - */ - -/* - * Copyright (C) 2014 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. - */ - -/* Genode includes */ -#include -#include - -using namespace Genode; - - -/*************** - ** IPC pager ** - ***************/ - -void Ipc_pager::wait_for_fault() -{ - PDBG("not implemented"); -} - - -void Ipc_pager::reply_and_wait_for_fault() -{ - PDBG("not implemented"); -} - - -void Ipc_pager::acknowledge_wakeup() -{ - PDBG("not implemented"); -} - - -Ipc_pager::Ipc_pager() { } - diff --git a/repos/base-sel4/src/base/pager/pager.cc b/repos/base-sel4/src/base/pager/pager.cc deleted file mode 100644 index 8da5dc17d9..0000000000 --- a/repos/base-sel4/src/base/pager/pager.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* - * \brief Pager framework - * \author Norman Feske - * \date 2015-05-01 - */ - -/* - * Copyright (C) 2015 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. - */ - -/* Genode includes */ -#include -#include - -using namespace Genode; - - -/********************** - ** Pager activation ** - **********************/ - -void Pager_activation_base::entry() -{ - Ipc_pager pager; - _cap = pager; - _cap_valid.unlock(); - - while (1) { - - PDBG("not implemented"); - sleep_forever(); - } -} - - -/********************** - ** Pager entrypoint ** - **********************/ - -Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) -: _activation(a) -{ _activation->ep(this); } - - -void Pager_entrypoint::dissolve(Pager_object *obj) -{ - remove_locked(obj); -} - - -Pager_capability Pager_entrypoint::manage(Pager_object *obj) -{ - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - - PDBG("not implemented"); - return Pager_capability(); -} diff --git a/repos/base-sel4/src/core/include/install_mapping.h b/repos/base-sel4/src/core/include/install_mapping.h new file mode 100644 index 0000000000..ae8002e7f8 --- /dev/null +++ b/repos/base-sel4/src/core/include/install_mapping.h @@ -0,0 +1,26 @@ +/* + * \brief Interface for mapping memory to the VM space of a pager object + * \author Norman Feske + * \date 2015-05-12 + */ + +/* + * Copyright (C) 2015 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__INSTALL_MAPPING_H_ +#define _CORE__INCLUDE__INSTALL_MAPPING_H_ + +/* Genode includes */ +#include +#include + +namespace Genode { + + void install_mapping(Mapping const &mapping, unsigned long pager_object_badge); +} + +#endif /* _CORE__INCLUDE__INSTALL_MAPPING_H_ */ diff --git a/repos/base-sel4/src/core/include/kernel_object.h b/repos/base-sel4/src/core/include/kernel_object.h index 7d16e04436..87d1f545e1 100644 --- a/repos/base-sel4/src/core/include/kernel_object.h +++ b/repos/base-sel4/src/core/include/kernel_object.h @@ -51,6 +51,13 @@ namespace Kernel_object { }; + struct Page_directory + { + enum { SEL4_TYPE = seL4_IA32_PageDirectoryObject, SIZE_LOG2 = 12 }; + static char const *name() { return "page directory"; } + }; + + /** * Create kernel object from untyped memory * diff --git a/repos/base-sel4/src/core/include/map_local.h b/repos/base-sel4/src/core/include/map_local.h index e89c4ac154..3a2a80920f 100644 --- a/repos/base-sel4/src/core/include/map_local.h +++ b/repos/base-sel4/src/core/include/map_local.h @@ -19,7 +19,7 @@ /* core includes */ #include -#include +#include namespace Genode { diff --git a/repos/base-sel4/src/core/include/platform_pd.h b/repos/base-sel4/src/core/include/platform_pd.h index 9cfd131f13..b004455797 100644 --- a/repos/base-sel4/src/core/include/platform_pd.h +++ b/repos/base-sel4/src/core/include/platform_pd.h @@ -20,6 +20,7 @@ /* core includes */ #include #include +#include namespace Genode { class Platform_pd; } @@ -27,6 +28,38 @@ namespace Genode { class Platform_pd; } class Genode::Platform_pd : public Address_space { + private: + + unsigned const _id; /* used as index in top-level CNode */ + + Page_table_registry _page_table_registry; + + unsigned const _vm_pad_cnode_sel; + + unsigned const _vm_cnode_sel; + + unsigned const _page_directory_sel; + Untyped_address _init_page_directory(); + Untyped_address const _page_directory = _init_page_directory(); + + Vm_space _vm_space; + + unsigned const _cspace_cnode_sel; + + Cnode _cspace_cnode; + + enum { CSPACE_SIZE_LOG2 = 12 }; + + /* + * Allocator for core-managed selectors within the PD's CSpace + */ + enum { NUM_CORE_MANAGED_SELECTORS_LOG2 = 10 }; + + struct Sel_alloc : Bit_allocator<1 << NUM_CORE_MANAGED_SELECTORS_LOG2> { }; + + Sel_alloc _sel_alloc; + Lock _sel_alloc_lock; + public: /** @@ -66,6 +99,23 @@ class Genode::Platform_pd : public Address_space *****************************/ void flush(addr_t, size_t) { PDBG("not implemented"); } + + + /***************************** + ** seL4-specific interface ** + *****************************/ + + unsigned alloc_sel(); + + void free_sel(unsigned sel); + + Cnode &cspace_cnode() { return _cspace_cnode; } + + unsigned page_directory_sel() const { return _page_directory_sel; } + + size_t cspace_size_log2() { return CSPACE_SIZE_LOG2; } + + void install_mapping(Mapping const &mapping); }; #endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */ diff --git a/repos/base-sel4/src/core/include/platform_thread.h b/repos/base-sel4/src/core/include/platform_thread.h index 436f46347e..2457ea5789 100644 --- a/repos/base-sel4/src/core/include/platform_thread.h +++ b/repos/base-sel4/src/core/include/platform_thread.h @@ -18,9 +18,13 @@ #include #include #include +#include +#include /* core includes */ #include +#include +#include namespace Genode { @@ -29,17 +33,27 @@ namespace Genode { } - -class Genode::Platform_thread +class Genode::Platform_thread : public List::Element { private: Pager_object *_pager = nullptr; - Weak_ptr _address_space; + String<128> _name; + + Thread_info _info; + + unsigned const _pager_obj_sel; + + /* + * Allocated when the thread is started + */ + unsigned _fault_handler_sel = 0; friend class Platform_pd; + Platform_pd *_pd = nullptr; + public: /** @@ -114,11 +128,7 @@ class Genode::Platform_thread /** * Return identification of thread when faulting */ - unsigned long pager_object_badge() const - { - PDBG("not implemented"); - return 0; - } + unsigned long pager_object_badge() const { return _pager_obj_sel; } /** * Set the executing CPU for this thread @@ -139,6 +149,15 @@ class Genode::Platform_thread * Get thread name */ const char *name() const { return "noname"; } + + + /***************************** + ** seL4-specific interface ** + *****************************/ + + unsigned tcb_sel() const { return _info.tcb_sel; } + + void install_mapping(Mapping const &mapping); }; #endif /* _CORE__INCLUDE__PLATFORM_THREAD_H_ */ diff --git a/repos/base-sel4/src/core/include/thread_sel4.h b/repos/base-sel4/src/core/include/thread_sel4.h new file mode 100644 index 0000000000..f688d560ee --- /dev/null +++ b/repos/base-sel4/src/core/include/thread_sel4.h @@ -0,0 +1,110 @@ +/* + * \brief Utilities fo thread creation on seL4 + * \author Norman Feske + * \date 2015-05-12 + * + * This file is used by both the core-specific implementation of the Thread API + * and the platform-thread implementation for managing threads outside of core. + */ + +/* + * Copyright (C) 2015 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__THREAD_SEL4_H_ +#define _CORE__INCLUDE__THREAD_SEL4_H_ + +/* Genode includes */ +#include + +/* base-internal includes */ +#include + +/* core includes */ +#include +#include + +namespace Genode { + + struct Thread_info + { + unsigned tcb_sel = 0; + unsigned ep_sel = 0; + + addr_t ipc_buffer_phys = 0; + + Thread_info() { } + + inline void init(addr_t const utcb_virt_addr); + }; + + /** + * Set register values for the instruction pointer and stack pointer and + * start the seL4 thread + */ + static inline void start_sel4_thread(unsigned tcb_sel, addr_t ip, addr_t sp); +}; + + +void Genode::Thread_info::init(addr_t const utcb_virt_addr) +{ + Platform &platform = *platform_specific(); + Range_allocator &phys_alloc = *platform.ram_alloc(); + + /* create IPC buffer of one page */ + size_t const ipc_buffer_size_log2 = get_page_size_log2(); + Untyped_address ipc_buffer = + Untyped_memory::alloc_log2(phys_alloc, ipc_buffer_size_log2); + + ipc_buffer_phys = ipc_buffer.phys(); + + Untyped_memory::convert_to_page_frames(ipc_buffer.phys(), 1); + + /* allocate TCB within core's CNode */ + tcb_sel = platform.alloc_core_sel(); + Kernel_object::create(phys_alloc, + platform.core_cnode().sel(), + tcb_sel); + + /* allocate synchronous endpoint within core's CNode */ + ep_sel = platform.alloc_core_sel(); + Kernel_object::create(phys_alloc, + platform.core_cnode().sel(), + ep_sel); + /* assign IPC buffer to thread */ + { + /* determine page frame selector of the allocated IPC buffer */ + unsigned ipc_buffer_sel = Untyped_memory::frame_sel(ipc_buffer.phys()); + + int const ret = seL4_TCB_SetIPCBuffer(tcb_sel, utcb_virt_addr, + ipc_buffer_sel); + ASSERT(ret == 0); + } + + /* set scheduling priority */ + enum { PRIORITY_MAX = 0xff }; + seL4_TCB_SetPriority(tcb_sel, PRIORITY_MAX); +} + + +void Genode::start_sel4_thread(unsigned tcb_sel, addr_t ip, addr_t sp) +{ + /* set register values for the instruction pointer and stack pointer */ + seL4_UserContext regs; + Genode::memset(®s, 0, sizeof(regs)); + size_t const num_regs = sizeof(regs)/sizeof(seL4_Word); + + regs.eip = ip; + regs.esp = sp; + regs.gs = IPCBUF_GDT_SELECTOR; + + int const ret = seL4_TCB_WriteRegisters(tcb_sel, false, 0, num_regs, ®s); + ASSERT(ret == 0); + + seL4_TCB_Resume(tcb_sel); +} + +#endif /* _CORE__INCLUDE__THREAD_SEL4_H_ */ diff --git a/repos/base-sel4/src/core/include/vm_space.h b/repos/base-sel4/src/core/include/vm_space.h index 8ba286ad88..0e2d1c241b 100644 --- a/repos/base-sel4/src/core/include/vm_space.h +++ b/repos/base-sel4/src/core/include/vm_space.h @@ -31,6 +31,7 @@ class Genode::Vm_space Page_table_registry &_page_table_registry; unsigned const _id; + unsigned const _pd_sel; Range_allocator &_phys_alloc; @@ -57,6 +58,8 @@ class Genode::Vm_space */ Bit_allocator<1UL << NUM_VM_SEL_LOG2> _sel_alloc; + Lock _lock; + /** * Return selector for a capability slot within '_vm_cnode' */ @@ -83,7 +86,7 @@ class Genode::Vm_space */ { seL4_IA32_Page const service = _idx_to_sel(pte_idx); - seL4_IA32_PageDirectory const pd = seL4_CapInitThreadPD; + seL4_IA32_PageDirectory const pd = _pd_sel; seL4_Word const vaddr = to_virt; seL4_CapRights const rights = seL4_AllRights; seL4_IA32_VMAttributes const attr = seL4_IA32_Default_VMAttributes; @@ -110,7 +113,7 @@ class Genode::Vm_space void _map_page_table(unsigned pt_sel, addr_t to_virt) { seL4_IA32_PageTable const service = pt_sel; - seL4_IA32_PageDirectory const pd = seL4_CapInitThreadPD; + seL4_IA32_PageDirectory const pd = _pd_sel; seL4_Word const vaddr = to_virt; seL4_IA32_VMAttributes const attr = seL4_IA32_Default_VMAttributes; @@ -152,6 +155,7 @@ class Genode::Vm_space /** * Constructor * + * \param pd_sel selector for page directory * \param vm_pad_cnode_sel selector for the (2nd-level) VM pad CNode * \param vm_cnode_sel selector for the (3rd-level) VM CNode * \param phys_alloc backing store for the CNodes @@ -160,7 +164,8 @@ class Genode::Vm_space * \param page_table_registry association of VM CNode selectors with * with virtual addresses */ - Vm_space(unsigned vm_pad_cnode_sel, + Vm_space(unsigned pd_sel, + unsigned vm_pad_cnode_sel, unsigned vm_cnode_sel, Range_allocator &phys_alloc, Cnode &top_level_cnode, @@ -169,7 +174,8 @@ class Genode::Vm_space unsigned id, Page_table_registry &page_table_registry) : - _page_table_registry(page_table_registry), _id(id), + _page_table_registry(page_table_registry), + _id(id), _pd_sel(pd_sel), _phys_alloc(phys_alloc), _top_level_cnode(top_level_cnode), _phys_cnode(phys_cnode), @@ -188,6 +194,8 @@ class Genode::Vm_space void map(addr_t from_phys, addr_t to_virt, size_t num_pages) { + Lock::Guard guard(_lock); + /* check if we need to add a page table to core's VM space */ if (!_page_table_registry.has_page_table_at(to_virt)) _alloc_and_map_page_table(to_virt); @@ -200,6 +208,8 @@ class Genode::Vm_space void unmap(addr_t virt, size_t num_pages) { + Lock::Guard guard(_lock); + for (size_t i = 0; i < num_pages; i++) { off_t const offset = i << get_page_size_log2(); _unmap_page(virt + offset); diff --git a/repos/base-sel4/src/core/pager.cc b/repos/base-sel4/src/core/pager.cc new file mode 100644 index 0000000000..fa8d357106 --- /dev/null +++ b/repos/base-sel4/src/core/pager.cc @@ -0,0 +1,202 @@ +/* + * \brief Pager + * \author Norman Feske + * \date 2015-05-01 + */ + +/* + * Copyright (C) 2015 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. + */ + +/* Genode includes */ +#include +#include + +/* core includes */ +#include +#include + +/* base-internal includes */ +#include + +/* seL4 includes */ +#include +#include + +using namespace Genode; + +static bool const verbose = true; + + +struct Fault_info +{ + addr_t ip = 0; + addr_t pf = 0; + bool write = 0; + + Fault_info(seL4_MessageInfo_t msg_info) + : + ip(seL4_GetMR(0)), + pf(seL4_GetMR(1)), + write(seL4_Fault_isWriteFault(seL4_GetMR(3))) + { + if (verbose) + PINF("PF: ip=0x%lx, pf=0x%lx, write=%d", ip, pf, write); + } +}; + + +/*************** + ** IPC pager ** + ***************/ + +void Ipc_pager::wait_for_fault() +{ + _last = 0; + reply_and_wait_for_fault(); +} + + +void Ipc_pager::reply_and_wait_for_fault() +{ + if (_last) + install_mapping(_reply_mapping, _last); + + seL4_Word badge = Rpc_obj_key::INVALID; + + seL4_MessageInfo_t page_fault_msg_info; + + if (_last) { + + seL4_MessageInfo_t const reply_msg = seL4_MessageInfo_new(0, 0, 0, 0); + + page_fault_msg_info = + seL4_ReplyWait(Thread_base::myself()->tid().ep_sel, reply_msg, &badge); + + } else { + page_fault_msg_info = + seL4_Wait(Thread_base::myself()->tid().ep_sel, &badge); + } + + Fault_info const fault_info(page_fault_msg_info); + + _pf_ip = fault_info.ip; + _pf_addr = fault_info.pf; + _pf_write = fault_info.write; + + _last = badge; +} + + +void Ipc_pager::acknowledge_wakeup() +{ + PDBG("not implemented"); +} + + +Ipc_pager::Ipc_pager() +: + Native_capability(Capability_space::create_ep_cap(*Thread_base::myself())), + _last(0) +{ } + + + +/********************** + ** Pager activation ** + **********************/ + +void Pager_activation_base::entry() +{ + Ipc_pager pager; + _cap = pager; + _cap_valid.unlock(); + + bool reply_pending = false; + while (1) { + + if (reply_pending) + pager.reply_and_wait_for_fault(); + else + pager.wait_for_fault(); + + reply_pending = false; + + /* lookup referenced object */ + Object_pool::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); + Pager_object *obj = _obj; + + /* handle request */ + if (obj) { + if (pager.is_exception()) { + obj->submit_exception_signal(); + continue; + } + + /* send reply if page-fault handling succeeded */ + if (!obj->pager(pager)) + reply_pending = true; + } + } +} + + +/****************** + ** Pager object ** + ******************/ + +void Pager_object::wake_up() +{ + PDBG("not implemented"); +} + + +void Pager_object::unresolved_page_fault_occurred() +{ + state.unresolved_page_fault = true; +} + + +/********************** + ** Pager entrypoint ** + **********************/ + +Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) +: _activation(a) +{ _activation->ep(this); } + + +void Pager_entrypoint::dissolve(Pager_object *obj) +{ + remove_locked(obj); +} + + +Pager_capability Pager_entrypoint::manage(Pager_object *obj) +{ + /* return invalid capability if no activation is present */ + if (!_activation) return Pager_capability(); + + /* + * Create minted endpoint capability of the pager entrypoint. + * The badge of the page-fault message is used to find the pager + * object for faulted thread. + */ + Native_capability ep_cap = _activation->cap(); + + Rpc_obj_key rpc_obj_key((addr_t)obj->badge()); + + Untyped_capability new_obj_cap = + Capability_space::create_rpc_obj_cap(ep_cap, 0, rpc_obj_key); + + /* add server object to object pool */ + obj->cap(new_obj_cap); + insert(obj); + + return reinterpret_cap_cast(new_obj_cap); +} + + diff --git a/repos/base-sel4/src/core/platform.cc b/repos/base-sel4/src/core/platform.cc index e1de333c6f..f1624ce590 100644 --- a/repos/base-sel4/src/core/platform.cc +++ b/repos/base-sel4/src/core/platform.cc @@ -348,7 +348,9 @@ Platform::Platform() _switch_to_core_cspace_done((_switch_to_core_cspace(), true)), _core_page_table_registry(*core_mem_alloc()), _init_core_page_table_registry_done((_init_core_page_table_registry(), true)), - _core_vm_space(Core_cspace::CORE_VM_PAD_CNODE_SEL, Core_cspace::CORE_VM_CNODE_SEL, + _core_vm_space(seL4_CapInitThreadPD, + Core_cspace::CORE_VM_PAD_CNODE_SEL, + Core_cspace::CORE_VM_CNODE_SEL, _phys_alloc, _top_cnode, _core_cnode, diff --git a/repos/base-sel4/src/core/platform_pd.cc b/repos/base-sel4/src/core/platform_pd.cc index e276e2feb3..d81ea92ba7 100644 --- a/repos/base-sel4/src/core/platform_pd.cc +++ b/repos/base-sel4/src/core/platform_pd.cc @@ -18,13 +18,42 @@ #include #include #include +#include +#include using namespace Genode; +/***************************************** + ** Allocator for protection-domain IDs ** + *****************************************/ + +struct Pd_id_alloc : Bit_allocator<1024> +{ + Pd_id_alloc() + { + /* + * Skip 0 because this top-level index is used to address the core + * CNode. + */ + _reserve(0, 1); + _reserve(Core_cspace::CORE_VM_ID, 1); + } +}; + + +static Pd_id_alloc &pd_id_alloc() +{ + static Pd_id_alloc inst; + return inst; +} + + int Platform_pd::bind_thread(Platform_thread *thread) { - PDBG("not implemented"); + ASSERT(thread); + + thread->_pd = this; return 0; } @@ -35,14 +64,64 @@ void Platform_pd::unbind_thread(Platform_thread *thread) } +Untyped_address Platform_pd::_init_page_directory() +{ + using namespace Kernel_object; + return create(*platform()->ram_alloc(), + platform_specific()->core_cnode().sel(), + _page_directory_sel); +} + + +unsigned Platform_pd::alloc_sel() +{ + Lock::Guard guard(_sel_alloc_lock); + + return _sel_alloc.alloc(); +} + + +void Platform_pd::free_sel(unsigned sel) +{ + Lock::Guard guard(_sel_alloc_lock); + + _sel_alloc.free(sel); +} + + +void Platform_pd::install_mapping(Mapping const &mapping) +{ + _vm_space.map(mapping.from_phys(), mapping.to_virt(), mapping.num_pages()); +} + + Platform_pd::Platform_pd(Allocator * md_alloc, size_t ram_quota, char const *, signed pd_id, bool create) -{ - PDBG("not implemented"); -} +: + _id(pd_id_alloc().alloc()), + _page_table_registry(*md_alloc), + _vm_pad_cnode_sel(platform_specific()->alloc_core_sel()), + _vm_cnode_sel(platform_specific()->alloc_core_sel()), + _page_directory_sel(platform_specific()->alloc_core_sel()), + _page_directory(_init_page_directory()), + _vm_space(_page_directory_sel, + _vm_pad_cnode_sel, _vm_cnode_sel, + *platform()->ram_alloc(), + platform_specific()->top_cnode(), + platform_specific()->core_cnode(), + platform_specific()->phys_cnode(), + _id, + _page_table_registry), + _cspace_cnode_sel(platform_specific()->alloc_core_sel()), + _cspace_cnode(platform_specific()->core_cnode().sel(), _cspace_cnode_sel, + CSPACE_SIZE_LOG2, + *platform()->ram_alloc()) +{ } Platform_pd::~Platform_pd() { - PWRN("not implemented"); + platform_specific()->free_core_sel(_vm_cnode_sel); + platform_specific()->free_core_sel(_vm_pad_cnode_sel); + platform_specific()->free_core_sel(_cspace_cnode_sel); } diff --git a/repos/base-sel4/src/core/platform_thread.cc b/repos/base-sel4/src/core/platform_thread.cc index ae24e10a17..3a88ce4ca9 100644 --- a/repos/base-sel4/src/core/platform_thread.cc +++ b/repos/base-sel4/src/core/platform_thread.cc @@ -17,13 +17,95 @@ /* core includes */ #include +#include + +/* base-internal includes */ +#include using namespace Genode; +/***************************************************** + ** Implementation of the install_mapping interface ** + *****************************************************/ + +class Platform_thread_registry : Noncopyable +{ + private: + + List _threads; + Lock _lock; + + public: + + void insert(Platform_thread &thread) + { + Lock::Guard guard(_lock); + _threads.insert(&thread); + } + + void remove(Platform_thread &thread) + { + Lock::Guard guard(_lock); + _threads.remove(&thread); + } + + void install_mapping(Mapping const &mapping, unsigned long pager_object_badge) + { + Lock::Guard guard(_lock); + + for (Platform_thread *t = _threads.first(); t; t = t->next()) { + if (t->pager_object_badge() == pager_object_badge) + t->install_mapping(mapping); + } + } +}; + + +Platform_thread_registry &platform_thread_registry() +{ + static Platform_thread_registry inst; + return inst; +} + + +void Genode::install_mapping(Mapping const &mapping, unsigned long pager_object_badge) +{ + platform_thread_registry().install_mapping(mapping, pager_object_badge); +} + + +/******************************* + ** Platform_thread interface ** + *******************************/ + int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no) { - PDBG("not implemented"); + ASSERT(_pd); + ASSERT(_pager); + + /* allocate fault handler selector in the PD's CSpace */ + _fault_handler_sel = _pd->alloc_sel(); + + /* pager endpoint in core */ + unsigned const pager_sel = Capability_space::ipc_cap_data(_pager->cap()).sel; + + /* install page-fault handler endpoint selector to the PD's CSpace */ + _pd->cspace_cnode().copy(platform_specific()->core_cnode(), pager_sel, + _fault_handler_sel); + + /* bind thread to PD and CSpace */ + seL4_CapData_t const guard_cap_data = + seL4_CapData_Guard_new(0, 32 - _pd->cspace_size_log2()); + + seL4_CapData_t const no_cap_data = { { 0 } }; + + int const ret = seL4_TCB_SetSpace(_info.tcb_sel, _fault_handler_sel, + _pd->cspace_cnode().sel(), guard_cap_data, + _pd->page_directory_sel(), no_cap_data); + ASSERT(ret == 0); + + start_sel4_thread(_info.tcb_sel, (addr_t)ip, (addr_t)(sp)); return 0; } @@ -42,14 +124,14 @@ void Platform_thread::resume() void Platform_thread::state(Thread_state s) { - PDBG("Not implemented"); + PDBG("not implemented"); throw Cpu_session::State_access_failed(); } Thread_state Platform_thread::state() { - PDBG("Not implemented"); + PDBG("not implemented"); throw Cpu_session::State_access_failed(); } @@ -62,17 +144,35 @@ void Platform_thread::cancel_blocking() Weak_ptr Platform_thread::address_space() { - return _address_space; + ASSERT(_pd); + return _pd->weak_ptr(); } -Platform_thread::Platform_thread(size_t, const char *name, unsigned, addr_t) +void Platform_thread::install_mapping(Mapping const &mapping) { - PDBG("not implemented"); + _pd->install_mapping(mapping); +} + + +Platform_thread::Platform_thread(size_t, const char *name, unsigned priority, + addr_t utcb) +: + _name(name), + _pager_obj_sel(platform_specific()->alloc_core_sel()) + +{ + _info.init(utcb); + platform_thread_registry().insert(*this); } Platform_thread::~Platform_thread() { - PDBG("not implemented"); + PDBG("not completely implemented"); + + platform_thread_registry().remove(*this); + platform_specific()->free_core_sel(_pager_obj_sel); } + + diff --git a/repos/base-sel4/src/core/thread_start.cc b/repos/base-sel4/src/core/thread_start.cc index c434cf387a..5b565e024b 100644 --- a/repos/base-sel4/src/core/thread_start.cc +++ b/repos/base-sel4/src/core/thread_start.cc @@ -19,77 +19,38 @@ /* core includes */ #include #include -#include -#include +#include using namespace Genode; -static Untyped_address create_and_map_ipc_buffer(Range_allocator &phys_alloc, - addr_t virt_addr) -{ - /* create IPC buffer of one page */ - size_t const ipc_buffer_size_log2 = get_page_size_log2(); - Untyped_address const untyped_addr = - Untyped_memory::alloc_log2(phys_alloc, ipc_buffer_size_log2); - - Untyped_memory::convert_to_page_frames(untyped_addr.phys(), 1); - - if (!map_local(untyped_addr.phys(), virt_addr, 1)) { - PERR("could not map IPC buffer phys %lx at local %lx", - untyped_addr.phys(), virt_addr); - } - - return untyped_addr; -} - - void Thread_base::_init_platform_thread(size_t, Type type) { - Platform &platform = *platform_specific(); - Range_allocator &phys_alloc = *platform.ram_alloc(); - addr_t const utcb_virt_addr = (addr_t)&_context->utcb; - Untyped_address const ipc_buffer = - create_and_map_ipc_buffer(phys_alloc, utcb_virt_addr); - /* allocate TCB within core's CNode */ - _tid.tcb_sel = platform.alloc_core_sel(); - Kernel_object::create(phys_alloc, - platform.core_cnode().sel(), - _tid.tcb_sel); - - /* allocate synchronous endpoint within core's CNode */ - _tid.ep_sel = platform.alloc_core_sel(); - Kernel_object::create(phys_alloc, - platform.core_cnode().sel(), - _tid.ep_sel); - - /* assign IPC buffer to thread */ - { - /* determine page frame selector of the allocated IPC buffer */ - unsigned ipc_buffer_sel = Untyped_memory::frame_sel(ipc_buffer.phys()); - - int const ret = seL4_TCB_SetIPCBuffer(_tid.tcb_sel, utcb_virt_addr, - ipc_buffer_sel); - if (ret != 0) - PDBG("seL4_TCB_SetIPCBuffer returned %d", ret); + if (type == MAIN) { + _tid.tcb_sel = seL4_CapInitThreadTCB; + return; } - /* set scheduling priority */ - enum { PRIORITY_MAX = 0xff }; - seL4_TCB_SetPriority(_tid.tcb_sel, PRIORITY_MAX); + Thread_info thread_info; + thread_info.init(utcb_virt_addr); - /* associate thread with core PD */ - { - seL4_CapData_t no_cap_data = { { 0 } }; - int const ret = seL4_TCB_SetSpace(_tid.tcb_sel, 0, - platform.top_cnode().sel(), no_cap_data, - seL4_CapInitThreadPD, no_cap_data); - - if (ret != 0) - PDBG("seL4_TCB_SetSpace returned %d", ret); + if (!map_local(thread_info.ipc_buffer_phys, utcb_virt_addr, 1)) { + PERR("could not map IPC buffer phys %lx at local %lx", + thread_info.ipc_buffer_phys, utcb_virt_addr); } + + _tid.tcb_sel = thread_info.tcb_sel; + _tid.ep_sel = thread_info.ep_sel; + + Platform &platform = *platform_specific(); + + seL4_CapData_t no_cap_data = { { 0 } }; + int const ret = seL4_TCB_SetSpace(_tid.tcb_sel, 0, + platform.top_cnode().sel(), no_cap_data, + seL4_CapInitThreadPD, no_cap_data); + ASSERT(ret == 0); } @@ -110,21 +71,7 @@ void Thread_base::_thread_start() void Thread_base::start() { - /* set register values for the instruction pointer and stack pointer */ - seL4_UserContext regs; - Genode::memset(®s, 0, sizeof(regs)); - - regs.eip = (uint32_t)&_thread_start; - regs.esp = (uint32_t)stack_top(); - regs.gs = IPCBUF_GDT_SELECTOR; - size_t const num_regs = sizeof(regs)/sizeof(seL4_Word); - int const ret = seL4_TCB_WriteRegisters(_tid.tcb_sel, false, - 0, num_regs, ®s); - - if (ret != 0) - PDBG("seL4_TCB_WriteRegisters returned %d", ret); - - seL4_TCB_Resume(_tid.tcb_sel); + start_sel4_thread(_tid.tcb_sel, (addr_t)&_thread_start, (addr_t)stack_top()); }