hw: evaluate write fault on RO page

rm_fault.run triggers write on read-only ROM provided by core, which
fails without this patch:

arm - "raised unhandled data abort"
x86 - (silent/invisible) busy loop because write fault gets never resolved
This commit is contained in:
Alexander Boettcher 2017-07-31 16:30:57 +02:00 committed by Christian Helmuth
parent 5adda2d934
commit de06eefbac
3 changed files with 27 additions and 5 deletions

View File

@ -148,8 +148,12 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
*/
bool in_fault(addr_t & va, addr_t & w) const
{
static constexpr Fsr::access_t section = 5;
static constexpr Fsr::access_t page = 7;
/* translation fault on section */
static constexpr Fsr::access_t section = 5;
/* translation fault on page */
static constexpr Fsr::access_t page = 7;
/* permission fault on page */
static constexpr Fsr::access_t permission = 0xf;
switch (cpu_exception) {
@ -167,9 +171,9 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
}
case DATA_ABORT:
{
/* check if fault was caused by translation miss */
/* check if fault is of known type */
Dfsr::access_t const fs = Fsr::Fs::get(Dfsr::read());
if (fs != section && fs != page)
if (fs != permission && fs != section && fs != page)
return false;
/* fetch fault data */

View File

@ -203,6 +203,9 @@ class Genode::Cpu : public Arm_v7_cpu
*/
bool in_fault(addr_t & va, addr_t & w) const
{
/* permission fault on page, 2nd level */
static constexpr Fsr::access_t permission = 0b1111;
switch (cpu_exception) {
case PREFETCH_ABORT:
@ -221,7 +224,8 @@ class Genode::Cpu : public Arm_v7_cpu
{
/* check if fault was caused by translation miss */
Fsr::access_t const fs = Fsr::Fs::get(Dfsr::read());
if ((fs & 0b11100) != 0b100) return false;
if ((fs != permission) && (fs & 0b11100) != 0b100)
return false;
/* fetch fault data */
Dfsr::access_t const dfsr = Dfsr::read();

View File

@ -24,11 +24,25 @@ void Kernel::Thread::_call_update_data_region() { }
void Kernel::Thread::_call_update_instr_region() { }
/*
* Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE
* Interrupt 14Page-Fault Exception (#PF)
*/
enum {
ERR_I = 1UL << 4,
ERR_R = 1UL << 3,
ERR_U = 1UL << 2,
ERR_W = 1UL << 1,
ERR_P = 1UL << 0,
};
void Kernel::Thread::_mmu_exception()
{
_become_inactive(AWAITS_RESTART);
_fault_pd = (addr_t)_pd->platform_pd();
_fault_addr = Cpu::Cr2::read();
_fault_writes = (errcode & ERR_P) && (errcode & ERR_W);
/*
* Core should never raise a page-fault. If this happens, print out an