[v2,09/10] Ptrace support for AArch64 SVE gdbsever

Message ID 20180606151629.36602-10-alan.hayward@arm.com
State New, archived
Headers

Commit Message

Alan Hayward June 6, 2018, 3:16 p.m. UTC
  Add checks to detect SVE tdesc. Easiest way to do this is by checking the
size of the vector registers.

Use the common aarch64 ptrace copy functions for reading/writing registers.
A wrapper is required due to the common functions using reg_buffer_common.

2018-06-06  Alan Hayward  <alan.hayward@arm.com>

gdbserver/
	* linux-aarch64-low.c (is_sve_tdesc): New function.
	(aarch64_sve_regs_copy_to_regcache): Likewise.
	(aarch64_sve_regs_copy_from_regcache):  Likewise.
	(aarch64_regs_info): Add SVE checks.
	(initialize_low_arch): Initialize SVE.
---
 gdb/gdbserver/linux-aarch64-low.c | 62 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 3 deletions(-)
  

Comments

Simon Marchi June 11, 2018, 2:43 a.m. UTC | #1
On 2018-06-06 11:16 AM, Alan Hayward wrote:
> Add checks to detect SVE tdesc. Easiest way to do this is by checking the
> size of the vector registers.
> 
> Use the common aarch64 ptrace copy functions for reading/writing registers.
> A wrapper is required due to the common functions using reg_buffer_common.

Hi Alan,

There are macros not defined in the headers adde in patch 2/10, so I get this since
I build against the headers of an older kernel:

  CXX    linux-aarch64-low.o
/home/simark/src/binutils-gdb/gdb/gdbserver/linux-aarch64-low.c:559:38: error: 'SVE_PT_REGS_SVE' was not declared in this scope
     SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE), EXTENDED_REGS,
                                      ^~~~~~~~~~~~~~~
/home/simark/src/binutils-gdb/gdb/gdbserver/linux-aarch64-low.c:559:53: error: 'SVE_PT_SIZE' was not declared in this scope
     SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE), EXTENDED_REGS,

If we decide not to include the Linux kernel header replacements in the GDB tree,
it's not an issue.

Simon
  
Simon Marchi June 11, 2018, 2:44 a.m. UTC | #2
On 2018-06-06 11:16 AM, Alan Hayward wrote:
> diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
> index 9db9a7c1c3..e7fec25a64 100644
> --- a/gdb/gdbserver/linux-aarch64-low.c
> +++ b/gdb/gdbserver/linux-aarch64-low.c
> @@ -73,6 +73,16 @@ is_64bit_tdesc (void)
>    return register_size (regcache->tdesc, 0) == 8;
>  }
>  
> +static bool
> +is_sve_tdesc (void)
> +{
> +  struct regcache *regcache = get_thread_regcache (current_thread, 0);
> +
> +  /* Mimimum size of Z0 on SVE is 256bit.  If not SVE, then Z0 will be the
> +     128bit V0 register.  */
> +  return register_size (regcache->tdesc, AARCH64_SVE_Z0_REGNUM) >= 32;

Hmm maybe I read wrong, but can't the SVE registers be 128 bits long?  Maybe this
is not up to date, but here it says

   "enabling implementation choices for vector lengths that scale from 128 to 2048 bits."

https://community.arm.com/processors/b/blog/posts/technology-update-the-scalable-vector-extension-sve-for-the-armv8-a-architecture

Simon
  

Patch

diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 9db9a7c1c3..e7fec25a64 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -73,6 +73,16 @@  is_64bit_tdesc (void)
   return register_size (regcache->tdesc, 0) == 8;
 }
 
+static bool
+is_sve_tdesc (void)
+{
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+
+  /* Mimimum size of Z0 on SVE is 256bit.  If not SVE, then Z0 will be the
+     128bit V0 register.  */
+  return register_size (regcache->tdesc, AARCH64_SVE_Z0_REGNUM) >= 32;
+}
+
 /* Implementation of linux_target_ops method "cannot_store_register".  */
 
 static int
@@ -514,6 +524,22 @@  aarch64_arch_setup (void)
   aarch64_linux_get_debug_reg_capacity (lwpid_of (current_thread));
 }
 
+/* Wrapper for aarch64_sve_regs_copy_to_reg_buf.  */
+
+static void
+aarch64_sve_regs_copy_to_regcache (struct regcache *regcache, const void *buf)
+{
+  return aarch64_sve_regs_copy_to_reg_buf (regcache, buf);
+}
+
+/* Wrapper for aarch64_sve_regs_copy_from_reg_buf.  */
+
+static void
+aarch64_sve_regs_copy_from_regcache (struct regcache *regcache, void *buf)
+{
+  return aarch64_sve_regs_copy_from_reg_buf (regcache, buf);
+}
+
 static struct regset_info aarch64_regsets[] =
 {
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
@@ -540,15 +566,44 @@  static struct regs_info regs_info_aarch64 =
     &aarch64_regsets_info,
   };
 
+static struct regset_info aarch64_sve_regsets[] =
+{
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
+    sizeof (struct user_pt_regs), GENERAL_REGS,
+    aarch64_fill_gregset, aarch64_store_gregset },
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_SVE,
+    SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE), EXTENDED_REGS,
+    aarch64_sve_regs_copy_from_regcache, aarch64_sve_regs_copy_to_regcache
+  },
+  NULL_REGSET
+};
+
+static struct regsets_info aarch64_sve_regsets_info =
+  {
+    aarch64_sve_regsets, /* regsets.  */
+    0, /* num_regsets.  */
+    NULL, /* disabled_regsets.  */
+  };
+
+static struct regs_info regs_info_aarch64_sve =
+  {
+    NULL, /* regset_bitmap.  */
+    NULL, /* usrregs.  */
+    &aarch64_sve_regsets_info,
+  };
+
 /* Implementation of linux_target_ops method "regs_info".  */
 
 static const struct regs_info *
 aarch64_regs_info (void)
 {
-  if (is_64bit_tdesc ())
-    return &regs_info_aarch64;
-  else
+  if (!is_64bit_tdesc ())
     return &regs_info_aarch32;
+
+  if (is_sve_tdesc ())
+    return &regs_info_aarch64_sve;
+
+  return &regs_info_aarch64;
 }
 
 /* Implementation of linux_target_ops method "supports_tracepoints".  */
@@ -3027,6 +3082,7 @@  initialize_low_arch (void)
   initialize_low_arch_aarch32 ();
 
   initialize_regsets_info (&aarch64_regsets_info);
+  initialize_regsets_info (&aarch64_sve_regsets_info);
 
 #if GDB_SELF_TEST
   initialize_low_tdesc ();