From 8ea584b1d2078753c722911d101cede7da44ff08 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 13 Oct 2017 14:26:09 +0200 Subject: [PATCH] foc: enable nx bit handling for x86_64 and arm Issue #1723 --- repos/base-foc/src/core/include/ipc_pager.h | 343 +++++++++--------- repos/base-foc/src/core/spec/arm/ipc_pager.cc | 4 + repos/base-foc/src/core/spec/x86/ipc_pager.cc | 3 + repos/base/run/rm_fault.run | 2 + 4 files changed, 184 insertions(+), 168 deletions(-) diff --git a/repos/base-foc/src/core/include/ipc_pager.h b/repos/base-foc/src/core/include/ipc_pager.h index c197d564e3..ac29553c40 100644 --- a/repos/base-foc/src/core/include/ipc_pager.h +++ b/repos/base-foc/src/core/include/ipc_pager.h @@ -34,174 +34,181 @@ namespace Fiasco { } namespace Genode { - - class Mapping - { - private: - - addr_t _dst_addr; - addr_t _src_addr; - Cache_attribute _cacheability; - bool _iomem; - unsigned _log2size; - bool _rw; - - public: - - /** - * Constructor - */ - Mapping(addr_t dst_addr, addr_t src_addr, - Cache_attribute c, bool io_mem, - unsigned l2size, - bool rw, bool executable) - : _dst_addr(dst_addr), _src_addr(src_addr), - _cacheability(c), _iomem(io_mem), _log2size(l2size), - _rw(rw) { } - - /** - * Construct invalid flexpage - */ - Mapping() : _dst_addr(0), _src_addr(0), _cacheability(UNCACHED), - _iomem(false), _log2size(0), _rw(false) { } - - Fiasco::l4_umword_t dst_addr() const { return _dst_addr; } - bool grant() const { return false; } - - Fiasco::l4_fpage_t fpage() const - { - unsigned char rights = _rw ? Fiasco::L4_FPAGE_RWX : Fiasco::L4_FPAGE_RX; - return Fiasco::l4_fpage(_src_addr, _log2size, rights); - } - - Cache_attribute cacheability() const { return _cacheability; } - bool iomem() { return _iomem; } - /** - * Prepare map operation is not needed on Fiasco.OC, since we clear the - * dataspace before this function is called. - */ - void prepare_map_operation() { } - }; - - - /** - * Special paging server class - */ - class Ipc_pager : public Native_capability - { - public: - - enum Msg_type { PAGEFAULT, WAKE_UP, PAUSE, EXCEPTION }; - - private: - - Native_thread _last; /* origin of last fault */ - addr_t _pf_addr; /* page-fault address */ - addr_t _pf_ip; /* ip of faulter */ - Mapping _reply_mapping; /* page-fault answer */ - unsigned long _badge; /* badge of faulting thread */ - Fiasco::l4_msgtag_t _tag; /* receive message tag */ - Fiasco::l4_exc_regs_t _regs; /* exception registers */ - Msg_type _type; - - void _parse_msg_type(void); - void _parse_exception(void); - void _parse_pagefault(void); - void _parse(unsigned long label); - - public: - - /** - * Constructor - */ - Ipc_pager(); - - /** - * Wait for a new page fault received as short message IPC - */ - void wait_for_fault(); - - /** - * Reply current page-fault and wait for a new one - * - * Send short flex page and wait for next short-message (register) - * IPC -- pagefault - */ - void reply_and_wait_for_fault(); - - /** - * Request instruction pointer of current page fault - */ - addr_t fault_ip() { return _pf_ip; } - - /** - * Request fault address of current page fault - */ - addr_t fault_addr() { return _pf_addr & ~3; } - - /** - * Set parameters for next reply - */ - void set_reply_mapping(Mapping m) { _reply_mapping = m; } - - /** - * Set destination for next reply - */ - void set_reply_dst(Native_thread t) { - _last = t; } - - /** - * Answer call without sending a flex-page mapping - * - * This function is used to acknowledge local calls from one of - * core's region-manager sessions. - */ - void acknowledge_wakeup(); - - /** - * Reply to an exception IPC - */ - void acknowledge_exception(); - - /** - * Return thread ID of last faulter - */ - Native_thread last() const { return _last; } - - /** - * Return badge for faulting thread - */ - unsigned long badge() { return _badge; } - - bool write_fault() const { return (_pf_addr & 2); } - - bool exec_fault() const { return false; } - - /** - * Return true if last fault was an exception - */ - bool exception() const - { - return _type == Ipc_pager::EXCEPTION; - } - - /** - * Return the type of ipc we received at last. - */ - Msg_type msg_type() { return _type; }; - - /** - * Copy the exception registers from the last exception - * to the given Thread_state object. - */ - void get_regs(Foc_thread_state *state); - - /* - * Copy the exception reply registers from the given - * Thread_state object - */ - void set_regs(Foc_thread_state state); - }; + class Mapping; + class Ipc_pager; } +class Genode::Mapping +{ + private: + + addr_t _dst_addr; + Fiasco::l4_fpage_t _fpage; + Cache_attribute _cacheability; + bool _iomem; + + public: + + /** + * Constructor + */ + Mapping(addr_t dst_addr, addr_t src_addr, + Cache_attribute c, bool io_mem, + unsigned log2size, bool write, bool executable) + : _dst_addr(dst_addr), _cacheability(c), _iomem(io_mem) + { + typedef Fiasco::L4_fpage_rights Rights; + Rights rights = (write && executable) ? Fiasco::L4_FPAGE_RWX : + (write && !executable) ? Fiasco::L4_FPAGE_RW : + (!write && !executable) ? Fiasco::L4_FPAGE_RO : + Fiasco::L4_FPAGE_RX; + + _fpage = Fiasco::l4_fpage(src_addr, log2size, rights); + } + + /** + * Construct invalid flexpage + */ + Mapping() : _dst_addr(0), _fpage(Fiasco::l4_fpage_invalid()), + _cacheability(UNCACHED), _iomem(false) { } + + Fiasco::l4_umword_t dst_addr() const { return _dst_addr; } + bool grant() const { return false; } + Fiasco::l4_fpage_t fpage() const { return _fpage; } + Cache_attribute cacheability() const { return _cacheability; } + bool iomem() const { return _iomem; } + /** + * Prepare map operation is not needed on Fiasco.OC, since we clear the + * dataspace before this function is called. + */ + void prepare_map_operation() { } +}; + + +/** + * Special paging server class + */ +class Genode::Ipc_pager : public Native_capability +{ + public: + + enum Msg_type { PAGEFAULT, WAKE_UP, PAUSE, EXCEPTION }; + + private: + + Native_thread _last; /* origin of last fault */ + addr_t _pf_addr; /* page-fault address */ + addr_t _pf_ip; /* ip of faulter */ + Mapping _reply_mapping; /* page-fault answer */ + unsigned long _badge; /* badge of faulting thread */ + Fiasco::l4_msgtag_t _tag; /* receive message tag */ + Fiasco::l4_exc_regs_t _regs; /* exception registers */ + Msg_type _type; + + void _parse_msg_type(void); + void _parse_exception(void); + void _parse_pagefault(void); + void _parse(unsigned long label); + + public: + + /** + * Constructor + */ + Ipc_pager(); + + /** + * Wait for a new page fault received as short message IPC + */ + void wait_for_fault(); + + /** + * Reply current page-fault and wait for a new one + * + * Send short flex page and wait for next short-message (register) + * IPC -- pagefault + */ + void reply_and_wait_for_fault(); + + /** + * Request instruction pointer of current page fault + */ + addr_t fault_ip() { return _pf_ip; } + + /** + * Request fault address of current page fault. Lower 3 bits are used + * to encode error codes. + */ + addr_t fault_addr() { return _pf_addr & ~7UL; } + + /** + * Set parameters for next reply + */ + void set_reply_mapping(Mapping m) { _reply_mapping = m; } + + /** + * Set destination for next reply + */ + void set_reply_dst(Native_thread t) { _last = t; } + + /** + * Answer call without sending a flex-page mapping + * + * This function is used to acknowledge local calls from one of + * core's region-manager sessions. + */ + void acknowledge_wakeup(); + + /** + * Reply to an exception IPC + */ + void acknowledge_exception(); + + /** + * Return thread ID of last faulter + */ + Native_thread last() const { return _last; } + + /** + * Return badge for faulting thread + */ + unsigned long badge() { return _badge; } + + /** + * Return true if fault was a write fault + */ + bool write_fault() const { return (_pf_addr & 2); } + + /** + * Return true if fault was caused by execution on non executable memory + */ + bool exec_fault() const; + + /** + * Return true if last fault was an exception + */ + + bool exception() const + { + return _type == Ipc_pager::EXCEPTION; + } + + /** + * Return the type of ipc we received at last. + */ + Msg_type msg_type() { return _type; }; + + /** + * Copy the exception registers from the last exception + * to the given Thread_state object. + */ + void get_regs(Foc_thread_state *state); + + /* + * Copy the exception reply registers from the given + * Thread_state object + */ + void set_regs(Foc_thread_state state); +}; + #endif /* _CORE__INCLUDE__IPC_PAGER_H_ */ diff --git a/repos/base-foc/src/core/spec/arm/ipc_pager.cc b/repos/base-foc/src/core/spec/arm/ipc_pager.cc index 69c50451e1..86c46ff977 100644 --- a/repos/base-foc/src/core/spec/arm/ipc_pager.cc +++ b/repos/base-foc/src/core/spec/arm/ipc_pager.cc @@ -75,3 +75,7 @@ void Genode::Ipc_pager::set_regs(Foc_thread_state state) _regs.cpsr = state.cpsr; } +bool Genode::Ipc_pager::exec_fault() const +{ + return (_pf_addr & 4) && !(_pf_addr & 1); +} diff --git a/repos/base-foc/src/core/spec/x86/ipc_pager.cc b/repos/base-foc/src/core/spec/x86/ipc_pager.cc index a09792cadd..d08f35307a 100644 --- a/repos/base-foc/src/core/spec/x86/ipc_pager.cc +++ b/repos/base-foc/src/core/spec/x86/ipc_pager.cc @@ -28,3 +28,6 @@ void Genode::Ipc_pager::_parse_exception() else _type = EXCEPTION; } + +bool Genode::Ipc_pager::exec_fault() const { + return ((_pf_addr & 1) && !write_fault()); } diff --git a/repos/base/run/rm_fault.run b/repos/base/run/rm_fault.run index 6b84037ca3..5a7848bbf2 100644 --- a/repos/base/run/rm_fault.run +++ b/repos/base/run/rm_fault.run @@ -7,6 +7,8 @@ if {[have_spec linux]} { # proc non_executable_supported { } { if {[have_spec nova] && [have_spec x86_64]} { return true } + if {[have_spec foc] && [have_spec x86_64]} { return true } + if {[have_spec foc] && [have_spec arm]} { return true } return false }