Update release making notes.
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-s390-low.c
index 231b61476c5e744a21c8b62d1bd7ebe4442028e5..f3d6f093099b12c6cc3687a5910e7c9bda8662b6 100644 (file)
@@ -1,6 +1,6 @@
 /* GNU/Linux S/390 specific low level interface, for the remote server
    for GDB.
-   Copyright (C) 2001-2016 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #define HWCAP_S390_VX 2048
 #endif
 
+#ifndef HWCAP_S390_GS
+#define HWCAP_S390_GS 16384
+#endif
+
 #define s390_num_regs 52
 
 static int s390_regmap[] = {
@@ -370,6 +374,26 @@ s390_store_vxrs_high (struct regcache *regcache, const void *buf)
     supply_register (regcache, v16 + i, (const char *) buf + 16 * i);
 }
 
+static void
+s390_store_gs (struct regcache *regcache, const void *buf)
+{
+  int gsd = find_regno (regcache->tdesc, "gsd");
+  int i;
+
+  for (i = 0; i < 3; i++)
+    supply_register (regcache, gsd + i, (const char *) buf + 8 * (i + 1));
+}
+
+static void
+s390_store_gsbc (struct regcache *regcache, const void *buf)
+{
+  int bc_gsd = find_regno (regcache->tdesc, "bc_gsd");
+  int i;
+
+  for (i = 0; i < 3; i++)
+    supply_register (regcache, bc_gsd + i, (const char *) buf + 8 * (i + 1));
+}
+
 static struct regset_info s390_regsets[] = {
   { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
 #ifndef __s390x__
@@ -388,6 +412,11 @@ static struct regset_info s390_regsets[] = {
     EXTENDED_REGS, s390_fill_vxrs_low, s390_store_vxrs_low },
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_HIGH, 0,
     EXTENDED_REGS, s390_fill_vxrs_high, s390_store_vxrs_high },
+  /* Guarded storage registers are read-only.  */
+  { PTRACE_GETREGSET, -1, NT_S390_GS_CB, 0, EXTENDED_REGS,
+    NULL, s390_store_gs },
+  { PTRACE_GETREGSET, -1, NT_S390_GS_BC, 0, EXTENDED_REGS,
+    NULL, s390_store_gsbc },
   NULL_REGSET
 };
 
@@ -438,33 +467,27 @@ s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
     }
 }
 
