public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux
@ 2023-08-22 11:21 Luis Machado
  2023-08-22 11:21 ` [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb " Luis Machado
                   ` (5 more replies)
  0 siblings, 6 replies; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: thiago.bauermann

The following series enables SME 2 (Scalable Matrix Extension 2) support for
AArch64 gdb and gdbserver.

SME2 expands on SME by adding a predicate register of 512 bits named ZT0.

At a high level, this series does the following:

- Adds support for the ZT0 register and adds a new target description feature
  for it.
- Core file support (depends on binutils patches).
- Signal frame context support.
- Native Linux handling of the new NT_ARM_ZT register set.

This series depends on the SME series, and should be applied on top of that
one.

Luis Machado (6):
  [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb on Linux
  [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver
  [gdb/aarch64] sme2: signal frame support
  [gdb/aarch64] sme2: Core file support for ZT register set
  [gdb/testsuite] sme2: Extend SME tests to include SME2
  [gdb/docs] sme2: Document SME2 registers and features

 gdb/NEWS                                      |   3 +
 gdb/aarch64-linux-nat.c                       |  49 ++++++
 gdb/aarch64-linux-tdep.c                      | 146 ++++++++++++++++++
 gdb/aarch64-tdep.c                            |  21 +++
 gdb/aarch64-tdep.h                            |  10 ++
 gdb/arch/aarch64-scalable-linux.h             |   6 +
 gdb/arch/aarch64.c                            |   4 +
 gdb/arch/aarch64.h                            |  12 +-
 gdb/doc/gdb.texinfo                           |  65 ++++++++
 gdb/features/aarch64-sme2.c                   |  43 ++++++
 gdb/nat/aarch64-scalable-linux-ptrace.c       | 134 ++++++++++++++++
 gdb/nat/aarch64-scalable-linux-ptrace.h       |  26 ++++
 gdb/testsuite/gdb.arch/aarch64-sme-core.c     |  32 +++-
 .../gdb.arch/aarch64-sme-core.exp.tcl         |   2 +-
 .../aarch64-sme-regs-available.exp.tcl        |  17 ++
 .../gdb.arch/aarch64-sme-regs-sigframe.c      |  32 +++-
 .../aarch64-sme-regs-sigframe.exp.tcl         |  13 +-
 .../aarch64-sme-regs-unavailable.exp.tcl      |  12 ++
 gdb/testsuite/gdb.arch/aarch64-sme-sanity.c   |  32 +++-
 gdb/testsuite/lib/aarch64-scalable.exp        |  44 ++++++
 gdb/testsuite/lib/aarch64.exp                 |  53 +++++++
 gdbserver/linux-aarch64-low.cc                |  63 ++++++++
 22 files changed, 810 insertions(+), 9 deletions(-)
 create mode 100644 gdb/features/aarch64-sme2.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb on Linux
  2023-08-22 11:21 [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux Luis Machado
@ 2023-08-22 11:21 ` Luis Machado
  2023-08-27  1:16   ` Thiago Jung Bauermann
  2023-08-22 11:21 ` [PATCH v2 2/6] [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver Luis Machado
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: thiago.bauermann

SME2 defines a new 512-bit register named ZT0, and it is only available
if SME is also supported.  The ZT0 state is valid only if the SVCR ZA bit
is enabled.  Otherwise its contents are empty (0).

The target description is dynamic and gets generated at runtime based on the
availability of the feature.

Validated under Fast Models.
---
 gdb/aarch64-linux-nat.c                 |  49 +++++++++
 gdb/aarch64-tdep.c                      |  21 ++++
 gdb/aarch64-tdep.h                      |  10 ++
 gdb/arch/aarch64-scalable-linux.h       |   6 ++
 gdb/arch/aarch64.c                      |   4 +
 gdb/arch/aarch64.h                      |  12 ++-
 gdb/features/aarch64-sme2.c             |  43 ++++++++
 gdb/nat/aarch64-scalable-linux-ptrace.c | 134 ++++++++++++++++++++++++
 gdb/nat/aarch64-scalable-linux-ptrace.h |  26 +++++
 9 files changed, 304 insertions(+), 1 deletion(-)
 create mode 100644 gdb/features/aarch64-sme2.c

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index d7fcef5a0db..edbe6895c86 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -376,6 +376,37 @@ store_za_to_thread (struct regcache *regcache)
 				     tdep->sme_svcr_regnum);
 }
 
+/* Fill GDB's REGCACHE with the ZT register set contents from the
+   current thread.  If there is no active ZA register state, make the
+   ZT register contents zero.  */
+
+static void
+fetch_zt_from_thread (struct regcache *regcache)
+{
+  aarch64_gdbarch_tdep *tdep
+    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+  /* Read ZT state from the thread to the register cache.  */
+  aarch64_zt_regs_copy_to_reg_buf (regcache->ptid ().lwp (),
+				   regcache,
+				   tdep->sme2_zt0_regnum);
+}
+
+/* Store the NT_ARM_ZT register set contents from GDB's REGCACHE to the current
+   thread.  */
+
+static void
+store_zt_to_thread (struct regcache *regcache)
+{
+  aarch64_gdbarch_tdep *tdep
+    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+  /* Write ZT state from the register cache to the thread.  */
+  aarch64_zt_regs_copy_from_reg_buf (regcache->ptid ().lwp (),
+				     regcache,
+				     tdep->sme2_zt0_regnum);
+}
+
 /* Fill GDB's register array with the pointer authentication mask values from
    the current thread.  */
 
@@ -549,6 +580,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
 
       if (tdep->has_sme ())
 	fetch_za_from_thread (regcache);
+
+      if (tdep->has_sme2 ())
+	fetch_zt_from_thread (regcache);
     }
   /* General purpose register?  */
   else if (regno < AARCH64_V0_REGNUM)
@@ -569,6 +603,9 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
   else if (tdep->has_sme () && regno >= tdep->sme_reg_base
 	   && regno < tdep->sme_reg_base + 3)
     fetch_za_from_thread (regcache);
+  /* SME2 register?  */
+  else if (tdep->has_sme2 () && regno == tdep->sme2_zt0_regnum)
+    fetch_zt_from_thread (regcache);
   /* MTE register?  */
   else if (tdep->has_mte ()
 	   && (regno == tdep->mte_reg_base))
@@ -646,6 +683,9 @@ aarch64_store_registers (struct regcache *regcache, int regno)
 
       if (tdep->has_sme ())
 	store_za_to_thread (regcache);
+
+      if (tdep->has_sme2 ())
+	store_zt_to_thread (regcache);
     }
   /* General purpose register?  */
   else if (regno < AARCH64_V0_REGNUM)
@@ -661,6 +701,8 @@ aarch64_store_registers (struct regcache *regcache, int regno)
   else if (tdep->has_sme () && regno >= tdep->sme_reg_base
 	   && regno < tdep->sme_reg_base + 3)
     store_za_to_thread (regcache);
+  else if (tdep->has_sme2 () && regno == tdep->sme2_zt0_regnum)
+    store_zt_to_thread (regcache);
   /* MTE register?  */
   else if (tdep->has_mte ()
 	   && (regno == tdep->mte_reg_base))
@@ -861,6 +903,10 @@ aarch64_linux_nat_target::read_description ()
   /* SME feature check.  */
   features.svq = aarch64_za_get_svq (tid);
 
+  /* Check for SME2 support.  */
+  if ((hwcap2 & HWCAP2_SME2) || (hwcap2 & HWCAP2_SME2P1))
+    features.sme2 = supports_zt_registers (tid);
+
   return aarch64_read_description (features);
 }
 
@@ -981,6 +1027,9 @@ aarch64_linux_nat_target::thread_architecture (ptid_t ptid)
   features.vq = vq;
   features.svq = svq;
 
+  /* Check for the SME2 feature.  */
+  features.sme2 = supports_zt_registers (ptid.lwp ());
+
   struct gdbarch_info info;
   info.bfd_arch_info = bfd_lookup_arch (bfd_arch_aarch64, bfd_mach_aarch64);
   info.target_desc = aarch64_read_description (features);
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 8e7259a6f42..eaae2d91047 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -4048,6 +4048,10 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc)
 
   features.svq = aarch64_get_tdesc_svq (tdesc);
 
+  /* Check for the SME2 feature.  */
+  features.sme2 = (tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sme2")
+		   != nullptr);
+
   return features;
 }
 
@@ -4310,6 +4314,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 
   int first_sme_regnum = -1;
+  int first_sme2_regnum = -1;
   int first_sme_pseudo_regnum = -1;
   const struct tdesc_feature *feature_sme
     = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sme");
@@ -4336,6 +4341,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
       /* Add the ZA tile pseudo registers.  */
       num_pseudo_regs += AARCH64_ZA_TILES_NUM;
+
+      /* Now check for the SME2 feature.  SME2 is only available if SME is
+	 available.  */
+      const struct tdesc_feature *feature_sme2
+	= tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sme2");
+      if (feature_sme2 != nullptr)
+	{
+	  /* Record the first SME2 register.  */
+	  first_sme2_regnum = num_regs;
+
+	  valid_p &= tdesc_numbered_register (feature_sme2, tdesc_data.get (),
+					      num_regs++, "zt0");
+	}
     }
 
   /* Add the TLS register.  */
@@ -4459,6 +4477,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->sme_za_regnum = first_sme_regnum + 2;
   tdep->sme_svq = svq;
 
+  /* Set the SME2 register set details.  */
+  tdep->sme2_zt0_regnum = first_sme2_regnum;
+
   set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
   set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
 
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 9297487a584..9e4d1a59734 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -172,6 +172,16 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base
   {
     return sme_svq != 0;
   }
+
+  /* Index of the SME2 ZT0 register.  This is -1 if SME2 is not
+     supported.  */
+  int sme2_zt0_regnum = -1;
+
+  /* Return true if the target supports SME2, and false otherwise.  */
+  bool has_sme2 () const
+  {
+    return sme2_zt0_regnum > 0;
+  }
 };
 
 const target_desc *aarch64_read_description (const aarch64_features &features);
diff --git a/gdb/arch/aarch64-scalable-linux.h b/gdb/arch/aarch64-scalable-linux.h
index cb9d85a9d5d..0f59ddb40b2 100644
--- a/gdb/arch/aarch64-scalable-linux.h
+++ b/gdb/arch/aarch64-scalable-linux.h
@@ -29,6 +29,12 @@
 #define HWCAP2_SME (1 << 23)
 #endif
 
+/* Feature check for Scalable Matrix Extension 2.  */
+#ifndef HWCAP2_SME2
+#define HWCAP2_SME2   (1UL << 37)
+#define HWCAP2_SME2P1 (1UL << 38)
+#endif
+
 /* Streaming mode enabled/disabled bit.  */
 #define SVCR_SM_BIT (1 << 0)
 /* ZA enabled/disabled bit.  */
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index e1f4948aa25..c93d602c66c 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -25,6 +25,7 @@
 #include "../features/aarch64-pauth.c"
 #include "../features/aarch64-mte.c"
 #include "../features/aarch64-sme.c"
+#include "../features/aarch64-sme2.c"
 #include "../features/aarch64-tls.c"
 
 /* See arch/aarch64.h.  */
@@ -62,6 +63,9 @@ aarch64_create_target_description (const aarch64_features &features)
     regnum = create_feature_aarch64_sme (tdesc.get (), regnum,
 					 sve_vl_from_vq (features.svq));
 
+  if (features.sme2)
+    regnum = create_feature_aarch64_sme2 (tdesc.get (), regnum);
+
   return tdesc.release ();
 }
 
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index c1cd233c51e..65c6205115e 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -48,6 +48,9 @@ struct aarch64_features
 
      These use at most 5 bits to represent.  */
   uint8_t svq = 0;
+
+  /* Whether SME2 is supported.  */
+  bool sme2 = false;
 };
 
 inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs)
@@ -56,7 +59,8 @@ inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs)
     && lhs.pauth == rhs.pauth
     && lhs.mte == rhs.mte
     && lhs.tls == rhs.tls
-    && lhs.svq == rhs.svq;
+    && lhs.svq == rhs.svq
+    && lhs.sme2 == rhs.sme2;
 }
 
 namespace std
@@ -79,6 +83,9 @@ namespace std
       gdb_assert (features.svq >= 0);
       gdb_assert (features.svq <= 16);
       h = h << 5 | (features.svq & 0x5);
+
+      /* SME2 feature.  */
+      h = h << 1 | features.sme2;
       return h;
     }
   };
@@ -220,4 +227,7 @@ enum aarch64_regnum
 #define AARCH64_SME_MIN_SVL 128
 #define AARCH64_SME_MAX_SVL 2048
 
+/* Size of the SME2 ZT0 register in bytes.  */
+#define AARCH64_SME2_ZT0_SIZE 64
+
 #endif /* ARCH_AARCH64_H */
diff --git a/gdb/features/aarch64-sme2.c b/gdb/features/aarch64-sme2.c
new file mode 100644
index 00000000000..a14b98fae9d
--- /dev/null
+++ b/gdb/features/aarch64-sme2.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "gdbsupport/tdesc.h"
+
+/* This function is NOT auto generated from xml.  Create the AArch64 SME2
+   feature into RESULT.
+
+   The ZT0 register is only available when the SME ZA register is
+   available.  */
+
+static int
+create_feature_aarch64_sme2 (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+  tdesc_type *element_type;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.sme2");
+
+  /* Byte type.  */
+  element_type = tdesc_named_type (feature, "uint8");
+
+  /* Vector of 64 bytes.  */
+  element_type = tdesc_create_vector (feature, "sme2_bv", element_type, 64);
+
+  /* The following is the ZT0 register, with 512 bits (64 bytes).  */
+  tdesc_create_reg (feature, "zt0", regnum++, 1, nullptr, 512, "sme2_bv");
+  return regnum;
+}
diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.c b/gdb/nat/aarch64-scalable-linux-ptrace.c
index e2fbe102472..f2f97a57eaf 100644
--- a/gdb/nat/aarch64-scalable-linux-ptrace.c
+++ b/gdb/nat/aarch64-scalable-linux-ptrace.c
@@ -519,10 +519,75 @@ aarch64_initialize_za_regset (int tid)
   if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_ZA, &iovec) < 0)
     perror_with_name (_("Failed to initialize the NT_ARM_ZA register set."));
 
+  if (supports_zt_registers (tid))
+    {
+      /* If this target supports SME2, upon initializing ZA, we also need to
+	 initialize the ZT registers with 0 values.  Do so now.  */
+      gdb::byte_vector zt_new_state (AARCH64_SME2_ZT0_SIZE, 0);
+      aarch64_store_zt_regset (tid, zt_new_state);
+    }
+
   /* The NT_ARM_ZA register set should now contain a zero-initialized ZA
      payload.  */
 }
 
+/* See nat/aarch64-scalable-linux-ptrace.h.  */
+
+gdb::byte_vector
+aarch64_fetch_zt_regset (int tid)
+{
+  /* Read NT_ARM_ZT.  This register set is only available if
+     the ZA bit is non-zero.  */
+  gdb::byte_vector zt_state (AARCH64_SME2_ZT0_SIZE);
+
+  struct iovec iovec;
+  iovec.iov_len = AARCH64_SME2_ZT0_SIZE;
+  iovec.iov_base = zt_state.data ();
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_ZT, &iovec) < 0)
+    perror_with_name (_("Failed to fetch NT_ARM_ZT register set."));
+
+  return zt_state;
+}
+
+/* See nat/aarch64-scalable-linux-ptrace.h.  */
+
+void
+aarch64_store_zt_regset (int tid, const gdb::byte_vector &zt_state)
+{
+  gdb_assert (zt_state.size () == AARCH64_SME2_ZT0_SIZE
+	      || zt_state.size () == 0);
+
+  /* We need to be mindful of writing data to NT_ARM_ZT.  If the ZA bit
+     is 0 and we write something to ZT, it will flip the ZA bit.
+
+     Right now this is taken care of by callers of this function.  */
+  struct iovec iovec;
+  iovec.iov_len = zt_state.size ();
+  iovec.iov_base = (void *) zt_state.data ();
+
+  /* Write the contents of ZT_STATE to the NT_ARM_ZT register set.  */
+  if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_ZT, &iovec) < 0)
+    perror_with_name (_("Failed to write to the NT_ARM_ZT register set."));
+}
+
+/* See nat/aarch64-scalable-linux-ptrace.h.  */
+
+bool
+supports_zt_registers (int tid)
+{
+  gdb_byte zt_state[AARCH64_SME2_ZT0_SIZE];
+
+  struct iovec iovec;
+  iovec.iov_len = AARCH64_SME2_ZT0_SIZE;
+  iovec.iov_base = (void *) zt_state;
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_ZT, &iovec) < 0)
+    return false;
+
+  return true;
+}
+
 /* If we are running in BE mode, byteswap the contents
    of SRC to DST for SIZE bytes.  Other, just copy the contents
    from SRC to DST.  */
@@ -989,3 +1054,72 @@ aarch64_za_regs_copy_from_reg_buf (int tid,
   /* At this point we have written the data contained in the register cache to
      the thread's NT_ARM_ZA register set.  */
 }
+
+/* See nat/aarch64-scalable-linux-ptrace.h.  */
+
+void
+aarch64_zt_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf,
+				 int zt_regnum)
+{
+  /* If we have ZA state, read the ZT state.  Otherwise, make the contents of
+     ZT in the register cache all zeroes.  This is how we present the ZT
+     state when it is not initialized (ZA not active).  */
+  if (aarch64_has_za_state (tid))
+    {
+      /* Fetch the current ZT state from the thread.  */
+      gdb::byte_vector zt_state = aarch64_fetch_zt_regset (tid);
+
+      /* Sanity check.  */
+      gdb_assert (!zt_state.empty ());
+
+      /* Copy the ZT data to the register buffer.  */
+      reg_buf->raw_supply (zt_regnum, zt_state.data ());
+    }
+  else
+    {
+      /* Zero out ZT.  */
+      gdb::byte_vector zt_zeroed (AARCH64_SME2_ZT0_SIZE, 0);
+      reg_buf->raw_supply (zt_regnum, zt_zeroed.data ());
+    }
+
+  /* The register buffer should now contain the updated copy of the NT_ARM_ZT
+     state.  */
+}
+
+/* See nat/aarch64-scalable-linux-ptrace.h.  */
+
+void
+aarch64_zt_regs_copy_from_reg_buf (int tid,
+				   struct reg_buffer_common *reg_buf,
+				   int zt_regnum)
+{
+  /* Do we have a valid ZA state?  */
+  bool valid_za = aarch64_has_za_state (tid);
+
+  /* Is the register buffer contents for ZT all zeroes?  */
+  gdb::byte_vector zt_bytes (AARCH64_SME2_ZT0_SIZE, 0);
+  bool zt_is_all_zeroes
+    = reg_buf->raw_compare (zt_regnum, zt_bytes.data (), 0);
+
+  /* If ZA state is valid or if we have non-zero data for ZT in the register
+     buffer, we will invoke ptrace to write the ZT state.  Otherwise we don't
+     have to do anything here.  */
+  if (valid_za || !zt_is_all_zeroes)
+    {
+      if (!valid_za)
+	{
+	  /* ZA state is not valid.  That means we need to initialize the ZA
+	     state prior to writing the ZT state.  */
+	  aarch64_initialize_za_regset (tid);
+	}
+
+      /* Extract the ZT data from the register buffer.  */
+      reg_buf->raw_collect (zt_regnum, zt_bytes.data ());
+
+      /* Write the ZT data to thread TID.  */
+      aarch64_store_zt_regset (tid, zt_bytes);
+    }
+
+  /* At this point we have (potentially) written the data contained in the
+     register cache to the thread's NT_ARM_ZT register set.  */
+}
diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.h b/gdb/nat/aarch64-scalable-linux-ptrace.h
index d609933801d..69c9982b009 100644
--- a/gdb/nat/aarch64-scalable-linux-ptrace.h
+++ b/gdb/nat/aarch64-scalable-linux-ptrace.h
@@ -120,6 +120,16 @@ extern void aarch64_store_za_regset (int tid, const gdb::byte_vector &za_state);
    size.  The bytes of the ZA register are initialized to zero.  */
 extern void aarch64_initialize_za_regset (int tid);
 
+/* Given TID, return the NT_ARM_ZT register set data as a vector of bytes.  */
+extern gdb::byte_vector aarch64_fetch_zt_regset (int tid);
+
+/* Write ZT_STATE for TID.  */
+extern void aarch64_store_zt_regset (int tid, const gdb::byte_vector &zt_state);
+
+/* Return TRUE if thread TID supports the NT_ARM_ZT register set.
+   Return FALSE otherwise.  */
+extern bool supports_zt_registers (int tid);
+
 /* Given a register buffer REG_BUF, update it with SVE/SSVE register data
    from SVE_STATE.  */
 extern void
@@ -151,4 +161,20 @@ aarch64_za_regs_copy_from_reg_buf (int tid,
 				   struct reg_buffer_common *reg_buf,
 				   int za_regnum, int svg_regnum,
 				   int svcr_regnum);
+
+/* Given a thread id TID and a register buffer REG_BUF, update the register
+   buffer with the ZT register set state from thread TID.
+
+   ZT_REGNUM is the register number for ZT0.  */
+extern void
+aarch64_zt_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf,
+				 int zt_regnum);
+
+/* Given a thread id TID and a register buffer REG_BUF containing the ZT
+   register set state, write the ZT data to thread TID.
+
+   ZT_REGNUM is the register number for ZT0.  */
+extern void
+aarch64_zt_regs_copy_from_reg_buf (int tid, struct reg_buffer_common *reg_buf,
+				   int zt_regnum);
 #endif /* NAT_AARCH64_SCALABLE_LINUX_PTRACE_H */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 2/6] [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver
  2023-08-22 11:21 [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux Luis Machado
  2023-08-22 11:21 ` [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb " Luis Machado
@ 2023-08-22 11:21 ` Luis Machado
  2023-08-27  1:18   ` Thiago Jung Bauermann
  2023-08-22 11:21 ` [PATCH v2 3/6] [gdb/aarch64] sme2: signal frame support Luis Machado
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: thiago.bauermann

This patch teaches gdbserver about the SME2 and the ZT0 register.

Since most of the code used by gdbserver for SME2 is shared with gdb, this
is a rather small patch that reuses most of the code put in place for native
AArch64 Linux.

Validated under Fast Models.
---
 gdbserver/linux-aarch64-low.cc | 63 ++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
index 95688480c3d..783053e359b 100644
--- a/gdbserver/linux-aarch64-low.cc
+++ b/gdbserver/linux-aarch64-low.cc
@@ -811,6 +811,52 @@ aarch64_za_regs_copy_from_regcache (struct regcache *regcache, void *buf)
   memcpy (buf, za_state.data (), za_state.size ());
 }
 
+/* Wrapper for aarch64_zt_regs_copy_to_reg_buf, to help copying NT_ARM_ZT
+   state from the thread (BUF) to the register cache.  */
+
+static void
+aarch64_zt_regs_copy_to_regcache (struct regcache *regcache,
+				  ATTRIBUTE_UNUSED const void *buf)
+{
+  /* BUF is unused here since we collect the data straight from a ptrace
+     request, therefore bypassing gdbserver's own call to ptrace.  */
+  int tid = lwpid_of (current_thread);
+
+  gdb::optional<int> zt_regnum
+    = find_regno_no_throw (regcache->tdesc, "zt0");
+
+  gdb_assert (zt_regnum.has_value ());
+
+  /* Update the register cache.  aarch64_zt_regs_copy_to_reg_buf handles
+     fetching the NT_ARM_ZT state from thread TID.  */
+  aarch64_zt_regs_copy_to_reg_buf (tid, regcache, *zt_regnum);
+}
+
+/* Wrapper for aarch64_zt_regs_copy_from_reg_buf, to help copying NT_ARM_ZT
+   state from the register cache to the thread (BUF).  */
+
+static void
+aarch64_zt_regs_copy_from_regcache (struct regcache *regcache, void *buf)
+{
+  int tid = lwpid_of (current_thread);
+
+  gdb::optional<int> zt_regnum
+    = find_regno_no_throw (regcache->tdesc, "za");
+
+  gdb_assert (zt_regnum.has_value ());
+
+  /* Update the thread NT_ARM_ZT state.  aarch64_zt_regs_copy_from_reg_buf
+     handles writing the ZT state back to thread TID.  */
+  aarch64_zt_regs_copy_from_reg_buf (tid, regcache, *zt_regnum);
+
+  /* We need to return the expected data in BUF, so copy whatever the kernel
+     already has to BUF.  */
+
+  /* Obtain a dump of NT_ARM_ZT from ptrace.  */
+  gdb::byte_vector zt_state = aarch64_fetch_zt_regset (tid);
+  memcpy (buf, zt_state.data (), zt_state.size ());
+}
+
 /* Array containing all the possible register sets for AArch64/Linux.  During
    architecture setup, these will be checked against the HWCAP/HWCAP2 bits for
    validity and enabled/disabled accordingly.
@@ -838,6 +884,11 @@ static struct regset_info aarch64_regsets[] =
     0, EXTENDED_REGS,
     aarch64_za_regs_copy_from_regcache, aarch64_za_regs_copy_to_regcache
   },
+  /* Scalable Matrix Extension 2 (SME2) ZT registers.  */
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_ZT,
+    0, EXTENDED_REGS,
+    aarch64_zt_regs_copy_from_regcache, aarch64_zt_regs_copy_to_regcache
+  },
   /* PAC registers.  */
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
     0, OPTIONAL_REGS,
@@ -909,6 +960,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
 	  if (features.svq > 0)
 	    regset->size = ZA_PT_SIZE (features.svq);
 	  break;
+	case NT_ARM_ZT:
+	  if (features.sme2)
+	    regset->size = 64;
+	  break;
 	default:
 	  gdb_assert_not_reached ("Unknown register set found.");
 	}
@@ -947,6 +1002,14 @@ aarch64_target::low_arch_setup ()
       if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME)
 	features.svq = aarch64_za_get_svq (tid);
 
+      /* Scalable Matrix Extension 2 feature check.  */
+      CORE_ADDR hwcap2 = linux_get_hwcap2 (pid, 8);
+      if ((hwcap2 & HWCAP2_SME2) || (hwcap2 & HWCAP2_SME2P1))
+	{
+	  /* Make sure ptrace supports NT_ARM_ZT.  */
+	  features.sme2 = supports_zt_registers (tid);
+	}
+
       current_process ()->tdesc = aarch64_linux_read_description (features);
 
       /* Adjust the register sets we should use for this particular set of
-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 3/6] [gdb/aarch64] sme2: signal frame support
  2023-08-22 11:21 [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux Luis Machado
  2023-08-22 11:21 ` [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb " Luis Machado
  2023-08-22 11:21 ` [PATCH v2 2/6] [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver Luis Machado
@ 2023-08-22 11:21 ` Luis Machado
  2023-08-27  1:19   ` Thiago Jung Bauermann
  2023-08-22 11:21 ` [PATCH v2 4/6] [gdb/aarch64] sme2: Core file support for ZT register set Luis Machado
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: thiago.bauermann

Teach gdb about the ZT state on signal frames and how to restore
the contents of the registers.

There is a new ZT_MAGIC context that the Linux Kernel uses to communicate
the ZT register state to gdb.

As mentioned before, the ZT state should only be available when the ZA state
is available.

Validated under Fast Models.
---
 gdb/aarch64-linux-tdep.c | 65 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index fe3a55361c2..8b0b4d32971 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -159,6 +159,7 @@
 #define AARCH64_SVE_MAGIC			0x53564501
 #define AARCH64_ZA_MAGIC			0x54366345
 #define AARCH64_TPIDR2_MAGIC			0x54504902
+#define AARCH64_ZT_MAGIC			0x5a544e01
 
 /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC.  */
 #define AARCH64_EXTRA_DATAP_OFFSET		8
@@ -192,6 +193,14 @@
 /* TPIDR2 register value offset in the TPIDR2 signal frame context.  */
 #define AARCH64_TPIDR2_CONTEXT_TPIDR2_OFFSET	8
 
+/* SME2 (ZT) constants.  */
+/* Offset of the field containing the number of registers in the SME2 signal
+   context state.  */
+#define AARCH64_SME2_CONTEXT_NREGS_OFFSET	8
+/* Offset of the beginning of the register data for the first ZT register in
+   the signal context state.  */
+#define AARCH64_SME2_CONTEXT_REGS_OFFSET	16
+
 /* Holds information about the signal frame.  */
 struct aarch64_linux_sigframe
 {
@@ -214,6 +223,8 @@ struct aarch64_linux_sigframe
   CORE_ADDR za_section = 0;
   /* Starting address of the section containing the TPIDR2 register.  */
   CORE_ADDR tpidr2_section = 0;
+  /* Starting address of the section containing the ZT registers.  */
+  CORE_ADDR zt_section = 0;
   /* Starting address of the section containing extra information.  */
   CORE_ADDR extra_section = 0;
 
@@ -221,10 +232,15 @@ struct aarch64_linux_sigframe
   ULONGEST vl = 0;
   /* The streaming vector length (SSVE/ZA).  */
   ULONGEST svl = 0;
+  /* Number of ZT registers in this context.  */
+  unsigned int zt_register_count = 0;
+
   /* True if we are in streaming mode, false otherwise.  */
   bool streaming_mode = false;
   /* True if we have a ZA payload, false otherwise.  */
   bool za_payload = false;
+  /* True if we have a ZT entry in the signal context, false otherwise.  */
+  bool zt_available = false;
 };
 
 /* Read an aarch64_ctx, returning the magic value, and setting *SIZE to the
@@ -478,6 +494,33 @@ aarch64_linux_read_signal_frame_info (frame_info_ptr this_frame,
 	  {
 	    /* This is context containing the tpidr2 register.  */
 	    signal_frame.tpidr2_section = section;
+	    section += size;
+	    break;
+	  }
+	case AARCH64_ZT_MAGIC:
+	  {
+	    gdb_byte buf[2];
+
+	    /* Extract the number of ZT registers available in this
+	       context.  */
+	    if (target_read_memory (section + AARCH64_SME2_CONTEXT_NREGS_OFFSET,
+				    buf, 2) != 0)
+	      {
+		warning (_("Failed to read the number of ZT registers from the "
+			   "ZT signal frame context."));
+		section += size;
+		break;
+	      }
+
+	    signal_frame.zt_register_count
+	      = extract_unsigned_integer (buf, 2, byte_order);
+
+	    /* This is a context containing the ZT registers.  This should only
+	       exist if we also have the ZA context.  The presence of the ZT
+	       context without the ZA context is invalid.  */
+	    signal_frame.zt_section = section;
+	    signal_frame.zt_available = true;
+
 	    section += size;
 	    break;
 	  }
@@ -515,6 +558,12 @@ aarch64_linux_read_signal_frame_info (frame_info_ptr this_frame,
       if (!extra_found && section > section_end)
 	break;
     }
+
+    /* Sanity check that if the ZT entry exists, the ZA entry must also
+       exist.  */
+    if (signal_frame.zt_available && !signal_frame.za_payload)
+      error (_("While reading signal context information, found a ZT context "
+	       "without a ZA context, which is invalid."));
 }
 
 /* Implement the "init" method of struct tramp_frame.  */
@@ -620,6 +669,22 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
       /* Restore SVG.  */
       trad_frame_set_reg_value (this_cache, tdep->sme_svg_regnum,
 				sve_vg_from_vl (signal_frame.svl));
+
+      /* Handle SME2 (ZT).  */
+      if (tdep->has_sme2 ()
+	  && signal_frame.za_section != 0
+	  && signal_frame.zt_register_count > 0)
+	{
+	  /* Is ZA state available?  */
+	  gdb_assert (svcr & SVCR_ZA_BIT);
+
+	  /* Restore the ZT state.  For now we assume that we only have
+	     a single ZT register.  If/When more ZT registers appear, we
+	     should update the code to handle that case accordingly.  */
+	  trad_frame_set_reg_addr (this_cache, tdep->sme2_zt0_regnum,
+				   signal_frame.zt_section
+				   + AARCH64_SME2_CONTEXT_REGS_OFFSET);
+	}
     }
 
   /* Restore the tpidr2 register, if the target supports it and if there is
-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 4/6] [gdb/aarch64] sme2: Core file support for ZT register set
  2023-08-22 11:21 [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux Luis Machado
                   ` (2 preceding siblings ...)
  2023-08-22 11:21 ` [PATCH v2 3/6] [gdb/aarch64] sme2: signal frame support Luis Machado
@ 2023-08-22 11:21 ` Luis Machado
  2023-08-27  1:21   ` Thiago Jung Bauermann
  2023-08-22 11:21 ` [PATCH v2 5/6] [gdb/testsuite] sme2: Extend SME tests to include SME2 Luis Machado
  2023-08-22 11:21 ` [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features Luis Machado
  5 siblings, 1 reply; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: thiago.bauermann

This patch adds support for ZT register dumps/reads for core files.  The
ZT register is available when the SME2 feature is advertised as available
by the Linux Kernel.

Unlike the enablement for SME1 and the ZA register, support for SME2 is rather
simple given the fixed size of the ZT0 register.

Validated on the Fast Models.
---
 gdb/aarch64-linux-tdep.c | 81 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 8b0b4d32971..a4d1fb87cbf 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -1374,6 +1374,50 @@ aarch64_linux_collect_za_regset (const struct regset *regset,
 			    size - SVE_HEADER_SIZE);
 }
 
+/* Supply register REGNUM from BUF to REGCACHE, using the register map
+   in REGSET.  If REGNUM is -1, do this for all registers in REGSET.
+   If BUF is NULL, set the registers to "unavailable" status.  */
+
+static void
+aarch64_linux_supply_zt_regset (const struct regset *regset,
+				struct regcache *regcache,
+				int regnum, const void *buf, size_t size)
+{
+  /* Read the ZT register note from a core file into the register buffer.  */
+
+  /* Handle an empty buffer.  */
+  if (buf == nullptr)
+    return regcache->supply_regset (regset, regnum, nullptr, size);
+
+  aarch64_gdbarch_tdep *tdep
+    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+  /* Supply the ZT0 register contents.  */
+  regcache->raw_supply (tdep->sme2_zt0_regnum, buf);
+}
+
+/* Collect register REGNUM from REGCACHE to BUF, using the register
+   map in REGSET.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+static void
+aarch64_linux_collect_zt_regset (const struct regset *regset,
+				 const struct regcache *regcache,
+				 int regnum, void *buf, size_t size)
+{
+  /* Read the ZT register contents from the register buffer into the core
+     file section.  */
+
+  gdb_assert (buf != nullptr);
+
+  aarch64_gdbarch_tdep *tdep
+    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
+
+  /* Dump the register cache contents for the ZT register to the buffer.  */
+  regcache->collect_regset (regset, tdep->sme2_zt0_regnum, buf,
+			    AARCH64_SME2_ZT0_SIZE);
+}
+
 /* Implement the "iterate_over_regset_sections" gdbarch method.  */
 
 static void
@@ -1462,6 +1506,30 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 	  SVE_HEADER_SIZE,
 	  SVE_HEADER_SIZE + std::pow (sve_vl_from_vq (tdep->sme_svq), 2),
 	  &aarch64_linux_za_regset, "ZA register", cb_data);
