mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-25 04:55:31 +00:00
target/arm: Factor out code to calculate FSR for debug exceptions
When a debug exception is taken to AArch32, it appears as a Prefetch Abort, and the Instruction Fault Status Register (IFSR) must be set. The IFSR has two possible formats, depending on whether LPAE is in use. Factor out the code in arm_debug_excp_handler() which picks an FSR value into its own utility function, update it to use arm_fi_to_lfsc() and arm_fi_to_sfsc() rather than hard-coded constants, and use the correct condition to select long or short format. In particular this fixes a bug where we could select the short format because we're at EL0 and the EL1 translation regime is not using LPAE, but then route the debug exception to EL2 because of MDCR_EL2.TDE and hand EL2 the wrong format FSR. Backports commit 81621d9ab8a0f07956e67850b15eebf6d6992eec from qemu
This commit is contained in:
parent
7a3ee5fd95
commit
16c0c2d253
|
@ -765,4 +765,29 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the FSR value for a debug exception (watchpoint, hardware
|
||||||
|
* breakpoint or BKPT insn) targeting the specified exception level.
|
||||||
|
*/
|
||||||
|
static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
|
||||||
|
{
|
||||||
|
ARMMMUFaultInfo fi = { ARMFault_Debug };
|
||||||
|
int target_el = arm_debug_target_el(env);
|
||||||
|
bool using_lpae = false;
|
||||||
|
|
||||||
|
if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
|
||||||
|
using_lpae = true;
|
||||||
|
} else {
|
||||||
|
if (arm_feature(env, ARM_FEATURE_LPAE) &&
|
||||||
|
(env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
|
||||||
|
using_lpae = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (using_lpae) {
|
||||||
|
return arm_fi_to_lfsc(&fi);
|
||||||
|
} else {
|
||||||
|
return arm_fi_to_sfsc(&fi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1311,11 +1311,7 @@ void arm_debug_excp_handler(CPUState *cs)
|
||||||
|
|
||||||
cs->watchpoint_hit = NULL;
|
cs->watchpoint_hit = NULL;
|
||||||
|
|
||||||
if (extended_addresses_enabled(env)) {
|
env->exception.fsr = arm_debug_exception_fsr(env);
|
||||||
env->exception.fsr = (1 << 9) | 0x22;
|
|
||||||
} else {
|
|
||||||
env->exception.fsr = 0x2;
|
|
||||||
}
|
|
||||||
env->exception.vaddress = wp_hit->hitaddr;
|
env->exception.vaddress = wp_hit->hitaddr;
|
||||||
raise_exception(env, EXCP_DATA_ABORT,
|
raise_exception(env, EXCP_DATA_ABORT,
|
||||||
syn_watchpoint(same_el, 0, wnr),
|
syn_watchpoint(same_el, 0, wnr),
|
||||||
|
@ -1335,11 +1331,7 @@ void arm_debug_excp_handler(CPUState *cs)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extended_addresses_enabled(env)) {
|
env->exception.fsr = arm_debug_exception_fsr(env);
|
||||||
env->exception.fsr = (1 << 9) | 0x22;
|
|
||||||
} else {
|
|
||||||
env->exception.fsr = 0x2;
|
|
||||||
}
|
|
||||||
/* FAR is UNKNOWN, so doesn't need setting */
|
/* FAR is UNKNOWN, so doesn't need setting */
|
||||||
raise_exception(env, EXCP_PREFETCH_ABORT,
|
raise_exception(env, EXCP_PREFETCH_ABORT,
|
||||||
syn_breakpoint(same_el),
|
syn_breakpoint(same_el),
|
||||||
|
|
Loading…
Reference in a new issue