mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-07-07 14:40:53 +00:00
target/arm: Make exception vector loads honour the SAU
Make the load of the exception vector from the vector table honour the SAU and any bus error on the load (possibly provoking a derived exception), rather than simply aborting if the load fails. Backports commit 600c33f24752a00e81e9372261e35c2befea612b from qemu
This commit is contained in:
parent
2c8a0fe0d7
commit
0dadc2575f
|
@ -5700,28 +5700,64 @@ static uint32_t *get_v7m_sp_ptr(CPUARMState *env, bool secure, bool threadmode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure)
|
static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure,
|
||||||
|
uint32_t *pvec)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
MemTxResult result;
|
MemTxResult result;
|
||||||
hwaddr vec = env->v7m.vecbase[targets_secure] + exc * 4;
|
uint32_t addr = env->v7m.vecbase[targets_secure] + exc * 4;
|
||||||
uint32_t addr;
|
uint32_t vector_entry;
|
||||||
|
MemTxAttrs attrs = {0};
|
||||||
|
ARMMMUIdx mmu_idx;
|
||||||
|
bool exc_secure;
|
||||||
|
|
||||||
addr = address_space_ldl(cs->as, vec,
|
mmu_idx = arm_v7m_mmu_idx_for_secstate_and_priv(env, targets_secure, true);
|
||||||
MEMTXATTRS_UNSPECIFIED, &result);
|
|
||||||
if (result != MEMTX_OK) {
|
/* We don't do a get_phys_addr() here because the rules for vector
|
||||||
/* Architecturally this should cause a HardFault setting HSFR.VECTTBL,
|
* loads are special: they always use the default memory map, and
|
||||||
* which would then be immediately followed by our failing to load
|
* the default memory map permits reads from all addresses.
|
||||||
* the entry vector for that HardFault, which is a Lockup case.
|
* Since there's no easy way to pass through to pmsav8_mpu_lookup()
|
||||||
* Since we don't model Lockup, we just report this guest error
|
* that we want this special case which would always say "yes",
|
||||||
* via cpu_abort().
|
* we just do the SAU lookup here followed by a direct physical load.
|
||||||
*/
|
*/
|
||||||
cpu_abort(cs, "Failed to read from %s exception vector table "
|
attrs.secure = targets_secure;
|
||||||
"entry %08x\n", targets_secure ? "secure" : "nonsecure",
|
attrs.user = false;
|
||||||
(unsigned)vec);
|
|
||||||
|
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||||
|
V8M_SAttributes sattrs = {0};
|
||||||
|
|
||||||
|
v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, &sattrs);
|
||||||
|
if (sattrs.ns) {
|
||||||
|
attrs.secure = false;
|
||||||
|
} else if (!targets_secure) {
|
||||||
|
/* NS access to S memory */
|
||||||
|
goto load_fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return addr;
|
|
||||||
|
vector_entry = address_space_ldl(arm_addressspace(cs, attrs), addr,
|
||||||
|
attrs, &result);
|
||||||
|
if (result != MEMTX_OK) {
|
||||||
|
goto load_fail;
|
||||||
|
}
|
||||||
|
*pvec = vector_entry;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
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
|
||||||
|
* 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()).
|
||||||
|
*/
|
||||||
|
exc_secure = targets_secure ||
|
||||||
|
!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK);
|
||||||
|
env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
|
||||||
|
// Unicorn: commented out
|
||||||
|
//armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
|
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
|
||||||
|
@ -5866,8 +5902,6 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = arm_v7m_load_vector(cpu, exc, targets_secure);
|
|
||||||
|
|
||||||
if (push_failed && !ignore_stackfaults) {
|
if (push_failed && !ignore_stackfaults) {
|
||||||
/* Derived exception on callee-saves register stacking:
|
/* Derived exception on callee-saves register stacking:
|
||||||
* we might now want to take a different exception which
|
* we might now want to take a different exception which
|
||||||
|
@ -5877,6 +5911,12 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!arm_v7m_load_vector(cpu, exc, targets_secure, &addr)) {
|
||||||
|
/* Vector load failed: derived exception */
|
||||||
|
v7m_exception_taken(cpu, lr, true, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we've done everything that might cause a derived exception
|
/* Now we've done everything that might cause a derived exception
|
||||||
* we can go ahead and activate whichever exception we're going to
|
* we can go ahead and activate whichever exception we're going to
|
||||||
* take (which might now be the derived exception).
|
* take (which might now be the derived exception).
|
||||||
|
|
Loading…
Reference in a new issue