[Lldb-commits] [lldb] [lldb][AArch64][Linux] Add register field information for SME's SVCR register (PR #71809)

David Spickett via lldb-commits lldb-commits at lists.llvm.org
Thu Nov 9 06:09:01 PST 2023


https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/71809

This register is a pseudo register but mirrors the architectural
register's contents. See:
https://developer.arm.com/documentation/ddi0616/latest/

For the full details. Example output:
```
(lldb) register read svcr
    svcr = 0x0000000000000002
         = (ZA = 1, SM = 0)
```

>From 92e5fc0bf7f5a72a1d89f505715db6a7756b3d52 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Wed, 11 Oct 2023 16:17:33 +0100
Subject: [PATCH 1/2] [lldb][AArch64][Linux] Add field information for the
 mte_ctrl register

This is a Linux pseudo register provided by the NT_ARM_TAGGED_ADDR_CTRL
register set. It reflects the value passed to prctl PR_SET_TAGGED_ADDR_CTRL.

https://docs.kernel.org/arch/arm64/memory-tagging-extension.html

The fields are made from the #defines the kernel provides for setting
the value. Its contents are constant so no runtime detection is needed
(once we've decided we have this register in the first place).

The permitted generated tags is technically a bitfield but
at this time we don't have a way to mark a field as preferring hex
formatting.

```
(lldb) register read mte_ctrl
mte_ctrl = 0x000000000007fffb
         = (TAGS = 65535, TCF_ASYNC = 0, TCF_SYNC = 1, TAGGED_ADDR_ENABLE = 1)
```

(4 bit tags mean 16 possible tags, 16 bit bitfield)

Testing has been added to TestMTECtrlRegister.py, which needed a more
granular way to check for XML support, so I've added hasXMLSupport
that can be used within a test case instead of skipping whole tests
if XML isn't supported.

Same for the core file tests.
---
 .../Python/lldbsuite/test/lldbtest.py         | 11 ++++++++
 .../Utility/RegisterFlagsLinux_arm64.cpp      | 13 +++++++++
 .../Utility/RegisterFlagsLinux_arm64.h        |  4 ++-
 .../TestMTECtrlRegister.py                    | 27 +++++++++++++------
 .../TestAArch64LinuxMTEMemoryTagCoreFile.py   |  9 ++++++-
 5 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index 15e8ba21266c896..19ba0e8c133edcf 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -1224,6 +1224,17 @@ def dumpSessionInfo(self):
     # (enables reading of the current test configuration)
     # ====================================================
 
+    def hasXMLSupport(self):
+        """Returns True if lldb was built with XML support. Use this check to
+        enable parts of tests, if you want to skip a whole test use skipIfXmlSupportMissing
+        instead."""
+        return (
+            lldb.SBDebugger.GetBuildConfiguration()
+            .GetValueForKey("xml")
+            .GetValueForKey("value")
+            .GetBooleanValue(False)
+        )
+
     def isMIPS(self):
         """Returns true if the architecture is MIPS."""
         arch = self.getArchitecture()
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
index 87f2464a9eb4868..ca247b628abe78f 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
@@ -24,6 +24,19 @@
 
 using namespace lldb_private;
 
+LinuxArm64RegisterFlags::Fields
+LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) {
+  (void)hwcap;
+  (void)hwcap2;
+  // Represents the contents of NT_ARM_TAGGED_ADDR_CTRL and the value passed
+  // to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines
+  // used to build the value.
+  return {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT.
+          {"TCF_ASYNC", 2},
+          {"TCF_SYNC", 1},
+          {"TAGGED_ADDR_ENABLE", 0}};
+}
+
 LinuxArm64RegisterFlags::Fields
 LinuxArm64RegisterFlags::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
   std::vector<RegisterFlags::Field> fpcr_fields{
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
index 651a8c86f7c86a9..deff977a03d0a12 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
@@ -58,6 +58,7 @@ class LinuxArm64RegisterFlags {
   static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2);
   static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
   static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
+  static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2);
 
   struct RegisterEntry {
     RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
@@ -67,10 +68,11 @@ class LinuxArm64RegisterFlags {
     llvm::StringRef m_name;
     RegisterFlags m_flags;
     DetectorFn m_detector;
-  } m_registers[3] = {
+  } m_registers[4] = {
       RegisterEntry("cpsr", 4, DetectCPSRFields),
       RegisterEntry("fpsr", 4, DetectFPSRFields),
       RegisterEntry("fpcr", 4, DetectFPCRFields),
+      RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields),
   };
 
   // Becomes true once field detection has been run for all registers.
