about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>2014-01-07 09:37:31 +0100
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>2014-01-07 09:42:23 +0100
commit05d138ef07481b16f1aaee648798cc51182ec65e (patch)
tree1b3641bd6db26d0a000aa899b69b7107463b65e5
parent93a45ff1ca6d459618bb0cf93580c4b2809a4b61 (diff)
downloadglibc-05d138ef07481b16f1aaee648798cc51182ec65e.tar.gz
glibc-05d138ef07481b16f1aaee648798cc51182ec65e.tar.xz
glibc-05d138ef07481b16f1aaee648798cc51182ec65e.zip
S/390: Make ucontext_t extendible.
-rw-r--r--ChangeLog38
-rw-r--r--sysdeps/s390/Makefile4
-rw-r--r--sysdeps/s390/rtld-global-offsets.sym7
-rw-r--r--sysdeps/unix/sysv/linux/s390/Versions1
-rw-r--r--sysdeps/unix/sysv/linux/s390/getcontext.S38
-rw-r--r--sysdeps/unix/sysv/linux/s390/rtld-getcontext.S19
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S (renamed from sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S)41
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S12
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S27
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/sys/ucontext.h96
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym26
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S (renamed from sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S)6
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S19
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/sys/ucontext.h (renamed from sysdeps/unix/sysv/linux/s390/sys/ucontext.h)9
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym (renamed from sysdeps/unix/sysv/linux/s390/ucontext_i.sym)0
17 files changed, 328 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index d6c0ddb464..a8b62e0a0e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,43 @@
 2014-01-07  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
