Skip to content

Commit 924b9f4

Browse files
author
Nicolas Pitre
committed
tests: arm64: Add comprehensive ARM architecture feature detection test
Add comprehensive test to validate ARM64 architectural feature detection across ARMv8.1 through ARMv9-A implementations, providing runtime verification of processor capabilities and security features. Core architecture features tested: - Exception Level (EL) support detection (EL0-EL3) - SVE (Scalable Vector Extension) presence and capabilities - Advanced SIMD (NEON) and Floating Point implementation levels - Architecture version classification (ARMv8 vs ARMv9-A) ARMv8.1-A+ features: - LSE (Large System Extensions) atomic operations with level detection - Pointer Authentication (PAC) with comprehensive variant analysis: * API/APA (Address), GPI/GPA (Generic) authentication * Enhanced PAC levels (1, 3, 4, 5) with FPACCOMBINE detection * QARMA3 algorithm support (GPA3/APA3) ARMv8.5-A+ security and performance features: - Branch Target Identification (BTI) for control flow integrity - Memory Tagging Extensions (MTE) with level classification - Random Number Generation (RNDR) hardware entropy - Speculative Store Bypass Safe (SSBS) side-channel mitigation ARMv8.7-A+ advanced features: - WFxT (Wait with Timeout) enhanced synchronization - RPRES (Reciprocal Precision) optimized math operations ARMv8.8-A+ features: - MOPS (Memory Copy/Set) optimized memory operations - BC (Branch Consistency) advanced branch handling Signed-off-by: Nicolas Pitre <[email protected]>
1 parent e397c0c commit 924b9f4

File tree

6 files changed

+261
-0
lines changed

6 files changed

+261
-0
lines changed

include/zephyr/arch/arm64/cpu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@
113113
#define ID_AA64PFR0_EL2_SHIFT (8)
114114
#define ID_AA64PFR0_EL3_SHIFT (12)
115115
#define ID_AA64PFR0_ELX_MASK (0xf)
116+
#define ID_AA64PFR0_FP_SHIFT (16)
117+
#define ID_AA64PFR0_FP_MASK (0xf)
118+
#define ID_AA64PFR0_ADVSIMD_SHIFT (20)
119+
#define ID_AA64PFR0_ADVSIMD_MASK (0xf)
120+
#define ID_AA64PFR0_SVE_SHIFT (32)
121+
#define ID_AA64PFR0_SVE_MASK (0xf)
116122
#define ID_AA64PFR0_SEL2_SHIFT (36)
117123
#define ID_AA64PFR0_SEL2_MASK (0xf)
118124

include/zephyr/arch/arm64/lib_helpers.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ MAKE_REG_HELPER(csselr_el1);
6969
MAKE_REG_HELPER(daif)
7070
MAKE_REG_HELPER(hcr_el2);
7171
MAKE_REG_HELPER(id_aa64pfr0_el1);
72+
MAKE_REG_HELPER(id_aa64pfr1_el1);
7273
MAKE_REG_HELPER(id_aa64mmfr0_el1);
74+
MAKE_REG_HELPER(id_aa64isar0_el1);
75+
MAKE_REG_HELPER(id_aa64isar1_el1);
76+
MAKE_REG_HELPER(id_aa64isar2_el1);
7377
MAKE_REG_HELPER(mpidr_el1);
7478
MAKE_REG_HELPER(par_el1);
7579
#if !defined(CONFIG_ARMV8_R)
@@ -199,6 +203,11 @@ static inline bool is_in_secure_state(void)
199203
return !IS_ENABLED(CONFIG_ARMV8_A_NS);
200204
}
201205

206+
static inline bool is_sve_implemented(void)
207+
{
208+
return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT) & ID_AA64PFR0_SVE_MASK) != 0U);
209+
}
210+
202211
#endif /* !_ASMLANGUAGE */
203212

