diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-07-08 20:44:58 +0530 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-07-11 13:19:35 +0100 |
commit | 75fe83564a2e41ac4bfcee72b1d9a590ddd46ebe (patch) | |
tree | 4e3f50a66066442f92b4cc8dbebcfa2285875436 /target/arm/helper.c | |
parent | e67cd1cac26181873496e5fb2464dbeb038e0fcd (diff) | |
download | qemu-75fe83564a2e41ac4bfcee72b1d9a590ddd46ebe.zip qemu-75fe83564a2e41ac4bfcee72b1d9a590ddd46ebe.tar.gz qemu-75fe83564a2e41ac4bfcee72b1d9a590ddd46ebe.tar.bz2 |
target/arm: Trap non-streaming usage when Streaming SVE is active
This new behaviour is in the ARM pseudocode function
AArch64.CheckFPAdvSIMDEnabled, which applies to AArch32
via AArch32.CheckAdvSIMDOrFPEnabled when the EL to which
the trap would be delivered is in AArch64 mode.
Given that ARMv9 drops support for AArch32 outside EL0, the trap EL
detection ought to be trivially true, but the pseudocode still contains
a number of conditions, and QEMU has not yet committed to dropping A32
support for EL[12] when v9 features are present.
Since the computation of SME_TRAP_NONSTREAMING is necessarily different
for the two modes, we might as well preserve bits within TBFLAG_ANY and
allocate separate bits within TBFLAG_A32 and TBFLAG_A64 instead.
Note that DDI0616A.a has typos for bits [22:21] of LD1RO in the table
of instructions illegal in streaming mode.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220708151540.18136-4-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r-- | target/arm/helper.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index e6f37e1..73a5b2b 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6098,6 +6098,32 @@ int sme_exception_el(CPUARMState *env, int el) return 0; } +/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */ +static bool sme_fa64(CPUARMState *env, int el) +{ + if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) { + return false; + } + + if (el <= 1 && !el_is_in_host(env, el)) { + if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) { + return false; + } + } + if (el <= 2 && arm_is_el2_enabled(env)) { + if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) { + return false; + } + } + if (arm_feature(env, ARM_FEATURE_EL3)) { + if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) { + return false; + } + } + + return true; +} + /* * Given that SVE is enabled, return the vector length for EL. */ @@ -10801,6 +10827,20 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, DP_TBFLAG_ANY(flags, PSTATE__IL, 1); } + /* + * The SME exception we are testing for is raised via + * AArch64.CheckFPAdvSIMDEnabled(), as called from + * AArch32.CheckAdvSIMDOrFPEnabled(). + */ + if (el == 0 + && FIELD_EX64(env->svcr, SVCR, SM) + && (!arm_is_el2_enabled(env) + || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE))) + && arm_el_is_aa64(env, 1) + && !sme_fa64(env, el)) { + DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1); + } + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } @@ -10850,6 +10890,7 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, } if (FIELD_EX64(env->svcr, SVCR, SM)) { DP_TBFLAG_A64(flags, PSTATE_SM, 1); + DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el)); } DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA)); } |