This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfc, s390] [gdb part] Support extended register sets


Hello,

Linux kernel version 3.2 will contain a fix to system call restart handling
on s390 that plugs a race condition, but in doing so removes special-cased
support for GDB performing inferior calls while a system call restart is
pending.

This causes regressions e.g. in the interrupt.exp and hand-call-in-threads.exp
test cases.

To fix this, we need to implement similar logic on s390 as is already done
for most other Linux architectures: the kernel exports a special "register"
that indicates whether system call restart is pending; GDB needs to save
and restore that register (together with the original contents of %r2)
across inferior calls, and needs to clear the register when actually
preforming an inferior call.

The only problem is that those registers have not been represented in GDB's
register set so far.  The patch below adds them:

 orig_r2:  the original contents of r2 before the system call
           This has always been part of the core gregset, but has simply
           been ignored by GDB

 system_call: presented as a new register set NT_S390_SYSTEM_CALL, always
              size 4 bytes; if nonzero, we're currently within a system
              call

Since I'm already at it, the patch also adds another register, which is
unrelated to system call restarting, but also has been added to the kernel
a while ago and is not yet supported in GDB:

 last_break: presented as a new register set NT_S390_LAST_BREAK, always
             size 8 bytes; holds the address of the last branch instruction


These are represented via target descriptions:

- orig_r2 is simply added to the base description
- last_break is added in a variant "v1"
- system_call is added in a variant "v2"

(since NT_S390_SYSTEM_CALL was added after NT_S390_LAST_BREAK).

Since we already had three target descriptions (s390x with 64-bit
registers, s390 with 32-bit registers, and s390 with 64-bit registers),
this means we add three versions each of the "v1" and "v2" variants.

The bulk of the patch below is adding those target descriptions and their
handling in native code, gdbserver, and core files.

In addition, the patch adds code to reset the system_call register when
performing an inferior call (in s390_write_pc), as well as support for
the fact that last_break is strictly read-only (in s390_cannot_store_register
and an update to the callfuncs.exp test case).

The previously posted BFD patch adding support for the new core file
note types is a prerequiste to this patch.

Tested on s390x-ibm-linux (31-bit and 64-bit) and s390-ibm-linux, both
natively and via gdbserver.  Fixes the above-mentioned regressions on
a Linux 3.2 kernel.

I'm planning on committing this soon, after the BFD patch is approved.

Bye,
Ulrich



ChangeLog:

	* s390-tdep.h (S390_ORIG_R2_REGNUM): Define.
	(S390_LAST_BREAK_REGNUM): Likewise.
	(S390_SYSTEM_CALL_REGNUM): Likewise.
	(S390_NUM_REGS): Update.

	(s390_regmap_last_break): Add declaration.
	(s390x_regmap_last_break): Likewise.
	(s390_regmap_system_call): Likewise.

	(tdesc_s390_linux32v1): Add declaration.
	(tdesc_s390_linux32v2): Likewise.
	(tdesc_s390_linux64v1): Likewise.
	(tdesc_s390_linux64v2): Likewise.
	(tdesc_s390x_linux64v1): Likewise.
	(tdesc_s390x_linux64v2): Likewise.

	* s390-tdep.c: Include new target description files
	"features/s390-linux32v1.c", "features/s390-linux32v2.c",
	"features/s390-linux64v1.c", "features/s390-linux64v2.c",
	"features/s390x-linux64v1.c", and "features/s390x-linux64v2.c".
	(s390_cannot_store_register): New function.
	(s390_write_pc): Likewise.
	(s390_dwarf_regmap): Add fields for new registers.
	(s390_regmap_gregset): Likewise.
	(s390x_regmap_gregset): Likewise.
	(s390_regmap_fpregset): Likewise.
	(s390_regmap_upper): Likewise.
	(s390_regmap_last_break): New variable.
	(s390x_regmap_last_break): Likewise.
	(s390_regmap_system_call): Likewise.
	(s390_last_break_regset): Likewise.
	(s390x_last_break_regset): Likewise.
	(s390_system_call_regset): Likewise.
	(s390_upper_regset_sections): Rename to ...
	(s390_linux64_regset_sections): ... this.
	(s390_linux32_regset_sections): New variable.
	(s390x_linux64_regset_sections): Likewise.
	(s390_linux32v1_regset_sections): Likewise.
	(s390_linux32v2_regset_sections): Likewise.
	(s390_linux64v1_regset_sections): Likewise.
	(s390_linux64v2_regset_sections): Likewise.
	(s390x_linux64v1_regset_sections): Likewise.
	(s390x_linux64v2_regset_sections): Likewise.
	(s390_regset_from_core_section): Handle .reg-s390-last-break and
	.reg-s390-system-call core file sections.
	(s390_core_read_description): Check for presence of
	.reg-s390-last-break and .reg-s390-system-call core file
	sections and return appropriate target description.
	(s390_gdbarch_init): Detect Linux-specific registers "orig_r2",
	"last_break" and "system_call" in target description.  Install
	appropriate gdbarch_core_regset_sections array.
	Call set_gdbarch_cannot_store_register and set_gdbarch_write_pc.
	(_initialize_s390_tdep): Initialize additional target descriptions.

	* s390-nat.c: Include "elf/common.h".
	(PTRACE_GETREGSET, PTRACE_SETREGSET): Define if undefined.
	(have_regset_last_break): New static variable.
	(have_regset_system_call): Likewise.
	(s390_native_supply): Handle S390_ORIG_R2_REGNUM.
	(s390_native_collect): Likewise.
	(fetch_regset, store_regset, check_regset): New functions.
	(s390_linux_fetch_inferior_registers): Handle S390_LAST_BREAK_REGNUM
	and S390_SYSTEM_CALL_REGNUM.
	(s390_linux_store_inferior_registers): Likewise.
	(s390_read_description): Check for presence of NT_S390_LAST_BREAK
	and NT_S390_SYSTEM_CALL regsets and use appropriate description.

	* features/Makefile (WHICH): Add s390-linux32v1, s390-linux64v1,
	s390x-linux64v1, s390-linux32v2, s390-linux64v2, and s390x-linux64v2.
	(s390-linux32v1-expedite): Define.
	(s390-linux32v2-expedite): Likewise.
	(s390-linux64v1-expedite): Likewise.
	(s390-linux64v2-expedite): Likewise.
	(s390x-linux64v1-expedite): Likewise.
	(s390x-linux64v2-expedite): Likewise.

	* features/s390-linux32.xml: Add orig_r2 register.
	* features/s390-linux64.xml: Likewise.
	* features/s390x-linux64.xml: Likewise.
	* features/s390-linux32v1.xml: New file.
	* features/s390-linux32v2.xml: Likewise.
	* features/s390-linux64v1.xml: Likewise.
	* features/s390-linux64v2.xml: Likewise.
	* features/s390x-linux64v1.xml: Likewise.
	* features/s390x-linux64v2.xml: Likewise.

	* features/s390-linux32.c: Regenerate.
	* features/s390-linux64.c: Likewise.
	* features/s390x-linux64.c: Likewise.
	* features/s390-linux32v1.c: New generated file.
	* features/s390-linux32v2.c: Likewise.
	* features/s390-linux64v1.c: Likewise.
	* features/s390-linux64v2.c: Likewise.
	* features/s390x-linux64v1.c: Likewise.
	* features/s390x-linux64v2.c: Likewise.

	* regformats/s390-linux32.dat: Regenerate.
	* regformats/s390-linux64.dat: Regenerate.
	* regformats/s390x-linux64.dat: Regenerate.
	* regformats/s390-linux32v1.dat: New generated file.
	* regformats/s390-linux32v2.dat: Likewise.
	* regformats/s390-linux64v1.dat: Likewise.
	* regformats/s390-linux64v2.dat: Likewise.
	* regformats/s390x-linux64v1.dat: Likewise.
	* regformats/s390x-linux64v2.dat: Likewise.

