[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking
From: |
Peter Maydell |
Subject: |
Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking |
Date: |
Fri, 24 Oct 2014 17:25:33 +0100 |
On 21 October 2014 17:55, Greg Bellows <address@hidden> wrote:
> From: Fabian Aggeler <address@hidden>
>
> This patch extends arm_excp_unmasked() according to ARM ARMv7 and
> ARM ARMv8 (all EL running in AArch32) and adds comments.
>
> If EL3 is using AArch64 IRQ/FIQ masking is ignored in
> all exception levels other than EL3 if SCR.{FIQ|IRQ} is
> set to 1 (routed to EL3).
>
> Signed-off-by: Fabian Aggeler <address@hidden>
> Signed-off-by: Greg Bellows <address@hidden>
>
> ==========
>
> v5 -> v6
> - Globally change Aarch# to AArch#
> - Fixed comment termination
>
> v4 -> v5
> - Merge with v4 patch 10
>
> Signed-off-by: Greg Bellows <address@hidden>
> ---
> target-arm/cpu.h | 117
> ++++++++++++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 107 insertions(+), 10 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index cb6ec5c..1a564b9 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1246,11 +1246,8 @@ static inline bool arm_excp_unmasked(CPUState *cs,
> unsigned int excp_idx)
> {
> CPUARMState *env = cs->env_ptr;
> unsigned int cur_el = arm_current_el(env);
> - unsigned int target_el = arm_excp_target_el(cs, excp_idx);
> - /* FIXME: Use actual secure state. */
> - bool secure = false;
> - /* If in EL1/0, Physical IRQ routing to EL2 only happens from NS state.
> */
> - bool irq_can_hyp = !secure && cur_el < 2 && target_el == 2;
> + bool secure = arm_is_secure(env);
> +
> /* ARMv7-M interrupt return works by loading a magic value
> * into the PC. On real hardware the load causes the
> * return to occur. The qemu implementation performs the
> @@ -1265,19 +1262,119 @@ static inline bool arm_excp_unmasked(CPUState *cs,
> unsigned int excp_idx)
> && (!IS_M(env) || env->regs[15] < 0xfffffff0);
>
> /* Don't take exceptions if they target a lower EL. */
> - if (cur_el > target_el) {
> + if (cur_el > arm_excp_target_el(cs, excp_idx)) {
> return false;
> }
>
> + /* ARM ARMv7 B1.8.6 Asynchronous exception masking (table B1-12/B1-13)
> + * ARM ARMv8 G1.11.3 Asynchronous exception masking controls
> + * (table G1-18/G1-19)
> + */
> switch (excp_idx) {
> case EXCP_FIQ:
> - if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_FMO)) {
> - return true;
> + if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
> + /* If EL3 is using AArch64 and FIQs are routed to EL3 masking is
> + * ignored in all exception levels except EL3.
> + */
> + if ((env->cp15.scr_el3 & SCR_FIQ) && cur_el < 3) {
Why are we recalculating whether the target level is EL3 by looking
at SCR_EL3.SCR_FIQ, rather than using the target_el which
arm_excp_target_el() returns?
> + return true;
> + }
> + /* If we are in EL3 but FIQs are not routed to EL3 the exception
> + * is not taken but remains pending.
> + */
> + if (!(env->cp15.scr_el3 & SCR_FIQ) && cur_el == 3) {
> + return false;
Isn't this unreachable? If SCR_FIQ is clear then arm_excp_target_el()
will have returned either 1 or 2, and so we'll have returned false
due to the check on cur_el earlier.
> + }
> + }
> + if (!secure) {
> + if (arm_feature(env, ARM_FEATURE_EL2)) {
> + if (env->cp15.hcr_el2 & HCR_FMO) {
> + /* CPSR.F/PSTATE.F ignored if
> + * - exception is taken from Non-secure state
> + * - HCR.FMO == 1
> + * - either: - not in Hyp mode
> + * - SCR.FIQ routes exception to monitor mode
> + * (EL3 in AArch32)
> + */
> + if (cur_el < 2) {
> + return true;
> + } else if (arm_feature(env, ARM_FEATURE_EL3) &&
> + (env->cp15.scr_el3 & SCR_FIQ) &&
> + !arm_el_is_aa64(env, 3)) {
> + return true;
> + }
> + } else if (arm_el_is_aa64(env, 3) &&
> + (env->cp15.scr_el3 & SCR_RW) &&
> + cur_el == 2) {
> + /* FIQs not routed to EL2 but currently in EL2 (A64).
> + * Exception is not taken but remains pending. */
> + return false;
> + }
> + }
> + /* In ARMv7 only applies if both Security Extensions (EL3) and
> + * Hypervirtualization Extensions (EL2) implemented, while
> + * for ARMv8 it applies also if only EL3 implemented.
> + */
> + if (arm_feature(env, ARM_FEATURE_EL3) &&
> + (arm_feature(env, ARM_FEATURE_EL2) ||
> + arm_feature(env, ARM_FEATURE_V8))) {
> + /* CPSR.F/PSTATE.F ignored if
> + * - exception is taken from Non-secure state
> + * - SCR.FIQ routes exception to monitor mode
> + * - SCR.FW bit is set to 0
> + * - HCR.FMO == 0 (if EL2 implemented)
> + */
> + if ((env->cp15.scr_el3 & SCR_FIQ) &&
> + !(env->cp15.scr_el3 & SCR_FW)) {
Something odd here -- in ARMv8 SCR_EL3 bit 4 is RES1, so this test
should never pass -- either this check is wrong or the check on
ARM_FEATURE_V8 in the outer if() is wrong, presumably.
> + if (!arm_feature(env, ARM_FEATURE_EL2)) {
> + return true;
> + } else if (!(env->cp15.hcr_el2 & HCR_FMO)) {
> + return true;
> + }
> + }
> + }
> }
> return !(env->daif & PSTATE_F);
> case EXCP_IRQ:
> - if (irq_can_hyp && (env->cp15.hcr_el2 & HCR_IMO)) {
> - return true;
> + if (arm_feature(env, ARM_FEATURE_EL3) && arm_el_is_aa64(env, 3)) {
> + /* If EL3 is using AArch64 and IRQs are routed to EL3 masking is
> + * ignored in all exception levels except EL3.
> + */
> + if ((env->cp15.scr_el3 & SCR_IRQ) && cur_el < 3) {
> + return true;
> + }
> + /* If we are in EL3 but IRQ s are not routed to EL3 the exception
> + * is not taken but remains pending.
> + */
> + if (!(env->cp15.scr_el3 & SCR_IRQ) && cur_el == 3) {
> + return false;
> + }
> + }
> + if (!secure) {
> + if (arm_feature(env, ARM_FEATURE_EL2)) {
> + if (env->cp15.hcr_el2 & HCR_IMO) {
> + /* CPSR.I/PSTATE.I ignored if
> + * - exception is taken from Non-secure state
> + * - HCR.IMO == 1
> + * - either: - not in Hyp mode
> + * - SCR.IRQ routes exception to monitor mode
> + * (EL3 in AArch32)
> + */
> + if (cur_el < 2) {
> + return true;
> + } else if (arm_feature(env, ARM_FEATURE_EL3) &&
> + (env->cp15.scr_el3 & SCR_IRQ) &&
> + !arm_el_is_aa64(env, 3)) {
> + return true;
> + }
> + } else if (arm_el_is_aa64(env, 3) &&
> + (env->cp15.scr_el3 & SCR_RW) &&
> + cur_el == 2) {
> + /* IRQs not routed to EL2 but currently in EL2 (A64).
> + * Exception is not taken but remains pending. */
> + return false;
> + }
> + }
> }
> return irq_unmasked;
> case EXCP_VFIQ:
> --
> 1.8.3.2
I have to say I find this set of nested conditionals pretty confusing,
and hard to relate to the tables in the ARM ARM. Maybe it would be better
if we actually had a set of data tables in our implementation which
we used to look up whether the exception should be always taken,
remain pending, or honour the PSTATE mask flag ?
I think it would also be good if our implementation tried to keep
the same separation of routing [ie "which exception level is this
exception going to go to?"] and masking [ie "do we take this exception
at this time?"] which the ARM ARM has. At the moment we sort of
have that in the arm_excp_target_el() and this function, but a lot
of the code here seems to be repeating bits of the routing calculation.
thanks
-- PMM
- [Qemu-devel] [PATCH v7 01/32] target-arm: increase arrays of registers R13 & R14, (continued)
- [Qemu-devel] [PATCH v7 01/32] target-arm: increase arrays of registers R13 & R14, Greg Bellows, 2014/10/21
- [Qemu-devel] [PATCH v7 02/32] target-arm: add arm_is_secure() function, Greg Bellows, 2014/10/21
- [Qemu-devel] [PATCH v7 05/32] target-arm: make arm_current_el() return EL3, Greg Bellows, 2014/10/21
- [Qemu-devel] [PATCH v7 10/32] target-arm: add non-secure Translation Block flag, Greg Bellows, 2014/10/21
- [Qemu-devel] [PATCH v7 08/32] target-arm: add async excp target_el function, Greg Bellows, 2014/10/21
- [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking, Greg Bellows, 2014/10/21
- Re: [Qemu-devel] [PATCH v7 07/32] target-arm: extend async excp masking,
Peter Maydell <=
[Qemu-devel] [PATCH v7 09/32] target-arm: add banked register accessors, Greg Bellows, 2014/10/21
[Qemu-devel] [PATCH v7 06/32] target-arm: A32: Emulate the SMC instruction, Greg Bellows, 2014/10/21
[Qemu-devel] [PATCH v7 04/32] target-arm: rename arm_current_pl to arm_current_el, Greg Bellows, 2014/10/21