@samitouri / QOSamiQemu / commits / fdf3c577a9

target/arm: Add new feature ARM_FEATURE_NEON_TRAPS

The traps configurable via CPACR.ASEDIS and HCPTR.TASE that trap only Neon instructions are unfortunately IMPDEF about whether they are implemented or not, and there is no ID register field that identifies whether they are present. In practice, they are present on every implementation I have checked except for the Cortex-A8 (which was the first CPU with Neon). Add a new feature ARM_FEATURE_NEON_TRAPS which we set on every ARM_FEATURE_NEON CPU except the Cortex-A8, and make the CPACR.ASEDIS and HCPTR.TASE bits RAZ/WI unless the CPU has ARM_FEATURE_NEON and ARM_FEATURE_NEON_TRAPS. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260817123838.1578060-5-peter.maydell@linaro.org

Peter Maydell committed Aug 17, 2026 at 13:38 UTC fdf3c577a966e06e03ede48f17fa905f1ee07c40
6 files changed +42 -2
target/arm/cpu-max.c
+1
@@ -23,6 +23,7 @@ void aarch64_aa32_a57_init(ARMCPU *cpu, bool aarch64_enabled)
23 cpu->dtb_compatible = "arm,cortex-a57";
24 set_feature(&cpu->env, ARM_FEATURE_V8);
25 set_feature(&cpu->env, ARM_FEATURE_NEON);
26 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
27 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
28 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
29 if (aarch64_enabled) {
target/arm/cpu.h
+7
@@ -2177,6 +2177,13 @@ enum arm_features {
2177 * CPU types added in future.
2178 */
2179 ARM_FEATURE_BACKCOMPAT_CNTFRQ, /* 62.5MHz timer default */
2180 + /*
2181 + * ARM_FEATURE_NEON_TRAPS should be set if the CPU implements the
2182 + * CPACR.ASEDIS and HCPTR.TASE bits for trapping A32 Neon. This
2183 + * is architecturally IMPDEF, but seems to be implemented by all
2184 + * ARM_FEATURE_NEON CPUs except the Cortex-A8.
2185 + */
2186 + ARM_FEATURE_NEON_TRAPS,
2187 };
2188
2189 static inline int arm_feature(const CPUARMState *env, int feature)
target/arm/cpu64.c
+1
@@ -699,6 +699,7 @@ static void aarch64_a53_initfn(Object *obj)
699 cpu->dtb_compatible = "arm,cortex-a53";
700 set_feature(&cpu->env, ARM_FEATURE_V8);
701 set_feature(&cpu->env, ARM_FEATURE_NEON);
702 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
703 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
704 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
705 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
target/arm/helper.c
+15 -2
@@ -573,14 +573,20 @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
573 */
574 if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) {
575 /* VFP coprocessor: cp10 & cp11 [23:20] */
576 - mask |= R_CPACR_ASEDIS_MASK |
577 - R_CPACR_D32DIS_MASK |
576 + mask |= R_CPACR_D32DIS_MASK |
577 R_CPACR_CP11_MASK |
578 R_CPACR_CP10_MASK;
579
580 if (!arm_feature(env, ARM_FEATURE_NEON)) {
581 /* ASEDIS [31] bit is RAO/WI */
582 value |= R_CPACR_ASEDIS_MASK;
583 + mask |= R_CPACR_ASEDIS_MASK;
584 + } else if (arm_feature(env, ARM_FEATURE_NEON_TRAPS)) {
585 + /*
586 + * bit is present unless CPU doesn't implement ASEDIS
587 + * (in which case it is RAZ/WI; this is the Cortex-A8)
588 + */
589 + mask |= R_CPACR_ASEDIS_MASK;
590 }
591
592 /*
@@ -4124,6 +4130,13 @@ uint64_t arm_hcrx_el2_eff(CPUARMState *env)
4130 static void cptr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
4131 uint64_t value)
4132 {
4133 + if (!arm_feature(env, ARM_FEATURE_NEON_TRAPS)) {
4134 + /*
4135 + * If CPU doesn't implement HCPTR.TASE it's RAZ/WI. Note that
4136 + * NSACR.NSASEDIS being 1 overrides this.
4137 + */
4138 + value &= ~R_HCPTR_TASE_MASK;
4139 + }
4140 /*
4141 * For A-profile AArch32 EL3, if NSACR.CP10
4142 * is 0 then HCPTR.{TCP11,TCP10} ignore writes and read as 1.
target/arm/tcg/cpu32.c
+8
@@ -251,6 +251,10 @@ static void cortex_a8_initfn(Object *obj)
251 cpu->dtb_compatible = "arm,cortex-a8";
252 set_feature(&cpu->env, ARM_FEATURE_V7);
253 set_feature(&cpu->env, ARM_FEATURE_NEON);
254 + /*
255 + * The Cortex-A8 doesn't have CPACR.ASEDIS and HCPTR.TASE,
256 + * so don't set ARM_FEATURE_NEON_TRAPS.
257 + */
258 set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
259 set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
260 set_feature(&cpu->env, ARM_FEATURE_EL3);
@@ -321,6 +325,7 @@ static void cortex_a9_initfn(Object *obj)
325 cpu->dtb_compatible = "arm,cortex-a9";
326 set_feature(&cpu->env, ARM_FEATURE_V7);
327 set_feature(&cpu->env, ARM_FEATURE_NEON);
328 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
329 set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
330 set_feature(&cpu->env, ARM_FEATURE_EL3);
331 set_feature(&cpu->env, ARM_FEATURE_PMU);
@@ -389,6 +394,7 @@ static void cortex_a7_initfn(Object *obj)
394 cpu->dtb_compatible = "arm,cortex-a7";
395 set_feature(&cpu->env, ARM_FEATURE_V7VE);
396 set_feature(&cpu->env, ARM_FEATURE_NEON);
397 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
398 set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
399 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
400 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
@@ -439,6 +445,7 @@ static void cortex_a15_initfn(Object *obj)
445 cpu->dtb_compatible = "arm,cortex-a15";
446 set_feature(&cpu->env, ARM_FEATURE_V7VE);
447 set_feature(&cpu->env, ARM_FEATURE_NEON);
448 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
449 set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
450 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
451 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
@@ -634,6 +641,7 @@ static void cortex_r52_initfn(Object *obj)
641 set_feature(&cpu->env, ARM_FEATURE_EL2);
642 set_feature(&cpu->env, ARM_FEATURE_PMSA);
643 set_feature(&cpu->env, ARM_FEATURE_NEON);
644 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
645 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
646 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
647 set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
target/arm/tcg/cpu64.c
+10
@@ -37,6 +37,7 @@ static void aarch64_a35_initfn(Object *obj)
37 cpu->dtb_compatible = "arm,cortex-a35";
38 set_feature(&cpu->env, ARM_FEATURE_V8);
39 set_feature(&cpu->env, ARM_FEATURE_NEON);
40 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
41 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
42 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
43 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -208,6 +209,7 @@ static void aarch64_a55_initfn(Object *obj)
209 cpu->dtb_compatible = "arm,cortex-a55";
210 set_feature(&cpu->env, ARM_FEATURE_V8);
211 set_feature(&cpu->env, ARM_FEATURE_NEON);
212 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
213 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
214 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
215 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -281,6 +283,7 @@ static void aarch64_a72_initfn(Object *obj)
283 cpu->dtb_compatible = "arm,cortex-a72";
284 set_feature(&cpu->env, ARM_FEATURE_V8);
285 set_feature(&cpu->env, ARM_FEATURE_NEON);
286 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
287 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
288 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
289 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -341,6 +344,7 @@ static void aarch64_a76_initfn(Object *obj)
344 cpu->dtb_compatible = "arm,cortex-a76";
345 set_feature(&cpu->env, ARM_FEATURE_V8);
346 set_feature(&cpu->env, ARM_FEATURE_NEON);
347 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
348 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
349 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
350 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -415,6 +419,7 @@ static void aarch64_a78ae_initfn(Object *obj)
419 cpu->dtb_compatible = "arm,cortex-a78ae";
420 set_feature(&cpu->env, ARM_FEATURE_V8);
421 set_feature(&cpu->env, ARM_FEATURE_NEON);
422 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
423 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
424 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
425 set_feature(&cpu->env, ARM_FEATURE_EL2);
@@ -488,6 +493,7 @@ static void aarch64_a64fx_initfn(Object *obj)
493 cpu->dtb_compatible = "arm,a64fx";
494 set_feature(&cpu->env, ARM_FEATURE_V8);
495 set_feature(&cpu->env, ARM_FEATURE_NEON);
496 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
497 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
498 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
499 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -662,6 +668,7 @@ static void aarch64_neoverse_n1_initfn(Object *obj)
668 cpu->dtb_compatible = "arm,neoverse-n1";
669 set_feature(&cpu->env, ARM_FEATURE_V8);
670 set_feature(&cpu->env, ARM_FEATURE_NEON);
671 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
672 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
673 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
674 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -738,6 +745,7 @@ static void aarch64_neoverse_v1_initfn(Object *obj)
745 cpu->dtb_compatible = "arm,neoverse-v1";
746 set_feature(&cpu->env, ARM_FEATURE_V8);
747 set_feature(&cpu->env, ARM_FEATURE_NEON);
748 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
749 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
750 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
751 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -965,6 +973,7 @@ static void aarch64_a710_initfn(Object *obj)
973 cpu->dtb_compatible = "arm,cortex-a710";
974 set_feature(&cpu->env, ARM_FEATURE_V8);
975 set_feature(&cpu->env, ARM_FEATURE_NEON);
976 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
977 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
978 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
979 set_feature(&cpu->env, ARM_FEATURE_AARCH64);
@@ -1067,6 +1076,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj)
1076 cpu->dtb_compatible = "arm,neoverse-n2";
1077 set_feature(&cpu->env, ARM_FEATURE_V8);
1078 set_feature(&cpu->env, ARM_FEATURE_NEON);
1079 + set_feature(&cpu->env, ARM_FEATURE_NEON_TRAPS);
1080 set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
1081 set_feature(&cpu->env, ARM_FEATURE_BACKCOMPAT_CNTFRQ);
1082 set_feature(&cpu->env, ARM_FEATURE_AARCH64);