[09/23] AArch64: Add target description/feature for MTE registers

Message ID 20200715194513.16641-10-luis.machado@linaro.org
State New
Headers show
Series
  • Memory Tagging Support + AArch64 Linux implementation
Related show

Commit Message

H.J. Lu via Gdb-patches July 15, 2020, 7:44 p.m.
This patch adds a target description and feature "mte" for aarch64.

It includes one new register, tag_ctl, that can be used to configure the
tag generation rules and sync/async modes.  It is 64-bit in size.

The patch also adjusts the code that creates the target descriptions at
runtime based on CPU feature checks.

gdb/ChangeLog:

YYYY-MM-DD  Luis Machado  <luis.machado@linaro.org>

	* aarch64-linux-nat.c
	(aarch64_linux_nat_target::read_description): Take MTE flag into
	account.
	Slight refactor to hwcap flag checking.
	* aarch64-linux-tdep.c
	(aarch64_linux_core_read_description): Likewise.
	* aarch64-tdep.c (tdesc_aarch64_list): Add one more dimension for
	MTE.
	(aarch64_read_description): Add mte_p parameter and update to use it.
	Update the documentation.
	(aarch64_gdbarch_init): Update call to aarch64_read_description.
	* aarch64-tdep.h (aarch64_read_description): Add mte_p parameter.
	* arch/aarch64.c: Include ../features/aarch64-mte.c.
	(aarch64_create_target_description): Add mte_p parameter and update
	the code to use it.
	* arch/aarch64.h (aarch64_create_target_description): Add mte_p
	parameter.
	* features/Makefile (FEATURE_XMLFILES): Add aarch64-mte.xml.
	* features/aarch64-mte.c: New file, generated.
	* features/aarch64-mte.xml: New file.

gdbserver/ChangeLog:

YYYY-MM-DD  Luis Machado  <luis.machado@linaro.org>

	* linux-aarch64-ipa.cc (get_ipa_tdesc): Update call to
	aarch64_linux_read_description.
	(initialize_low_tracepoint): Likewise.
	* linux-aarch64-low.cc (aarch64_target::low_arch_setup): Take MTE flag
	into account.
	* linux-aarch64-tdesc.cc (tdesc_aarch64_list): Add one more dimension
	for MTE.
	(aarch64_linux_read_description): Add mte_p parameter and update to
	use it.
	* linux-aarch64-tdesc.h (aarch64_linux_read_description): Add mte_p
	parameter.
---
 gdb/aarch64-linux-nat.c          |  7 +++++--
 gdb/aarch64-linux-tdep.c         |  5 ++++-
 gdb/aarch64-tdep.c               | 16 +++++++++-------
 gdb/aarch64-tdep.h               |  3 ++-
 gdb/arch/aarch64.c               |  7 ++++++-
 gdb/arch/aarch64.h               |  7 +++++--
 gdb/features/Makefile            |  1 +
 gdb/features/aarch64-mte.c       | 14 ++++++++++++++
 gdb/features/aarch64-mte.xml     | 11 +++++++++++
 gdbserver/linux-aarch64-ipa.cc   |  8 ++++----
 gdbserver/linux-aarch64-low.cc   |  6 +++++-
 gdbserver/linux-aarch64-tdesc.cc | 10 +++++-----
 gdbserver/linux-aarch64-tdesc.h  |  3 ++-
 13 files changed, 73 insertions(+), 25 deletions(-)
 create mode 100644 gdb/features/aarch64-mte.c
 create mode 100644 gdb/features/aarch64-mte.xml

-- 
2.17.1

Patch

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 260f47558b..1392ec440c 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -653,9 +653,12 @@  aarch64_linux_nat_target::read_description ()
     return aarch32_read_description ();
 
   CORE_ADDR hwcap = linux_get_hwcap (this);
+  CORE_ADDR hwcap2 = linux_get_hwcap2 (this);
 
-  return aarch64_read_description (aarch64_sve_get_vq (tid),
-				   hwcap & AARCH64_HWCAP_PACA);
+  bool pauth_p = hwcap & AARCH64_HWCAP_PACA;
+  bool mte_p = hwcap2 & HWCAP2_MTE;
+
+  return aarch64_read_description (aarch64_sve_get_vq (tid), pauth_p, mte_p);
 }
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index bfb4fc51e1..53f9d9f6d2 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -654,9 +654,12 @@  aarch64_linux_core_read_description (struct gdbarch *gdbarch,
 				     struct target_ops *target, bfd *abfd)
 {
   CORE_ADDR hwcap = linux_get_hwcap (target);
+  CORE_ADDR hwcap2 = linux_get_hwcap2 (target);
 
+  bool pauth_p = hwcap & AARCH64_HWCAP_PACA;
+  bool mte_p = hwcap2 & HWCAP2_MTE;
   return aarch64_read_description (aarch64_linux_core_read_vq (gdbarch, abfd),
-				   hwcap & AARCH64_HWCAP_PACA);
+				   pauth_p, mte_p);
 }
 
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 5e7d0d0b86..536f6f3dc9 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -62,7 +62,7 @@ 
 #define HA_MAX_NUM_FLDS		4
 
 /* All possible aarch64 target descriptors.  */
-struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/];
+struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/][2 /* mte */];
 
 /* The standard register names, and all the valid aliases for them.  */
 static const struct
@@ -3139,21 +3139,23 @@  aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
 
 /* Get the correct target description for the given VQ value.
    If VQ is zero then it is assumed SVE is not supported.
-   (It is not possible to set VQ to zero on an SVE system).  */
+   (It is not possible to set VQ to zero on an SVE system).
+
+   MTE_P indicates the presence of the Memory Tagging Extension feature. */
 
 const target_desc *
-aarch64_read_description (uint64_t vq, bool pauth_p)
+aarch64_read_description (uint64_t vq, bool pauth_p, bool mte_p)
 {
   if (vq > AARCH64_MAX_SVE_VQ)
     error (_("VQ is %" PRIu64 ", maximum supported value is %d"), vq,
 	   AARCH64_MAX_SVE_VQ);
 
-  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p];
+  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p][mte_p];
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq, pauth_p);
-      tdesc_aarch64_list[vq][pauth_p] = tdesc;
+      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p);
+      tdesc_aarch64_list[vq][pauth_p][mte_p] = tdesc;
     }
 
   return tdesc;
@@ -3253,7 +3255,7 @@  aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      value.  */
   const struct target_desc *tdesc = info.target_desc;
   if (!tdesc_has_registers (tdesc) || vq != aarch64_get_tdesc_vq (tdesc))
-    tdesc = aarch64_read_description (vq, false);
+    tdesc = aarch64_read_description (vq, false, false);
   gdb_assert (tdesc);
 
   feature_core = tdesc_find_feature (tdesc,"org.gnu.gdb.aarch64.core");
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index f6ebabeaeb..4f8b19ad2f 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -102,7 +102,8 @@  struct gdbarch_tdep
   }
 };
 
-const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p);
+const target_desc *aarch64_read_description (uint64_t vq, bool pauth_p,
+					     bool mte_p);
 
 extern int aarch64_process_record (struct gdbarch *gdbarch,
                                struct regcache *regcache, CORE_ADDR addr);
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index f611543498..9104caf767 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -23,11 +23,12 @@ 
 #include "../features/aarch64-fpu.c"
 #include "../features/aarch64-sve.c"
 #include "../features/aarch64-pauth.c"
+#include "../features/aarch64-mte.c"
 
 /* See arch/aarch64.h.  */
 
 target_desc *
-aarch64_create_target_description (uint64_t vq, bool pauth_p)
+aarch64_create_target_description (uint64_t vq, bool pauth_p, bool mte_p)
 {
   target_desc *tdesc = allocate_target_description ();
 
@@ -47,5 +48,9 @@  aarch64_create_target_description (uint64_t vq, bool pauth_p)
   if (pauth_p)
     regnum = create_feature_aarch64_pauth (tdesc, regnum);
 
+  /* Memory tagging extension registers.  */
+  if (mte_p)
+    regnum = create_feature_aarch64_mte (tdesc, regnum);
+
   return tdesc;
 }
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index 857bb22b03..6b1882afcc 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -25,9 +25,12 @@ 
 /* Create the aarch64 target description.  A non zero VQ value indicates both
    the presence of SVE and the Vector Quotient - the number of 128bit chunks in
    an SVE Z register.  HAS_PAUTH_P indicates the presence of the PAUTH
-   feature.  */
+   feature.
 
-target_desc *aarch64_create_target_description (uint64_t vq, bool has_pauth_p);
+   MTE_P indicates the presence of the Memory Tagging Extension feature.  */
+
+target_desc *aarch64_create_target_description (uint64_t vq, bool has_pauth_p,
+						bool mte_p);
 
 /* Register numbers of various important registers.
    Note that on SVE, the Z registers reuse the V register numbers and the V
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index d0af9a47b4..a746cccca9 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -201,6 +201,7 @@  $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
 FEATURE_XMLFILES = aarch64-core.xml \
 	aarch64-fpu.xml \
 	aarch64-pauth.xml \
+	aarch64-mte.xml \
 	arc/core-v2.xml \
 	arc/aux-v2.xml \
 	arc/core-arcompact.xml \
diff --git a/gdb/features/aarch64-mte.c b/gdb/features/aarch64-mte.c
new file mode 100644
index 0000000000..883b19cd15
--- /dev/null
+++ b/gdb/features/aarch64-mte.c
@@ -0,0 +1,14 @@ 
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aarch64-mte.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_aarch64_mte (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.mte");
+  tdesc_create_reg (feature, "tag_ctl", regnum++, 0, "system", 64, "uint64");
+  return regnum;
+}
diff --git a/gdb/features/aarch64-mte.xml b/gdb/features/aarch64-mte.xml
new file mode 100644
index 0000000000..85455b13b2
--- /dev/null
+++ b/gdb/features/aarch64-mte.xml
@@ -0,0 +1,11 @@ 
+<?xml version="1.0"?>
+<!-- Copyright (C) 2020 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.mte">
+  <reg name="tag_ctl" bitsize="64" type="uint64" group="system" save-restore="no"/>
+</feature>
diff --git a/gdbserver/linux-aarch64-ipa.cc b/gdbserver/linux-aarch64-ipa.cc
index 694dfd77df..1a47bf95d7 100644
--- a/gdbserver/linux-aarch64-ipa.cc
+++ b/gdbserver/linux-aarch64-ipa.cc
@@ -147,12 +147,12 @@  get_raw_reg (const unsigned char *raw_regs, int regnum)
 
 /* Return target_desc to use for IPA, given the tdesc index passed by
    gdbserver.  Index is ignored, since we have only one tdesc
-   at the moment.  SVE and pauth not yet supported.  */
+   at the moment.  SVE, pauth and MTE not yet supported.  */
 
 const struct target_desc *
 get_ipa_tdesc (int idx)
 {
-  return aarch64_linux_read_description (0, false);
+  return aarch64_linux_read_description (0, false, false);
 }
 
 /* Allocate buffer for the jump pads.  The branch instruction has a reach
@@ -204,6 +204,6 @@  alloc_jump_pad_buffer (size_t size)
 void
 initialize_low_tracepoint (void)
 {
-  /* SVE and pauth not yet supported.  */
-  aarch64_linux_read_description (0, false);
+  /* SVE, pauth and MTE not yet supported.  */
+  aarch64_linux_read_description (0, false, false);
 }
diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
index 7512aac54b..60d60a4d5c 100644
--- a/gdbserver/linux-aarch64-low.cc
+++ b/gdbserver/linux-aarch64-low.cc
@@ -642,9 +642,13 @@  aarch64_target::low_arch_setup ()
     {
       uint64_t vq = aarch64_sve_get_vq (tid);
       unsigned long hwcap = linux_get_hwcap (8);
+      unsigned long hwcap2 = linux_get_hwcap2 (8);
       bool pauth_p = hwcap & AARCH64_HWCAP_PACA;
+      /* MTE is AArch64-only.  */
+      bool mte_p = hwcap2 & HWCAP2_MTE;
 
-      current_process ()->tdesc = aarch64_linux_read_description (vq, pauth_p);
+      current_process ()->tdesc
+	= aarch64_linux_read_description (vq, pauth_p, mte_p);
     }
   else
     current_process ()->tdesc = aarch32_linux_read_description ();
diff --git a/gdbserver/linux-aarch64-tdesc.cc b/gdbserver/linux-aarch64-tdesc.cc
index 897fbb43bd..3c5233d1fb 100644
--- a/gdbserver/linux-aarch64-tdesc.cc
+++ b/gdbserver/linux-aarch64-tdesc.cc
@@ -27,22 +27,22 @@ 
 #include <inttypes.h>
 
 /* All possible aarch64 target descriptors.  */
-struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/];
+struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1][2/*pauth*/][2 /* mte */];
 
 /* Create the aarch64 target description.  */
 
 const target_desc *
-aarch64_linux_read_description (uint64_t vq, bool pauth_p)
+aarch64_linux_read_description (uint64_t vq, bool pauth_p, bool mte_p)
 {
   if (vq > AARCH64_MAX_SVE_VQ)
     error (_("VQ is %" PRIu64 ", maximum supported value is %d"), vq,
 	   AARCH64_MAX_SVE_VQ);
 
-  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p];
+  struct target_desc *tdesc = tdesc_aarch64_list[vq][pauth_p][mte_p];
 
   if (tdesc == NULL)
     {
-      tdesc = aarch64_create_target_description (vq, pauth_p);
+      tdesc = aarch64_create_target_description (vq, pauth_p, mte_p);
 
       static const char *expedite_regs_aarch64[] = { "x29", "sp", "pc", NULL };
       static const char *expedite_regs_aarch64_sve[] = { "x29", "sp", "pc",
@@ -53,7 +53,7 @@  aarch64_linux_read_description (uint64_t vq, bool pauth_p)
       else
 	init_target_desc (tdesc, expedite_regs_aarch64_sve);
 
-      tdesc_aarch64_list[vq][pauth_p] = tdesc;
+      tdesc_aarch64_list[vq][pauth_p][mte_p] = tdesc;
     }
 
   return tdesc;
diff --git a/gdbserver/linux-aarch64-tdesc.h b/gdbserver/linux-aarch64-tdesc.h
index 0165e633d4..09d42970a9 100644
--- a/gdbserver/linux-aarch64-tdesc.h
+++ b/gdbserver/linux-aarch64-tdesc.h
@@ -20,6 +20,7 @@ 
 #ifndef GDBSERVER_LINUX_AARCH64_TDESC_H
 #define GDBSERVER_LINUX_AARCH64_TDESC_H
 
-const target_desc * aarch64_linux_read_description (uint64_t vq, bool pauth_p);
+const target_desc * aarch64_linux_read_description (uint64_t vq, bool pauth_p,
+						    bool mte_p);
 
 #endif /* GDBSERVER_LINUX_AARCH64_TDESC_H */