+
+      /* Handle SME2 (ZT) as well, which is only available if SME is
+	 available.  */
+      if (tdep->has_sme2 ())
+	{
+	  const struct regcache_map_entry zt_regmap[] =
+	    {
+	      { 1, tdep->sme2_zt0_regnum, AARCH64_SME2_ZT0_SIZE }
+	    };
+
+	  /* We set the register set size to REGSET_VARIABLE_SIZE here because
+	     in the future there might be more ZT registers.  */
+	  const struct regset aarch64_linux_zt_regset =
+	    {
+	      zt_regmap,
+	      aarch64_linux_supply_zt_regset, aarch64_linux_collect_zt_regset,
+	      REGSET_VARIABLE_SIZE
+	    };
+
+	  cb (".reg-aarch-zt",
+	      AARCH64_SME2_ZT0_SIZE,
+	      AARCH64_SME2_ZT0_SIZE,
+	      &aarch64_linux_zt_regset, "ZT registers", cb_data);
+	}
     }
 
   if (tdep->has_pauth ())
@@ -1567,6 +1635,19 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
   features.svq
     = aarch64_linux_core_read_vq (gdbarch, abfd, ".reg-aarch-za");
 
+  /* Are the ZT registers available?  */
+  if (bfd_get_section_by_name (abfd, ".reg-aarch-zt") != nullptr)
+    {
+      /* Check if ZA is also available, otherwise this is an invalid
+	 combination.  */
+      if (bfd_get_section_by_name (abfd, ".reg-aarch-za") != nullptr)
+	features.sme2 = true;
+      else
+	warning (_("While reading core file sections, found ZT registers entry "
+		   "but no ZA register entry.  The ZT contents will be "
+		   "ignored"));
+    }
+
   return aarch64_read_description (features);
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 5/6] [gdb/testsuite] sme2: Extend SME tests to include SME2
  2023-08-22 11:21 [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux Luis Machado
                   ` (3 preceding siblings ...)
  2023-08-22 11:21 ` [PATCH v2 4/6] [gdb/aarch64] sme2: Core file support for ZT register set Luis Machado
@ 2023-08-22 11:21 ` Luis Machado
  2023-08-27  1:23   ` Thiago Jung Bauermann
  2023-08-22 11:21 ` [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features Luis Machado
  5 siblings, 1 reply; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: thiago.bauermann

v2:

- Updated to use the new naming/organization of the test support files.

--

Reusing the SME tests, this patch introduces additional tests to exercise
reading/writing ZT0, availability of the register set, signal context reading
for ZT0 and also core file generation.
---
 gdb/testsuite/gdb.arch/aarch64-sme-core.c     | 32 ++++++++++-
 .../gdb.arch/aarch64-sme-core.exp.tcl         |  2 +-
 .../aarch64-sme-regs-available.exp.tcl        | 17 ++++++
 .../gdb.arch/aarch64-sme-regs-sigframe.c      | 32 ++++++++++-
 .../aarch64-sme-regs-sigframe.exp.tcl         | 13 ++++-
 .../aarch64-sme-regs-unavailable.exp.tcl      | 12 +++++
 gdb/testsuite/gdb.arch/aarch64-sme-sanity.c   | 32 ++++++++++-
 gdb/testsuite/lib/aarch64-scalable.exp        | 44 +++++++++++++++
 gdb/testsuite/lib/aarch64.exp                 | 53 +++++++++++++++++++
 9 files changed, 229 insertions(+), 8 deletions(-)

diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core.c b/gdb/testsuite/gdb.arch/aarch64-sme-core.c
index d71d18ebd3b..fcb14670e0d 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-core.c
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core.c
@@ -35,6 +35,11 @@
 #define HWCAP2_SME (1 << 23)
 #endif
 
+#ifndef HWCAP2_SME2
+#define HWCAP2_SME2 (1UL << 37)
+#define HWCAP2_SME2P1 (1UL << 38)
+#endif
+
 #ifndef PR_SVE_SET_VL
 #define PR_SVE_SET_VL 50
 #define PR_SVE_GET_VL 51
@@ -145,6 +150,27 @@ initialize_za_state ()
   __asm __volatile ("bne loop");
 }
 
+static void
+initialize_zt_state ()
+{
+  unsigned long hwcap2 = getauxval (AT_HWCAP2);
+
+  if (!(hwcap2 & HWCAP2_SME2) && !(hwcap2 & HWCAP2_SME2P1))
+    return;
+
+  char buffer[64];
+
+  for (int i = 0; i < 64; i++)
+    buffer[i] = 0xff;
+
+  __asm __volatile ("mov x0, %0\n\t" \
+		    : : "r" (buffer));
+
+  /* Initialize ZT0.  */
+  /* ldr zt0, x0 */
+  __asm __volatile (".word 0xe11f8000");
+}
+
 static void
 initialize_tpidr2 ()
 {
@@ -273,8 +299,8 @@ static int set_svl_size (int new_svl)
    0 - FPSIMD
    1 - SVE
    2 - SSVE
-   3 - ZA
-   4 - ZA and SSVE.  */
+   3 - ZA (+ SME2 ZT0)
+   4 - ZA and SSVE (+ SME2 ZT0).  */
 
 void enable_states (int state)
 {
@@ -295,6 +321,7 @@ void enable_states (int state)
     {
       enable_za ();
       initialize_za_state ();
+      initialize_zt_state ();
     }
   else if (state == 4)
     {
@@ -302,6 +329,7 @@ void enable_states (int state)
       enable_sm ();
       initialize_sve_state ();
       initialize_za_state ();
+      initialize_zt_state ();
     }
 
   return;
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
index 35e3d981e10..d387dd11a0e 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
@@ -13,7 +13,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-# Exercise core file reading/writing in the presence of SME support.
+# Exercise core file reading/writing in the presence of SME and SME2 support.
 # This test exercises GDB's dumping/loading capability for Linux
 # Kernel core files and for gcore core files.
 
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl
index ad3f0ee1dcc..74aeeb46684 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl
@@ -14,6 +14,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # Exercise reading/writing ZA registers when there is ZA state.
+# Exercise reading/writing to ZT0 when there is ZA state available.
 
 load_lib aarch64-scalable.exp
 
@@ -119,6 +120,22 @@ proc check_regs { mode vl svl } {
 	set last_slice [expr ($last_slice / 2)]
 	set num_elements [expr $num_elements / 2]
     }
+
+    # Exercise reading/writing from/to SME2 registers.
+    if [is_sme2_available] {
+      # The target supports SME2.
+      set zt_size 64
+      gdb_test "print sizeof \$zt0" " = $zt_size"
+
+      # Initially, when ZA is activated, ZT0 will be all zeroes.
+      set zt_pattern [string_to_regexp [1d_array_value_pattern 0 $zt_size]]
+      gdb_test "print \$zt0" " = $zt_pattern" "validate zeroed zt0"
+
+      # Validate that writing to ZT0 does the right thing.
+      initialize_1d_array "\$zt0" 255 $zt_size
+      set zt_pattern [string_to_regexp [1d_array_value_pattern 255 $zt_size]]
+      gdb_test "print \$zt0" " = $zt_pattern" "read back from zt0"
+    }
 }
 
 #
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c
index 9bc3e9c16fc..8f0827cf83a 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c
@@ -34,6 +34,11 @@
 #define HWCAP2_SME (1 << 23)
 #endif
 
+#ifndef HWCAP2_SME2
+#define HWCAP2_SME2 (1UL << 37)
+#define HWCAP2_SME2P1 (1UL << 38)
+#endif
+
 #ifndef PR_SVE_SET_VL
 #define PR_SVE_SET_VL 50
 #define PR_SVE_GET_VL 51
@@ -152,6 +157,27 @@ initialize_za_state ()
   __asm __volatile ("bne loop");
 }
 
+static void
+initialize_zt_state ()
+{
+  unsigned long hwcap2 = getauxval (AT_HWCAP2);
+
+  if (!(hwcap2 & HWCAP2_SME2) && !(hwcap2 & HWCAP2_SME2P1))
+    return;
+
+  char buffer[64];
+
+  for (int i = 0; i < 64; i++)
+    buffer[i] = 0xff;
+
+  __asm __volatile ("mov x0, %0\n\t" \
+		    : : "r" (buffer));
+
+  /* Initialize ZT0.  */
+  /* ldr zt0, x0 */
+  __asm __volatile (".word 0xe11f8000");
+}
+
 static void
 initialize_sve_state ()
 {
@@ -271,8 +297,8 @@ static int set_svl_size (int new_svl)
    0 - FPSIMD
    1 - SVE
    2 - SSVE
-   3 - ZA
-   4 - ZA and SSVE.  */
+   3 - ZA (+ SME2 ZT0)
+   4 - ZA and SSVE (+ SME2 ZT0).  */
 
 void enable_states (int state)
 {
@@ -293,6 +319,7 @@ void enable_states (int state)
     {
       enable_za ();
       initialize_za_state ();
+      initialize_zt_state ();
     }
   else if (state == 4)
     {
@@ -300,6 +327,7 @@ void enable_states (int state)
       enable_sm ();
       initialize_sve_state ();
       initialize_za_state ();
+      initialize_zt_state ();
     }
 
   return;
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl
index c2962417f70..30c7adb4db6 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl
@@ -90,10 +90,12 @@ proc test_sme_registers_sigframe { id_start id_end } {
 	    # Check the value of SVCR.
 	    gdb_test "print \$svcr" [get_svcr_value $state] "svcr before signal"
 
-	    # Handle SME ZA initialization and state.
+	    # Handle SME ZA and SME2 initialization and state.
 	    set byte 0
+	    set sme2_byte 0
 	    if { $state == "za" || $state == "za_ssve" } {
 		set byte 170
+		set sme2_byte 255
 	    }
 
 	    # Set the expected ZA pattern.
@@ -160,6 +162,15 @@ proc test_sme_registers_sigframe { id_start id_end } {
 
 	    # Check the value of TPIDR2 in the signal frame.
 	    gdb_test "print/x \$tpidr2" " = 0x102030405060708" "tpidr2 contents from signal frame"
+
+	    # Check the value of SME2 ZT0 in the signal frame.
+	    if [is_sme2_available] {
+		# The target supports SME2.
+		set zt_size 64
+		gdb_test "print sizeof \$zt0" " = $zt_size"
+		set zt_pattern [string_to_regexp [1d_array_value_pattern $sme2_byte $zt_size]]
+		gdb_test "print \$zt0" " = $zt_pattern" "zt contents from signal frame"
+	    }
 	}
     }
 }
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl
index 41d65c523f3..402996826b7 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl
@@ -17,6 +17,7 @@
 # - Printing ZA registers when there is no ZA state.
 # - Setting values of ZA registers when there is no ZA state.
 # - Validating ZA state is activated when we write to ZA registers.
+# - Validate that reading ZT0 without an active ZA state works as expected.
 
 load_lib aarch64-scalable.exp
 
@@ -89,6 +90,17 @@ proc_with_prefix check_regs { vl svl } {
 	set expected_size [expr $expected_size / 2]
 	set elements [expr ($elements / 2)]
     }
+
+    # Exercise reading from SME2 registers.
+    if [is_sme2_available] {
+	# The target supports SME2.
+	set zt_size 64
+	gdb_test "print sizeof \$zt0" " = $zt_size"
+
+	# If ZA is not active, ZT0 will always be zero.
+	set zt_pattern [string_to_regexp [1d_array_value_pattern 0 $zt_size]]
+	gdb_test "print \$zt0" " = $zt_pattern"
+    }
 }
 
 #
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c
index 694de0626d2..71b46b17855 100644
--- a/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c
@@ -33,6 +33,11 @@
 #define HWCAP2_SME (1 << 23)
 #endif
 
+#ifndef HWCAP2_SME2
+#define HWCAP2_SME2 (1UL << 37)
+#define HWCAP2_SME2P1 (1UL << 38)
+#endif
+
 static void
 enable_za ()
 {
@@ -131,6 +136,27 @@ initialize_za_state ()
   __asm __volatile ("bne loop");
 }
 
+static void
+initialize_zt_state ()
+{
+  unsigned long hwcap2 = getauxval (AT_HWCAP2);
+
+  if (!(hwcap2 & HWCAP2_SME2) && !(hwcap2 & HWCAP2_SME2P1))
+    return;
+
+  char buffer[64];
+
+  for (int i = 0; i < 64; i++)
+    buffer[i] = 0xff;
+
+  __asm __volatile ("mov x0, %0\n\t" \
+		    : : "r" (buffer));
+
+  /* Initialize ZT0.  */
+  /* ldr zt0, x0 */
+  __asm __volatile (".word 0xe11f8000");
+}
+
 static void
 initialize_sve_state ()
 {
@@ -190,8 +216,8 @@ initialize_sve_state ()
    0 - FPSIMD
    1 - SVE
    2 - SSVE
-   3 - ZA
-   4 - ZA and SSVE.  */
+   3 - ZA (+ SME2 ZT0)
+   4 - ZA and SSVE (+ SME2 ZT0).  */
 
 void enable_states (int state)
 {
@@ -212,6 +238,7 @@ void enable_states (int state)
     {
       enable_za ();
       initialize_za_state ();
+      initialize_zt_state ();
     }
   else if (state == 4)
     {
@@ -219,6 +246,7 @@ void enable_states (int state)
       enable_sm ();
       initialize_sve_state ();
       initialize_za_state ();
+      initialize_zt_state ();
     }
 
   return;
diff --git a/gdb/testsuite/lib/aarch64-scalable.exp b/gdb/testsuite/lib/aarch64-scalable.exp
index 5512fcb9d1c..f77daec2308 100644
--- a/gdb/testsuite/lib/aarch64-scalable.exp
+++ b/gdb/testsuite/lib/aarch64-scalable.exp
@@ -186,6 +186,18 @@ proc check_sme_regs { byte state svl } {
     gdb_test "print \$za" $za_pattern
 }
 
+#
+# Validate the values of the SME2 registers.
+#
+proc check_sme2_regs { byte } {
+    # The size of the ZT registers should always be fixed to 64 bytes.
+    set zt_size 64
+    gdb_test "print sizeof \$zt0" " = $zt_size"
+    # Check that we have the expected pattern of bytes for the ZT registers.
+    set zt_pattern [string_to_regexp [1d_array_value_pattern $byte $zt_size]]
+    gdb_test "print \$zt0" $zt_pattern
+}
+
 #
 # With register STATE, vector length VL and streaming vector length SVL,
 # run some register state checks to make sure the values are the expected
@@ -200,6 +212,9 @@ proc check_state { state vl svl } {
     #
     # The SME (ZA) register is initialized with a value of 0xaa (170) for
     # each byte.
+    #
+    # The SME2 (ZT) registers are initialized with a value of 0xff (255) for
+    # each byte.
 
     # Check VG to make sure it is correct
     set expected_vg [expr $vl / 8]
@@ -234,6 +249,35 @@ proc check_state { state vl svl } {
     check_sve_regs $sve_byte $state $vl $svl
     # Check SME registers
     check_sme_regs 170 $state $svl
+
+    # Check SME2 registers
+    if [is_sme2_available] {
+	# The SME2 ZT0 register will always be zero, except when ZA is active.
+	set sme2_byte 0
+	if {$state == "za" || $state == "za_ssve"} {
+	    set sme2_byte 255
+	}
+
+	# The target supports SME2, so check the ZT register values.
+	check_sme2_regs $sme2_byte
+    }
 }
 
+#
+# Return 1 if SME2 is available (meaning the ZT0 register exists).
+# Return 0 otherwise.
+#
+proc is_sme2_available { } {
 
+    # Does the ZT0 register exist?
+    gdb_test_multiple "print \$zt0" "" {
+	-re " = void.*${::gdb_prompt} $" {
+	    # SME2 is not available.
+	    return 0
+	}
+	-re " = {.*}\r\n${::gdb_prompt} $" {
+	    # SME2 is available.
+	    return 1
+	}
+    }
+}
diff --git a/gdb/testsuite/lib/aarch64.exp b/gdb/testsuite/lib/aarch64.exp
index cd43a4c4f77..40bba861b5f 100644
--- a/gdb/testsuite/lib/aarch64.exp
+++ b/gdb/testsuite/lib/aarch64.exp
@@ -151,3 +151,56 @@ proc check_fpsimd_regs { byte state vl svl} {
 	gdb_test "print $register_name" $fpsimd_pattern
     }
 }
+
+#
+# Validate the values of the SVE registers.
+#
+proc check_sve_regs { byte state vl svl } {
+
+    # If streaming mode is enabled, the vector length is the streaming
+    # vector length.
+    set z_pattern ""
+    set z_size 0
+    if {$state == "ssve" || $state == "za_ssve"} {
+	set z_pattern [string_to_regexp [1d_array_value_pattern $byte $svl]]
+	set z_size $svl
+    } else {
+	set z_size $vl
+
+	if {$state == "fpsimd" || $state == "za"} {
+	    # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
+	    # are zero.
+	    if {$vl == 16} {
+		set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
+	    } else {
+		set z_repeats [expr $vl - 16]
+		set z_pattern [string_to_regexp "{$byte <repeats 16 times>, 0 <repeats $z_repeats times>}"]
+	      }
+	} else {
+	    set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
+	}
+    }
+    set p_size [expr $z_size / 8]
+
+    # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
+    # are zero.
+    set p_byte $byte
+    if {$state == "fpsimd" || $state == "za"} {
+	set p_byte 0
+    }
+    set p_pattern [string_to_regexp [1d_array_value_pattern $p_byte $p_size]]
+
+    for {set number 0} {$number < 32} {incr number} {
+	set register_name "\$z${number}\.b\.u"
+	gdb_test "print sizeof $register_name" " = $z_size"
+	gdb_test "print $register_name" $z_pattern
+    }
+
+    for {set number 0} {$number < 16} {incr number} {
+	set register_name "\$p${number}"
+	gdb_test "print sizeof $register_name" " = $p_size"
+	gdb_test "print $register_name" $p_pattern
+    }
+
+    gdb_test "print \$ffr" $p_pattern
+}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features
  2023-08-22 11:21 [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux Luis Machado
                   ` (4 preceding siblings ...)
  2023-08-22 11:21 ` [PATCH v2 5/6] [gdb/testsuite] sme2: Extend SME tests to include SME2 Luis Machado
@ 2023-08-22 11:21 ` Luis Machado
  2023-08-22 11:34   ` Eli Zaretskii
  2023-08-27  1:27   ` Thiago Jung Bauermann
  5 siblings, 2 replies; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: thiago.bauermann

Document changes introduced by gdb's SME2 support.
---
 gdb/NEWS            |  3 +++
 gdb/doc/gdb.texinfo | 65 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index 49acc765ea7..20d1ffe4880 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,9 @@
 
 *** Changes since GDB 13
 
+* GDB now supports the AArch64 Scalable Matrix Extension 2 (SME2), which
+  includes a new 512 bit lookup table register named ZT0.
+
 * GDB now supports the AArch64 Scalable Matrix Extension (SME), which includes
   a new matrix register named ZA, a new thread register TPIDR2 and a new vector
   length register SVG (streaming vector granule).  GDB also supports tracking
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 23a40f0e8de..0b2f4a8d26d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -26358,6 +26358,50 @@ incorrect values for SVE registers (when in streaming mode).
 This is the same limitation we have for the @acronym{SVE} registers, and there
 are plans to address this limitation going forward.
 
+@subsubsection AArch64 SME2.
+@anchor{AArch64 SME2}
+@cindex SME2
+@cindex AArch64 SME2
+@cindex Scalable Matrix Extension 2
+
+The Scalable Matrix Extension 2 is an AArch64 architecture extension that
+further expands the @acronym{SME} extension with the following:
+
+@itemize
+
+@item The ability to address the @code{ZA} array through groups of
+one-dimensional @code{ZA} array vectors, as opposed to @code{ZA} tiles
+with 2 dimensions.
+
+@item Instructions to operate on groups of @acronym{SVE} @code{Z} registers and
+@code{ZA} array vectors.
+
+@item A new 512 bit @code{ZT0} lookup table register, for data decompression.
+
+@end itemize
+
+When @value{GDBN} is debugging the AArch64 architecture, if the Scalable Matrix
+Extension 2 (@acronym{SME2}) is present, then @value{GDBN} will make the
+@code{ZT0} register available.
+
+The @code{ZT0} register is only considered active when the @code{ZA} register
+state is active, therefore when the @sc{za} bit of the @code{SVCR} is 1.
+
+When the @sc{za} bit of @code{SVCR} is 0, that means the @code{ZA} register
+state is not active, which means the @code{ZT0} register state is also not
+active.
+
+When @code{ZT0} is not active, it is comprised of zeroes, just like @code{ZA}.
+
+Similarly to the @code{ZA} register, if the @code{ZT0} state is not active and
+the user attempts to modify its value such that any of its bytes is non-zero,
+then @value{GDBN} will initialize the @code{ZA} register state as well, which
+means the @code{SVCR} @sc{za} bit gets set to 1.
+
+For more information about @acronym{SME2}, please refer to the
+official @url{https://developer.arm.com/documentation/ddi0487/latest,
+architecture documentation}.
+
 @subsubsection AArch64 Pointer Authentication.
 @cindex AArch64 Pointer Authentication.
 @anchor{AArch64 PAC}
@@ -48540,6 +48584,27 @@ extensions of the architecture.
 Extra registers are allowed in this feature, but they will not affect
 @value{GDBN}.
 
+The @samp{org.gnu.gdb.aarch64.sme} feature is required when the target also
+reports support for the @samp{org.gnu.gdb.aarch64.sme2} feature.
+
+@subsubsection AArch64 SME2 registers feature
+
+The @samp{org.gnu.gdb.aarch64.sme2} feature is optional.  If present,
+then the @samp{org.gnu.gdb.aarch64.sme} feature must also be present. The
+@samp{org.gnu.gdb.aarch64.sme2} feature should contain the following:
+@xref{AArch64 SME2}
+
+@itemize @minus
+
+@item
+@code{ZT0} is a register of 512 bits (64 bytes).  It is defined as a vector
+of bytes.
+
+@end itemize
+
+Extra registers are allowed in this feature, but they will not affect
+@value{GDBN}.
+
 @node ARC Features
 @subsection ARC Features
 @cindex target descriptions, ARC Features
-- 
2.25.1


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features
  2023-08-22 11:21 ` [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features Luis Machado
@ 2023-08-22 11:34   ` Eli Zaretskii
  2023-08-22 11:45     ` Luis Machado
  2023-08-27  1:27   ` Thiago Jung Bauermann
  1 sibling, 1 reply; 19+ messages in thread
From: Eli Zaretskii @ 2023-08-22 11:34 UTC (permalink / raw)
  To: Luis Machado; +Cc: gdb-patches, thiago.bauermann

> CC: <thiago.bauermann@linaro.org>
> Date: Tue, 22 Aug 2023 12:21:44 +0100
> From: Luis Machado via Gdb-patches <gdb-patches@sourceware.org>
> 
> +The @samp{org.gnu.gdb.aarch64.sme2} feature is optional.  If present,
> +then the @samp{org.gnu.gdb.aarch64.sme} feature must also be present. The
                                                                       ^^
Two spaces there, please.

Thanks.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features
  2023-08-22 11:34   ` Eli Zaretskii
@ 2023-08-22 11:45     ` Luis Machado
  0 siblings, 0 replies; 19+ messages in thread
From: Luis Machado @ 2023-08-22 11:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches, thiago.bauermann

On 8/22/23 12:34, Eli Zaretskii wrote:
>> CC: <thiago.bauermann@linaro.org>
>> Date: Tue, 22 Aug 2023 12:21:44 +0100
>> From: Luis Machado via Gdb-patches <gdb-patches@sourceware.org>
>>
>> +The @samp{org.gnu.gdb.aarch64.sme2} feature is optional.  If present,
>> +then the @samp{org.gnu.gdb.aarch64.sme} feature must also be present. The
>                                                                        ^^
> Two spaces there, please.
> 
> Thanks.
> 
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>

Thanks. Fixed now. Also fixed the missing period after xref.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb on Linux
  2023-08-22 11:21 ` [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb " Luis Machado
@ 2023-08-27  1:16   ` Thiago Jung Bauermann
  2023-08-30 12:53     ` Luis Machado
  0 siblings, 1 reply; 19+ messages in thread
From: Thiago Jung Bauermann @ 2023-08-27  1:16 UTC (permalink / raw)
  To: Luis Machado; +Cc: gdb-patches


Hello Luis,

I have only one minor nit about this patch. In any case:

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

Luis Machado <luis.machado@arm.com> writes:

> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index d7fcef5a0db..edbe6895c86 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -376,6 +376,37 @@ store_za_to_thread (struct regcache *regcache)
>  				     tdep->sme_svcr_regnum);
>  }
>  
> +/* Fill GDB's REGCACHE with the ZT register set contents from the
> +   current thread.  If there is no active ZA register state, make the
> +   ZT register contents zero.  */

Same comment about "current thread" from the SME patch series: the
function uses the regcache's ptid to identify the thread, so it's not
from the current thread that it gets the register values.

> +static void
> +fetch_zt_from_thread (struct regcache *regcache)
> +{
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> +
> +  /* Read ZT state from the thread to the register cache.  */
> +  aarch64_zt_regs_copy_to_reg_buf (regcache->ptid ().lwp (),
> +				   regcache,
> +				   tdep->sme2_zt0_regnum);
> +}
> +
> +/* Store the NT_ARM_ZT register set contents from GDB's REGCACHE to the current
> +   thread.  */

Also here.

> +
> +static void
> +store_zt_to_thread (struct regcache *regcache)
> +{
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> +
> +  /* Write ZT state from the register cache to the thread.  */
> +  aarch64_zt_regs_copy_from_reg_buf (regcache->ptid ().lwp (),
> +				     regcache,
> +				     tdep->sme2_zt0_regnum);
> +}

-- 
Thiago

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/6] [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver
  2023-08-22 11:21 ` [PATCH v2 2/6] [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver Luis Machado
@ 2023-08-27  1:18   ` Thiago Jung Bauermann
  2023-08-30 12:54     ` Luis Machado
  0 siblings, 1 reply; 19+ messages in thread
From: Thiago Jung Bauermann @ 2023-08-27  1:18 UTC (permalink / raw)
  To: Luis Machado; +Cc: gdb-patches


Luis Machado <luis.machado@arm.com> writes:

> This patch teaches gdbserver about the SME2 and the ZT0 register.
>
> Since most of the code used by gdbserver for SME2 is shared with gdb, this
> is a rather small patch that reuses most of the code put in place for native
> AArch64 Linux.
>
> Validated under Fast Models.
> ---
>  gdbserver/linux-aarch64-low.cc | 63 ++++++++++++++++++++++++++++++++++
>  1 file changed, 63 insertions(+)
>
> diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
> index 95688480c3d..783053e359b 100644
> --- a/gdbserver/linux-aarch64-low.cc
> +++ b/gdbserver/linux-aarch64-low.cc
> @@ -811,6 +811,52 @@ aarch64_za_regs_copy_from_regcache (struct regcache *regcache, void *buf)
>    memcpy (buf, za_state.data (), za_state.size ());
>  }
>  
> +/* Wrapper for aarch64_zt_regs_copy_to_reg_buf, to help copying NT_ARM_ZT
> +   state from the thread (BUF) to the register cache.  */
> +
> +static void
> +aarch64_zt_regs_copy_to_regcache (struct regcache *regcache,
> +				  ATTRIBUTE_UNUSED const void *buf)
> +{
> +  /* BUF is unused here since we collect the data straight from a ptrace
> +     request, therefore bypassing gdbserver's own call to ptrace.  */
> +  int tid = lwpid_of (current_thread);
> +
> +  gdb::optional<int> zt_regnum
> +    = find_regno_no_throw (regcache->tdesc, "zt0");
> +
> +  gdb_assert (zt_regnum.has_value ());

If this code is changed to use find_regno(), this gdb_assert() becomes
unnecessary.

> +
> +  /* Update the register cache.  aarch64_zt_regs_copy_to_reg_buf handles
> +     fetching the NT_ARM_ZT state from thread TID.  */
> +  aarch64_zt_regs_copy_to_reg_buf (tid, regcache, *zt_regnum);
> +}
> +
> +/* Wrapper for aarch64_zt_regs_copy_from_reg_buf, to help copying NT_ARM_ZT
> +   state from the register cache to the thread (BUF).  */
> +
> +static void
> +aarch64_zt_regs_copy_from_regcache (struct regcache *regcache, void *buf)
> +{
> +  int tid = lwpid_of (current_thread);
> +
> +  gdb::optional<int> zt_regnum
> +    = find_regno_no_throw (regcache->tdesc, "za");
> +
> +  gdb_assert (zt_regnum.has_value ());

Same comment about find_regno().

> +
> +  /* Update the thread NT_ARM_ZT state.  aarch64_zt_regs_copy_from_reg_buf
> +     handles writing the ZT state back to thread TID.  */
> +  aarch64_zt_regs_copy_from_reg_buf (tid, regcache, *zt_regnum);
> +
> +  /* We need to return the expected data in BUF, so copy whatever the kernel
> +     already has to BUF.  */
> +
> +  /* Obtain a dump of NT_ARM_ZT from ptrace.  */
> +  gdb::byte_vector zt_state = aarch64_fetch_zt_regset (tid);
> +  memcpy (buf, zt_state.data (), zt_state.size ());
> +}
> +
>  /* Array containing all the possible register sets for AArch64/Linux.  During
>     architecture setup, these will be checked against the HWCAP/HWCAP2 bits for
>     validity and enabled/disabled accordingly.
> @@ -838,6 +884,11 @@ static struct regset_info aarch64_regsets[] =
>      0, EXTENDED_REGS,
>      aarch64_za_regs_copy_from_regcache, aarch64_za_regs_copy_to_regcache
>    },
> +  /* Scalable Matrix Extension 2 (SME2) ZT registers.  */
> +  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_ZT,
> +    0, EXTENDED_REGS,
> +    aarch64_zt_regs_copy_from_regcache, aarch64_zt_regs_copy_to_regcache
> +  },
>    /* PAC registers.  */
>    { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
>      0, OPTIONAL_REGS,
> @@ -909,6 +960,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
>  	  if (features.svq > 0)
>  	    regset->size = ZA_PT_SIZE (features.svq);
>  	  break;
> +	case NT_ARM_ZT:
> +	  if (features.sme2)
> +	    regset->size = 64;

Suggest using AARCH64_SME2_ZT0_SIZE here.

> +	  break;
>  	default:
>  	  gdb_assert_not_reached ("Unknown register set found.");
>  	}
> @@ -947,6 +1002,14 @@ aarch64_target::low_arch_setup ()
>        if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME)
>  	features.svq = aarch64_za_get_svq (tid);
>  
> +      /* Scalable Matrix Extension 2 feature check.  */
> +      CORE_ADDR hwcap2 = linux_get_hwcap2 (pid, 8);
> +      if ((hwcap2 & HWCAP2_SME2) || (hwcap2 & HWCAP2_SME2P1))
> +	{
> +	  /* Make sure ptrace supports NT_ARM_ZT.  */
> +	  features.sme2 = supports_zt_registers (tid);
> +	}
> +
>        current_process ()->tdesc = aarch64_linux_read_description (features);
>  
>        /* Adjust the register sets we should use for this particular set of

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

-- 
Thiago

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 3/6] [gdb/aarch64] sme2: signal frame support
  2023-08-22 11:21 ` [PATCH v2 3/6] [gdb/aarch64] sme2: signal frame support Luis Machado
@ 2023-08-27  1:19   ` Thiago Jung Bauermann
  0 siblings, 0 replies; 19+ messages in thread
From: Thiago Jung Bauermann @ 2023-08-27  1:19 UTC (permalink / raw)
  To: Luis Machado; +Cc: gdb-patches


Luis Machado <luis.machado@arm.com> writes:

> Teach gdb about the ZT state on signal frames and how to restore
> the contents of the registers.
>
> There is a new ZT_MAGIC context that the Linux Kernel uses to communicate
> the ZT register state to gdb.
>
> As mentioned before, the ZT state should only be available when the ZA state
> is available.
>
> Validated under Fast Models.
> ---
>  gdb/aarch64-linux-tdep.c | 65 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 65 insertions(+)

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

-- 
Thiago

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 4/6] [gdb/aarch64] sme2: Core file support for ZT register set
  2023-08-22 11:21 ` [PATCH v2 4/6] [gdb/aarch64] sme2: Core file support for ZT register set Luis Machado
@ 2023-08-27  1:21   ` Thiago Jung Bauermann
  2023-08-30 12:56     ` Luis Machado
  0 siblings, 1 reply; 19+ messages in thread
From: Thiago Jung Bauermann @ 2023-08-27  1:21 UTC (permalink / raw)
  To: Luis Machado; +Cc: gdb-patches


Luis Machado <luis.machado@arm.com> writes:

> This patch adds support for ZT register dumps/reads for core files.  The
> ZT register is available when the SME2 feature is advertised as available
> by the Linux Kernel.
>
> Unlike the enablement for SME1 and the ZA register, support for SME2 is rather
> simple given the fixed size of the ZT0 register.
>
> Validated on the Fast Models.
> ---
>  gdb/aarch64-linux-tdep.c | 81 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 81 insertions(+)
>
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index 8b0b4d32971..a4d1fb87cbf 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -1374,6 +1374,50 @@ aarch64_linux_collect_za_regset (const struct regset *regset,
>  			    size - SVE_HEADER_SIZE);
>  }
>  
> +/* Supply register REGNUM from BUF to REGCACHE, using the register map
> +   in REGSET.  If REGNUM is -1, do this for all registers in REGSET.
> +   If BUF is NULL, set the registers to "unavailable" status.  */
> +
> +static void
> +aarch64_linux_supply_zt_regset (const struct regset *regset,
> +				struct regcache *regcache,
> +				int regnum, const void *buf, size_t size)
> +{
> +  /* Read the ZT register note from a core file into the register buffer.  */
> +
> +  /* Handle an empty buffer.  */
> +  if (buf == nullptr)
> +    return regcache->supply_regset (regset, regnum, nullptr, size);
> +
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());

