summaryrefslogtreecommitdiffstats
path: root/ArmPkg
diff options
context:
space:
mode:
authorMarcin Juszkiewicz <marcin.juszkiewicz@linaro.org>2023-04-21 17:51:16 +0200
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-04-21 18:50:05 +0000
commit2c2cb235289642775a7c4e6eaeffa6d3828d279c (patch)
tree33f758a153d7b9a0f7c4a5501d2f08e6337e5809 /ArmPkg
parenta7c8969d03bb025020948fe9ababf428033de668 (diff)
downloadedk2-2c2cb235289642775a7c4e6eaeffa6d3828d279c.tar.gz
edk2-2c2cb235289642775a7c4e6eaeffa6d3828d279c.tar.bz2
edk2-2c2cb235289642775a7c4e6eaeffa6d3828d279c.zip
ArmPkg: add ArmCpuInfo EFI application
App goes through ID_AA64*_EL1 system registers and decode their values. Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org> Reviewed-by: Leif Lindholm <quic_llindhol@quicinc.com>
Diffstat (limited to 'ArmPkg')
-rw-r--r--ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.c2430
-rw-r--r--ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.inf31
-rw-r--r--ArmPkg/ArmPkg.dsc1
3 files changed, 2462 insertions, 0 deletions
diff --git a/ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.c b/ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.c
new file mode 100644
index 0000000000..deea90fbdf
--- /dev/null
+++ b/ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.c
@@ -0,0 +1,2430 @@
+/** @file
+ Application to present AArch64 cpu information.
+
+ Based on ARM DDI 0487I.a. Update this information when the
+ app is updated with features from subsequent releases.
+
+Copyright (c) 2023, Linaro Ltd. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiLib.h>
+#include <Library/ArmLib/AArch64/AArch64Lib.h>
+
+// We cannot assume GCC extensions to be present so let use
+// binary numbers via enum.
+// Arm ARM uses binary numbers so this way it is more readable.
+enum {
+ b0000,
+ b0001,
+ b0010,
+ b0011,
+ b0100,
+ b0101,
+ b0110,
+ b0111,
+ b1000,
+ b1001,
+ b1010,
+ b1011,
+ b1100,
+ b1101,
+ b1110,
+ b1111
+};
+
+/**
+ Print formatted table line.
+
+ Values can be empty if only new description line is needed.
+
+ @param[in] Field name of system register
+ @param[in] Bits bits of system register
+ @param[in] Value value of those bits
+ @param[in] Description meaning of value
+**/
+VOID
+PrintText (
+ CONST CHAR8 *Field,
+ CONST CHAR8 *Bits,
+ CONST CHAR8 *Value,
+ CONST CHAR8 *Description
+ )
+{
+ AsciiPrint (" %-16a | %5a | %5a | %a\n", Field, Bits, Value, Description);
+}
+
+/**
+ Print formatted table line with value printed in binary.
+
+ @param[in] Field name of system register
+ @param[in] Bits bits of system register
+ @param[in] Value value of those bits
+ @param[in] Description meaning of value
+**/
+VOID
+PrintValues (
+ CONST CHAR8 *Field,
+ CONST CHAR8 *Bits,
+ CONST UINT8 Value,
+ CONST CHAR8 *Description
+ )
+{
+ STATIC CONST CHAR8 Nibbles[][5] = {
+ "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
+ "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
+ };
+
+ AsciiPrint (" %-16a | %5a | %5a | %a\n", Field, Bits, Nibbles[Value & 0xf], Description);
+}
+
+/**
+ Print spacer for results table.
+**/
+VOID
+PrintSpacer (
+ VOID
+ )
+{
+ AsciiPrint ("------------------|-------|-------|----------------------------------------------\n");
+}
+
+/**
+ Handle ID_AA64DFR0_EL1 system register.
+
+ @param[in] Aa64Dfr0 value of ID_AA64DFR0_EL1 system register
+**/
+VOID
+HandleAa64Dfr0 (
+ CONST UINT64 Aa64Dfr0
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64DFR0";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = (Aa64Dfr0 >> 4) & 0xf;
+ switch (Value) {
+ case b0110:
+ Description = "Armv8 debug architecture";
+ break;
+ case b0111:
+ Description = "Armv8 debug architecture with VHE";
+ break;
+ case b1000:
+ Description = "FEAT_Debugv8p2 implemented.";
+ break;
+ case b1001:
+ Description = "FEAT_Debugv8p4 implemented.";
+ break;
+ case b1010:
+ Description = "FEAT_Debugv8p8 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "7:4 ";
+ Value = (Aa64Dfr0 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Trace unit System registers not implemented.";
+ break;
+ case b0001:
+ Description = "Trace unit System registers implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Dfr0 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Performance Monitors Extension not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PMUv3 implemented.";
+ break;
+ case b0100:
+ Description = "FEAT_PMUv3p1 implemented.";
+ break;
+ case b0101:
+ Description = "FEAT_PMUv3p4 implemented.";
+ break;
+ case b0110:
+ Description = "FEAT_PMUv3p5 implemented.";
+ break;
+ case b0111:
+ Description = "FEAT_PMUv3p7 implemented.";
+ break;
+ case b1000:
+ Description = "FEAT_PMUv3p8 implemented.";
+ break;
+ case b1111:
+ Description = "IMPLEMENTATION DEFINED form of performance monitors supported.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "15:12";
+ Value = (Aa64Dfr0 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "reserved";
+ break;
+ default:
+ Description = "Number of breakpoints, minus 1.";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 19:16 reserved
+
+ Bits = "23:20";
+ Value = (Aa64Dfr0 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "reserved";
+ break;
+ default:
+ Description = "Number of watchpoints, minus 1.";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 27:24 reserved
+
+ Bits = "31:28";
+ Value = (Aa64Dfr0 >> 28) & 0xf;
+ switch (Value) {
+ default:
+ Description = "Number of breakpoints that are context-aware, minus 1.";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "35:32";
+ Value = (Aa64Dfr0 >> 32) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SPE not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SPE implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_SPEv1p1 implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_SPEv1p2 implemented.";
+ break;
+ case b0100:
+ Description = "FEAT_SPEv1p3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "39:36";
+ Value = (Aa64Dfr0 >> 36) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_DoubleLock implemented.";
+ break;
+ case b1111:
+ Description = "FEAT_DoubleLock not implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "43:40";
+ Value = (Aa64Dfr0 >> 40) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TRF not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_TRF implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "47:44";
+ Value = (Aa64Dfr0 >> 44) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TRBE not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_TRBE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "51:48";
+ Value = (Aa64Dfr0 >> 48) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_MTPMU not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_MTPMU and FEAT_PMUv3 implemented.";
+ break;
+ case b1111:
+ Description = "FEAT_MTPMU not implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "55:52";
+ Value = (Aa64Dfr0 >> 52) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_BRBE not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_BRBE implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_BRBEv1p1 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 59:56 reserved
+
+ Bits = "63:60";
+ Value = (Aa64Dfr0 >> 60) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Setting MDCR_EL2.HPMN to zero has CONSTRAINED UNPREDICTABLE behavior.";
+ break;
+ case b0001:
+ Description = "FEAT_HPMN0 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+}
+
+/**
+ Handle ID_AA64ISAR0_EL1 system register.
+
+ @param[in] Aa64Isar0 value of ID_AA64ISAR0_EL1 system register
+**/
+VOID
+HandleAa64Isar0 (
+ CONST UINT64 Aa64Isar0
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64ISAR0";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ // 3:0 reserved
+
+ Bits = "7:4 ";
+ Value = (Aa64Isar0 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_AES, FEAT_PMULL not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_AES implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_AES and FEAT_PMULL implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Isar0 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SHA1 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SHA1 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "15:12";
+ Value = (Aa64Isar0 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SHA256, FEAT_SHA512 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SHA256 implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_SHA512 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "19:16";
+ Value = (Aa64Isar0 >> 16) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "CRC32 not implemented.";
+ break;
+ case b0001:
+ Description = "CRC32 instructions implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "23:20";
+ Value = (Aa64Isar0 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_LSE not implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_LSE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "27:24";
+ Value = (Aa64Isar0 >> 24) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "TME instructions not implemented.";
+ break;
+ case b0001:
+ Description = "TME instructions implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "31:28";
+ Value = (Aa64Isar0 >> 28) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_RDM not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_RDM implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "35:32";
+ Value = (Aa64Isar0 >> 32) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SHA3 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SHA3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "39:36";
+ Value = (Aa64Isar0 >> 36) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SM3 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SM3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "43:40";
+ Value = (Aa64Isar0 >> 40) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SM4 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SM4 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "47:44";
+ Value = (Aa64Isar0 >> 44) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_DotProd not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_DotProd implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "51:48";
+ Value = (Aa64Isar0 >> 48) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_FHM not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_FHM implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "55:52";
+ Value = (Aa64Isar0 >> 52) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_FlagM/FEAT_FlagM2 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_FlagM implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_FlagM2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "59:56";
+ Value = (Aa64Isar0 >> 56) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TLBIOS/FEAT_TLBIRANGE not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_TLBIOS implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_TLBIRANGE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "63:60";
+ Value = (Aa64Isar0 >> 60) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_RNG not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_RNG implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+}
+
+/**
+ Handle ID_AA64ISAR1_EL1 system register.
+
+ @param[in] Aa64Isar1 value of ID_AA64ISAR1_EL1 system register
+**/
+VOID
+HandleAa64Isar1 (
+ CONST UINT64 Aa64Isar1
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64ISAR1";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = (Aa64Isar1 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "DC CVAP not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_DPB implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_DPB2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "7:4 ";
+ Value = (Aa64Isar1 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Address Authentication (APA) not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PAuth implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_EPAC implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_PAuth2 implemented.";
+ break;
+ case b0100:
+ Description = "FEAT_FPAC implemented.";
+ break;
+ case b0101:
+ Description = "FEAT_FPACCOMBINE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+ if (Value > 0) {
+ PrintText ("", "", "", "FEAT_PACQARMA5 implemented.");
+ }
+
+ Bits = "11:8 ";
+ Value = (Aa64Isar1 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Address Authentication (API) not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PAuth implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_EPAC implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_PAuth2 implemented.";
+ break;
+ case b0100:
+ Description = "FEAT_FPAC implemented.";
+ break;
+ case b0101:
+ Description = "FEAT_FPACCOMBINE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+ if (Value > 0) {
+ PrintText ("", "", "", "FEAT_PACIMP implemented.");
+ }
+
+ Bits = "15:12";
+ Value = (Aa64Isar1 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_JSCVT not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_JSCVT implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "19:16";
+ Value = (Aa64Isar1 >> 16) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_FCMA not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_FCMA implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "23:20";
+ Value = (Aa64Isar1 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_LRCPC (2) not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_LRCPC implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_LRCPC2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "27:24";
+ Value = (Aa64Isar1 >> 24) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_PACQARMA5 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PACQARMA5 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "31:28";
+ Value = (Aa64Isar1 >> 28) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_PACIMP not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PACIMP implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "35:32";
+ Value = (Aa64Isar1 >> 32) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_FRINTTS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_FRINTTS implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "39:36";
+ Value = (Aa64Isar1 >> 36) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SB not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SB implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "43:40";
+ Value = (Aa64Isar1 >> 40) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SPECRES not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SPECRES implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "47:44";
+ Value = (Aa64Isar1 >> 44) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_BF16 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_BF16 implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_EBF16 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "51:48";
+ Value = (Aa64Isar1 >> 48) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_DGH not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_DGH implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "55:52";
+ Value = (Aa64Isar1 >> 52) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_I8MM not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_I8MM implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "59:56";
+ Value = (Aa64Isar1 >> 56) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_XS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_XS implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "63:60";
+ Value = (Aa64Isar1 >> 60) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_LS64 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_LS64 implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_LS64_V implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_LS64_ACCDATA implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+}
+
+/**
+ Handle ID_AA64ISAR2_EL1 system register.
+
+ @param[in] Aa64Isar2 value of ID_AA64ISAR2_EL1 system register
+**/
+VOID
+HandleAa64Isar2 (
+ CONST UINT64 Aa64Isar2
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64ISAR2";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = (Aa64Isar2 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_WFxT not implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_WFxT implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "7:4 ";
+ Value = (Aa64Isar2 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_RPRES not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_RPRES implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Isar2 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_PACQARMA3 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PACQARMA3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "15:12";
+ Value = (Aa64Isar2 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Address Authentication (APA3) not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PAuth implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_EPAC implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_PAuth2 implemented.";
+ break;
+ case b0100:
+ Description = "FEAT_FPAC implemented.";
+ break;
+ case b0101:
+ Description = "FEAT_FPACCOMBINE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "19:16";
+ Value = (Aa64Isar2 >> 16) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_MOPS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_MOPS implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "23:20";
+ Value = (Aa64Isar2 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_HBC not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_HBC implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "27:24";
+ Value = (Aa64Isar2 >> 24) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_CONSTPACFIELD not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_CONSTPACFIELD implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 63:28 reserved
+}
+
+/**
+ Handle ID_AA64MMFR0_EL1 system register.
+
+ @param[in] Aa64Mmfr0 value of ID_AA64MMFR0_EL1 system register
+**/
+VOID
+HandleAa64Mmfr0 (
+ CONST UINT64 Aa64Mmfr0
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64MMFR0";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = Aa64Mmfr0 & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "32 Bits (4GB) of physical address range supported.";
+ break;
+ case b0001:
+ Description = "36 Bits (64GB) of physical address range supported.";
+ break;
+ case b0010:
+ Description = "40 Bits (1TB) of physical address range supported.";
+ break;
+ case b0011:
+ Description = "42 Bits (4TB) of physical address range supported.";
+ break;
+ case b0100:
+ Description = "44 Bits (16TB) of physical address range supported.";
+ break;
+ case b0101:
+ Description = "48 Bits (256TB) of physical address range supported.";
+ break;
+ case b0110:
+ Description = "52 Bits (4PB) of physical address range supported.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+ if (Value == b0110) {
+ PrintText ("", "", "", "FEAT_LPA implemented.");
+ }
+
+ Bits = "7:4 ";
+ Value = (Aa64Mmfr0 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "ASID: 8 Bits";
+ break;
+ case b0010:
+ Description = "ASID: 16 Bits";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Mmfr0 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "No mixed-endian support.";
+ break;
+ case b0001:
+ Description = "Mixed-endian support.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // If mixed-endian is present, check whether supported at EL0
+ if (((Aa64Mmfr0 >> 8) & 0xf) != b0000 ) {
+ if (((Aa64Mmfr0 >> 16) & 0xf) == b0000 ) {
+ PrintValues ("ID_AA64MMFR0", "19:16", b0000, "No mixed-endian support at EL0.");
+ }
+
+ if (((Aa64Mmfr0 >> 16) & 0xf) == b0001 ) {
+ PrintValues ("ID_AA64MMFR0", "19:16", b0001, "Mixed-endian support at EL0.");
+ }
+ }
+
+ Bits = "15:12";
+ Value = (Aa64Mmfr0 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "No support for a distinction between Secure and Non-Secure Memory.";
+ break;
+ case b0001:
+ Description = "Supports a distinction between Secure and Non-Secure Memory.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "31:28";
+ Value = (Aa64Mmfr0 >> 28) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = " 4KB granule supported.";
+ break;
+ case b1111:
+ Description = " 4KB granule not supported.";
+ break;
+ case b0001:
+ Description = " 4KB granule supported for 52-bit address.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "43:40";
+ Value = (Aa64Mmfr0 >> 40) & 0xf;
+ switch (Value) {
+ case b0001:
+ Description = " 4KB granule not supported at stage 2.";
+ break;
+ case b0010:
+ Description = " 4KB granule supported at stage 2.";
+ break;
+ case b0011:
+ Description = " 4KB granule supported at stage 2 for 52-bit address.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "23:20";
+ Value = (Aa64Mmfr0 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "16KB granule not supported.";
+ break;
+ case b0001:
+ Description = "16KB granule supported.";
+ break;
+ case b0010:
+ Description = "16KB granule supported for 52-bit address.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "35:32";
+ Value = (Aa64Mmfr0 >> 32) & 0xf;
+ switch (Value) {
+ case b0001:
+ Description = "16KB granule not supported at stage 2.";
+ break;
+ case b0010:
+ Description = "16KB granule supported at stage 2.";
+ break;
+ case b0011:
+ Description = "16KB granule supported at stage 2 for 52-bit address.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "27:24";
+ Value = (Aa64Mmfr0 >> 24) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "64KB granule supported.";
+ break;
+ case b1111:
+ Description = "64KB granule not supported.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "39:36";
+ Value = (Aa64Mmfr0 >> 36) & 0xf;
+ switch (Value) {
+ case b0001:
+ Description = "64KB granule not supported at stage 2.";
+ break;
+ case b0010:
+ Description = "64KB granule supported at stage 2.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "47:44";
+ Value = (Aa64Mmfr0 >> 44) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_ExS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_ExS implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 55:48 reserved
+
+ Bits = "59:56";
+ Value = (Aa64Mmfr0 >> 56) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_FGT not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_FGT implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "63:60";
+ Value = (Aa64Mmfr0 >> 60) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_ECV not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_ECV implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_ECV implemented with extras.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+}
+
+/**
+ Handle ID_AA64MMFR1_EL1 system register.
+
+ @param[in] Aa64Mmfr1 value of ID_AA64MMFR1_EL1 system register
+ @param[in] Aa64Pfr0, value of ID_AA64PFR0_EL1 system register
+**/
+VOID
+HandleAa64Mmfr1 (
+ CONST UINT64 Aa64Mmfr1,
+ CONST UINT64 Aa64Pfr0
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64MMFR1";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = Aa64Mmfr1 & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_HAFDBS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_HAFDBS implemented without dirty status support.";
+ break;
+ case b0010:
+ Description = "FEAT_HAFDBS implemented with dirty status support.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "7:4 ";
+ Value = (Aa64Mmfr1 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_VMID16 not implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_VMID16 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Mmfr1 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_VHE not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_VHE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "15:12";
+ Value = (Aa64Mmfr1 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_HPDS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_HPDS implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_HPDS2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "19:16";
+ Value = (Aa64Mmfr1 >> 16) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_LOR not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_LOR implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "23:20";
+ Value = (Aa64Mmfr1 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_PAN not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_PAN implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_PAN2 implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_PAN3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // when FEAT_RAS implemented
+ if ((((Aa64Pfr0 >> 28) & 0xf) == b0001) ||
+ (((Aa64Pfr0 >> 28) & 0xf) == b0010))
+ {
+ if (((Aa64Mmfr1 >> 24) & 0xf) == b0000 ) {
+ PrintValues ("ID_AA64MMFR1", "27:24", b0000, "The PE never generates an SError interrupt due to");
+ PrintText ("", "", "", "an External abort on a speculative read.");
+ }
+
+ if (((Aa64Mmfr1 >> 24) & 0xf) == b0001 ) {
+ PrintValues ("ID_AA64MMFR1", "27:24", b0001, "The PE might generate an SError interrupt due to");
+ PrintText ("", "", "", "an External abort on a speculative read.");
+ }
+ }
+
+ Bits = "31:28";
+ Value = (Aa64Mmfr1 >> 28) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_XNX not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_XNX implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "35:32";
+ Value = (Aa64Mmfr1 >> 32) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TWED not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_TWED implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "39:36";
+ Value = (Aa64Mmfr1 >> 36) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_ETS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_ETS implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "43:40";
+ Value = (Aa64Mmfr1 >> 40) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_HCX not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_HCX implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "47:44";
+ Value = (Aa64Mmfr1 >> 44) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_AFP not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_AFP implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "51:48";
+ Value = (Aa64Mmfr1 >> 48) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_nTLBPA not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_nTLBPA implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "55:52";
+ Value = (Aa64Mmfr1 >> 52) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TIDCP1 not implemented";
+ break;
+ case b0001:
+ Description = "FEAT_TIDCP1 implemented";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "59:56";
+ Value = (Aa64Mmfr1 >> 56) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_CMOW not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_CMOW implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 63:60 reserved
+}
+
+/**
+ Handle ID_AA64MMFR2_EL1 system register.
+
+ @param[in] Aa64Mmfr2 value of ID_AA64MMFR2_EL1 system register
+**/
+VOID
+HandleAa64Mmfr2 (
+ CONST UINT64 Aa64Mmfr2
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64MMFR2";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = (Aa64Mmfr2) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TTCNP not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_TTCNP implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "7:4 ";
+ Value = (Aa64Mmfr2 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_UAO not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_UAO implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Mmfr2 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_LSMAOC not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_LSMAOC implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "15:12";
+ Value = (Aa64Mmfr2 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_IESB not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_IESB implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "19:16";
+ Value = (Aa64Mmfr2 >> 16) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_LVA not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_LVA implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "23:20";
+ Value = (Aa64Mmfr2 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_CCIDX not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_CCIDX implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "27:24";
+ Value = (Aa64Mmfr2 >> 24) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_NV not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_NV implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_NV2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "31:28";
+ Value = (Aa64Mmfr2 >> 28) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TTST not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_TTST implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "35:32";
+ Value = (Aa64Mmfr2 >> 32) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_LSE2 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_LSE2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "39:36";
+ Value = (Aa64Mmfr2 >> 36) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_IDST not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_IDST implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "43:40";
+ Value = (Aa64Mmfr2 >> 40) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_S2FWB not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_S2FWB implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 47:44 reserved
+
+ Bits = "51:48";
+ Value = (Aa64Mmfr2 >> 48) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_TTL not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_TTL implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "55:52";
+ Value = (Aa64Mmfr2 >> 52) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_BBM: Level 0 support for changing block size is supported.";
+ break;
+ case b0001:
+ Description = "FEAT_BBM: Level 1 support for changing block size is supported.";
+ break;
+ case b0010:
+ Description = "FEAT_BBM: Level 2 support for changing block size is supported.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "59:56";
+ Value = (Aa64Mmfr2 >> 56) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_EVT not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_EVT: HCR_EL2.{TOCU, TICAB, TID4} traps are supported.";
+ break;
+ case b0010:
+ Description = "FEAT_EVT: HCR_EL2.{TTLBOS, TTLSBIS, TOCU, TICAB, TID4} traps are supported.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "63:60";
+ Value = (Aa64Mmfr2 >> 60) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_E0PD not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_E0PD implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+}
+
+/**
+ Handle ID_AA64PFR0_EL1 system register.
+
+ @param[in] Aa64Pfr0, value of ID_AA64PFR0_EL1 system register
+ @param[in] Aa64Pfr1, value of ID_AA64PFR1_EL1 system register
+**/
+VOID
+HandleAa64Pfr0 (
+ CONST UINT64 Aa64Pfr0,
+ CONST UINT64 Aa64Pfr1
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64PFR0";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = (Aa64Pfr0) & 0xf;
+ switch (Value) {
+ case b0001:
+ Description = "EL0 in AArch64 only";
+ break;
+ case b0010:
+ Description = "EL0 in AArch64 and AArch32";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "7:4 ";
+ Value = (Aa64Pfr0 >> 4) & 0xf;
+ switch (Value) {
+ case b0001:
+ Description = "EL1 in AArch64 only";
+ break;
+ case b0010:
+ Description = "EL1 in AArch64 and AArch32";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Pfr0 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "EL2 not implemented.";
+ break;
+ case b0001:
+ Description = "EL2 in AArch64 only";
+ break;
+ case b0010:
+ Description = "EL2 in AArch64 and AArch32";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "15:12";
+ Value = (Aa64Pfr0 >> 12) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "EL3 not implemented.";
+ break;
+ case b0001:
+ Description = "EL3 in AArch64 only";
+ break;
+ case b0010:
+ Description = "EL3 in AArch64 and AArch32";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "19:16";
+ Value = (Aa64Pfr0 >> 16) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Floating-point implemented.";
+ break;
+ case b0001:
+ Description = "Floating-point with half-precision support (FEAT_FP16).";
+ break;
+ case b1111:
+ Description = "Floating-point not implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "23:20";
+ Value = (Aa64Pfr0 >> 20) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Advanced SIMD implemented.";
+ break;
+ case b0001:
+ Description = "Advanced SIMD with half precision support (FEAT_FP16).";
+ break;
+ case b1111:
+ Description = "Advanced SIMD not implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "27:24";
+ Value = (Aa64Pfr0 >> 24) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "System registers of GIC CPU not implemented.";
+ break;
+ case b0001:
+ Description = "System registers to versions 3.0/4.0 of GIC CPU implemented.";
+ break;
+ case b0011:
+ Description = "System registers to versions 4.1 of GIC CPU implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "31:28";
+ Value = (Aa64Pfr0 >> 28) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_RAS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_RAS implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_RASv1p1 implemented.";
+ // b0010 FEAT_RASv1p1 implemented and, if EL3 is implemented, FEAT_DoubleFault implemented.
+ if ((((Aa64Pfr0 >> 12) & 0xf) == b0001) ||
+ (((Aa64Pfr0 >> 12) & 0xf) == b0010))
+ {
+ Description = "FEAT_RASv1p1 implemented. FEAT_DoubleFault implemented.";
+ }
+
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+ if (Value == b0001) {
+ if (((Aa64Pfr1 >> 12) & 0xf) == b0001 ) {
+ PrintValues ("ID_AA64PRF1", "15:12", b0001, "FEAT_RASv1p1 implemented.");
+ }
+ }
+
+ Bits = "35:32";
+ Value = (Aa64Pfr0 >> 32) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SVE not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SVE implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "39:36";
+ Value = (Aa64Pfr0 >> 36) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Secure EL2 not implemented.";
+ break;
+ case b0001:
+ Description = "Secure EL2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "43:40";
+ Value = (Aa64Pfr0 >> 40) & 0xf;
+ switch (Value) {
+ case b0000:
+ if (((Aa64Pfr1 >> 16) & 0xf) == b0000 ) {
+ Description = "FEAT_MPAM not implemented.";
+ }
+
+ if (((Aa64Pfr1 >> 16) & 0xf) == b0001 ) {
+ Description = "FEAT_MPAM v0.1 implemented.";
+ }
+
+ break;
+ case b0001:
+ if (((Aa64Pfr1 >> 16) & 0xf) == b0000 ) {
+ Description = "FEAT_MPAM v1.0 implemented.";
+ }
+
+ if (((Aa64Pfr1 >> 16) & 0xf) == b0001 ) {
+ Description = "FEAT_MPAM v1.1 implemented.";
+ }
+
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "47:44";
+ Value = (Aa64Pfr0 >> 44) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_AMU not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_AMUv1 implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_AMUv1p1 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "51:48";
+ Value = (Aa64Pfr0 >> 48) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_DIT not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_DIT implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "55:52";
+ Value = (Aa64Pfr0 >> 52) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_RME not implemented";
+ break;
+ case b0001:
+ Description = "FEAT_RME implemented";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "59:56";
+ Value = (Aa64Pfr0 >> 56) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "Not disclosed whether FEAT_CSV2 is implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_CSV2 implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_CSV2_2 implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_CSV2_3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+ if (Value == b0001) {
+ if (((Aa64Pfr1 >> 32) & 0xf) == b0001 ) {
+ PrintValues ("ID_AA64PRF1", "35:32", b0001, "FEAT_CSV2_1p1 implemented.");
+ }
+
+ if (((Aa64Pfr1 >> 32) & 0xf) == b0010 ) {
+ PrintValues ("ID_AA64PRF1", "35:32", b0010, "FEAT_CSV2_1p2 implemented.");
+ }
+ }
+
+ Bits = "63:60";
+ Value = (Aa64Pfr0 >> 60) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_CSV3 not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_CSV3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+}
+
+/**
+ Handle ID_AA64PFR1_EL1 system register.
+
+ @param[in] Aa64Pfr1 value of ID_AA64PFR1_EL1 system register
+**/
+VOID
+HandleAa64Pfr1 (
+ CONST UINT64 Aa64Pfr1
+ )
+{
+ UINT64 Value;
+ STATIC CONST CHAR8 RegName[] = "ID_AA64PFR1";
+ CONST CHAR8 *Description;
+ CONST CHAR8 *Bits;
+
+ Bits = "3:0 ";
+ Value = Aa64Pfr1 & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_BTI not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_BTI implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "7:4 ";
+ Value = (Aa64Pfr1 >> 4) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SSBS not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SSBS implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_SSBS2 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "11:8 ";
+ Value = (Aa64Pfr1 >> 8) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_MTE not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_MTE implemented.";
+ break;
+ case b0010:
+ Description = "FEAT_MTE2 implemented.";
+ break;
+ case b0011:
+ Description = "FEAT_MTE3 implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 15:12 is RAS_frac
+ // 19:16 is MPAM_frac
+ // 23:20 is reserved
+
+ Bits = "27:24";
+ Value = (Aa64Pfr1 >> 24) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_SME not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_SME implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ Bits = "31:28";
+ Value = (Aa64Pfr1 >> 28) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_RNG_TRAP not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_RNG_TRAP implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 35:32 is CSV2_frac
+
+ Bits = "39:36";
+ Value = (Aa64Pfr1 >> 36) & 0xf;
+ switch (Value) {
+ case b0000:
+ Description = "FEAT_NMI not implemented.";
+ break;
+ case b0001:
+ Description = "FEAT_NMI implemented.";
+ break;
+ default:
+ Description = "unknown";
+ break;
+ }
+
+ PrintValues (RegName, Bits, Value, Description);
+
+ // 63:40 are reserved
+}
+
+/**
+ The user Entry Point for Application. The user code starts with this function
+ as the real entry point for the application.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT64 Aa64Dfr0;
+ UINT64 Aa64Isar0;
+ UINT64 Aa64Isar1;
+ UINT64 Aa64Isar2;
+ UINT64 Aa64Mmfr0;
+ UINT64 Aa64Mmfr1;
+ UINT64 Aa64Mmfr2;
+ UINT64 Aa64Pfr0;
+ UINT64 Aa64Pfr1;
+
+ Aa64Dfr0 = ArmReadIdAA64Dfr0 ();
+ Aa64Isar0 = ArmReadIdAA64Isar0 ();
+ Aa64Isar1 = ArmReadIdAA64Isar1 ();
+ Aa64Isar2 = ArmReadIdAA64Isar2 ();
+ Aa64Mmfr0 = ArmReadIdAA64Mmfr0 ();
+ Aa64Mmfr1 = ArmReadIdAA64Mmfr1 ();
+ Aa64Mmfr2 = ArmReadIdAA64Mmfr2 ();
+ Aa64Pfr0 = ArmReadIdAA64Pfr0 ();
+ Aa64Pfr1 = ArmReadIdAA64Pfr1 ();
+
+ AsciiPrint ("ID_AA64MMFR0_EL1 = 0x%016lx\n", Aa64Mmfr0);
+ AsciiPrint ("ID_AA64MMFR1_EL1 = 0x%016lx\n", Aa64Mmfr1);
+ AsciiPrint ("ID_AA64MMFR2_EL1 = 0x%016lx\n", Aa64Mmfr2);
+ AsciiPrint ("ID_AA64PFR0_EL1 = 0x%016lx\n", Aa64Pfr0);
+ AsciiPrint ("ID_AA64PFR1_EL1 = 0x%016lx\n", Aa64Pfr1);
+ AsciiPrint ("ID_AA64ISAR0_EL1 = 0x%016lx\n", Aa64Isar0);
+ AsciiPrint ("ID_AA64ISAR1_EL1 = 0x%016lx\n", Aa64Isar1);
+ AsciiPrint ("ID_AA64ISAR2_EL1 = 0x%016lx\n", Aa64Isar2);
+ AsciiPrint ("ID_AA64DFR0_EL1 = 0x%016lx\n", Aa64Dfr0);
+ AsciiPrint ("\n");
+
+ PrintText ("Register", "Bits", "Value", "Feature");
+ PrintSpacer ();
+
+ HandleAa64Mmfr0 (Aa64Mmfr0);
+ PrintSpacer ();
+ HandleAa64Mmfr1 (Aa64Mmfr1, Aa64Pfr0);
+ PrintSpacer ();
+ HandleAa64Mmfr2 (Aa64Mmfr2);
+
+ PrintSpacer ();
+ HandleAa64Pfr0 (Aa64Pfr0, Aa64Pfr1);
+ PrintSpacer ();
+ HandleAa64Pfr1 (Aa64Pfr1);
+
+ PrintSpacer ();
+ HandleAa64Isar0 (Aa64Isar0);
+ PrintSpacer ();
+ HandleAa64Isar1 (Aa64Isar1);
+ PrintSpacer ();
+ HandleAa64Isar2 (Aa64Isar2);
+
+ PrintSpacer ();
+ HandleAa64Dfr0 (Aa64Dfr0);
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.inf b/ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.inf
new file mode 100644
index 0000000000..da29548a7f
--- /dev/null
+++ b/ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.inf
@@ -0,0 +1,31 @@
+## @file
+# Application to present AArch64 cpu information.
+#
+# Based on HelloWorld:
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2023, Linaro Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010019
+ BASE_NAME = ArmCpuInfo
+ FILE_GUID = b3134491-6502-4faf-a9da-007184e32163
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UefiMain
+
+[Sources]
+ ArmCpuInfo.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmLib
+ UefiApplicationEntryPoint
+ UefiLib
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
index 3fb95d1951..6b938ce8b6 100644
--- a/ArmPkg/ArmPkg.dsc
+++ b/ArmPkg/ArmPkg.dsc
@@ -166,6 +166,7 @@
ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
+ ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.inf
[Components.AARCH64, Components.ARM]
ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf