diff options
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/Makefile | 3 | ||||
-rw-r--r-- | lib/libc/aarch64/sys/__vdso_gettc.c | 12 | ||||
-rw-r--r-- | lib/libc/amd64/sys/Makefile.inc | 2 | ||||
-rw-r--r-- | lib/libc/amd64/sys/__vdso_gettc.c | 70 | ||||
-rw-r--r-- | lib/libc/arm/sys/__vdso_gettc.c | 15 | ||||
-rw-r--r-- | lib/libc/i386/sys/Makefile.inc | 3 | ||||
-rw-r--r-- | lib/libc/sys/__vdso_gettimeofday.c | 23 | ||||
-rw-r--r-- | lib/libc/sys/trivial-vdso_tc.c | 6 | ||||
-rw-r--r-- | lib/libc/x86/sys/Makefile.inc | 6 | ||||
-rw-r--r-- | lib/libc/x86/sys/__vdso_gettc.c (renamed from lib/libc/i386/sys/__vdso_gettc.c) | 103 |
10 files changed, 130 insertions, 113 deletions
diff --git a/lib/libc/Makefile b/lib/libc/Makefile index e511c9b..2e17ec4 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -110,6 +110,9 @@ NOASM= ${LIBC_ARCH} == "mips" .include "${LIBC_SRCTOP}/softfloat/Makefile.inc" .endif +.if ${LIBC_ARCH} == "i386" || ${LIBC_ARCH} == "amd64" +.include "${LIBC_SRCTOP}/x86/sys/Makefile.inc" +.endif .if ${MK_NIS} != "no" CFLAGS+= -DYP .include "${LIBC_SRCTOP}/yp/Makefile.inc" diff --git a/lib/libc/aarch64/sys/__vdso_gettc.c b/lib/libc/aarch64/sys/__vdso_gettc.c index f9015e2..85e1b2e 100644 --- a/lib/libc/aarch64/sys/__vdso_gettc.c +++ b/lib/libc/aarch64/sys/__vdso_gettc.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/time.h> #include <sys/vdso.h> #include <machine/cpufunc.h> +#include <errno.h> #include "libc_private.h" static inline uint64_t @@ -55,14 +56,15 @@ cp15_cntpct_get(void) } #pragma weak __vdso_gettc -u_int -__vdso_gettc(const struct vdso_timehands *th) +int +__vdso_gettc(const struct vdso_timehands *th, u_int *tc) { - uint64_t val; + if (th->th_algo != VDSO_TH_ALGO_ARM_GENTIM) + return (ENOSYS); __asm __volatile("isb" : : : "memory"); - val = th->th_physical == 0 ? cp15_cntvct_get() : cp15_cntpct_get(); - return (val); + *tc = th->th_physical == 0 ? cp15_cntvct_get() : cp15_cntpct_get(); + return (0); } #pragma weak __vdso_gettimekeep diff --git a/lib/libc/amd64/sys/Makefile.inc b/lib/libc/amd64/sys/Makefile.inc index d5d416f..078a017 100644 --- a/lib/libc/amd64/sys/Makefile.inc +++ b/lib/libc/amd64/sys/Makefile.inc @@ -2,7 +2,7 @@ # $FreeBSD$ SRCS+= amd64_get_fsbase.c amd64_get_gsbase.c amd64_set_fsbase.c \ - amd64_set_gsbase.c __vdso_gettc.c + amd64_set_gsbase.c MDASM= vfork.S brk.S cerror.S exect.S getcontext.S \ sbrk.S setlogin.S sigreturn.S diff --git a/lib/libc/amd64/sys/__vdso_gettc.c b/lib/libc/amd64/sys/__vdso_gettc.c deleted file mode 100644 index 1899b21..0000000 --- a/lib/libc/amd64/sys/__vdso_gettc.c +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org> - * - * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/elf.h> -#include <sys/time.h> -#include <sys/vdso.h> -#include <machine/cpufunc.h> -#include "libc_private.h" - -static u_int -__vdso_gettc_low(const struct vdso_timehands *th) -{ - u_int rv; - - __asm __volatile("lfence; rdtsc; shrd %%cl, %%edx, %0" - : "=a" (rv) : "c" (th->th_x86_shift) : "edx"); - return (rv); -} - -static u_int -__vdso_rdtsc32(void) -{ - u_int rv; - - __asm __volatile("lfence;rdtsc" : "=a" (rv) : : "edx"); - return (rv); -} - -#pragma weak __vdso_gettc -u_int -__vdso_gettc(const struct vdso_timehands *th) -{ - - return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) : - __vdso_rdtsc32()); -} - -#pragma weak __vdso_gettimekeep -int -__vdso_gettimekeep(struct vdso_timekeep **tk) -{ - - return (_elf_aux_info(AT_TIMEKEEP, tk, sizeof(*tk))); -} diff --git a/lib/libc/arm/sys/__vdso_gettc.c b/lib/libc/arm/sys/__vdso_gettc.c index 1f43e72..9f8631d 100644 --- a/lib/libc/arm/sys/__vdso_gettc.c +++ b/lib/libc/arm/sys/__vdso_gettc.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/vdso.h> #include <machine/cpufunc.h> #include <machine/acle-compat.h> +#include <errno.h> #include "libc_private.h" #if __ARM_ARCH >= 6 @@ -58,11 +59,12 @@ cp15_cntpct_get(void) #endif #pragma weak __vdso_gettc -u_int -__vdso_gettc(const struct vdso_timehands *th) +int +__vdso_gettc(const struct vdso_timehands *th, u_int *tc) { - uint64_t val; + if (th->th_algo != VDSO_TH_ALGO_ARM_GENTIM) + return (ENOSYS); #if __ARM_ARCH >= 6 /* * Userspace gettimeofday() is only enabled on ARMv7 CPUs, but @@ -70,11 +72,12 @@ __vdso_gettc(const struct vdso_timehands *th) * armv7-a directive does not work. */ __asm __volatile(".word\t0xf57ff06f" : : : "memory"); /* isb */ - val = th->th_physical == 0 ? cp15_cntvct_get() : cp15_cntpct_get(); + *tc = th->th_physical == 0 ? cp15_cntvct_get() : cp15_cntpct_get(); + return (0); #else - val = 0; + *tc = 0; + return (ENOSYS); #endif - return (val); } #pragma weak __vdso_gettimekeep diff --git a/lib/libc/i386/sys/Makefile.inc b/lib/libc/i386/sys/Makefile.inc index 9bc2a56..3f96bd9 100644 --- a/lib/libc/i386/sys/Makefile.inc +++ b/lib/libc/i386/sys/Makefile.inc @@ -5,8 +5,7 @@ SRCS+= i386_clr_watch.c i386_set_watch.c i386_vm86.c .endif SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ioperm.c i386_get_ldt.c \ - i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c \ - __vdso_gettc.c + i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c MDASM= Ovfork.S brk.S cerror.S exect.S getcontext.S \ sbrk.S setlogin.S sigreturn.S syscall.S diff --git a/lib/libc/sys/__vdso_gettimeofday.c b/lib/libc/sys/__vdso_gettimeofday.c index b3527fa..0368b97 100644 --- a/lib/libc/sys/__vdso_gettimeofday.c +++ b/lib/libc/sys/__vdso_gettimeofday.c @@ -34,12 +34,16 @@ __FBSDID("$FreeBSD$"); #include <machine/atomic.h> #include "libc_private.h" -static u_int -tc_delta(const struct vdso_timehands *th) +static int +tc_delta(const struct vdso_timehands *th, u_int *delta) { + int error; + u_int tc; - return ((__vdso_gettc(th) - th->th_offset_count) & - th->th_counter_mask); + error = __vdso_gettc(th, &tc); + if (error == 0) + *delta = (tc - th->th_offset_count) & th->th_counter_mask; + return (error); } /* @@ -56,6 +60,8 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs) { struct vdso_timehands *th; uint32_t curr, gen; + u_int delta; + int error; do { if (!tk->tk_enabled) @@ -63,11 +69,14 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs) curr = atomic_load_acq_32(&tk->tk_current); th = &tk->tk_th[curr]; - if (th->th_algo != VDSO_TH_ALGO_1) - return (ENOSYS); gen = atomic_load_acq_32(&th->th_gen); *bt = th->th_offset; - bintime_addx(bt, th->th_scale * tc_delta(th)); + error = tc_delta(th, &delta); + if (error == EAGAIN) + continue; + if (error != 0) + return (error); + bintime_addx(bt, th->th_scale * delta); if (abs) bintime_add(bt, &th->th_boottime); diff --git a/lib/libc/sys/trivial-vdso_tc.c b/lib/libc/sys/trivial-vdso_tc.c index b99bbc4..ce0c144 100644 --- a/lib/libc/sys/trivial-vdso_tc.c +++ b/lib/libc/sys/trivial-vdso_tc.c @@ -32,11 +32,11 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #pragma weak __vdso_gettc -u_int -__vdso_gettc(const struct vdso_timehands *th) +int +__vdso_gettc(const struct vdso_timehands *th, u_int *tc) { - return (0); + return (ENOSYS); } #pragma weak __vdso_gettimekeep diff --git a/lib/libc/x86/sys/Makefile.inc b/lib/libc/x86/sys/Makefile.inc new file mode 100644 index 0000000..c00a217 --- /dev/null +++ b/lib/libc/x86/sys/Makefile.inc @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.PATH: ${LIBC_SRCTOP}/x86/sys + +SRCS+= \ + __vdso_gettc.c diff --git a/lib/libc/i386/sys/__vdso_gettc.c b/lib/libc/x86/sys/__vdso_gettc.c index 1454f16..743b3ad 100644 --- a/lib/libc/i386/sys/__vdso_gettc.c +++ b/lib/libc/x86/sys/__vdso_gettc.c @@ -1,5 +1,10 @@ /*- * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org> + * Copyright (c) 2016 The FreeBSD Foundation + * All rights reserved. + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,19 +31,27 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <sys/types.h> +#include <sys/param.h> +#include "namespace.h" #include <sys/elf.h> +#include <sys/fcntl.h> +#include <sys/mman.h> #include <sys/time.h> #include <sys/vdso.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include "un-namespace.h" #include <machine/cpufunc.h> #include <machine/specialreg.h> +#include <dev/acpica/acpi_hpet.h> #include "libc_private.h" -static int lfence_works = -1; - -static int -get_lfence_usage(void) +static void +lfence_mb(void) { +#if defined(__i386__) + static int lfence_works = -1; u_int cpuid_supported, p[4]; if (lfence_works == -1) { @@ -57,7 +70,7 @@ get_lfence_usage(void) " jmp 2f\n" "1: movl $0,%0\n" "2:\n" - : "=r" (cpuid_supported) : : "eax", "ecx"); + : "=r" (cpuid_supported) : : "eax", "ecx", "cc"); if (cpuid_supported) { __asm __volatile( " pushl %%ebx\n" @@ -70,16 +83,21 @@ get_lfence_usage(void) } else lfence_works = 0; } - return (lfence_works); + if (lfence_works == 1) + lfence(); +#elif defined(__amd64__) + lfence(); +#else +#error "arch" +#endif } static u_int -__vdso_gettc_low(const struct vdso_timehands *th) +__vdso_gettc_rdtsc_low(const struct vdso_timehands *th) { u_int rv; - if (get_lfence_usage() == 1) - lfence(); + lfence_mb(); __asm __volatile("rdtsc; shrd %%cl, %%edx, %0" : "=a" (rv) : "c" (th->th_x86_shift) : "edx"); return (rv); @@ -88,21 +106,68 @@ __vdso_gettc_low(const struct vdso_timehands *th) static u_int __vdso_rdtsc32(void) { - u_int rv; - if (get_lfence_usage() == 1) - lfence(); - rv = rdtsc32(); - return (rv); + lfence_mb(); + return (rdtsc32()); +} + +static char *hpet_dev_map = NULL; +static uint32_t hpet_idx = 0xffffffff; + +static void +__vdso_init_hpet(uint32_t u) +{ + static const char devprefix[] = "/dev/hpet"; + char devname[64], *c, *c1, t; + int fd; + + c1 = c = stpcpy(devname, devprefix); + u = hpet_idx; + do { + *c++ = u % 10 + '0'; + u /= 10; + } while (u != 0); + *c = '\0'; + for (c--; c1 != c; c1++, c--) { + t = *c1; + *c1 = *c; + *c = t; + } + fd = _open(devname, O_RDONLY); + if (fd == -1) { + hpet_dev_map = MAP_FAILED; + return; + } + if (hpet_dev_map != NULL && hpet_dev_map != MAP_FAILED) + munmap(hpet_dev_map, PAGE_SIZE); + hpet_dev_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0); + _close(fd); } #pragma weak __vdso_gettc -u_int -__vdso_gettc(const struct vdso_timehands *th) +int +__vdso_gettc(const struct vdso_timehands *th, u_int *tc) { + uint32_t tmp; - return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) : - __vdso_rdtsc32()); + switch (th->th_algo) { + case VDSO_TH_ALGO_X86_TSC: + *tc = th->th_x86_shift > 0 ? __vdso_gettc_rdtsc_low(th) : + __vdso_rdtsc32(); + return (0); + case VDSO_TH_ALGO_X86_HPET: + tmp = th->th_x86_hpet_idx; + if (hpet_dev_map == NULL || tmp != hpet_idx) { + hpet_idx = tmp; + __vdso_init_hpet(hpet_idx); + } + if (hpet_dev_map == MAP_FAILED) + return (ENOSYS); + *tc = *(volatile uint32_t *)(hpet_dev_map + HPET_MAIN_COUNTER); + return (0); + default: + return (ENOSYS); + } } #pragma weak __vdso_gettimekeep |