hw: enable nx bit handling for arm

This commit is contained in:
Alexander Boettcher 2017-10-17 11:36:10 +02:00 committed by Christian Helmuth
parent aa1d5a7dd1
commit 4dd5e6b266
5 changed files with 41 additions and 9 deletions

View File

@ -139,9 +139,10 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
* Return if the context is in a page fault due to translation miss
*
* \param va holds the virtual fault-address if call returns 1
* \param w holds wether it's a write fault if call returns 1
* \param w holds whether it's a write fault if call returns 1
* \param p holds whether it's a permission fault if call returns 1
*/
bool in_fault(addr_t & va, addr_t & w) const
bool in_fault(addr_t & va, addr_t & w, bool & p) const
{
/* translation fault on section */
static constexpr Fsr::access_t section = 5;
@ -156,12 +157,21 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
{
/* check if fault was caused by a translation miss */
Ifsr::access_t const fs = Fsr::Fs::get(Ifsr::read());
if (fs == permission) {
w = 0;
va = regs->ip;
p = true;
return true;
}
if (fs != section && fs != page)
return false;
/* fetch fault data */
w = 0;
va = regs->ip;
p = false;
return true;
}
case Context::DATA_ABORT:
@ -175,6 +185,7 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
Dfsr::access_t const dfsr = Dfsr::read();
w = Dfsr::Wnr::get(dfsr);
va = Dfar::read();
p = false;
return true;
}

View File

@ -59,7 +59,7 @@ void Thread::exception(unsigned const cpu)
void Thread::_mmu_exception()
{
_become_inactive(AWAITS_RESTART);
if (in_fault(_fault_addr, _fault_writes)) {
if (in_fault(_fault_addr, _fault_writes, _fault_exec)) {
_fault_pd = (addr_t)_pd->platform_pd();
/*
@ -73,14 +73,21 @@ void Thread::_mmu_exception()
if (_pager) _pager->submit(1);
return;
}
bool da = regs->cpu_exception == Cpu::Context::DATA_ABORT;
char const *abort_type = "unknown";
if (regs->cpu_exception == Cpu::Context::DATA_ABORT)
abort_type = "data";
if (regs->cpu_exception == Cpu::Context::PREFETCH_ABORT)
abort_type = "prefetch";
Genode::error(*this, ": raised unhandled ",
da ? "data abort" : "prefetch abort", " "
abort_type, " abort ",
"DFSR=", Genode::Hex(Cpu::Dfsr::read()), " "
"ISFR=", Genode::Hex(Cpu::Ifsr::read()), " "
"DFAR=", Genode::Hex(Cpu::Dfar::read()), " "
"ip=", Genode::Hex(regs->ip), " "
"sp=", Genode::Hex(regs->sp));
"sp=", Genode::Hex(regs->sp), " "
"exception=", Genode::Hex(regs->cpu_exception));
}

View File

@ -195,9 +195,10 @@ class Genode::Cpu : public Arm_v7_cpu
* Return if the context is in a page fault due to translation miss
*
* \param va holds the virtual fault-address if call returns 1
* \param w holds wether it's a write fault if call returns 1
* \param w holds whether it's a write fault if call returns 1
* \param p holds whether it's a permission fault if call returns 1
*/
bool in_fault(addr_t & va, addr_t & w) const
bool in_fault(addr_t & va, addr_t & w, bool &p) const
{
/* permission fault on page, 2nd level */
static constexpr Fsr::access_t permission = 0b1111;
@ -208,11 +209,19 @@ class Genode::Cpu : public Arm_v7_cpu
{
/* check if fault was caused by a translation miss */
Fsr::access_t const fs = Fsr::Fs::get(Ifsr::read());
if (fs == permission) {
w = 0;
va = regs->ip;
p = true;
return true;
}
if ((fs & 0b11100) != 0b100) return false;
/* fetch fault data */
w = 0;
va = regs->ip;
p = false;
return true;
}
@ -227,6 +236,7 @@ class Genode::Cpu : public Arm_v7_cpu
Dfsr::access_t const dfsr = Dfsr::read();
w = Dfsr::Wnr::get(dfsr);
va = Dfar::read();
p = false;
return true;
}

View File

@ -240,6 +240,8 @@ class Hw::Long_translation_table
struct Privileged_execute_never : Base::template Bitfield<53,1> { };
struct Execute_never : Base::template Bitfield<54,1> { };
static typename Descriptor::access_t create(Page_flags const &f,
addr_t const pa)
{
@ -250,7 +252,8 @@ class Hw::Long_translation_table
Base::Shareability::OUTER_SHAREABLE)
| Base::Output_address::masked(pa)
| Base::Access_flag::bits(1)
| Descriptor::Valid::bits(1);
| Descriptor::Valid::bits(1)
| Execute_never::bits(!f.executable);
}
};

View File

@ -8,6 +8,7 @@ if {[have_spec linux]} {
proc non_executable_supported { } {
if {[have_spec hw] && [have_spec x86_64]} { return true }
if {[have_spec hw] && [have_spec arm]} { return true }
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 }