S/390: Make ucontext_t extendible.

This commit is contained in:
Andreas Krebbel 2014-01-07 09:37:31 +01:00
parent 93a45ff1ca
commit 05d138ef07
17 changed files with 328 additions and 17 deletions

View File

@ -1,3 +1,41 @@
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.

View File

@ -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

View File

@ -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)

View File

@ -1,6 +1,7 @@
libc {
GLIBC_2.19 {
__longjmp_chk;
getcontext;
}
GLIBC_PRIVATE {
__vdso_clock_gettime;

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -1781,6 +1781,7 @@ GLIBC_2.19
__sigsetjmp F
_longjmp F
_setjmp F
getcontext F
longjmp F
setjmp F
siglongjmp F

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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)

View File

@ -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)

View File

@ -102,6 +102,7 @@ GLIBC_2.19
__sigsetjmp F
_longjmp F
_setjmp F
getcontext F
longjmp F
setjmp F
siglongjmp F

View File

@ -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. */

View File

@ -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];
};