gdbserver/ChangeLog:

	* Makefile.in (s390-linux32v1.o, s390-linux32v1.c): New rules.
	(s390-linux32v2.o, s390-linux32v2.c): Likewise.
	(s390-linux64v1.o, s390-linux64v1.c): Likewise.
	(s390-linux64v2.o, s390-linux64v2.c): Likewise.
	(s390x-linux64v1.o, s390x-linux64v1.c): Likewise.
	(s390x-linux64v2.o, s390x-linux64v2.c): Likewise.
	* configure.srv [s390*-*-linux*] (srv_regobj): Add new objects.
	(srv_xmlfiles): Add new XML files.

	* linux-s390-low.c: Include "elf/common.h", <sys/ptrace.h>,
	and <sys/uio.h>.
	(PTRACE_GETREGSET, PTRACE_SETREGSET): Define if undefined.
	(init_registers_s390_linux32v1): Add prototype.
	(init_registers_s390_linux32v2): Likewise.
	(init_registers_s390_linux64v1): Likewise.
	(init_registers_s390_linux64v2): Likewise.
	(init_registers_s390x_linux64v1): Likewise.
	(init_registers_s390x_linux64v2): Likewise.
	(s390_num_regs): Increment to 52.
	(s390_regmap): Add orig_r2 register.
	(s390_num_regs_3264): Increment to 68.
	(s390_regmap_3264): Add orig_r2 register.
	(s390_collect_ptrace_register): Handle orig_r2 register.
	(s390_supply_ptrace_register): Likewise.
	(s390_fill_last_break): New function.
	(s390_store_last_break): Likewise.
	(s390_fill_system_call): New function.
	(s390_store_system_call): Likewise.
	(target_regsets): Handle NT_S390_LAST_BREAK and NT_S390_SYSTEM_CALL
	register sets.
	(s390_check_regset): New function.
	(s390_arch_setup): Check for presence of NT_S390_LAST_BREAK and
	NT_S390_SYSTEM_CALL regsets and use appropriate description.
	Update target_regsets for available register sets.

testsuite/ChangeLog:

	* gdb.base/callfuncs.exp (fetch_all_registers): Filter out read-only
	last_break register on s390*-*-* targets.


Index: gdb-head/gdb/s390-nat.c
===================================================================
--- gdb-head.orig/gdb/s390-nat.c
+++ gdb-head/gdb/s390-nat.c
@@ -28,6 +28,7 @@
 #include "auxv.h"
 
 #include "s390-tdep.h"
+#include "elf/common.h"
 
 #include <asm/ptrace.h>
 #include <sys/ptrace.h>
@@ -40,6 +41,16 @@
 #define HWCAP_S390_HIGH_GPRS 512
 #endif
 
+#ifndef PTRACE_GETREGSET
+#define PTRACE_GETREGSET 0x4204
+#endif
+
+#ifndef PTRACE_SETREGSET
+#define PTRACE_SETREGSET 0x4205
+#endif
+
+static int have_regset_last_break = 0;
+static int have_regset_system_call = 0;
 
 /* Map registers to gregset/ptrace offsets.
    These arrays are defined in s390-tdep.c.  */
@@ -97,7 +108,8 @@ s390_native_supply (struct regcache *reg
 	  return;
 	}
 
-      if (regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
+      if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
+	  || regno == S390_ORIG_R2_REGNUM)
 	offset += 4;
     }
 #endif
@@ -151,7 +163,8 @@ s390_native_collect (const struct regcac
 	  return;
 	}
 
-      if (regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
+      if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
+	  || regno == S390_ORIG_R2_REGNUM)
 	{
 	  memset (regp + offset, 0, 4);
 	  offset += 4;
@@ -293,6 +306,70 @@ store_fpregs (const struct regcache *reg
     perror_with_name (_("Couldn't write floating point status"));
 }
 
+/* Fetch all registers in the kernel's register set whose number is REGSET,
+   whose size is REGSIZE, and whose layout is described by REGMAP, from
+   process/thread TID and store their values in GDB's register cache.  */
+static void
+fetch_regset (struct regcache *regcache, int tid,
+	      int regset, int regsize, int *regmap)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  gdb_byte *buf = alloca (regsize);
+  struct iovec iov;
+  int i;
+
+  iov.iov_base = buf;
+  iov.iov_len = regsize;
+
+  if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
+    perror_with_name (_("Couldn't get register set"));
+
+  for (i = 0; i < S390_NUM_REGS; i++)
+    s390_native_supply (regcache, i, buf, regmap);
+}
+
+/* Store all registers in the kernel's register set whose number is REGSET,
+   whose size is REGSIZE, and whose layout is described by REGMAP, from
+   GDB's register cache back to process/thread TID.  */
+static void
+store_regset (struct regcache *regcache, int tid,
+	      int regset, int regsize, int *regmap)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  gdb_byte *buf = alloca (regsize);
+  struct iovec iov;
+  int i;
+
+  iov.iov_base = buf;
+  iov.iov_len = regsize;
+
+  if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
+    perror_with_name (_("Couldn't get register set"));
+
+  for (i = 0; i < S390_NUM_REGS; i++)
+    s390_native_collect (regcache, i, buf, regmap);
+
+  if (ptrace (PTRACE_SETREGSET, tid, (long) regset, (long) &iov) < 0)
+    perror_with_name (_("Couldn't set register set"));
+}
+
+/* Check whether the kernel provides a register set with number REGSET
+   of size REGSIZE for process/thread TID.  */
+static int
+check_regset (int tid, int regset, int regsize)
+{
+  gdb_byte *buf = alloca (regsize);
+  struct iovec iov;
+
+  iov.iov_base = buf;
+  iov.iov_len = regsize;
+
+  if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
+    return 0;
+  else
+    return 1;
+}
+
 /* Fetch register REGNUM from the child process.  If REGNUM is -1, do
    this for all registers.  */
 static void
@@ -308,6 +385,17 @@ s390_linux_fetch_inferior_registers (str
   if (regnum == -1 
       || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
     fetch_fpregs (regcache, tid);
+
+  if (have_regset_last_break)
+    if (regnum == -1 || regnum == S390_LAST_BREAK_REGNUM)
+      fetch_regset (regcache, tid, NT_S390_LAST_BREAK, 8,
+		    (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 32
+		     ? s390_regmap_last_break : s390x_regmap_last_break));
+
+  if (have_regset_system_call)
+    if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM)
+      fetch_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4,
+		    s390_regmap_system_call);
 }
 
 /* Store register REGNUM back into the child process.  If REGNUM is
@@ -325,6 +413,13 @@ s390_linux_store_inferior_registers (str
   if (regnum == -1 
       || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1))
     store_fpregs (regcache, tid, regnum);
+
+  /* S390_LAST_BREAK_REGNUM is read-only.  */
+
+  if (have_regset_system_call)
+    if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM)
+      store_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4,
+		    s390_regmap_system_call);
 }
 
 
@@ -539,6 +634,13 @@ s390_get_hwcap (void)
 static const struct target_desc *
 s390_read_description (struct target_ops *ops)
 {
+  int tid = s390_inferior_tid ();
+
+  have_regset_last_break
+    = check_regset (tid, NT_S390_LAST_BREAK, 8);
+  have_regset_system_call
+    = check_regset (tid, NT_S390_SYSTEM_CALL, 4);
+
 #ifdef __s390x__
   /* If GDB itself is compiled as 64-bit, we are running on a machine in
      z/Architecture mode.  If the target is running in 64-bit addressing
@@ -547,16 +649,22 @@ s390_read_description (struct target_ops
      that mode, report s390 architecture with 64-bit GPRs.  */
 
   if (s390_target_wordsize () == 8)
-    return tdesc_s390x_linux64;
+    return (have_regset_system_call? tdesc_s390x_linux64v2 :
+	    have_regset_last_break? tdesc_s390x_linux64v1 :
+	    tdesc_s390x_linux64);
 
   if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
-    return tdesc_s390_linux64;
+    return (have_regset_system_call? tdesc_s390_linux64v2 :
+	    have_regset_last_break? tdesc_s390_linux64v1 :
+	    tdesc_s390_linux64);
 #endif
 
   /* If GDB itself is compiled as 31-bit, or if we're running a 31-bit inferior
      on a 64-bit kernel that does not support using 64-bit registers in 31-bit
      mode, report s390 architecture with 32-bit GPRs.  */
-  return tdesc_s390_linux32;
+  return (have_regset_system_call? tdesc_s390_linux32v2 :
+	  have_regset_last_break? tdesc_s390_linux32v1 :
+	  tdesc_s390_linux32);
 }
 
 void _initialize_s390_nat (void);
Index: gdb-head/gdb/s390-tdep.c
===================================================================
--- gdb-head.orig/gdb/s390-tdep.c
+++ gdb-head/gdb/s390-tdep.c
@@ -47,8 +47,14 @@
 #include "s390-tdep.h"
 
 #include "features/s390-linux32.c"
+#include "features/s390-linux32v1.c"
+#include "features/s390-linux32v2.c"
 #include "features/s390-linux64.c"
+#include "features/s390-linux64v1.c"
+#include "features/s390-linux64v2.c"
 #include "features/s390x-linux64.c"
+#include "features/s390x-linux64v1.c"
+#include "features/s390x-linux64v2.c"
 
 
 /* The tdep structure.  */
@@ -101,6 +107,32 @@ s390_register_call_saved (struct gdbarch
   return 0;
 }
 
