S390: Fix TDB regset recognition
authorAndreas Arnez <arnez at linux dot vnet dot ibm dot com>
Tue, 5 Nov 2013 17:43:50 +0000 (18:43 +0100)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Wed, 6 Nov 2013 20:44:31 +0000 (21:44 +0100)
When checking for the presence of the TDB regset, the current code
interprets ENODATA from PTRACE_GETREGSET as an indication that the TDB
regset *could* occur on this system, but the inferior stopped outside
a transaction.  However, the Linux kernel actually reports ENODATA
even on systems without the transactional execution facility.  Thus
the logic is now changed to check the TE field in the HWCAP as well.

This version also checks the existence of the TDB regset -- just to be
on the safe side when running on TE-enabled hardware with a kernel
that does not offer the TDB regset for some reason.

gdb/
* s390-linux-nat.c (s390_read_description): Consider the TE field
in the HWCAP for determining 'have_regset_tdb'.

gdbserver/
* linux-s390-low.c (HWCAP_S390_TE): New define.
(s390_arch_setup): Consider the TE field in the HWCAP for
determining 'have_regset_tdb'.

gdb/ChangeLog
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-s390-low.c
gdb/s390-linux-nat.c

index 45f92e8210e8f4aaeb49b511a438f529613c40aa..a282b82bb217a9bbba31a6e76dd2cb20a53d7bba 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-06  Andreas Arnez  <arnez@linux.vnet.ibm.com>
+
+       * s390-linux-nat.c (s390_read_description): Consider the TE field
+       in the HWCAP for determining 'have_regset_tdb'.
+
 2013-11-06  Will Newton  <will.newton@linaro.org>
 
        PR gdb/12866
index 4f15cfb2cf64e59bf9154fc8f88665dc853701e2..9d514e5e6aa7cfdfebededc8de545ee0b20ec9bc 100644 (file)
@@ -1,3 +1,9 @@
+2013-11-06  Andreas Arnez  <arnez@linux.vnet.ibm.com>
+
+       * linux-s390-low.c (HWCAP_S390_TE): New define.
+       (s390_arch_setup): Consider the TE field in the HWCAP for
+       determining 'have_regset_tdb'.
+
 2013-10-16  Sergio Durigan Junior  <sergiodj@redhat.com>
 
        PR gdb/16014
index a2df03736cf2b2408746e2fc3a944fea7dc8f5dc..ae8204bd61ea461c1c786f73ddb67bbbc809191f 100644 (file)
 #define HWCAP_S390_HIGH_GPRS 512
 #endif
 
+#ifndef HWCAP_S390_TE
+#define HWCAP_S390_TE 1024
+#endif
+
 #ifndef PTRACE_GETREGSET
 #define PTRACE_GETREGSET 0x4204
 #endif
@@ -425,23 +429,6 @@ s390_arch_setup (void)
     = s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
   int have_regset_tdb = s390_check_regset (pid, NT_S390_TDB, 256);
 
-  /* Update target_regsets according to available register sets.  */
-  for (regset = s390_regsets; regset->fill_function != NULL; regset++)
-    if (regset->get_request == PTRACE_GETREGSET)
-      switch (regset->nt_type)
-       {
-       case NT_S390_LAST_BREAK:
-         regset->size = have_regset_last_break? 8 : 0;
-         break;
-       case NT_S390_SYSTEM_CALL:
-         regset->size = have_regset_system_call? 4 : 0;
-         break;
-       case NT_S390_TDB:
-         regset->size = have_regset_tdb ? 256 : 0;
-       default:
-         break;
-       }
-
   /* Assume 31-bit inferior process.  */
   if (have_regset_system_call)
     tdesc = tdesc_s390_linux32v2;
@@ -456,15 +443,20 @@ s390_arch_setup (void)
   {
     unsigned int pswm;
     struct regcache *regcache = new_register_cache (tdesc);
+
     fetch_inferior_registers (regcache, find_regno (tdesc, "pswm"));
     collect_register_by_name (regcache, "pswm", &pswm);
     free_register_cache (regcache);
 
     if (pswm & 1)
       {
+       if (have_regset_tdb)
+         have_regset_tdb =
+           (s390_get_hwcap (tdesc_s390x_linux64v2) & HWCAP_S390_TE) != 0;
+
        if (have_regset_tdb)
          tdesc = tdesc_s390x_te_linux64;
-       if (have_regset_system_call)
+       else if (have_regset_system_call)
          tdesc = tdesc_s390x_linux64v2;
        else if (have_regset_last_break)
          tdesc = tdesc_s390x_linux64v1;
@@ -477,6 +469,8 @@ s390_arch_setup (void)
     else if (s390_get_hwcap (tdesc) & HWCAP_S390_HIGH_GPRS)
       {
        have_hwcap_s390_high_gprs = 1;
+       if (have_regset_tdb)
+         have_regset_tdb = (s390_get_hwcap (tdesc) & HWCAP_S390_TE) != 0;
 
        if (have_regset_tdb)
          tdesc = tdesc_s390_te_linux64;
@@ -489,6 +483,24 @@ s390_arch_setup (void)
       }
   }
 #endif
+
+  /* Update target_regsets according to available register sets.  */
+  for (regset = s390_regsets; regset->fill_function != NULL; regset++)
+    if (regset->get_request == PTRACE_GETREGSET)
+      switch (regset->nt_type)
+       {
+       case NT_S390_LAST_BREAK:
+         regset->size = have_regset_last_break? 8 : 0;
+         break;
+       case NT_S390_SYSTEM_CALL:
+         regset->size = have_regset_system_call? 4 : 0;
+         break;
+       case NT_S390_TDB:
+         regset->size = have_regset_tdb ? 256 : 0;
+       default:
+         break;
+       }
+
   current_process ()->tdesc = tdesc;
 }
 
index 67f97f9a05b42630f6a0a77ea50f8d93d97f02c0..cf3f7d7c8288d795ec9e666857f8f79bf4a94513 100644 (file)
@@ -632,8 +632,6 @@ s390_read_description (struct target_ops *ops)
     = check_regset (tid, NT_S390_LAST_BREAK, 8);
   have_regset_system_call
     = check_regset (tid, NT_S390_SYSTEM_CALL, 4);
-  have_regset_tdb
-    = check_regset (tid, NT_S390_TDB, s390_sizeof_tdbregset);
 
 #ifdef __s390x__
   /* If GDB itself is compiled as 64-bit, we are running on a machine in
@@ -642,6 +640,9 @@ s390_read_description (struct target_ops *ops)
      addressing mode, but the kernel supports using 64-bit registers in
      that mode, report s390 architecture with 64-bit GPRs.  */
 
+  have_regset_tdb = (s390_get_hwcap () & HWCAP_S390_TE) ?
+    check_regset (tid, NT_S390_TDB, s390_sizeof_tdbregset) : 0;
+
   if (s390_target_wordsize () == 8)
     return (have_regset_tdb ? tdesc_s390x_te_linux64 :
            have_regset_system_call? tdesc_s390x_linux64v2 :