diff options
author | Michal Meloun <mmel@FreeBSD.org> | 2017-10-16 12:53:54 +0000 |
---|---|---|
committer | Michal Meloun <mmel@FreeBSD.org> | 2017-10-16 12:53:54 +0000 |
commit | a86d7982105eac5572e6dcd9d7bd1a0b124d3c71 (patch) | |
tree | 3406f247c0666a6edaaf0bd2f7a0f09c170adfb5 /lib/libc/arm/gen | |
parent | 0c40a4ac6166e4525e2ff3aa5dfe16807d8fefcb (diff) |
Save VFP state in getcontext(3) on ARM.
This is a last followup of r315974, which fixes userland part
of VFP save/restore problems described in PR 217611.
PR: 217611
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=324660
Diffstat (limited to 'lib/libc/arm/gen')
-rw-r--r-- | lib/libc/arm/gen/Makefile.inc | 2 | ||||
-rw-r--r-- | lib/libc/arm/gen/getcontextx.c | 99 |
2 files changed, 100 insertions, 1 deletions
diff --git a/lib/libc/arm/gen/Makefile.inc b/lib/libc/arm/gen/Makefile.inc index 95b1bba4c12f..05f3e95889a5 100644 --- a/lib/libc/arm/gen/Makefile.inc +++ b/lib/libc/arm/gen/Makefile.inc @@ -5,7 +5,7 @@ SRCS+= _ctx_start.S _setjmp.S _set_tp.c alloca.S fabs.c \ infinity.c ldexp.c makecontext.c \ __aeabi_read_tp.S setjmp.S signalcontext.c sigsetjmp.S flt_rounds.c \ arm_initfini.c \ - trivial-getcontextx.c + getcontextx.c .if ${MACHINE_ARCH:Marmv[67]*} && (!defined(CPUTYPE) || ${CPUTYPE:M*soft*} == "") SRCS+= fpgetmask_vfp.c fpgetround_vfp.c fpgetsticky_vfp.c fpsetmask_vfp.c \ diff --git a/lib/libc/arm/gen/getcontextx.c b/lib/libc/arm/gen/getcontextx.c new file mode 100644 index 000000000000..3092e2818e92 --- /dev/null +++ b/lib/libc/arm/gen/getcontextx.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2017 Michal Meloun <mmel@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/ucontext.h> +#include <errno.h> +#include <stdlib.h> +#include <machine/sysarch.h> + +struct ucontextx { + ucontext_t ucontext; + mcontext_vfp_t mcontext_vfp; +}; + +int +__getcontextx_size(void) +{ + + return (sizeof(struct ucontextx)); +} + +int +__fillcontextx2(char *ctx) +{ + struct ucontextx *ucxp; + ucontext_t *ucp; + mcontext_vfp_t *mvp; + struct arm_get_vfpstate_args vfp_arg; + + ucxp = (struct ucontextx *)ctx; + ucp = &ucxp->ucontext; + mvp = &ucxp->mcontext_vfp; + + vfp_arg.mc_vfp_size = sizeof(mcontext_vfp_t); + vfp_arg.mc_vfp = mvp; + if (sysarch(ARM_GET_VFPSTATE, &vfp_arg) == -1) + return (-1); + ucp->uc_mcontext.mc_vfp_size = sizeof(mcontext_vfp_t); + ucp->uc_mcontext.mc_vfp_ptr = mvp; + return (0); +} + +int +__fillcontextx(char *ctx) +{ + struct ucontextx *ucxp; + + ucxp = (struct ucontextx *)ctx; + if (getcontext(&ucxp->ucontext) == -1) + return (-1); + __fillcontextx2(ctx); + return (0); +} + +__weak_reference(__getcontextx, getcontextx); + +ucontext_t * +__getcontextx(void) +{ + char *ctx; + int error; + + ctx = malloc(__getcontextx_size()); + if (ctx == NULL) + return (NULL); + if (__fillcontextx(ctx) == -1) { + error = errno; + free(ctx); + errno = error; + return (NULL); + } + return ((ucontext_t *)ctx); +} |