summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/Makefile3
-rw-r--r--lib/libc/aarch64/sys/__vdso_gettc.c12
-rw-r--r--lib/libc/amd64/sys/Makefile.inc2
-rw-r--r--lib/libc/amd64/sys/__vdso_gettc.c70
-rw-r--r--lib/libc/arm/sys/__vdso_gettc.c15
-rw-r--r--lib/libc/i386/sys/Makefile.inc3
-rw-r--r--lib/libc/sys/__vdso_gettimeofday.c23
-rw-r--r--lib/libc/sys/trivial-vdso_tc.c6
-rw-r--r--lib/libc/x86/sys/Makefile.inc6
-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
OpenPOWER on IntegriCloud