diff --git a/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py b/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py
index 7fd6b2dada640e6..3eaca00b0dccca9 100644
--- a/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py
+++ b/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py
@@ -34,17 +34,28 @@ def test_mte_ctrl_register(self):
             substrs=["stop reason = breakpoint 1."],
         )
 
-        # Bit 0 = tagged addressing enabled
-        # Bit 1 = synchronous faults
-        # Bit 2 = asynchronous faults
-        # We start enabled with synchronous faults.
-        self.expect("register read mte_ctrl", substrs=["0x0000000000000003"])
+        def check_mte_ctrl(async_err, sync_err):
+            # Bit 0 = tagged addressing enabled
+            # Bit 1 = synchronous faults
+            # Bit 2 = asynchronous faults
+            value = "0x{:016x}".format((async_err << 2) | (sync_err << 1) | 1)
+            expected = [value]
+
+            if self.hasXMLSupport():
+                expected.append(
+                    "(TAGS = 0, TCF_ASYNC = {}, TCF_SYNC = {}, TAGGED_ADDR_ENABLE = 1)".format(
+                        async_err, sync_err
+                    )
+                )
+
+            self.expect("register read mte_ctrl", substrs=expected)
 
+        # We start enabled with synchronous faults.
+        check_mte_ctrl(0, 1)
         # Change to asynchronous faults.
         self.runCmd("register write mte_ctrl 5")
-        self.expect("register read mte_ctrl", substrs=["0x0000000000000005"])
-
+        check_mte_ctrl(1, 0)
         # This would return to synchronous faults if we did not restore the
         # previous value.
         self.expect("expression setup_mte()", substrs=["= 0"])
-        self.expect("register read mte_ctrl", substrs=["0x0000000000000005"])
+        check_mte_ctrl(1, 0)
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
index 4389d3d761d79c2..045f8c0a7010839 100644
--- a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
+++ b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
@@ -235,4 +235,11 @@ def test_mte_ctrl_register(self):
         # * Allowed tags value of 0xFFFF, shifted up by 3 resulting in 0x7fff8.
         # * Bit 1 set to enable synchronous tag faults.
         # * Bit 0 set to enable the tagged address ABI.
-        self.expect("register read mte_ctrl", substrs=["mte_ctrl = 0x000000000007fffb"])
+        expected = ["mte_ctrl = 0x000000000007fffb"]
+
+        if self.hasXMLSupport():
+            expected.append(
+                "(TAGS = 65535, TCF_ASYNC = 0, TCF_SYNC = 1, TAGGED_ADDR_ENABLE = 1)"
+            )
+
+        self.expect("register read mte_ctrl", substrs=expected)

>From c0aef387b930e9f1a875121983acfac75b743b5f Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Mon, 9 Oct 2023 11:05:47 +0100
Subject: [PATCH 2/2] [lldb][AArch64][Linux] Add register field information for
 SME's SVCR register

This register is a pseudo register but mirrors the architectural
register's contents. See:
https://developer.arm.com/documentation/ddi0616/latest/

For the full details. Example output:
```
(lldb) register read svcr
    svcr = 0x0000000000000002
         = (ZA = 1, SM = 0)
```
---
 .../Process/Utility/RegisterFlagsLinux_arm64.cpp    | 13 +++++++++++++
 .../Process/Utility/RegisterFlagsLinux_arm64.h      |  4 +++-
 .../save_restore/TestSMEZRegistersSaveRestore.py    | 12 ++++++++----
 .../sme_core_file/TestAArch64LinuxSMECoreFile.py    | 13 +++++++++----
 4 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
index ca247b628abe78f..77c7116d3c624ae 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
@@ -24,6 +24,19 @@
 
 using namespace lldb_private;
 
