[PATCH v3 09/24] AArch64: Add target description/feature for MTE registers

Luis Machado via Gdb-patches
2020-11-09T17:05:10Z

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

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 0fd806a5aa..5f6fb42792 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 2c1d888904..846b0ba0f3 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
@@ -3266,21 +3266,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;
@@ -3380,7 +3382,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 81ce4d84b4..6f3299f2cb 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 f89d5e014d..6c90bb36e4 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_up 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.get (), regnum);

+ /* Memory tagging extension registers. */
+ if (mte_p)
+ regnum = create_feature_aarch64_mte (tdesc.get (), regnum);
+
return tdesc.release ();
}
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 689603847a..bdc6c60c78 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/v1-core.xml \
arc/v1-aux.xml \
arc/v2-core.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. -->
+
+
+<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 */
--
2.17.1