aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Davidsaver <mdavidsaver@gmail.com>2015-12-02 19:18:53 -0500
committerPeter Maydell <peter.maydell@linaro.org>2017-01-23 13:33:40 +0000
commit8a4e10dfb5cb5010512c495c26abdd9723ce4603 (patch)
tree51f8c9350719b13f685c4c241935dff3d2d3d6fc
parent9bc4a56198bfdac9d01aeeb0e0d27996ba210ad4 (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.c35
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()) {