[v6,12/17,gdb/aarch64] sme: Support TPIDR2 signal frame context

Message ID 20230913101815.178154-13-luis.machado@arm.com
State New
Headers
Series SME support for AArch64 gdb/gdbserver on Linux |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Luis Machado Sept. 13, 2023, 10:18 a.m. UTC
  The Linux Kernel defines a separate context for the TPIDR2 register in a
signal frame.  Handle this additional context in gdb so this register
gets restored properly when unwinding through signal frames.

The TPIDR2 register is closely related to SME, and is available when SME
support is reported.

This is tested by testcases that are available in a later patch in the series.

Regressions-tested on aarch64-linux Ubuntu 22.04/20.04.
---
 gdb/aarch64-linux-tdep.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
  

Patch

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 39855844ad0..47e5e1db641 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -154,6 +154,7 @@ 
 #define AARCH64_FPSIMD_MAGIC			0x46508001
 #define AARCH64_SVE_MAGIC			0x53564501
 #define AARCH64_ZA_MAGIC			0x54366345
+#define AARCH64_TPIDR2_MAGIC			0x54504902
 
 /* Defines for the extra_context that follows an AARCH64_EXTRA_MAGIC.  */
 #define AARCH64_EXTRA_DATAP_OFFSET		8
@@ -184,6 +185,9 @@ 
 #define AARCH64_SME_CONTEXT_SIZE(svq) \
   (AARCH64_SME_CONTEXT_REGS_OFFSET + AARCH64_SME_CONTEXT_ZA_SIZE (svq))
 
+/* TPIDR2 register value offset in the TPIDR2 signal frame context.  */
+#define AARCH64_TPIDR2_CONTEXT_TPIDR2_OFFSET	8
+
 /* Holds information about the signal frame.  */
 struct aarch64_linux_sigframe
 {
@@ -204,6 +208,8 @@  struct aarch64_linux_sigframe
   CORE_ADDR sve_section = 0;
   /* Starting address of the section containing the ZA register.  */
   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 extra information.  */
   CORE_ADDR extra_section = 0;
 
@@ -464,6 +470,13 @@  aarch64_linux_read_signal_frame_info (frame_info_ptr this_frame,
 	    break;
 	  }
 
+	case AARCH64_TPIDR2_MAGIC:
+	  {
+	    /* This is context containing the tpidr2 register.  */
+	    signal_frame.tpidr2_section = section;
+	    section += size;
+	    break;
+	  }
 	case AARCH64_EXTRA_MAGIC:
 	  {
 	    /* Extra is always the last valid section in reserved and points to
@@ -605,6 +618,17 @@  aarch64_linux_sigframe_init (const struct tramp_frame *self,
 				sve_vg_from_vl (signal_frame.svl));
     }
 
+  /* Restore the tpidr2 register, if the target supports it and if there is
+     an entry for it.  */
+  if (signal_frame.tpidr2_section != 0 && tdep->has_tls ()
+      && tdep->tls_register_count >= 2)
+    {
+      /* Restore tpidr2.  */
+      trad_frame_set_reg_addr (this_cache, tdep->tls_regnum_base + 1,
+			       signal_frame.tpidr2_section
+			       + AARCH64_TPIDR2_CONTEXT_TPIDR2_OFFSET);
+    }
+
   trad_frame_set_id (this_cache, frame_id_build (signal_frame.sp, func));
 }