]> xenbits.xensource.com Git - ovmf.git/commitdiff
ArmPkg: add ArmCpuInfo EFI application
authorMarcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
Fri, 21 Apr 2023 15:51:16 +0000 (17:51 +0200)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 21 Apr 2023 18:50:05 +0000 (18:50 +0000)
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>
ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.c [new file with mode: 0644]
ArmPkg/Application/ArmCpuInfo/ArmCpuInfo.inf [new file with mode: 0644]
ArmPkg/ArmPkg.dsc

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