204213
#endif /* ZEPHYR_INCLUDE_ARCH_ARM64_LIB_HELPERS_H_ */
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(arm64_isa_features)
6+
7+
target_sources(app PRIVATE src/main.c)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CONFIG_ZTEST=y
2+
CONFIG_OUTPUT_DISASSEMBLY=y
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Copyright (c) 2025 BayLibre SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/ztest.h>
8+
#include <zephyr/arch/arm64/lib_helpers.h>
9+
#include <stdint.h>
10+
11+
ZTEST_SUITE(arm64_isa_features, NULL, NULL, NULL, NULL, NULL);
12+
13+
ZTEST(arm64_isa_features, test_arm64_feature_detection)
14+
{
15+
uint64_t pfr0 = read_id_aa64pfr0_el1();
16+
uint64_t current_el = read_currentel();
17+
uint64_t mmfr0 = read_id_aa64mmfr0_el1();
18+
19+
TC_PRINT("=== ARM64 ISA Feature Detection ===\n");
20+
TC_PRINT("ID_AA64PFR0_EL1: 0x%016llx\n", pfr0);
21+
TC_PRINT("ID_AA64MMFR0_EL1: 0x%016llx\n", mmfr0);
22+
23+
/* Check for ARMv9-A specific features */
24+
TC_PRINT("\n=== Feature Analysis ===\n");
25+
26+
/* SVE support (Scalable Vector Extension) */
27+
bool sve = is_sve_implemented();
28+
29+
TC_PRINT("SVE support: %s\n", sve ? "YES" : "NO");
30+
31+
/* Current Exception Level */
32+
TC_PRINT("Current EL: EL%llu\n", GET_EL(current_el));
33+
34+
/* Check EL support */
35+
TC_PRINT("EL0 AArch64: %s\n", is_el_implemented(0) ? "YES" : "NO");
36+
TC_PRINT("EL1 AArch64: %s\n", is_el_implemented(1) ? "YES" : "NO");
37+
TC_PRINT("EL2 AArch64: %s\n", is_el_implemented(2) ? "YES" : "NO");
38+
TC_PRINT("EL3 AArch64: %s\n", is_el_implemented(3) ? "YES" : "NO");
39+
40+
/* Advanced SIMD (NEON) */
41+
uint64_t advsimd = (pfr0 >> ID_AA64PFR0_ADVSIMD_SHIFT) & ID_AA64PFR0_ADVSIMD_MASK;
42+
43+
TC_PRINT("Advanced SIMD (NEON): %s (0x%llx)\n",
44+
(advsimd == 0) ? "YES" : (advsimd == 0xf) ? "NO" : "PARTIAL", advsimd);
45+
46+
/* Floating Point */
47+
uint64_t fp = (pfr0 >> ID_AA64PFR0_FP_SHIFT) & ID_AA64PFR0_FP_MASK;
48+
49+
TC_PRINT("Floating Point: %s (0x%llx)\n",
50+
(fp == 0) ? "YES" : (fp == 0xf) ? "NO" : "PARTIAL", fp);
51+
52+
/* Check for additional ARMv8.5-A+ and ARMv9-A indicators */
53+
uint64_t pfr1 = read_id_aa64pfr1_el1();
54+
uint64_t isar0 = read_id_aa64isar0_el1();
55+
uint64_t isar1 = read_id_aa64isar1_el1();
56+
uint64_t isar2 = read_id_aa64isar2_el1();
57+
58+
TC_PRINT("\nID_AA64PFR1_EL1: 0x%016llx\n", pfr1);
59+
TC_PRINT("ID_AA64ISAR0_EL1: 0x%016llx\n", isar0);
60+
TC_PRINT("ID_AA64ISAR1_EL1: 0x%016llx\n", isar1);
61+
TC_PRINT("ID_AA64ISAR2_EL1: 0x%016llx\n", isar2);
62+
63+
/* Check for ARMv8.1 LSE atomics */
64+
uint64_t lse = (isar0 >> 20) & 0xf;
65+
66+
TC_PRINT("LSE Atomics: %s (0x%llx)\n", lse ? "YES" : "NO", lse);
67+
68+
/* Check for Pointer Authentication */
69+
uint64_t pauth_api = (isar1 >> 4) & 0xf;
70+
uint64_t pauth_apa = (isar1 >> 8) & 0xf;
71+
uint64_t pauth_gpi = (isar1 >> 28) & 0xf;
72+
uint64_t pauth_gpa = (isar1 >> 24) & 0xf;
73+
74+
TC_PRINT("Pointer Auth (API - Address ImplDef): %s (0x%llx)\n",
75+
pauth_api ? "YES" : "NO", pauth_api);
76+
TC_PRINT("Pointer Auth (APA - Address Arch): %s (0x%llx)\n",
77+
pauth_apa ? "YES" : "NO", pauth_apa);
78+
TC_PRINT("Pointer Auth (GPI - Instr ImplDef): %s (0x%llx)\n",
79+
pauth_gpi ? "YES" : "NO", pauth_gpi);
80+
TC_PRINT("Pointer Auth (GPA - Instr Arch): %s (0x%llx)\n",
81+
pauth_gpa ? "YES" : "NO", pauth_gpa);
82+
83+
/* Decode APA level */
84+
if (pauth_apa == 0x5) {
85+
TC_PRINT(" APA Level 5: Enhanced PAC with FPACCOMBINE\n");
86+
} else if (pauth_apa == 0x4) {
87+
TC_PRINT(" APA Level 4: Enhanced PAC with FPAC\n");
88+
} else if (pauth_apa == 0x3) {
89+
TC_PRINT(" APA Level 3: Enhanced PAC2\n");
90+
} else if (pauth_apa == 0x1) {
91+
TC_PRINT(" APA Level 1: Basic PAC\n");
92+
}
93+
94+
/* Check for Branch Target Identification (ARMv8.5-A) */
95+
uint64_t bti = (pfr1 >> 0) & 0xf;
96+
97+
TC_PRINT("Branch Target Identification (BTI): %s (0x%llx)\n", bti ? "YES" : "NO", bti);
98+
99+
/* Check for Memory Tagging Extensions (ARMv8.5-A) */
100+
uint64_t mte = (pfr1 >> 8) & 0xf;
101+
102+
TC_PRINT("Memory Tagging Extension (MTE): %s (0x%llx)\n", mte ? "YES" : "NO", mte);
103+
if (mte == 0x2) {
104+
TC_PRINT(" MTE Level 2: Full MTE\n");
105+
} else if (mte == 0x1) {
106+
TC_PRINT(" MTE Level 1: EL0-only\n");
107+
}
108+
109+
/* Check for Random Number Generation (ARMv8.5-A) */
110+
uint64_t rndr = (pfr1 >> 16) & 0xf;
111+
112+
TC_PRINT("Random Number Generation (RNDR): %s (0x%llx)\n", rndr ? "YES" : "NO", rndr);
113+
114+
/* Check for Speculative Store Bypass Safe (ARMv8.5-A) */
115+
uint64_t ssbs = (pfr1 >> 12) & 0xf;
116+
117+
TC_PRINT("Speculative Store Bypass Safe (SSBS): %s (0x%llx)\n", ssbs ? "YES" : "NO", ssbs);
118+
119+
/* Check for additional ISAR2 features */
120+
/* WFxT - Wait For Event/Interrupt with Timeout (ARMv8.7-A) */
121+
uint64_t wfxt = (isar2 >> 0) & 0xf;
122+
123+
TC_PRINT("WFxT (Wait with Timeout): %s (0x%llx)\n", wfxt ? "YES" : "NO", wfxt);
124+
125+
/* RPRES - Reciprocal Estimate and Reciprocal Square Root Estimate */
126+
uint64_t rpres = (isar2 >> 4) & 0xf;
127+
128+
TC_PRINT("RPRES (Reciprocal Precision): %s (0x%llx)\n", rpres ? "YES" : "NO", rpres);
129+
130+
/* GPA3 - Generic Pointer Authentication using QARMA3 */
131+
uint64_t gpa3 = (isar2 >> 8) & 0xf;
132+
133+
TC_PRINT("Pointer Auth (GPA3 - QARMA3): %s (0x%llx)\n", gpa3 ? "YES" : "NO", gpa3);
134+
135+
/* APA3 - Address Pointer Authentication using QARMA3 */
136+
uint64_t apa3 = (isar2 >> 12) & 0xf;
137+
138+
TC_PRINT("Pointer Auth (APA3 - QARMA3): %s (0x%llx)\n", apa3 ? "YES" : "NO", apa3);
139+
140+
/* MOPS - Memory Copy and Memory Set instructions (ARMv8.8-A) */
141+
uint64_t mops = (isar2 >> 16) & 0xf;
142+
143+
TC_PRINT("MOPS (Memory Copy/Set): %s (0x%llx)\n", mops ? "YES" : "NO", mops);
144+
145+
/* BC - BC (Branch Consistency) model */
146+
uint64_t bc = (isar2 >> 20) & 0xf;
147+
148+
TC_PRINT("BC (Branch Consistency): %s (0x%llx)\n", bc ? "YES" : "NO", bc);
149+
150+
TC_PRINT("\n=== Architecture Assessment ===\n");
151+
if (sve) {
152+
TC_PRINT("Architecture: ARMv9-A (SVE detected)\n");
153+
if (bti || mte || rndr) {
154+
TC_PRINT("ARMv8.5-A+ features: ");
155+
if (bti) {
156+
TC_PRINT("BTI ");
157+
}
158+
if (mte) {
159+
TC_PRINT("MTE ");
160+
}
161+
if (rndr) {
162+
TC_PRINT("RNDR ");
163+
}
164+
if (ssbs) {
165+
TC_PRINT("SSBS ");
166+
}
167+
TC_PRINT("\n");
168+
}
169+
if (wfxt || mops || gpa3 || apa3) {
170+
TC_PRINT("ARMv8.7-A+ features: ");
171+
if (wfxt) {
172+
TC_PRINT("WFxT ");
173+
}
174+
if (mops) {
175+
TC_PRINT("MOPS ");
176+
}
177+
if (gpa3) {
178+
TC_PRINT("GPA3 ");
179+
}
180+
if (apa3) {
181+
TC_PRINT("APA3 ");
182+
}
183+
TC_PRINT("\n");
184+
}
185+
} else if (bti || mte || rndr || ssbs) {
186+
TC_PRINT("Architecture: ARMv8.5-A+ (BTI/MTE/RNDR detected)\n");
187+
} else if (lse >= 2 && (pauth_api || pauth_apa)) {
188+
TC_PRINT("Architecture: ARMv8.1+ with enhanced features (LSE Level 2+ and PAC)\n");
189+
} else if (lse || pauth_api || pauth_apa) {
190+
TC_PRINT("Architecture: ARMv8.1+ with ARMv9-A features (LSE/PAC)\n");
191+
} else {
192+
TC_PRINT("Architecture: ARMv8-A (no ARMv8.1+ features detected)\n");
193+
}
194+
195+
/* Decode LSE level */
196+
if (lse >= 2) {
197+
TC_PRINT("LSE Level 2: Atomics with enhanced ordering\n");
198+
} else if (lse == 1) {
199+
TC_PRINT("LSE Level 1: Basic atomic instructions\n");
200+
}
201+
202+
/* Basic validation that we can read system registers */
203+
zassert_not_equal(pfr0, 0, "ID_AA64PFR0_EL1 should not be zero");
204+
zassert_not_equal(current_el, 0, "CurrentEL should not be zero");
205+
206+
/* We should be running in EL1 */
207+
zassert_equal(GET_EL(current_el), 1, "Should be running in EL1");
208+
209+
/* ARMv9-A configuration validation */
210+
if (IS_ENABLED(CONFIG_ARMV9_A)) {
211+
/* ARMv9-A mandates SVE support */
212+
zassert_true(sve, "CONFIG_ARMV9_A enabled but no SVE detected");
213+
214+
/* ARMv9-A should have enhanced security features */
215+
zassert_true(pauth_api || pauth_apa,
216+
"CONFIG_ARMV9_A enabled but no Pointer Authentication detected");
217+
218+
/* If PAC is present, validate it's enhanced (Level 3+) */
219+
if (pauth_apa) {
220+
zassert_true(pauth_apa >= 3,
221+
"CONFIG_ARMV9_A enabled but PAC level too low (0x%llx) - "
222+
"expected enhanced PAC (Level 3+)", pauth_apa);
223+
}
224+
225+
/* ARMv9-A platforms should support modern atomic operations */
226+
zassert_true(lse >= 1,
227+
"CONFIG_ARMV9_A enabled but no LSE atomics detected");
228+
}
229+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
common:
2+
arch_allow: arm64
3+
tags: arm64
4+
5+
tests:
6+
arch.arm64.isa_features:
7+
integration_platforms:
8+
- fvp_base_revc_2xaem/v9a

0 commit comments

Comments
 (0)