From the diary of AArch64 porter — ID registers

This post is part 14 of the "From the diary of AArch64 porter" series:

  1. From the diary of AArch64 porter — autoconf
  2. From the diary of AArch64 porter — rpm packaging
  3. From the diary of AArch64 porter — testsuites
  4. From the diary of AArch64 porter — POSIX.1 functionality
  5. From the diary of AArch64 porter — PAGE_SIZE
  6. From the diary of AArch64 porter — vfp precision
  7. From the diary of AArch64 porter — system calls
  8. From the diary of AArch64 porter — parallel builds
  9. From the diary of AArch64 porter — firefighting
  10. From the diary of AArch64 porter — drive-by coding
  11. From the diary of AArch64 porter — manylinux2014
  12. From the diary of AArch64 porter — handling big patches
  13. From the diary of AArch64 porter — Arm CPU features table
  14. 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:

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:

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.

aarch64 development edk2 linux python

Comments?

If you want to comment, head over to my post on Mastodon.