DavidSpickett updated this revision to Diff 557011.
DavidSpickett added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154927/new/

https://reviews.llvm.org/D154927

Files:
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
  lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
  lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
  
lldb/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py
  
lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py
  
lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/main.c
  
lldb/test/API/commands/register/register/aarch64_za_register/za_save_restore/TestZARegisterSaveRestore.py

Index: lldb/test/API/commands/register/register/aarch64_za_register/za_save_restore/TestZARegisterSaveRestore.py
===================================================================
--- lldb/test/API/commands/register/register/aarch64_za_register/za_save_restore/TestZARegisterSaveRestore.py
+++ lldb/test/API/commands/register/register/aarch64_za_register/za_save_restore/TestZARegisterSaveRestore.py
@@ -164,6 +164,10 @@
         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
+
         def check_regs():
             if za_state == ZA.Enabled:
                 self.check_za(start_vl)
@@ -175,6 +179,7 @@
             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)])
 
         for expr in exprs:
             expr_cmd = "expression {}()".format(expr)
Index: lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/main.c
===================================================================
--- lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/main.c
+++ lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/main.c
@@ -9,7 +9,7 @@
 #define PR_SME_SET_VL 63
 #endif
 
-#define SMSTART() asm volatile("msr  s0_3_c4_c7_3, xzr" /*smstart*/)
+#define SMSTART_SM() asm volatile("msr  s0_3_c4_c3_3, xzr" /*smstart sm*/)
 
 void write_sve_regs() {
   // We assume the smefa64 feature is present, which allows ffr access
@@ -130,18 +130,18 @@
   // Note that doing a syscall brings you back to non-streaming mode, so we
   // don't need to SMSTOP here.
   if (streaming)
-    SMSTART();
+    SMSTART_SM();
   write_sve_regs_expr();
   prctl(SET_VL_OPT, 8 * 4);
   if (streaming)
-    SMSTART();
+    SMSTART_SM();
   write_sve_regs_expr();
   return 1;
 }
 
 int main() {
 #ifdef START_SSVE
-  SMSTART();
+  SMSTART_SM();
 #endif
   write_sve_regs();
 
Index: lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py
===================================================================
--- lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py
+++ lldb/test/API/commands/register/register/aarch64_sve_registers/rw_access_static_config/TestSVERegisters.py
@@ -24,7 +24,15 @@
             reg_value.GetByteSize(), expected, 'Verify "%s" == %i' % (name, expected)
         )
 
-    def check_sve_regs_read(self, z_reg_size):
+    def check_sve_regs_read(self, z_reg_size, expected_mode):
+        if self.isAArch64SME():
+            # This test uses SMSTART SM, which only enables streaming mode,
+            # leaving ZA disabled.
+            expected_value = "1" if expected_mode == Mode.SSVE else "0"
+            self.expect(
+                "register read svcr", substrs=["0x000000000000000" + expected_value]
+            )
+
         p_reg_size = int(z_reg_size / 8)
 
         for i in range(32):
@@ -168,7 +176,7 @@
 
         vg_reg_value = sve_registers.GetChildMemberWithName("vg").GetValueAsUnsigned()
         z_reg_size = vg_reg_value * 8
-        self.check_sve_regs_read(z_reg_size)
+        self.check_sve_regs_read(z_reg_size, start_mode)
 
         # Evaluate simple expression and print function expr_eval_func address.
         self.expect("expression expr_eval_func", substrs=["= 0x"])
@@ -184,7 +192,7 @@
 
         # We called a jitted function above which must not have changed SVE
         # vector length or register values.
-        self.check_sve_regs_read(z_reg_size)
+        self.check_sve_regs_read(z_reg_size, start_mode)
 
         self.check_sve_regs_read_after_write(z_reg_size)
 
Index: lldb/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py
===================================================================
--- lldb/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py
+++ lldb/test/API/commands/register/register/aarch64_dynamic_regset/TestArm64DynamicRegsets.py
@@ -171,6 +171,11 @@
         svg = sme_registers.GetChildMemberWithName("svg").GetValueAsUnsigned()
         self.assertEqual(vg, svg)
 
+        # SVCR should be SVCR.SM | SVCR.ZA aka 3 because streaming mode is on
+        # and ZA is enabled.
+        svcr = sme_registers.GetChildMemberWithName("svcr").GetValueAsUnsigned()
+        self.assertEqual(3, svcr)
+
     @no_debug_info_test
     @skipIf(archs=no_match(["aarch64"]))
     @skipIf(oslist=no_match(["linux"]))
@@ -191,6 +196,10 @@
         self.assertTrue(sme_registers.IsValid())
         svg = sme_registers.GetChildMemberWithName("svg").GetValueAsUnsigned()
 
