mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-26 07:26:50 +00:00
target-arm: Fix "no 64-bit EL2" assumption in arm_excp_unmasked()
The code in arm_excp_unmasked() suppresses the ability of PSTATE.AIF to mask exceptions from a lower EL targeting EL2 or EL3 if the CPU is 64-bit. This is correct for a target of EL3, but not correct for targeting EL2. Further, we go to some effort to calculate scr and hcr values which are not used at all for the 64-bit CPU case. Rearrange the code to correctly implement the 64-bit CPU logic and keep the hcr/scr calculations in the 32-bit CPU codepath. Backports commit 7cd6de3bb1ca55dfa8f53fb9894803eb33f497b3 from qemu
This commit is contained in:
parent
828d48d077
commit
91941f8d3c
|
@ -1539,8 +1539,6 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
|
||||||
CPUARMState *env = cs->env_ptr;
|
CPUARMState *env = cs->env_ptr;
|
||||||
unsigned int cur_el = arm_current_el(env);
|
unsigned int cur_el = arm_current_el(env);
|
||||||
bool secure = arm_is_secure(env);
|
bool secure = arm_is_secure(env);
|
||||||
bool scr;
|
|
||||||
bool hcr;
|
|
||||||
bool pstate_unmasked;
|
bool pstate_unmasked;
|
||||||
int8_t unmasked = 0;
|
int8_t unmasked = 0;
|
||||||
|
|
||||||
|
@ -1554,30 +1552,9 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
|
||||||
|
|
||||||
switch (excp_idx) {
|
switch (excp_idx) {
|
||||||
case EXCP_FIQ:
|
case EXCP_FIQ:
|
||||||
/* If FIQs are routed to EL3 or EL2 then there are cases where we
|
|
||||||
* override the CPSR.F in determining if the exception is masked or
|
|
||||||
* not. If neither of these are set then we fall back to the CPSR.F
|
|
||||||
* setting otherwise we further assess the state below.
|
|
||||||
*/
|
|
||||||
hcr = (env->cp15.hcr_el2 & HCR_FMO);
|
|
||||||
scr = (env->cp15.scr_el3 & SCR_FIQ);
|
|
||||||
|
|
||||||
/* When EL3 is 32-bit, the SCR.FW bit controls whether the CPSR.F bit
|
|
||||||
* masks FIQ interrupts when taken in non-secure state. If SCR.FW is
|
|
||||||
* set then FIQs can be masked by CPSR.F when non-secure but only
|
|
||||||
* when FIQs are only routed to EL3.
|
|
||||||
*/
|
|
||||||
scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr);
|
|
||||||
pstate_unmasked = !(env->daif & PSTATE_F);
|
pstate_unmasked = !(env->daif & PSTATE_F);
|
||||||
break;
|
break;
|
||||||
case EXCP_IRQ:
|
case EXCP_IRQ:
|
||||||
/* When EL3 execution state is 32-bit, if HCR.IMO is set then we may
|
|
||||||
* override the CPSR.I masking when in non-secure state. The SCR.IRQ
|
|
||||||
* setting has already been taken into consideration when setting the
|
|
||||||
* target EL, so it does not have a further affect here.
|
|
||||||
*/
|
|
||||||
hcr = (env->cp15.hcr_el2 & HCR_IMO);
|
|
||||||
scr = false;
|
|
||||||
pstate_unmasked = !(env->daif & PSTATE_I);
|
pstate_unmasked = !(env->daif & PSTATE_I);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1603,14 +1580,59 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
|
||||||
* interrupt.
|
* interrupt.
|
||||||
*/
|
*/
|
||||||
if ((target_el > cur_el) && (target_el != 1)) {
|
if ((target_el > cur_el) && (target_el != 1)) {
|
||||||
/* ARM_FEATURE_AARCH64 enabled means the highest EL is AArch64.
|
/* Exceptions targeting a higher EL may not be maskable */
|
||||||
* This code currently assumes that EL2 is not implemented
|
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
|
||||||
* (and so that highest EL will be 3 and the target_el also 3).
|
/* 64-bit masking rules are simple: exceptions to EL3
|
||||||
|
* can't be masked, and exceptions to EL2 can only be
|
||||||
|
* masked from Secure state. The HCR and SCR settings
|
||||||
|
* don't affect the masking logic, only the interrupt routing.
|
||||||
*/
|
*/
|
||||||
if (arm_feature(env, ARM_FEATURE_AARCH64) ||
|
if (target_el == 3 || !secure) {
|
||||||
((scr || hcr) && (!secure))) {
|
|
||||||
unmasked = 1;
|
unmasked = 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* The old 32-bit-only environment has a more complicated
|
||||||
|
* masking setup. HCR and SCR bits not only affect interrupt
|
||||||
|
* routing but also change the behaviour of masking.
|
||||||
|
*/
|
||||||
|
bool hcr, scr;
|
||||||
|
|
||||||
|
switch (excp_idx) {
|
||||||
|
case EXCP_FIQ:
|
||||||
|
/* If FIQs are routed to EL3 or EL2 then there are cases where
|
||||||
|
* we override the CPSR.F in determining if the exception is
|
||||||
|
* masked or not. If neither of these are set then we fall back
|
||||||
|
* to the CPSR.F setting otherwise we further assess the state
|
||||||
|
* below.
|
||||||
|
*/
|
||||||
|
hcr = (env->cp15.hcr_el2 & HCR_FMO);
|
||||||
|
scr = (env->cp15.scr_el3 & SCR_FIQ);
|
||||||
|
|
||||||
|
/* When EL3 is 32-bit, the SCR.FW bit controls whether the
|
||||||
|
* CPSR.F bit masks FIQ interrupts when taken in non-secure
|
||||||
|
* state. If SCR.FW is set then FIQs can be masked by CPSR.F
|
||||||
|
* when non-secure but only when FIQs are only routed to EL3.
|
||||||
|
*/
|
||||||
|
scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr);
|
||||||
|
break;
|
||||||
|
case EXCP_IRQ:
|
||||||
|
/* When EL3 execution state is 32-bit, if HCR.IMO is set then
|
||||||
|
* we may override the CPSR.I masking when in non-secure state.
|
||||||
|
* The SCR.IRQ setting has already been taken into consideration
|
||||||
|
* when setting the target EL, so it does not have a further
|
||||||
|
* affect here.
|
||||||
|
*/
|
||||||
|
hcr = (env->cp15.hcr_el2 & HCR_IMO);
|
||||||
|
scr = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((scr || hcr) && !secure) {
|
||||||
|
unmasked = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The PSTATE bits only mask the interrupt if we have not overridden the
|
/* The PSTATE bits only mask the interrupt if we have not overridden the
|
||||||
|
|
Loading…
Reference in a new issue