summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux
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 /sysdeps/unix/sysv/linux
parent93a45ff1ca6d459618bb0cf93580c4b2809a4b61 (diff)
S/390: Make ucontext_t extendible.
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-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
14 files changed, 279 insertions, 17 deletions
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