+        # We are not in streaming mode, ZA is disabled, so this should be 0.
+        svcr = sme_registers.GetChildMemberWithName("svcr").GetValueAsUnsigned()
+        self.assertEqual(0, svcr)
+
         svl = svg * 8
         # A disabled ZA is shown as all 0s.
         self.expect("register read za", substrs=[self.make_za_value(svl, lambda r: 0)])
@@ -199,3 +208,6 @@
         # it back.
         self.runCmd("register write za '{}'".format(za_value))
         self.expect("register read za", substrs=[za_value])
+
+        # Now SVCR.ZA should be set, which is bit 1.
+        self.expect("register read svcr", substrs=["0x0000000000000002"])
Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -84,6 +84,7 @@
     DEFINE_EXTENSION_REG(tpidr2)};
 
 static lldb_private::RegisterInfo g_register_infos_sme[] = {
+    DEFINE_EXTENSION_REG(svcr),
     DEFINE_EXTENSION_REG(svg),
     // 16 is a default size we will change later.
     {"za", nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,
@@ -97,7 +98,7 @@
   k_num_mte_register = 1,
   // Number of TLS registers is dynamic so it is not listed here.
   k_num_pauth_register = 2,
-  k_num_sme_register = 2,
+  k_num_sme_register = 3,
   k_num_register_sets_default = 2,
   k_num_register_sets = 3
 };
@@ -449,7 +450,7 @@
   // dynamic set and is just 1 register so we make an exception to const here.
   lldb_private::RegisterInfo *non_const_reginfo =
       const_cast<lldb_private::RegisterInfo *>(m_register_info_p);
-  non_const_reginfo[m_sme_regnum_collection[1]].byte_size =
+  non_const_reginfo[m_sme_regnum_collection[2]].byte_size =
       (za_vq * 16) * (za_vq * 16);
 }
 
@@ -473,7 +474,7 @@
 }
 
 bool RegisterInfoPOSIX_arm64::IsSMERegZA(unsigned reg) const {
-  return reg == m_sme_regnum_collection[1];
+  return reg == m_sme_regnum_collection[2];
 }
 
 bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const {
@@ -503,7 +504,7 @@
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; }
 
 uint32_t RegisterInfoPOSIX_arm64::GetRegNumSMESVG() const {
-  return m_sme_regnum_collection[0];
+  return m_sme_regnum_collection[1];
 }
 
 uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const {
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -115,6 +115,7 @@
   uint64_t m_mte_ctrl_reg;
 
   struct sme_pseudo_regs {
+    uint64_t ctrl_reg;
     uint64_t svg_reg;
   };
 
@@ -162,6 +163,9 @@
   // Instead use WriteZA and ensure you have the correct ZA buffer size set
   // beforehand if you wish to disable it.
 
+  // SVCR is a pseudo register and we do not allow writes to it.
+  Status ReadSMEControl();
+
   bool IsSVE(unsigned reg) const;
   bool IsSME(unsigned reg) const;
   bool IsPAuth(unsigned reg) const;
Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -360,6 +360,9 @@
       if (error.Fail())
         return error;
 
+      // This is a psuedo so it never fails.
+      ReadSMEControl();
+
       offset = reg_info->byte_offset - GetRegisterInfo().GetSMEOffset();
       assert(offset < GetSMEPseudoBufferSize());
       src = (uint8_t *)GetSMEPseudoBuffer() + offset;
@@ -550,7 +553,7 @@
     return WriteTLS();
   } else if (IsSME(reg)) {
     if (!GetRegisterInfo().IsSMERegZA(reg))
-      return Status("Writing to SVG is not supported.");
+      return Status("Writing to SVG or SVCR is not supported.");
 
     error = ReadZA();
     if (error.Fail())
@@ -1160,6 +1163,24 @@
   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), GetSVERegSet());
 }
 
+Status NativeRegisterContextLinux_arm64::ReadSMEControl() {
+  // The real register is SVCR and is accessible from EL0. However we don't want
+  // to have to JIT code into the target process so we'll just recreate it using
+  // what we know from ptrace.
+
+  // Bit 0 indicates whether streaming mode is active.
+  m_sme_pseudo_regs.ctrl_reg = m_sve_state == SVEState::Streaming;
+
+  // Bit 1 indicates whether the array storage is active.
+  // It is active if we can read the header and the size field tells us that
+  // there is register data following it.
+  Status error = ReadZAHeader();
+  if (error.Success() && (m_za_header.size > sizeof(m_za_header)))
+    m_sme_pseudo_regs.ctrl_reg |= 2;
+
+  return {};
+}
+
 Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
   Status error;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to