Skip to content

[lldb][AArch64][Linux] Add register field information for SME's SVCR register #71809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 10, 2023

Conversation

DavidSpickett
Copy link
Collaborator

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)

@DavidSpickett
Copy link
Collaborator Author

First commit is #71808, review the second.

@llvmbot
Copy link
Member

llvmbot commented Nov 9, 2023

@llvm/pr-subscribers-lldb

Author: David Spickett (DavidSpickett)

Changes

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)

Full diff: https://github.com/llvm/llvm-project/pull/71809.diff

7 Files Affected:

  • (modified) lldb/packages/Python/lldbsuite/test/lldbtest.py (+11)
  • (modified) lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp (+26)
  • (modified) lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h (+5-1)
  • (modified) lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py (+19-8)
  • (modified) lldb/test/API/commands/register/register/aarch64_sme_z_registers/save_restore/TestSMEZRegistersSaveRestore.py (+8-4)
  • (modified) lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py (+8-1)
  • (modified) lldb/test/API/linux/aarch64/sme_core_file/TestAArch64LinuxSMECoreFile.py (+9-4)
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..77c7116d3c624ae 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp
@@ -24,6 +24,32 @@
 
 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;
+  (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..660bef08700f4c8 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h
@@ -58,6 +58,8 @@ 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);
+  static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2);
 
   struct RegisterEntry {
     RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
@@ -67,10 +69,12 @@ class LinuxArm64RegisterFlags {
     llvm::StringRef m_name;
     RegisterFlags m_flags;
     DetectorFn m_detector;
-  } m_registers[3] = {
+  } 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_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/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/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)
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)
 

Copy link
Collaborator

@jasonmolenda jasonmolenda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

…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)
```
@DavidSpickett DavidSpickett merged commit 9ad25f2 into llvm:main Nov 10, 2023
@DavidSpickett DavidSpickett deleted the lldb-svcr branch November 10, 2023 09:30
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
…register (llvm#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)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants