This post is part 14 of the "From the diary of AArch64 porter" series:
- From the diary of AArch64 porter — autoconf
- From the diary of AArch64 porter — rpm packaging
- From the diary of AArch64 porter — testsuites
- From the diary of AArch64 porter — POSIX.1 functionality
- From the diary of AArch64 porter — PAGE_SIZE
- From the diary of AArch64 porter — vfp precision
- From the diary of AArch64 porter — system calls
- From the diary of AArch64 porter — parallel builds
- From the diary of AArch64 porter — firefighting
- From the diary of AArch64 porter — drive-by coding
- From the diary of AArch64 porter — manylinux2014
- From the diary of AArch64 porter — handling big patches
- From the diary of AArch64 porter — Arm CPU features table
- From the diary of AArch64 porter — ID registers
People are used to looking at “Features” field in the /proc/cpuinfo file under
Linux. But does it show everything about the CPU cores present in the system?
What ID registers?
AArch64 CPUs have a set of “identification registers” which are named “ID_AA64*_EL1”, where “*” can be:
- AFR — Auxiliary Feature Registers
- DFR — Debug Feature Registers
- FPFR — Floating-Point Feature Registers
- ISAR — Instruction Set Attribute Registers
- MMFR — Memory Model Feature Registers
- PFR — Processor Feature Registers
- SMFR — SME Feature ID Registers
- ZFR — SVE Feature ID Registers
They can be used to check which features are present in a given CPU core. Their presence depends on things like age, generation, revision, and the design of the SoC.
Introductions of registers
As the AArch64 architecture was progressing, more and more identification registers were needed to describe CPU core features.
From a quick look through Arm docs, I compiled a simple table of chronology:
| ID register | Architecture version | Year | First Arm core |
|---|---|---|---|
| ID_AA64DFR0_EL1 | v8.0-A | 2011/2012 | Cortex-A53, Cortex-A57 |
| ID_AA64PFR0_EL1 | v8.0-A | 2011/2012 | Cortex-A53, Cortex-A57 |
| ID_AA64ISAR0_EL1 | v8.0-A | 2011/2012 | Cortex-A53, Cortex-A57 |
| ID_AA64MMFR0_EL1 | v8.0-A | 2011/2012 | Cortex-A53, Cortex-A57 |
| ID_AA64AFR0_EL1 | v8.0-A | 2013/2014 | Cortex-A53, Cortex-A73 |
| ID_AA64AFR1_EL1 | v8.0-A | 2013/2014 | Cortex-A53, Cortex-A73 |
| ID_AA64DFR1_EL1 | v8.0-A | 2013/2014 | Cortex-A53, Cortex-A73 |
| ID_AA64PFR1_EL1 | v8.0-A | 2013/2014 | Cortex-A53, Cortex-A73 |
| ID_AA64ISAR1_EL1 | v8.0-A | 2013/2014 | Cortex-A53, Cortex-A73 |
| ID_AA64MMFR1_EL1 | v8.0-A | 2013/2014 | Cortex-A53, Cortex-A73 |
| ID_AA64MMFR2_EL1 | v8.2-A | 2016 | Cortex-A55, Cortex-A75 |
| ID_AA64ZFR0_EL1 | v8.2-A (SVE) | 2017 | Fujitsu A64FX, Cortex-A710 |
| ID_AA64MMFR3_EL1 | v8.3-A | 2017 | Cortex-X4 |
| ID_AA64ISAR2_EL1 | v8.5-A | 2018 | Cortex-A520 |
| ID_AA64ISAR3_EL1 | v8.5-A | 2018 | Cortex-A520 |
| ID_AA64MMFR4_EL1 | v8.7-A | 2021 | Cortex-A715 |
| ID_AA64SMFR0_EL1 | v9.0-A (SME) | 2021 | Neoverse V1 |
| ID_AA64FPFR0_EL1 | v9.5-A | 2023 | |
| ID_AA64PFR2_EL1 | v8.9-A/9.5-A | 2023 | C1 |
I am not 100% sure about years and architecture versions. Not every document has all versions available on the Arm developer website.
It also shows that the Cortex-A53 was a very popular core design — it had multiple revisions, which added several features.
How to read those?
In my opinion, the easiest way is to use my ArmCpuInfo tool. It runs on any EFI environment (EDK2, U-Boot, and so on), reads the ID registers and prints their meaning. I wrote about it some time ago.
Empty registers
A TRM document may list an ID register, explain all its fields, and it still can look like something to ignore because it only contains zeros. Like the ID_AA64MMFR3_EL1 register in the Neoverse-V3 TRM:
- SpecFPACC
- ADERR
- SDERR
- RPZ
- ANERR
- SNERR
- D128_2
- D128
- MEC
- AIE
- S2POE
- S1POE
- S2PIE
- S1PIE
- SCTLRX
- TCRX
All those fields have descriptions and they mean something. At the same time, they all have a 0b0000 value. I assume that the value of some fields may change when the SoC vendor pays more and begins designing its own version of a CPU core based on Arm’s design.
Strange cases
Cortex-A75 present in the MediaTek Helio G70 SoC reports SSBS (Speculative Store Bypass Safe) feature under Linux:
processor : 6
BogoMIPS : 26.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp
asimdhp cpuid asimdrdm lrcpc dcpop asimddp asimddp sha512 ssbs
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x3
CPU part : 0xd0a
CPU revision : 1
But to read it, you need the ID_AA64PRF1_EL1 register, which is not mentioned in the Cortex-A75 technical reference manual (TRM). It is present in the newer versions of the Cortex-A55 TRM, and both CPU core models are present in the Helio G70 SoC.
SSBS (and SSBS2) were introduced into Arm v8.5 and then added to v8.0 to allow every CPU core to have it implemented.
Let me list it for you
As you may know, I have a page about ARM CPU cores where I list some basic information. Last weekend I added showing of potential CPU features to it. Small example:
| CPU core name | features |
|---|---|
| Cortex-A53 | AA32EL0, AA32EL1, AA32EL2, AA32EL3, AA64EL0, AA64EL1, AA64EL2, AA64EL3, AES, ASID16, AdvSIMD, CRC32, Debugv8, DoubleLock, FP, MixedEnd, MixedEndEL0, PMULL, PMUv3, SHA1, SHA256 |
| Cortex-A520 | AA64EL0, AA64EL1, AA64EL2, AA64EL3, AES, AFP, AMUv1, ASID16, AdvSIMD, BBM, BF16, BTI, CCIDX, CONSTPACFIELD, CRC32, CSV2_2, CSV3, DGH, DIT, DPB2, Debugv8p4, DotProd, E0PD, ECBHB, ECV_POFF, EVT, FCMA, FGT, FHM, FP, FP16, FRINTTS, FlagM2, HAFDBS, HCX, HPDS2, HPMN0, I8MM, IDST, IESB, JSCVT, LOR, LRCPC, LRCPC2, LSE, LSE2, MTE3, MixedEnd, MixedEndEL0, PACQARMA3, PAN3, PAuth2, PMULL, PMUv3p7, RASv1p1, RDM, S2FWB, SB, SHA1, SHA256, SHA3, SHA512, SM3, SM4, SPECRES, SSBS2, SVE, SVE2, SVE_AES, SVE_BitPerm, SVE_PMULL128, SVE_SHA3, SVE_SM4, TLBIOS, TLBIRANGE, TRBE, TRF, TTCNP, TTL, TTST, UAO, VHE, VMID16, XNX, XS, nTLBPA |
There may be some mistakes in the table — I strongly advise checking Technical Reference Manuals (TRMs) to be sure. Please report any error — I will take a look at fixing them.