diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 1867435db7..84609f446e 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -624,7 +624,11 @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure, if (sattrs.ns) { attrs.secure = false; } else if (!targets_secure) { - /* NS access to S memory */ + /* + * NS access to S memory: the underlying exception which we escalate + * to HardFault is SecureFault, which always targets Secure. + */ + exc_secure = true; goto load_fail; } } @@ -632,6 +636,11 @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure, vector_entry = address_space_ldl(arm_addressspace(cs, attrs), addr, attrs, &result); if (result != MEMTX_OK) { + /* + * Underlying exception is BusFault: its target security state + * depends on BFHFNMINS. + */ + exc_secure = !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK); goto load_fail; } *pvec = vector_entry; @@ -641,13 +650,17 @@ load_fail: /* * All vector table fetch fails are reported as HardFault, with * HFSR.VECTTBL and .FORCED set. (FORCED is set because - * technically the underlying exception is a MemManage or BusFault + * technically the underlying exception is a SecureFault or BusFault * that is escalated to HardFault.) This is a terminal exception, * so we will either take the HardFault immediately or else enter * lockup (the latter case is handled in armv7m_nvic_set_pending_derived()). + * The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are + * secure); otherwise it targets the same security state as the + * underlying exception. */ - exc_secure = targets_secure || - !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK); + if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) { + exc_secure = true; + } env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK; armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure); return false;