+static int
+s390_cannot_store_register (struct gdbarch *gdbarch, int regnum)
+{
+  /* The last-break address is read-only.  */
+  return regnum == S390_LAST_BREAK_REGNUM;
+}
+
+static void
+s390_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
+
+  /* Set special SYSTEM_CALL register to 0 to prevent the kernel from
+     messing with the PC we just installed, if we happen to be within
+     an interrupted system call that the kernel wants to restart.
+
+     Note that after we return from the dummy call, the SYSTEM_CALL and
+     ORIG_R2 registers will be automatically restored, and the kernel
+     continues to restart the system call at this point.  */
+  if (register_size (gdbarch, S390_SYSTEM_CALL_REGNUM) > 0)
+    regcache_cooked_write_unsigned (regcache, S390_SYSTEM_CALL_REGNUM, 0);
+}
+
 
 /* DWARF Register Mapping.  */
 
@@ -137,6 +169,9 @@ static int s390_dwarf_regmap[] =
   S390_R4_REGNUM, S390_R5_REGNUM, S390_R6_REGNUM, S390_R7_REGNUM,
   S390_R8_REGNUM, S390_R9_REGNUM, S390_R10_REGNUM, S390_R11_REGNUM,
   S390_R12_REGNUM, S390_R13_REGNUM, S390_R14_REGNUM, S390_R15_REGNUM,
+
+  /* Linux-specific registers (not mapped).  */
+  -1, -1, -1,
 };
 
 /* Convert DWARF register number REG to the appropriate register
@@ -391,6 +426,8 @@ int s390_regmap_gregset[S390_NUM_REGS] =
   /* GPR Uppper Halves.  */
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Linux-specific optional "registers".  */
+  0x88, -1, -1,
 };
 
 int s390x_regmap_gregset[S390_NUM_REGS] =
@@ -417,6 +454,8 @@ int s390x_regmap_gregset[S390_NUM_REGS] 
   0x30, 0x38, 0x40, 0x48,
   0x50, 0x58, 0x60, 0x68,
   0x70, 0x78, 0x80, 0x88,
+  /* Linux-specific optional "registers".  */
+  0xd0, -1, -1,
 };
 
 int s390_regmap_fpregset[S390_NUM_REGS] =
@@ -439,6 +478,8 @@ int s390_regmap_fpregset[S390_NUM_REGS] 
   /* GPR Uppper Halves.  */
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Linux-specific optional "registers".  */
+  -1, -1, -1,
 };
 
 int s390_regmap_upper[S390_NUM_REGS] =
@@ -461,6 +502,74 @@ int s390_regmap_upper[S390_NUM_REGS] =
   0x10, 0x14, 0x18, 0x1c,
   0x20, 0x24, 0x28, 0x2c,
   0x30, 0x34, 0x38, 0x3c,
+  /* Linux-specific optional "registers".  */
+  -1, -1, -1,
+};
+
+int s390_regmap_last_break[S390_NUM_REGS] =
+{
+  /* Program Status Word.  */
+  -1, -1,
+  /* General Purpose Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Access Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Floating Point Control Word.  */
+  -1,
+  /* Floating Point Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* GPR Uppper Halves.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Linux-specific optional "registers".  */
+  -1, 4, -1,
+};
+
+int s390x_regmap_last_break[S390_NUM_REGS] =
+{
+  /* Program Status Word.  */
+  -1, -1,
+  /* General Purpose Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Access Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Floating Point Control Word.  */
+  -1,
+  /* Floating Point Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* GPR Uppper Halves.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Linux-specific optional "registers".  */
+  -1, 0, -1,
+};
+
+int s390_regmap_system_call[S390_NUM_REGS] =
+{
+  /* Program Status Word.  */
+  -1, -1,
+  /* General Purpose Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Access Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Floating Point Control Word.  */
+  -1,
+  /* Floating Point Registers.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* GPR Uppper Halves.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  /* Linux-specific optional "registers".  */
+  -1, -1, 0,
 };
 
 /* Supply register REGNUM from the register set REGSET to register cache 
@@ -522,14 +631,100 @@ static const struct regset s390_upper_re
   s390_collect_regset
 };
 
-static struct core_regset_section s390_upper_regset_sections[] =
+static const struct regset s390_last_break_regset = {
+  s390_regmap_last_break,
+  s390_supply_regset,
+  s390_collect_regset
+};
+
+static const struct regset s390x_last_break_regset = {
+  s390x_regmap_last_break,
+  s390_supply_regset,
+  s390_collect_regset
+};
+
+static const struct regset s390_system_call_regset = {
+  s390_regmap_system_call,
+  s390_supply_regset,
+  s390_collect_regset
+};
+
+static struct core_regset_section s390_linux32_regset_sections[] =
+{
+  { ".reg", s390_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
+  { NULL, 0}
+};
+
+static struct core_regset_section s390_linux32v1_regset_sections[] =
+{
+  { ".reg", s390_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
+  { ".reg-s390-last-break", 8, "s390 last-break address" },
+  { NULL, 0}
+};
+
+static struct core_regset_section s390_linux32v2_regset_sections[] =
+{
+  { ".reg", s390_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
+  { ".reg-s390-last-break", 8, "s390 last-break address" },
+  { ".reg-s390-system-call", 4, "s390 system-call" },
+  { NULL, 0}
+};
+
+static struct core_regset_section s390_linux64_regset_sections[] =
+{
+  { ".reg", s390_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
+  { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" },
+  { NULL, 0}
+};
+
+static struct core_regset_section s390_linux64v1_regset_sections[] =
+{
+  { ".reg", s390_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
+  { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" },
+  { ".reg-s390-last-break", 8, "s930 last-break address" },
+  { NULL, 0}
+};
+
+static struct core_regset_section s390_linux64v2_regset_sections[] =
 {
   { ".reg", s390_sizeof_gregset, "general-purpose" },
   { ".reg2", s390_sizeof_fpregset, "floating-point" },
   { ".reg-s390-high-gprs", 16*4, "s390 GPR upper halves" },
+  { ".reg-s390-last-break", 8, "s930 last-break address" },
+  { ".reg-s390-system-call", 4, "s390 system-call" },
+  { NULL, 0}
+};
+
+static struct core_regset_section s390x_linux64_regset_sections[] =
+{
+  { ".reg", s390x_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
   { NULL, 0}
 };
 
+static struct core_regset_section s390x_linux64v1_regset_sections[] =
+{
+  { ".reg", s390x_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
+  { ".reg-s390-last-break", 8, "s930 last-break address" },
+  { NULL, 0}
+};
+
+static struct core_regset_section s390x_linux64v2_regset_sections[] =
+{
+  { ".reg", s390x_sizeof_gregset, "general-purpose" },
+  { ".reg2", s390_sizeof_fpregset, "floating-point" },
+  { ".reg-s390-last-break", 8, "s930 last-break address" },
+  { ".reg-s390-system-call", 4, "s390 system-call" },
+  { NULL, 0}
+};
+
+
 /* Return the appropriate register set for the core section identified
    by SECT_NAME and SECT_SIZE.  */
 static const struct regset *
@@ -547,6 +742,13 @@ s390_regset_from_core_section (struct gd
   if (strcmp (sect_name, ".reg-s390-high-gprs") == 0 && sect_size >= 16*4)
     return &s390_upper_regset;
 
+  if (strcmp (sect_name, ".reg-s390-last-break") == 0 && sect_size >= 8)
+    return (gdbarch_ptr_bit (gdbarch) == 32
+	    ?  &s390_last_break_regset : &s390x_last_break_regset);
+
+  if (strcmp (sect_name, ".reg-s390-system-call") == 0 && sect_size >= 4)
+    return &s390_system_call_regset;
+
   return NULL;
 }
 
