diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 9d1351946e..0e85e71089 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -42,7 +42,6 @@
 #include "trad-frame.h"
 #include "xml-syscall.h"
 
-#include "features/s390-linux32.c"
 #include "features/s390-linux32v1.c"
 #include "features/s390-linux32v2.c"
 #include "features/s390-linux64.c"
@@ -52,7 +51,6 @@
 #include "features/s390-vx-linux64.c"
 #include "features/s390-tevx-linux64.c"
 #include "features/s390-gs-linux64.c"
-#include "features/s390x-linux64.c"
 #include "features/s390x-linux64v1.c"
 #include "features/s390x-linux64v2.c"
 #include "features/s390x-te-linux64.c"
@@ -1158,9 +1156,6 @@ s390_linux_init_abi_31 (struct gdbarch_info info, struct gdbarch *gdbarch)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   tdep->abi = ABI_LINUX_S390;
-  if (!tdesc_has_registers (tdesc))
-    tdesc = tdesc_s390_linux32;
-  tdep->tdesc = tdesc;
 
   s390_linux_init_abi_any (info, gdbarch);
 
@@ -1178,9 +1173,6 @@ s390_linux_init_abi_64 (struct gdbarch_info info, struct gdbarch *gdbarch)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   tdep->abi = ABI_LINUX_ZSERIES;
-  if (!tdesc_has_registers (tdesc))
-    tdesc = tdesc_s390x_linux64;
-  tdep->tdesc = tdesc;
 
   s390_linux_init_abi_any (info, gdbarch);
 
@@ -1199,7 +1191,6 @@ _initialize_s390_linux_tdep (void)
 			  s390_linux_init_abi_64);
 
   /* Initialize the GNU/Linux target descriptions.  */
-  initialize_tdesc_s390_linux32 ();
   initialize_tdesc_s390_linux32v1 ();
   initialize_tdesc_s390_linux32v2 ();
   initialize_tdesc_s390_linux64 ();
@@ -1209,7 +1200,6 @@ _initialize_s390_linux_tdep (void)
   initialize_tdesc_s390_vx_linux64 ();
   initialize_tdesc_s390_tevx_linux64 ();
   initialize_tdesc_s390_gs_linux64 ();
-  initialize_tdesc_s390x_linux64 ();
   initialize_tdesc_s390x_linux64v1 ();
   initialize_tdesc_s390x_linux64v2 ();
   initialize_tdesc_s390x_te_linux64 ();
diff --git a/gdb/s390-linux-tdep.h b/gdb/s390-linux-tdep.h
index 6542464951..a3288e3bb1 100644
--- a/gdb/s390-linux-tdep.h
+++ b/gdb/s390-linux-tdep.h
@@ -48,7 +48,6 @@ extern const struct regset s390_gs_regset;
 extern const struct regset s390_gsbc_regset;
 
 /* GNU/Linux target descriptions.  */
-extern struct target_desc *tdesc_s390_linux32;
 extern struct target_desc *tdesc_s390_linux32v1;
 extern struct target_desc *tdesc_s390_linux32v2;
 extern struct target_desc *tdesc_s390_linux64;
@@ -58,7 +57,6 @@ extern struct target_desc *tdesc_s390_te_linux64;
 extern struct target_desc *tdesc_s390_vx_linux64;
 extern struct target_desc *tdesc_s390_tevx_linux64;
 extern struct target_desc *tdesc_s390_gs_linux64;
-extern struct target_desc *tdesc_s390x_linux64;
 extern struct target_desc *tdesc_s390x_linux64v1;
 extern struct target_desc *tdesc_s390x_linux64v2;
 extern struct target_desc *tdesc_s390x_te_linux64;
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index 1f2a536cd1..b60f4e2a04 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -40,6 +40,9 @@
 #include "trad-frame.h"
 #include "value.h"
 
+#include "features/s390-linux32.c"
+#include "features/s390x-linux64.c"
+
 /* Holds the current set of options to be passed to the disassembler.  */
 static char *s390_disassembler_options;
 
@@ -6789,6 +6792,9 @@ s390_tdesc_valid (struct gdbarch_tdep *tdep,
   const struct target_desc *tdesc = tdep->tdesc;
   const struct tdesc_feature *feature;
 
+  if (!tdesc_has_registers (tdesc))
+    return false;
+
   /* Core registers, i.e. general purpose and PSW.  */
   feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.core");
   if (feature == NULL)
@@ -6929,7 +6935,6 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   static const char *const stap_register_indirection_suffixes[] = { ")",
 								    NULL };
 
-  /* Otherwise create a new gdbarch for the specified machine type.  */
   struct gdbarch_tdep *tdep = s390_gdbarch_tdep_alloc ();
   struct gdbarch *gdbarch = gdbarch_alloc (&info, tdep);
   struct tdesc_arch_data *tdesc_data = tdesc_data_alloc ();
@@ -7044,8 +7049,19 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Initialize the OSABI.  */
   gdbarch_init_osabi (info, gdbarch);
 
+  /* Always create a default tdesc.  Otherwise commands like 'set osabi'
+     causes GDB to crash with an internal error when the user tries to set
+     a non supported osabi.  */
+  if (!tdesc_has_registers (tdesc))
+  {
+    if (info.bfd_arch_info->mach == bfd_mach_s390_31)
+      tdesc = tdesc_s390_linux32;
+    else
+      tdesc = tdesc_s390x_linux64;
+  }
+  tdep->tdesc = tdesc;
+
   /* Check any target description for validity.  */
-  gdb_assert (tdesc_has_registers (tdep->tdesc));
   if (!s390_tdesc_valid (tdep, tdesc_data))
     {
       tdesc_data_cleanup (tdesc_data);
@@ -7120,4 +7136,7 @@ _initialize_s390_tdep (void)
 {
   /* Hook us into the gdbarch mechanism.  */
   register_gdbarch_init (bfd_arch_s390, s390_gdbarch_init);
+
+  initialize_tdesc_s390_linux32 ();
+  initialize_tdesc_s390x_linux64 ();
 }
diff --git a/gdb/s390-tdep.h b/gdb/s390-tdep.h
index 4a44da0190..14530cef31 100644
--- a/gdb/s390-tdep.h
+++ b/gdb/s390-tdep.h
@@ -315,4 +315,7 @@ extern struct value *s390_trad_frame_prev_register
     (struct frame_info *this_frame, struct trad_frame_saved_reg saved_regs[],
      int regnum);
 
+extern struct target_desc *tdesc_s390_linux32;
+extern struct target_desc *tdesc_s390x_linux64;
+
 #endif /* S390_TDEP_H */
