diff --git a/repos/base-sel4/patches/arm_cache.patch b/repos/base-sel4/patches/arm_cache.patch
index 3ea96e9eb1..3fa8b2379e 100644
--- a/repos/base-sel4/patches/arm_cache.patch
+++ b/repos/base-sel4/patches/arm_cache.patch
@@ -1,6 +1,6 @@
--- src/kernel/sel4/libsel4/arch_include/arm/sel4/arch/types.h
+++ src/kernel/sel4/libsel4/arch_include/arm/sel4/arch/types.h
-@@ -24,6 +24,7 @@
+@@ -26,10 +26,12 @@
typedef seL4_CPtr seL4_ARM_IOPageTable;
typedef enum {
@@ -8,3 +8,8 @@
seL4_ARM_PageCacheable = 0x01,
seL4_ARM_ParityEnabled = 0x02,
seL4_ARM_Default_VMAttributes = 0x03,
+ seL4_ARM_ExecuteNever = 0x04,
++ seL4_ARM_Default_VMAttributes_NoExecute = 0x07,
+ /* seL4_ARM_PageCacheable | seL4_ARM_ParityEnabled */
+ SEL4_FORCE_LONG_ENUM(seL4_ARM_VMAttributes),
+ } seL4_ARM_VMAttributes;
diff --git a/repos/base-sel4/ports/sel4.hash b/repos/base-sel4/ports/sel4.hash
index 8fae257642..3bbeb1e8b2 100644
--- a/repos/base-sel4/ports/sel4.hash
+++ b/repos/base-sel4/ports/sel4.hash
@@ -1 +1 @@
-b00bc949a62cc71b45191b19c966f3a542b25c20
+fac219549e9515349e61deae22a199ae3196e67a
diff --git a/repos/base-sel4/src/core/include/ipc_pager.h b/repos/base-sel4/src/core/include/ipc_pager.h
index b3939b0078..e332c3a3a5 100644
--- a/repos/base-sel4/src/core/include/ipc_pager.h
+++ b/repos/base-sel4/src/core/include/ipc_pager.h
@@ -18,135 +18,139 @@
#include
#include
-namespace Genode { class Ipc_pager; }
-
namespace Genode {
-
- class Mapping
- {
- friend class Ipc_pager;
-
- private:
-
- addr_t _from_phys_addr;
- addr_t _to_virt_addr;
- Cache_attribute _attr;
- size_t _num_pages;
- bool _writeable;
- addr_t _fault_type = { 0 };
-
- enum { PAGE_SIZE_LOG2 = 12 };
-
- public:
-
- /**
- * Constructor
- */
- Mapping(addr_t dst_addr, addr_t src_addr,
- Cache_attribute const cacheability, bool io_mem,
- unsigned l2size, bool rw, bool executable)
- :
- _from_phys_addr(src_addr),
- _to_virt_addr(dst_addr),
- _attr(cacheability),
- _num_pages(1 << (l2size - PAGE_SIZE_LOG2)),
- _writeable(rw)
- { }
-
- /**
- * Construct invalid mapping
- */
- Mapping() : _num_pages(0) { }
-
- /**
- * Prepare map operation
- *
- * No preparations are needed on seL4 because all mapping
- * originate from the physical address space.
- */
- void prepare_map_operation() { }
-
- addr_t from_phys() const { return _from_phys_addr; }
- addr_t to_virt() const { return _to_virt_addr; }
- size_t num_pages() const { return _num_pages; }
- bool writeable() const { return _writeable; }
- Cache_attribute cacheability() const { return _attr; }
- addr_t fault_type() const { return _fault_type; }
- };
-
-
- /**
- * Special paging server class
- */
- class Ipc_pager : public Native_capability
- {
- private:
-
- addr_t _badge; /* faulted badge of thread */
- addr_t _reply_sel; /* selector to save reply cap */
- addr_t _pf_addr; /* page-fault address */
- addr_t _pf_ip; /* instruction pointer of faulter */
- bool _pf_write; /* true on write fault */
- addr_t _fault_type; /* type of fault */
-
- Mapping _reply_mapping;
-
- 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
- */
- 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; }
-
- /**
- * Set parameters for next reply
- */
- void set_reply_mapping(Mapping m)
- {
- _reply_mapping = m;
- _reply_mapping._fault_type = _fault_type;
- }
-
- /**
- * Set destination for next reply
- */
- void reply_save_caller(addr_t sel) { _reply_sel = sel; }
-
- /**
- * Return badge for faulting thread
- */
- unsigned long badge() const { return _badge; }
-
- /**
- * Return true if page fault was a write fault
- */
- bool write_fault() const { return _pf_write; }
-
- /**
- * Return true if page fault was on non-executable memory
- */
- bool exec_fault() const { return false; }
- };
+ class Mapping;
+ class Ipc_pager;
}
+
+class Genode::Mapping
+{
+ friend class Ipc_pager;
+
+ private:
+
+ addr_t _from_phys_addr;
+ addr_t _to_virt_addr;
+ Cache_attribute _attr;
+ size_t _num_pages;
+ addr_t _fault_type = { 0 };
+ bool _writeable = { false };
+ bool _executable = { false };
+
+ enum { PAGE_SIZE_LOG2 = 12 };
+
+ public:
+
+ /**
+ * Constructor
+ */
+ Mapping(addr_t dst_addr, addr_t src_addr,
+ Cache_attribute const cacheability, bool io_mem,
+ unsigned l2size, bool rw, bool executable)
+ :
+ _from_phys_addr(src_addr),
+ _to_virt_addr(dst_addr),
+ _attr(cacheability),
+ _num_pages(1 << (l2size - PAGE_SIZE_LOG2)),
+ _writeable(rw), _executable(executable)
+ { }
+
+ /**
+ * Construct invalid mapping
+ */
+ Mapping() : _num_pages(0) { }
+
+ /**
+ * Prepare map operation
+ *
+ * No preparations are needed on seL4 because all mapping
+ * originate from the physical address space.
+ */
+ void prepare_map_operation() { }
+
+ addr_t from_phys() const { return _from_phys_addr; }
+ addr_t to_virt() const { return _to_virt_addr; }
+ size_t num_pages() const { return _num_pages; }
+ bool writeable() const { return _writeable; }
+ bool executable() const { return _executable; }
+ Cache_attribute cacheability() const { return _attr; }
+ addr_t fault_type() const { return _fault_type; }
+};
+
+
+/**
+ * Special paging server class
+ */
+class Genode::Ipc_pager : public Native_capability
+{
+ private:
+
+ addr_t _badge; /* faulted badge of thread */
+ addr_t _reply_sel; /* selector to save reply cap */
+ addr_t _pf_addr; /* page-fault address */
+ addr_t _pf_ip; /* instruction pointer of faulter */
+ addr_t _fault_type; /* type of fault */
+ bool _pf_write; /* true on write fault */
+ bool _pf_exec; /* true on exec fault */
+
+ Mapping _reply_mapping;
+
+ 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
+ */
+ 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; }
+
+ /**
+ * Set parameters for next reply
+ */
+ void set_reply_mapping(Mapping m)
+ {
+ _reply_mapping = m;
+ _reply_mapping._fault_type = _fault_type;
+ }
+
+ /**
+ * Set destination for next reply
+ */
+ void reply_save_caller(addr_t sel) { _reply_sel = sel; }
+
+ /**
+ * Return badge for faulting thread
+ */
+ unsigned long badge() const { return _badge; }
+
+ /**
+ * Return true if page fault was a write fault
+ */
+ bool write_fault() const { return _pf_write; }
+
+ /**
+ * Return true if page fault was on non-executable memory
+ */
+ bool exec_fault() const { return _pf_exec; }
+};
+
#endif /* _CORE__INCLUDE__IPC_PAGER_H_ */
diff --git a/repos/base-sel4/src/core/include/map_local.h b/repos/base-sel4/src/core/include/map_local.h
index 8a59e58e59..5c328f89bf 100644
--- a/repos/base-sel4/src/core/include/map_local.h
+++ b/repos/base-sel4/src/core/include/map_local.h
@@ -36,12 +36,13 @@ namespace Genode {
inline bool map_local(addr_t from_phys, addr_t to_virt, size_t num_pages,
Platform * platform = nullptr)
{
- enum { DONT_FLUSH = false, WRITEABLE = true };
+ enum { DONT_FLUSH = false, WRITEABLE = true, NON_EXECUTABLE = false };
try {
platform = platform ? platform : platform_specific();
platform->core_vm_space().map(from_phys, to_virt, num_pages,
Cache_attribute::CACHED,
- WRITEABLE, DONT_FLUSH);
+ WRITEABLE, NON_EXECUTABLE,
+ DONT_FLUSH);
} catch (Page_table_registry::Mapping_cache_full) {
return false;
}
diff --git a/repos/base-sel4/src/core/include/vm_space.h b/repos/base-sel4/src/core/include/vm_space.h
index 2849d98c69..a84735cca6 100644
--- a/repos/base-sel4/src/core/include/vm_space.h
+++ b/repos/base-sel4/src/core/include/vm_space.h
@@ -157,7 +157,8 @@ class Genode::Vm_space
bool _map_frame(addr_t const from_phys, addr_t const to_virt,
Cache_attribute const cacheability,
- bool const writable, bool const flush_support)
+ bool const writable, bool const executable,
+ bool const flush_support)
{
if (_page_table_registry.page_frame_at(to_virt)) {
/*
@@ -228,7 +229,7 @@ class Genode::Vm_space
* Insert copy of page-frame selector into page table
*/
long ret = _map_page(Cap_sel(pte_idx), to_virt, cacheability,
- writable);
+ writable, executable);
if (ret != seL4_NoError) {
error("seL4_*_Page_Map ", Hex(from_phys), "->",
Hex(to_virt), " returned ", ret);
@@ -241,7 +242,8 @@ class Genode::Vm_space
* Platform specific map/unmap of a page frame
*/
long _map_page(Genode::Cap_sel const &idx, Genode::addr_t const virt,
- Cache_attribute const cacheability, bool const write);
+ Cache_attribute const cacheability, bool const write,
+ bool const writable);
long _unmap_page(Genode::Cap_sel const &idx);
class Alloc_page_table_failed : Exception { };
@@ -374,7 +376,7 @@ class Genode::Vm_space
void map(addr_t const from_phys, addr_t const to_virt,
size_t const num_pages, Cache_attribute const cacheability,
- bool const writable, bool flush_support)
+ bool const writable, bool const executable, bool flush_support)
{
Lock::Guard guard(_lock);
@@ -382,7 +384,8 @@ class Genode::Vm_space
off_t const offset = i << get_page_size_log2();
if (!_map_frame(from_phys + offset, to_virt + offset,
- cacheability, writable, flush_support))
+ cacheability, writable, executable,
+ flush_support))
error("mapping failed ", Hex(from_phys + offset),
" -> ", Hex(to_virt + offset));
}
diff --git a/repos/base-sel4/src/core/pager.cc b/repos/base-sel4/src/core/pager.cc
index fd0f07c840..8ae86614a3 100644
--- a/repos/base-sel4/src/core/pager.cc
+++ b/repos/base-sel4/src/core/pager.cc
@@ -74,6 +74,7 @@ void Ipc_pager::reply_and_wait_for_fault()
_pf_ip = fault_info.ip;
_pf_addr = fault_info.pf;
_pf_write = fault_info.write;
+ _pf_exec = fault_info.exec_fault();
_fault_type = seL4_MessageInfo_get_label(page_fault_msg_info);
_badge = badge;
diff --git a/repos/base-sel4/src/core/platform_pd.cc b/repos/base-sel4/src/core/platform_pd.cc
index 5d354b97bf..b06074e3c7 100644
--- a/repos/base-sel4/src/core/platform_pd.cc
+++ b/repos/base-sel4/src/core/platform_pd.cc
@@ -89,10 +89,10 @@ bool Platform_pd::bind_thread(Platform_thread *thread)
*/
addr_t const utcb = (thread->_utcb) ? thread->_utcb : thread->INITIAL_IPC_BUFFER_VIRT;
- enum { WRITABLE = true, ONE_PAGE = 1, FLUSHABLE = true };
+ enum { WRITABLE = true, ONE_PAGE = 1, FLUSHABLE = true, NON_EXECUTABLE = false };
_vm_space.alloc_page_tables(utcb, get_page_size());
_vm_space.map(thread->_info.ipc_buffer_phys, utcb, ONE_PAGE,
- Cache_attribute::CACHED, WRITABLE, FLUSHABLE);
+ Cache_attribute::CACHED, WRITABLE, NON_EXECUTABLE, FLUSHABLE);
return true;
}
@@ -161,7 +161,7 @@ bool Platform_pd::install_mapping(Mapping const &mapping,
_vm_space.map(mapping.from_phys(), mapping.to_virt(),
mapping.num_pages(), mapping.cacheability(),
- mapping.writeable(), FLUSHABLE);
+ mapping.writeable(), mapping.executable(), FLUSHABLE);
return true;
} catch (...) {
char const * fault_name = "unknown";
diff --git a/repos/base-sel4/src/core/spec/arm/fault_info.h b/repos/base-sel4/src/core/spec/arm/fault_info.h
index 22f65438d3..5f598ea756 100644
--- a/repos/base-sel4/src/core/spec/arm/fault_info.h
+++ b/repos/base-sel4/src/core/spec/arm/fault_info.h
@@ -18,12 +18,23 @@ struct Fault_info
bool data_abort = 0;
bool write = 0;
+ enum {
+ IFSR_FAULT = 1,
+ IFSR_FAULT_PERMISSION = 0xf,
+ DFSR_WRITE_FAULT = 1UL << 11
+ };
+
Fault_info(seL4_MessageInfo_t msg_info)
:
ip(seL4_GetMR(0)),
pf(seL4_GetMR(1)),
- data_abort(seL4_GetMR(2) != 1),
+ data_abort(seL4_GetMR(2) != IFSR_FAULT),
/* Instruction Fault Status Register (IFSR) resp. Data FSR (DFSR) */
- write(data_abort && (seL4_GetMR(3) & (1 << 11)))
- { }
+ write(data_abort && (seL4_GetMR(3) & DFSR_WRITE_FAULT))
+ {
+ if (!data_abort && seL4_GetMR(3) != IFSR_FAULT_PERMISSION)
+ data_abort = true;
+ }
+
+ bool exec_fault() const { return !data_abort; }
};
diff --git a/repos/base-sel4/src/core/spec/arm/vm_space.cc b/repos/base-sel4/src/core/spec/arm/vm_space.cc
index 1b9d2e35f9..22b213b56f 100644
--- a/repos/base-sel4/src/core/spec/arm/vm_space.cc
+++ b/repos/base-sel4/src/core/spec/arm/vm_space.cc
@@ -27,12 +27,13 @@ static long map_page_table(Genode::Cap_sel const pagetable,
long Genode::Vm_space::_map_page(Genode::Cap_sel const &idx,
Genode::addr_t const virt,
Cache_attribute const cacheability,
- bool const writable)
+ bool const writable,
+ bool const executable)
{
seL4_ARM_Page const service = _idx_to_sel(idx.value());
seL4_ARM_PageDirectory const pd = _pd_sel.value();
seL4_CapRights_t const rights = writable ? seL4_ReadWrite : seL4_CanRead;
- seL4_ARM_VMAttributes attr = seL4_ARM_Default_VMAttributes;
+ seL4_ARM_VMAttributes attr = executable ? seL4_ARM_Default_VMAttributes : seL4_ARM_Default_VMAttributes_NoExecute;
if (cacheability == UNCACHED)
attr = seL4_ARM_Uncacheable;
diff --git a/repos/base-sel4/src/core/spec/x86/fault_info.h b/repos/base-sel4/src/core/spec/x86/fault_info.h
index fae42e868e..6527678d6c 100644
--- a/repos/base-sel4/src/core/spec/x86/fault_info.h
+++ b/repos/base-sel4/src/core/spec/x86/fault_info.h
@@ -35,4 +35,6 @@ struct Fault_info
pf(seL4_GetMR(1)),
write(seL4_GetMR(3) & ERR_W)
{ }
+
+ bool exec_fault() const { return false; }
};
diff --git a/repos/base-sel4/src/core/spec/x86/vm_space.cc b/repos/base-sel4/src/core/spec/x86/vm_space.cc
index 34f6d89e09..2c04c14071 100644
--- a/repos/base-sel4/src/core/spec/x86/vm_space.cc
+++ b/repos/base-sel4/src/core/spec/x86/vm_space.cc
@@ -17,7 +17,8 @@
long Genode::Vm_space::_map_page(Genode::Cap_sel const &idx,
Genode::addr_t const virt,
Cache_attribute const cacheability,
- bool const writable)
+ bool const writable,
+ bool const executable)
{
seL4_X86_Page const service = _idx_to_sel(idx.value());
seL4_X86_PageDirectory const pd = _pd_sel.value();
diff --git a/repos/base/run/rm_fault.run b/repos/base/run/rm_fault.run
index 932a2d0b00..e318addff9 100644
--- a/repos/base/run/rm_fault.run
+++ b/repos/base/run/rm_fault.run
@@ -12,6 +12,7 @@ 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 }
+ if {[have_spec sel4] && [have_spec arm]} { return true }
return false
}