Is it worth adding here a "gdb_assert (size >= AARCH64_SME2_ZT0_SIZE)"?

> +
> +  /* Supply the ZT0 register contents.  */
> +  regcache->raw_supply (tdep->sme2_zt0_regnum, buf);
> +}
> +
> +/* Collect register REGNUM from REGCACHE to BUF, using the register
> +   map in REGSET.  If REGNUM is -1, do this for all registers in
> +   REGSET.  */
> +
> +static void
> +aarch64_linux_collect_zt_regset (const struct regset *regset,
> +				 const struct regcache *regcache,
> +				 int regnum, void *buf, size_t size)
> +{
> +  /* Read the ZT register contents from the register buffer into the core
> +     file section.  */
> +
> +  gdb_assert (buf != nullptr);

Also here, is it worth adding a
"gdb_assert (size >= AARCH64_SME2_ZT0_SIZE)"?

> +
> +  aarch64_gdbarch_tdep *tdep
> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> +
> +  /* Dump the register cache contents for the ZT register to the buffer.  */
> +  regcache->collect_regset (regset, tdep->sme2_zt0_regnum, buf,
> +			    AARCH64_SME2_ZT0_SIZE);
> +}
> +

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

-- 
Thiago

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 5/6] [gdb/testsuite] sme2: Extend SME tests to include SME2
  2023-08-22 11:21 ` [PATCH v2 5/6] [gdb/testsuite] sme2: Extend SME tests to include SME2 Luis Machado
@ 2023-08-27  1:23   ` Thiago Jung Bauermann
  2023-08-30 12:56     ` Luis Machado
  0 siblings, 1 reply; 19+ messages in thread
From: Thiago Jung Bauermann @ 2023-08-27  1:23 UTC (permalink / raw)
  To: Luis Machado; +Cc: gdb-patches


Luis Machado <luis.machado@arm.com> writes:

> diff --git a/gdb/testsuite/lib/aarch64.exp b/gdb/testsuite/lib/aarch64.exp
> index cd43a4c4f77..40bba861b5f 100644
> --- a/gdb/testsuite/lib/aarch64.exp
> +++ b/gdb/testsuite/lib/aarch64.exp
> @@ -151,3 +151,56 @@ proc check_fpsimd_regs { byte state vl svl} {
>  	gdb_test "print $register_name" $fpsimd_pattern
>      }
>  }
> +
> +#
> +# Validate the values of the SVE registers.
> +#
> +proc check_sve_regs { byte state vl svl } {

This is a duplicate of the same function in aarch64-scalable.exp. It
seems to be included here by mistake.

> +
> +    # If streaming mode is enabled, the vector length is the streaming
> +    # vector length.
> +    set z_pattern ""
> +    set z_size 0
> +    if {$state == "ssve" || $state == "za_ssve"} {
> +	set z_pattern [string_to_regexp [1d_array_value_pattern $byte $svl]]
> +	set z_size $svl
> +    } else {
> +	set z_size $vl
> +
> +	if {$state == "fpsimd" || $state == "za"} {
> +	    # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
> +	    # are zero.
> +	    if {$vl == 16} {
> +		set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
> +	    } else {
> +		set z_repeats [expr $vl - 16]
> +		set z_pattern [string_to_regexp "{$byte <repeats 16 times>, 0 <repeats $z_repeats times>}"]
> +	      }
> +	} else {
> +	    set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
> +	}
> +    }
> +    set p_size [expr $z_size / 8]
> +
> +    # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
> +    # are zero.
> +    set p_byte $byte
> +    if {$state == "fpsimd" || $state == "za"} {
> +	set p_byte 0
> +    }
> +    set p_pattern [string_to_regexp [1d_array_value_pattern $p_byte $p_size]]
> +
> +    for {set number 0} {$number < 32} {incr number} {
> +	set register_name "\$z${number}\.b\.u"
> +	gdb_test "print sizeof $register_name" " = $z_size"
> +	gdb_test "print $register_name" $z_pattern
> +    }
> +
> +    for {set number 0} {$number < 16} {incr number} {
> +	set register_name "\$p${number}"
> +	gdb_test "print sizeof $register_name" " = $p_size"
> +	gdb_test "print $register_name" $p_pattern
> +    }
> +
> +    gdb_test "print \$ffr" $p_pattern
> +}

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

-- 
Thiago

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features
  2023-08-22 11:21 ` [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features Luis Machado
  2023-08-22 11:34   ` Eli Zaretskii
@ 2023-08-27  1:27   ` Thiago Jung Bauermann
  1 sibling, 0 replies; 19+ messages in thread
From: Thiago Jung Bauermann @ 2023-08-27  1:27 UTC (permalink / raw)
  To: Luis Machado; +Cc: gdb-patches


Luis Machado <luis.machado@arm.com> writes:

> Document changes introduced by gdb's SME2 support.
> ---
>  gdb/NEWS            |  3 +++
>  gdb/doc/gdb.texinfo | 65 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 68 insertions(+)

Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>

-- 
Thiago

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb on Linux
  2023-08-27  1:16   ` Thiago Jung Bauermann
@ 2023-08-30 12:53     ` Luis Machado
  0 siblings, 0 replies; 19+ messages in thread
From: Luis Machado @ 2023-08-30 12:53 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches

On 8/27/23 02:16, Thiago Jung Bauermann wrote:
> 
> Hello Luis,
> 
> I have only one minor nit about this patch. In any case:
> 
> Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> 
> Luis Machado <luis.machado@arm.com> writes:
> 
>> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
>> index d7fcef5a0db..edbe6895c86 100644
>> --- a/gdb/aarch64-linux-nat.c
>> +++ b/gdb/aarch64-linux-nat.c
>> @@ -376,6 +376,37 @@ store_za_to_thread (struct regcache *regcache)
>>  				     tdep->sme_svcr_regnum);
>>  }
>>  
>> +/* Fill GDB's REGCACHE with the ZT register set contents from the
>> +   current thread.  If there is no active ZA register state, make the
>> +   ZT register contents zero.  */
> 
> Same comment about "current thread" from the SME patch series: the
> function uses the regcache's ptid to identify the thread, so it's not
> from the current thread that it gets the register values.
> 
>> +static void
>> +fetch_zt_from_thread (struct regcache *regcache)
>> +{
>> +  aarch64_gdbarch_tdep *tdep
>> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
>> +
>> +  /* Read ZT state from the thread to the register cache.  */
>> +  aarch64_zt_regs_copy_to_reg_buf (regcache->ptid ().lwp (),
>> +				   regcache,
>> +				   tdep->sme2_zt0_regnum);
>> +}
>> +
>> +/* Store the NT_ARM_ZT register set contents from GDB's REGCACHE to the current
>> +   thread.  */
> 
> Also here.
> 

