diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 1a8361a..0b18d1d 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -49,11 +49,15 @@ srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-wa
 case "${target}" in
   aarch64*-*-linux*)
 			srv_regobj="aarch64.o"
+			srv_regobj="${srv_regobj} arm-with-neon.o"
 			srv_tgtobj="linux-aarch64-low.o aarch64-linux-hw-point.o"
+			srv_tgtobj="$srv_tgtobj linux-aarch32-low.o"
 			srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
 			srv_xmlfiles="aarch64.xml"
 			srv_xmlfiles="${srv_xmlfiles} aarch64-core.xml"
 			srv_xmlfiles="${srv_xmlfiles} aarch64-fpu.xml"
+			srv_xmlfiles="${srv_xmlfiles} arm-core.xml arm-vfpv3.xml"
+			srv_xmlfiles="${srv_xmlfiles} arm-with-neon.xml"
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
 			;;
diff --git a/gdb/gdbserver/linux-aarch32-low.c b/gdb/gdbserver/linux-aarch32-low.c
index 0ca40c3..d39dfac 100644
--- a/gdb/gdbserver/linux-aarch32-low.c
+++ b/gdb/gdbserver/linux-aarch32-low.c
@@ -67,6 +67,10 @@ arm_fill_vfpregset (struct regcache *regcache, void *buf)
 {
   int i, num, base;
 
+#ifdef __aarch64__
+  gdb_assert (regcache->tdesc == tdesc_arm_with_neon);
+  num = 32;
+#else
   if (regcache->tdesc == tdesc_arm_with_neon
       || regcache->tdesc == tdesc_arm_with_vfpv3)
     num = 32;
@@ -74,6 +78,7 @@ arm_fill_vfpregset (struct regcache *regcache, void *buf)
     num = 16;
   else
     return;
+#endif
 
   base = find_regno (regcache->tdesc, "d0");
   for (i = 0; i < num; i++)
@@ -88,7 +93,10 @@ void
 arm_store_vfpregset (struct regcache *regcache, const void *buf)
 {
   int i, num, base;
-
+#ifdef __aarch64__
+  gdb_assert (regcache->tdesc == tdesc_arm_with_neon);
+  num = 32;
+#else
   if (regcache->tdesc == tdesc_arm_with_neon
       || regcache->tdesc == tdesc_arm_with_vfpv3)
     num = 32;
@@ -96,6 +104,7 @@ arm_store_vfpregset (struct regcache *regcache, const void *buf)
     num = 16;
   else
     return;
+#endif
 
   base = find_regno (regcache->tdesc, "d0");
   for (i = 0; i < num; i++)
@@ -133,8 +142,10 @@ struct regs_info regs_info_aarch32 =
 void
 initialize_low_arch_aarch32 (void)
 {
+#ifndef __aarch64__
   init_registers_arm_with_vfpv2 ();
   init_registers_arm_with_vfpv3 ();
+#endif
   init_registers_arm_with_neon ();
 
   initialize_regsets_info (&aarch32_regsets_info);
diff --git a/gdb/gdbserver/linux-aarch32-low.h b/gdb/gdbserver/linux-aarch32-low.h
index 49bd5c3..72e5d37 100644
--- a/gdb/gdbserver/linux-aarch32-low.h
+++ b/gdb/gdbserver/linux-aarch32-low.h
@@ -24,9 +24,13 @@ void arm_store_vfpregset (struct regcache *regcache, const void *buf);
 
 void initialize_low_arch_aarch32 (void);
 
+#ifndef __aarch64__
 void init_registers_arm_with_vfpv2 (void);
 extern const struct target_desc *tdesc_arm_with_vfpv2;
+
 void init_registers_arm_with_vfpv3 (void);
 extern const struct target_desc *tdesc_arm_with_vfpv3;
+#endif
+
 void init_registers_arm_with_neon (void);
 extern const struct target_desc *tdesc_arm_with_neon;
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 3a47521..e4a41ce 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -22,6 +22,7 @@
 #include "server.h"
 #include "linux-low.h"
 #include "nat/aarch64-linux-hw-point.h"
+#include "linux-aarch32-low.h"
 #include "elf/common.h"
 
 #include <signal.h>
@@ -69,6 +70,16 @@ struct arch_process_info
   struct aarch64_debug_reg_state debug_reg_state;
 };
 
+/* Return true if the size of register 0 is 8 byte.  */
+
+static int
+is_64bit_tdesc (void)
+{
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+
+  return register_size (regcache->tdesc, 0) == 8;
+}
+
 /* Implementation of linux_target_ops method "cannot_store_register".  */
 
 static int
@@ -582,12 +593,32 @@ aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
     }
 }
 
+/* Return the right target description according to the ELF file of
+   current thread.  */
+
+static const struct target_desc *
+aarch64_linux_read_description (void)
+{
+  unsigned int machine;
+  int is_elf64;
+  int tid;
+
+  tid = lwpid_of (current_thread);
+
+  is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
+
+  if (is_elf64)
+    return tdesc_aarch64;
+  else
+    return tdesc_arm_with_neon;
+}
+
 /* Implementation of linux_target_ops method "arch_setup".  */
 
 static void
 aarch64_arch_setup (void)
 {
-  current_process ()->tdesc = tdesc_aarch64;
+  current_process ()->tdesc = aarch64_linux_read_description ();
 
   aarch64_linux_get_debug_reg_capacity (lwpid_of (current_thread));
 }
@@ -611,7 +642,7 @@ static struct regsets_info aarch64_regsets_info =
     NULL, /* disabled_regsets */
   };
 
-static struct regs_info regs_info =
+static struct regs_info regs_info_aarch64 =
   {
     NULL, /* regset_bitmap */
     NULL, /* usrregs */
@@ -623,7 +654,10 @@ static struct regs_info regs_info =
 static const struct regs_info *
 aarch64_regs_info (void)
 {
-  return &regs_info;
+  if (is_64bit_tdesc ())
+    return &regs_info_aarch64;
+  else
+    return &regs_info_aarch32;
 }
 
 /* Implementation of linux_target_ops method "supports_tracepoints".  */
@@ -682,5 +716,7 @@ initialize_low_arch (void)
 {
   init_registers_aarch64 ();
 
+  initialize_low_arch_aarch32 ();
+
   initialize_regsets_info (&aarch64_regsets_info);
 }