+	* sysdeps/s390/Makefile: Build rtld-global-offsets.sym.
+	* sysdeps/s390/rtld-global-offsets.sym: New file.
+	* sysdeps/unix/sysv/linux/s390/Versions: Add getcontext as new
+	GLIBC_2.19 symbol.
+	* sysdeps/unix/sysv/linux/s390/getcontext.S: New file.
+	* sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S: Rename to ...
+	* sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S:
+	... this.
+	* sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S: Rename to ...
+	* sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S:
+	... this.
+	* sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist:
+	Regenerate.
+	* sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist:
+	Regenerate.
+	* sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S: Restore upper
+	halfs of GPRs for high_gprs contexts.
+	* sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S: Save and
+	restore upper halfs of GPRs for high_gprs contexts.  Copy uc_flags
+	field.
+	* sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S: Copy
+	uc_flags field.
+	* sysdeps/unix/sysv/linux/s390/sys/ucontext.h: Split into 32 and
+	64 bit versions:
+	* sysdeps/unix/sysv/linux/s390/s390-32/sys/ucontext.h: Add field
+	for high GPRs (uc_high_gprs) and for future extensions
+	(__reserved).
+	* sysdeps/unix/sysv/linux/s390/s390-64/sys/ucontext.h: Add field
+	for future extensions (__reserved).
+	* sysdeps/unix/sysv/linux/s390/ucontext_i.sym: Split into 32 and
+	64 bit versions:
+	* sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym: Add
+	SC_HIGHGPRS offset definition.
+	* sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym: New file.
+	* sysdeps/unix/sysv/linux/s390/rtld-getcontext.S: New file.
+
+2014-01-07  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
 	* Versions.def: Add GLIBC_2.19 for libpthread.
 	* nptl/sysdeps/unix/sysv/linux/s390/Versions: Add longjmp and
 	siglongjmp for libpthread with GLIBC_2.19 symver.
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
index fdc6ee50dc..42978dc8b2 100644
--- a/sysdeps/s390/Makefile
+++ b/sysdeps/s390/Makefile
@@ -3,3 +3,7 @@ ifeq (yes,$(build-shared))
 sysdep_routines += v1-longjmp v1-sigjmp
 endif
 endif
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += rtld-global-offsets.sym
+endif
diff --git a/sysdeps/s390/rtld-global-offsets.sym b/sysdeps/s390/rtld-global-offsets.sym
new file mode 100644
index 0000000000..ff4e97f2a6
--- /dev/null
+++ b/sysdeps/s390/rtld-global-offsets.sym
@@ -0,0 +1,7 @@
+#define SHARED 1
+
+#include <ldsodefs.h>
+
+#define rtld_global_ro_offsetof(mem) offsetof (struct rtld_global_ro, mem)
+
+RTLD_GLOBAL_RO_DL_HWCAP_OFFSET	rtld_global_ro_offsetof (_dl_hwcap)
diff --git a/sysdeps/unix/sysv/linux/s390/Versions b/sysdeps/unix/sysv/linux/s390/Versions
index 95778235bf..f71a6bd2c3 100644
--- a/sysdeps/unix/sysv/linux/s390/Versions
+++ b/sysdeps/unix/sysv/linux/s390/Versions
@@ -1,6 +1,7 @@
 libc {
   GLIBC_2.19 {
     __longjmp_chk;
+    getcontext;
   }
   GLIBC_PRIVATE {
     __vdso_clock_gettime;
diff --git a/sysdeps/unix/sysv/linux/s390/getcontext.S b/sysdeps/unix/sysv/linux/s390/getcontext.S
new file mode 100644
index 0000000000..5edbf95ccb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/getcontext.S
@@ -0,0 +1,38 @@
+/* Extendible version of getcontext for System z
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <libc-symbols.h>
+#include <shlib-compat.h>
+
+versioned_symbol (libc, __v2getcontext, getcontext, GLIBC_2_19)
+#define __getcontext __v2getcontext
+
+#include "getcontext-common.S"
+
+#undef __getcontext
+
+libc_hidden_ver (__v2getcontext, getcontext)
+
+#if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_1, GLIBC_2_19)
+# define __V1_UCONTEXT
+compat_symbol (libc, __v1getcontext, getcontext, GLIBC_2_1)
+# define __getcontext __v1getcontext
+# include "getcontext-common.S"
+# undef __getcontext
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/s390/rtld-getcontext.S b/sysdeps/unix/sysv/linux/s390/rtld-getcontext.S
new file mode 100644
index 0000000000..653f2b656f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/rtld-getcontext.S
@@ -0,0 +1,19 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Build a non-versioned object for rtld-*.  */
+#include "getcontext-common.S"
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S b/sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S
index ce2d99430b..4992030239 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/getcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/getcontext-common.S
@@ -19,6 +19,7 @@
 #include <sysdep.h>
 #include <features.h>
 
+#include "rtld-global-offsets.h"
 #include "ucontext_i.h"
 
 /*  __getcontext (const ucontext_t *ucp)
@@ -33,10 +34,10 @@
 ENTRY(__getcontext)
 	lr      %r1,%r2
 
-	/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask, sigsetsize).  */
 	la      %r2,SIG_BLOCK
 	slr	%r3,%r3
-	la	%r4,SC_MASK(%r1)
+	la      %r4,SC_MASK(%r1)
 	lhi	%r5,_NSIG8
 	svc	SYS_ify(rt_sigprocmask)
 
@@ -59,6 +60,42 @@ ENTRY(__getcontext)
 	std     %f14,SC_FPRS+112(%r1)
 	std     %f15,SC_FPRS+120(%r1)
 
+	lhi	%r2,0
+#ifndef __V1_UCONTEXT
+	bras	%r3,0f
+# ifdef IS_IN_rtld
+  /* Within ld.so we can do slightly better by addressing dl_hwap
+     relative to GOT start.  */
+1:	.long	_GLOBAL_OFFSET_TABLE_ - 1b
+	.long	C_SYMBOL_NAME(_rtld_global_ro)@GOTOFF
+0:	l	%r4,0(%r3)
+	la	%r4,0(%r3,%r4)
+	l	%r5,4(%r3)
+	/* _dl_hwcap is 64 bit and we need the lower 32.  */
+	l	%r3,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(%r4,%r5)
+# elif PIC
+1:	.long	_GLOBAL_OFFSET_TABLE_ - 1b
+	.long	C_SYMBOL_NAME(_rtld_global_ro)@GOT
+0:	l	%r4,0(%r3)
+	la	%r4,0(%r3,%r4)  /* GOT pointer -> r4 */
+	l	%r5,4(%r3)      /* GOT offset -> r5 */
+	l	%r5,0(%r4,%r5)  /* GOT slot -> r5 */
+	l	%r3,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(%r5)
+# else
+	.long	C_SYMBOL_NAME(_dl_hwcap)
+0:	l	%r3,0(%r3)
+	l	%r3,0(%r3)
+# endif
+	tml	%r3,512 /* HWCAP_S390_HIGH_GPRS */
+	jz	2f
+	/* highgprs implies zarch so stmh/oill is ok here.  */
+	.machine "z900"
+	.machinemode "zarch_nohighgprs"
+	stmh	%r0,%r15,SC_HIGHGPRS(%r1)
+	oill	%r2,1 /* UCONTEXT_UC_FLAGS_HIGH_GPRS */
+#endif
+2:	st	%r2,SC_FLGS(%r1)
+
 	/* Set __getcontext return value to 0.  */
 	slr     %r2,%r2
 
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
index 18ec9944e1..03f2e83805 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/nptl/libc.abilist
@@ -1781,6 +1781,7 @@ GLIBC_2.19
  __sigsetjmp F
  _longjmp F
  _setjmp F
+ getcontext F
  longjmp F
  setjmp F
  siglongjmp F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S b/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
index 3008f8e4af..fbe8b77caf 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
@@ -33,7 +33,7 @@
 ENTRY(__setcontext)
 	lr	%r1,%r2
 
-	/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
+	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
 	la      %r2,SIG_BLOCK
 	la	%r3,SC_MASK(%r1)
 	slr	%r4,%r4
@@ -62,8 +62,16 @@ ENTRY(__setcontext)
 	/* Don't touch %a0, used for thread purposes.  */
 	lam	%a1,%a15,SC_ACRS+4(%r1)
 
+	/* Restore the upper halfs if available.  */
+	l	%r2,SC_FLGS(%r1)
+	tml	%r2,1   /* UCONTEXT_UC_FLAGS_HIGH_GPRS */
+	jz	0f
+	.machine	"z900"
+	.machinemode	"zarch_nohighgprs"
+	lmh	%r0,%r15,SC_HIGHGPRS(%r1)
+
 	/* Load general purpose registers.  */
-	lm	%r0,%r15,SC_GPRS(%r1)
+0:	lm	%r0,%r15,SC_GPRS(%r1)
 
 	/* Return.  */
 	br	%r14
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S b/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
index 6c40c994ef..41ede4b7b2 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
@@ -33,6 +33,9 @@
   other than the PRESERVED state.  */
 
 ENTRY(__swapcontext)
+	/* While not part of the ABI a system call never clobbers r0
+	   or r1.  So keeping the values here while calling
+	   rt_sigprocmask is ok.  */
 	lr	%r1,%r2
 	lr      %r0,%r3
 
@@ -62,19 +65,31 @@ ENTRY(__swapcontext)
 	std     %f14,SC_FPRS+112(%r1)
 	std     %f15,SC_FPRS+120(%r1)
 
-	/* Set __swapcontext return value to 0.  */
-	slr     %r2,%r2
-
 	/* Store access registers.  */
 	stam    %a0,%a15,SC_ACRS(%r1)
 
+	/* Set __swapcontext return value to 0.  */
+	slr     %r2,%r2
+
 	/* Store general purpose registers.  */
 	stm     %r0,%r15,SC_GPRS(%r1)
 
-	/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
-	la      %r2,SIG_BLOCK
+	/* Copy uc_flags into the new ucontext_t.  */
 	lr	%r5,%r0
-	la	%r3,SC_MASK(%r5)
+	l	%r2,SC_FLGS(%r5)
+	st	%r2,SC_FLGS(%r1)
+
+	/* Save/restore the upper halfs if necessary.  */
+	tml	%r2,1   /* UCONTEXT_UC_FLAGS_HIGH_GPRS */
+	jz	0f
+	.machine	"z900"
+	.machinemode	"zarch_nohighgprs"
+	stmh	%r0,%r15,SC_HIGHGPRS(%r1)
+	lmh	%r0,%r15,SC_HIGHGPRS(%r5)
+
+	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
+0:	la      %r2,SIG_BLOCK
+	la      %r3,SC_MASK(%r5)
 	slr	%r4,%r4
 	lhi	%r5,_NSIG8
 	svc	SYS_ify(rt_sigprocmask)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sys/ucontext.h b/sysdeps/unix/sysv/linux/s390/s390-32/sys/ucontext.h
new file mode 100644
index 0000000000..90adc2d1fc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sys/ucontext.h
@@ -0,0 +1,96 @@
+/* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+   Contributed by Denis Joseph Barrow (djbarrow@de.ibm.com).
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H	1
+/* Forward definition to avoid parse errors */
+struct ucontext;
+typedef struct ucontext ucontext_t;
+#include <features.h>
+#include <signal.h>
+
+/* We need the signal context definitions even if they are not used
+   included in <signal.h>.  */
+#include <bits/sigcontext.h>
+
+/* Type for a program status word.  */
+typedef struct
+{
+  unsigned long mask;
+  unsigned long addr;
+} __attribute__ ((__aligned__(8))) __psw_t;
+
+/* Type for a general-purpose register.  */
+typedef unsigned long greg_t;
+
+/* And the whole bunch of them.  We should have used `struct s390_regs',
+   but to avoid name space pollution and since the tradition says that
+   the register set is an array, we make gregset_t a simple array
+   that has the same size as s390_regs.  This is needed for the
+   elf_prstatus structure.  */
+#if __WORDSIZE == 64
+# define NGREG 27
+#else
+# define NGREG 36
+#endif
+/* Must match kernels psw_t alignment.  */
+typedef greg_t gregset_t[NGREG] __attribute__ ((__aligned__(8)));
+
+typedef union
+  {
+    double  d;
+    float   f;
+  } fpreg_t;
+
+/* Register set for the floating-point registers.  */
+typedef struct
+  {
+    unsigned int fpc;
+    fpreg_t fprs[16];
+  } fpregset_t;
+
+/* Bit is set if the uc_high_gprs field contains the upper halfs of
+   the 64 bit general purpose registers.  */
+#define UCONTEXT_UC_FLAGS_HIGH_GPRS (1UL << 0)
+
+/* A new uc_flags constant will be defined when actually making use of
+   the reserved space: UCONTEXT_UCFLAGS_RESERVED (1UL << 1).  */
+
+/* Context to describe whole processor state.  */
+typedef struct
+  {
+    __psw_t psw;
+    unsigned long gregs[16];
+    unsigned int aregs[16];
+    fpregset_t fpregs;
+  } mcontext_t;
+
+/* Userlevel context.  */
+struct ucontext
+  {
+    unsigned long int uc_flags;
+    struct ucontext *uc_link;
+    stack_t uc_stack;
+    mcontext_t uc_mcontext;
+    __sigset_t uc_sigmask;
+    unsigned long uc_high_gprs[16];
+    char __reserved[512];
+  };
+
+
+#endif /* sys/ucontext.h */
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym b/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym
new file mode 100644
index 0000000000..705c7ab6cf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/ucontext_i.sym
@@ -0,0 +1,26 @@
+#include <stddef.h>
+#include <signal.h>
+#include <sys/ucontext.h>
+
+--
+
+SIG_BLOCK
+SIG_UNBLOCK
+SIG_SETMASK
+
+_NSIG8          (_NSIG / 8)
+
+#define ucontext(member)	offsetof (ucontext_t, member)
+#define mcontext(member)	ucontext (uc_mcontext.member)
+
+SC_FLGS		ucontext (uc_flags)
+SC_LINK		ucontext (uc_link)
+SC_STCK		ucontext (uc_stack.ss_sp)
+SC_STSZ		ucontext (uc_stack.ss_size)
+SC_PSW		mcontext (psw)
+SC_GPRS		mcontext (gregs)
+SC_ACRS		mcontext (aregs)
+SC_FPC		mcontext (fpregs.fpc)
+SC_FPRS		mcontext (fpregs.fprs)
+SC_MASK		ucontext (uc_sigmask)
+SC_HIGHGPRS	ucontext (uc_high_gprs)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S b/sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S
index db271c5dc5..3e61e30702 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/getcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/getcontext-common.S
@@ -33,7 +33,7 @@
 ENTRY(__getcontext)
 	lgr     %r1,%r2
 
-	/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask).  */
+	/* rt_sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask, sigsetsize).  */
 	la      %r2,SIG_BLOCK
 	slgr	%r3,%r3
 	la	%r4,SC_MASK(%r1)
@@ -62,6 +62,10 @@ ENTRY(__getcontext)
 	/* Set __getcontext return value to 0.  */
 	slgr    %r2,%r2
 
+	/* Store the version number into the uc_flags field.  So far
+	   we do not make use of the reserved bytes so we store a zero.  */
+	stg	%r2,SC_FLGS(%r1)
+
 	/* Store access registers.  */
 	stam    %a0,%a15,SC_ACRS(%r1)
 
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
index 05b5286058..4576fc8d14 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/nptl/libc.abilist
@@ -102,6 +102,7 @@ GLIBC_2.19
  __sigsetjmp F
  _longjmp F
  _setjmp F
+ getcontext F
  longjmp F
  setjmp F
  siglongjmp F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S b/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
index ec92898964..ac74b6bc08 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
@@ -33,6 +33,9 @@
   other than the PRESERVED state.  */
 
 ENTRY(__swapcontext)
+	/* While not part of the ABI a system call never clobbers r0
+	   or r1.  So keeping the values here while calling
+	   rt_sigprocmask is ok.  */
 	lgr	%r1,%r2
 	lgr     %r0,%r3
 
@@ -62,21 +65,25 @@ ENTRY(__swapcontext)
 	std     %f14,SC_FPRS+112(%r1)
 	std     %f15,SC_FPRS+120(%r1)
 
-	/* Set __swapcontext return value to 0.  */
-	slgr     %r2,%r2
-
 	/* Store access registers.  */
 	stam    %a0,%a15,SC_ACRS(%r1)
 
+	/* Set __swapcontext return value to 0.  */
+	slgr	%r2,%r2
+
 	/* Store general purpose registers.  */
 	stmg    %r0,%r15,SC_GPRS(%r1)
 
-	/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL).  */
-	la      %r2,SIG_BLOCK
+	/* Copy uc_flags into the new ucontext_t.  */
 	lgr	%r5,%r0