Thanks. Fixed now.

>> +
>> +static void
>> +store_zt_to_thread (struct regcache *regcache)
>> +{
>> +  aarch64_gdbarch_tdep *tdep
>> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
>> +
>> +  /* Write ZT state from the register cache to the thread.  */
>> +  aarch64_zt_regs_copy_from_reg_buf (regcache->ptid ().lwp (),
>> +				     regcache,
>> +				     tdep->sme2_zt0_regnum);
>> +}
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/6] [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver
  2023-08-27  1:18   ` Thiago Jung Bauermann
@ 2023-08-30 12:54     ` Luis Machado
  0 siblings, 0 replies; 19+ messages in thread
From: Luis Machado @ 2023-08-30 12:54 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches

On 8/27/23 02:18, Thiago Jung Bauermann wrote:
> 
> Luis Machado <luis.machado@arm.com> writes:
> 
>> This patch teaches gdbserver about the SME2 and the ZT0 register.
>>
>> Since most of the code used by gdbserver for SME2 is shared with gdb, this
>> is a rather small patch that reuses most of the code put in place for native
>> AArch64 Linux.
>>
>> Validated under Fast Models.
>> ---
>>  gdbserver/linux-aarch64-low.cc | 63 ++++++++++++++++++++++++++++++++++
>>  1 file changed, 63 insertions(+)
>>
>> diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
>> index 95688480c3d..783053e359b 100644
>> --- a/gdbserver/linux-aarch64-low.cc
>> +++ b/gdbserver/linux-aarch64-low.cc
>> @@ -811,6 +811,52 @@ aarch64_za_regs_copy_from_regcache (struct regcache *regcache, void *buf)
>>    memcpy (buf, za_state.data (), za_state.size ());
>>  }
>>  
>> +/* Wrapper for aarch64_zt_regs_copy_to_reg_buf, to help copying NT_ARM_ZT
>> +   state from the thread (BUF) to the register cache.  */
>> +
>> +static void
>> +aarch64_zt_regs_copy_to_regcache (struct regcache *regcache,
>> +				  ATTRIBUTE_UNUSED const void *buf)
>> +{
>> +  /* BUF is unused here since we collect the data straight from a ptrace
>> +     request, therefore bypassing gdbserver's own call to ptrace.  */
>> +  int tid = lwpid_of (current_thread);
>> +
>> +  gdb::optional<int> zt_regnum
>> +    = find_regno_no_throw (regcache->tdesc, "zt0");
>> +
>> +  gdb_assert (zt_regnum.has_value ());
> 
> If this code is changed to use find_regno(), this gdb_assert() becomes
> unnecessary.
> 

Indeed. Fixed now.

>> +
>> +  /* Update the register cache.  aarch64_zt_regs_copy_to_reg_buf handles
>> +     fetching the NT_ARM_ZT state from thread TID.  */
>> +  aarch64_zt_regs_copy_to_reg_buf (tid, regcache, *zt_regnum);
>> +}
>> +
>> +/* Wrapper for aarch64_zt_regs_copy_from_reg_buf, to help copying NT_ARM_ZT
>> +   state from the register cache to the thread (BUF).  */
>> +
>> +static void
>> +aarch64_zt_regs_copy_from_regcache (struct regcache *regcache, void *buf)
>> +{
>> +  int tid = lwpid_of (current_thread);
>> +
>> +  gdb::optional<int> zt_regnum
>> +    = find_regno_no_throw (regcache->tdesc, "za");
>> +
>> +  gdb_assert (zt_regnum.has_value ());
> 
> Same comment about find_regno().
> 

Fixed.

>> +
>> +  /* Update the thread NT_ARM_ZT state.  aarch64_zt_regs_copy_from_reg_buf
>> +     handles writing the ZT state back to thread TID.  */
>> +  aarch64_zt_regs_copy_from_reg_buf (tid, regcache, *zt_regnum);
>> +
>> +  /* We need to return the expected data in BUF, so copy whatever the kernel
>> +     already has to BUF.  */
>> +
>> +  /* Obtain a dump of NT_ARM_ZT from ptrace.  */
>> +  gdb::byte_vector zt_state = aarch64_fetch_zt_regset (tid);
>> +  memcpy (buf, zt_state.data (), zt_state.size ());
>> +}
>> +
>>  /* Array containing all the possible register sets for AArch64/Linux.  During
>>     architecture setup, these will be checked against the HWCAP/HWCAP2 bits for
>>     validity and enabled/disabled accordingly.
>> @@ -838,6 +884,11 @@ static struct regset_info aarch64_regsets[] =
>>      0, EXTENDED_REGS,
>>      aarch64_za_regs_copy_from_regcache, aarch64_za_regs_copy_to_regcache
>>    },
>> +  /* Scalable Matrix Extension 2 (SME2) ZT registers.  */
>> +  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_ZT,
>> +    0, EXTENDED_REGS,
>> +    aarch64_zt_regs_copy_from_regcache, aarch64_zt_regs_copy_to_regcache
>> +  },
>>    /* PAC registers.  */
>>    { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
>>      0, OPTIONAL_REGS,
>> @@ -909,6 +960,10 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
>>  	  if (features.svq > 0)
>>  	    regset->size = ZA_PT_SIZE (features.svq);
>>  	  break;
>> +	case NT_ARM_ZT:
>> +	  if (features.sme2)
>> +	    regset->size = 64;
> 
> Suggest using AARCH64_SME2_ZT0_SIZE here.
> 

Yeah. I think I wrote this before I defined the size. Changed now.

>> +	  break;
>>  	default:
>>  	  gdb_assert_not_reached ("Unknown register set found.");
>>  	}
>> @@ -947,6 +1002,14 @@ aarch64_target::low_arch_setup ()
>>        if (linux_get_hwcap2 (pid, 8) & HWCAP2_SME)
>>  	features.svq = aarch64_za_get_svq (tid);
>>  
>> +      /* Scalable Matrix Extension 2 feature check.  */
>> +      CORE_ADDR hwcap2 = linux_get_hwcap2 (pid, 8);
>> +      if ((hwcap2 & HWCAP2_SME2) || (hwcap2 & HWCAP2_SME2P1))
>> +	{
>> +	  /* Make sure ptrace supports NT_ARM_ZT.  */
>> +	  features.sme2 = supports_zt_registers (tid);
>> +	}
>> +
>>        current_process ()->tdesc = aarch64_linux_read_description (features);
>>  
>>        /* Adjust the register sets we should use for this particular set of
> 
> Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 4/6] [gdb/aarch64] sme2: Core file support for ZT register set
  2023-08-27  1:21   ` Thiago Jung Bauermann
@ 2023-08-30 12:56     ` Luis Machado
  0 siblings, 0 replies; 19+ messages in thread
From: Luis Machado @ 2023-08-30 12:56 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches

On 8/27/23 02:21, Thiago Jung Bauermann wrote:
> 
> Luis Machado <luis.machado@arm.com> writes:
> 
>> This patch adds support for ZT register dumps/reads for core files.  The
>> ZT register is available when the SME2 feature is advertised as available
>> by the Linux Kernel.
>>
>> Unlike the enablement for SME1 and the ZA register, support for SME2 is rather
>> simple given the fixed size of the ZT0 register.
>>
>> Validated on the Fast Models.
>> ---
>>  gdb/aarch64-linux-tdep.c | 81 ++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 81 insertions(+)
>>
>> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
>> index 8b0b4d32971..a4d1fb87cbf 100644
>> --- a/gdb/aarch64-linux-tdep.c
>> +++ b/gdb/aarch64-linux-tdep.c
>> @@ -1374,6 +1374,50 @@ aarch64_linux_collect_za_regset (const struct regset *regset,
>>  			    size - SVE_HEADER_SIZE);
>>  }
>>  
>> +/* Supply register REGNUM from BUF to REGCACHE, using the register map
>> +   in REGSET.  If REGNUM is -1, do this for all registers in REGSET.
>> +   If BUF is NULL, set the registers to "unavailable" status.  */
>> +
>> +static void
>> +aarch64_linux_supply_zt_regset (const struct regset *regset,
>> +				struct regcache *regcache,
>> +				int regnum, const void *buf, size_t size)
>> +{
>> +  /* Read the ZT register note from a core file into the register buffer.  */
>> +
>> +  /* Handle an empty buffer.  */
>> +  if (buf == nullptr)
>> +    return regcache->supply_regset (regset, regnum, nullptr, size);
>> +
>> +  aarch64_gdbarch_tdep *tdep
>> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
> 
> Is it worth adding here a "gdb_assert (size >= AARCH64_SME2_ZT0_SIZE)"?
> 

Yes. That makes sense.

>> +
>> +  /* Supply the ZT0 register contents.  */
>> +  regcache->raw_supply (tdep->sme2_zt0_regnum, buf);
>> +}
>> +
>> +/* Collect register REGNUM from REGCACHE to BUF, using the register
>> +   map in REGSET.  If REGNUM is -1, do this for all registers in
>> +   REGSET.  */
>> +
>> +static void
>> +aarch64_linux_collect_zt_regset (const struct regset *regset,
>> +				 const struct regcache *regcache,
>> +				 int regnum, void *buf, size_t size)
>> +{
>> +  /* Read the ZT register contents from the register buffer into the core
>> +     file section.  */
>> +
>> +  gdb_assert (buf != nullptr);
> 
> Also here, is it worth adding a
> "gdb_assert (size >= AARCH64_SME2_ZT0_SIZE)"?
> 

Fixed as well.

>> +
>> +  aarch64_gdbarch_tdep *tdep
>> +    = gdbarch_tdep<aarch64_gdbarch_tdep> (regcache->arch ());
>> +
>> +  /* Dump the register cache contents for the ZT register to the buffer.  */
>> +  regcache->collect_regset (regset, tdep->sme2_zt0_regnum, buf,
>> +			    AARCH64_SME2_ZT0_SIZE);
>> +}
>> +
> 
> Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 5/6] [gdb/testsuite] sme2: Extend SME tests to include SME2
  2023-08-27  1:23   ` Thiago Jung Bauermann
@ 2023-08-30 12:56     ` Luis Machado
  0 siblings, 0 replies; 19+ messages in thread