+LinuxArm64RegisterFlags::Fields
+LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
+  (void)hwcap;
+  (void)hwcap2;
+  // Represents the pseudo register that lldb-server builds, which itself
+  // matches the architectural register SCVR. The fields match SVCR in the Arm
+  // manual.
+  return {
+      {"ZA", 1},
+      {"SM", 0},
+  };
+}
+
 LinuxArm64RegisterFlags::Fields
 LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) {
   (void)hwcap;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
index deff977a03d0a12..660bef08700f4c8 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
@@ -59,6 +59,7 @@ class LinuxArm64RegisterFlags {
   static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
   static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
   static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2);
+  static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2);
 
   struct RegisterEntry {
     RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
@@ -68,11 +69,12 @@ class LinuxArm64RegisterFlags {
     llvm::StringRef m_name;
     RegisterFlags m_flags;
     DetectorFn m_detector;
-  } m_registers[4] = {
+  } m_registers[5] = {
       RegisterEntry("cpsr", 4, DetectCPSRFields),
       RegisterEntry("fpsr", 4, DetectFPSRFields),
       RegisterEntry("fpcr", 4, DetectFPCRFields),
       RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields),
+      RegisterEntry("svcr", 8, DetectSVCRFields),
   };
 
   // Becomes true once field detection has been run for all registers.
diff --git a/lldb/test/API/commands/register/register/aarch64_sme_z_registers/save_restore/TestSMEZRegistersSaveRestore.py b/lldb/test/API/commands/register/register/aarch64_sme_z_registers/save_restore/TestSMEZRegistersSaveRestore.py
index a0949d80c56640a..9433aae0c53c45e 100644
--- a/lldb/test/API/commands/register/register/aarch64_sme_z_registers/save_restore/TestSMEZRegistersSaveRestore.py
+++ b/lldb/test/API/commands/register/register/aarch64_sme_z_registers/save_restore/TestSMEZRegistersSaveRestore.py
@@ -180,9 +180,12 @@ def za_expr_test_impl(self, sve_mode, za_state, swap_start_vl):
         self.runCmd("register read " + sve_reg_names)
         sve_values = self.res.GetOutput()
 
-        svcr_value = 1 if sve_mode == Mode.SSVE else 0
-        if za_state == ZA.Enabled:
-            svcr_value += 2
+        za = 1 if za_state == ZA.Enabled else 0
+        sm = 1 if sve_mode == Mode.SSVE else 0
+        svcr_value = "0x{:016x}".format((za << 1) | sm)
+        expected_svcr = [svcr_value]
+        if self.hasXMLSupport():
+            expected_svcr.append("(ZA = {}, SM = {})".format(za, sm))
 
         has_zt0 = self.isAArch64SME2()
 
@@ -201,7 +204,8 @@ def check_regs():
             self.assertEqual(start_vg, self.read_vg())
 
             self.expect("register read " + sve_reg_names, substrs=[sve_values])
-            self.expect("register read svcr", substrs=["0x{:016x}".format(svcr_value)])
+
+            self.expect("register read svcr", substrs=expected_svcr)
 
         for expr in exprs:
             expr_cmd = "expression {}()".format(expr)
diff --git a/lldb/test/API/linux/aarch64/sme_core_file/TestAArch64LinuxSMECoreFile.py b/lldb/test/API/linux/aarch64/sme_core_file/TestAArch64LinuxSMECoreFile.py
index a5fdd0ab2068cbb..ee699aad2982607 100644
--- a/lldb/test/API/linux/aarch64/sme_core_file/TestAArch64LinuxSMECoreFile.py
+++ b/lldb/test/API/linux/aarch64/sme_core_file/TestAArch64LinuxSMECoreFile.py
@@ -5,17 +5,17 @@
 
 import lldb
 import itertools
-from enum import Enum
+from enum import IntEnum
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 
 
-class Mode(Enum):
+class Mode(IntEnum):
     SVE = 0
     SSVE = 1
 
 
-class ZA(Enum):
+class ZA(IntEnum):
     Disabled = 0
     Enabled = 1
 
@@ -56,7 +56,12 @@ def check_corefile(self, corefile):
         svcr = 1 if sve_mode == Mode.SSVE else 0
         if za == ZA.Enabled:
             svcr |= 2
-        self.expect("register read svcr", substrs=["0x{:016x}".format(svcr)])
+
+        expected_svcr = ["0x{:016x}".format(svcr)]
+        if self.hasXMLSupport():
+            expected_svcr.append("(ZA = {:d}, SM = {})".format(za, sve_mode))
+
+        self.expect("register read svcr", substrs=expected_svcr)
 
         repeat_bytes = lambda v, n: " ".join(["0x{:02x}".format(v)] * n)
 



More information about the lldb-commits mailing list