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. --- target-arm/helper.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/target-arm/helper.c b/target-arm/helper.c index c890b3a..630d5c9 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -5546,12 +5546,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()) { -- 2.1.4