diff --git a/base-hw/include/kernel/syscalls.h b/base-hw/include/kernel/syscalls.h index 59bb373a89..fa061d56c8 100644 --- a/base-hw/include/kernel/syscalls.h +++ b/base-hw/include/kernel/syscalls.h @@ -39,6 +39,7 @@ namespace Kernel START_THREAD = 2, PAUSE_THREAD = 3, RESUME_THREAD = 4, + RESUME_FAULTER = 28, GET_THREAD = 5, CURRENT_THREAD_ID = 6, YIELD_THREAD = 7, @@ -247,6 +248,15 @@ namespace Kernel { return syscall(RESUME_THREAD, id); } + /** + * Continue thread after a pagefault that could be resolved + * + * \param id ID of the targeted thread + */ + inline void resume_faulter(unsigned long const id = 0) { + syscall(RESUME_FAULTER, id); } + + /** * Let the current thread give up its remaining timeslice * diff --git a/base-hw/src/core/include/arm/section_table.h b/base-hw/src/core/include/arm/section_table.h index 08a919ccd8..8d8ee33ea3 100644 --- a/base-hw/src/core/include/arm/section_table.h +++ b/base-hw/src/core/include/arm/section_table.h @@ -154,7 +154,7 @@ namespace Arm return Tex::bits(2) | C::bits(0) | B::bits(0); if(cache_support()) { if(Page_flags::C::get(flags)) - return Tex::bits(6) | C::bits(1) | B::bits(0); + return Tex::bits(5) | C::bits(0) | B::bits(1); return Tex::bits(4) | C::bits(0) | B::bits(0); } return Tex::bits(4) | C::bits(0) | B::bits(0); diff --git a/base-hw/src/core/kernel.cc b/base-hw/src/core/kernel.cc index faf2020836..7d6357f47e 100644 --- a/base-hw/src/core/kernel.cc +++ b/base-hw/src/core/kernel.cc @@ -1726,6 +1726,31 @@ namespace Kernel } + /** + * Do specific syscall for 'user', for details see 'syscall.h' + */ + void do_resume_faulter(Thread * const user) + { + /* get targeted thread */ + Thread * const t = Thread::pool()->object(user->user_arg_1()); + assert(t); + + /* check permissions */ + assert(user->pd_id() == core_id() || user->pd_id() == t->pd_id()); + + /* + * Writeback the TLB entry that resolves the fault. + * This is a substitution for write-through-flagging + * the memory that holds the TLB data, because the latter + * is not feasible in core space. + */ + Cpu::flush_caches(); + + /* resume targeted thread */ + t->resume(); + } + + /** * Do specific syscall for 'user', for details see 'syscall.h' */ @@ -2075,6 +2100,7 @@ namespace Kernel /* 25 */ do_run_vm, /* 26 */ do_delete_thread, /* 27 */ do_signal_pending, + /* 28 */ do_resume_faulter, }; enum { MAX_SYSCALL = sizeof(handle_sysc)/sizeof(handle_sysc[0]) - 1 }; diff --git a/base-hw/src/core/rm_session_support.cc b/base-hw/src/core/rm_session_support.cc index 51733c9250..e6a6b2a657 100644 --- a/base-hw/src/core/rm_session_support.cc +++ b/base-hw/src/core/rm_session_support.cc @@ -80,8 +80,8 @@ void Ipc_pager::resolve_and_wait_for_fault() _mapping.size_log2, flags, space); assert(!sl2); } - /* try to wake up faulter */ - assert(!Kernel::resume_thread(_pagefault.thread_id)); + /* wake up faulter */ + Kernel::resume_faulter(_pagefault.thread_id); /* wait for next page fault */ wait_for_fault();