Unify i386 and amd64 getcontextx.c, and use ifuncs while there.
In particular, use ifuncs for __getcontextx_size(), also calculate the size of the extended save area in resolver. Same for __fillcontextx2(). Sponsored by: The FreeBSD Foundation MFC after: 1 week
This commit is contained in:
parent
b5d72efb7a
commit
071bca67ee
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=344120
@ -122,6 +122,7 @@ NOASM=
|
||||
.endif
|
||||
.if ${LIBC_ARCH} == "i386" || ${LIBC_ARCH} == "amd64"
|
||||
.include "${LIBC_SRCTOP}/x86/sys/Makefile.inc"
|
||||
.include "${LIBC_SRCTOP}/x86/gen/Makefile.inc"
|
||||
.endif
|
||||
.if ${MK_NIS} != "no"
|
||||
CFLAGS+= -DYP
|
||||
|
@ -2,7 +2,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SRCS+= _setjmp.S _set_tp.c rfork_thread.S setjmp.S sigsetjmp.S \
|
||||
fabs.S getcontextx.c \
|
||||
fabs.S \
|
||||
infinity.c ldexp.c makecontext.c signalcontext.c \
|
||||
flt_rounds.c fpgetmask.c fpsetmask.c fpgetprec.c fpsetprec.c \
|
||||
fpgetround.c fpsetround.c fpgetsticky.c
|
||||
|
@ -2,5 +2,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SRCS+= _ctx_start.S _setjmp.S _set_tp.c fabs.S \
|
||||
flt_rounds.c getcontextx.c infinity.c ldexp.c makecontext.c \
|
||||
flt_rounds.c infinity.c ldexp.c makecontext.c \
|
||||
rfork_thread.S setjmp.S signalcontext.c sigsetjmp.S
|
||||
|
@ -1,145 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2011 Konstantin Belousov <kib@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 <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <machine/npx.h>
|
||||
#include <machine/specialreg.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
static int xstate_sz = -1;
|
||||
|
||||
int
|
||||
__getcontextx_size(void)
|
||||
{
|
||||
u_int p[4];
|
||||
int cpuid_supported;
|
||||
|
||||
if (xstate_sz == -1) {
|
||||
__asm __volatile(
|
||||
" pushfl\n"
|
||||
" popl %%eax\n"
|
||||
" movl %%eax,%%ecx\n"
|
||||
" xorl $0x200000,%%eax\n"
|
||||
" pushl %%eax\n"
|
||||
" popfl\n"
|
||||
" pushfl\n"
|
||||
" popl %%eax\n"
|
||||
" xorl %%eax,%%ecx\n"
|
||||
" je 1f\n"
|
||||
" movl $1,%0\n"
|
||||
" jmp 2f\n"
|
||||
"1: movl $0,%0\n"
|
||||
"2:\n"
|
||||
: "=r" (cpuid_supported) : : "eax", "ecx");
|
||||
if (cpuid_supported) {
|
||||
__asm __volatile(
|
||||
" pushl %%ebx\n"
|
||||
" cpuid\n"
|
||||
" movl %%ebx,%1\n"
|
||||
" popl %%ebx\n"
|
||||
: "=a" (p[0]), "=r" (p[1]), "=c" (p[2]), "=d" (p[3])
|
||||
: "0" (0x1));
|
||||
if ((p[2] & CPUID2_OSXSAVE) != 0) {
|
||||
__asm __volatile(
|
||||
" pushl %%ebx\n"
|
||||
" cpuid\n"
|
||||
" movl %%ebx,%1\n"
|
||||
" popl %%ebx\n"
|
||||
: "=a" (p[0]), "=r" (p[1]), "=c" (p[2]),
|
||||
"=d" (p[3])
|
||||
: "0" (0xd), "2" (0x0));
|
||||
xstate_sz = p[1] - sizeof(struct savexmm);
|
||||
} else
|
||||
xstate_sz = 0;
|
||||
} else
|
||||
xstate_sz = 0;
|
||||
}
|
||||
|
||||
return (sizeof(ucontext_t) + xstate_sz);
|
||||
}
|
||||
|
||||
int
|
||||
__fillcontextx2(char *ctx)
|
||||
{
|
||||
struct i386_get_xfpustate xfpu;
|
||||
ucontext_t *ucp;
|
||||
|
||||
ucp = (ucontext_t *)ctx;
|
||||
if (xstate_sz != 0) {
|
||||
xfpu.addr = (char *)(ucp + 1);
|
||||
xfpu.len = xstate_sz;
|
||||
if (sysarch(I386_GET_XFPUSTATE, &xfpu) == -1)
|
||||
return (-1);
|
||||
ucp->uc_mcontext.mc_xfpustate = (__register_t)xfpu.addr;
|
||||
ucp->uc_mcontext.mc_xfpustate_len = xstate_sz;
|
||||
ucp->uc_mcontext.mc_flags |= _MC_HASFPXSTATE;
|
||||
} else {
|
||||
ucp->uc_mcontext.mc_xfpustate = 0;
|
||||
ucp->uc_mcontext.mc_xfpustate_len = 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
__fillcontextx(char *ctx)
|
||||
{
|
||||
ucontext_t *ucp;
|
||||
|
||||
ucp = (ucontext_t *)ctx;
|
||||
if (getcontext(ucp) == -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);
|
||||
}
|
6
lib/libc/x86/gen/Makefile.inc
Normal file
6
lib/libc/x86/gen/Makefile.inc
Normal file
@ -0,0 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${LIBC_SRCTOP}/x86/gen
|
||||
|
||||
SRCS+= \
|
||||
getcontextx.c
|
@ -35,51 +35,78 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/fpu.h>
|
||||
#include <machine/specialreg.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <x86/ifunc.h>
|
||||
#include <x86/fpu.h>
|
||||
|
||||
static int xstate_sz = -1;
|
||||
#if defined __i386__
|
||||
#define X86_GET_XFPUSTATE I386_GET_XFPUSTATE
|
||||
typedef struct savexmm savex86_t ;
|
||||
typedef struct i386_get_xfpustate x86_get_xfpustate_t;
|
||||
#elif defined __amd64__
|
||||
#define X86_GET_XFPUSTATE AMD64_GET_XFPUSTATE
|
||||
typedef struct savefpu savex86_t;
|
||||
typedef struct amd64_get_xfpustate x86_get_xfpustate_t;
|
||||
#else
|
||||
#error "Wrong arch"
|
||||
#endif
|
||||
|
||||
int
|
||||
__getcontextx_size(void)
|
||||
static int xstate_sz = 0;
|
||||
|
||||
static int
|
||||
__getcontextx_size_xfpu(void)
|
||||
{
|
||||
u_int p[4];
|
||||
|
||||
if (xstate_sz == -1) {
|
||||
do_cpuid(1, p);
|
||||
if ((p[2] & CPUID2_OSXSAVE) != 0) {
|
||||
cpuid_count(0xd, 0x0, p);
|
||||
xstate_sz = p[1] - sizeof(struct savefpu);
|
||||
} else
|
||||
xstate_sz = 0;
|
||||
}
|
||||
|
||||
return (sizeof(ucontext_t) + xstate_sz);
|
||||
}
|
||||
|
||||
int
|
||||
__fillcontextx2(char *ctx)
|
||||
DEFINE_UIFUNC(, int, __getcontextx_size, (void), static)
|
||||
{
|
||||
struct amd64_get_xfpustate xfpu;
|
||||
u_int p[4];
|
||||
|
||||
if ((cpu_feature2 & CPUID2_OSXSAVE) != 0) {
|
||||
cpuid_count(0xd, 0x0, p);
|
||||
xstate_sz = p[1] - sizeof(savex86_t);
|
||||
}
|
||||
return (__getcontextx_size_xfpu);
|
||||
}
|
||||
|
||||
static int
|
||||
__fillcontextx2_xfpu(char *ctx)
|
||||
{
|
||||
x86_get_xfpustate_t xfpu;
|
||||
ucontext_t *ucp;
|
||||
|
||||
ucp = (ucontext_t *)ctx;
|
||||
if (xstate_sz != 0) {
|
||||
xfpu.addr = (char *)(ucp + 1);
|
||||
xfpu.len = xstate_sz;
|
||||
if (sysarch(AMD64_GET_XFPUSTATE, &xfpu) == -1)
|
||||
return (-1);
|
||||
ucp->uc_mcontext.mc_xfpustate = (__register_t)xfpu.addr;
|
||||
ucp->uc_mcontext.mc_xfpustate_len = xstate_sz;
|
||||
ucp->uc_mcontext.mc_flags |= _MC_HASFPXSTATE;
|
||||
} else {
|
||||
ucp->uc_mcontext.mc_xfpustate = 0;
|
||||
ucp->uc_mcontext.mc_xfpustate_len = 0;
|
||||
}
|
||||
xfpu.addr = (char *)(ucp + 1);
|
||||
xfpu.len = xstate_sz;
|
||||
if (sysarch(X86_GET_XFPUSTATE, &xfpu) == -1)
|
||||
return (-1);
|
||||
ucp->uc_mcontext.mc_xfpustate = (__register_t)xfpu.addr;
|
||||
ucp->uc_mcontext.mc_xfpustate_len = xstate_sz;
|
||||
ucp->uc_mcontext.mc_flags |= _MC_HASFPXSTATE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
__fillcontextx2_noxfpu(char *ctx)
|
||||
{
|
||||
ucontext_t *ucp;
|
||||
|
||||
ucp = (ucontext_t *)ctx;
|
||||
ucp->uc_mcontext.mc_xfpustate = 0;
|
||||
ucp->uc_mcontext.mc_xfpustate_len = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
DEFINE_UIFUNC(, int, __fillcontextx2, (char *), static)
|
||||
{
|
||||
|
||||
return ((cpu_feature2 & CPUID2_OSXSAVE) != 0 ? __fillcontextx2_xfpu :
|
||||
__fillcontextx2_noxfpu);
|
||||
}
|
||||
|
||||
int
|
||||
__fillcontextx(char *ctx)
|
||||
{
|
Loading…
Reference in New Issue
Block a user