+	lg	%r2,SC_FLGS(%r5)
+	stg	%r2,SC_FLGS(%r1)
+
+	/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize).  */
+	la      %r2,SIG_BLOCK
 	la	%r3,SC_MASK(%r5)
-	lghi	%r5,_NSIG8
 	slgr	%r4,%r4
+	lghi	%r5,_NSIG8
 	svc	SYS_ify(rt_sigprocmask)
 
 	/* Load fpu context.  */
diff --git a/sysdeps/unix/sysv/linux/s390/sys/ucontext.h b/sysdeps/unix/sysv/linux/s390/s390-64/sys/ucontext.h
index d528cb189d..b563e98f05 100644
--- a/sysdeps/unix/sysv/linux/s390/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sys/ucontext.h
@@ -64,6 +64,14 @@ typedef struct
     fpreg_t fprs[16];
   } fpregset_t;
 
+/* Bit 0 is reserved for the uc_high_gprs field only available in the
+   32 bit version of ucontext_t.  This bit will never be set for 64
+   bit.  */
+#define UCONTEXT_UC_FLAGS_HIGH_GPRS (1UL << 0)
+
+/* A new uc_flags constant will be defined when actually making use of
+   the reserved space: UCONTEXT_UCFLAGS_RESERVED (1UL << 1).  */
+
 /* Context to describe whole processor state.  */
 typedef struct
   {
@@ -81,6 +89,7 @@ struct ucontext
     stack_t uc_stack;
     mcontext_t uc_mcontext;
     __sigset_t uc_sigmask;
+    char reserved[512];
   };
 
 
diff --git a/sysdeps/unix/sysv/linux/s390/ucontext_i.sym b/sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym
index 6cc9f19624..6cc9f19624 100644
--- a/sysdeps/unix/sysv/linux/s390/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/ucontext_i.sym