-static unsigned long
-s390_get_hwcap (const struct target_desc *tdesc)
-{
-  int wordsize = register_size (tdesc, 0);
-  gdb_byte *data = (gdb_byte *) alloca (2 * wordsize);
-  int offset = 0;
+/* Determine the word size for the given PID, in bytes.  */
 
-  while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
+#ifdef __s390x__
+static int
+s390_get_wordsize (int pid)
+{
+  errno = 0;
+  PTRACE_XFER_TYPE pswm = ptrace (PTRACE_PEEKUSER, pid,
+                                 (PTRACE_TYPE_ARG3) 0,
+                                 (PTRACE_TYPE_ARG4) 0);
+  if (errno != 0)
     {
-      if (wordsize == 4)
-        {
-          unsigned int *data_p = (unsigned int *)data;
-          if (data_p[0] == AT_HWCAP)
-           return data_p[1];
-        }
-      else
-        {
-          unsigned long *data_p = (unsigned long *)data;
-          if (data_p[0] == AT_HWCAP)
-           return data_p[1];
-        }
-
-      offset += 2 * wordsize;
+      warning (_("Couldn't determine word size, assuming 64-bit."));
+      return 8;
     }
-
-  return 0;
+  /* Derive word size from extended addressing mode (PSW bit 31).  */
+  return pswm & (1L << 32) ? 8 : 4;
 }
+#else
+#define s390_get_wordsize(pid) 4
+#endif
 
 static int
 s390_check_regset (int pid, int regset, int regsize)
@@ -492,45 +515,35 @@ s390_arch_setup (void)
   const struct target_desc *tdesc;
   struct regset_info *regset;
 
-  /* Check whether the kernel supports extra register sets.  */
+  /* Determine word size and HWCAP.  */
   int pid = pid_of (current_thread);
+  int wordsize = s390_get_wordsize (pid);
+  unsigned long hwcap = linux_get_hwcap (wordsize);
+
+  /* Check whether the kernel supports extra register sets.  */
   int have_regset_last_break
     = s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
   int have_regset_system_call
     = s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
-  int have_regset_tdb = s390_check_regset (pid, NT_S390_TDB, 256);
-  int have_regset_vxrs = s390_check_regset (pid, NT_S390_VXRS_LOW, 128)
-    && s390_check_regset (pid, NT_S390_VXRS_HIGH, 256);
-
-  /* Assume 31-bit inferior process.  */
-  if (have_regset_system_call)
-    tdesc = tdesc_s390_linux32v2;
-  else if (have_regset_last_break)
-    tdesc = tdesc_s390_linux32v1;
-  else
-    tdesc = tdesc_s390_linux32;
+  int have_regset_tdb
+    = (s390_check_regset (pid, NT_S390_TDB, 256)
+       && (hwcap & HWCAP_S390_TE) != 0);
+  int have_regset_vxrs
+    = (s390_check_regset (pid, NT_S390_VXRS_LOW, 128)
+       && s390_check_regset (pid, NT_S390_VXRS_HIGH, 256)
+       && (hwcap & HWCAP_S390_VX) != 0);
+  int have_regset_gs
+    = (s390_check_regset (pid, NT_S390_GS_CB, 32)
+       && s390_check_regset (pid, NT_S390_GS_BC, 32)
+       && (hwcap & HWCAP_S390_GS) != 0);
 
-  /* On a 64-bit host, check the low bit of the (31-bit) PSWM
-     -- if this is one, we actually have a 64-bit inferior.  */
   {
 #ifdef __s390x__
-    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 (wordsize == 8)
       {
-       if (have_regset_tdb)
-         have_regset_tdb =
-           (s390_get_hwcap (tdesc_s390x_linux64v2) & HWCAP_S390_TE) != 0;
-       if (have_regset_vxrs)
-         have_regset_vxrs =
-           (s390_get_hwcap (tdesc_s390x_linux64v2) & HWCAP_S390_VX) != 0;
-
-       if (have_regset_vxrs)
+       if (have_regset_gs)
+         tdesc = tdesc_s390x_gs_linux64;
+       else if (have_regset_vxrs)
          tdesc = (have_regset_tdb ? tdesc_s390x_tevx_linux64 :
                   tdesc_s390x_vx_linux64);
        else if (have_regset_tdb)
@@ -547,15 +560,12 @@ s390_arch_setup (void)
        using the full 64-bit GPRs.  */
     else
 #endif
-    if (s390_get_hwcap (tdesc) & HWCAP_S390_HIGH_GPRS)
+    if (hwcap & 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_vxrs)
-         have_regset_vxrs = (s390_get_hwcap (tdesc) & HWCAP_S390_VX) != 0;
-
-       if (have_regset_vxrs)
+       if (have_regset_gs)
+         tdesc = tdesc_s390_gs_linux64;
+       else if (have_regset_vxrs)
          tdesc = (have_regset_tdb ? tdesc_s390_tevx_linux64 :
                   tdesc_s390_vx_linux64);
        else if (have_regset_tdb)
@@ -567,6 +577,16 @@ s390_arch_setup (void)
        else
          tdesc = tdesc_s390_linux64;
       }
+    else
+      {
+       /* Assume 31-bit inferior process.  */
+       if (have_regset_system_call)
+         tdesc = tdesc_s390_linux32v2;
+       else if (have_regset_last_break)
+         tdesc = tdesc_s390_linux32v1;
+       else
+         tdesc = tdesc_s390_linux32;
+      }
 
     have_hwcap_s390_vx = have_regset_vxrs;
   }
@@ -596,6 +616,9 @@ s390_arch_setup (void)
        case NT_S390_VXRS_HIGH:
          regset->size = have_regset_vxrs ? 256 : 0;
          break;
+       case NT_S390_GS_CB:
+       case NT_S390_GS_BC:
+         regset->size = have_regset_gs ? 32 : 0;
        default:
          break;
        }
