diff options
author | Michael Davidsaver <mdavidsaver@gmail.com> | 2015-12-02 19:18:53 -0500 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-01-23 13:33:40 +0000 |
commit | 8a4e10dfb5cb5010512c495c26abdd9723ce4603 (patch) | |
tree | 51f8c9350719b13f685c4c241935dff3d2d3d6fc | |
parent | 9bc4a56198bfdac9d01aeeb0e0d27996ba210ad4 (diff) |
armv7m: decide whether faults are MemManage or BusFaultnvic-rebase
General logic is that operations stopped by the MPU are MemManage,
and those which go through the MPU and are caught by the unassigned
handle are BusFault.
Signed-off-by: Michael Davidsaver <mdavidsaver@gmail.com>
-rw-r--r-- | target/arm/helper.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index 559ea48145..f3966e810f 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6159,12 +6159,35 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) break; case EXCP_PREFETCH_ABORT: case EXCP_DATA_ABORT: - /* TODO: if we implemented the MPU registers, this is where we - * should set the MMFAR, etc from exception.fsr and exception.vaddress. - */ - armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM); - env->v7m.mmfar = env->exception.vaddress; - env->v7m.cfsr = (1<<1)|(1<<7); /* DACCVIOL and MMARVALID */ + switch (env->exception.fsr & 0xf) { + case 0x8: /* External Abort */ + switch (cs->exception_index) { + case EXCP_PREFETCH_ABORT: + env->v7m.cfsr |= (1<<(8+1)); /* PRECISERR */ + break; + case EXCP_DATA_ABORT: + env->v7m.cfsr |= (1<<(8+0)); /* IBUSERR */ + break; + } + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS); + env->v7m.bfar = env->exception.vaddress; + env->v7m.cfsr |= (1<<(8+7)); /* BFARVALID */ + break; + case 0xd: /* Permission fault */ + default: + switch (cs->exception_index) { + case EXCP_PREFETCH_ABORT: + env->v7m.cfsr |= (1<<0); /* IACCVIOL */ + break; + case EXCP_DATA_ABORT: + env->v7m.cfsr |= (1<<1); /* DACCVIOL */ + break; + } + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM); + env->v7m.mmfar = env->exception.vaddress; + env->v7m.cfsr |= (1<<7); /* MMARVALID */ + break; + } break; case EXCP_BKPT: if (semihosting_enabled()) { |