Enabling ARM64 CPU Capabilities in the Linux Kernel

ARM64 design defines features long before there is a CPU that can implement those features. Since the ARM ecosystem is so varied, there are many different CPU designs out there with different capabilities. A general purpose linux Kernel build put out by a major distribution has to work across a wide array of chips by a large nuymber of vendors. Thus, there is an enumeration of the capabilities inside the Kernel and mechnism for describing how to probe each of these capabilities.

If we look at the cpufeatures.c file, we can see this array. There is an entry of type struct arm64_cpu_capabilities. This specifies a system register and the fields inside that system register that should be queried by the running Kernel to confirm that the feature is enabled. The System register is of the form SYS_ID_AA64PFR0_EL1. The characters that vary in the middle of the4se constants are

PFR[01]: Processor Feature Register

MMFR[012] Memory Model Feature (0, 1, 2)

ISAR[01] Interrupt Status Register

For example, the very first entry in this list is:

		.desc = "GIC system register CPU interface",
		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
		.matches = has_useable_gicv3_cpuif,
		.sys_reg = SYS_ID_AA64PFR0_EL1,
		.field_pos = ID_AA64PFR0_GIC_SHIFT,
		.field_width = 4,
		.sign = FTR_UNSIGNED,
		.min_field_value = 1,

This feature has a custome .matches entry, which is afunction that is called to see if the CPU m,atches the fetaure (or the feature matches the CPU?)

More of the entries have the simple .matches function of has_cpuid_feature( which calls __read_sysreg_by_encoding. This is mostly a long switch statement that pulls the current value out of the specified sys register. Then checks it against a bitmask.  The function used by the GIC system register code above calls this as well, but also provides additional checks to make sure it was not disabled.

Any one of the matches functions has to provide the following function prototype:

static bool function_name (const struct arm64_cpu_capabilities *entry, int scope)

This set of structures are checked and then added to the colletion cpu_hwcaps_ptrs before being checked. The real check happens from update_cpu_capabilities. The matches function is called inside a loop. During kernel bring up, an information message should be printed for any detected capability:

Notice that the loop is limited by the constant ARM64_NCAPS which is used to specify the maximum number of capabilities currently defined by the ARM64 architecture.

On My AltraMax system with the Centos 8 Kernel running, I get the following set of messages:

$ sudo dmesg | grep detected:
[    0.000000] CPU features: detected: GIC system register CPU interface
[    0.000000] CPU features: detected: Virtualization Host Extensions
[    0.000000] CPU features: detected: Hardware dirty bit management
[    0.000000] CPU features: detected: Spectre-v4
[    0.000000] CPU features: detected: Spectre-BHB
[    0.000000] CPU features: detected: Kernel page table isolation (KPTI)
[    0.000000] CPU features: detected: ARM erratum 1418040
[    0.037751] CPU features: detected: 32-bit EL0 Support
[    0.037752] CPU features: detected: Data cache clean to the PoU not required for I/D coherence
[    0.037753] CPU features: detected: Common not Private translations
[    0.037754] CPU features: detected: CRC32 instructions
[    0.037755] CPU features: detected: Data cache clean to Point of Persistence
[    0.037757] CPU features: detected: RCpc load-acquire (LDAPR)
[    0.037757] CPU features: detected: LSE atomic instructions
[    0.037758] CPU features: detected: Privileged Access Never
[    0.037759] CPU features: detected: RAS Extension Support
[    0.037761] CPU features: detected: Speculative Store Bypassing Safe (SSBS)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.