@@ -1013,7 +1036,7 @@ static const unsigned char s390_ft_exit_gpr_zarch[] = {
 static void
 append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
 {
-  write_inferior_memory (*to, buf, len);
+  target_write_memory (*to, buf, len);
   *to += len;
 }
 
@@ -1379,6 +1402,8 @@ s390_get_ipa_tdesc_idx (void)
     return S390_TDESC_VX;
   if (tdesc == tdesc_s390x_tevx_linux64)
     return S390_TDESC_TEVX;
+  if (tdesc == tdesc_s390x_gs_linux64)
+    return S390_TDESC_GS;
 #endif
 
   if (tdesc == tdesc_s390_linux32)
@@ -1399,6 +1424,8 @@ s390_get_ipa_tdesc_idx (void)
     return S390_TDESC_VX;
   if (tdesc == tdesc_s390_tevx_linux64)
     return S390_TDESC_TEVX;
+  if (tdesc == tdesc_s390_gs_linux64)
+    return S390_TDESC_GS;
 
   return 0;
 }
@@ -1548,8 +1575,8 @@ static void
 s390_emit_ext (int arg)
 {
   unsigned char buf[] = {
-    0x8d, 0x20, 0x00, 64 - arg,        /* sldl %r2, <64-arg> */
-    0x8e, 0x20, 0x00, 64 - arg,        /* srda %r2, <64-arg> */
+    0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
+    0x8e, 0x20, 0x00, (unsigned char) (64 - arg), /* srda %r2, <64-arg> */
   };
   add_insns (buf, sizeof buf);
 }
@@ -1766,7 +1793,7 @@ s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
     }
 
   memcpy (buf, &sdiff, sizeof sdiff);
-  write_inferior_memory (from, buf, sizeof sdiff);
+  target_write_memory (from, buf, sizeof sdiff);
 }
 
 /* Preparation for emitting a literal pool of given size.  Loads the address
@@ -1780,7 +1807,8 @@ s390_emit_litpool (int size)
     0x07, 0x07,
   };
   unsigned char buf[] = {
-    0xa7, 0x15, 0x00, (size + 4) / 2,  /* bras %r1, .Lend+size */
+    0xa7, 0x15, 0x00,
+    (unsigned char) ((size + 4) / 2),  /* bras %r1, .Lend+size */
     /* .Lend: */
   };
   if (size == 4)