From: Luis Machado @ 2023-08-30 12:56 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: gdb-patches

On 8/27/23 02:23, Thiago Jung Bauermann wrote:
> 
> Luis Machado <luis.machado@arm.com> writes:
> 
>> diff --git a/gdb/testsuite/lib/aarch64.exp b/gdb/testsuite/lib/aarch64.exp
>> index cd43a4c4f77..40bba861b5f 100644
>> --- a/gdb/testsuite/lib/aarch64.exp
>> +++ b/gdb/testsuite/lib/aarch64.exp
>> @@ -151,3 +151,56 @@ proc check_fpsimd_regs { byte state vl svl} {
>>  	gdb_test "print $register_name" $fpsimd_pattern
>>      }
>>  }
>> +
>> +#
>> +# Validate the values of the SVE registers.
>> +#
>> +proc check_sve_regs { byte state vl svl } {
> 
> This is a duplicate of the same function in aarch64-scalable.exp. It
> seems to be included here by mistake.
> 

Oops. Missed removing that entry when I split aarch64.exp.

Removed now.

Thanks for the reviews!

>> +
>> +    # If streaming mode is enabled, the vector length is the streaming
>> +    # vector length.
>> +    set z_pattern ""
>> +    set z_size 0
>> +    if {$state == "ssve" || $state == "za_ssve"} {
>> +	set z_pattern [string_to_regexp [1d_array_value_pattern $byte $svl]]
>> +	set z_size $svl
>> +    } else {
>> +	set z_size $vl
>> +
>> +	if {$state == "fpsimd" || $state == "za"} {
>> +	    # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
>> +	    # are zero.
>> +	    if {$vl == 16} {
>> +		set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
>> +	    } else {
>> +		set z_repeats [expr $vl - 16]
>> +		set z_pattern [string_to_regexp "{$byte <repeats 16 times>, 0 <repeats $z_repeats times>}"]
>> +	      }
>> +	} else {
>> +	    set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
>> +	}
>> +    }
>> +    set p_size [expr $z_size / 8]
>> +
>> +    # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
>> +    # are zero.
>> +    set p_byte $byte
>> +    if {$state == "fpsimd" || $state == "za"} {
>> +	set p_byte 0
>> +    }
>> +    set p_pattern [string_to_regexp [1d_array_value_pattern $p_byte $p_size]]
>> +
>> +    for {set number 0} {$number < 32} {incr number} {
>> +	set register_name "\$z${number}\.b\.u"
>> +	gdb_test "print sizeof $register_name" " = $z_size"
>> +	gdb_test "print $register_name" $z_pattern
>> +    }
>> +
>> +    for {set number 0} {$number < 16} {incr number} {
>> +	set register_name "\$p${number}"
>> +	gdb_test "print sizeof $register_name" " = $p_size"
>> +	gdb_test "print $register_name" $p_pattern
>> +    }
>> +
>> +    gdb_test "print \$ffr" $p_pattern
>> +}
> 
> Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
> 


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2023-08-30 12:57 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-22 11:21 [PATCH v2 0/6] SME2 support for AArch64 gdb/gdbserver on Linux Luis Machado
2023-08-22 11:21 ` [PATCH v2 1/6] [gdb/aarch64] sme2: Enable SME2 for AArch64 gdb " Luis Machado
2023-08-27  1:16   ` Thiago Jung Bauermann
2023-08-30 12:53     ` Luis Machado
2023-08-22 11:21 ` [PATCH v2 2/6] [gdbserver/aarch64] sme2: Enable SME2 support in gdbserver Luis Machado
2023-08-27  1:18   ` Thiago Jung Bauermann
2023-08-30 12:54     ` Luis Machado
2023-08-22 11:21 ` [PATCH v2 3/6] [gdb/aarch64] sme2: signal frame support Luis Machado
2023-08-27  1:19   ` Thiago Jung Bauermann
2023-08-22 11:21 ` [PATCH v2 4/6] [gdb/aarch64] sme2: Core file support for ZT register set Luis Machado
2023-08-27  1:21   ` Thiago Jung Bauermann
2023-08-30 12:56     ` Luis Machado
2023-08-22 11:21 ` [PATCH v2 5/6] [gdb/testsuite] sme2: Extend SME tests to include SME2 Luis Machado
2023-08-27  1:23   ` Thiago Jung Bauermann
2023-08-30 12:56     ` Luis Machado
2023-08-22 11:21 ` [PATCH v2 6/6] [gdb/docs] sme2: Document SME2 registers and features Luis Machado
2023-08-22 11:34   ` Eli Zaretskii
2023-08-22 11:45     ` Luis Machado
2023-08-27  1:27   ` Thiago Jung Bauermann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).