@@ -555,6 +757,8 @@ s390_core_read_description (struct gdbar
 			    struct target_ops *target, bfd *abfd)
 {
   asection *high_gprs = bfd_get_section_by_name (abfd, ".reg-s390-high-gprs");
+  asection *v1 = bfd_get_section_by_name (abfd, ".reg-s390-last-break");
+  asection *v2 = bfd_get_section_by_name (abfd, ".reg-s390-system-call");
   asection *section = bfd_get_section_by_name (abfd, ".reg");
   if (!section)
     return NULL;
@@ -562,10 +766,16 @@ s390_core_read_description (struct gdbar
   switch (bfd_section_size (abfd, section))
     {
     case s390_sizeof_gregset:
-      return high_gprs? tdesc_s390_linux64 : tdesc_s390_linux32;
+      if (high_gprs)
+	return (v2? tdesc_s390_linux64v2 :
+		v1? tdesc_s390_linux64v1 : tdesc_s390_linux64);
+      else
+	return (v2? tdesc_s390_linux32v2 :
+		v1? tdesc_s390_linux32v1 : tdesc_s390_linux32);
 
     case s390x_sizeof_gregset:
-      return tdesc_s390x_linux64;
+      return (v2? tdesc_s390x_linux64v2 :
+	      v1? tdesc_s390x_linux64v1 : tdesc_s390x_linux64);
 
     default:
       return NULL;
@@ -2749,6 +2959,8 @@ s390_gdbarch_init (struct gdbarch_info i
   struct gdbarch_tdep *tdep;
   int tdep_abi;
   int have_upper = 0;
+  int have_linux_v1 = 0;
+  int have_linux_v2 = 0;
   int first_pseudo_reg, last_pseudo_reg;
 
   /* Default ABI and register size.  */
@@ -2856,6 +3068,25 @@ s390_gdbarch_init (struct gdbarch_info i
 	valid_p &= tdesc_numbered_register (feature, tdesc_data,
 					    S390_A0_REGNUM + i, acrs[i]);
 
+      /* Optional Linux-specific "registers".  */
+      feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.linux");
+      if (feature)
+	{
+	  tdesc_numbered_register (feature, tdesc_data,
+				   S390_ORIG_R2_REGNUM, "orig_r2");
+
+	  if (tdesc_numbered_register (feature, tdesc_data,
+				       S390_LAST_BREAK_REGNUM, "last_break"))
+	    have_linux_v1 = 1;
+
+	  if (tdesc_numbered_register (feature, tdesc_data,
+				       S390_SYSTEM_CALL_REGNUM, "system_call"))
+	    have_linux_v2 = 1;
+
+	  if (have_linux_v2 > have_linux_v1)
+	    valid_p = 0;
+	}
+
       if (!valid_p)
 	{
 	  tdesc_data_cleanup (tdesc_data);
@@ -2913,8 +3144,8 @@ s390_gdbarch_init (struct gdbarch_info i
   set_gdbarch_regset_from_core_section (gdbarch,
                                         s390_regset_from_core_section);
   set_gdbarch_core_read_description (gdbarch, s390_core_read_description);
-  if (have_upper)
-    set_gdbarch_core_regset_sections (gdbarch, s390_upper_regset_sections);
+  set_gdbarch_cannot_store_register (gdbarch, s390_cannot_store_register);
+  set_gdbarch_write_pc (gdbarch, s390_write_pc);
   set_gdbarch_pseudo_register_read (gdbarch, s390_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, s390_pseudo_register_write);
   set_tdesc_pseudo_register_name (gdbarch, s390_pseudo_register_name);
@@ -2980,6 +3211,31 @@ s390_gdbarch_init (struct gdbarch_info i
       set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
       set_solib_svr4_fetch_link_map_offsets
 	(gdbarch, svr4_ilp32_fetch_link_map_offsets);
+
+      if (have_upper)
+	{
+	  if (have_linux_v2)
+	    set_gdbarch_core_regset_sections (gdbarch,
+					      s390_linux64v2_regset_sections);
+	  else if (have_linux_v1)
+	    set_gdbarch_core_regset_sections (gdbarch,
+					      s390_linux64v1_regset_sections);
+	  else
+	    set_gdbarch_core_regset_sections (gdbarch,
+					      s390_linux64_regset_sections);
+	}
+      else
+	{
+	  if (have_linux_v2)
+	    set_gdbarch_core_regset_sections (gdbarch,
+					      s390_linux32v2_regset_sections);
+	  else if (have_linux_v1)
+	    set_gdbarch_core_regset_sections (gdbarch,
+					      s390_linux32v1_regset_sections);
+	  else
+	    set_gdbarch_core_regset_sections (gdbarch,
+					      s390_linux32_regset_sections);
+	}
       break;
 
     case ABI_LINUX_ZSERIES:
@@ -2999,6 +3255,16 @@ s390_gdbarch_init (struct gdbarch_info i
                                                     s390_address_class_type_flags_to_name);
       set_gdbarch_address_class_name_to_type_flags (gdbarch,
                                                     s390_address_class_name_to_type_flags);
+
+      if (have_linux_v2)
+	set_gdbarch_core_regset_sections (gdbarch,
+					  s390x_linux64v2_regset_sections);
+      else if (have_linux_v1)
+	set_gdbarch_core_regset_sections (gdbarch,
+					  s390x_linux64v1_regset_sections);
+      else
+	set_gdbarch_core_regset_sections (gdbarch,
+					  s390x_linux64_regset_sections);
       break;
     }
 
@@ -3026,6 +3292,12 @@ _initialize_s390_tdep (void)
 
   /* Initialize the Linux target descriptions.  */
   initialize_tdesc_s390_linux32 ();
+  initialize_tdesc_s390_linux32v1 ();
+  initialize_tdesc_s390_linux32v2 ();
   initialize_tdesc_s390_linux64 ();
+  initialize_tdesc_s390_linux64v1 ();
+  initialize_tdesc_s390_linux64v2 ();
   initialize_tdesc_s390x_linux64 ();
+  initialize_tdesc_s390x_linux64v1 ();
+  initialize_tdesc_s390x_linux64v2 ();
 }
Index: gdb-head/gdb/s390-tdep.h
===================================================================
--- gdb-head.orig/gdb/s390-tdep.h
+++ gdb-head/gdb/s390-tdep.h
@@ -95,8 +95,12 @@
 #define S390_R13_UPPER_REGNUM 64
 #define S390_R14_UPPER_REGNUM 65
 #define S390_R15_UPPER_REGNUM 66
+/* Linux-specific optional registers.  */
+#define S390_ORIG_R2_REGNUM 67
+#define S390_LAST_BREAK_REGNUM 68
+#define S390_SYSTEM_CALL_REGNUM 69
 /* Total.  */
-#define S390_NUM_REGS 67
+#define S390_NUM_REGS 70
 
 /* Special register usage.  */
 #define S390_SP_REGNUM S390_R15_REGNUM
@@ -110,11 +114,20 @@ extern int s390_regmap_gregset[S390_NUM_
 extern int s390x_regmap_gregset[S390_NUM_REGS];
 #define s390_sizeof_fpregset 0x88
 extern int s390_regmap_fpregset[S390_NUM_REGS];
+extern int s390_regmap_last_break[S390_NUM_REGS];
+extern int s390x_regmap_last_break[S390_NUM_REGS];
+extern int s390_regmap_system_call[S390_NUM_REGS];
 
 /* 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;
+extern struct target_desc *tdesc_s390_linux64v1;
+extern struct target_desc *tdesc_s390_linux64v2;
 extern struct target_desc *tdesc_s390x_linux64;
+extern struct target_desc *tdesc_s390x_linux64v1;
+extern struct target_desc *tdesc_s390x_linux64v2;
 
 #endif
 
Index: gdb-head/gdb/testsuite/gdb.base/callfuncs.exp
===================================================================
--- gdb-head.orig/gdb/testsuite/gdb.base/callfuncs.exp
+++ gdb-head/gdb/testsuite/gdb.base/callfuncs.exp
@@ -294,6 +294,15 @@ proc fetch_all_registers {test} {
 	    }
 	    exp_continue
 	}
+	-re "^last_break\[ \t\]+\[^\r\n\]+\r\n" {
+	    if [istarget "s390*-*-*"] {
+		# Filter out last_break which is read-only,
+		# giving spurious differences.
+	    } else {
+		lappend all_registers_lines $expect_out(0,string)
+	    }
+	    exp_continue
+	}
 	-re "^\[^ \t\]+\[ \t\]+\[^\r\n\]+\r\n" {
 	    lappend all_registers_lines $expect_out(0,string)
 	    exp_continue
Index: gdb-head/gdb/features/Makefile
===================================================================
--- gdb-head.orig/gdb/features/Makefile
+++ gdb-head/gdb/features/Makefile
@@ -42,6 +42,8 @@ WHICH = arm-with-iwmmxt arm-with-vfpv2 a
 	rs6000/powerpc-64l rs6000/powerpc-altivec64l rs6000/powerpc-vsx32l \
 	rs6000/powerpc-vsx64l rs6000/powerpc-cell32l rs6000/powerpc-cell64l \
 	s390-linux32 s390-linux64 s390x-linux64 \
+	s390-linux32v1 s390-linux64v1 s390x-linux64v1 \
+	s390-linux32v2 s390-linux64v2 s390x-linux64v2 \
 	tic6x-c64xp tic6x-c64x tic6x-c62x \
 	tic6x-c64xp-linux tic6x-c64x-linux tic6x-c62x-linux
 
@@ -63,8 +65,14 @@ powerpc-expedite = r1,pc
 rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
 rs6000/powerpc-cell64l-expedite = r1,pc,r0,orig_r3,r4
 s390-linux32-expedite = r14,r15,pswa
+s390-linux32v1-expedite = r14,r15,pswa
+s390-linux32v2-expedite = r14,r15,pswa
 s390-linux64-expedite = r14l,r15l,pswa
+s390-linux64v1-expedite = r14l,r15l,pswa
+s390-linux64v2-expedite = r14l,r15l,pswa
 s390x-linux64-expedite = r14,r15,pswa
+s390x-linux64v1-expedite = r14,r15,pswa
+s390x-linux64v2-expedite = r14,r15,pswa
 tic6x-c64xp-expedite = A15,PC
 tic6x-c64x-expedite = A15,PC
 tic6x-c62x-expedite = A15,PC
Index: gdb-head/gdb/features/s390-linux32v1.c
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux32v1.c
@@ -0,0 +1,79 @@
+/* THIS FILE IS GENERATED.  Original: s390-linux32v1.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390_linux32v1;
+static void
+initialize_tdesc_s390_linux32v1 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+  tdesc_create_reg (feature, "pswm", 0, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "pswa", 1, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "r0", 2, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r1", 3, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r2", 4, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r3", 5, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r4", 6, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r5", 7, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r6", 8, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r7", 9, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r8", 10, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r9", 11, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r10", 12, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r11", 13, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r12", 14, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r13", 15, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r14", 16, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r15", 17, 1, "general", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+  tdesc_create_reg (feature, "acr0", 18, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr1", 19, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr2", 20, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr3", 21, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr4", 22, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr5", 23, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr6", 24, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr7", 25, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr8", 26, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr9", 27, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr10", 28, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr11", 29, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr12", 30, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr13", 31, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr14", 32, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr15", 33, 1, "access", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+  tdesc_create_reg (feature, "fpc", 34, 1, "float", 32, "uint32");
+  tdesc_create_reg (feature, "f0", 35, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 36, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 37, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 38, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 39, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 40, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 41, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 42, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 43, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 44, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 45, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 46, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 47, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 48, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 51, 1, "system", 32, "uint32");
+  tdesc_create_reg (feature, "last_break", 52, 0, "system", 32, "code_ptr");
+
+  tdesc_s390_linux32v1 = result;
+}
Index: gdb-head/gdb/features/s390-linux32v1.xml
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux32v1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- S/390 31-bit user-level code on a machine operating
+     in ESA/390 architecture mode.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>s390:31-bit</architecture>
+  <xi:include href="s390-core32.xml"/>
+  <xi:include href="s390-acr.xml"/>
+  <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="32" type="uint32" group="system"/>
+    <reg name="last_break" bitsize="32" type="code_ptr" group="system" save-restore="no"/>
+  </feature>
+</target>
Index: gdb-head/gdb/features/s390-linux32v2.c
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux32v2.c
@@ -0,0 +1,80 @@
+/* THIS FILE IS GENERATED.  Original: s390-linux32v2.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390_linux32v2;
+static void
+initialize_tdesc_s390_linux32v2 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+  tdesc_create_reg (feature, "pswm", 0, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "pswa", 1, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "r0", 2, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r1", 3, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r2", 4, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r3", 5, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r4", 6, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r5", 7, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r6", 8, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r7", 9, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r8", 10, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r9", 11, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r10", 12, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r11", 13, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r12", 14, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r13", 15, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r14", 16, 1, "general", 32, "uint32");
+  tdesc_create_reg (feature, "r15", 17, 1, "general", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+  tdesc_create_reg (feature, "acr0", 18, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr1", 19, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr2", 20, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr3", 21, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr4", 22, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr5", 23, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr6", 24, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr7", 25, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr8", 26, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr9", 27, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr10", 28, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr11", 29, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr12", 30, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr13", 31, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr14", 32, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr15", 33, 1, "access", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+  tdesc_create_reg (feature, "fpc", 34, 1, "float", 32, "uint32");
+  tdesc_create_reg (feature, "f0", 35, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 36, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 37, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 38, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 39, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 40, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 41, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 42, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 43, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 44, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 45, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 46, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 47, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 48, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 51, 1, "system", 32, "uint32");
+  tdesc_create_reg (feature, "last_break", 52, 0, "system", 32, "code_ptr");
+  tdesc_create_reg (feature, "system_call", 53, 1, "system", 32, "uint32");
+
+  tdesc_s390_linux32v2 = result;
+}
Index: gdb-head/gdb/features/s390-linux32v2.xml
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux32v2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- S/390 31-bit user-level code on a machine operating
+     in ESA/390 architecture mode.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>s390:31-bit</architecture>
+  <xi:include href="s390-core32.xml"/>
+  <xi:include href="s390-acr.xml"/>
+  <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="32" type="uint32" group="system"/>
+    <reg name="last_break" bitsize="32" type="code_ptr" group="system" save-restore="no"/>
+    <reg name="system_call" bitsize="32" type="uint32" group="system"/>
+  </feature>
+</target>
Index: gdb-head/gdb/features/s390-linux64v1.c
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux64v1.c
@@ -0,0 +1,95 @@
+/* THIS FILE IS GENERATED.  Original: s390-linux64v1.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390_linux64v1;
+static void
+initialize_tdesc_s390_linux64v1 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+  tdesc_create_reg (feature, "pswm", 0, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "pswa", 1, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "r0h", 2, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r0l", 3, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r1h", 4, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r1l", 5, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r2h", 6, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r2l", 7, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r3h", 8, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r3l", 9, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r4h", 10, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r4l", 11, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r5h", 12, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r5l", 13, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r6h", 14, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r6l", 15, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r7h", 16, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r7l", 17, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r8h", 18, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r8l", 19, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r9h", 20, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r9l", 21, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r10h", 22, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r10l", 23, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r11h", 24, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r11l", 25, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r12h", 26, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r12l", 27, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r13h", 28, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r13l", 29, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r14h", 30, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r14l", 31, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r15h", 32, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r15l", 33, 1, "lower", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+  tdesc_create_reg (feature, "acr0", 34, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr1", 35, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr2", 36, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr3", 37, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr4", 38, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr5", 39, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr6", 40, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr7", 41, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr8", 42, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr9", 43, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr10", 44, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr11", 45, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr12", 46, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr13", 47, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr14", 48, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr15", 49, 1, "access", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+  tdesc_create_reg (feature, "fpc", 50, 1, "float", 32, "uint32");
+  tdesc_create_reg (feature, "f0", 51, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 52, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 53, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 54, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 55, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 56, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 57, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 58, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 59, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 60, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 61, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 62, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 63, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 64, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 65, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 66, 1, "float", 64, "ieee_double");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 67, 1, "system", 32, "uint32");
+  tdesc_create_reg (feature, "last_break", 68, 0, "system", 32, "code_ptr");
+
+  tdesc_s390_linux64v1 = result;
+}
Index: gdb-head/gdb/features/s390-linux64v1.xml
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux64v1.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- S/390 31-bit user-level code on a machine operating
+     in z/Architecture mode.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>s390:31-bit</architecture>
+  <xi:include href="s390-core64.xml"/>
+  <xi:include href="s390-acr.xml"/>
+  <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="32" type="uint32" group="system"/>
+    <reg name="last_break" bitsize="32" type="code_ptr" group="system" save-restore="no"/>
+  </feature>
+</target>
Index: gdb-head/gdb/features/s390-linux64v2.c
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux64v2.c
@@ -0,0 +1,96 @@
+/* THIS FILE IS GENERATED.  Original: s390-linux64v2.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390_linux64v2;
+static void
+initialize_tdesc_s390_linux64v2 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("s390:31-bit"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+  tdesc_create_reg (feature, "pswm", 0, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "pswa", 1, 1, "psw", 32, "uint32");
+  tdesc_create_reg (feature, "r0h", 2, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r0l", 3, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r1h", 4, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r1l", 5, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r2h", 6, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r2l", 7, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r3h", 8, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r3l", 9, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r4h", 10, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r4l", 11, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r5h", 12, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r5l", 13, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r6h", 14, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r6l", 15, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r7h", 16, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r7l", 17, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r8h", 18, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r8l", 19, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r9h", 20, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r9l", 21, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r10h", 22, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r10l", 23, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r11h", 24, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r11l", 25, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r12h", 26, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r12l", 27, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r13h", 28, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r13l", 29, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r14h", 30, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r14l", 31, 1, "lower", 32, "uint32");
+  tdesc_create_reg (feature, "r15h", 32, 1, "upper", 32, "uint32");
+  tdesc_create_reg (feature, "r15l", 33, 1, "lower", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+  tdesc_create_reg (feature, "acr0", 34, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr1", 35, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr2", 36, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr3", 37, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr4", 38, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr5", 39, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr6", 40, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr7", 41, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr8", 42, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr9", 43, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr10", 44, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr11", 45, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr12", 46, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr13", 47, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr14", 48, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr15", 49, 1, "access", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+  tdesc_create_reg (feature, "fpc", 50, 1, "float", 32, "uint32");
+  tdesc_create_reg (feature, "f0", 51, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 52, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 53, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 54, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 55, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 56, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 57, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 58, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 59, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 60, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 61, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 62, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 63, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 64, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 65, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 66, 1, "float", 64, "ieee_double");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 67, 1, "system", 32, "uint32");
+  tdesc_create_reg (feature, "last_break", 68, 0, "system", 32, "code_ptr");
+  tdesc_create_reg (feature, "system_call", 69, 1, "system", 32, "uint32");
+
+  tdesc_s390_linux64v2 = result;
+}
Index: gdb-head/gdb/features/s390-linux64v2.xml
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390-linux64v2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- S/390 31-bit user-level code on a machine operating
+     in z/Architecture mode.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>s390:31-bit</architecture>
+  <xi:include href="s390-core64.xml"/>
+  <xi:include href="s390-acr.xml"/>
+  <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="32" type="uint32" group="system"/>
+    <reg name="last_break" bitsize="32" type="code_ptr" group="system" save-restore="no"/>
+    <reg name="system_call" bitsize="32" type="uint32" group="system"/>
+  </feature>
+</target>
Index: gdb-head/gdb/features/s390x-linux64v1.c
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390x-linux64v1.c
@@ -0,0 +1,79 @@
+/* THIS FILE IS GENERATED.  Original: s390x-linux64v1.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390x_linux64v1;
+static void
+initialize_tdesc_s390x_linux64v1 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+  tdesc_create_reg (feature, "pswm", 0, 1, "psw", 64, "uint64");
+  tdesc_create_reg (feature, "pswa", 1, 1, "psw", 64, "uint64");
+  tdesc_create_reg (feature, "r0", 2, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r1", 3, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r2", 4, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r3", 5, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r4", 6, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r5", 7, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r6", 8, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r7", 9, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r8", 10, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r9", 11, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r10", 12, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r11", 13, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r12", 14, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r13", 15, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r14", 16, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r15", 17, 1, "general", 64, "uint64");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+  tdesc_create_reg (feature, "acr0", 18, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr1", 19, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr2", 20, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr3", 21, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr4", 22, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr5", 23, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr6", 24, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr7", 25, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr8", 26, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr9", 27, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr10", 28, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr11", 29, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr12", 30, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr13", 31, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr14", 32, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr15", 33, 1, "access", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+  tdesc_create_reg (feature, "fpc", 34, 1, "float", 32, "uint32");
+  tdesc_create_reg (feature, "f0", 35, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 36, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 37, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 38, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 39, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 40, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 41, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 42, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 43, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 44, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 45, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 46, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 47, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 48, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 51, 1, "system", 64, "uint64");
+  tdesc_create_reg (feature, "last_break", 52, 0, "system", 64, "code_ptr");
+
+  tdesc_s390x_linux64v1 = result;
+}
Index: gdb-head/gdb/features/s390x-linux64v1.xml
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390x-linux64v1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- S/390 64-bit user-level code.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>s390:64-bit</architecture>
+  <xi:include href="s390x-core64.xml"/>
+  <xi:include href="s390-acr.xml"/>
+  <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="64" type="uint64" group="system"/>
+    <reg name="last_break" bitsize="64" type="code_ptr" group="system" save-restore="no"/>
+  </feature>
+</target>
Index: gdb-head/gdb/features/s390x-linux64v2.c
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390x-linux64v2.c
@@ -0,0 +1,80 @@
+/* THIS FILE IS GENERATED.  Original: s390x-linux64v2.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_s390x_linux64v2;
+static void
+initialize_tdesc_s390x_linux64v2 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct tdesc_type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("s390:64-bit"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.core");
+  tdesc_create_reg (feature, "pswm", 0, 1, "psw", 64, "uint64");
+  tdesc_create_reg (feature, "pswa", 1, 1, "psw", 64, "uint64");
+  tdesc_create_reg (feature, "r0", 2, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r1", 3, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r2", 4, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r3", 5, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r4", 6, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r5", 7, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r6", 8, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r7", 9, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r8", 10, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r9", 11, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r10", 12, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r11", 13, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r12", 14, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r13", 15, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r14", 16, 1, "general", 64, "uint64");
+  tdesc_create_reg (feature, "r15", 17, 1, "general", 64, "uint64");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.acr");
+  tdesc_create_reg (feature, "acr0", 18, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr1", 19, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr2", 20, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr3", 21, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr4", 22, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr5", 23, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr6", 24, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr7", 25, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr8", 26, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr9", 27, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr10", 28, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr11", 29, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr12", 30, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr13", 31, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr14", 32, 1, "access", 32, "uint32");
+  tdesc_create_reg (feature, "acr15", 33, 1, "access", 32, "uint32");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.fpr");
+  tdesc_create_reg (feature, "fpc", 34, 1, "float", 32, "uint32");
+  tdesc_create_reg (feature, "f0", 35, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 36, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 37, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 38, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 39, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 40, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 41, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 42, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 43, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 44, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 45, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 46, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 47, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 48, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 51, 1, "system", 64, "uint64");
+  tdesc_create_reg (feature, "last_break", 52, 0, "system", 64, "code_ptr");
+  tdesc_create_reg (feature, "system_call", 53, 1, "system", 32, "uint32");
+
+  tdesc_s390x_linux64v2 = result;
+}
Index: gdb-head/gdb/features/s390x-linux64v2.xml
===================================================================
--- /dev/null
+++ gdb-head/gdb/features/s390x-linux64v2.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- S/390 64-bit user-level code.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>s390:64-bit</architecture>
+  <xi:include href="s390x-core64.xml"/>
+  <xi:include href="s390-acr.xml"/>
+  <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="64" type="uint64" group="system"/>
+    <reg name="last_break" bitsize="64" type="code_ptr" group="system" save-restore="no"/>
+    <reg name="system_call" bitsize="32" type="uint32" group="system"/>
+  </feature>
+</target>
Index: gdb-head/gdb/regformats/s390-linux32v1.dat
===================================================================
--- /dev/null
+++ gdb-head/gdb/regformats/s390-linux32v1.dat
@@ -0,0 +1,57 @@
+# DO NOT EDIT: generated from s390-linux32v1.xml
+name:s390_linux32v1
+xmltarget:s390-linux32v1.xml
+expedite:r14,r15,pswa
+32:pswm
+32:pswa
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+32:orig_r2
+32:last_break
Index: gdb-head/gdb/regformats/s390-linux32v2.dat
===================================================================
--- /dev/null
+++ gdb-head/gdb/regformats/s390-linux32v2.dat
@@ -0,0 +1,58 @@
+# DO NOT EDIT: generated from s390-linux32v2.xml
+name:s390_linux32v2
+xmltarget:s390-linux32v2.xml
+expedite:r14,r15,pswa
+32:pswm
+32:pswa
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+32:orig_r2
+32:last_break
+32:system_call
Index: gdb-head/gdb/regformats/s390-linux64v1.dat
===================================================================
--- /dev/null
+++ gdb-head/gdb/regformats/s390-linux64v1.dat
@@ -0,0 +1,73 @@
+# DO NOT EDIT: generated from s390-linux64v1.xml
+name:s390_linux64v1
+xmltarget:s390-linux64v1.xml
+expedite:r14l,r15l,pswa
+32:pswm
+32:pswa
+32:r0h
+32:r0l
+32:r1h
+32:r1l
+32:r2h
+32:r2l
+32:r3h
+32:r3l
+32:r4h
+32:r4l
+32:r5h
+32:r5l
+32:r6h
+32:r6l
+32:r7h
+32:r7l
+32:r8h
+32:r8l
+32:r9h
+32:r9l
+32:r10h
+32:r10l
+32:r11h
+32:r11l
+32:r12h
+32:r12l
+32:r13h
+32:r13l
+32:r14h
+32:r14l
+32:r15h
+32:r15l
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+32:orig_r2
+32:last_break
Index: gdb-head/gdb/regformats/s390-linux64v2.dat
===================================================================
--- /dev/null
+++ gdb-head/gdb/regformats/s390-linux64v2.dat
@@ -0,0 +1,74 @@
+# DO NOT EDIT: generated from s390-linux64v2.xml
+name:s390_linux64v2
+xmltarget:s390-linux64v2.xml
+expedite:r14l,r15l,pswa
+32:pswm
+32:pswa
+32:r0h
+32:r0l
+32:r1h
+32:r1l
+32:r2h
+32:r2l
+32:r3h
+32:r3l
+32:r4h
+32:r4l
+32:r5h
+32:r5l
+32:r6h
+32:r6l
+32:r7h
+32:r7l
+32:r8h
+32:r8l
+32:r9h
+32:r9l
+32:r10h
+32:r10l
+32:r11h
+32:r11l
+32:r12h
+32:r12l
+32:r13h
+32:r13l
+32:r14h
+32:r14l
+32:r15h
+32:r15l
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+32:orig_r2
+32:last_break
+32:system_call
Index: gdb-head/gdb/regformats/s390x-linux64v1.dat
===================================================================
--- /dev/null
+++ gdb-head/gdb/regformats/s390x-linux64v1.dat
@@ -0,0 +1,57 @@
+# DO NOT EDIT: generated from s390x-linux64v1.xml
+name:s390x_linux64v1
+xmltarget:s390x-linux64v1.xml
+expedite:r14,r15,pswa
+64:pswm
+64:pswa
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:orig_r2
+64:last_break
Index: gdb-head/gdb/regformats/s390x-linux64v2.dat
===================================================================
--- /dev/null
+++ gdb-head/gdb/regformats/s390x-linux64v2.dat
@@ -0,0 +1,58 @@
+# DO NOT EDIT: generated from s390x-linux64v2.xml
+name:s390x_linux64v2
+xmltarget:s390x-linux64v2.xml
+expedite:r14,r15,pswa
+64:pswm
+64:pswa
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+32:acr0
+32:acr1
+32:acr2
+32:acr3
+32:acr4
+32:acr5
+32:acr6
+32:acr7
+32:acr8
+32:acr9
+32:acr10
+32:acr11
+32:acr12
+32:acr13
+32:acr14
+32:acr15
+32:fpc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:orig_r2
+64:last_break
+32:system_call
Index: gdb-head/gdb/features/s390-linux32.c
===================================================================
--- gdb-head.orig/gdb/features/s390-linux32.c
+++ gdb-head/gdb/features/s390-linux32.c
@@ -71,5 +71,8 @@ initialize_tdesc_s390_linux32 (void)
   tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double");
   tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double");
 
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 51, 1, "system", 32, "uint32");
+
   tdesc_s390_linux32 = result;
 }
Index: gdb-head/gdb/features/s390-linux64.c
===================================================================
--- gdb-head.orig/gdb/features/s390-linux64.c
+++ gdb-head/gdb/features/s390-linux64.c
@@ -87,5 +87,8 @@ initialize_tdesc_s390_linux64 (void)
   tdesc_create_reg (feature, "f14", 65, 1, "float", 64, "ieee_double");
   tdesc_create_reg (feature, "f15", 66, 1, "float", 64, "ieee_double");
 
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 67, 1, "system", 32, "uint32");
+
   tdesc_s390_linux64 = result;
 }
Index: gdb-head/gdb/features/s390x-linux64.c
===================================================================
--- gdb-head.orig/gdb/features/s390x-linux64.c
+++ gdb-head/gdb/features/s390x-linux64.c
@@ -71,5 +71,8 @@ initialize_tdesc_s390x_linux64 (void)
   tdesc_create_reg (feature, "f14", 49, 1, "float", 64, "ieee_double");
   tdesc_create_reg (feature, "f15", 50, 1, "float", 64, "ieee_double");
 
+  feature = tdesc_create_feature (result, "org.gnu.gdb.s390.linux");
+  tdesc_create_reg (feature, "orig_r2", 51, 1, "system", 64, "uint64");
+
   tdesc_s390x_linux64 = result;
 }
Index: gdb-head/gdb/features/s390-linux32.xml
===================================================================
--- gdb-head.orig/gdb/features/s390-linux32.xml
+++ gdb-head/gdb/features/s390-linux32.xml
@@ -14,4 +14,8 @@
   <xi:include href="s390-core32.xml"/>
   <xi:include href="s390-acr.xml"/>
   <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="32" type="uint32" group="system"/>
+  </feature>
 </target>
Index: gdb-head/gdb/features/s390-linux64.xml
===================================================================
--- gdb-head.orig/gdb/features/s390-linux64.xml
+++ gdb-head/gdb/features/s390-linux64.xml
@@ -14,4 +14,8 @@
   <xi:include href="s390-core64.xml"/>
   <xi:include href="s390-acr.xml"/>
   <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="32" type="uint32" group="system"/>
+  </feature>
 </target>
Index: gdb-head/gdb/features/s390x-linux64.xml
===================================================================
--- gdb-head.orig/gdb/features/s390x-linux64.xml
+++ gdb-head/gdb/features/s390x-linux64.xml
@@ -13,4 +13,8 @@
   <xi:include href="s390x-core64.xml"/>
   <xi:include href="s390-acr.xml"/>
   <xi:include href="s390-fpr.xml"/>
+
+  <feature name="org.gnu.gdb.s390.linux">
+    <reg name="orig_r2" bitsize="64" type="uint64" group="system"/>
+  </feature>
 </target>
Index: gdb-head/gdb/regformats/s390-linux32.dat
===================================================================
--- gdb-head.orig/gdb/regformats/s390-linux32.dat
+++ gdb-head/gdb/regformats/s390-linux32.dat
@@ -53,3 +53,4 @@ expedite:r14,r15,pswa
 64:f13
 64:f14
 64:f15
+32:orig_r2
Index: gdb-head/gdb/regformats/s390-linux64.dat
===================================================================
--- gdb-head.orig/gdb/regformats/s390-linux64.dat
+++ gdb-head/gdb/regformats/s390-linux64.dat
@@ -69,3 +69,4 @@ expedite:r14l,r15l,pswa
 64:f13
 64:f14
 64:f15
+32:orig_r2
Index: gdb-head/gdb/regformats/s390x-linux64.dat
===================================================================
--- gdb-head.orig/gdb/regformats/s390x-linux64.dat
+++ gdb-head/gdb/regformats/s390x-linux64.dat
@@ -53,3 +53,4 @@ expedite:r14,r15,pswa
 64:f13
 64:f14
 64:f15
+64:orig_r2
Index: gdb-head/gdb/gdbserver/linux-s390-low.c
===================================================================
--- gdb-head.orig/gdb/gdbserver/linux-s390-low.c
+++ gdb-head/gdb/gdbserver/linux-s390-low.c
@@ -22,22 +22,45 @@
 
 #include "server.h"
 #include "linux-low.h"
+#include "elf/common.h"
 
 #include <asm/ptrace.h>
+#include <sys/ptrace.h>
+#include <sys/uio.h>
 #include <elf.h>
 
 #ifndef HWCAP_S390_HIGH_GPRS
 #define HWCAP_S390_HIGH_GPRS 512
 #endif
 
+#ifndef PTRACE_GETREGSET
+#define PTRACE_GETREGSET 0x4204
+#endif
+
+#ifndef PTRACE_SETREGSET
+#define PTRACE_SETREGSET 0x4205
+#endif
+
 /* Defined in auto-generated file s390-linux32.c.  */
 void init_registers_s390_linux32 (void);
+/* Defined in auto-generated file s390-linux32v1.c.  */
+void init_registers_s390_linux32v1 (void);
+/* Defined in auto-generated file s390-linux32v2.c.  */
+void init_registers_s390_linux32v2 (void);
 /* Defined in auto-generated file s390-linux64.c.  */
 void init_registers_s390_linux64 (void);
+/* Defined in auto-generated file s390-linux64v1.c.  */
+void init_registers_s390_linux64v1 (void);
+/* Defined in auto-generated file s390-linux64v2.c.  */
+void init_registers_s390_linux64v2 (void);
 /* Defined in auto-generated file s390x-linux64.c.  */
 void init_registers_s390x_linux64 (void);
+/* Defined in auto-generated file s390x-linux64v1.c.  */
+void init_registers_s390x_linux64v1 (void);
+/* Defined in auto-generated file s390x-linux64v2.c.  */
+void init_registers_s390x_linux64v2 (void);
 
-#define s390_num_regs 51
+#define s390_num_regs 52
 
 static int s390_regmap[] = {
   PT_PSWMASK, PT_PSWADDR,
@@ -65,10 +88,12 @@ static int s390_regmap[] = {
   PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
   PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
 #endif
+
+  PT_ORIGGPR2,
 };
 
 #ifdef __s390x__
-#define s390_num_regs_3264 67
+#define s390_num_regs_3264 68
 
 static int s390_regmap_3264[] = {
   PT_PSWMASK, PT_PSWADDR,
@@ -93,6 +118,8 @@ static int s390_regmap_3264[] = {
   PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
   PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
   PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
+
+  PT_ORIGGPR2,
 };
 #endif
 
@@ -143,7 +170,8 @@ s390_collect_ptrace_register (struct reg
 	  collect_register (regcache, regno, buf + sizeof (long) - size);
 	  buf[sizeof (long) - size] &= ~0x80;
 	}
-      else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
+      else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
+	       || regaddr == PT_ORIGGPR2)
 	collect_register (regcache, regno, buf + sizeof (long) - size);
       else
 	collect_register (regcache, regno, buf);
@@ -196,7 +224,8 @@ s390_supply_ptrace_register (struct regc
 	  addr[0] |= amode;
 	  supply_register (regcache, regno, addr);
 	}
-      else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
+      else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
+	       || regaddr == PT_ORIGGPR2)
 	supply_register (regcache, regno, buf + sizeof (long) - size);
       else
 	supply_register (regcache, regno, buf);
@@ -223,8 +252,40 @@ static void s390_fill_gregset (struct re
     }
 }
 
+/* Fill and store functions for extended register sets.  */
+
+static void
+s390_fill_last_break (struct regcache *regcache, void *buf)
+{
+  /* Last break address is read-only.  */
+}
+
+static void
+s390_store_last_break (struct regcache *regcache, const void *buf)
+{
+  supply_register_by_name (regcache, "last_break",
+			   (const char *)buf + 8 - register_size (0));
+}
+
+static void
+s390_fill_system_call (struct regcache *regcache, void *buf)
+{
+  collect_register_by_name (regcache, "system_call", buf);
+}
+
+static void
+s390_store_system_call (struct regcache *regcache, const void *buf)
+{
+  supply_register_by_name (regcache, "system_call", buf);
+}
+
 struct regset_info target_regsets[] = {
   { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
+  /* Last break address is read-only; do not attempt PTRACE_SETREGSET.  */
+  { PTRACE_GETREGSET, PTRACE_GETREGSET, NT_S390_LAST_BREAK, 0,
+    EXTENDED_REGS, s390_fill_last_break, s390_store_last_break },
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_SYSTEM_CALL, 0,
+    EXTENDED_REGS, s390_fill_system_call, s390_store_system_call },
   { 0, 0, 0, -1, -1, NULL, NULL }
 };
 
@@ -296,11 +357,56 @@ s390_get_hwcap (void)
 }
 #endif
 
+static int
+s390_check_regset (int pid, int regset, int regsize)
+{
+  gdb_byte *buf = alloca (regsize);
+  struct iovec iov;
+
+  iov.iov_base = buf;
+  iov.iov_len = regsize;
+
+  if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) < 0)
+    return 0;
+  else
+    return 1;
+}
+
 static void
 s390_arch_setup (void)
 {
+  struct regset_info *regset;
+
+  /* Check whether the kernel supports extra register sets.  */
+  int pid = pid_of (get_thread_lwp (current_inferior));
+  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);
+
+  /* Update target_regsets according to available register sets.  */
+  for (regset = target_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;
+	default:
+	  break;
+	}
+
   /* Assume 31-bit inferior process.  */
-  init_registers_s390_linux32 ();
+  if (have_regset_system_call)
+    init_registers_s390_linux32v2 ();
+  else if (have_regset_last_break)
+    init_registers_s390_linux32v1 ();
+  else
+    init_registers_s390_linux32 ();
+
   the_low_target.num_regs = s390_num_regs;
   the_low_target.regmap = s390_regmap;
 
@@ -315,13 +421,26 @@ s390_arch_setup (void)
     free_register_cache (regcache);
 
     if (pswm & 1)
-      init_registers_s390x_linux64 ();
+      {
+	if (have_regset_system_call)
+	  init_registers_s390x_linux64v2 ();
+	else if (have_regset_last_break)
+	  init_registers_s390x_linux64v1 ();
+	else
+	  init_registers_s390x_linux64 ();
+      }
 
     /* For a 31-bit inferior, check whether the kernel supports
        using the full 64-bit GPRs.  */
     else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
       {
-        init_registers_s390_linux64 ();
+	if (have_regset_system_call)
+	  init_registers_s390_linux64v2 ();
+	else if (have_regset_last_break)
+	  init_registers_s390_linux64v1 ();
+	else
+	  init_registers_s390_linux64 ();
+
 	the_low_target.num_regs = s390_num_regs_3264;
 	the_low_target.regmap = s390_regmap_3264;
       }
Index: gdb-head/gdb/gdbserver/Makefile.in
===================================================================
--- gdb-head.orig/gdb/gdbserver/Makefile.in
+++ gdb-head/gdb/gdbserver/Makefile.in
@@ -594,12 +594,30 @@ powerpc-isa205-vsx64l.c : $(srcdir)/../r
 s390-linux32.o : s390-linux32.c $(regdef_h)
 s390-linux32.c : $(srcdir)/../regformats/s390-linux32.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux32.dat s390-linux32.c
+s390-linux32v1.o : s390-linux32v1.c $(regdef_h)
+s390-linux32v1.c : $(srcdir)/../regformats/s390-linux32v1.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux32v1.dat s390-linux32v1.c
+s390-linux32v2.o : s390-linux32v2.c $(regdef_h)
+s390-linux32v2.c : $(srcdir)/../regformats/s390-linux32v2.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux32v2.dat s390-linux32v2.c
 s390-linux64.o : s390-linux64.c $(regdef_h)
 s390-linux64.c : $(srcdir)/../regformats/s390-linux64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux64.dat s390-linux64.c
+s390-linux64v1.o : s390-linux64v1.c $(regdef_h)
+s390-linux64v1.c : $(srcdir)/../regformats/s390-linux64v1.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux64v1.dat s390-linux64v1.c
+s390-linux64v2.o : s390-linux64v2.c $(regdef_h)
+s390-linux64v2.c : $(srcdir)/../regformats/s390-linux64v2.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390-linux64v2.dat s390-linux64v2.c
 s390x-linux64.o : s390x-linux64.c $(regdef_h)
 s390x-linux64.c : $(srcdir)/../regformats/s390x-linux64.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-linux64.dat s390x-linux64.c
+s390x-linux64v1.o : s390x-linux64v1.c $(regdef_h)
+s390x-linux64v1.c : $(srcdir)/../regformats/s390x-linux64v1.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-linux64v1.dat s390x-linux64v1.c
+s390x-linux64v2.o : s390x-linux64v2.c $(regdef_h)
+s390x-linux64v2.c : $(srcdir)/../regformats/s390x-linux64v2.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/s390x-linux64v2.dat s390x-linux64v2.c
 
 tic6x-c64xp-linux.o : tic6x-c64xp-linux.c $(regdef_h)
 tic6x-c64xp-linux.c : $(srcdir)/../regformats/tic6x-c64xp-linux.dat $(regdat_sh)
Index: gdb-head/gdb/gdbserver/configure.srv
===================================================================
--- gdb-head.orig/gdb/gdbserver/configure.srv
+++ gdb-head/gdb/gdbserver/configure.srv
@@ -214,12 +214,24 @@ case "${target}" in
 			srv_lynxos=yes
 			;;
   s390*-*-linux*)	srv_regobj="s390-linux32.o"
+			srv_regobj="${srv_regobj} s390-linux32v1.o"
+			srv_regobj="${srv_regobj} s390-linux32v2.o"
 			srv_regobj="${srv_regobj} s390-linux64.o"
+			srv_regobj="${srv_regobj} s390-linux64v1.o"
+			srv_regobj="${srv_regobj} s390-linux64v2.o"
 			srv_regobj="${srv_regobj} s390x-linux64.o"
+			srv_regobj="${srv_regobj} s390x-linux64v1.o"
+			srv_regobj="${srv_regobj} s390x-linux64v2.o"
 			srv_tgtobj="linux-low.o linux-osdata.o linux-s390-low.o linux-procfs.o"
 			srv_xmlfiles="s390-linux32.xml"
+			srv_xmlfiles="${srv_xmlfiles} s390-linux32v1.xml"
+			srv_xmlfiles="${srv_xmlfiles} s390-linux32v2.xml"
 			srv_xmlfiles="${srv_xmlfiles} s390-linux64.xml"
+			srv_xmlfiles="${srv_xmlfiles} s390-linux64v1.xml"
+			srv_xmlfiles="${srv_xmlfiles} s390-linux64v2.xml"
 			srv_xmlfiles="${srv_xmlfiles} s390x-linux64.xml"
+			srv_xmlfiles="${srv_xmlfiles} s390x-linux64v1.xml"
+			srv_xmlfiles="${srv_xmlfiles} s390x-linux64v2.xml"
 			srv_xmlfiles="${srv_xmlfiles} s390-core32.xml"
 			srv_xmlfiles="${srv_xmlfiles} s390-core64.xml"
 			srv_xmlfiles="${srv_xmlfiles} s390x-core64.xml"
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]