@@ -1804,8 +1832,11 @@ s390_emit_const (LONGEST num)
 {
   unsigned long long n = num;
   unsigned char buf_s[] = {
-    0xa7, 0x38, num >> 8, num, /* lhi %r3, <num> */
-    0x17, 0x22,                        /* xr %r2, %r2 */
+    /* lhi %r3, <num> */
+    0xa7, 0x38,
+    (unsigned char) (num >> 8), (unsigned char) num,
+    /* xr %r2, %r2 */
+    0x17, 0x22,
   };
   static const unsigned char buf_l[] = {
     0x98, 0x23, 0x10, 0x00,    /* lm %r2, %r3, 0(%r1) */
@@ -1845,8 +1876,10 @@ static void
 s390_emit_reg (int reg)
 {
   unsigned char bufpre[] = {
-    0x18, 0x29,                        /* lr %r2, %r9 */
-    0xa7, 0x38, reg >> 8, reg, /* lhi %r3, <reg> */
+    /* lr %r2, %r9 */
+    0x18, 0x29,
+    /* lhi %r3, <reg> */
+    0xa7, 0x38, (unsigned char) (reg >> 8), (unsigned char) reg,
   };
   add_insns (bufpre, sizeof bufpre);
   s390_emit_call (get_raw_reg_func_addr ());
@@ -1882,8 +1915,8 @@ static void
 s390_emit_zero_ext (int arg)
 {
   unsigned char buf[] = {
-    0x8d, 0x20, 0x00, 64 - arg,        /* sldl %r2, <64-arg> */
-    0x8c, 0x20, 0x00, 64 - arg,        /* srdl %r2, <64-arg> */
+    0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
+    0x8c, 0x20, 0x00, (unsigned char) (64 - arg), /* srdl %r2, <64-arg> */
   };
   add_insns (buf, sizeof buf);
 }
@@ -1908,7 +1941,9 @@ static void
 s390_emit_stack_adjust (int n)
 {
   unsigned char buf[] = {
-    0xa7, 0xfa, n * 8 >> 8, n * 8,     /* ahi %r15, 8*n */
+    /* ahi %r15, 8*n */
+    0xa7, 0xfa,
+    (unsigned char ) (n * 8 >> 8), (unsigned char) (n * 8),
   };
   add_insns (buf, sizeof buf);
 }
@@ -1919,7 +1954,8 @@ static void
 s390_emit_set_r2 (int arg1)
 {
   unsigned char buf_s[] = {
-    0xa7, 0x28, arg1 >> 8, arg1,       /* lhi %r2, <arg1> */
+    /* lhi %r2, <arg1> */
+    0xa7, 0x28, (unsigned char) (arg1 >> 8), (unsigned char) arg1,
   };
   static const unsigned char buf_l[] = {
     0x58, 0x20, 0x10, 0x00,    /* l %r2, 0(%r1) */
@@ -2273,8 +2309,10 @@ static void
 s390x_emit_ext (int arg)
 {
   unsigned char buf[] = {
-    0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0d,    /* sllg %r2, %r2, <64-arg> */
-    0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0a,    /* srag %r2, %r2, <64-arg> */
+    /* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
+    /* srag %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0a,
   };
   add_insns (buf, sizeof buf);
 }
@@ -2442,7 +2480,8 @@ s390x_emit_const (LONGEST num)
 {
   unsigned long long n = num;
   unsigned char buf_s[] = {
-    0xa7, 0x29, num >> 8, num,         /* lghi %r2, <num> */
+    /* lghi %r2, <num> */
+    0xa7, 0x29, (unsigned char) (num >> 8), (unsigned char) num,
   };
   static const unsigned char buf_l[] = {
     0xe3, 0x20, 0x10, 0x00, 0x00, 0x04,        /* lg %r2, 0(%r1) */
@@ -2482,8 +2521,10 @@ static void
 s390x_emit_reg (int reg)
 {
   unsigned char buf[] = {
-    0xb9, 0x04, 0x00, 0x29,            /* lgr %r2, %r9 */
-    0xa7, 0x39, reg >> 8, reg,         /* lghi %r3, <reg> */
+    /* lgr %r2, %r9 */
+    0xb9, 0x04, 0x00, 0x29,
+    /* lghi %r3, <reg> */
+    0xa7, 0x39, (unsigned char) (reg >> 8), (unsigned char) reg,
   };
   add_insns (buf, sizeof buf);
   s390x_emit_call (get_raw_reg_func_addr ());
@@ -2519,8 +2560,10 @@ static void
 s390x_emit_zero_ext (int arg)
 {
   unsigned char buf[] = {
-    0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0d,    /* sllg %r2, %r2, <64-arg> */
-    0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0c,    /* srlg %r2, %r2, <64-arg> */
+    /* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
+    /* srlg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0c,
   };
   add_insns (buf, sizeof buf);
 }
@@ -2544,7 +2587,9 @@ static void
 s390x_emit_stack_adjust (int n)
 {
   unsigned char buf[] = {
-    0xa7, 0xfb, n * 8 >> 8, n * 8,     /* aghi %r15, 8*n */
+    /* aghi %r15, 8*n */
+    0xa7, 0xfb,
+    (unsigned char) (n * 8 >> 8), (unsigned char) (n * 8),
   };
   add_insns (buf, sizeof buf);
 }
@@ -2767,7 +2812,9 @@ struct linux_target_ops the_low_target = {
   s390_supply_ptrace_register,
   NULL, /* siginfo_fixup */
   NULL, /* new_process */
+  NULL, /* delete_process */
   NULL, /* new_thread */
+  NULL, /* delete_thread */
   NULL, /* new_fork */
   NULL, /* prepare_to_resume */
   NULL, /* process_qsupported */
@@ -2797,6 +2844,7 @@ initialize_low_arch (void)
   init_registers_s390_te_linux64 ();
   init_registers_s390_vx_linux64 ();
   init_registers_s390_tevx_linux64 ();
+  init_registers_s390_gs_linux64 ();
 #ifdef __s390x__
   init_registers_s390x_linux64 ();
   init_registers_s390x_linux64v1 ();
@@ -2804,6 +2852,7 @@ initialize_low_arch (void)
   init_registers_s390x_te_linux64 ();
   init_registers_s390x_vx_linux64 ();
   init_registers_s390x_tevx_linux64 ();
+  init_registers_s390x_gs_linux64 ();
 #endif
 
   initialize_regsets_info (&s390_regsets_info);
This page took 0.037047 seconds and 4 git commands to generate.