userland clock_gettime proof of concept

classic Classic list List threaded Threaded
203 messages Options
1 ... 4567891011
Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Paul Irofti-4
On Fri, Jun 19, 2020 at 05:20:24PM +0300, Paul Irofti wrote:

> Hi Lucas,
>
> Will reply inline.
>
> > As a matter of syntax, there are quite some places with functions
> > without parameters defined as `f()` instead of `f(void)`.
>
> Sure. Good catch.
>
> > > + if (tc == NULL || tk_user < 1 || tk_user > TC_LAST)
> >
> > Shouldn't you check for >= TC_LAST in here? Otherwise you'll be reading
> > and invoking dragons in the following lines.
> >
> > *Unless*, the semantic meaning of TC_LAST is to indicate the last valid
> > index of get_tc[]. In that case, TC_LAST is defined to 3 in amd64,
> > instead of 2.
>
> You are correct. It should be >= TC_LAST. Fixed locally.
>
> As a note. This bit will be removed when I commit this. Here it is just for
> showing how we can support multiple clocks. On amd64 (at least for now) we
> will only have TSC support so all the functions above will also go away and
> tc_get_timecount will contain the rdtsc() code.
>
> The sparc64 bits that will follow this commit will have the correct idiom.

So the final diff looks like this (w/o the amd64 multiple clocks PoC).


diff --git lib/libc/arch/aarch64/gen/Makefile.inc lib/libc/arch/aarch64/gen/Makefile.inc
index a7b1b73f3ef..ee198f5d611 100644
--- lib/libc/arch/aarch64/gen/Makefile.inc
+++ lib/libc/arch/aarch64/gen/Makefile.inc
@@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
 SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
 SRCS+= fpclassifyl.c
 SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
-SRCS+= signbitl.c
+SRCS+= signbitl.c usertc.c
diff --git lib/libc/arch/aarch64/gen/usertc.c lib/libc/arch/aarch64/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/aarch64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/alpha/gen/Makefile.inc lib/libc/arch/alpha/gen/Makefile.inc
index a44599d2cab..2a8abd32b61 100644
--- lib/libc/arch/alpha/gen/Makefile.inc
+++ lib/libc/arch/alpha/gen/Makefile.inc
@@ -3,5 +3,5 @@
 
 SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
- fpsetround.c fpsetsticky.c
+ fpsetround.c fpsetsticky.c usertc.c
 SRCS+= sigsetjmp.S
diff --git lib/libc/arch/alpha/gen/usertc.c lib/libc/arch/alpha/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/alpha/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/amd64/gen/Makefile.inc lib/libc/arch/amd64/gen/Makefile.inc
index e995309ed71..f6349e2b974 100644
--- lib/libc/arch/amd64/gen/Makefile.inc
+++ lib/libc/arch/amd64/gen/Makefile.inc
@@ -2,6 +2,7 @@
 
 SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
  sigsetjmp.S
-SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
+SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \
+ usertc.c
 SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
  fpsetround.S fpsetsticky.S
diff --git lib/libc/arch/amd64/gen/usertc.c lib/libc/arch/amd64/gen/usertc.c
new file mode 100644
index 00000000000..fa0d10207d3
--- /dev/null
+++ lib/libc/arch/amd64/gen/usertc.c
@@ -0,0 +1,41 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+static inline uint
+rdtsc(void)
+{
+ uint32_t hi, lo;
+ asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((uint64_t)lo)|(((uint64_t)hi)<<32);
+}
+
+int
+tc_get_timecount(struct timekeep *tk, uint *tc)
+{
+ int tk_user = tk->tk_user;
+
+ if (tc == NULL || tk_user < 1 || tk_user >= TC_LAST)
+ return -1;
+
+ *tc = rdtsc();
+ return 0;
+}
+int (*const _tc_get_timecount)(struct timekeep *tk, uint *tc)
+ = tc_get_timecount;
diff --git lib/libc/arch/arm/gen/Makefile.inc lib/libc/arch/arm/gen/Makefile.inc
index 1b4ab2f3ae7..27090a0d9dc 100644
--- lib/libc/arch/arm/gen/Makefile.inc
+++ lib/libc/arch/arm/gen/Makefile.inc
@@ -2,5 +2,5 @@
 # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
 
 SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c infinity.c
-SRCS+= ldexp.c modf.c nan.c
+SRCS+= ldexp.c modf.c nan.c usertc.c
 SRCS+= setjmp.S _setjmp.S sigsetjmp.S
diff --git lib/libc/arch/arm/gen/usertc.c lib/libc/arch/arm/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/arm/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/hppa/gen/Makefile.inc lib/libc/arch/hppa/gen/Makefile.inc
index e0c864242fe..1fde24670f1 100644
--- lib/libc/arch/hppa/gen/Makefile.inc
+++ lib/libc/arch/hppa/gen/Makefile.inc
@@ -2,6 +2,6 @@
 
 SRCS+= setjmp.S
 SRCS+= fabs.c
-SRCS+= infinity.c ldexp.c modf.c nan.c
+SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
diff --git lib/libc/arch/hppa/gen/usertc.c lib/libc/arch/hppa/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/hppa/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/i386/gen/Makefile.inc lib/libc/arch/i386/gen/Makefile.inc
index 4c18e059581..b7dd30adccd 100644
--- lib/libc/arch/i386/gen/Makefile.inc
+++ lib/libc/arch/i386/gen/Makefile.inc
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
  modf.S nan.c setjmp.S sigsetjmp.S
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
 SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
diff --git lib/libc/arch/i386/gen/usertc.c lib/libc/arch/i386/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/i386/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/m88k/gen/Makefile.inc lib/libc/arch/m88k/gen/Makefile.inc
index cff75b8d425..d66f66af4af 100644
--- lib/libc/arch/m88k/gen/Makefile.inc
+++ lib/libc/arch/m88k/gen/Makefile.inc
@@ -1,7 +1,7 @@
 # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
 # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
 SRCS+= setjmp.S sigsetjmp.S
diff --git lib/libc/arch/m88k/gen/usertc.c lib/libc/arch/m88k/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/m88k/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/mips64/gen/Makefile.inc lib/libc/arch/mips64/gen/Makefile.inc
index 8cf1fc2d28a..839241a2069 100644
--- lib/libc/arch/mips64/gen/Makefile.inc
+++ lib/libc/arch/mips64/gen/Makefile.inc
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
diff --git lib/libc/arch/mips64/gen/usertc.c lib/libc/arch/mips64/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/mips64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/powerpc/gen/Makefile.inc lib/libc/arch/powerpc/gen/Makefile.inc
index 6b2e4613ee8..d4d7b00bff7 100644
--- lib/libc/arch/powerpc/gen/Makefile.inc
+++ lib/libc/arch/powerpc/gen/Makefile.inc
@@ -1,5 +1,5 @@
 SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c nan.c
-SRCS+= fabs.c
+SRCS+= fabs.c usertc.c
 SRCS+= fpgetmask.c fpsetmask.c
 SRCS+= fpgetround.c fpsetround.c
 SRCS+= fpgetsticky.c fpsetsticky.c
diff --git lib/libc/arch/powerpc/gen/usertc.c lib/libc/arch/powerpc/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/powerpc/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/sh/gen/Makefile.inc lib/libc/arch/sh/gen/Makefile.inc
index 55de1973b30..4724fb3a6a8 100644
--- lib/libc/arch/sh/gen/Makefile.inc
+++ lib/libc/arch/sh/gen/Makefile.inc
@@ -3,4 +3,4 @@
 SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S _setjmp.S
 SRCS+= sigsetjmp.S
 SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
- fpsetmask.c fpsetround.c fpsetsticky.c
+ fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
diff --git lib/libc/arch/sh/gen/usertc.c lib/libc/arch/sh/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/sh/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/arch/sparc64/gen/Makefile.inc lib/libc/arch/sparc64/gen/Makefile.inc
index 58259cedef6..a908e022954 100644
--- lib/libc/arch/sparc64/gen/Makefile.inc
+++ lib/libc/arch/sparc64/gen/Makefile.inc
@@ -3,5 +3,5 @@
 SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
  fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
- isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
+ isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
  mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
diff --git lib/libc/arch/sparc64/gen/usertc.c lib/libc/arch/sparc64/gen/usertc.c
new file mode 100644
index 00000000000..3bdea089284
--- /dev/null
+++ lib/libc/arch/sparc64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
index 131da4b2190..40e84771f86 100644
--- lib/libc/asr/asr.c
+++ lib/libc/asr/asr.c
@@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds, int timeout)
  struct timespec pollstart, pollend, elapsed;
  int r;
 
- if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
  return -1;
 
  while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
- if (clock_gettime(CLOCK_MONOTONIC, &pollend))
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
  return -1;
  timespecsub(&pollend, &pollstart, &elapsed);
  timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
@@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
  asr->a_rtime = 0;
  }
 
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
  return;
 
  if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
index 82de8fa33b7..02fd3013cc1 100644
--- lib/libc/crypt/bcrypt.c
+++ lib/libc/crypt/bcrypt.c
@@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
  char buf[_PASSWORD_LEN];
  int duration;
 
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
+ WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
  bcrypt_newhash("testpassword", r, buf, sizeof(buf));
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
+ WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
 
  duration = after.tv_sec - before.tv_sec;
  duration *= 1000000;
diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
index 270f54aada5..6f535853335 100644
--- lib/libc/dlfcn/init.c
+++ lib/libc/dlfcn/init.c
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 #include <sys/syscall.h>
+#include <sys/timetc.h> /* timekeep */
 
 #ifndef PIC
 #include <sys/mman.h>
@@ -45,8 +46,9 @@
 /* XXX should be in an include file shared with csu */
 char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void));
 
-/* provide definition for this */
+/* provide definitions for these */
 int _pagesize = 0;
+struct timekeep *_timekeep = NULL;
 
 /*
  * In dynamicly linked binaries environ and __progname are overriden by
@@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb)
  phnum = aux->au_v;
  break;
 #endif /* !PIC */
+ case AUX_openbsd_timekeep:
+ if (_tc_get_timecount) {
+ _timekeep = (void *)aux->au_v;
+ if (_timekeep->tk_version != TK_VERSION)
+ _timekeep = NULL;
+ }
+ break;
  }
  }
 
diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
index 1286a96fe40..32f86eda50f 100644
--- lib/libc/gen/auth_subr.c
+++ lib/libc/gen/auth_subr.c
@@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
 
  if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
  if (as->now.tv_sec == 0)
- gettimeofday(&as->now, NULL);
+ WRAP(gettimeofday)(&as->now, NULL);
  if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
  as->state &= ~AUTH_ALLOW;
  as->state |= AUTH_EXPIRED;
@@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
 
  if (as->pwd && (quad_t)as->pwd->pw_change) {
  if (as->now.tv_sec == 0)
- gettimeofday(&as->now, NULL);
+ WRAP(gettimeofday)(&as->now, NULL);
  if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
  as->state &= ~AUTH_ALLOW;
  as->state |= AUTH_PWEXPIRED;
diff --git lib/libc/gen/time.c lib/libc/gen/time.c
index 3bbd0d733d1..b3ce9a800f1 100644
--- lib/libc/gen/time.c
+++ lib/libc/gen/time.c
@@ -36,7 +36,7 @@ time(time_t *t)
 {
  struct timeval tt;
 
- if (gettimeofday(&tt, NULL) == -1)
+ if (WRAP(gettimeofday)(&tt, NULL) == -1)
  return (-1);
  if (t)
  *t = (time_t)tt.tv_sec;
diff --git lib/libc/gen/times.c lib/libc/gen/times.c
index 02e4dd44b5c..36841810d1b 100644
--- lib/libc/gen/times.c
+++ lib/libc/gen/times.c
@@ -52,7 +52,7 @@ times(struct tms *tp)
  return ((clock_t)-1);
  tp->tms_cutime = CONVTCK(ru.ru_utime);
  tp->tms_cstime = CONVTCK(ru.ru_stime);
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
  return ((clock_t)-1);
  return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK));
 }
diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
index 520a5954025..845cbe80356 100644
--- lib/libc/gen/timespec_get.c
+++ lib/libc/gen/timespec_get.c
@@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
 {
  switch (base) {
  case TIME_UTC:
- if (clock_gettime(CLOCK_REALTIME, ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
  return 0;
  break;
  default:
diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
index ed112320fa2..df717021cab 100644
--- lib/libc/hidden/sys/time.h
+++ lib/libc/hidden/sys/time.h
@@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
 PROTO_NORMAL(adjtime);
 PROTO_NORMAL(futimes);
 PROTO_NORMAL(getitimer);
-PROTO_NORMAL(gettimeofday);
+PROTO_WRAP(gettimeofday);
 PROTO_NORMAL(setitimer);
 PROTO_NORMAL(settimeofday);
 PROTO_NORMAL(utimes);
diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h
new file mode 100644
index 00000000000..243c0137a42
--- /dev/null
+++ lib/libc/hidden/sys/timetc.h
@@ -0,0 +1,38 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBC_SYS_TIMETC_H_
+#define _LIBC_SYS_TIMETC_H_
+
+#define _LIBC
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include_next <sys/timetc.h>
+
+__BEGIN_HIDDEN_DECLS
+extern struct timekeep *_timekeep;
+
+extern int (*const _tc_get_timecount)(struct timekeep *, uint *);
+
+int _microtime(struct timeval *, struct timekeep *);
+int _nanotime(struct timespec *, struct timekeep *);
+int _nanoruntime(struct timespec *, struct timekeep *);
+int _nanouptime(struct timespec *, struct timekeep *);
+__END_HIDDEN_DECLS
+
+#endif /* !_LIBC_SYS_TIMETC_H_ */
diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h
index 18c49f8fcb9..d8e1e0caf64 100644
--- lib/libc/hidden/time.h
+++ lib/libc/hidden/time.h
@@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r);
 PROTO_STD_DEPRECATED(clock);
 PROTO_DEPRECATED(clock_getcpuclockid);
 PROTO_NORMAL(clock_getres);
-PROTO_NORMAL(clock_gettime);
+PROTO_WRAP(clock_gettime);
 PROTO_NORMAL(clock_settime);
 PROTO_STD_DEPRECATED(ctime);
 PROTO_DEPRECATED(ctime_r);
diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c
index 763e420bb88..9babb28470a 100644
--- lib/libc/net/res_random.c
+++ lib/libc/net/res_random.c
@@ -219,7 +219,7 @@ res_initid(void)
  if (ru_prf != NULL)
  arc4random_buf(ru_prf, sizeof(*ru_prf));
 
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
  ru_reseed = ts.tv_sec + RU_OUT;
  ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
 }
@@ -232,7 +232,7 @@ __res_randomid(void)
  u_int r;
  static void *randomid_mutex;
 
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
  pid = getpid();
 
  _MUTEX_LOCK(&randomid_mutex);
diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c
index 402d98cede4..917a6d42b8a 100644
--- lib/libc/rpc/auth_unix.c
+++ lib/libc/rpc/auth_unix.c
@@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
  /*
  * fill in param struct from the given params
  */
- (void)gettimeofday(&now,  NULL);
+ (void)WRAP(gettimeofday)(&now,  NULL);
  aup.aup_time = now.tv_sec;
  aup.aup_machname = machname;
  aup.aup_uid = uid;
@@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth)
  goto done;
 
  /* update the time and serialize in place */
- (void)gettimeofday(&now, NULL);
+ (void)WRAP(gettimeofday)(&now, NULL);
  aup.aup_time = now.tv_sec;
  xdrs.x_op = XDR_ENCODE;
  XDR_SETPOS(&xdrs, 0);
diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c
index 8e6ef515b0e..927b4bf2028 100644
--- lib/libc/rpc/clnt_tcp.c
+++ lib/libc/rpc/clnt_tcp.c
@@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int len)
  pfd[0].events = POLLIN;
  TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait);
  delta = wait;
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  for (;;) {
  r = ppoll(pfd, 1, &delta, NULL);
  save_errno = errno;
 
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&start, &after, &duration);
  timespecsub(&wait, &duration, &delta);
  if (delta.tv_sec < 0 || !timespecisset(&delta))
diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c
index 68d01674410..92e1d5c350d 100644
--- lib/libc/rpc/clnt_udp.c
+++ lib/libc/rpc/clnt_udp.c
@@ -265,7 +265,7 @@ send_again:
  reply_msg.acpted_rply.ar_results.where = resultsp;
  reply_msg.acpted_rply.ar_results.proc = xresults;
 
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  for (;;) {
  switch (ppoll(pfd, 1, &wait, NULL)) {
  case 0:
@@ -283,7 +283,7 @@ send_again:
  /* FALLTHROUGH */
  case -1:
  if (errno == EINTR) {
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&after, &start, &duration);
  timespecadd(&time_waited, &duration, &time_waited);
  if (timespeccmp(&time_waited, &timeout, <))
diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c
index f9d7a70938f..6c99db84359 100644
--- lib/libc/rpc/svc_tcp.c
+++ lib/libc/rpc/svc_tcp.c
@@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
  * A timeout is fatal for the connection.
  */
  delta = wait_per_try;
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  pfd[0].fd = sock;
  pfd[0].events = POLLIN;
  do {
@@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
  case -1:
  if (errno != EINTR)
  goto fatal_err;
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&after, &start, &duration);
  timespecsub(&wait_per_try, &duration, &delta);
  if (delta.tv_sec < 0 || !timespecisset(&delta))
diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc
index 34769576ced..d57418d81bf 100644
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \
 
 # glue to offer userland wrappers for some syscalls
 SRCS+= posix_madvise.c pthread_sigmask.c \
- w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c
+ w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \
+ w_clock_gettime.c w_gettimeofday.c microtime.c
 
 # glue for compat with old syscall interfaces.
 SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c truncate.c \
@@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c w_pwrite.c w_pwritev.c
 ASM= __semctl.o __syscall.o __thrsigdivert.o \
  access.o acct.o adjfreq.o adjtime.o \
  bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \
- clock_getres.o clock_gettime.o clock_settime.o \
+ clock_getres.o clock_settime.o \
  dup.o dup2.o dup3.o \
  execve.o \
  faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \
@@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \
  getgroups.o getitimer.o getpeername.o getpgid.o \
  getpriority.o getresgid.o getresuid.o \
  getrlimit.o getrusage.o getsid.o getsockname.o \
- getsockopt.o gettimeofday.o ioctl.o \
+ getsockopt.o ioctl.o \
  kevent.o kill.o kqueue.o ktrace.o lchown.o \
  link.o linkat.o listen.o lstat.o madvise.o \
  minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
@@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po}
 SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so}
 DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do}
 
-HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o}
+HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o} \
+ clock_gettime.o gettimeofday.o
 PHIDDEN=${HIDDEN:.o=.po}
 SHIDDEN=${HIDDEN:.o=.so}
 DHIDDEN=${HIDDEN:.o=.do}
diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c
new file mode 100644
index 00000000000..4684298c4ae
--- /dev/null
+++ lib/libc/sys/microtime.c
@@ -0,0 +1,180 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2000 Poul-Henning Kamp <[hidden email]>
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/atomic.h>
+#include <sys/timetc.h>
+
+#include <time.h>
+
+/*
+ * Return the difference between the timehands' counter value now and what
+ * was when we copied it to the timehands' offset_count.
+ */
+static inline int
+tc_delta(struct timekeep *tk, u_int *delta)
+{
+ uint tc;
+ if (delta == NULL || _tc_get_timecount(tk, &tc))
+ return -1;
+ *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
+ return 0;
+}
+
+static inline void
+bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct)
+{
+ ct->sec = bt->sec;
+ if (bt->frac > bt->frac + x)
+ ct->sec++;
+ ct->frac = bt->frac + x;
+}
+
+static inline void
+BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts)
+{
+ ts->tv_sec = bt->sec;
+ ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32);
+}
+
+static inline void
+BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv)
+{
+ tv->tv_sec = bt->sec;
+ tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32);
+}
+
+static int
+binuptime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ *bt = tk->tk_offset;
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(bt, tk->tk_scale * delta, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+static inline void
+bintimeadd(const struct bintime *bt, const struct bintime *ct,
+    struct bintime *dt)
+{
+ dt->sec = bt->sec + ct->sec;
+ if (bt->frac > bt->frac + ct->frac)
+ dt->sec++;
+ dt->frac = bt->frac + ct->frac;
+}
+
+static inline void
+bintimesub(const struct bintime *bt, const struct bintime *ct,
+    struct bintime *dt)
+{
+ dt->sec = bt->sec - ct->sec;
+ if (bt->frac < bt->frac - ct->frac)
+ dt->sec--;
+ dt->frac = bt->frac - ct->frac;
+}
+
+static int
+binruntime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt);
+ bintimesub(bt, &tk->tk_naptime, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+static int
+bintime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ *bt = tk->tk_offset;
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(bt, tk->tk_scale * delta, bt);
+ bintimeadd(bt, &tk->tk_boottime, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+int
+_microtime(struct timeval *tvp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (bintime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMEVAL(&bt, tvp);
+ return 0;
+}
+
+int
+_nanotime(struct timespec *tsp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (bintime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, tsp);
+ return 0;
+}
+
+int
+_nanoruntime(struct timespec *ts, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (binruntime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, ts);
+ return 0;
+}
+
+
+int
+_nanouptime(struct timespec *tsp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (binuptime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, tsp);
+ return 0;
+}
diff --git lib/libc/sys/w_clock_gettime.c lib/libc/sys/w_clock_gettime.c
new file mode 100644
index 00000000000..6e6478bd131
--- /dev/null
+++ lib/libc/sys/w_clock_gettime.c
@@ -0,0 +1,51 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/timetc.h>
+
+#include <time.h>
+
+int
+WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp)
+{
+ int rc = 0;
+ struct timekeep *timekeep = _timekeep;
+
+ if (timekeep == NULL || timekeep->tk_user == 0)
+ return clock_gettime(clock_id, tp);
+
+ switch (clock_id) {
+ case CLOCK_REALTIME:
+ rc = _nanotime(tp, timekeep);
+ break;
+ case CLOCK_UPTIME:
+ rc = _nanoruntime(tp, timekeep);
+ break;
+ case CLOCK_MONOTONIC:
+ case CLOCK_BOOTTIME:
+ rc = _nanouptime(tp, timekeep);
+ break;
+ default:
+ return clock_gettime(clock_id, tp);
+ }
+
+ if (rc)
+ return clock_gettime(clock_id, tp);
+
+ return 0;
+}
+DEF_WRAP(clock_gettime);
diff --git lib/libc/sys/w_gettimeofday.c lib/libc/sys/w_gettimeofday.c
new file mode 100644
index 00000000000..f44edfbb1ad
--- /dev/null
+++ lib/libc/sys/w_gettimeofday.c
@@ -0,0 +1,40 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Robert Nagy <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/timetc.h>
+
+int
+WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp)
+{
+ int rc = 0;
+ struct timekeep *timekeep = _timekeep;
+ static struct timezone zerotz = { 0, 0 };
+
+ if (timekeep == NULL || timekeep->tk_user == 0)
+ return gettimeofday(tp, tzp);
+
+ if (tp)
+ rc = _microtime(tp, timekeep);
+ if (rc)
+ return gettimeofday(tp, tzp);
+
+ if (tzp)
+ *tzp = zerotz;
+
+ return 0;
+}
+DEF_WRAP(gettimeofday);
diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h
index 788890add89..df2239438d2 100644
--- lib/libc/thread/synch.h
+++ lib/libc/thread/synch.h
@@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
  if (abs == NULL)
  return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
 
- if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
+ if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel))
  return (EINVAL);
 
  rel.tv_sec = abs->tv_sec - rel.tv_sec;
diff --git regress/lib/libc/timekeep/Makefile regress/lib/libc/timekeep/Makefile
new file mode 100644
index 00000000000..a7f3080290d
--- /dev/null
+++ regress/lib/libc/timekeep/Makefile
@@ -0,0 +1,5 @@
+# $OpenBSD$
+
+PROGS= test_clock_gettime test_time_skew test_gettimeofday
+
+.include <bsd.regress.mk>
diff --git regress/lib/libc/timekeep/test_clock_gettime.c regress/lib/libc/timekeep/test_clock_gettime.c
new file mode 100644
index 00000000000..859ec368215
--- /dev/null
+++ regress/lib/libc/timekeep/test_clock_gettime.c
@@ -0,0 +1,43 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <time.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+
+void
+check()
+{
+ struct timespec tp = {0};
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp));
+
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp));
+
+}
+
+int main()
+{
+ check();
+ return 0;
+}
diff --git regress/lib/libc/timekeep/test_gettimeofday.c regress/lib/libc/timekeep/test_gettimeofday.c
new file mode 100644
index 00000000000..ea90a1be7e0
--- /dev/null
+++ regress/lib/libc/timekeep/test_gettimeofday.c
@@ -0,0 +1,37 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <sys/time.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+
+void
+check()
+{
+ struct timeval tv = {0};
+ struct timezone tzp;
+
+ ASSERT_EQ(0, gettimeofday(&tv, NULL));
+ ASSERT_EQ(0, gettimeofday(&tv, &tzp));
+}
+
+int main()
+{
+ check();
+ return 0;
+}
diff --git regress/lib/libc/timekeep/test_time_skew.c regress/lib/libc/timekeep/test_time_skew.c
new file mode 100644
index 00000000000..dfa9481c091
--- /dev/null
+++ regress/lib/libc/timekeep/test_time_skew.c
@@ -0,0 +1,55 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/time.h>
+
+#include <assert.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+#define ASSERT_NE(a, b) assert((a) != (b))
+
+void
+check()
+{
+         struct timespec tp1, tp2, tout;
+
+         tout.tv_sec = 0;
+         tout.tv_nsec = 100000;
+
+         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1));
+
+         nanosleep(&tout, NULL);
+
+         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2));
+
+         /* tp1 should never be larger than tp2 */
+         ASSERT_NE(1, timespeccmp(&tp1, &tp2, >));
+}
+
+int
+main(void)
+{
+ int i;
+
+ for (i = 0; i < 1000; i++)
+ check();
+
+ return 0;
+}
diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c
index 3f5f2c5b42b..6eaf8b107c6 100644
--- sys/arch/alpha/alpha/clock.c
+++ sys/arch/alpha/alpha/clock.c
@@ -64,7 +64,7 @@ int clk_irq = 0;
 
 u_int rpcc_get_timecount(struct timecounter *);
 struct timecounter rpcc_timecounter = {
- rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
+ rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0
 };
 
 extern todr_chip_handle_t todr_handle;
diff --git sys/arch/alpha/include/timetc.h sys/arch/alpha/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/alpha/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c
index 7a1dcb4ad75..682f9c1ca1a 100644
--- sys/arch/amd64/amd64/tsc.c
+++ sys/arch/amd64/amd64/tsc.c
@@ -50,7 +50,7 @@ extern u_int32_t lapic_per_second;
 #endif
 
 struct timecounter tsc_timecounter = {
- tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL
+ tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, TC_TSC
 };
 
 uint64_t
@@ -244,6 +244,7 @@ tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
  printf("ERROR: %lld cycle TSC drift observed\n",
     (long long)tsc_drift_observed);
  tsc_timecounter.tc_quality = -1000;
+ tsc_timecounter.tc_user = 0;
  tsc_is_invariant = 0;
  }
 
diff --git sys/arch/amd64/include/timetc.h sys/arch/amd64/include/timetc.h
new file mode 100644
index 00000000000..c2d40bcd1e7
--- /dev/null
+++ sys/arch/amd64/include/timetc.h
@@ -0,0 +1,24 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_TSC 1
+#define TC_LAST 2
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c
index 613f7ee0e0f..00da0c6a8d0 100644
--- sys/arch/amd64/isa/clock.c
+++ sys/arch/amd64/isa/clock.c
@@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
 u_int i8254_simple_get_timecount(struct timecounter *tc);
 
 static struct timecounter i8254_timecounter = {
- i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
 };
 
 int clockintr(void *);
diff --git sys/arch/arm/include/timetc.h sys/arch/arm/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/arm/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c
index 11196b5c60d..1a2106ef94c 100644
--- sys/arch/arm64/dev/agtimer.c
+++ sys/arch/arm64/dev/agtimer.c
@@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY;
 u_int agtimer_get_timecount(struct timecounter *);
 
 static struct timecounter agtimer_timecounter = {
- agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL
+ agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0
 };
 
 struct agtimer_pcpu_softc {
diff --git sys/arch/arm64/include/timetc.h sys/arch/arm64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/arm64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/armv7/include/timetc.h sys/arch/armv7/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/armv7/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/armv7/omap/gptimer.c sys/arch/armv7/omap/gptimer.c
index 7605845d5e2..061542d532f 100644
--- sys/arch/armv7/omap/gptimer.c
+++ sys/arch/armv7/omap/gptimer.c
@@ -117,7 +117,7 @@ int gptimer_irq = 0;
 u_int gptimer_get_timecount(struct timecounter *);
 
 static struct timecounter gptimer_timecounter = {
- gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
+ gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0
 };
 
 volatile u_int32_t nexttickevent;
diff --git sys/arch/armv7/sunxi/sxitimer.c sys/arch/armv7/sunxi/sxitimer.c
index 14a243c78d0..41028f9a602 100644
--- sys/arch/armv7/sunxi/sxitimer.c
+++ sys/arch/armv7/sunxi/sxitimer.c
@@ -89,7 +89,7 @@ void sxitimer_delay(u_int);
 u_int sxitimer_get_timecount(struct timecounter *);
 
 static struct timecounter sxitimer_timecounter = {
- sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL
+ sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0
 };
 
 bus_space_tag_t sxitimer_iot;
diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c
index 4c594ab5ec7..8cce6c3a893 100644
--- sys/arch/hppa/dev/clock.c
+++ sys/arch/hppa/dev/clock.c
@@ -47,7 +47,7 @@ int cpu_hardclock(void *);
 u_int itmr_get_timecount(struct timecounter *);
 
 struct timecounter itmr_timecounter = {
- itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
+ itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0
 };
 
 extern todr_chip_handle_t todr_handle;
diff --git sys/arch/hppa/include/timetc.h sys/arch/hppa/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/hppa/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/i386/include/timetc.h sys/arch/i386/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/i386/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c
index 09a6db983f2..dd74bd425ad 100644
--- sys/arch/i386/isa/clock.c
+++ sys/arch/i386/isa/clock.c
@@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
 u_int i8254_simple_get_timecount(struct timecounter *tc);
 
 static struct timecounter i8254_timecounter = {
- i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
 };
 struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
 u_long rtclock_tval;
diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
index 9d9f061eef9..bb8e4c7f9ae 100644
--- sys/arch/i386/pci/geodesc.c
+++ sys/arch/i386/pci/geodesc.c
@@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = {
  0xffffffff, /* counter_mask */
  27000000, /* frequency */
  "GEOTSC", /* name */
- 2000 /* quality */
+ 2000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 int
diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c
index 8b8aa4ac430..a6f324e66f3 100644
--- sys/arch/i386/pci/gscpm.c
+++ sys/arch/i386/pci/gscpm.c
@@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = {
  0xffffff, /* counter_mask */
  3579545, /* frequency */
  "GSCPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 struct cfattach gscpm_ca = {
diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c
index 6abf1627de2..629a86a14ff 100644
--- sys/arch/i386/pci/ichpcib.c
+++ sys/arch/i386/pci/ichpcib.c
@@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = {
  0xffffff, /* counter_mask */
  3579545, /* frequency */
  "ICHPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 struct cfattach ichpcib_ca = {
diff --git sys/arch/landisk/include/timetc.h sys/arch/landisk/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/landisk/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/loongson/include/timetc.h sys/arch/loongson/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/loongson/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/loongson/loongson/generic3a_machdep.c sys/arch/loongson/loongson/generic3a_machdep.c
index ac3f1db6ccd..53489b07549 100644
--- sys/arch/loongson/loongson/generic3a_machdep.c
+++ sys/arch/loongson/loongson/generic3a_machdep.c
@@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = {
  .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */
  .tc_frequency = HPET_FREQ,
  .tc_name = "hpet",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 /* Firmware entry points */
diff --git sys/arch/luna88k/include/timetc.h sys/arch/luna88k/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/luna88k/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/luna88k/luna88k/clock.c sys/arch/luna88k/luna88k/clock.c
index a04120987e0..6580a4a46bf 100644
--- sys/arch/luna88k/luna88k/clock.c
+++ sys/arch/luna88k/luna88k/clock.c
@@ -112,7 +112,9 @@ struct timecounter clock_tc = {
  .tc_counter_mask = 0xffffffff,
  .tc_frequency = 0, /* will be filled in */
  .tc_name = "clock",
- .tc_quality = 0
+ .tc_quality = 0,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 /*
diff --git sys/arch/m88k/include/timetc.h sys/arch/m88k/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/m88k/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/macppc/include/timetc.h sys/arch/macppc/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/macppc/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/macppc/macppc/clock.c sys/arch/macppc/macppc/clock.c
index 4a44a92cfc0..8c3ad620be8 100644
--- sys/arch/macppc/macppc/clock.c
+++ sys/arch/macppc/macppc/clock.c
@@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320;
 static int32_t ticks_per_intr;
 
 static struct timecounter tb_timecounter = {
- tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
+ tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0
 };
 
 /* calibrate the timecounter frequency for the listed models */
diff --git sys/arch/mips64/include/timetc.h sys/arch/mips64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/mips64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/mips64/mips64/mips64_machdep.c sys/arch/mips64/mips64/mips64_machdep.c
index d4a42ed5acc..5c4dbadb5bb 100644
--- sys/arch/mips64/mips64/mips64_machdep.c
+++ sys/arch/mips64/mips64/mips64_machdep.c
@@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = {
  0xffffffff, /* counter_mask */
  0, /* frequency */
  "CP0", /* name */
- 0 /* quality */
+ 0, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 u_int
diff --git sys/arch/octeon/include/timetc.h sys/arch/octeon/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/octeon/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/octeon/octeon/machdep.c sys/arch/octeon/octeon/machdep.c
index 902e462d53f..d8377653abe 100644
--- sys/arch/octeon/octeon/machdep.c
+++ sys/arch/octeon/octeon/machdep.c
@@ -151,8 +151,9 @@ struct timecounter ioclock_timecounter = {
  .tc_name = "ioclock",
  .tc_quality = 0, /* ioclock can be overridden
  * by cp0 counter */
- .tc_priv = 0 /* clock register,
+ .tc_priv = 0, /* clock register,
  * determined at runtime */
+ .tc_user = 0, /* expose to user */
 };
 
 static int
diff --git sys/arch/powerpc/include/timetc.h sys/arch/powerpc/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/powerpc/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/powerpc64/include/timetc.h sys/arch/powerpc64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/powerpc64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sgi/include/timetc.h sys/arch/sgi/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sgi/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sgi/sgi/ip27_machdep.c sys/arch/sgi/sgi/ip27_machdep.c
index ba7fa558b96..2a2cc144242 100644
--- sys/arch/sgi/sgi/ip27_machdep.c
+++ sys/arch/sgi/sgi/ip27_machdep.c
@@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = {
  .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */
  .tc_frequency = 1250000,
  .tc_name = "hubrt",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = 0,
+ .tc_user = 0,
 };
 
 volatile uint64_t ip27_spinup_a0;
diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c
index 56b29915c70..827775512ac 100644
--- sys/arch/sgi/xbow/xheart.c
+++ sys/arch/sgi/xbow/xheart.c
@@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = {
  .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit */
  .tc_frequency = 12500000,
  .tc_name = "heart",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *);
diff --git sys/arch/sh/include/timetc.h sys/arch/sh/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sh/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sparc64/dev/psycho.c sys/arch/sparc64/dev/psycho.c
index e24f804dff6..1a7a1afa8c2 100644
--- sys/arch/sparc64/dev/psycho.c
+++ sys/arch/sparc64/dev/psycho.c
@@ -127,7 +127,7 @@ extern struct sparc_pci_chipset _sparc_pci_chipset;
 u_int stick_get_timecount(struct timecounter *);
 
 struct timecounter stick_timecounter = {
- stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
+ stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0
 };
 
 /*
diff --git sys/arch/sparc64/include/timetc.h sys/arch/sparc64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sparc64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sparc64/sparc64/clock.c sys/arch/sparc64/sparc64/clock.c
index fd5e8a9c15b..5c2e47d386b 100644
--- sys/arch/sparc64/sparc64/clock.c
+++ sys/arch/sparc64/sparc64/clock.c
@@ -109,13 +109,13 @@ struct cfdriver clock_cd = {
 u_int tick_get_timecount(struct timecounter *);
 
 struct timecounter tick_timecounter = {
- tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL
+ tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0
 };
 
 u_int sys_tick_get_timecount(struct timecounter *);
 
 struct timecounter sys_tick_timecounter = {
- sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL
+ sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0
 };
 
 /*
diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c
index d0ee72cec9b..13177a909da 100644
--- sys/dev/acpi/acpihpet.c
+++ sys/dev/acpi/acpihpet.c
@@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = {
  0xffffffff, /* counter_mask (32 bits) */
  0, /* frequency */
  0, /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 #define HPET_TIMERS 3
diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c
index cdc8c99a17a..89b5a397e47 100644
--- sys/dev/acpi/acpitimer.c
+++ sys/dev/acpi/acpitimer.c
@@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = {
  0x00ffffff, /* counter_mask (24 bits) */
  ACPI_FREQUENCY, /* frequency */
  0, /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 struct acpitimer_softc {
diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c
index 6df82858016..9610d5bc1f0 100644
--- sys/dev/pci/amdpm.c
+++ sys/dev/pci/amdpm.c
@@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = {
  0xffffff, /* counter_mask */
  AMDPM_FREQUENCY, /* frequency */
  "AMDPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 #define AMDPM_CONFREG 0x40
diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c
index db806eedf80..ce33cd175e6 100644
--- sys/dev/pci/viapm.c
+++ sys/dev/pci/viapm.c
@@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = {
  0xffffff, /* counter_mask */
  VIAPM_FREQUENCY, /* frequency */
  "VIAPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 struct timeout viapm_timeout;
diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c
index b32facdacb1..b9ee2feec4c 100644
--- sys/dev/pv/hyperv.c
+++ sys/dev/pv/hyperv.c
@@ -141,7 +141,7 @@ struct {
 };
 
 struct timecounter hv_timecounter = {
- hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001
+ hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0
 };
 
 struct cfdriver hyperv_cd = {
diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c
index 6b242f7448d..b80e4d2a484 100644
--- sys/dev/pv/pvclock.c
+++ sys/dev/pv/pvclock.c
@@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = {
 };
 
 struct timecounter pvclock_timecounter = {
- pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL
+ pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0
 };
 
 int
diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c
index 9b5b8eb3acf..59bc923a6fb 100644
--- sys/kern/exec_elf.c
+++ sys/kern/exec_elf.c
@@ -124,7 +124,7 @@ extern char *syscallnames[];
 /*
  * How many entries are in the AuxInfo array we pass to the process?
  */
-#define ELF_AUX_ENTRIES 8
+#define ELF_AUX_ENTRIES 9
 
 /*
  * This is the OpenBSD ELF emul
@@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct exec_package *epp)
  a->au_v = ap->arg_entry;
  a++;
 
+ a->au_id = AUX_openbsd_timekeep;
+ a->au_v = p->p_p->ps_timekeep;
+ a++;
+
  a->au_id = AUX_null;
  a->au_v = 0;
  a++;
diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
index 20480c2fc28..b695b6dc627 100644
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -64,6 +64,11 @@
 #include <uvm/uvm_extern.h>
 #include <machine/tcb.h>
 
+#include <sys/timetc.h>
+
+struct uvm_object *timekeep_object;
+struct timekeep* timekeep;
+
 void unveil_destroy(struct process *ps);
 
 const struct kmem_va_mode kv_exec = {
@@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = {
  */
 int exec_sigcode_map(struct process *, struct emul *);
 
+/*
+ * Map the shared timekeep page.
+ */
+int exec_timekeep_map(struct process *);
+
 /*
  * If non-zero, stackgap_random specifies the upper limit of the random gap size
  * added to the fixed stack position. Must be n^2.
@@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t *retval)
  /* map the process's signal trampoline code */
  if (exec_sigcode_map(pr, pack.ep_emul))
  goto free_pack_abort;
+ /* map the process's timekeep page */
+ if (exec_timekeep_map(pr))
+ goto free_pack_abort;
 
 #ifdef __HAVE_EXEC_MD_MAP
  /* perform md specific mappings that process might need */
@@ -863,3 +876,40 @@ exec_sigcode_map(struct process *pr, struct emul *e)
 
  return (0);
 }
+
+int
+exec_timekeep_map(struct process *pr)
+{
+ size_t timekeep_sz = sizeof(struct timekeep);
+
+ /*
+ * Similar to the sigcode object, except that there is a single timekeep
+ * object, and not one per emulation.
+ */
+ if (timekeep_object == NULL) {
+ vaddr_t va;
+
+ timekeep_object = uao_create(timekeep_sz, 0);
+ uao_reference(timekeep_object);
+
+ if (uvm_map(kernel_map, &va, round_page(timekeep_sz), timekeep_object,
+    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
+    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
+ uao_detach(timekeep_object);
+ return (ENOMEM);
+ }
+
+ timekeep = (struct timekeep *)va;
+ timekeep->tk_version = TK_VERSION;
+ }
+
+ uao_reference(timekeep_object);
+ if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, round_page(timekeep_sz),
+    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
+    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
+ uao_detach(timekeep_object);
+ return (ENOMEM);
+ }
+
+ return (0);
+}
diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
index 88d4a3379f9..47efbdd0b78 100644
--- sys/kern/kern_tc.c
+++ sys/kern/kern_tc.c
@@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc)
 }
 
 static struct timecounter dummy_timecounter = {
- dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
+ dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0
 };
 
 /*
@@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts)
 #endif
 }
 
+void
+tc_update_timekeep(void)
+{
+ static struct timecounter *last_tc = NULL;
+ struct timehands *th;
+
+ if (timekeep == NULL)
+ return;
+
+ th = timehands;
+ timekeep->tk_generation = 0;
+ membar_producer();
+ timekeep->tk_scale = th->th_scale;
+ timekeep->tk_offset_count = th->th_offset_count;
+ timekeep->tk_offset = th->th_offset;
+ timekeep->tk_naptime = th->th_naptime;
+ timekeep->tk_boottime = th->th_boottime;
+ if (last_tc != th->th_counter) {
+ timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
+ timekeep->tk_user = th->th_counter->tc_user;
+ last_tc = th->th_counter;
+ }
+ membar_producer();
+ timekeep->tk_generation = th->th_generation;
+
+ return;
+}
+
 /*
  * Initialize the next struct timehands in the ring and make
  * it the active timehands.  Along the way we might switch to a different
@@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
  time_uptime = th->th_offset.sec;
  membar_producer();
  timehands = th;
+
+ tc_update_timekeep();
 }
 
 /* Report or change the active timecounter hardware. */
diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h
index a40e0510273..3084ed595a6 100644
--- sys/sys/exec_elf.h
+++ sys/sys/exec_elf.h
@@ -691,7 +691,8 @@ enum AuxID {
  AUX_sun_uid = 2000, /* euid */
  AUX_sun_ruid = 2001, /* ruid */
  AUX_sun_gid = 2002, /* egid */
- AUX_sun_rgid = 2003 /* rgid */
+ AUX_sun_rgid = 2003, /* rgid */
+ AUX_openbsd_timekeep = 4000, /* userland clock_gettime */
 };
 
 struct elf_args {
diff --git sys/sys/proc.h sys/sys/proc.h
index 357c0c0d52c..c6d54572bdd 100644
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -242,6 +242,7 @@ struct process {
  char ps_comm[MAXCOMLEN+1];
 
  vaddr_t ps_strings; /* User pointers to argv/env */
+ vaddr_t ps_timekeep; /* User pointer to timekeep */
  vaddr_t ps_sigcode; /* User pointer to the signal code */
  vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */
  u_long ps_sigcookie;
diff --git sys/sys/time.h sys/sys/time.h
index e758a64ce07..bcd3acd034d 100644
--- sys/sys/time.h
+++ sys/sys/time.h
@@ -163,7 +163,7 @@ struct clockinfo {
 };
 #endif /* __BSD_VISIBLE */
 
-#if defined(_KERNEL) || defined(_STANDALONE)
+#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC)
 #include <sys/_time.h>
 
 /* Time expressed as seconds and fractions of a second + operations on it. */
@@ -171,6 +171,9 @@ struct bintime {
  time_t sec;
  uint64_t frac;
 };
+#endif
+
+#if defined(_KERNEL) || defined(_STANDALONE)
 
 #define bintimecmp(btp, ctp, cmp) \
  ((btp)->sec == (ctp)->sec ? \
diff --git sys/sys/timetc.h sys/sys/timetc.h
index ce81c3475a0..c5ad27695ba 100644
--- sys/sys/timetc.h
+++ sys/sys/timetc.h
@@ -24,10 +24,11 @@
 #ifndef _SYS_TIMETC_H_
 #define _SYS_TIMETC_H_
 
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_LIBC)
 #error "no user-serviceable parts inside"
 #endif
 
+#include <machine/timetc.h>
 #include <sys/queue.h>
 
 /*-
@@ -80,6 +81,8 @@ struct timecounter {
  */
  void *tc_priv; /* [I] */
  /* Pointer to the timecounter's private parts. */
+ int tc_user; /* [I] */
+ /* Expose this timecounter to userland. */
  SLIST_ENTRY(timecounter) tc_next; /* [I] */
  /* Pointer to the next timecounter. */
  int64_t tc_freq_adj; /* [tw] */
@@ -88,11 +91,32 @@ struct timecounter {
  /* Precision of the counter.  Computed in tc_init(). */
 };
 
+struct timekeep {
+ /* set at initialization */
+ uint32_t tk_version; /* version number */
+
+ /* timehands members */
+ uint64_t tk_scale;
+ u_int tk_offset_count;
+ struct bintime tk_offset;
+ struct bintime tk_naptime;
+ struct bintime tk_boottime;
+ volatile u_int tk_generation;
+
+ /* timecounter members */
+ int tk_user;
+ u_int tk_counter_mask;
+};
+#define TK_VERSION 0
+
 struct rwlock;
 extern struct rwlock tc_lock;
 
 extern struct timecounter *timecounter;
 
+extern struct uvm_object *timekeep_object;
+extern struct timekeep *timekeep;
+
 u_int64_t tc_getfrequency(void);
 u_int64_t tc_getprecision(void);
 void tc_init(struct timecounter *tc);

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Mark Kettenis
In reply to this post by Paul Irofti-4
> Date: Fri, 19 Jun 2020 14:31:17 +0300
> From: Paul Irofti <[hidden email]>
>
> Hi,
>
> Here is another iteration of the diff that addresses all issues raised
> in the meantime:
>
>   - Switch tc to uint

The request was to use u_int, like we de in the kernel.  The uint type
should not be used in OpenBSD code.

>   - Check for version at init and switch to machite/timetc.h defs
>   - Remove tk_nclocks
>   - Switch to single version and ditch minor/major
>   - Do not enable user TSC for large skew values
>   - Add amd64 clocks and use the define in TSC
>   - Include and add machine/timetc.h
>
> As we have seen most architectures have support for clocks now and the
> above addresses Mark's last concerns.
>
> Unless other blocking issues arise, this time around I am looking for
> OKs to commit. Theo? Mark?

There is one other issue that I wanted to raise.  An that is whether
we really need to implement CLOCK_UPTINME as a userland clock.  If we
don't do that we can drop tk_naptime from the shared struct.  I
mention this because th_naptime was only recently added to struct
timehands and much more an implementation detail than the other fields.

I don't expect userland processes to call CLOCK_UPTIME in a loop like
they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
doesn't have it ;).

We're getting there...


> diff --git lib/libc/arch/aarch64/gen/Makefile.inc lib/libc/arch/aarch64/gen/Makefile.inc
> index a7b1b73f3ef..ee198f5d611 100644
> --- lib/libc/arch/aarch64/gen/Makefile.inc
> +++ lib/libc/arch/aarch64/gen/Makefile.inc
> @@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
>  SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
>  SRCS+= fpclassifyl.c
>  SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
> -SRCS+= signbitl.c
> +SRCS+= signbitl.c usertc.c
> diff --git lib/libc/arch/aarch64/gen/usertc.c lib/libc/arch/aarch64/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/aarch64/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/alpha/gen/Makefile.inc lib/libc/arch/alpha/gen/Makefile.inc
> index a44599d2cab..2a8abd32b61 100644
> --- lib/libc/arch/alpha/gen/Makefile.inc
> +++ lib/libc/arch/alpha/gen/Makefile.inc
> @@ -3,5 +3,5 @@
>  
>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
> - fpsetround.c fpsetsticky.c
> + fpsetround.c fpsetsticky.c usertc.c
>  SRCS+= sigsetjmp.S
> diff --git lib/libc/arch/alpha/gen/usertc.c lib/libc/arch/alpha/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/alpha/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/amd64/gen/Makefile.inc lib/libc/arch/amd64/gen/Makefile.inc
> index e995309ed71..f6349e2b974 100644
> --- lib/libc/arch/amd64/gen/Makefile.inc
> +++ lib/libc/arch/amd64/gen/Makefile.inc
> @@ -2,6 +2,7 @@
>  
>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
>   sigsetjmp.S
> -SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
> +SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \
> + usertc.c
>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
>   fpsetround.S fpsetsticky.S
> diff --git lib/libc/arch/amd64/gen/usertc.c lib/libc/arch/amd64/gen/usertc.c
> new file mode 100644
> index 00000000000..ee44d61de4b
> --- /dev/null
> +++ lib/libc/arch/amd64/gen/usertc.c
> @@ -0,0 +1,53 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +static uint
> +rdtsc()
> +{
> + uint32_t hi, lo;
> + asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
> + return ((uint64_t)lo)|(((uint64_t)hi)<<32);
> +}
> +
> +static uint
> +acpihpet()
> +{
> + return rdtsc(); /* JUST TO COMPILE */
> +}
> +
> +static uint (*const get_tc[])(void) =
> +{
> + [TC_TSC] = rdtsc,
> + [TC_HPET] = acpihpet,
> +};
> +
> +int
> +tc_get_timecount(struct timekeep *tk, uint *tc)
> +{
> + int tk_user = tk->tk_user;
> +
> + if (tc == NULL || tk_user < 1 || tk_user > TC_LAST)

No need to check for tc == NULL here.

> + return -1;
> +
> + *tc = (*get_tc[tk_user])();
> + return 0;
> +}
> +int (*const _tc_get_timecount)(struct timekeep *tk, uint *tc)
> + = tc_get_timecount;
> diff --git lib/libc/arch/arm/gen/Makefile.inc lib/libc/arch/arm/gen/Makefile.inc
> index 1b4ab2f3ae7..27090a0d9dc 100644
> --- lib/libc/arch/arm/gen/Makefile.inc
> +++ lib/libc/arch/arm/gen/Makefile.inc
> @@ -2,5 +2,5 @@
>  # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
>  
>  SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c infinity.c
> -SRCS+= ldexp.c modf.c nan.c
> +SRCS+= ldexp.c modf.c nan.c usertc.c
>  SRCS+= setjmp.S _setjmp.S sigsetjmp.S
> diff --git lib/libc/arch/arm/gen/usertc.c lib/libc/arch/arm/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/arm/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/hppa/gen/Makefile.inc lib/libc/arch/hppa/gen/Makefile.inc
> index e0c864242fe..1fde24670f1 100644
> --- lib/libc/arch/hppa/gen/Makefile.inc
> +++ lib/libc/arch/hppa/gen/Makefile.inc
> @@ -2,6 +2,6 @@
>  
>  SRCS+= setjmp.S
>  SRCS+= fabs.c
> -SRCS+= infinity.c ldexp.c modf.c nan.c
> +SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c
> diff --git lib/libc/arch/hppa/gen/usertc.c lib/libc/arch/hppa/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/hppa/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/i386/gen/Makefile.inc lib/libc/arch/i386/gen/Makefile.inc
> index 4c18e059581..b7dd30adccd 100644
> --- lib/libc/arch/i386/gen/Makefile.inc
> +++ lib/libc/arch/i386/gen/Makefile.inc
> @@ -1,6 +1,6 @@
>  # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
>  
> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
>   modf.S nan.c setjmp.S sigsetjmp.S
>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
> diff --git lib/libc/arch/i386/gen/usertc.c lib/libc/arch/i386/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/i386/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/m88k/gen/Makefile.inc lib/libc/arch/m88k/gen/Makefile.inc
> index cff75b8d425..d66f66af4af 100644
> --- lib/libc/arch/m88k/gen/Makefile.inc
> +++ lib/libc/arch/m88k/gen/Makefile.inc
> @@ -1,7 +1,7 @@
>  # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
>  # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
>  
> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c
>  SRCS+= setjmp.S sigsetjmp.S
> diff --git lib/libc/arch/m88k/gen/usertc.c lib/libc/arch/m88k/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/m88k/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/mips64/gen/Makefile.inc lib/libc/arch/mips64/gen/Makefile.inc
> index 8cf1fc2d28a..839241a2069 100644
> --- lib/libc/arch/mips64/gen/Makefile.inc
> +++ lib/libc/arch/mips64/gen/Makefile.inc
> @@ -1,6 +1,6 @@
>  # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
>  
> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c
>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
> diff --git lib/libc/arch/mips64/gen/usertc.c lib/libc/arch/mips64/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/mips64/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/powerpc/gen/Makefile.inc lib/libc/arch/powerpc/gen/Makefile.inc
> index 6b2e4613ee8..d4d7b00bff7 100644
> --- lib/libc/arch/powerpc/gen/Makefile.inc
> +++ lib/libc/arch/powerpc/gen/Makefile.inc
> @@ -1,5 +1,5 @@
>  SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c nan.c
> -SRCS+= fabs.c
> +SRCS+= fabs.c usertc.c
>  SRCS+= fpgetmask.c fpsetmask.c
>  SRCS+= fpgetround.c fpsetround.c
>  SRCS+= fpgetsticky.c fpsetsticky.c
> diff --git lib/libc/arch/powerpc/gen/usertc.c lib/libc/arch/powerpc/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/powerpc/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/sh/gen/Makefile.inc lib/libc/arch/sh/gen/Makefile.inc
> index 55de1973b30..4724fb3a6a8 100644
> --- lib/libc/arch/sh/gen/Makefile.inc
> +++ lib/libc/arch/sh/gen/Makefile.inc
> @@ -3,4 +3,4 @@
>  SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S _setjmp.S
>  SRCS+= sigsetjmp.S
>  SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
> - fpsetmask.c fpsetround.c fpsetsticky.c
> + fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
> diff --git lib/libc/arch/sh/gen/usertc.c lib/libc/arch/sh/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/sh/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/arch/sparc64/gen/Makefile.inc lib/libc/arch/sparc64/gen/Makefile.inc
> index 58259cedef6..a908e022954 100644
> --- lib/libc/arch/sparc64/gen/Makefile.inc
> +++ lib/libc/arch/sparc64/gen/Makefile.inc
> @@ -3,5 +3,5 @@
>  SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
>   fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
> - isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
> + isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
>   mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
> diff --git lib/libc/arch/sparc64/gen/usertc.c lib/libc/arch/sparc64/gen/usertc.c
> new file mode 100644
> index 00000000000..3bdea089284
> --- /dev/null
> +++ lib/libc/arch/sparc64/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, uint *) = NULL;
> diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
> index 131da4b2190..40e84771f86 100644
> --- lib/libc/asr/asr.c
> +++ lib/libc/asr/asr.c
> @@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds, int timeout)
>   struct timespec pollstart, pollend, elapsed;
>   int r;
>  
> - if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
>   return -1;
>  
>   while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
> - if (clock_gettime(CLOCK_MONOTONIC, &pollend))
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
>   return -1;
>   timespecsub(&pollend, &pollstart, &elapsed);
>   timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
> @@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
>   asr->a_rtime = 0;
>   }
>  
> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>   return;
>  
>   if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
> diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
> index 82de8fa33b7..02fd3013cc1 100644
> --- lib/libc/crypt/bcrypt.c
> +++ lib/libc/crypt/bcrypt.c
> @@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
>   char buf[_PASSWORD_LEN];
>   int duration;
>  
> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
>   bcrypt_newhash("testpassword", r, buf, sizeof(buf));
> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
>  
>   duration = after.tv_sec - before.tv_sec;
>   duration *= 1000000;
> diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
> index 270f54aada5..6f535853335 100644
> --- lib/libc/dlfcn/init.c
> +++ lib/libc/dlfcn/init.c
> @@ -20,6 +20,7 @@
>  
>  #include <sys/types.h>
>  #include <sys/syscall.h>
> +#include <sys/timetc.h> /* timekeep */
>  
>  #ifndef PIC
>  #include <sys/mman.h>
> @@ -45,8 +46,9 @@
>  /* XXX should be in an include file shared with csu */
>  char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void));
>  
> -/* provide definition for this */
> +/* provide definitions for these */
>  int _pagesize = 0;
> +struct timekeep *_timekeep = NULL;

Is there a reason why this needs to be "= NULL"?  Unless there is
something special going on (which may be the case for _pagesize) there
should be no reason to explicitly initialize things to 0 or NULL.
Paging guenther@...

>  /*
>   * In dynamicly linked binaries environ and __progname are overriden by
> @@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb)
>   phnum = aux->au_v;
>   break;
>  #endif /* !PIC */
> + case AUX_openbsd_timekeep:
> + if (_tc_get_timecount) {
> + _timekeep = (void *)aux->au_v;
> + if (_timekeep->tk_version != TK_VERSION)
> + _timekeep = NULL;
> + }
> + break;
>   }
>   }
>  
> diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
> index 1286a96fe40..32f86eda50f 100644
> --- lib/libc/gen/auth_subr.c
> +++ lib/libc/gen/auth_subr.c
> @@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
>  
>   if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
>   if (as->now.tv_sec == 0)
> - gettimeofday(&as->now, NULL);
> + WRAP(gettimeofday)(&as->now, NULL);
>   if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
>   as->state &= ~AUTH_ALLOW;
>   as->state |= AUTH_EXPIRED;
> @@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
>  
>   if (as->pwd && (quad_t)as->pwd->pw_change) {
>   if (as->now.tv_sec == 0)
> - gettimeofday(&as->now, NULL);
> + WRAP(gettimeofday)(&as->now, NULL);
>   if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
>   as->state &= ~AUTH_ALLOW;
>   as->state |= AUTH_PWEXPIRED;
> diff --git lib/libc/gen/time.c lib/libc/gen/time.c
> index 3bbd0d733d1..b3ce9a800f1 100644
> --- lib/libc/gen/time.c
> +++ lib/libc/gen/time.c
> @@ -36,7 +36,7 @@ time(time_t *t)
>  {
>   struct timeval tt;
>  
> - if (gettimeofday(&tt, NULL) == -1)
> + if (WRAP(gettimeofday)(&tt, NULL) == -1)
>   return (-1);
>   if (t)
>   *t = (time_t)tt.tv_sec;
> diff --git lib/libc/gen/times.c lib/libc/gen/times.c
> index 02e4dd44b5c..36841810d1b 100644
> --- lib/libc/gen/times.c
> +++ lib/libc/gen/times.c
> @@ -52,7 +52,7 @@ times(struct tms *tp)
>   return ((clock_t)-1);
>   tp->tms_cutime = CONVTCK(ru.ru_utime);
>   tp->tms_cstime = CONVTCK(ru.ru_stime);
> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>   return ((clock_t)-1);
>   return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK));
>  }
> diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
> index 520a5954025..845cbe80356 100644
> --- lib/libc/gen/timespec_get.c
> +++ lib/libc/gen/timespec_get.c
> @@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
>  {
>   switch (base) {
>   case TIME_UTC:
> - if (clock_gettime(CLOCK_REALTIME, ts) == -1)
> + if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
>   return 0;
>   break;
>   default:
> diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
> index ed112320fa2..df717021cab 100644
> --- lib/libc/hidden/sys/time.h
> +++ lib/libc/hidden/sys/time.h
> @@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
>  PROTO_NORMAL(adjtime);
>  PROTO_NORMAL(futimes);
>  PROTO_NORMAL(getitimer);
> -PROTO_NORMAL(gettimeofday);
> +PROTO_WRAP(gettimeofday);
>  PROTO_NORMAL(setitimer);
>  PROTO_NORMAL(settimeofday);
>  PROTO_NORMAL(utimes);
> diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h
> new file mode 100644
> index 00000000000..243c0137a42
> --- /dev/null
> +++ lib/libc/hidden/sys/timetc.h
> @@ -0,0 +1,38 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _LIBC_SYS_TIMETC_H_
> +#define _LIBC_SYS_TIMETC_H_
> +
> +#define _LIBC
> +#include <sys/types.h>
> +#include <sys/time.h>
> +
> +#include_next <sys/timetc.h>
> +
> +__BEGIN_HIDDEN_DECLS
> +extern struct timekeep *_timekeep;
> +
> +extern int (*const _tc_get_timecount)(struct timekeep *, uint *);
> +
> +int _microtime(struct timeval *, struct timekeep *);
> +int _nanotime(struct timespec *, struct timekeep *);
> +int _nanoruntime(struct timespec *, struct timekeep *);
> +int _nanouptime(struct timespec *, struct timekeep *);
> +__END_HIDDEN_DECLS
> +
> +#endif /* !_LIBC_SYS_TIMETC_H_ */
> diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h
> index 18c49f8fcb9..d8e1e0caf64 100644
> --- lib/libc/hidden/time.h
> +++ lib/libc/hidden/time.h
> @@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r);
>  PROTO_STD_DEPRECATED(clock);
>  PROTO_DEPRECATED(clock_getcpuclockid);
>  PROTO_NORMAL(clock_getres);
> -PROTO_NORMAL(clock_gettime);
> +PROTO_WRAP(clock_gettime);
>  PROTO_NORMAL(clock_settime);
>  PROTO_STD_DEPRECATED(ctime);
>  PROTO_DEPRECATED(ctime_r);
> diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c
> index 763e420bb88..9babb28470a 100644
> --- lib/libc/net/res_random.c
> +++ lib/libc/net/res_random.c
> @@ -219,7 +219,7 @@ res_initid(void)
>   if (ru_prf != NULL)
>   arc4random_buf(ru_prf, sizeof(*ru_prf));
>  
> - clock_gettime(CLOCK_MONOTONIC, &ts);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
>   ru_reseed = ts.tv_sec + RU_OUT;
>   ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
>  }
> @@ -232,7 +232,7 @@ __res_randomid(void)
>   u_int r;
>   static void *randomid_mutex;
>  
> - clock_gettime(CLOCK_MONOTONIC, &ts);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
>   pid = getpid();
>  
>   _MUTEX_LOCK(&randomid_mutex);
> diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c
> index 402d98cede4..917a6d42b8a 100644
> --- lib/libc/rpc/auth_unix.c
> +++ lib/libc/rpc/auth_unix.c
> @@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
>   /*
>   * fill in param struct from the given params
>   */
> - (void)gettimeofday(&now,  NULL);
> + (void)WRAP(gettimeofday)(&now,  NULL);
>   aup.aup_time = now.tv_sec;
>   aup.aup_machname = machname;
>   aup.aup_uid = uid;
> @@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth)
>   goto done;
>  
>   /* update the time and serialize in place */
> - (void)gettimeofday(&now, NULL);
> + (void)WRAP(gettimeofday)(&now, NULL);
>   aup.aup_time = now.tv_sec;
>   xdrs.x_op = XDR_ENCODE;
>   XDR_SETPOS(&xdrs, 0);
> diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c
> index 8e6ef515b0e..927b4bf2028 100644
> --- lib/libc/rpc/clnt_tcp.c
> +++ lib/libc/rpc/clnt_tcp.c
> @@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int len)
>   pfd[0].events = POLLIN;
>   TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait);
>   delta = wait;
> - clock_gettime(CLOCK_MONOTONIC, &start);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>   for (;;) {
>   r = ppoll(pfd, 1, &delta, NULL);
>   save_errno = errno;
>  
> - clock_gettime(CLOCK_MONOTONIC, &after);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>   timespecsub(&start, &after, &duration);
>   timespecsub(&wait, &duration, &delta);
>   if (delta.tv_sec < 0 || !timespecisset(&delta))
> diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c
> index 68d01674410..92e1d5c350d 100644
> --- lib/libc/rpc/clnt_udp.c
> +++ lib/libc/rpc/clnt_udp.c
> @@ -265,7 +265,7 @@ send_again:
>   reply_msg.acpted_rply.ar_results.where = resultsp;
>   reply_msg.acpted_rply.ar_results.proc = xresults;
>  
> - clock_gettime(CLOCK_MONOTONIC, &start);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>   for (;;) {
>   switch (ppoll(pfd, 1, &wait, NULL)) {
>   case 0:
> @@ -283,7 +283,7 @@ send_again:
>   /* FALLTHROUGH */
>   case -1:
>   if (errno == EINTR) {
> - clock_gettime(CLOCK_MONOTONIC, &after);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>   timespecsub(&after, &start, &duration);
>   timespecadd(&time_waited, &duration, &time_waited);
>   if (timespeccmp(&time_waited, &timeout, <))
> diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c
> index f9d7a70938f..6c99db84359 100644
> --- lib/libc/rpc/svc_tcp.c
> +++ lib/libc/rpc/svc_tcp.c
> @@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
>   * A timeout is fatal for the connection.
>   */
>   delta = wait_per_try;
> - clock_gettime(CLOCK_MONOTONIC, &start);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>   pfd[0].fd = sock;
>   pfd[0].events = POLLIN;
>   do {
> @@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
>   case -1:
>   if (errno != EINTR)
>   goto fatal_err;
> - clock_gettime(CLOCK_MONOTONIC, &after);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>   timespecsub(&after, &start, &duration);
>   timespecsub(&wait_per_try, &duration, &delta);
>   if (delta.tv_sec < 0 || !timespecisset(&delta))
> diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc
> index 34769576ced..d57418d81bf 100644
> --- lib/libc/sys/Makefile.inc
> +++ lib/libc/sys/Makefile.inc
> @@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \
>  
>  # glue to offer userland wrappers for some syscalls
>  SRCS+= posix_madvise.c pthread_sigmask.c \
> - w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c
> + w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \
> + w_clock_gettime.c w_gettimeofday.c microtime.c
>  
>  # glue for compat with old syscall interfaces.
>  SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c truncate.c \
> @@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c w_pwrite.c w_pwritev.c
>  ASM= __semctl.o __syscall.o __thrsigdivert.o \
>   access.o acct.o adjfreq.o adjtime.o \
>   bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \
> - clock_getres.o clock_gettime.o clock_settime.o \
> + clock_getres.o clock_settime.o \
>   dup.o dup2.o dup3.o \
>   execve.o \
>   faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \
> @@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \
>   getgroups.o getitimer.o getpeername.o getpgid.o \
>   getpriority.o getresgid.o getresuid.o \
>   getrlimit.o getrusage.o getsid.o getsockname.o \
> - getsockopt.o gettimeofday.o ioctl.o \
> + getsockopt.o ioctl.o \
>   kevent.o kill.o kqueue.o ktrace.o lchown.o \
>   link.o linkat.o listen.o lstat.o madvise.o \
>   minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
> @@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po}
>  SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so}
>  DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do}
>  
> -HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o}
> +HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o} \
> + clock_gettime.o gettimeofday.o
>  PHIDDEN=${HIDDEN:.o=.po}
>  SHIDDEN=${HIDDEN:.o=.so}
>  DHIDDEN=${HIDDEN:.o=.do}
> diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c
> new file mode 100644
> index 00000000000..4684298c4ae
> --- /dev/null
> +++ lib/libc/sys/microtime.c
> @@ -0,0 +1,180 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2000 Poul-Henning Kamp <[hidden email]>
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/atomic.h>
> +#include <sys/timetc.h>
> +
> +#include <time.h>
> +
> +/*
> + * Return the difference between the timehands' counter value now and what
> + * was when we copied it to the timehands' offset_count.
> + */
> +static inline int
> +tc_delta(struct timekeep *tk, u_int *delta)
> +{
> + uint tc;

blank line here please

> + if (delta == NULL || _tc_get_timecount(tk, &tc))

Checking delta here is pointless.

> + return -1;
> + *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
> + return 0;
> +}
> +
> +static inline void
> +bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct)
> +{
> + ct->sec = bt->sec;
> + if (bt->frac > bt->frac + x)
> + ct->sec++;
> + ct->frac = bt->frac + x;
> +}
> +
> +static inline void
> +BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts)
> +{
> + ts->tv_sec = bt->sec;
> + ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32);
> +}
> +
> +static inline void
> +BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv)
> +{
> + tv->tv_sec = bt->sec;
> + tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32);
> +}
> +
> +static int
> +binuptime(struct bintime *bt, struct timekeep *tk)
> +{
> + u_int gen, delta;
> +
> + do {
> + gen = tk->tk_generation;
> + membar_consumer();
> + *bt = tk->tk_offset;
> + if (tc_delta(tk, &delta))
> + return -1;
> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
> + membar_consumer();
> + } while (gen == 0 || gen != tk->tk_generation);
> +
> + return 0;
> +}
> +
> +static inline void
> +bintimeadd(const struct bintime *bt, const struct bintime *ct,
> +    struct bintime *dt)
> +{
> + dt->sec = bt->sec + ct->sec;
> + if (bt->frac > bt->frac + ct->frac)
> + dt->sec++;
> + dt->frac = bt->frac + ct->frac;
> +}
> +
> +static inline void
> +bintimesub(const struct bintime *bt, const struct bintime *ct,
> +    struct bintime *dt)
> +{
> + dt->sec = bt->sec - ct->sec;
> + if (bt->frac < bt->frac - ct->frac)
> + dt->sec--;
> + dt->frac = bt->frac - ct->frac;
> +}
> +
> +static int
> +binruntime(struct bintime *bt, struct timekeep *tk)
> +{
> + u_int gen, delta;
> +
> + do {
> + gen = tk->tk_generation;
> + membar_consumer();
> + if (tc_delta(tk, &delta))
> + return -1;
> + bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt);
> + bintimesub(bt, &tk->tk_naptime, bt);
> + membar_consumer();
> + } while (gen == 0 || gen != tk->tk_generation);
> +
> + return 0;
> +}
> +
> +static int
> +bintime(struct bintime *bt, struct timekeep *tk)
> +{
> + u_int gen, delta;
> +
> + do {
> + gen = tk->tk_generation;
> + membar_consumer();
> + *bt = tk->tk_offset;
> + if (tc_delta(tk, &delta))
> + return -1;
> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
> + bintimeadd(bt, &tk->tk_boottime, bt);
> + membar_consumer();
> + } while (gen == 0 || gen != tk->tk_generation);
> +
> + return 0;
> +}
> +
> +int
> +_microtime(struct timeval *tvp, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (bintime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMEVAL(&bt, tvp);
> + return 0;
> +}
> +
> +int
> +_nanotime(struct timespec *tsp, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (bintime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMESPEC(&bt, tsp);
> + return 0;
> +}
> +
> +int
> +_nanoruntime(struct timespec *ts, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (binruntime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMESPEC(&bt, ts);
> + return 0;
> +}
> +
> +
> +int
> +_nanouptime(struct timespec *tsp, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (binuptime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMESPEC(&bt, tsp);
> + return 0;
> +}
> diff --git lib/libc/sys/w_clock_gettime.c lib/libc/sys/w_clock_gettime.c
> new file mode 100644
> index 00000000000..6e6478bd131
> --- /dev/null
> +++ lib/libc/sys/w_clock_gettime.c
> @@ -0,0 +1,51 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/timetc.h>
> +
> +#include <time.h>
> +
> +int
> +WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp)
> +{
> + int rc = 0;
> + struct timekeep *timekeep = _timekeep;
> +
> + if (timekeep == NULL || timekeep->tk_user == 0)
> + return clock_gettime(clock_id, tp);
> +
> + switch (clock_id) {
> + case CLOCK_REALTIME:
> + rc = _nanotime(tp, timekeep);
> + break;
> + case CLOCK_UPTIME:
> + rc = _nanoruntime(tp, timekeep);
> + break;
> + case CLOCK_MONOTONIC:
> + case CLOCK_BOOTTIME:
> + rc = _nanouptime(tp, timekeep);
> + break;
> + default:
> + return clock_gettime(clock_id, tp);
> + }
> +
> + if (rc)
> + return clock_gettime(clock_id, tp);
> +
> + return 0;
> +}
> +DEF_WRAP(clock_gettime);
> diff --git lib/libc/sys/w_gettimeofday.c lib/libc/sys/w_gettimeofday.c
> new file mode 100644
> index 00000000000..f44edfbb1ad
> --- /dev/null
> +++ lib/libc/sys/w_gettimeofday.c
> @@ -0,0 +1,40 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Robert Nagy <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/timetc.h>
> +
> +int
> +WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp)
> +{
> + int rc = 0;
> + struct timekeep *timekeep = _timekeep;
> + static struct timezone zerotz = { 0, 0 };
> +
> + if (timekeep == NULL || timekeep->tk_user == 0)
> + return gettimeofday(tp, tzp);
> +
> + if (tp)
> + rc = _microtime(tp, timekeep);
> + if (rc)
> + return gettimeofday(tp, tzp);
> +
> + if (tzp)
> + *tzp = zerotz;
> +
> + return 0;
> +}
> +DEF_WRAP(gettimeofday);
> diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h
> index 788890add89..df2239438d2 100644
> --- lib/libc/thread/synch.h
> +++ lib/libc/thread/synch.h
> @@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
>   if (abs == NULL)
>   return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
>  
> - if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
> + if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel))
>   return (EINVAL);
>  
>   rel.tv_sec = abs->tv_sec - rel.tv_sec;
> diff --git regress/lib/libc/timekeep/Makefile regress/lib/libc/timekeep/Makefile
> new file mode 100644
> index 00000000000..a7f3080290d
> --- /dev/null
> +++ regress/lib/libc/timekeep/Makefile
> @@ -0,0 +1,5 @@
> +# $OpenBSD$
> +
> +PROGS= test_clock_gettime test_time_skew test_gettimeofday
> +
> +.include <bsd.regress.mk>
> diff --git regress/lib/libc/timekeep/test_clock_gettime.c regress/lib/libc/timekeep/test_clock_gettime.c
> new file mode 100644
> index 00000000000..859ec368215
> --- /dev/null
> +++ regress/lib/libc/timekeep/test_clock_gettime.c
> @@ -0,0 +1,43 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <assert.h>
> +#include <time.h>
> +
> +#define ASSERT_EQ(a, b) assert((a) == (b))
> +
> +void
> +check()
> +{
> + struct timespec tp = {0};
> +
> + ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp));
> +
> +
> + ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp));
> +
> +}
> +
> +int main()
> +{
> + check();
> + return 0;
> +}
> diff --git regress/lib/libc/timekeep/test_gettimeofday.c regress/lib/libc/timekeep/test_gettimeofday.c
> new file mode 100644
> index 00000000000..ea90a1be7e0
> --- /dev/null
> +++ regress/lib/libc/timekeep/test_gettimeofday.c
> @@ -0,0 +1,37 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <assert.h>
> +#include <sys/time.h>
> +
> +#define ASSERT_EQ(a, b) assert((a) == (b))
> +
> +void
> +check()
> +{
> + struct timeval tv = {0};
> + struct timezone tzp;
> +
> + ASSERT_EQ(0, gettimeofday(&tv, NULL));
> + ASSERT_EQ(0, gettimeofday(&tv, &tzp));
> +}
> +
> +int main()
> +{
> + check();
> + return 0;
> +}
> diff --git regress/lib/libc/timekeep/test_time_skew.c regress/lib/libc/timekeep/test_time_skew.c
> new file mode 100644
> index 00000000000..dfa9481c091
> --- /dev/null
> +++ regress/lib/libc/timekeep/test_time_skew.c
> @@ -0,0 +1,55 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/time.h>
> +
> +#include <assert.h>
> +#include <time.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#define ASSERT_EQ(a, b) assert((a) == (b))
> +#define ASSERT_NE(a, b) assert((a) != (b))
> +
> +void
> +check()
> +{
> +         struct timespec tp1, tp2, tout;
> +
> +         tout.tv_sec = 0;
> +         tout.tv_nsec = 100000;
> +
> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1));
> +
> +         nanosleep(&tout, NULL);
> +
> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2));
> +
> +         /* tp1 should never be larger than tp2 */
> +         ASSERT_NE(1, timespeccmp(&tp1, &tp2, >));
> +}
> +
> +int
> +main(void)
> +{
> + int i;
> +
> + for (i = 0; i < 1000; i++)
> + check();
> +
> + return 0;
> +}
> diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c
> index 3f5f2c5b42b..6eaf8b107c6 100644
> --- sys/arch/alpha/alpha/clock.c
> +++ sys/arch/alpha/alpha/clock.c
> @@ -64,7 +64,7 @@ int clk_irq = 0;
>  
>  u_int rpcc_get_timecount(struct timecounter *);
>  struct timecounter rpcc_timecounter = {
> - rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
> + rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0
>  };
>  
>  extern todr_chip_handle_t todr_handle;
> diff --git sys/arch/alpha/include/timetc.h sys/arch/alpha/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/alpha/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c
> index 7a1dcb4ad75..682f9c1ca1a 100644
> --- sys/arch/amd64/amd64/tsc.c
> +++ sys/arch/amd64/amd64/tsc.c
> @@ -50,7 +50,7 @@ extern u_int32_t lapic_per_second;
>  #endif
>  
>  struct timecounter tsc_timecounter = {
> - tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL
> + tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, TC_TSC
>  };
>  
>  uint64_t
> @@ -244,6 +244,7 @@ tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
>   printf("ERROR: %lld cycle TSC drift observed\n",
>      (long long)tsc_drift_observed);
>   tsc_timecounter.tc_quality = -1000;
> + tsc_timecounter.tc_user = 0;
>   tsc_is_invariant = 0;
>   }

You also need to add code that sets tc_user to zero if there are CPUs
with skews that are too large,

We probably should measure typical skews on some single-socket
machines to get a idea what the skew is on those since we suspect that
all the cores are actually synchronized in that case.

> diff --git sys/arch/amd64/include/timetc.h sys/arch/amd64/include/timetc.h
> new file mode 100644
> index 00000000000..72dfc969a76
> --- /dev/null
> +++ sys/arch/amd64/include/timetc.h
> @@ -0,0 +1,25 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_TSC 1
> +#define TC_HPET 2
> +#define TC_LAST 3
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c
> index 613f7ee0e0f..00da0c6a8d0 100644
> --- sys/arch/amd64/isa/clock.c
> +++ sys/arch/amd64/isa/clock.c
> @@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
>  u_int i8254_simple_get_timecount(struct timecounter *tc);
>  
>  static struct timecounter i8254_timecounter = {
> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
>  };

I don't think it is helpful to add extra 0 and NULL in cases where it
isn't necessary.  That'll make your diff smaller and easier to review.

>  
>  int clockintr(void *);
> diff --git sys/arch/arm/include/timetc.h sys/arch/arm/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/arm/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c
> index 11196b5c60d..1a2106ef94c 100644
> --- sys/arch/arm64/dev/agtimer.c
> +++ sys/arch/arm64/dev/agtimer.c
> @@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY;
>  u_int agtimer_get_timecount(struct timecounter *);
>  
>  static struct timecounter agtimer_timecounter = {
> - agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL
> + agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0
>  };
>  
>  struct agtimer_pcpu_softc {
> diff --git sys/arch/arm64/include/timetc.h sys/arch/arm64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/arm64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/armv7/include/timetc.h sys/arch/armv7/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/armv7/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/armv7/omap/gptimer.c sys/arch/armv7/omap/gptimer.c
> index 7605845d5e2..061542d532f 100644
> --- sys/arch/armv7/omap/gptimer.c
> +++ sys/arch/armv7/omap/gptimer.c
> @@ -117,7 +117,7 @@ int gptimer_irq = 0;
>  u_int gptimer_get_timecount(struct timecounter *);
>  
>  static struct timecounter gptimer_timecounter = {
> - gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
> + gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0
>  };
>  
>  volatile u_int32_t nexttickevent;
> diff --git sys/arch/armv7/sunxi/sxitimer.c sys/arch/armv7/sunxi/sxitimer.c
> index 14a243c78d0..41028f9a602 100644
> --- sys/arch/armv7/sunxi/sxitimer.c
> +++ sys/arch/armv7/sunxi/sxitimer.c
> @@ -89,7 +89,7 @@ void sxitimer_delay(u_int);
>  u_int sxitimer_get_timecount(struct timecounter *);
>  
>  static struct timecounter sxitimer_timecounter = {
> - sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL
> + sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0
>  };
>  
>  bus_space_tag_t sxitimer_iot;
> diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c
> index 4c594ab5ec7..8cce6c3a893 100644
> --- sys/arch/hppa/dev/clock.c
> +++ sys/arch/hppa/dev/clock.c
> @@ -47,7 +47,7 @@ int cpu_hardclock(void *);
>  u_int itmr_get_timecount(struct timecounter *);
>  
>  struct timecounter itmr_timecounter = {
> - itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
> + itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0
>  };
>  
>  extern todr_chip_handle_t todr_handle;
> diff --git sys/arch/hppa/include/timetc.h sys/arch/hppa/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/hppa/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/i386/include/timetc.h sys/arch/i386/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/i386/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c
> index 09a6db983f2..dd74bd425ad 100644
> --- sys/arch/i386/isa/clock.c
> +++ sys/arch/i386/isa/clock.c
> @@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
>  u_int i8254_simple_get_timecount(struct timecounter *tc);
>  
>  static struct timecounter i8254_timecounter = {
> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
>  };
>  struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
>  u_long rtclock_tval;
> diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
> index 9d9f061eef9..bb8e4c7f9ae 100644
> --- sys/arch/i386/pci/geodesc.c
> +++ sys/arch/i386/pci/geodesc.c
> @@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = {
>   0xffffffff, /* counter_mask */
>   27000000, /* frequency */
>   "GEOTSC", /* name */
> - 2000 /* quality */
> + 2000, /* quality */
> + NULL, /* private bits */
> + 0 /* expose to user */
>  };
>  
>  int
> diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c
> index 8b8aa4ac430..a6f324e66f3 100644
> --- sys/arch/i386/pci/gscpm.c
> +++ sys/arch/i386/pci/gscpm.c
> @@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = {
>   0xffffff, /* counter_mask */
>   3579545, /* frequency */
>   "GSCPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0 /* expose to user */
>  };
>  
>  struct cfattach gscpm_ca = {
> diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c
> index 6abf1627de2..629a86a14ff 100644
> --- sys/arch/i386/pci/ichpcib.c
> +++ sys/arch/i386/pci/ichpcib.c
> @@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = {
>   0xffffff, /* counter_mask */
>   3579545, /* frequency */
>   "ICHPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0 /* expose to user */
>  };
>  
>  struct cfattach ichpcib_ca = {
> diff --git sys/arch/landisk/include/timetc.h sys/arch/landisk/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/landisk/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/loongson/include/timetc.h sys/arch/loongson/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/loongson/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/loongson/loongson/generic3a_machdep.c sys/arch/loongson/loongson/generic3a_machdep.c
> index ac3f1db6ccd..53489b07549 100644
> --- sys/arch/loongson/loongson/generic3a_machdep.c
> +++ sys/arch/loongson/loongson/generic3a_machdep.c
> @@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = {
>   .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */
>   .tc_frequency = HPET_FREQ,
>   .tc_name = "hpet",
> - .tc_quality = 100
> + .tc_quality = 100,
> + .tc_priv = NULL,
> + .tc_user = 0,
>  };
>  
>  /* Firmware entry points */
> diff --git sys/arch/luna88k/include/timetc.h sys/arch/luna88k/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/luna88k/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/luna88k/luna88k/clock.c sys/arch/luna88k/luna88k/clock.c
> index a04120987e0..6580a4a46bf 100644
> --- sys/arch/luna88k/luna88k/clock.c
> +++ sys/arch/luna88k/luna88k/clock.c
> @@ -112,7 +112,9 @@ struct timecounter clock_tc = {
>   .tc_counter_mask = 0xffffffff,
>   .tc_frequency = 0, /* will be filled in */
>   .tc_name = "clock",
> - .tc_quality = 0
> + .tc_quality = 0,
> + .tc_priv = NULL,
> + .tc_user = 0,
>  };
>  
>  /*
> diff --git sys/arch/m88k/include/timetc.h sys/arch/m88k/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/m88k/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/macppc/include/timetc.h sys/arch/macppc/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/macppc/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/macppc/macppc/clock.c sys/arch/macppc/macppc/clock.c
> index 4a44a92cfc0..8c3ad620be8 100644
> --- sys/arch/macppc/macppc/clock.c
> +++ sys/arch/macppc/macppc/clock.c
> @@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320;
>  static int32_t ticks_per_intr;
>  
>  static struct timecounter tb_timecounter = {
> - tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
> + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0
>  };
>  
>  /* calibrate the timecounter frequency for the listed models */
> diff --git sys/arch/mips64/include/timetc.h sys/arch/mips64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/mips64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/mips64/mips64/mips64_machdep.c sys/arch/mips64/mips64/mips64_machdep.c
> index d4a42ed5acc..5c4dbadb5bb 100644
> --- sys/arch/mips64/mips64/mips64_machdep.c
> +++ sys/arch/mips64/mips64/mips64_machdep.c
> @@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = {
>   0xffffffff, /* counter_mask */
>   0, /* frequency */
>   "CP0", /* name */
> - 0 /* quality */
> + 0, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  u_int
> diff --git sys/arch/octeon/include/timetc.h sys/arch/octeon/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/octeon/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/octeon/octeon/machdep.c sys/arch/octeon/octeon/machdep.c
> index 902e462d53f..d8377653abe 100644
> --- sys/arch/octeon/octeon/machdep.c
> +++ sys/arch/octeon/octeon/machdep.c
> @@ -151,8 +151,9 @@ struct timecounter ioclock_timecounter = {
>   .tc_name = "ioclock",
>   .tc_quality = 0, /* ioclock can be overridden
>   * by cp0 counter */
> - .tc_priv = 0 /* clock register,
> + .tc_priv = 0, /* clock register,
>   * determined at runtime */
> + .tc_user = 0, /* expose to user */
>  };
>  
>  static int
> diff --git sys/arch/powerpc/include/timetc.h sys/arch/powerpc/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/powerpc/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/powerpc64/include/timetc.h sys/arch/powerpc64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/powerpc64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sgi/include/timetc.h sys/arch/sgi/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/sgi/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sgi/sgi/ip27_machdep.c sys/arch/sgi/sgi/ip27_machdep.c
> index ba7fa558b96..2a2cc144242 100644
> --- sys/arch/sgi/sgi/ip27_machdep.c
> +++ sys/arch/sgi/sgi/ip27_machdep.c
> @@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = {
>   .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */
>   .tc_frequency = 1250000,
>   .tc_name = "hubrt",
> - .tc_quality = 100
> + .tc_quality = 100,
> + .tc_priv = 0,
> + .tc_user = 0,
>  };
>  
>  volatile uint64_t ip27_spinup_a0;
> diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c
> index 56b29915c70..827775512ac 100644
> --- sys/arch/sgi/xbow/xheart.c
> +++ sys/arch/sgi/xbow/xheart.c
> @@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = {
>   .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit */
>   .tc_frequency = 12500000,
>   .tc_name = "heart",
> - .tc_quality = 100
> + .tc_quality = 100,
> + .tc_priv = NULL,
> + .tc_user = 0,
>  };
>  
>  extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *);
> diff --git sys/arch/sh/include/timetc.h sys/arch/sh/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/sh/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sparc64/dev/psycho.c sys/arch/sparc64/dev/psycho.c
> index e24f804dff6..1a7a1afa8c2 100644
> --- sys/arch/sparc64/dev/psycho.c
> +++ sys/arch/sparc64/dev/psycho.c
> @@ -127,7 +127,7 @@ extern struct sparc_pci_chipset _sparc_pci_chipset;
>  u_int stick_get_timecount(struct timecounter *);
>  
>  struct timecounter stick_timecounter = {
> - stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
> + stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0
>  };
>  
>  /*
> diff --git sys/arch/sparc64/include/timetc.h sys/arch/sparc64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/sparc64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sparc64/sparc64/clock.c sys/arch/sparc64/sparc64/clock.c
> index fd5e8a9c15b..5c2e47d386b 100644
> --- sys/arch/sparc64/sparc64/clock.c
> +++ sys/arch/sparc64/sparc64/clock.c
> @@ -109,13 +109,13 @@ struct cfdriver clock_cd = {
>  u_int tick_get_timecount(struct timecounter *);
>  
>  struct timecounter tick_timecounter = {
> - tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL
> + tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0
>  };
>  
>  u_int sys_tick_get_timecount(struct timecounter *);
>  
>  struct timecounter sys_tick_timecounter = {
> - sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL
> + sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0
>  };
>  
>  /*
> diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c
> index d0ee72cec9b..13177a909da 100644
> --- sys/dev/acpi/acpihpet.c
> +++ sys/dev/acpi/acpihpet.c
> @@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = {
>   0xffffffff, /* counter_mask (32 bits) */
>   0, /* frequency */
>   0, /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  #define HPET_TIMERS 3
> diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c
> index cdc8c99a17a..89b5a397e47 100644
> --- sys/dev/acpi/acpitimer.c
> +++ sys/dev/acpi/acpitimer.c
> @@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = {
>   0x00ffffff, /* counter_mask (24 bits) */
>   ACPI_FREQUENCY, /* frequency */
>   0, /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  struct acpitimer_softc {
> diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c
> index 6df82858016..9610d5bc1f0 100644
> --- sys/dev/pci/amdpm.c
> +++ sys/dev/pci/amdpm.c
> @@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = {
>   0xffffff, /* counter_mask */
>   AMDPM_FREQUENCY, /* frequency */
>   "AMDPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  #define AMDPM_CONFREG 0x40
> diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c
> index db806eedf80..ce33cd175e6 100644
> --- sys/dev/pci/viapm.c
> +++ sys/dev/pci/viapm.c
> @@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = {
>   0xffffff, /* counter_mask */
>   VIAPM_FREQUENCY, /* frequency */
>   "VIAPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  struct timeout viapm_timeout;
> diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c
> index b32facdacb1..b9ee2feec4c 100644
> --- sys/dev/pv/hyperv.c
> +++ sys/dev/pv/hyperv.c
> @@ -141,7 +141,7 @@ struct {
>  };
>  
>  struct timecounter hv_timecounter = {
> - hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001
> + hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0
>  };
>  
>  struct cfdriver hyperv_cd = {
> diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c
> index 6b242f7448d..b80e4d2a484 100644
> --- sys/dev/pv/pvclock.c
> +++ sys/dev/pv/pvclock.c
> @@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = {
>  };
>  
>  struct timecounter pvclock_timecounter = {
> - pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL
> + pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0
>  };
>  
>  int
> diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c
> index 9b5b8eb3acf..59bc923a6fb 100644
> --- sys/kern/exec_elf.c
> +++ sys/kern/exec_elf.c
> @@ -124,7 +124,7 @@ extern char *syscallnames[];
>  /*
>   * How many entries are in the AuxInfo array we pass to the process?
>   */
> -#define ELF_AUX_ENTRIES 8
> +#define ELF_AUX_ENTRIES 9
>  
>  /*
>   * This is the OpenBSD ELF emul
> @@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct exec_package *epp)
>   a->au_v = ap->arg_entry;
>   a++;
>  
> + a->au_id = AUX_openbsd_timekeep;
> + a->au_v = p->p_p->ps_timekeep;
> + a++;
> +
>   a->au_id = AUX_null;
>   a->au_v = 0;
>   a++;
> diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
> index 20480c2fc28..b695b6dc627 100644
> --- sys/kern/kern_exec.c
> +++ sys/kern/kern_exec.c
> @@ -64,6 +64,11 @@
>  #include <uvm/uvm_extern.h>
>  #include <machine/tcb.h>
>  
> +#include <sys/timetc.h>
> +
> +struct uvm_object *timekeep_object;
> +struct timekeep* timekeep;
> +
>  void unveil_destroy(struct process *ps);
>  
>  const struct kmem_va_mode kv_exec = {
> @@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = {
>   */
>  int exec_sigcode_map(struct process *, struct emul *);
>  
> +/*
> + * Map the shared timekeep page.
> + */
> +int exec_timekeep_map(struct process *);
> +
>  /*
>   * If non-zero, stackgap_random specifies the upper limit of the random gap size
>   * added to the fixed stack position. Must be n^2.
> @@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t *retval)
>   /* map the process's signal trampoline code */
>   if (exec_sigcode_map(pr, pack.ep_emul))
>   goto free_pack_abort;
> + /* map the process's timekeep page */
> + if (exec_timekeep_map(pr))
> + goto free_pack_abort;
>  
>  #ifdef __HAVE_EXEC_MD_MAP
>   /* perform md specific mappings that process might need */
> @@ -863,3 +876,40 @@ exec_sigcode_map(struct process *pr, struct emul *e)
>  
>   return (0);
>  }
> +
> +int
> +exec_timekeep_map(struct process *pr)
> +{
> + size_t timekeep_sz = sizeof(struct timekeep);
> +
> + /*
> + * Similar to the sigcode object, except that there is a single timekeep
> + * object, and not one per emulation.
> + */

Pleas wrap the line after "single" to prevent this from hitting column 79.

> + if (timekeep_object == NULL) {
> + vaddr_t va;
> +
> + timekeep_object = uao_create(timekeep_sz, 0);
> + uao_reference(timekeep_object);
> +
> + if (uvm_map(kernel_map, &va, round_page(timekeep_sz), timekeep_object,
> +    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
> +    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
> + uao_detach(timekeep_object);
> + return (ENOMEM);
> + }
> +
> + timekeep = (struct timekeep *)va;
> + timekeep->tk_version = TK_VERSION;
> + }
> +
> + uao_reference(timekeep_object);
> + if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, round_page(timekeep_sz),
> +    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
> +    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
> + uao_detach(timekeep_object);
> + return (ENOMEM);
> + }
> +
> + return (0);
> +}
> diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
> index 88d4a3379f9..47efbdd0b78 100644
> --- sys/kern/kern_tc.c
> +++ sys/kern/kern_tc.c
> @@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc)
>  }
>  
>  static struct timecounter dummy_timecounter = {
> - dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
> + dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0
>  };
>  
>  /*
> @@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts)
>  #endif
>  }
>  
> +void
> +tc_update_timekeep(void)
> +{
> + static struct timecounter *last_tc = NULL;
> + struct timehands *th;
> +
> + if (timekeep == NULL)
> + return;
> +
> + th = timehands;
> + timekeep->tk_generation = 0;
> + membar_producer();
> + timekeep->tk_scale = th->th_scale;
> + timekeep->tk_offset_count = th->th_offset_count;
> + timekeep->tk_offset = th->th_offset;
> + timekeep->tk_naptime = th->th_naptime;
> + timekeep->tk_boottime = th->th_boottime;
> + if (last_tc != th->th_counter) {
> + timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
> + timekeep->tk_user = th->th_counter->tc_user;
> + last_tc = th->th_counter;
> + }
> + membar_producer();
> + timekeep->tk_generation = th->th_generation;
> +
> + return;
> +}
> +
>  /*
>   * Initialize the next struct timehands in the ring and make
>   * it the active timehands.  Along the way we might switch to a different
> @@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
>   time_uptime = th->th_offset.sec;
>   membar_producer();
>   timehands = th;
> +
> + tc_update_timekeep();
>  }
>  
>  /* Report or change the active timecounter hardware. */
> diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h
> index a40e0510273..3084ed595a6 100644
> --- sys/sys/exec_elf.h
> +++ sys/sys/exec_elf.h
> @@ -691,7 +691,8 @@ enum AuxID {
>   AUX_sun_uid = 2000, /* euid */
>   AUX_sun_ruid = 2001, /* ruid */
>   AUX_sun_gid = 2002, /* egid */
> - AUX_sun_rgid = 2003 /* rgid */
> + AUX_sun_rgid = 2003, /* rgid */
> + AUX_openbsd_timekeep = 4000, /* userland clock_gettime */
>  };
>  
>  struct elf_args {
> diff --git sys/sys/proc.h sys/sys/proc.h
> index 357c0c0d52c..c6d54572bdd 100644
> --- sys/sys/proc.h
> +++ sys/sys/proc.h
> @@ -242,6 +242,7 @@ struct process {
>   char ps_comm[MAXCOMLEN+1];
>  
>   vaddr_t ps_strings; /* User pointers to argv/env */
> + vaddr_t ps_timekeep; /* User pointer to timekeep */
>   vaddr_t ps_sigcode; /* User pointer to the signal code */
>   vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */
>   u_long ps_sigcookie;
> diff --git sys/sys/time.h sys/sys/time.h
> index e758a64ce07..bcd3acd034d 100644
> --- sys/sys/time.h
> +++ sys/sys/time.h
> @@ -163,7 +163,7 @@ struct clockinfo {
>  };
>  #endif /* __BSD_VISIBLE */
>  
> -#if defined(_KERNEL) || defined(_STANDALONE)
> +#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC)
>  #include <sys/_time.h>
>  
>  /* Time expressed as seconds and fractions of a second + operations on it. */
> @@ -171,6 +171,9 @@ struct bintime {
>   time_t sec;
>   uint64_t frac;
>  };
> +#endif
> +
> +#if defined(_KERNEL) || defined(_STANDALONE)
>  
>  #define bintimecmp(btp, ctp, cmp) \
>   ((btp)->sec == (ctp)->sec ? \
> diff --git sys/sys/timetc.h sys/sys/timetc.h
> index ce81c3475a0..c5ad27695ba 100644
> --- sys/sys/timetc.h
> +++ sys/sys/timetc.h
> @@ -24,10 +24,11 @@
>  #ifndef _SYS_TIMETC_H_
>  #define _SYS_TIMETC_H_
>  
> -#ifndef _KERNEL
> +#if !defined(_KERNEL) && !defined(_LIBC)
>  #error "no user-serviceable parts inside"
>  #endif
>  
> +#include <machine/timetc.h>
>  #include <sys/queue.h>
>  
>  /*-
> @@ -80,6 +81,8 @@ struct timecounter {
>   */
>   void *tc_priv; /* [I] */
>   /* Pointer to the timecounter's private parts. */
> + int tc_user; /* [I] */
> + /* Expose this timecounter to userland. */
>   SLIST_ENTRY(timecounter) tc_next; /* [I] */
>   /* Pointer to the next timecounter. */
>   int64_t tc_freq_adj; /* [tw] */
> @@ -88,11 +91,32 @@ struct timecounter {
>   /* Precision of the counter.  Computed in tc_init(). */
>  };
>  
> +struct timekeep {
> + /* set at initialization */
> + uint32_t tk_version; /* version number */
> +
> + /* timehands members */
> + uint64_t tk_scale;
> + u_int tk_offset_count;
> + struct bintime tk_offset;
> + struct bintime tk_naptime;
> + struct bintime tk_boottime;
> + volatile u_int tk_generation;
> +
> + /* timecounter members */
> + int tk_user;
> + u_int tk_counter_mask;
> +};
> +#define TK_VERSION 0
> +
>  struct rwlock;
>  extern struct rwlock tc_lock;
>  
>  extern struct timecounter *timecounter;
>  
> +extern struct uvm_object *timekeep_object;
> +extern struct timekeep *timekeep;
> +
>  u_int64_t tc_getfrequency(void);
>  u_int64_t tc_getprecision(void);
>  void tc_init(struct timecounter *tc);
>
>

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Paul Irofti-4
On Fri, Jun 19, 2020 at 06:52:40PM +0200, Mark Kettenis wrote:

> > Date: Fri, 19 Jun 2020 14:31:17 +0300
> > From: Paul Irofti <[hidden email]>
> >
> > Hi,
> >
> > Here is another iteration of the diff that addresses all issues raised
> > in the meantime:
> >
> >   - Switch tc to uint
>
> The request was to use u_int, like we de in the kernel.  The uint type
> should not be used in OpenBSD code.
>
> >   - Check for version at init and switch to machite/timetc.h defs
> >   - Remove tk_nclocks
> >   - Switch to single version and ditch minor/major
> >   - Do not enable user TSC for large skew values
> >   - Add amd64 clocks and use the define in TSC
> >   - Include and add machine/timetc.h
> >
> > As we have seen most architectures have support for clocks now and the
> > above addresses Mark's last concerns.
> >
> > Unless other blocking issues arise, this time around I am looking for
> > OKs to commit. Theo? Mark?
>
> There is one other issue that I wanted to raise.  An that is whether
> we really need to implement CLOCK_UPTINME as a userland clock.  If we
> don't do that we can drop tk_naptime from the shared struct.  I
> mention this because th_naptime was only recently added to struct
> timehands and much more an implementation detail than the other fields.
>
> I don't expect userland processes to call CLOCK_UPTIME in a loop like
> they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
> doesn't have it ;).

I don't care eitherway about this. But I don't see why we would not have
this functionality if it is easy to offer. Maybe someone can help us
grep the ports tree for this? Stuart? :)

> We're getting there...

I have addressed your comments bellow, except for the CPU skew one. That
code disables TSC for all CPUs, not just for PRIMARY. Would you like to
walk and add code for every CPU to check the drift and then disable the
TSC? It seems a little too much...


diff --git lib/libc/arch/aarch64/gen/Makefile.inc lib/libc/arch/aarch64/gen/Makefile.inc
index a7b1b73f3ef..ee198f5d611 100644
--- lib/libc/arch/aarch64/gen/Makefile.inc
+++ lib/libc/arch/aarch64/gen/Makefile.inc
@@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
 SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
 SRCS+= fpclassifyl.c
 SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
-SRCS+= signbitl.c
+SRCS+= signbitl.c usertc.c
diff --git lib/libc/arch/aarch64/gen/usertc.c lib/libc/arch/aarch64/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/aarch64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/alpha/gen/Makefile.inc lib/libc/arch/alpha/gen/Makefile.inc
index a44599d2cab..2a8abd32b61 100644
--- lib/libc/arch/alpha/gen/Makefile.inc
+++ lib/libc/arch/alpha/gen/Makefile.inc
@@ -3,5 +3,5 @@
 
 SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
- fpsetround.c fpsetsticky.c
+ fpsetround.c fpsetsticky.c usertc.c
 SRCS+= sigsetjmp.S
diff --git lib/libc/arch/alpha/gen/usertc.c lib/libc/arch/alpha/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/alpha/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/amd64/gen/Makefile.inc lib/libc/arch/amd64/gen/Makefile.inc
index e995309ed71..f6349e2b974 100644
--- lib/libc/arch/amd64/gen/Makefile.inc
+++ lib/libc/arch/amd64/gen/Makefile.inc
@@ -2,6 +2,7 @@
 
 SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
  sigsetjmp.S
-SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
+SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \
+ usertc.c
 SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
  fpsetround.S fpsetsticky.S
diff --git lib/libc/arch/amd64/gen/usertc.c lib/libc/arch/amd64/gen/usertc.c
new file mode 100644
index 00000000000..742fb0cc458
--- /dev/null
+++ lib/libc/arch/amd64/gen/usertc.c
@@ -0,0 +1,41 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+static inline uint
+rdtsc(void)
+{
+ uint32_t hi, lo;
+ asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((uint64_t)lo)|(((uint64_t)hi)<<32);
+}
+
+int
+tc_get_timecount(struct timekeep *tk, u_int *tc)
+{
+ int tk_user = tk->tk_user;
+
+ if (tk_user < 1 || tk_user >= TC_LAST)
+ return -1;
+
+ *tc = rdtsc();
+ return 0;
+}
+int (*const _tc_get_timecount)(struct timekeep *tk, u_int *tc)
+ = tc_get_timecount;
diff --git lib/libc/arch/arm/gen/Makefile.inc lib/libc/arch/arm/gen/Makefile.inc
index 1b4ab2f3ae7..27090a0d9dc 100644
--- lib/libc/arch/arm/gen/Makefile.inc
+++ lib/libc/arch/arm/gen/Makefile.inc
@@ -2,5 +2,5 @@
 # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
 
 SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c infinity.c
-SRCS+= ldexp.c modf.c nan.c
+SRCS+= ldexp.c modf.c nan.c usertc.c
 SRCS+= setjmp.S _setjmp.S sigsetjmp.S
diff --git lib/libc/arch/arm/gen/usertc.c lib/libc/arch/arm/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/arm/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/hppa/gen/Makefile.inc lib/libc/arch/hppa/gen/Makefile.inc
index e0c864242fe..1fde24670f1 100644
--- lib/libc/arch/hppa/gen/Makefile.inc
+++ lib/libc/arch/hppa/gen/Makefile.inc
@@ -2,6 +2,6 @@
 
 SRCS+= setjmp.S
 SRCS+= fabs.c
-SRCS+= infinity.c ldexp.c modf.c nan.c
+SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
diff --git lib/libc/arch/hppa/gen/usertc.c lib/libc/arch/hppa/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/hppa/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/i386/gen/Makefile.inc lib/libc/arch/i386/gen/Makefile.inc
index 4c18e059581..b7dd30adccd 100644
--- lib/libc/arch/i386/gen/Makefile.inc
+++ lib/libc/arch/i386/gen/Makefile.inc
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
  modf.S nan.c setjmp.S sigsetjmp.S
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
 SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
diff --git lib/libc/arch/i386/gen/usertc.c lib/libc/arch/i386/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/i386/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/m88k/gen/Makefile.inc lib/libc/arch/m88k/gen/Makefile.inc
index cff75b8d425..d66f66af4af 100644
--- lib/libc/arch/m88k/gen/Makefile.inc
+++ lib/libc/arch/m88k/gen/Makefile.inc
@@ -1,7 +1,7 @@
 # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
 # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
 SRCS+= setjmp.S sigsetjmp.S
diff --git lib/libc/arch/m88k/gen/usertc.c lib/libc/arch/m88k/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/m88k/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/mips64/gen/Makefile.inc lib/libc/arch/mips64/gen/Makefile.inc
index 8cf1fc2d28a..839241a2069 100644
--- lib/libc/arch/mips64/gen/Makefile.inc
+++ lib/libc/arch/mips64/gen/Makefile.inc
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
diff --git lib/libc/arch/mips64/gen/usertc.c lib/libc/arch/mips64/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/mips64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/powerpc/gen/Makefile.inc lib/libc/arch/powerpc/gen/Makefile.inc
index 6b2e4613ee8..d4d7b00bff7 100644
--- lib/libc/arch/powerpc/gen/Makefile.inc
+++ lib/libc/arch/powerpc/gen/Makefile.inc
@@ -1,5 +1,5 @@
 SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c nan.c
-SRCS+= fabs.c
+SRCS+= fabs.c usertc.c
 SRCS+= fpgetmask.c fpsetmask.c
 SRCS+= fpgetround.c fpsetround.c
 SRCS+= fpgetsticky.c fpsetsticky.c
diff --git lib/libc/arch/powerpc/gen/usertc.c lib/libc/arch/powerpc/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/powerpc/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/sh/gen/Makefile.inc lib/libc/arch/sh/gen/Makefile.inc
index 55de1973b30..4724fb3a6a8 100644
--- lib/libc/arch/sh/gen/Makefile.inc
+++ lib/libc/arch/sh/gen/Makefile.inc
@@ -3,4 +3,4 @@
 SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S _setjmp.S
 SRCS+= sigsetjmp.S
 SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
- fpsetmask.c fpsetround.c fpsetsticky.c
+ fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
diff --git lib/libc/arch/sh/gen/usertc.c lib/libc/arch/sh/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/sh/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/sparc64/gen/Makefile.inc lib/libc/arch/sparc64/gen/Makefile.inc
index 58259cedef6..a908e022954 100644
--- lib/libc/arch/sparc64/gen/Makefile.inc
+++ lib/libc/arch/sparc64/gen/Makefile.inc
@@ -3,5 +3,5 @@
 SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
  fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
- isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
+ isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
  mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
diff --git lib/libc/arch/sparc64/gen/usertc.c lib/libc/arch/sparc64/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/sparc64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
index 131da4b2190..40e84771f86 100644
--- lib/libc/asr/asr.c
+++ lib/libc/asr/asr.c
@@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds, int timeout)
  struct timespec pollstart, pollend, elapsed;
  int r;
 
- if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
  return -1;
 
  while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
- if (clock_gettime(CLOCK_MONOTONIC, &pollend))
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
  return -1;
  timespecsub(&pollend, &pollstart, &elapsed);
  timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
@@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
  asr->a_rtime = 0;
  }
 
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
  return;
 
  if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
index 82de8fa33b7..02fd3013cc1 100644
--- lib/libc/crypt/bcrypt.c
+++ lib/libc/crypt/bcrypt.c
@@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
  char buf[_PASSWORD_LEN];
  int duration;
 
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
+ WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
  bcrypt_newhash("testpassword", r, buf, sizeof(buf));
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
+ WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
 
  duration = after.tv_sec - before.tv_sec;
  duration *= 1000000;
diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
index 270f54aada5..d2632455f11 100644
--- lib/libc/dlfcn/init.c
+++ lib/libc/dlfcn/init.c
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 #include <sys/syscall.h>
+#include <sys/timetc.h> /* timekeep */
 
 #ifndef PIC
 #include <sys/mman.h>
@@ -45,8 +46,9 @@
 /* XXX should be in an include file shared with csu */
 char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void));
 
-/* provide definition for this */
+/* provide definitions for these */
 int _pagesize = 0;
+struct timekeep *_timekeep;
 
 /*
  * In dynamicly linked binaries environ and __progname are overriden by
@@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb)
  phnum = aux->au_v;
  break;
 #endif /* !PIC */
+ case AUX_openbsd_timekeep:
+ if (_tc_get_timecount) {
+ _timekeep = (void *)aux->au_v;
+ if (_timekeep->tk_version != TK_VERSION)
+ _timekeep = NULL;
+ }
+ break;
  }
  }
 
diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
index 1286a96fe40..32f86eda50f 100644
--- lib/libc/gen/auth_subr.c
+++ lib/libc/gen/auth_subr.c
@@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
 
  if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
  if (as->now.tv_sec == 0)
- gettimeofday(&as->now, NULL);
+ WRAP(gettimeofday)(&as->now, NULL);
  if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
  as->state &= ~AUTH_ALLOW;
  as->state |= AUTH_EXPIRED;
@@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
 
  if (as->pwd && (quad_t)as->pwd->pw_change) {
  if (as->now.tv_sec == 0)
- gettimeofday(&as->now, NULL);
+ WRAP(gettimeofday)(&as->now, NULL);
  if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
  as->state &= ~AUTH_ALLOW;
  as->state |= AUTH_PWEXPIRED;
diff --git lib/libc/gen/time.c lib/libc/gen/time.c
index 3bbd0d733d1..b3ce9a800f1 100644
--- lib/libc/gen/time.c
+++ lib/libc/gen/time.c
@@ -36,7 +36,7 @@ time(time_t *t)
 {
  struct timeval tt;
 
- if (gettimeofday(&tt, NULL) == -1)
+ if (WRAP(gettimeofday)(&tt, NULL) == -1)
  return (-1);
  if (t)
  *t = (time_t)tt.tv_sec;
diff --git lib/libc/gen/times.c lib/libc/gen/times.c
index 02e4dd44b5c..36841810d1b 100644
--- lib/libc/gen/times.c
+++ lib/libc/gen/times.c
@@ -52,7 +52,7 @@ times(struct tms *tp)
  return ((clock_t)-1);
  tp->tms_cutime = CONVTCK(ru.ru_utime);
  tp->tms_cstime = CONVTCK(ru.ru_stime);
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
  return ((clock_t)-1);
  return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK));
 }
diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
index 520a5954025..845cbe80356 100644
--- lib/libc/gen/timespec_get.c
+++ lib/libc/gen/timespec_get.c
@@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
 {
  switch (base) {
  case TIME_UTC:
- if (clock_gettime(CLOCK_REALTIME, ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
  return 0;
  break;
  default:
diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
index ed112320fa2..df717021cab 100644
--- lib/libc/hidden/sys/time.h
+++ lib/libc/hidden/sys/time.h
@@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
 PROTO_NORMAL(adjtime);
 PROTO_NORMAL(futimes);
 PROTO_NORMAL(getitimer);
-PROTO_NORMAL(gettimeofday);
+PROTO_WRAP(gettimeofday);
 PROTO_NORMAL(setitimer);
 PROTO_NORMAL(settimeofday);
 PROTO_NORMAL(utimes);
diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h
new file mode 100644
index 00000000000..bbdaa2d0d4c
--- /dev/null
+++ lib/libc/hidden/sys/timetc.h
@@ -0,0 +1,38 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBC_SYS_TIMETC_H_
+#define _LIBC_SYS_TIMETC_H_
+
+#define _LIBC
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include_next <sys/timetc.h>
+
+__BEGIN_HIDDEN_DECLS
+extern struct timekeep *_timekeep;
+
+extern int (*const _tc_get_timecount)(struct timekeep *, u_int *);
+
+int _microtime(struct timeval *, struct timekeep *);
+int _nanotime(struct timespec *, struct timekeep *);
+int _nanoruntime(struct timespec *, struct timekeep *);
+int _nanouptime(struct timespec *, struct timekeep *);
+__END_HIDDEN_DECLS
+
+#endif /* !_LIBC_SYS_TIMETC_H_ */
diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h
index 18c49f8fcb9..d8e1e0caf64 100644
--- lib/libc/hidden/time.h
+++ lib/libc/hidden/time.h
@@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r);
 PROTO_STD_DEPRECATED(clock);
 PROTO_DEPRECATED(clock_getcpuclockid);
 PROTO_NORMAL(clock_getres);
-PROTO_NORMAL(clock_gettime);
+PROTO_WRAP(clock_gettime);
 PROTO_NORMAL(clock_settime);
 PROTO_STD_DEPRECATED(ctime);
 PROTO_DEPRECATED(ctime_r);
diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c
index 763e420bb88..9babb28470a 100644
--- lib/libc/net/res_random.c
+++ lib/libc/net/res_random.c
@@ -219,7 +219,7 @@ res_initid(void)
  if (ru_prf != NULL)
  arc4random_buf(ru_prf, sizeof(*ru_prf));
 
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
  ru_reseed = ts.tv_sec + RU_OUT;
  ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
 }
@@ -232,7 +232,7 @@ __res_randomid(void)
  u_int r;
  static void *randomid_mutex;
 
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
  pid = getpid();
 
  _MUTEX_LOCK(&randomid_mutex);
diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c
index 402d98cede4..917a6d42b8a 100644
--- lib/libc/rpc/auth_unix.c
+++ lib/libc/rpc/auth_unix.c
@@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
  /*
  * fill in param struct from the given params
  */
- (void)gettimeofday(&now,  NULL);
+ (void)WRAP(gettimeofday)(&now,  NULL);
  aup.aup_time = now.tv_sec;
  aup.aup_machname = machname;
  aup.aup_uid = uid;
@@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth)
  goto done;
 
  /* update the time and serialize in place */
- (void)gettimeofday(&now, NULL);
+ (void)WRAP(gettimeofday)(&now, NULL);
  aup.aup_time = now.tv_sec;
  xdrs.x_op = XDR_ENCODE;
  XDR_SETPOS(&xdrs, 0);
diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c
index 8e6ef515b0e..927b4bf2028 100644
--- lib/libc/rpc/clnt_tcp.c
+++ lib/libc/rpc/clnt_tcp.c
@@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int len)
  pfd[0].events = POLLIN;
  TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait);
  delta = wait;
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  for (;;) {
  r = ppoll(pfd, 1, &delta, NULL);
  save_errno = errno;
 
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&start, &after, &duration);
  timespecsub(&wait, &duration, &delta);
  if (delta.tv_sec < 0 || !timespecisset(&delta))
diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c
index 68d01674410..92e1d5c350d 100644
--- lib/libc/rpc/clnt_udp.c
+++ lib/libc/rpc/clnt_udp.c
@@ -265,7 +265,7 @@ send_again:
  reply_msg.acpted_rply.ar_results.where = resultsp;
  reply_msg.acpted_rply.ar_results.proc = xresults;
 
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  for (;;) {
  switch (ppoll(pfd, 1, &wait, NULL)) {
  case 0:
@@ -283,7 +283,7 @@ send_again:
  /* FALLTHROUGH */
  case -1:
  if (errno == EINTR) {
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&after, &start, &duration);
  timespecadd(&time_waited, &duration, &time_waited);
  if (timespeccmp(&time_waited, &timeout, <))
diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c
index f9d7a70938f..6c99db84359 100644
--- lib/libc/rpc/svc_tcp.c
+++ lib/libc/rpc/svc_tcp.c
@@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
  * A timeout is fatal for the connection.
  */
  delta = wait_per_try;
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  pfd[0].fd = sock;
  pfd[0].events = POLLIN;
  do {
@@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
  case -1:
  if (errno != EINTR)
  goto fatal_err;
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&after, &start, &duration);
  timespecsub(&wait_per_try, &duration, &delta);
  if (delta.tv_sec < 0 || !timespecisset(&delta))
diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc
index 34769576ced..d57418d81bf 100644
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \
 
 # glue to offer userland wrappers for some syscalls
 SRCS+= posix_madvise.c pthread_sigmask.c \
- w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c
+ w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \
+ w_clock_gettime.c w_gettimeofday.c microtime.c
 
 # glue for compat with old syscall interfaces.
 SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c truncate.c \
@@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c w_pwrite.c w_pwritev.c
 ASM= __semctl.o __syscall.o __thrsigdivert.o \
  access.o acct.o adjfreq.o adjtime.o \
  bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \
- clock_getres.o clock_gettime.o clock_settime.o \
+ clock_getres.o clock_settime.o \
  dup.o dup2.o dup3.o \
  execve.o \
  faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \
@@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \
  getgroups.o getitimer.o getpeername.o getpgid.o \
  getpriority.o getresgid.o getresuid.o \
  getrlimit.o getrusage.o getsid.o getsockname.o \
- getsockopt.o gettimeofday.o ioctl.o \
+ getsockopt.o ioctl.o \
  kevent.o kill.o kqueue.o ktrace.o lchown.o \
  link.o linkat.o listen.o lstat.o madvise.o \
  minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
@@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po}
 SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so}
 DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do}
 
-HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o}
+HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o} \
+ clock_gettime.o gettimeofday.o
 PHIDDEN=${HIDDEN:.o=.po}
 SHIDDEN=${HIDDEN:.o=.so}
 DHIDDEN=${HIDDEN:.o=.do}
diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c
new file mode 100644
index 00000000000..5191b5b2606
--- /dev/null
+++ lib/libc/sys/microtime.c
@@ -0,0 +1,181 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2000 Poul-Henning Kamp <[hidden email]>
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/atomic.h>
+#include <sys/timetc.h>
+
+#include <time.h>
+
+/*
+ * Return the difference between the timehands' counter value now and what
+ * was when we copied it to the timehands' offset_count.
+ */
+static inline int
+tc_delta(struct timekeep *tk, u_int *delta)
+{
+ uint tc;
+
+ if (_tc_get_timecount(tk, &tc))
+ return -1;
+ *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
+ return 0;
+}
+
+static inline void
+bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct)
+{
+ ct->sec = bt->sec;
+ if (bt->frac > bt->frac + x)
+ ct->sec++;
+ ct->frac = bt->frac + x;
+}
+
+static inline void
+BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts)
+{
+ ts->tv_sec = bt->sec;
+ ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32);
+}
+
+static inline void
+BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv)
+{
+ tv->tv_sec = bt->sec;
+ tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32);
+}
+
+static int
+binuptime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ *bt = tk->tk_offset;
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(bt, tk->tk_scale * delta, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+static inline void
+bintimeadd(const struct bintime *bt, const struct bintime *ct,
+    struct bintime *dt)
+{
+ dt->sec = bt->sec + ct->sec;
+ if (bt->frac > bt->frac + ct->frac)
+ dt->sec++;
+ dt->frac = bt->frac + ct->frac;
+}
+
+static inline void
+bintimesub(const struct bintime *bt, const struct bintime *ct,
+    struct bintime *dt)
+{
+ dt->sec = bt->sec - ct->sec;
+ if (bt->frac < bt->frac - ct->frac)
+ dt->sec--;
+ dt->frac = bt->frac - ct->frac;
+}
+
+static int
+binruntime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt);
+ bintimesub(bt, &tk->tk_naptime, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+static int
+bintime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ *bt = tk->tk_offset;
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(bt, tk->tk_scale * delta, bt);
+ bintimeadd(bt, &tk->tk_boottime, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+int
+_microtime(struct timeval *tvp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (bintime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMEVAL(&bt, tvp);
+ return 0;
+}
+
+int
+_nanotime(struct timespec *tsp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (bintime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, tsp);
+ return 0;
+}
+
+int
+_nanoruntime(struct timespec *ts, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (binruntime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, ts);
+ return 0;
+}
+
+
+int
+_nanouptime(struct timespec *tsp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (binuptime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, tsp);
+ return 0;
+}
diff --git lib/libc/sys/w_clock_gettime.c lib/libc/sys/w_clock_gettime.c
new file mode 100644
index 00000000000..6e6478bd131
--- /dev/null
+++ lib/libc/sys/w_clock_gettime.c
@@ -0,0 +1,51 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/timetc.h>
+
+#include <time.h>
+
+int
+WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp)
+{
+ int rc = 0;
+ struct timekeep *timekeep = _timekeep;
+
+ if (timekeep == NULL || timekeep->tk_user == 0)
+ return clock_gettime(clock_id, tp);
+
+ switch (clock_id) {
+ case CLOCK_REALTIME:
+ rc = _nanotime(tp, timekeep);
+ break;
+ case CLOCK_UPTIME:
+ rc = _nanoruntime(tp, timekeep);
+ break;
+ case CLOCK_MONOTONIC:
+ case CLOCK_BOOTTIME:
+ rc = _nanouptime(tp, timekeep);
+ break;
+ default:
+ return clock_gettime(clock_id, tp);
+ }
+
+ if (rc)
+ return clock_gettime(clock_id, tp);
+
+ return 0;
+}
+DEF_WRAP(clock_gettime);
diff --git lib/libc/sys/w_gettimeofday.c lib/libc/sys/w_gettimeofday.c
new file mode 100644
index 00000000000..f44edfbb1ad
--- /dev/null
+++ lib/libc/sys/w_gettimeofday.c
@@ -0,0 +1,40 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Robert Nagy <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/timetc.h>
+
+int
+WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp)
+{
+ int rc = 0;
+ struct timekeep *timekeep = _timekeep;
+ static struct timezone zerotz = { 0, 0 };
+
+ if (timekeep == NULL || timekeep->tk_user == 0)
+ return gettimeofday(tp, tzp);
+
+ if (tp)
+ rc = _microtime(tp, timekeep);
+ if (rc)
+ return gettimeofday(tp, tzp);
+
+ if (tzp)
+ *tzp = zerotz;
+
+ return 0;
+}
+DEF_WRAP(gettimeofday);
diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h
index 788890add89..df2239438d2 100644
--- lib/libc/thread/synch.h
+++ lib/libc/thread/synch.h
@@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
  if (abs == NULL)
  return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
 
- if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
+ if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel))
  return (EINVAL);
 
  rel.tv_sec = abs->tv_sec - rel.tv_sec;
diff --git regress/lib/libc/timekeep/Makefile regress/lib/libc/timekeep/Makefile
new file mode 100644
index 00000000000..a7f3080290d
--- /dev/null
+++ regress/lib/libc/timekeep/Makefile
@@ -0,0 +1,5 @@
+# $OpenBSD$
+
+PROGS= test_clock_gettime test_time_skew test_gettimeofday
+
+.include <bsd.regress.mk>
diff --git regress/lib/libc/timekeep/test_clock_gettime.c regress/lib/libc/timekeep/test_clock_gettime.c
new file mode 100644
index 00000000000..859ec368215
--- /dev/null
+++ regress/lib/libc/timekeep/test_clock_gettime.c
@@ -0,0 +1,43 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <time.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+
+void
+check()
+{
+ struct timespec tp = {0};
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp));
+
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp));
+
+}
+
+int main()
+{
+ check();
+ return 0;
+}
diff --git regress/lib/libc/timekeep/test_gettimeofday.c regress/lib/libc/timekeep/test_gettimeofday.c
new file mode 100644
index 00000000000..ea90a1be7e0
--- /dev/null
+++ regress/lib/libc/timekeep/test_gettimeofday.c
@@ -0,0 +1,37 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <sys/time.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+
+void
+check()
+{
+ struct timeval tv = {0};
+ struct timezone tzp;
+
+ ASSERT_EQ(0, gettimeofday(&tv, NULL));
+ ASSERT_EQ(0, gettimeofday(&tv, &tzp));
+}
+
+int main()
+{
+ check();
+ return 0;
+}
diff --git regress/lib/libc/timekeep/test_time_skew.c regress/lib/libc/timekeep/test_time_skew.c
new file mode 100644
index 00000000000..dfa9481c091
--- /dev/null
+++ regress/lib/libc/timekeep/test_time_skew.c
@@ -0,0 +1,55 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/time.h>
+
+#include <assert.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+#define ASSERT_NE(a, b) assert((a) != (b))
+
+void
+check()
+{
+         struct timespec tp1, tp2, tout;
+
+         tout.tv_sec = 0;
+         tout.tv_nsec = 100000;
+
+         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1));
+
+         nanosleep(&tout, NULL);
+
+         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2));
+
+         /* tp1 should never be larger than tp2 */
+         ASSERT_NE(1, timespeccmp(&tp1, &tp2, >));
+}
+
+int
+main(void)
+{
+ int i;
+
+ for (i = 0; i < 1000; i++)
+ check();
+
+ return 0;
+}
diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c
index 3f5f2c5b42b..6eaf8b107c6 100644
--- sys/arch/alpha/alpha/clock.c
+++ sys/arch/alpha/alpha/clock.c
@@ -64,7 +64,7 @@ int clk_irq = 0;
 
 u_int rpcc_get_timecount(struct timecounter *);
 struct timecounter rpcc_timecounter = {
- rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
+ rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0
 };
 
 extern todr_chip_handle_t todr_handle;
diff --git sys/arch/alpha/include/timetc.h sys/arch/alpha/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/alpha/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c
index 7a1dcb4ad75..5839fa15d6c 100644
--- sys/arch/amd64/amd64/tsc.c
+++ sys/arch/amd64/amd64/tsc.c
@@ -42,7 +42,7 @@ int64_t tsc_drift_observed;
 volatile int64_t tsc_sync_val;
 volatile struct cpu_info *tsc_sync_cpu;
 
-uint tsc_get_timecount(struct timecounter *tc);
+u_int tsc_get_timecount(struct timecounter *tc);
 
 #include "lapic.h"
 #if NLAPIC > 0
@@ -50,7 +50,7 @@ extern u_int32_t lapic_per_second;
 #endif
 
 struct timecounter tsc_timecounter = {
- tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL
+ tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, TC_TSC
 };
 
 uint64_t
@@ -244,6 +244,7 @@ tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
  printf("ERROR: %lld cycle TSC drift observed\n",
     (long long)tsc_drift_observed);
  tsc_timecounter.tc_quality = -1000;
+ tsc_timecounter.tc_user = 0;
  tsc_is_invariant = 0;
  }
 
diff --git sys/arch/amd64/include/timetc.h sys/arch/amd64/include/timetc.h
new file mode 100644
index 00000000000..c2d40bcd1e7
--- /dev/null
+++ sys/arch/amd64/include/timetc.h
@@ -0,0 +1,24 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_TSC 1
+#define TC_LAST 2
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c
index 613f7ee0e0f..00da0c6a8d0 100644
--- sys/arch/amd64/isa/clock.c
+++ sys/arch/amd64/isa/clock.c
@@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
 u_int i8254_simple_get_timecount(struct timecounter *tc);
 
 static struct timecounter i8254_timecounter = {
- i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
 };
 
 int clockintr(void *);
diff --git sys/arch/arm/include/timetc.h sys/arch/arm/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/arm/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c
index 11196b5c60d..1a2106ef94c 100644
--- sys/arch/arm64/dev/agtimer.c
+++ sys/arch/arm64/dev/agtimer.c
@@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY;
 u_int agtimer_get_timecount(struct timecounter *);
 
 static struct timecounter agtimer_timecounter = {
- agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL
+ agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0
 };
 
 struct agtimer_pcpu_softc {
diff --git sys/arch/arm64/include/timetc.h sys/arch/arm64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/arm64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/armv7/include/timetc.h sys/arch/armv7/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/armv7/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/armv7/omap/gptimer.c sys/arch/armv7/omap/gptimer.c
index 7605845d5e2..061542d532f 100644
--- sys/arch/armv7/omap/gptimer.c
+++ sys/arch/armv7/omap/gptimer.c
@@ -117,7 +117,7 @@ int gptimer_irq = 0;
 u_int gptimer_get_timecount(struct timecounter *);
 
 static struct timecounter gptimer_timecounter = {
- gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
+ gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0
 };
 
 volatile u_int32_t nexttickevent;
diff --git sys/arch/armv7/sunxi/sxitimer.c sys/arch/armv7/sunxi/sxitimer.c
index 14a243c78d0..41028f9a602 100644
--- sys/arch/armv7/sunxi/sxitimer.c
+++ sys/arch/armv7/sunxi/sxitimer.c
@@ -89,7 +89,7 @@ void sxitimer_delay(u_int);
 u_int sxitimer_get_timecount(struct timecounter *);
 
 static struct timecounter sxitimer_timecounter = {
- sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL
+ sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0
 };
 
 bus_space_tag_t sxitimer_iot;
diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c
index 4c594ab5ec7..8cce6c3a893 100644
--- sys/arch/hppa/dev/clock.c
+++ sys/arch/hppa/dev/clock.c
@@ -47,7 +47,7 @@ int cpu_hardclock(void *);
 u_int itmr_get_timecount(struct timecounter *);
 
 struct timecounter itmr_timecounter = {
- itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
+ itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0
 };
 
 extern todr_chip_handle_t todr_handle;
diff --git sys/arch/hppa/include/timetc.h sys/arch/hppa/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/hppa/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/i386/include/timetc.h sys/arch/i386/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/i386/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c
index 09a6db983f2..dd74bd425ad 100644
--- sys/arch/i386/isa/clock.c
+++ sys/arch/i386/isa/clock.c
@@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
 u_int i8254_simple_get_timecount(struct timecounter *tc);
 
 static struct timecounter i8254_timecounter = {
- i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
 };
 struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
 u_long rtclock_tval;
diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
index 9d9f061eef9..bb8e4c7f9ae 100644
--- sys/arch/i386/pci/geodesc.c
+++ sys/arch/i386/pci/geodesc.c
@@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = {
  0xffffffff, /* counter_mask */
  27000000, /* frequency */
  "GEOTSC", /* name */
- 2000 /* quality */
+ 2000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 int
diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c
index 8b8aa4ac430..a6f324e66f3 100644
--- sys/arch/i386/pci/gscpm.c
+++ sys/arch/i386/pci/gscpm.c
@@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = {
  0xffffff, /* counter_mask */
  3579545, /* frequency */
  "GSCPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 struct cfattach gscpm_ca = {
diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c
index 6abf1627de2..629a86a14ff 100644
--- sys/arch/i386/pci/ichpcib.c
+++ sys/arch/i386/pci/ichpcib.c
@@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = {
  0xffffff, /* counter_mask */
  3579545, /* frequency */
  "ICHPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 struct cfattach ichpcib_ca = {
diff --git sys/arch/landisk/include/timetc.h sys/arch/landisk/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/landisk/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/loongson/include/timetc.h sys/arch/loongson/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/loongson/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/loongson/loongson/generic3a_machdep.c sys/arch/loongson/loongson/generic3a_machdep.c
index ac3f1db6ccd..53489b07549 100644
--- sys/arch/loongson/loongson/generic3a_machdep.c
+++ sys/arch/loongson/loongson/generic3a_machdep.c
@@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = {
  .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */
  .tc_frequency = HPET_FREQ,
  .tc_name = "hpet",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 /* Firmware entry points */
diff --git sys/arch/luna88k/include/timetc.h sys/arch/luna88k/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/luna88k/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/luna88k/luna88k/clock.c sys/arch/luna88k/luna88k/clock.c
index a04120987e0..6580a4a46bf 100644
--- sys/arch/luna88k/luna88k/clock.c
+++ sys/arch/luna88k/luna88k/clock.c
@@ -112,7 +112,9 @@ struct timecounter clock_tc = {
  .tc_counter_mask = 0xffffffff,
  .tc_frequency = 0, /* will be filled in */
  .tc_name = "clock",
- .tc_quality = 0
+ .tc_quality = 0,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 /*
diff --git sys/arch/m88k/include/timetc.h sys/arch/m88k/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/m88k/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/macppc/include/timetc.h sys/arch/macppc/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/macppc/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/macppc/macppc/clock.c sys/arch/macppc/macppc/clock.c
index 4a44a92cfc0..8c3ad620be8 100644
--- sys/arch/macppc/macppc/clock.c
+++ sys/arch/macppc/macppc/clock.c
@@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320;
 static int32_t ticks_per_intr;
 
 static struct timecounter tb_timecounter = {
- tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
+ tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0
 };
 
 /* calibrate the timecounter frequency for the listed models */
diff --git sys/arch/mips64/include/timetc.h sys/arch/mips64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/mips64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/mips64/mips64/mips64_machdep.c sys/arch/mips64/mips64/mips64_machdep.c
index d4a42ed5acc..5c4dbadb5bb 100644
--- sys/arch/mips64/mips64/mips64_machdep.c
+++ sys/arch/mips64/mips64/mips64_machdep.c
@@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = {
  0xffffffff, /* counter_mask */
  0, /* frequency */
  "CP0", /* name */
- 0 /* quality */
+ 0, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 u_int
diff --git sys/arch/octeon/include/timetc.h sys/arch/octeon/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/octeon/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/octeon/octeon/machdep.c sys/arch/octeon/octeon/machdep.c
index 902e462d53f..d8377653abe 100644
--- sys/arch/octeon/octeon/machdep.c
+++ sys/arch/octeon/octeon/machdep.c
@@ -151,8 +151,9 @@ struct timecounter ioclock_timecounter = {
  .tc_name = "ioclock",
  .tc_quality = 0, /* ioclock can be overridden
  * by cp0 counter */
- .tc_priv = 0 /* clock register,
+ .tc_priv = 0, /* clock register,
  * determined at runtime */
+ .tc_user = 0, /* expose to user */
 };
 
 static int
diff --git sys/arch/powerpc/include/timetc.h sys/arch/powerpc/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/powerpc/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/powerpc64/include/timetc.h sys/arch/powerpc64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/powerpc64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sgi/include/timetc.h sys/arch/sgi/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sgi/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sgi/sgi/ip27_machdep.c sys/arch/sgi/sgi/ip27_machdep.c
index ba7fa558b96..2a2cc144242 100644
--- sys/arch/sgi/sgi/ip27_machdep.c
+++ sys/arch/sgi/sgi/ip27_machdep.c
@@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = {
  .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */
  .tc_frequency = 1250000,
  .tc_name = "hubrt",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = 0,
+ .tc_user = 0,
 };
 
 volatile uint64_t ip27_spinup_a0;
diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c
index 56b29915c70..827775512ac 100644
--- sys/arch/sgi/xbow/xheart.c
+++ sys/arch/sgi/xbow/xheart.c
@@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = {
  .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit */
  .tc_frequency = 12500000,
  .tc_name = "heart",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *);
diff --git sys/arch/sh/include/timetc.h sys/arch/sh/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sh/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sparc64/dev/psycho.c sys/arch/sparc64/dev/psycho.c
index e24f804dff6..1a7a1afa8c2 100644
--- sys/arch/sparc64/dev/psycho.c
+++ sys/arch/sparc64/dev/psycho.c
@@ -127,7 +127,7 @@ extern struct sparc_pci_chipset _sparc_pci_chipset;
 u_int stick_get_timecount(struct timecounter *);
 
 struct timecounter stick_timecounter = {
- stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
+ stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0
 };
 
 /*
diff --git sys/arch/sparc64/include/timetc.h sys/arch/sparc64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sparc64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sparc64/sparc64/clock.c sys/arch/sparc64/sparc64/clock.c
index fd5e8a9c15b..5c2e47d386b 100644
--- sys/arch/sparc64/sparc64/clock.c
+++ sys/arch/sparc64/sparc64/clock.c
@@ -109,13 +109,13 @@ struct cfdriver clock_cd = {
 u_int tick_get_timecount(struct timecounter *);
 
 struct timecounter tick_timecounter = {
- tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL
+ tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0
 };
 
 u_int sys_tick_get_timecount(struct timecounter *);
 
 struct timecounter sys_tick_timecounter = {
- sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL
+ sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0
 };
 
 /*
diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c
index d0ee72cec9b..13177a909da 100644
--- sys/dev/acpi/acpihpet.c
+++ sys/dev/acpi/acpihpet.c
@@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = {
  0xffffffff, /* counter_mask (32 bits) */
  0, /* frequency */
  0, /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 #define HPET_TIMERS 3
diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c
index cdc8c99a17a..89b5a397e47 100644
--- sys/dev/acpi/acpitimer.c
+++ sys/dev/acpi/acpitimer.c
@@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = {
  0x00ffffff, /* counter_mask (24 bits) */
  ACPI_FREQUENCY, /* frequency */
  0, /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 struct acpitimer_softc {
diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c
index 6df82858016..9610d5bc1f0 100644
--- sys/dev/pci/amdpm.c
+++ sys/dev/pci/amdpm.c
@@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = {
  0xffffff, /* counter_mask */
  AMDPM_FREQUENCY, /* frequency */
  "AMDPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 #define AMDPM_CONFREG 0x40
diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c
index db806eedf80..ce33cd175e6 100644
--- sys/dev/pci/viapm.c
+++ sys/dev/pci/viapm.c
@@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = {
  0xffffff, /* counter_mask */
  VIAPM_FREQUENCY, /* frequency */
  "VIAPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 struct timeout viapm_timeout;
diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c
index b32facdacb1..b9ee2feec4c 100644
--- sys/dev/pv/hyperv.c
+++ sys/dev/pv/hyperv.c
@@ -141,7 +141,7 @@ struct {
 };
 
 struct timecounter hv_timecounter = {
- hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001
+ hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0
 };
 
 struct cfdriver hyperv_cd = {
diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c
index 6b242f7448d..b80e4d2a484 100644
--- sys/dev/pv/pvclock.c
+++ sys/dev/pv/pvclock.c
@@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = {
 };
 
 struct timecounter pvclock_timecounter = {
- pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL
+ pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0
 };
 
 int
diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c
index 9b5b8eb3acf..59bc923a6fb 100644
--- sys/kern/exec_elf.c
+++ sys/kern/exec_elf.c
@@ -124,7 +124,7 @@ extern char *syscallnames[];
 /*
  * How many entries are in the AuxInfo array we pass to the process?
  */
-#define ELF_AUX_ENTRIES 8
+#define ELF_AUX_ENTRIES 9
 
 /*
  * This is the OpenBSD ELF emul
@@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct exec_package *epp)
  a->au_v = ap->arg_entry;
  a++;
 
+ a->au_id = AUX_openbsd_timekeep;
+ a->au_v = p->p_p->ps_timekeep;
+ a++;
+
  a->au_id = AUX_null;
  a->au_v = 0;
  a++;
diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
index 20480c2fc28..222450607d5 100644
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -64,6 +64,11 @@
 #include <uvm/uvm_extern.h>
 #include <machine/tcb.h>
 
+#include <sys/timetc.h>
+
+struct uvm_object *timekeep_object;
+struct timekeep* timekeep;
+
 void unveil_destroy(struct process *ps);
 
 const struct kmem_va_mode kv_exec = {
@@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = {
  */
 int exec_sigcode_map(struct process *, struct emul *);
 
+/*
+ * Map the shared timekeep page.
+ */
+int exec_timekeep_map(struct process *);
+
 /*
  * If non-zero, stackgap_random specifies the upper limit of the random gap size
  * added to the fixed stack position. Must be n^2.
@@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t *retval)
  /* map the process's signal trampoline code */
  if (exec_sigcode_map(pr, pack.ep_emul))
  goto free_pack_abort;
+ /* map the process's timekeep page */
+ if (exec_timekeep_map(pr))
+ goto free_pack_abort;
 
 #ifdef __HAVE_EXEC_MD_MAP
  /* perform md specific mappings that process might need */
@@ -863,3 +876,40 @@ exec_sigcode_map(struct process *pr, struct emul *e)
 
  return (0);
 }
+
+int
+exec_timekeep_map(struct process *pr)
+{
+ size_t timekeep_sz = sizeof(struct timekeep);
+
+ /*
+ * Similar to the sigcode object, except that there is a single
+ * timekeep object, and not one per emulation.
+ */
+ if (timekeep_object == NULL) {
+ vaddr_t va;
+
+ timekeep_object = uao_create(timekeep_sz, 0);
+ uao_reference(timekeep_object);
+
+ if (uvm_map(kernel_map, &va, round_page(timekeep_sz), timekeep_object,
+    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
+    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
+ uao_detach(timekeep_object);
+ return (ENOMEM);
+ }
+
+ timekeep = (struct timekeep *)va;
+ timekeep->tk_version = TK_VERSION;
+ }
+
+ uao_reference(timekeep_object);
+ if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, round_page(timekeep_sz),
+    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
+    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
+ uao_detach(timekeep_object);
+ return (ENOMEM);
+ }
+
+ return (0);
+}
diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
index 88d4a3379f9..47efbdd0b78 100644
--- sys/kern/kern_tc.c
+++ sys/kern/kern_tc.c
@@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc)
 }
 
 static struct timecounter dummy_timecounter = {
- dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
+ dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0
 };
 
 /*
@@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts)
 #endif
 }
 
+void
+tc_update_timekeep(void)
+{
+ static struct timecounter *last_tc = NULL;
+ struct timehands *th;
+
+ if (timekeep == NULL)
+ return;
+
+ th = timehands;
+ timekeep->tk_generation = 0;
+ membar_producer();
+ timekeep->tk_scale = th->th_scale;
+ timekeep->tk_offset_count = th->th_offset_count;
+ timekeep->tk_offset = th->th_offset;
+ timekeep->tk_naptime = th->th_naptime;
+ timekeep->tk_boottime = th->th_boottime;
+ if (last_tc != th->th_counter) {
+ timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
+ timekeep->tk_user = th->th_counter->tc_user;
+ last_tc = th->th_counter;
+ }
+ membar_producer();
+ timekeep->tk_generation = th->th_generation;
+
+ return;
+}
+
 /*
  * Initialize the next struct timehands in the ring and make
  * it the active timehands.  Along the way we might switch to a different
@@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
  time_uptime = th->th_offset.sec;
  membar_producer();
  timehands = th;
+
+ tc_update_timekeep();
 }
 
 /* Report or change the active timecounter hardware. */
diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h
index a40e0510273..3084ed595a6 100644
--- sys/sys/exec_elf.h
+++ sys/sys/exec_elf.h
@@ -691,7 +691,8 @@ enum AuxID {
  AUX_sun_uid = 2000, /* euid */
  AUX_sun_ruid = 2001, /* ruid */
  AUX_sun_gid = 2002, /* egid */
- AUX_sun_rgid = 2003 /* rgid */
+ AUX_sun_rgid = 2003, /* rgid */
+ AUX_openbsd_timekeep = 4000, /* userland clock_gettime */
 };
 
 struct elf_args {
diff --git sys/sys/proc.h sys/sys/proc.h
index 357c0c0d52c..c6d54572bdd 100644
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -242,6 +242,7 @@ struct process {
  char ps_comm[MAXCOMLEN+1];
 
  vaddr_t ps_strings; /* User pointers to argv/env */
+ vaddr_t ps_timekeep; /* User pointer to timekeep */
  vaddr_t ps_sigcode; /* User pointer to the signal code */
  vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */
  u_long ps_sigcookie;
diff --git sys/sys/time.h sys/sys/time.h
index e758a64ce07..bcd3acd034d 100644
--- sys/sys/time.h
+++ sys/sys/time.h
@@ -163,7 +163,7 @@ struct clockinfo {
 };
 #endif /* __BSD_VISIBLE */
 
-#if defined(_KERNEL) || defined(_STANDALONE)
+#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC)
 #include <sys/_time.h>
 
 /* Time expressed as seconds and fractions of a second + operations on it. */
@@ -171,6 +171,9 @@ struct bintime {
  time_t sec;
  uint64_t frac;
 };
+#endif
+
+#if defined(_KERNEL) || defined(_STANDALONE)
 
 #define bintimecmp(btp, ctp, cmp) \
  ((btp)->sec == (ctp)->sec ? \
diff --git sys/sys/timetc.h sys/sys/timetc.h
index ce81c3475a0..c5ad27695ba 100644
--- sys/sys/timetc.h
+++ sys/sys/timetc.h
@@ -24,10 +24,11 @@
 #ifndef _SYS_TIMETC_H_
 #define _SYS_TIMETC_H_
 
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_LIBC)
 #error "no user-serviceable parts inside"
 #endif
 
+#include <machine/timetc.h>
 #include <sys/queue.h>
 
 /*-
@@ -80,6 +81,8 @@ struct timecounter {
  */
  void *tc_priv; /* [I] */
  /* Pointer to the timecounter's private parts. */
+ int tc_user; /* [I] */
+ /* Expose this timecounter to userland. */
  SLIST_ENTRY(timecounter) tc_next; /* [I] */
  /* Pointer to the next timecounter. */
  int64_t tc_freq_adj; /* [tw] */
@@ -88,11 +91,32 @@ struct timecounter {
  /* Precision of the counter.  Computed in tc_init(). */
 };
 
+struct timekeep {
+ /* set at initialization */
+ uint32_t tk_version; /* version number */
+
+ /* timehands members */
+ uint64_t tk_scale;
+ u_int tk_offset_count;
+ struct bintime tk_offset;
+ struct bintime tk_naptime;
+ struct bintime tk_boottime;
+ volatile u_int tk_generation;
+
+ /* timecounter members */
+ int tk_user;
+ u_int tk_counter_mask;
+};
+#define TK_VERSION 0
+
 struct rwlock;
 extern struct rwlock tc_lock;
 
 extern struct timecounter *timecounter;
 
+extern struct uvm_object *timekeep_object;
+extern struct timekeep *timekeep;
+
 u_int64_t tc_getfrequency(void);
 u_int64_t tc_getprecision(void);
 void tc_init(struct timecounter *tc);

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Todd C. Miller-3
In reply to this post by Mark Kettenis
On Fri, 19 Jun 2020 18:52:40 +0200, Mark Kettenis wrote:

> There is one other issue that I wanted to raise.  An that is whether
> we really need to implement CLOCK_UPTINME as a userland clock.  If we
> don't do that we can drop tk_naptime from the shared struct.  I
> mention this because th_naptime was only recently added to struct
> timehands and much more an implementation detail than the other fields.
>
> I don't expect userland processes to call CLOCK_UPTIME in a loop like
> they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
> doesn't have it ;).

That's not entirely true.  On Linux, CLOCK_MONOTONIC does not count
time that the system is suspended so it is analogous to our
CLOCK_UPTIME.  On Linux CLOCK_BOOTTIME is the clock that counts
time while suspended.  On OpenBSD CLOCK_BOOTTIME and CLOCK_MONOTONIC
are the same but that is not true of other systems.

 - todd

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Mark Kettenis
> From: "Todd C. Miller" <[hidden email]>
> Date: Fri, 19 Jun 2020 12:24:33 -0600
>
> On Fri, 19 Jun 2020 18:52:40 +0200, Mark Kettenis wrote:
>
> > There is one other issue that I wanted to raise.  An that is whether
> > we really need to implement CLOCK_UPTINME as a userland clock.  If we
> > don't do that we can drop tk_naptime from the shared struct.  I
> > mention this because th_naptime was only recently added to struct
> > timehands and much more an implementation detail than the other fields.
> >
> > I don't expect userland processes to call CLOCK_UPTIME in a loop like
> > they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
> > doesn't have it ;).
>
> That's not entirely true.  On Linux, CLOCK_MONOTONIC does not count
> time that the system is suspended so it is analogous to our
> CLOCK_UPTIME.  On Linux CLOCK_BOOTTIME is the clock that counts
> time while suspended.  On OpenBSD CLOCK_BOOTTIME and CLOCK_MONOTONIC
> are the same but that is not true of other systems.

Sure, Linux doesn't faithfully implement POSIX in this respect.  But
most software doesn't actually care about the difference and Linux
does not have CLOCK_UPTIME which was my point.

Anyway, if the consensus is that we should offer CLOCK_UPTIME that's
fine with me.  It just means that we have to be a bit more careful
tinkering with the timecounter internals in the future.  We can always
get out of this hole we're digging by disabling the userland
optimization.

Yes, folks have to realize that is an optimization, and an
optimization that you can't rely on.  It won't be available on all
machines.  And it may not be available when you're doing an upgrade of
some sort.

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Mark Kettenis
In reply to this post by Paul Irofti-4
> Date: Fri, 19 Jun 2020 20:28:58 +0300
> From: Paul Irofti <[hidden email]>
>
> On Fri, Jun 19, 2020 at 06:52:40PM +0200, Mark Kettenis wrote:
> > > Date: Fri, 19 Jun 2020 14:31:17 +0300
> > > From: Paul Irofti <[hidden email]>
> > >
> > > Hi,
> > >
> > > Here is another iteration of the diff that addresses all issues raised
> > > in the meantime:
> > >
> > >   - Switch tc to uint
> >
> > The request was to use u_int, like we de in the kernel.  The uint type
> > should not be used in OpenBSD code.
> >
> > >   - Check for version at init and switch to machite/timetc.h defs
> > >   - Remove tk_nclocks
> > >   - Switch to single version and ditch minor/major
> > >   - Do not enable user TSC for large skew values
> > >   - Add amd64 clocks and use the define in TSC
> > >   - Include and add machine/timetc.h
> > >
> > > As we have seen most architectures have support for clocks now and the
> > > above addresses Mark's last concerns.
> > >
> > > Unless other blocking issues arise, this time around I am looking for
> > > OKs to commit. Theo? Mark?
> >
> > There is one other issue that I wanted to raise.  An that is whether
> > we really need to implement CLOCK_UPTINME as a userland clock.  If we
> > don't do that we can drop tk_naptime from the shared struct.  I
> > mention this because th_naptime was only recently added to struct
> > timehands and much more an implementation detail than the other fields.
> >
> > I don't expect userland processes to call CLOCK_UPTIME in a loop like
> > they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
> > doesn't have it ;).
>
> I don't care eitherway about this. But I don't see why we would not have
> this functionality if it is easy to offer. Maybe someone can help us
> grep the ports tree for this? Stuart? :)
>
> > We're getting there...
>
> I have addressed your comments bellow, except for the CPU skew one. That
> code disables TSC for all CPUs, not just for PRIMARY. Would you like to
> walk and add code for every CPU to check the drift and then disable the
> TSC? It seems a little too much...

Still uses uint instead of u_int in places.  Still has the pointless
extra NULL and 0 for timecounters in files that are otherwise

And regarding the TSC.  That issue is a show-stopper.  We can tolerate
a small amout of skew, but not a large amount.  Because otherwise a
multithreaded process might observe time going backwards.

> diff --git lib/libc/arch/aarch64/gen/Makefile.inc lib/libc/arch/aarch64/gen/Makefile.inc
> index a7b1b73f3ef..ee198f5d611 100644
> --- lib/libc/arch/aarch64/gen/Makefile.inc
> +++ lib/libc/arch/aarch64/gen/Makefile.inc
> @@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
>  SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
>  SRCS+= fpclassifyl.c
>  SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
> -SRCS+= signbitl.c
> +SRCS+= signbitl.c usertc.c
> diff --git lib/libc/arch/aarch64/gen/usertc.c lib/libc/arch/aarch64/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/aarch64/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/alpha/gen/Makefile.inc lib/libc/arch/alpha/gen/Makefile.inc
> index a44599d2cab..2a8abd32b61 100644
> --- lib/libc/arch/alpha/gen/Makefile.inc
> +++ lib/libc/arch/alpha/gen/Makefile.inc
> @@ -3,5 +3,5 @@
>  
>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
> - fpsetround.c fpsetsticky.c
> + fpsetround.c fpsetsticky.c usertc.c
>  SRCS+= sigsetjmp.S
> diff --git lib/libc/arch/alpha/gen/usertc.c lib/libc/arch/alpha/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/alpha/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/amd64/gen/Makefile.inc lib/libc/arch/amd64/gen/Makefile.inc
> index e995309ed71..f6349e2b974 100644
> --- lib/libc/arch/amd64/gen/Makefile.inc
> +++ lib/libc/arch/amd64/gen/Makefile.inc
> @@ -2,6 +2,7 @@
>  
>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
>   sigsetjmp.S
> -SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
> +SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \
> + usertc.c
>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
>   fpsetround.S fpsetsticky.S
> diff --git lib/libc/arch/amd64/gen/usertc.c lib/libc/arch/amd64/gen/usertc.c
> new file mode 100644
> index 00000000000..742fb0cc458
> --- /dev/null
> +++ lib/libc/arch/amd64/gen/usertc.c
> @@ -0,0 +1,41 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +static inline uint
> +rdtsc(void)
> +{
> + uint32_t hi, lo;
> + asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
> + return ((uint64_t)lo)|(((uint64_t)hi)<<32);
> +}
> +
> +int
> +tc_get_timecount(struct timekeep *tk, u_int *tc)
> +{
> + int tk_user = tk->tk_user;
> +
> + if (tk_user < 1 || tk_user >= TC_LAST)
> + return -1;
> +
> + *tc = rdtsc();
> + return 0;
> +}
> +int (*const _tc_get_timecount)(struct timekeep *tk, u_int *tc)
> + = tc_get_timecount;
> diff --git lib/libc/arch/arm/gen/Makefile.inc lib/libc/arch/arm/gen/Makefile.inc
> index 1b4ab2f3ae7..27090a0d9dc 100644
> --- lib/libc/arch/arm/gen/Makefile.inc
> +++ lib/libc/arch/arm/gen/Makefile.inc
> @@ -2,5 +2,5 @@
>  # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
>  
>  SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c infinity.c
> -SRCS+= ldexp.c modf.c nan.c
> +SRCS+= ldexp.c modf.c nan.c usertc.c
>  SRCS+= setjmp.S _setjmp.S sigsetjmp.S
> diff --git lib/libc/arch/arm/gen/usertc.c lib/libc/arch/arm/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/arm/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/hppa/gen/Makefile.inc lib/libc/arch/hppa/gen/Makefile.inc
> index e0c864242fe..1fde24670f1 100644
> --- lib/libc/arch/hppa/gen/Makefile.inc
> +++ lib/libc/arch/hppa/gen/Makefile.inc
> @@ -2,6 +2,6 @@
>  
>  SRCS+= setjmp.S
>  SRCS+= fabs.c
> -SRCS+= infinity.c ldexp.c modf.c nan.c
> +SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c
> diff --git lib/libc/arch/hppa/gen/usertc.c lib/libc/arch/hppa/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/hppa/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/i386/gen/Makefile.inc lib/libc/arch/i386/gen/Makefile.inc
> index 4c18e059581..b7dd30adccd 100644
> --- lib/libc/arch/i386/gen/Makefile.inc
> +++ lib/libc/arch/i386/gen/Makefile.inc
> @@ -1,6 +1,6 @@
>  # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
>  
> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
>   modf.S nan.c setjmp.S sigsetjmp.S
>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
> diff --git lib/libc/arch/i386/gen/usertc.c lib/libc/arch/i386/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/i386/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/m88k/gen/Makefile.inc lib/libc/arch/m88k/gen/Makefile.inc
> index cff75b8d425..d66f66af4af 100644
> --- lib/libc/arch/m88k/gen/Makefile.inc
> +++ lib/libc/arch/m88k/gen/Makefile.inc
> @@ -1,7 +1,7 @@
>  # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
>  # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
>  
> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c
>  SRCS+= setjmp.S sigsetjmp.S
> diff --git lib/libc/arch/m88k/gen/usertc.c lib/libc/arch/m88k/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/m88k/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/mips64/gen/Makefile.inc lib/libc/arch/mips64/gen/Makefile.inc
> index 8cf1fc2d28a..839241a2069 100644
> --- lib/libc/arch/mips64/gen/Makefile.inc
> +++ lib/libc/arch/mips64/gen/Makefile.inc
> @@ -1,6 +1,6 @@
>  # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
>  
> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c
>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
> diff --git lib/libc/arch/mips64/gen/usertc.c lib/libc/arch/mips64/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/mips64/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/powerpc/gen/Makefile.inc lib/libc/arch/powerpc/gen/Makefile.inc
> index 6b2e4613ee8..d4d7b00bff7 100644
> --- lib/libc/arch/powerpc/gen/Makefile.inc
> +++ lib/libc/arch/powerpc/gen/Makefile.inc
> @@ -1,5 +1,5 @@
>  SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c nan.c
> -SRCS+= fabs.c
> +SRCS+= fabs.c usertc.c
>  SRCS+= fpgetmask.c fpsetmask.c
>  SRCS+= fpgetround.c fpsetround.c
>  SRCS+= fpgetsticky.c fpsetsticky.c
> diff --git lib/libc/arch/powerpc/gen/usertc.c lib/libc/arch/powerpc/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/powerpc/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/sh/gen/Makefile.inc lib/libc/arch/sh/gen/Makefile.inc
> index 55de1973b30..4724fb3a6a8 100644
> --- lib/libc/arch/sh/gen/Makefile.inc
> +++ lib/libc/arch/sh/gen/Makefile.inc
> @@ -3,4 +3,4 @@
>  SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S _setjmp.S
>  SRCS+= sigsetjmp.S
>  SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
> - fpsetmask.c fpsetround.c fpsetsticky.c
> + fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
> diff --git lib/libc/arch/sh/gen/usertc.c lib/libc/arch/sh/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/sh/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/arch/sparc64/gen/Makefile.inc lib/libc/arch/sparc64/gen/Makefile.inc
> index 58259cedef6..a908e022954 100644
> --- lib/libc/arch/sparc64/gen/Makefile.inc
> +++ lib/libc/arch/sparc64/gen/Makefile.inc
> @@ -3,5 +3,5 @@
>  SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
>   fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>   fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
> - isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
> + isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
>   mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
> diff --git lib/libc/arch/sparc64/gen/usertc.c lib/libc/arch/sparc64/gen/usertc.c
> new file mode 100644
> index 00000000000..6551854a010
> --- /dev/null
> +++ lib/libc/arch/sparc64/gen/usertc.c
> @@ -0,0 +1,21 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/timetc.h>
> +
> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
> index 131da4b2190..40e84771f86 100644
> --- lib/libc/asr/asr.c
> +++ lib/libc/asr/asr.c
> @@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds, int timeout)
>   struct timespec pollstart, pollend, elapsed;
>   int r;
>  
> - if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
>   return -1;
>  
>   while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
> - if (clock_gettime(CLOCK_MONOTONIC, &pollend))
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
>   return -1;
>   timespecsub(&pollend, &pollstart, &elapsed);
>   timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
> @@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
>   asr->a_rtime = 0;
>   }
>  
> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>   return;
>  
>   if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
> diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
> index 82de8fa33b7..02fd3013cc1 100644
> --- lib/libc/crypt/bcrypt.c
> +++ lib/libc/crypt/bcrypt.c
> @@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
>   char buf[_PASSWORD_LEN];
>   int duration;
>  
> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
>   bcrypt_newhash("testpassword", r, buf, sizeof(buf));
> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
>  
>   duration = after.tv_sec - before.tv_sec;
>   duration *= 1000000;
> diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
> index 270f54aada5..d2632455f11 100644
> --- lib/libc/dlfcn/init.c
> +++ lib/libc/dlfcn/init.c
> @@ -20,6 +20,7 @@
>  
>  #include <sys/types.h>
>  #include <sys/syscall.h>
> +#include <sys/timetc.h> /* timekeep */
>  
>  #ifndef PIC
>  #include <sys/mman.h>
> @@ -45,8 +46,9 @@
>  /* XXX should be in an include file shared with csu */
>  char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void));
>  
> -/* provide definition for this */
> +/* provide definitions for these */
>  int _pagesize = 0;
> +struct timekeep *_timekeep;
>  
>  /*
>   * In dynamicly linked binaries environ and __progname are overriden by
> @@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb)
>   phnum = aux->au_v;
>   break;
>  #endif /* !PIC */
> + case AUX_openbsd_timekeep:
> + if (_tc_get_timecount) {
> + _timekeep = (void *)aux->au_v;
> + if (_timekeep->tk_version != TK_VERSION)
> + _timekeep = NULL;
> + }
> + break;
>   }
>   }
>  
> diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
> index 1286a96fe40..32f86eda50f 100644
> --- lib/libc/gen/auth_subr.c
> +++ lib/libc/gen/auth_subr.c
> @@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
>  
>   if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
>   if (as->now.tv_sec == 0)
> - gettimeofday(&as->now, NULL);
> + WRAP(gettimeofday)(&as->now, NULL);
>   if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
>   as->state &= ~AUTH_ALLOW;
>   as->state |= AUTH_EXPIRED;
> @@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
>  
>   if (as->pwd && (quad_t)as->pwd->pw_change) {
>   if (as->now.tv_sec == 0)
> - gettimeofday(&as->now, NULL);
> + WRAP(gettimeofday)(&as->now, NULL);
>   if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
>   as->state &= ~AUTH_ALLOW;
>   as->state |= AUTH_PWEXPIRED;
> diff --git lib/libc/gen/time.c lib/libc/gen/time.c
> index 3bbd0d733d1..b3ce9a800f1 100644
> --- lib/libc/gen/time.c
> +++ lib/libc/gen/time.c
> @@ -36,7 +36,7 @@ time(time_t *t)
>  {
>   struct timeval tt;
>  
> - if (gettimeofday(&tt, NULL) == -1)
> + if (WRAP(gettimeofday)(&tt, NULL) == -1)
>   return (-1);
>   if (t)
>   *t = (time_t)tt.tv_sec;
> diff --git lib/libc/gen/times.c lib/libc/gen/times.c
> index 02e4dd44b5c..36841810d1b 100644
> --- lib/libc/gen/times.c
> +++ lib/libc/gen/times.c
> @@ -52,7 +52,7 @@ times(struct tms *tp)
>   return ((clock_t)-1);
>   tp->tms_cutime = CONVTCK(ru.ru_utime);
>   tp->tms_cstime = CONVTCK(ru.ru_stime);
> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>   return ((clock_t)-1);
>   return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK));
>  }
> diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
> index 520a5954025..845cbe80356 100644
> --- lib/libc/gen/timespec_get.c
> +++ lib/libc/gen/timespec_get.c
> @@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
>  {
>   switch (base) {
>   case TIME_UTC:
> - if (clock_gettime(CLOCK_REALTIME, ts) == -1)
> + if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
>   return 0;
>   break;
>   default:
> diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
> index ed112320fa2..df717021cab 100644
> --- lib/libc/hidden/sys/time.h
> +++ lib/libc/hidden/sys/time.h
> @@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
>  PROTO_NORMAL(adjtime);
>  PROTO_NORMAL(futimes);
>  PROTO_NORMAL(getitimer);
> -PROTO_NORMAL(gettimeofday);
> +PROTO_WRAP(gettimeofday);
>  PROTO_NORMAL(setitimer);
>  PROTO_NORMAL(settimeofday);
>  PROTO_NORMAL(utimes);
> diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h
> new file mode 100644
> index 00000000000..bbdaa2d0d4c
> --- /dev/null
> +++ lib/libc/hidden/sys/timetc.h
> @@ -0,0 +1,38 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _LIBC_SYS_TIMETC_H_
> +#define _LIBC_SYS_TIMETC_H_
> +
> +#define _LIBC
> +#include <sys/types.h>
> +#include <sys/time.h>
> +
> +#include_next <sys/timetc.h>
> +
> +__BEGIN_HIDDEN_DECLS
> +extern struct timekeep *_timekeep;
> +
> +extern int (*const _tc_get_timecount)(struct timekeep *, u_int *);
> +
> +int _microtime(struct timeval *, struct timekeep *);
> +int _nanotime(struct timespec *, struct timekeep *);
> +int _nanoruntime(struct timespec *, struct timekeep *);
> +int _nanouptime(struct timespec *, struct timekeep *);
> +__END_HIDDEN_DECLS
> +
> +#endif /* !_LIBC_SYS_TIMETC_H_ */
> diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h
> index 18c49f8fcb9..d8e1e0caf64 100644
> --- lib/libc/hidden/time.h
> +++ lib/libc/hidden/time.h
> @@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r);
>  PROTO_STD_DEPRECATED(clock);
>  PROTO_DEPRECATED(clock_getcpuclockid);
>  PROTO_NORMAL(clock_getres);
> -PROTO_NORMAL(clock_gettime);
> +PROTO_WRAP(clock_gettime);
>  PROTO_NORMAL(clock_settime);
>  PROTO_STD_DEPRECATED(ctime);
>  PROTO_DEPRECATED(ctime_r);
> diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c
> index 763e420bb88..9babb28470a 100644
> --- lib/libc/net/res_random.c
> +++ lib/libc/net/res_random.c
> @@ -219,7 +219,7 @@ res_initid(void)
>   if (ru_prf != NULL)
>   arc4random_buf(ru_prf, sizeof(*ru_prf));
>  
> - clock_gettime(CLOCK_MONOTONIC, &ts);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
>   ru_reseed = ts.tv_sec + RU_OUT;
>   ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
>  }
> @@ -232,7 +232,7 @@ __res_randomid(void)
>   u_int r;
>   static void *randomid_mutex;
>  
> - clock_gettime(CLOCK_MONOTONIC, &ts);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
>   pid = getpid();
>  
>   _MUTEX_LOCK(&randomid_mutex);
> diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c
> index 402d98cede4..917a6d42b8a 100644
> --- lib/libc/rpc/auth_unix.c
> +++ lib/libc/rpc/auth_unix.c
> @@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
>   /*
>   * fill in param struct from the given params
>   */
> - (void)gettimeofday(&now,  NULL);
> + (void)WRAP(gettimeofday)(&now,  NULL);
>   aup.aup_time = now.tv_sec;
>   aup.aup_machname = machname;
>   aup.aup_uid = uid;
> @@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth)
>   goto done;
>  
>   /* update the time and serialize in place */
> - (void)gettimeofday(&now, NULL);
> + (void)WRAP(gettimeofday)(&now, NULL);
>   aup.aup_time = now.tv_sec;
>   xdrs.x_op = XDR_ENCODE;
>   XDR_SETPOS(&xdrs, 0);
> diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c
> index 8e6ef515b0e..927b4bf2028 100644
> --- lib/libc/rpc/clnt_tcp.c
> +++ lib/libc/rpc/clnt_tcp.c
> @@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int len)
>   pfd[0].events = POLLIN;
>   TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait);
>   delta = wait;
> - clock_gettime(CLOCK_MONOTONIC, &start);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>   for (;;) {
>   r = ppoll(pfd, 1, &delta, NULL);
>   save_errno = errno;
>  
> - clock_gettime(CLOCK_MONOTONIC, &after);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>   timespecsub(&start, &after, &duration);
>   timespecsub(&wait, &duration, &delta);
>   if (delta.tv_sec < 0 || !timespecisset(&delta))
> diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c
> index 68d01674410..92e1d5c350d 100644
> --- lib/libc/rpc/clnt_udp.c
> +++ lib/libc/rpc/clnt_udp.c
> @@ -265,7 +265,7 @@ send_again:
>   reply_msg.acpted_rply.ar_results.where = resultsp;
>   reply_msg.acpted_rply.ar_results.proc = xresults;
>  
> - clock_gettime(CLOCK_MONOTONIC, &start);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>   for (;;) {
>   switch (ppoll(pfd, 1, &wait, NULL)) {
>   case 0:
> @@ -283,7 +283,7 @@ send_again:
>   /* FALLTHROUGH */
>   case -1:
>   if (errno == EINTR) {
> - clock_gettime(CLOCK_MONOTONIC, &after);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>   timespecsub(&after, &start, &duration);
>   timespecadd(&time_waited, &duration, &time_waited);
>   if (timespeccmp(&time_waited, &timeout, <))
> diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c
> index f9d7a70938f..6c99db84359 100644
> --- lib/libc/rpc/svc_tcp.c
> +++ lib/libc/rpc/svc_tcp.c
> @@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
>   * A timeout is fatal for the connection.
>   */
>   delta = wait_per_try;
> - clock_gettime(CLOCK_MONOTONIC, &start);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>   pfd[0].fd = sock;
>   pfd[0].events = POLLIN;
>   do {
> @@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
>   case -1:
>   if (errno != EINTR)
>   goto fatal_err;
> - clock_gettime(CLOCK_MONOTONIC, &after);
> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>   timespecsub(&after, &start, &duration);
>   timespecsub(&wait_per_try, &duration, &delta);
>   if (delta.tv_sec < 0 || !timespecisset(&delta))
> diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc
> index 34769576ced..d57418d81bf 100644
> --- lib/libc/sys/Makefile.inc
> +++ lib/libc/sys/Makefile.inc
> @@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \
>  
>  # glue to offer userland wrappers for some syscalls
>  SRCS+= posix_madvise.c pthread_sigmask.c \
> - w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c
> + w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \
> + w_clock_gettime.c w_gettimeofday.c microtime.c
>  
>  # glue for compat with old syscall interfaces.
>  SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c truncate.c \
> @@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c w_pwrite.c w_pwritev.c
>  ASM= __semctl.o __syscall.o __thrsigdivert.o \
>   access.o acct.o adjfreq.o adjtime.o \
>   bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \
> - clock_getres.o clock_gettime.o clock_settime.o \
> + clock_getres.o clock_settime.o \
>   dup.o dup2.o dup3.o \
>   execve.o \
>   faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \
> @@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \
>   getgroups.o getitimer.o getpeername.o getpgid.o \
>   getpriority.o getresgid.o getresuid.o \
>   getrlimit.o getrusage.o getsid.o getsockname.o \
> - getsockopt.o gettimeofday.o ioctl.o \
> + getsockopt.o ioctl.o \
>   kevent.o kill.o kqueue.o ktrace.o lchown.o \
>   link.o linkat.o listen.o lstat.o madvise.o \
>   minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
> @@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po}
>  SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so}
>  DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do}
>  
> -HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o}
> +HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o} \
> + clock_gettime.o gettimeofday.o
>  PHIDDEN=${HIDDEN:.o=.po}
>  SHIDDEN=${HIDDEN:.o=.so}
>  DHIDDEN=${HIDDEN:.o=.do}
> diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c
> new file mode 100644
> index 00000000000..5191b5b2606
> --- /dev/null
> +++ lib/libc/sys/microtime.c
> @@ -0,0 +1,181 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2000 Poul-Henning Kamp <[hidden email]>
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/atomic.h>
> +#include <sys/timetc.h>
> +
> +#include <time.h>
> +
> +/*
> + * Return the difference between the timehands' counter value now and what
> + * was when we copied it to the timehands' offset_count.
> + */
> +static inline int
> +tc_delta(struct timekeep *tk, u_int *delta)
> +{
> + uint tc;
> +
> + if (_tc_get_timecount(tk, &tc))
> + return -1;
> + *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
> + return 0;
> +}
> +
> +static inline void
> +bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct)
> +{
> + ct->sec = bt->sec;
> + if (bt->frac > bt->frac + x)
> + ct->sec++;
> + ct->frac = bt->frac + x;
> +}
> +
> +static inline void
> +BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts)
> +{
> + ts->tv_sec = bt->sec;
> + ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32);
> +}
> +
> +static inline void
> +BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv)
> +{
> + tv->tv_sec = bt->sec;
> + tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32);
> +}
> +
> +static int
> +binuptime(struct bintime *bt, struct timekeep *tk)
> +{
> + u_int gen, delta;
> +
> + do {
> + gen = tk->tk_generation;
> + membar_consumer();
> + *bt = tk->tk_offset;
> + if (tc_delta(tk, &delta))
> + return -1;
> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
> + membar_consumer();
> + } while (gen == 0 || gen != tk->tk_generation);
> +
> + return 0;
> +}
> +
> +static inline void
> +bintimeadd(const struct bintime *bt, const struct bintime *ct,
> +    struct bintime *dt)
> +{
> + dt->sec = bt->sec + ct->sec;
> + if (bt->frac > bt->frac + ct->frac)
> + dt->sec++;
> + dt->frac = bt->frac + ct->frac;
> +}
> +
> +static inline void
> +bintimesub(const struct bintime *bt, const struct bintime *ct,
> +    struct bintime *dt)
> +{
> + dt->sec = bt->sec - ct->sec;
> + if (bt->frac < bt->frac - ct->frac)
> + dt->sec--;
> + dt->frac = bt->frac - ct->frac;
> +}
> +
> +static int
> +binruntime(struct bintime *bt, struct timekeep *tk)
> +{
> + u_int gen, delta;
> +
> + do {
> + gen = tk->tk_generation;
> + membar_consumer();
> + if (tc_delta(tk, &delta))
> + return -1;
> + bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt);
> + bintimesub(bt, &tk->tk_naptime, bt);
> + membar_consumer();
> + } while (gen == 0 || gen != tk->tk_generation);
> +
> + return 0;
> +}
> +
> +static int
> +bintime(struct bintime *bt, struct timekeep *tk)
> +{
> + u_int gen, delta;
> +
> + do {
> + gen = tk->tk_generation;
> + membar_consumer();
> + *bt = tk->tk_offset;
> + if (tc_delta(tk, &delta))
> + return -1;
> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
> + bintimeadd(bt, &tk->tk_boottime, bt);
> + membar_consumer();
> + } while (gen == 0 || gen != tk->tk_generation);
> +
> + return 0;
> +}
> +
> +int
> +_microtime(struct timeval *tvp, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (bintime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMEVAL(&bt, tvp);
> + return 0;
> +}
> +
> +int
> +_nanotime(struct timespec *tsp, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (bintime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMESPEC(&bt, tsp);
> + return 0;
> +}
> +
> +int
> +_nanoruntime(struct timespec *ts, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (binruntime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMESPEC(&bt, ts);
> + return 0;
> +}
> +
> +
> +int
> +_nanouptime(struct timespec *tsp, struct timekeep *tk)
> +{
> + struct bintime bt;
> +
> + if (binuptime(&bt, tk))
> + return -1;
> + BINTIME_TO_TIMESPEC(&bt, tsp);
> + return 0;
> +}
> diff --git lib/libc/sys/w_clock_gettime.c lib/libc/sys/w_clock_gettime.c
> new file mode 100644
> index 00000000000..6e6478bd131
> --- /dev/null
> +++ lib/libc/sys/w_clock_gettime.c
> @@ -0,0 +1,51 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/timetc.h>
> +
> +#include <time.h>
> +
> +int
> +WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp)
> +{
> + int rc = 0;
> + struct timekeep *timekeep = _timekeep;
> +
> + if (timekeep == NULL || timekeep->tk_user == 0)
> + return clock_gettime(clock_id, tp);
> +
> + switch (clock_id) {
> + case CLOCK_REALTIME:
> + rc = _nanotime(tp, timekeep);
> + break;
> + case CLOCK_UPTIME:
> + rc = _nanoruntime(tp, timekeep);
> + break;
> + case CLOCK_MONOTONIC:
> + case CLOCK_BOOTTIME:
> + rc = _nanouptime(tp, timekeep);
> + break;
> + default:
> + return clock_gettime(clock_id, tp);
> + }
> +
> + if (rc)
> + return clock_gettime(clock_id, tp);
> +
> + return 0;
> +}
> +DEF_WRAP(clock_gettime);
> diff --git lib/libc/sys/w_gettimeofday.c lib/libc/sys/w_gettimeofday.c
> new file mode 100644
> index 00000000000..f44edfbb1ad
> --- /dev/null
> +++ lib/libc/sys/w_gettimeofday.c
> @@ -0,0 +1,40 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Robert Nagy <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/timetc.h>
> +
> +int
> +WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp)
> +{
> + int rc = 0;
> + struct timekeep *timekeep = _timekeep;
> + static struct timezone zerotz = { 0, 0 };
> +
> + if (timekeep == NULL || timekeep->tk_user == 0)
> + return gettimeofday(tp, tzp);
> +
> + if (tp)
> + rc = _microtime(tp, timekeep);
> + if (rc)
> + return gettimeofday(tp, tzp);
> +
> + if (tzp)
> + *tzp = zerotz;
> +
> + return 0;
> +}
> +DEF_WRAP(gettimeofday);
> diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h
> index 788890add89..df2239438d2 100644
> --- lib/libc/thread/synch.h
> +++ lib/libc/thread/synch.h
> @@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
>   if (abs == NULL)
>   return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
>  
> - if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
> + if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel))
>   return (EINVAL);
>  
>   rel.tv_sec = abs->tv_sec - rel.tv_sec;
> diff --git regress/lib/libc/timekeep/Makefile regress/lib/libc/timekeep/Makefile
> new file mode 100644
> index 00000000000..a7f3080290d
> --- /dev/null
> +++ regress/lib/libc/timekeep/Makefile
> @@ -0,0 +1,5 @@
> +# $OpenBSD$
> +
> +PROGS= test_clock_gettime test_time_skew test_gettimeofday
> +
> +.include <bsd.regress.mk>
> diff --git regress/lib/libc/timekeep/test_clock_gettime.c regress/lib/libc/timekeep/test_clock_gettime.c
> new file mode 100644
> index 00000000000..859ec368215
> --- /dev/null
> +++ regress/lib/libc/timekeep/test_clock_gettime.c
> @@ -0,0 +1,43 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <assert.h>
> +#include <time.h>
> +
> +#define ASSERT_EQ(a, b) assert((a) == (b))
> +
> +void
> +check()
> +{
> + struct timespec tp = {0};
> +
> + ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp));
> +
> +
> + ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp));
> + ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp));
> +
> +}
> +
> +int main()
> +{
> + check();
> + return 0;
> +}
> diff --git regress/lib/libc/timekeep/test_gettimeofday.c regress/lib/libc/timekeep/test_gettimeofday.c
> new file mode 100644
> index 00000000000..ea90a1be7e0
> --- /dev/null
> +++ regress/lib/libc/timekeep/test_gettimeofday.c
> @@ -0,0 +1,37 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <assert.h>
> +#include <sys/time.h>
> +
> +#define ASSERT_EQ(a, b) assert((a) == (b))
> +
> +void
> +check()
> +{
> + struct timeval tv = {0};
> + struct timezone tzp;
> +
> + ASSERT_EQ(0, gettimeofday(&tv, NULL));
> + ASSERT_EQ(0, gettimeofday(&tv, &tzp));
> +}
> +
> +int main()
> +{
> + check();
> + return 0;
> +}
> diff --git regress/lib/libc/timekeep/test_time_skew.c regress/lib/libc/timekeep/test_time_skew.c
> new file mode 100644
> index 00000000000..dfa9481c091
> --- /dev/null
> +++ regress/lib/libc/timekeep/test_time_skew.c
> @@ -0,0 +1,55 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/time.h>
> +
> +#include <assert.h>
> +#include <time.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#define ASSERT_EQ(a, b) assert((a) == (b))
> +#define ASSERT_NE(a, b) assert((a) != (b))
> +
> +void
> +check()
> +{
> +         struct timespec tp1, tp2, tout;
> +
> +         tout.tv_sec = 0;
> +         tout.tv_nsec = 100000;
> +
> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1));
> +
> +         nanosleep(&tout, NULL);
> +
> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2));
> +
> +         /* tp1 should never be larger than tp2 */
> +         ASSERT_NE(1, timespeccmp(&tp1, &tp2, >));
> +}
> +
> +int
> +main(void)
> +{
> + int i;
> +
> + for (i = 0; i < 1000; i++)
> + check();
> +
> + return 0;
> +}
> diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c
> index 3f5f2c5b42b..6eaf8b107c6 100644
> --- sys/arch/alpha/alpha/clock.c
> +++ sys/arch/alpha/alpha/clock.c
> @@ -64,7 +64,7 @@ int clk_irq = 0;
>  
>  u_int rpcc_get_timecount(struct timecounter *);
>  struct timecounter rpcc_timecounter = {
> - rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
> + rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0
>  };
>  
>  extern todr_chip_handle_t todr_handle;
> diff --git sys/arch/alpha/include/timetc.h sys/arch/alpha/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/alpha/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c
> index 7a1dcb4ad75..5839fa15d6c 100644
> --- sys/arch/amd64/amd64/tsc.c
> +++ sys/arch/amd64/amd64/tsc.c
> @@ -42,7 +42,7 @@ int64_t tsc_drift_observed;
>  volatile int64_t tsc_sync_val;
>  volatile struct cpu_info *tsc_sync_cpu;
>  
> -uint tsc_get_timecount(struct timecounter *tc);
> +u_int tsc_get_timecount(struct timecounter *tc);
>  
>  #include "lapic.h"
>  #if NLAPIC > 0
> @@ -50,7 +50,7 @@ extern u_int32_t lapic_per_second;
>  #endif
>  
>  struct timecounter tsc_timecounter = {
> - tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL
> + tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, TC_TSC
>  };
>  
>  uint64_t
> @@ -244,6 +244,7 @@ tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
>   printf("ERROR: %lld cycle TSC drift observed\n",
>      (long long)tsc_drift_observed);
>   tsc_timecounter.tc_quality = -1000;
> + tsc_timecounter.tc_user = 0;
>   tsc_is_invariant = 0;
>   }
>  
> diff --git sys/arch/amd64/include/timetc.h sys/arch/amd64/include/timetc.h
> new file mode 100644
> index 00000000000..c2d40bcd1e7
> --- /dev/null
> +++ sys/arch/amd64/include/timetc.h
> @@ -0,0 +1,24 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_TSC 1
> +#define TC_LAST 2
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c
> index 613f7ee0e0f..00da0c6a8d0 100644
> --- sys/arch/amd64/isa/clock.c
> +++ sys/arch/amd64/isa/clock.c
> @@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
>  u_int i8254_simple_get_timecount(struct timecounter *tc);
>  
>  static struct timecounter i8254_timecounter = {
> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
>  };
>  
>  int clockintr(void *);
> diff --git sys/arch/arm/include/timetc.h sys/arch/arm/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/arm/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c
> index 11196b5c60d..1a2106ef94c 100644
> --- sys/arch/arm64/dev/agtimer.c
> +++ sys/arch/arm64/dev/agtimer.c
> @@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY;
>  u_int agtimer_get_timecount(struct timecounter *);
>  
>  static struct timecounter agtimer_timecounter = {
> - agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL
> + agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0
>  };
>  
>  struct agtimer_pcpu_softc {
> diff --git sys/arch/arm64/include/timetc.h sys/arch/arm64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/arm64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/armv7/include/timetc.h sys/arch/armv7/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/armv7/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/armv7/omap/gptimer.c sys/arch/armv7/omap/gptimer.c
> index 7605845d5e2..061542d532f 100644
> --- sys/arch/armv7/omap/gptimer.c
> +++ sys/arch/armv7/omap/gptimer.c
> @@ -117,7 +117,7 @@ int gptimer_irq = 0;
>  u_int gptimer_get_timecount(struct timecounter *);
>  
>  static struct timecounter gptimer_timecounter = {
> - gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
> + gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0
>  };
>  
>  volatile u_int32_t nexttickevent;
> diff --git sys/arch/armv7/sunxi/sxitimer.c sys/arch/armv7/sunxi/sxitimer.c
> index 14a243c78d0..41028f9a602 100644
> --- sys/arch/armv7/sunxi/sxitimer.c
> +++ sys/arch/armv7/sunxi/sxitimer.c
> @@ -89,7 +89,7 @@ void sxitimer_delay(u_int);
>  u_int sxitimer_get_timecount(struct timecounter *);
>  
>  static struct timecounter sxitimer_timecounter = {
> - sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL
> + sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0
>  };
>  
>  bus_space_tag_t sxitimer_iot;
> diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c
> index 4c594ab5ec7..8cce6c3a893 100644
> --- sys/arch/hppa/dev/clock.c
> +++ sys/arch/hppa/dev/clock.c
> @@ -47,7 +47,7 @@ int cpu_hardclock(void *);
>  u_int itmr_get_timecount(struct timecounter *);
>  
>  struct timecounter itmr_timecounter = {
> - itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
> + itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0
>  };
>  
>  extern todr_chip_handle_t todr_handle;
> diff --git sys/arch/hppa/include/timetc.h sys/arch/hppa/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/hppa/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/i386/include/timetc.h sys/arch/i386/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/i386/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c
> index 09a6db983f2..dd74bd425ad 100644
> --- sys/arch/i386/isa/clock.c
> +++ sys/arch/i386/isa/clock.c
> @@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
>  u_int i8254_simple_get_timecount(struct timecounter *tc);
>  
>  static struct timecounter i8254_timecounter = {
> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
>  };
>  struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
>  u_long rtclock_tval;
> diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
> index 9d9f061eef9..bb8e4c7f9ae 100644
> --- sys/arch/i386/pci/geodesc.c
> +++ sys/arch/i386/pci/geodesc.c
> @@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = {
>   0xffffffff, /* counter_mask */
>   27000000, /* frequency */
>   "GEOTSC", /* name */
> - 2000 /* quality */
> + 2000, /* quality */
> + NULL, /* private bits */
> + 0 /* expose to user */
>  };
>  
>  int
> diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c
> index 8b8aa4ac430..a6f324e66f3 100644
> --- sys/arch/i386/pci/gscpm.c
> +++ sys/arch/i386/pci/gscpm.c
> @@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = {
>   0xffffff, /* counter_mask */
>   3579545, /* frequency */
>   "GSCPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0 /* expose to user */
>  };
>  
>  struct cfattach gscpm_ca = {
> diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c
> index 6abf1627de2..629a86a14ff 100644
> --- sys/arch/i386/pci/ichpcib.c
> +++ sys/arch/i386/pci/ichpcib.c
> @@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = {
>   0xffffff, /* counter_mask */
>   3579545, /* frequency */
>   "ICHPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0 /* expose to user */
>  };
>  
>  struct cfattach ichpcib_ca = {
> diff --git sys/arch/landisk/include/timetc.h sys/arch/landisk/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/landisk/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/loongson/include/timetc.h sys/arch/loongson/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/loongson/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/loongson/loongson/generic3a_machdep.c sys/arch/loongson/loongson/generic3a_machdep.c
> index ac3f1db6ccd..53489b07549 100644
> --- sys/arch/loongson/loongson/generic3a_machdep.c
> +++ sys/arch/loongson/loongson/generic3a_machdep.c
> @@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = {
>   .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */
>   .tc_frequency = HPET_FREQ,
>   .tc_name = "hpet",
> - .tc_quality = 100
> + .tc_quality = 100,
> + .tc_priv = NULL,
> + .tc_user = 0,
>  };
>  
>  /* Firmware entry points */
> diff --git sys/arch/luna88k/include/timetc.h sys/arch/luna88k/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/luna88k/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/luna88k/luna88k/clock.c sys/arch/luna88k/luna88k/clock.c
> index a04120987e0..6580a4a46bf 100644
> --- sys/arch/luna88k/luna88k/clock.c
> +++ sys/arch/luna88k/luna88k/clock.c
> @@ -112,7 +112,9 @@ struct timecounter clock_tc = {
>   .tc_counter_mask = 0xffffffff,
>   .tc_frequency = 0, /* will be filled in */
>   .tc_name = "clock",
> - .tc_quality = 0
> + .tc_quality = 0,
> + .tc_priv = NULL,
> + .tc_user = 0,
>  };
>  
>  /*
> diff --git sys/arch/m88k/include/timetc.h sys/arch/m88k/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/m88k/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/macppc/include/timetc.h sys/arch/macppc/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/macppc/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/macppc/macppc/clock.c sys/arch/macppc/macppc/clock.c
> index 4a44a92cfc0..8c3ad620be8 100644
> --- sys/arch/macppc/macppc/clock.c
> +++ sys/arch/macppc/macppc/clock.c
> @@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320;
>  static int32_t ticks_per_intr;
>  
>  static struct timecounter tb_timecounter = {
> - tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
> + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0
>  };
>  
>  /* calibrate the timecounter frequency for the listed models */
> diff --git sys/arch/mips64/include/timetc.h sys/arch/mips64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/mips64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/mips64/mips64/mips64_machdep.c sys/arch/mips64/mips64/mips64_machdep.c
> index d4a42ed5acc..5c4dbadb5bb 100644
> --- sys/arch/mips64/mips64/mips64_machdep.c
> +++ sys/arch/mips64/mips64/mips64_machdep.c
> @@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = {
>   0xffffffff, /* counter_mask */
>   0, /* frequency */
>   "CP0", /* name */
> - 0 /* quality */
> + 0, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  u_int
> diff --git sys/arch/octeon/include/timetc.h sys/arch/octeon/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/octeon/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/octeon/octeon/machdep.c sys/arch/octeon/octeon/machdep.c
> index 902e462d53f..d8377653abe 100644
> --- sys/arch/octeon/octeon/machdep.c
> +++ sys/arch/octeon/octeon/machdep.c
> @@ -151,8 +151,9 @@ struct timecounter ioclock_timecounter = {
>   .tc_name = "ioclock",
>   .tc_quality = 0, /* ioclock can be overridden
>   * by cp0 counter */
> - .tc_priv = 0 /* clock register,
> + .tc_priv = 0, /* clock register,
>   * determined at runtime */
> + .tc_user = 0, /* expose to user */
>  };
>  
>  static int
> diff --git sys/arch/powerpc/include/timetc.h sys/arch/powerpc/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/powerpc/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/powerpc64/include/timetc.h sys/arch/powerpc64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/powerpc64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sgi/include/timetc.h sys/arch/sgi/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/sgi/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sgi/sgi/ip27_machdep.c sys/arch/sgi/sgi/ip27_machdep.c
> index ba7fa558b96..2a2cc144242 100644
> --- sys/arch/sgi/sgi/ip27_machdep.c
> +++ sys/arch/sgi/sgi/ip27_machdep.c
> @@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = {
>   .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */
>   .tc_frequency = 1250000,
>   .tc_name = "hubrt",
> - .tc_quality = 100
> + .tc_quality = 100,
> + .tc_priv = 0,
> + .tc_user = 0,
>  };
>  
>  volatile uint64_t ip27_spinup_a0;
> diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c
> index 56b29915c70..827775512ac 100644
> --- sys/arch/sgi/xbow/xheart.c
> +++ sys/arch/sgi/xbow/xheart.c
> @@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = {
>   .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit */
>   .tc_frequency = 12500000,
>   .tc_name = "heart",
> - .tc_quality = 100
> + .tc_quality = 100,
> + .tc_priv = NULL,
> + .tc_user = 0,
>  };
>  
>  extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *);
> diff --git sys/arch/sh/include/timetc.h sys/arch/sh/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/sh/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sparc64/dev/psycho.c sys/arch/sparc64/dev/psycho.c
> index e24f804dff6..1a7a1afa8c2 100644
> --- sys/arch/sparc64/dev/psycho.c
> +++ sys/arch/sparc64/dev/psycho.c
> @@ -127,7 +127,7 @@ extern struct sparc_pci_chipset _sparc_pci_chipset;
>  u_int stick_get_timecount(struct timecounter *);
>  
>  struct timecounter stick_timecounter = {
> - stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
> + stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0
>  };
>  
>  /*
> diff --git sys/arch/sparc64/include/timetc.h sys/arch/sparc64/include/timetc.h
> new file mode 100644
> index 00000000000..e58a7fb4faa
> --- /dev/null
> +++ sys/arch/sparc64/include/timetc.h
> @@ -0,0 +1,23 @@
> +/* $OpenBSD$ */
> +/*
> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef _MACHINE_TIMETC_H_
> +#define _MACHINE_TIMETC_H_
> +
> +#define TC_LAST 0
> +
> +#endif /* _MACHINE_TIMETC_H_ */
> diff --git sys/arch/sparc64/sparc64/clock.c sys/arch/sparc64/sparc64/clock.c
> index fd5e8a9c15b..5c2e47d386b 100644
> --- sys/arch/sparc64/sparc64/clock.c
> +++ sys/arch/sparc64/sparc64/clock.c
> @@ -109,13 +109,13 @@ struct cfdriver clock_cd = {
>  u_int tick_get_timecount(struct timecounter *);
>  
>  struct timecounter tick_timecounter = {
> - tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL
> + tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0
>  };
>  
>  u_int sys_tick_get_timecount(struct timecounter *);
>  
>  struct timecounter sys_tick_timecounter = {
> - sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL
> + sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0
>  };
>  
>  /*
> diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c
> index d0ee72cec9b..13177a909da 100644
> --- sys/dev/acpi/acpihpet.c
> +++ sys/dev/acpi/acpihpet.c
> @@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = {
>   0xffffffff, /* counter_mask (32 bits) */
>   0, /* frequency */
>   0, /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  #define HPET_TIMERS 3
> diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c
> index cdc8c99a17a..89b5a397e47 100644
> --- sys/dev/acpi/acpitimer.c
> +++ sys/dev/acpi/acpitimer.c
> @@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = {
>   0x00ffffff, /* counter_mask (24 bits) */
>   ACPI_FREQUENCY, /* frequency */
>   0, /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  struct acpitimer_softc {
> diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c
> index 6df82858016..9610d5bc1f0 100644
> --- sys/dev/pci/amdpm.c
> +++ sys/dev/pci/amdpm.c
> @@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = {
>   0xffffff, /* counter_mask */
>   AMDPM_FREQUENCY, /* frequency */
>   "AMDPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  #define AMDPM_CONFREG 0x40
> diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c
> index db806eedf80..ce33cd175e6 100644
> --- sys/dev/pci/viapm.c
> +++ sys/dev/pci/viapm.c
> @@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = {
>   0xffffff, /* counter_mask */
>   VIAPM_FREQUENCY, /* frequency */
>   "VIAPM", /* name */
> - 1000 /* quality */
> + 1000, /* quality */
> + NULL, /* private bits */
> + 0, /* expose to user */
>  };
>  
>  struct timeout viapm_timeout;
> diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c
> index b32facdacb1..b9ee2feec4c 100644
> --- sys/dev/pv/hyperv.c
> +++ sys/dev/pv/hyperv.c
> @@ -141,7 +141,7 @@ struct {
>  };
>  
>  struct timecounter hv_timecounter = {
> - hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001
> + hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0
>  };
>  
>  struct cfdriver hyperv_cd = {
> diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c
> index 6b242f7448d..b80e4d2a484 100644
> --- sys/dev/pv/pvclock.c
> +++ sys/dev/pv/pvclock.c
> @@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = {
>  };
>  
>  struct timecounter pvclock_timecounter = {
> - pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL
> + pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0
>  };
>  
>  int
> diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c
> index 9b5b8eb3acf..59bc923a6fb 100644
> --- sys/kern/exec_elf.c
> +++ sys/kern/exec_elf.c
> @@ -124,7 +124,7 @@ extern char *syscallnames[];
>  /*
>   * How many entries are in the AuxInfo array we pass to the process?
>   */
> -#define ELF_AUX_ENTRIES 8
> +#define ELF_AUX_ENTRIES 9
>  
>  /*
>   * This is the OpenBSD ELF emul
> @@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct exec_package *epp)
>   a->au_v = ap->arg_entry;
>   a++;
>  
> + a->au_id = AUX_openbsd_timekeep;
> + a->au_v = p->p_p->ps_timekeep;
> + a++;
> +
>   a->au_id = AUX_null;
>   a->au_v = 0;
>   a++;
> diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
> index 20480c2fc28..222450607d5 100644
> --- sys/kern/kern_exec.c
> +++ sys/kern/kern_exec.c
> @@ -64,6 +64,11 @@
>  #include <uvm/uvm_extern.h>
>  #include <machine/tcb.h>
>  
> +#include <sys/timetc.h>
> +
> +struct uvm_object *timekeep_object;
> +struct timekeep* timekeep;
> +
>  void unveil_destroy(struct process *ps);
>  
>  const struct kmem_va_mode kv_exec = {
> @@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = {
>   */
>  int exec_sigcode_map(struct process *, struct emul *);
>  
> +/*
> + * Map the shared timekeep page.
> + */
> +int exec_timekeep_map(struct process *);
> +
>  /*
>   * If non-zero, stackgap_random specifies the upper limit of the random gap size
>   * added to the fixed stack position. Must be n^2.
> @@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t *retval)
>   /* map the process's signal trampoline code */
>   if (exec_sigcode_map(pr, pack.ep_emul))
>   goto free_pack_abort;
> + /* map the process's timekeep page */
> + if (exec_timekeep_map(pr))
> + goto free_pack_abort;
>  
>  #ifdef __HAVE_EXEC_MD_MAP
>   /* perform md specific mappings that process might need */
> @@ -863,3 +876,40 @@ exec_sigcode_map(struct process *pr, struct emul *e)
>  
>   return (0);
>  }
> +
> +int
> +exec_timekeep_map(struct process *pr)
> +{
> + size_t timekeep_sz = sizeof(struct timekeep);
> +
> + /*
> + * Similar to the sigcode object, except that there is a single
> + * timekeep object, and not one per emulation.
> + */
> + if (timekeep_object == NULL) {
> + vaddr_t va;
> +
> + timekeep_object = uao_create(timekeep_sz, 0);
> + uao_reference(timekeep_object);
> +
> + if (uvm_map(kernel_map, &va, round_page(timekeep_sz), timekeep_object,
> +    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
> +    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
> + uao_detach(timekeep_object);
> + return (ENOMEM);
> + }
> +
> + timekeep = (struct timekeep *)va;
> + timekeep->tk_version = TK_VERSION;
> + }
> +
> + uao_reference(timekeep_object);
> + if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, round_page(timekeep_sz),
> +    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
> +    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
> + uao_detach(timekeep_object);
> + return (ENOMEM);
> + }
> +
> + return (0);
> +}
> diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
> index 88d4a3379f9..47efbdd0b78 100644
> --- sys/kern/kern_tc.c
> +++ sys/kern/kern_tc.c
> @@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc)
>  }
>  
>  static struct timecounter dummy_timecounter = {
> - dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
> + dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0
>  };
>  
>  /*
> @@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts)
>  #endif
>  }
>  
> +void
> +tc_update_timekeep(void)
> +{
> + static struct timecounter *last_tc = NULL;
> + struct timehands *th;
> +
> + if (timekeep == NULL)
> + return;
> +
> + th = timehands;
> + timekeep->tk_generation = 0;
> + membar_producer();
> + timekeep->tk_scale = th->th_scale;
> + timekeep->tk_offset_count = th->th_offset_count;
> + timekeep->tk_offset = th->th_offset;
> + timekeep->tk_naptime = th->th_naptime;
> + timekeep->tk_boottime = th->th_boottime;
> + if (last_tc != th->th_counter) {
> + timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
> + timekeep->tk_user = th->th_counter->tc_user;
> + last_tc = th->th_counter;
> + }
> + membar_producer();
> + timekeep->tk_generation = th->th_generation;
> +
> + return;
> +}
> +
>  /*
>   * Initialize the next struct timehands in the ring and make
>   * it the active timehands.  Along the way we might switch to a different
> @@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
>   time_uptime = th->th_offset.sec;
>   membar_producer();
>   timehands = th;
> +
> + tc_update_timekeep();
>  }
>  
>  /* Report or change the active timecounter hardware. */
> diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h
> index a40e0510273..3084ed595a6 100644
> --- sys/sys/exec_elf.h
> +++ sys/sys/exec_elf.h
> @@ -691,7 +691,8 @@ enum AuxID {
>   AUX_sun_uid = 2000, /* euid */
>   AUX_sun_ruid = 2001, /* ruid */
>   AUX_sun_gid = 2002, /* egid */
> - AUX_sun_rgid = 2003 /* rgid */
> + AUX_sun_rgid = 2003, /* rgid */
> + AUX_openbsd_timekeep = 4000, /* userland clock_gettime */
>  };
>  
>  struct elf_args {
> diff --git sys/sys/proc.h sys/sys/proc.h
> index 357c0c0d52c..c6d54572bdd 100644
> --- sys/sys/proc.h
> +++ sys/sys/proc.h
> @@ -242,6 +242,7 @@ struct process {
>   char ps_comm[MAXCOMLEN+1];
>  
>   vaddr_t ps_strings; /* User pointers to argv/env */
> + vaddr_t ps_timekeep; /* User pointer to timekeep */
>   vaddr_t ps_sigcode; /* User pointer to the signal code */
>   vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */
>   u_long ps_sigcookie;
> diff --git sys/sys/time.h sys/sys/time.h
> index e758a64ce07..bcd3acd034d 100644
> --- sys/sys/time.h
> +++ sys/sys/time.h
> @@ -163,7 +163,7 @@ struct clockinfo {
>  };
>  #endif /* __BSD_VISIBLE */
>  
> -#if defined(_KERNEL) || defined(_STANDALONE)
> +#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC)
>  #include <sys/_time.h>
>  
>  /* Time expressed as seconds and fractions of a second + operations on it. */
> @@ -171,6 +171,9 @@ struct bintime {
>   time_t sec;
>   uint64_t frac;
>  };
> +#endif
> +
> +#if defined(_KERNEL) || defined(_STANDALONE)
>  
>  #define bintimecmp(btp, ctp, cmp) \
>   ((btp)->sec == (ctp)->sec ? \
> diff --git sys/sys/timetc.h sys/sys/timetc.h
> index ce81c3475a0..c5ad27695ba 100644
> --- sys/sys/timetc.h
> +++ sys/sys/timetc.h
> @@ -24,10 +24,11 @@
>  #ifndef _SYS_TIMETC_H_
>  #define _SYS_TIMETC_H_
>  
> -#ifndef _KERNEL
> +#if !defined(_KERNEL) && !defined(_LIBC)
>  #error "no user-serviceable parts inside"
>  #endif
>  
> +#include <machine/timetc.h>
>  #include <sys/queue.h>
>  
>  /*-
> @@ -80,6 +81,8 @@ struct timecounter {
>   */
>   void *tc_priv; /* [I] */
>   /* Pointer to the timecounter's private parts. */
> + int tc_user; /* [I] */
> + /* Expose this timecounter to userland. */
>   SLIST_ENTRY(timecounter) tc_next; /* [I] */
>   /* Pointer to the next timecounter. */
>   int64_t tc_freq_adj; /* [tw] */
> @@ -88,11 +91,32 @@ struct timecounter {
>   /* Precision of the counter.  Computed in tc_init(). */
>  };
>  
> +struct timekeep {
> + /* set at initialization */
> + uint32_t tk_version; /* version number */
> +
> + /* timehands members */
> + uint64_t tk_scale;
> + u_int tk_offset_count;
> + struct bintime tk_offset;
> + struct bintime tk_naptime;
> + struct bintime tk_boottime;
> + volatile u_int tk_generation;
> +
> + /* timecounter members */
> + int tk_user;
> + u_int tk_counter_mask;
> +};
> +#define TK_VERSION 0
> +
>  struct rwlock;
>  extern struct rwlock tc_lock;
>  
>  extern struct timecounter *timecounter;
>  
> +extern struct uvm_object *timekeep_object;
> +extern struct timekeep *timekeep;
> +
>  u_int64_t tc_getfrequency(void);
>  u_int64_t tc_getprecision(void);
>  void tc_init(struct timecounter *tc);
>

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Paul Irofti-4


În 19 iunie 2020 22:49:32 EEST, Mark Kettenis <[hidden email]> a scris:

>> Date: Fri, 19 Jun 2020 20:28:58 +0300
>> From: Paul Irofti <[hidden email]>
>>
>> On Fri, Jun 19, 2020 at 06:52:40PM +0200, Mark Kettenis wrote:
>> > > Date: Fri, 19 Jun 2020 14:31:17 +0300
>> > > From: Paul Irofti <[hidden email]>
>> > >
>> > > Hi,
>> > >
>> > > Here is another iteration of the diff that addresses all issues
>raised
>> > > in the meantime:
>> > >
>> > >   - Switch tc to uint
>> >
>> > The request was to use u_int, like we de in the kernel.  The uint
>type
>> > should not be used in OpenBSD code.
>> >
>> > >   - Check for version at init and switch to machite/timetc.h defs
>> > >   - Remove tk_nclocks
>> > >   - Switch to single version and ditch minor/major
>> > >   - Do not enable user TSC for large skew values
>> > >   - Add amd64 clocks and use the define in TSC
>> > >   - Include and add machine/timetc.h
>> > >
>> > > As we have seen most architectures have support for clocks now
>and the
>> > > above addresses Mark's last concerns.
>> > >
>> > > Unless other blocking issues arise, this time around I am looking
>for
>> > > OKs to commit. Theo? Mark?
>> >
>> > There is one other issue that I wanted to raise.  An that is
>whether
>> > we really need to implement CLOCK_UPTINME as a userland clock.  If
>we
>> > don't do that we can drop tk_naptime from the shared struct.  I
>> > mention this because th_naptime was only recently added to struct
>> > timehands and much more an implementation detail than the other
>fields.
>> >
>> > I don't expect userland processes to call CLOCK_UPTIME in a loop
>like
>> > they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
>> > doesn't have it ;).
>>
>> I don't care eitherway about this. But I don't see why we would not
>have
>> this functionality if it is easy to offer. Maybe someone can help us
>> grep the ports tree for this? Stuart? :)
>>
>> > We're getting there...
>>
>> I have addressed your comments bellow, except for the CPU skew one.
>That
>> code disables TSC for all CPUs, not just for PRIMARY. Would you like
>to
>> walk and add code for every CPU to check the drift and then disable
>the
>> TSC? It seems a little too much...
>
>Still uses uint instead of u_int in places.

Ok. I will check that again.

> Still has the pointless
>extra NULL and 0 for timecounters in files that are otherwise

I am not fixing that. If there's a null present before my diff, then there can be a 0 afterwards. If anything my diff unifies this. This is silly.

>And regarding the TSC.  That issue is a show-stopper.  We can tolerate
>a small amout of skew, but not a large amount.  Because otherwise a
>multithreaded process might observe time going backwards.

I don't see how this is still an issue with my diff, which is what I said last time. I am stopping the TSC when the drift is larger than a random value that I defined a year ago. What more is needed? Can you describe in more details?

Thank you,
Paul


>
>> diff --git lib/libc/arch/aarch64/gen/Makefile.inc
>lib/libc/arch/aarch64/gen/Makefile.inc
>> index a7b1b73f3ef..ee198f5d611 100644
>> --- lib/libc/arch/aarch64/gen/Makefile.inc
>> +++ lib/libc/arch/aarch64/gen/Makefile.inc
>> @@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
>>  SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
>>  SRCS+= fpclassifyl.c
>>  SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
>> -SRCS+= signbitl.c
>> +SRCS+= signbitl.c usertc.c
>> diff --git lib/libc/arch/aarch64/gen/usertc.c
>lib/libc/arch/aarch64/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/aarch64/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/alpha/gen/Makefile.inc
>lib/libc/arch/alpha/gen/Makefile.inc
>> index a44599d2cab..2a8abd32b61 100644
>> --- lib/libc/arch/alpha/gen/Makefile.inc
>> +++ lib/libc/arch/alpha/gen/Makefile.inc
>> @@ -3,5 +3,5 @@
>>  
>>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
>>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>fpsetmask.c \
>> - fpsetround.c fpsetsticky.c
>> + fpsetround.c fpsetsticky.c usertc.c
>>  SRCS+= sigsetjmp.S
>> diff --git lib/libc/arch/alpha/gen/usertc.c
>lib/libc/arch/alpha/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/alpha/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/amd64/gen/Makefile.inc
>lib/libc/arch/amd64/gen/Makefile.inc
>> index e995309ed71..f6349e2b974 100644
>> --- lib/libc/arch/amd64/gen/Makefile.inc
>> +++ lib/libc/arch/amd64/gen/Makefile.inc
>> @@ -2,6 +2,7 @@
>>  
>>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
>>   sigsetjmp.S
>> -SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>signbitl.c
>> +SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>signbitl.c \
>> + usertc.c
>>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S
>fpsetmask.S \
>>   fpsetround.S fpsetsticky.S
>> diff --git lib/libc/arch/amd64/gen/usertc.c
>lib/libc/arch/amd64/gen/usertc.c
>> new file mode 100644
>> index 00000000000..742fb0cc458
>> --- /dev/null
>> +++ lib/libc/arch/amd64/gen/usertc.c
>> @@ -0,0 +1,41 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +static inline uint
>> +rdtsc(void)
>> +{
>> + uint32_t hi, lo;
>> + asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
>> + return ((uint64_t)lo)|(((uint64_t)hi)<<32);
>> +}
>> +
>> +int
>> +tc_get_timecount(struct timekeep *tk, u_int *tc)
>> +{
>> + int tk_user = tk->tk_user;
>> +
>> + if (tk_user < 1 || tk_user >= TC_LAST)
>> + return -1;
>> +
>> + *tc = rdtsc();
>> + return 0;
>> +}
>> +int (*const _tc_get_timecount)(struct timekeep *tk, u_int *tc)
>> + = tc_get_timecount;
>> diff --git lib/libc/arch/arm/gen/Makefile.inc
>lib/libc/arch/arm/gen/Makefile.inc
>> index 1b4ab2f3ae7..27090a0d9dc 100644
>> --- lib/libc/arch/arm/gen/Makefile.inc
>> +++ lib/libc/arch/arm/gen/Makefile.inc
>> @@ -2,5 +2,5 @@
>>  # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
>>  
>>  SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c
>infinity.c
>> -SRCS+= ldexp.c modf.c nan.c
>> +SRCS+= ldexp.c modf.c nan.c usertc.c
>>  SRCS+= setjmp.S _setjmp.S sigsetjmp.S
>> diff --git lib/libc/arch/arm/gen/usertc.c
>lib/libc/arch/arm/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/arm/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/hppa/gen/Makefile.inc
>lib/libc/arch/hppa/gen/Makefile.inc
>> index e0c864242fe..1fde24670f1 100644
>> --- lib/libc/arch/hppa/gen/Makefile.inc
>> +++ lib/libc/arch/hppa/gen/Makefile.inc
>> @@ -2,6 +2,6 @@
>>  
>>  SRCS+= setjmp.S
>>  SRCS+= fabs.c
>> -SRCS+= infinity.c ldexp.c modf.c nan.c
>> +SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
>>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>fpsetmask.c \
>>   fpsetround.c fpsetsticky.c
>> diff --git lib/libc/arch/hppa/gen/usertc.c
>lib/libc/arch/hppa/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/hppa/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/i386/gen/Makefile.inc
>lib/libc/arch/i386/gen/Makefile.inc
>> index 4c18e059581..b7dd30adccd 100644
>> --- lib/libc/arch/i386/gen/Makefile.inc
>> +++ lib/libc/arch/i386/gen/Makefile.inc
>> @@ -1,6 +1,6 @@
>>  # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
>>  
>> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
>> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
>>   modf.S nan.c setjmp.S sigsetjmp.S
>>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>signbitl.c
>>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S
>fpsetmask.S \
>> diff --git lib/libc/arch/i386/gen/usertc.c
>lib/libc/arch/i386/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/i386/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/m88k/gen/Makefile.inc
>lib/libc/arch/m88k/gen/Makefile.inc
>> index cff75b8d425..d66f66af4af 100644
>> --- lib/libc/arch/m88k/gen/Makefile.inc
>> +++ lib/libc/arch/m88k/gen/Makefile.inc
>> @@ -1,7 +1,7 @@
>>  # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
>>  # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
>>  
>> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
>> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
>>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>fpsetmask.c \
>>   fpsetround.c fpsetsticky.c
>>  SRCS+= setjmp.S sigsetjmp.S
>> diff --git lib/libc/arch/m88k/gen/usertc.c
>lib/libc/arch/m88k/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/m88k/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/mips64/gen/Makefile.inc
>lib/libc/arch/mips64/gen/Makefile.inc
>> index 8cf1fc2d28a..839241a2069 100644
>> --- lib/libc/arch/mips64/gen/Makefile.inc
>> +++ lib/libc/arch/mips64/gen/Makefile.inc
>> @@ -1,6 +1,6 @@
>>  # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
>>  
>> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
>> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
>>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>fpsetmask.c \
>>   fpsetround.c fpsetsticky.c
>>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>signbitl.c
>> diff --git lib/libc/arch/mips64/gen/usertc.c
>lib/libc/arch/mips64/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/mips64/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/powerpc/gen/Makefile.inc
>lib/libc/arch/powerpc/gen/Makefile.inc
>> index 6b2e4613ee8..d4d7b00bff7 100644
>> --- lib/libc/arch/powerpc/gen/Makefile.inc
>> +++ lib/libc/arch/powerpc/gen/Makefile.inc
>> @@ -1,5 +1,5 @@
>>  SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c
>nan.c
>> -SRCS+= fabs.c
>> +SRCS+= fabs.c usertc.c
>>  SRCS+= fpgetmask.c fpsetmask.c
>>  SRCS+= fpgetround.c fpsetround.c
>>  SRCS+= fpgetsticky.c fpsetsticky.c
>> diff --git lib/libc/arch/powerpc/gen/usertc.c
>lib/libc/arch/powerpc/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/powerpc/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/sh/gen/Makefile.inc
>lib/libc/arch/sh/gen/Makefile.inc
>> index 55de1973b30..4724fb3a6a8 100644
>> --- lib/libc/arch/sh/gen/Makefile.inc
>> +++ lib/libc/arch/sh/gen/Makefile.inc
>> @@ -3,4 +3,4 @@
>>  SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S
>_setjmp.S
>>  SRCS+= sigsetjmp.S
>>  SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
>> - fpsetmask.c fpsetround.c fpsetsticky.c
>> + fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
>> diff --git lib/libc/arch/sh/gen/usertc.c
>lib/libc/arch/sh/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/sh/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/arch/sparc64/gen/Makefile.inc
>lib/libc/arch/sparc64/gen/Makefile.inc
>> index 58259cedef6..a908e022954 100644
>> --- lib/libc/arch/sparc64/gen/Makefile.inc
>> +++ lib/libc/arch/sparc64/gen/Makefile.inc
>> @@ -3,5 +3,5 @@
>>  SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
>>   fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>>   fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
>> - isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
>> + isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
>>   mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
>> diff --git lib/libc/arch/sparc64/gen/usertc.c
>lib/libc/arch/sparc64/gen/usertc.c
>> new file mode 100644
>> index 00000000000..6551854a010
>> --- /dev/null
>> +++ lib/libc/arch/sparc64/gen/usertc.c
>> @@ -0,0 +1,21 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/timetc.h>
>> +
>> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
>> diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
>> index 131da4b2190..40e84771f86 100644
>> --- lib/libc/asr/asr.c
>> +++ lib/libc/asr/asr.c
>> @@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds,
>int timeout)
>>   struct timespec pollstart, pollend, elapsed;
>>   int r;
>>  
>> - if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
>> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
>>   return -1;
>>  
>>   while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
>> - if (clock_gettime(CLOCK_MONOTONIC, &pollend))
>> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
>>   return -1;
>>   timespecsub(&pollend, &pollstart, &elapsed);
>>   timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
>> @@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
>>   asr->a_rtime = 0;
>>   }
>>  
>> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
>> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>>   return;
>>  
>>   if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
>> diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
>> index 82de8fa33b7..02fd3013cc1 100644
>> --- lib/libc/crypt/bcrypt.c
>> +++ lib/libc/crypt/bcrypt.c
>> @@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
>>   char buf[_PASSWORD_LEN];
>>   int duration;
>>  
>> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
>> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
>>   bcrypt_newhash("testpassword", r, buf, sizeof(buf));
>> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
>> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
>>  
>>   duration = after.tv_sec - before.tv_sec;
>>   duration *= 1000000;
>> diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
>> index 270f54aada5..d2632455f11 100644
>> --- lib/libc/dlfcn/init.c
>> +++ lib/libc/dlfcn/init.c
>> @@ -20,6 +20,7 @@
>>  
>>  #include <sys/types.h>
>>  #include <sys/syscall.h>
>> +#include <sys/timetc.h> /* timekeep */
>>  
>>  #ifndef PIC
>>  #include <sys/mman.h>
>> @@ -45,8 +46,9 @@
>>  /* XXX should be in an include file shared with csu */
>>  char ***_csu_finish(char **_argv, char **_envp, void
>(*_cleanup)(void));
>>  
>> -/* provide definition for this */
>> +/* provide definitions for these */
>>  int _pagesize = 0;
>> +struct timekeep *_timekeep;
>>  
>>  /*
>>   * In dynamicly linked binaries environ and __progname are overriden
>by
>> @@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char
>**envp, dl_cb_cb *cb)
>>   phnum = aux->au_v;
>>   break;
>>  #endif /* !PIC */
>> + case AUX_openbsd_timekeep:
>> + if (_tc_get_timecount) {
>> + _timekeep = (void *)aux->au_v;
>> + if (_timekeep->tk_version != TK_VERSION)
>> + _timekeep = NULL;
>> + }
>> + break;
>>   }
>>   }
>>  
>> diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
>> index 1286a96fe40..32f86eda50f 100644
>> --- lib/libc/gen/auth_subr.c
>> +++ lib/libc/gen/auth_subr.c
>> @@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
>>  
>>   if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
>>   if (as->now.tv_sec == 0)
>> - gettimeofday(&as->now, NULL);
>> + WRAP(gettimeofday)(&as->now, NULL);
>>   if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
>>   as->state &= ~AUTH_ALLOW;
>>   as->state |= AUTH_EXPIRED;
>> @@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
>>  
>>   if (as->pwd && (quad_t)as->pwd->pw_change) {
>>   if (as->now.tv_sec == 0)
>> - gettimeofday(&as->now, NULL);
>> + WRAP(gettimeofday)(&as->now, NULL);
>>   if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
>>   as->state &= ~AUTH_ALLOW;
>>   as->state |= AUTH_PWEXPIRED;
>> diff --git lib/libc/gen/time.c lib/libc/gen/time.c
>> index 3bbd0d733d1..b3ce9a800f1 100644
>> --- lib/libc/gen/time.c
>> +++ lib/libc/gen/time.c
>> @@ -36,7 +36,7 @@ time(time_t *t)
>>  {
>>   struct timeval tt;
>>  
>> - if (gettimeofday(&tt, NULL) == -1)
>> + if (WRAP(gettimeofday)(&tt, NULL) == -1)
>>   return (-1);
>>   if (t)
>>   *t = (time_t)tt.tv_sec;
>> diff --git lib/libc/gen/times.c lib/libc/gen/times.c
>> index 02e4dd44b5c..36841810d1b 100644
>> --- lib/libc/gen/times.c
>> +++ lib/libc/gen/times.c
>> @@ -52,7 +52,7 @@ times(struct tms *tp)
>>   return ((clock_t)-1);
>>   tp->tms_cutime = CONVTCK(ru.ru_utime);
>>   tp->tms_cstime = CONVTCK(ru.ru_stime);
>> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
>> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>>   return ((clock_t)-1);
>>   return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK));
>>  }
>> diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
>> index 520a5954025..845cbe80356 100644
>> --- lib/libc/gen/timespec_get.c
>> +++ lib/libc/gen/timespec_get.c
>> @@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
>>  {
>>   switch (base) {
>>   case TIME_UTC:
>> - if (clock_gettime(CLOCK_REALTIME, ts) == -1)
>> + if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
>>   return 0;
>>   break;
>>   default:
>> diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
>> index ed112320fa2..df717021cab 100644
>> --- lib/libc/hidden/sys/time.h
>> +++ lib/libc/hidden/sys/time.h
>> @@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
>>  PROTO_NORMAL(adjtime);
>>  PROTO_NORMAL(futimes);
>>  PROTO_NORMAL(getitimer);
>> -PROTO_NORMAL(gettimeofday);
>> +PROTO_WRAP(gettimeofday);
>>  PROTO_NORMAL(setitimer);
>>  PROTO_NORMAL(settimeofday);
>>  PROTO_NORMAL(utimes);
>> diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h
>> new file mode 100644
>> index 00000000000..bbdaa2d0d4c
>> --- /dev/null
>> +++ lib/libc/hidden/sys/timetc.h
>> @@ -0,0 +1,38 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _LIBC_SYS_TIMETC_H_
>> +#define _LIBC_SYS_TIMETC_H_
>> +
>> +#define _LIBC
>> +#include <sys/types.h>
>> +#include <sys/time.h>
>> +
>> +#include_next <sys/timetc.h>
>> +
>> +__BEGIN_HIDDEN_DECLS
>> +extern struct timekeep *_timekeep;
>> +
>> +extern int (*const _tc_get_timecount)(struct timekeep *, u_int *);
>> +
>> +int _microtime(struct timeval *, struct timekeep *);
>> +int _nanotime(struct timespec *, struct timekeep *);
>> +int _nanoruntime(struct timespec *, struct timekeep *);
>> +int _nanouptime(struct timespec *, struct timekeep *);
>> +__END_HIDDEN_DECLS
>> +
>> +#endif /* !_LIBC_SYS_TIMETC_H_ */
>> diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h
>> index 18c49f8fcb9..d8e1e0caf64 100644
>> --- lib/libc/hidden/time.h
>> +++ lib/libc/hidden/time.h
>> @@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r);
>>  PROTO_STD_DEPRECATED(clock);
>>  PROTO_DEPRECATED(clock_getcpuclockid);
>>  PROTO_NORMAL(clock_getres);
>> -PROTO_NORMAL(clock_gettime);
>> +PROTO_WRAP(clock_gettime);
>>  PROTO_NORMAL(clock_settime);
>>  PROTO_STD_DEPRECATED(ctime);
>>  PROTO_DEPRECATED(ctime_r);
>> diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c
>> index 763e420bb88..9babb28470a 100644
>> --- lib/libc/net/res_random.c
>> +++ lib/libc/net/res_random.c
>> @@ -219,7 +219,7 @@ res_initid(void)
>>   if (ru_prf != NULL)
>>   arc4random_buf(ru_prf, sizeof(*ru_prf));
>>  
>> - clock_gettime(CLOCK_MONOTONIC, &ts);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
>>   ru_reseed = ts.tv_sec + RU_OUT;
>>   ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
>>  }
>> @@ -232,7 +232,7 @@ __res_randomid(void)
>>   u_int r;
>>   static void *randomid_mutex;
>>  
>> - clock_gettime(CLOCK_MONOTONIC, &ts);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
>>   pid = getpid();
>>  
>>   _MUTEX_LOCK(&randomid_mutex);
>> diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c
>> index 402d98cede4..917a6d42b8a 100644
>> --- lib/libc/rpc/auth_unix.c
>> +++ lib/libc/rpc/auth_unix.c
>> @@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid,
>int len, int *aup_gids)
>>   /*
>>   * fill in param struct from the given params
>>   */
>> - (void)gettimeofday(&now,  NULL);
>> + (void)WRAP(gettimeofday)(&now,  NULL);
>>   aup.aup_time = now.tv_sec;
>>   aup.aup_machname = machname;
>>   aup.aup_uid = uid;
>> @@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth)
>>   goto done;
>>  
>>   /* update the time and serialize in place */
>> - (void)gettimeofday(&now, NULL);
>> + (void)WRAP(gettimeofday)(&now, NULL);
>>   aup.aup_time = now.tv_sec;
>>   xdrs.x_op = XDR_ENCODE;
>>   XDR_SETPOS(&xdrs, 0);
>> diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c
>> index 8e6ef515b0e..927b4bf2028 100644
>> --- lib/libc/rpc/clnt_tcp.c
>> +++ lib/libc/rpc/clnt_tcp.c
>> @@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int
>len)
>>   pfd[0].events = POLLIN;
>>   TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait);
>>   delta = wait;
>> - clock_gettime(CLOCK_MONOTONIC, &start);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>>   for (;;) {
>>   r = ppoll(pfd, 1, &delta, NULL);
>>   save_errno = errno;
>>  
>> - clock_gettime(CLOCK_MONOTONIC, &after);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>>   timespecsub(&start, &after, &duration);
>>   timespecsub(&wait, &duration, &delta);
>>   if (delta.tv_sec < 0 || !timespecisset(&delta))
>> diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c
>> index 68d01674410..92e1d5c350d 100644
>> --- lib/libc/rpc/clnt_udp.c
>> +++ lib/libc/rpc/clnt_udp.c
>> @@ -265,7 +265,7 @@ send_again:
>>   reply_msg.acpted_rply.ar_results.where = resultsp;
>>   reply_msg.acpted_rply.ar_results.proc = xresults;
>>  
>> - clock_gettime(CLOCK_MONOTONIC, &start);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>>   for (;;) {
>>   switch (ppoll(pfd, 1, &wait, NULL)) {
>>   case 0:
>> @@ -283,7 +283,7 @@ send_again:
>>   /* FALLTHROUGH */
>>   case -1:
>>   if (errno == EINTR) {
>> - clock_gettime(CLOCK_MONOTONIC, &after);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>>   timespecsub(&after, &start, &duration);
>>   timespecadd(&time_waited, &duration, &time_waited);
>>   if (timespeccmp(&time_waited, &timeout, <))
>> diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c
>> index f9d7a70938f..6c99db84359 100644
>> --- lib/libc/rpc/svc_tcp.c
>> +++ lib/libc/rpc/svc_tcp.c
>> @@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
>>   * A timeout is fatal for the connection.
>>   */
>>   delta = wait_per_try;
>> - clock_gettime(CLOCK_MONOTONIC, &start);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
>>   pfd[0].fd = sock;
>>   pfd[0].events = POLLIN;
>>   do {
>> @@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
>>   case -1:
>>   if (errno != EINTR)
>>   goto fatal_err;
>> - clock_gettime(CLOCK_MONOTONIC, &after);
>> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
>>   timespecsub(&after, &start, &duration);
>>   timespecsub(&wait_per_try, &duration, &delta);
>>   if (delta.tv_sec < 0 || !timespecisset(&delta))
>> diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc
>> index 34769576ced..d57418d81bf 100644
>> --- lib/libc/sys/Makefile.inc
>> +++ lib/libc/sys/Makefile.inc
>> @@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \
>>  
>>  # glue to offer userland wrappers for some syscalls
>>  SRCS+= posix_madvise.c pthread_sigmask.c \
>> - w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c
>> + w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \
>> + w_clock_gettime.c w_gettimeofday.c microtime.c
>>  
>>  # glue for compat with old syscall interfaces.
>>  SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c
>truncate.c \
>> @@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c
>w_pwrite.c w_pwritev.c
>>  ASM= __semctl.o __syscall.o __thrsigdivert.o \
>>   access.o acct.o adjfreq.o adjtime.o \
>>   bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \
>> - clock_getres.o clock_gettime.o clock_settime.o \
>> + clock_getres.o clock_settime.o \
>>   dup.o dup2.o dup3.o \
>>   execve.o \
>>   faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \
>> @@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \
>>   getgroups.o getitimer.o getpeername.o getpgid.o \
>>   getpriority.o getresgid.o getresuid.o \
>>   getrlimit.o getrusage.o getsid.o getsockname.o \
>> - getsockopt.o gettimeofday.o ioctl.o \
>> + getsockopt.o ioctl.o \
>>   kevent.o kill.o kqueue.o ktrace.o lchown.o \
>>   link.o linkat.o listen.o lstat.o madvise.o \
>>   minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
>> @@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po}
>>  SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so}
>>  DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do}
>>  
>> -HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o
>${CANCEL:=.o}
>> +HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o
>${CANCEL:=.o} \
>> + clock_gettime.o gettimeofday.o
>>  PHIDDEN=${HIDDEN:.o=.po}
>>  SHIDDEN=${HIDDEN:.o=.so}
>>  DHIDDEN=${HIDDEN:.o=.do}
>> diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c
>> new file mode 100644
>> index 00000000000..5191b5b2606
>> --- /dev/null
>> +++ lib/libc/sys/microtime.c
>> @@ -0,0 +1,181 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2000 Poul-Henning Kamp <[hidden email]>
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/types.h>
>> +#include <sys/atomic.h>
>> +#include <sys/timetc.h>
>> +
>> +#include <time.h>
>> +
>> +/*
>> + * Return the difference between the timehands' counter value now
>and what
>> + * was when we copied it to the timehands' offset_count.
>> + */
>> +static inline int
>> +tc_delta(struct timekeep *tk, u_int *delta)
>> +{
>> + uint tc;
>> +
>> + if (_tc_get_timecount(tk, &tc))
>> + return -1;
>> + *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
>> + return 0;
>> +}
>> +
>> +static inline void
>> +bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime
>*ct)
>> +{
>> + ct->sec = bt->sec;
>> + if (bt->frac > bt->frac + x)
>> + ct->sec++;
>> + ct->frac = bt->frac + x;
>> +}
>> +
>> +static inline void
>> +BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts)
>> +{
>> + ts->tv_sec = bt->sec;
>> + ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >>
>32)) >> 32);
>> +}
>> +
>> +static inline void
>> +BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv)
>> +{
>> + tv->tv_sec = bt->sec;
>> + tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >>
>32)) >> 32);
>> +}
>> +
>> +static int
>> +binuptime(struct bintime *bt, struct timekeep *tk)
>> +{
>> + u_int gen, delta;
>> +
>> + do {
>> + gen = tk->tk_generation;
>> + membar_consumer();
>> + *bt = tk->tk_offset;
>> + if (tc_delta(tk, &delta))
>> + return -1;
>> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
>> + membar_consumer();
>> + } while (gen == 0 || gen != tk->tk_generation);
>> +
>> + return 0;
>> +}
>> +
>> +static inline void
>> +bintimeadd(const struct bintime *bt, const struct bintime *ct,
>> +    struct bintime *dt)
>> +{
>> + dt->sec = bt->sec + ct->sec;
>> + if (bt->frac > bt->frac + ct->frac)
>> + dt->sec++;
>> + dt->frac = bt->frac + ct->frac;
>> +}
>> +
>> +static inline void
>> +bintimesub(const struct bintime *bt, const struct bintime *ct,
>> +    struct bintime *dt)
>> +{
>> + dt->sec = bt->sec - ct->sec;
>> + if (bt->frac < bt->frac - ct->frac)
>> + dt->sec--;
>> + dt->frac = bt->frac - ct->frac;
>> +}
>> +
>> +static int
>> +binruntime(struct bintime *bt, struct timekeep *tk)
>> +{
>> + u_int gen, delta;
>> +
>> + do {
>> + gen = tk->tk_generation;
>> + membar_consumer();
>> + if (tc_delta(tk, &delta))
>> + return -1;
>> + bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt);
>> + bintimesub(bt, &tk->tk_naptime, bt);
>> + membar_consumer();
>> + } while (gen == 0 || gen != tk->tk_generation);
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +bintime(struct bintime *bt, struct timekeep *tk)
>> +{
>> + u_int gen, delta;
>> +
>> + do {
>> + gen = tk->tk_generation;
>> + membar_consumer();
>> + *bt = tk->tk_offset;
>> + if (tc_delta(tk, &delta))
>> + return -1;
>> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
>> + bintimeadd(bt, &tk->tk_boottime, bt);
>> + membar_consumer();
>> + } while (gen == 0 || gen != tk->tk_generation);
>> +
>> + return 0;
>> +}
>> +
>> +int
>> +_microtime(struct timeval *tvp, struct timekeep *tk)
>> +{
>> + struct bintime bt;
>> +
>> + if (bintime(&bt, tk))
>> + return -1;
>> + BINTIME_TO_TIMEVAL(&bt, tvp);
>> + return 0;
>> +}
>> +
>> +int
>> +_nanotime(struct timespec *tsp, struct timekeep *tk)
>> +{
>> + struct bintime bt;
>> +
>> + if (bintime(&bt, tk))
>> + return -1;
>> + BINTIME_TO_TIMESPEC(&bt, tsp);
>> + return 0;
>> +}
>> +
>> +int
>> +_nanoruntime(struct timespec *ts, struct timekeep *tk)
>> +{
>> + struct bintime bt;
>> +
>> + if (binruntime(&bt, tk))
>> + return -1;
>> + BINTIME_TO_TIMESPEC(&bt, ts);
>> + return 0;
>> +}
>> +
>> +
>> +int
>> +_nanouptime(struct timespec *tsp, struct timekeep *tk)
>> +{
>> + struct bintime bt;
>> +
>> + if (binuptime(&bt, tk))
>> + return -1;
>> + BINTIME_TO_TIMESPEC(&bt, tsp);
>> + return 0;
>> +}
>> diff --git lib/libc/sys/w_clock_gettime.c
>lib/libc/sys/w_clock_gettime.c
>> new file mode 100644
>> index 00000000000..6e6478bd131
>> --- /dev/null
>> +++ lib/libc/sys/w_clock_gettime.c
>> @@ -0,0 +1,51 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/timetc.h>
>> +
>> +#include <time.h>
>> +
>> +int
>> +WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp)
>> +{
>> + int rc = 0;
>> + struct timekeep *timekeep = _timekeep;
>> +
>> + if (timekeep == NULL || timekeep->tk_user == 0)
>> + return clock_gettime(clock_id, tp);
>> +
>> + switch (clock_id) {
>> + case CLOCK_REALTIME:
>> + rc = _nanotime(tp, timekeep);
>> + break;
>> + case CLOCK_UPTIME:
>> + rc = _nanoruntime(tp, timekeep);
>> + break;
>> + case CLOCK_MONOTONIC:
>> + case CLOCK_BOOTTIME:
>> + rc = _nanouptime(tp, timekeep);
>> + break;
>> + default:
>> + return clock_gettime(clock_id, tp);
>> + }
>> +
>> + if (rc)
>> + return clock_gettime(clock_id, tp);
>> +
>> + return 0;
>> +}
>> +DEF_WRAP(clock_gettime);
>> diff --git lib/libc/sys/w_gettimeofday.c
>lib/libc/sys/w_gettimeofday.c
>> new file mode 100644
>> index 00000000000..f44edfbb1ad
>> --- /dev/null
>> +++ lib/libc/sys/w_gettimeofday.c
>> @@ -0,0 +1,40 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Robert Nagy <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/timetc.h>
>> +
>> +int
>> +WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp)
>> +{
>> + int rc = 0;
>> + struct timekeep *timekeep = _timekeep;
>> + static struct timezone zerotz = { 0, 0 };
>> +
>> + if (timekeep == NULL || timekeep->tk_user == 0)
>> + return gettimeofday(tp, tzp);
>> +
>> + if (tp)
>> + rc = _microtime(tp, timekeep);
>> + if (rc)
>> + return gettimeofday(tp, tzp);
>> +
>> + if (tzp)
>> + *tzp = zerotz;
>> +
>> + return 0;
>> +}
>> +DEF_WRAP(gettimeofday);
>> diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h
>> index 788890add89..df2239438d2 100644
>> --- lib/libc/thread/synch.h
>> +++ lib/libc/thread/synch.h
>> @@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t
>clockid, const struct timespec *
>>   if (abs == NULL)
>>   return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
>>  
>> - if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
>> + if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid,
>&rel))
>>   return (EINVAL);
>>  
>>   rel.tv_sec = abs->tv_sec - rel.tv_sec;
>> diff --git regress/lib/libc/timekeep/Makefile
>regress/lib/libc/timekeep/Makefile
>> new file mode 100644
>> index 00000000000..a7f3080290d
>> --- /dev/null
>> +++ regress/lib/libc/timekeep/Makefile
>> @@ -0,0 +1,5 @@
>> +# $OpenBSD$
>> +
>> +PROGS= test_clock_gettime test_time_skew test_gettimeofday
>> +
>> +.include <bsd.regress.mk>
>> diff --git regress/lib/libc/timekeep/test_clock_gettime.c
>regress/lib/libc/timekeep/test_clock_gettime.c
>> new file mode 100644
>> index 00000000000..859ec368215
>> --- /dev/null
>> +++ regress/lib/libc/timekeep/test_clock_gettime.c
>> @@ -0,0 +1,43 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <assert.h>
>> +#include <time.h>
>> +
>> +#define ASSERT_EQ(a, b) assert((a) == (b))
>> +
>> +void
>> +check()
>> +{
>> + struct timespec tp = {0};
>> +
>> + ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp));
>> + ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp));
>> + ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp));
>> + ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp));
>> +
>> +
>> + ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp));
>> + ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp));
>> +
>> +}
>> +
>> +int main()
>> +{
>> + check();
>> + return 0;
>> +}
>> diff --git regress/lib/libc/timekeep/test_gettimeofday.c
>regress/lib/libc/timekeep/test_gettimeofday.c
>> new file mode 100644
>> index 00000000000..ea90a1be7e0
>> --- /dev/null
>> +++ regress/lib/libc/timekeep/test_gettimeofday.c
>> @@ -0,0 +1,37 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <assert.h>
>> +#include <sys/time.h>
>> +
>> +#define ASSERT_EQ(a, b) assert((a) == (b))
>> +
>> +void
>> +check()
>> +{
>> + struct timeval tv = {0};
>> + struct timezone tzp;
>> +
>> + ASSERT_EQ(0, gettimeofday(&tv, NULL));
>> + ASSERT_EQ(0, gettimeofday(&tv, &tzp));
>> +}
>> +
>> +int main()
>> +{
>> + check();
>> + return 0;
>> +}
>> diff --git regress/lib/libc/timekeep/test_time_skew.c
>regress/lib/libc/timekeep/test_time_skew.c
>> new file mode 100644
>> index 00000000000..dfa9481c091
>> --- /dev/null
>> +++ regress/lib/libc/timekeep/test_time_skew.c
>> @@ -0,0 +1,55 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#include <sys/time.h>
>> +
>> +#include <assert.h>
>> +#include <time.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +
>> +#define ASSERT_EQ(a, b) assert((a) == (b))
>> +#define ASSERT_NE(a, b) assert((a) != (b))
>> +
>> +void
>> +check()
>> +{
>> +         struct timespec tp1, tp2, tout;
>> +
>> +         tout.tv_sec = 0;
>> +         tout.tv_nsec = 100000;
>> +
>> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1));
>> +
>> +         nanosleep(&tout, NULL);
>> +
>> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2));
>> +
>> +         /* tp1 should never be larger than tp2 */
>> +         ASSERT_NE(1, timespeccmp(&tp1, &tp2, >));
>> +}
>> +
>> +int
>> +main(void)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < 1000; i++)
>> + check();
>> +
>> + return 0;
>> +}
>> diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c
>> index 3f5f2c5b42b..6eaf8b107c6 100644
>> --- sys/arch/alpha/alpha/clock.c
>> +++ sys/arch/alpha/alpha/clock.c
>> @@ -64,7 +64,7 @@ int clk_irq = 0;
>>  
>>  u_int rpcc_get_timecount(struct timecounter *);
>>  struct timecounter rpcc_timecounter = {
>> - rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
>> + rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0
>>  };
>>  
>>  extern todr_chip_handle_t todr_handle;
>> diff --git sys/arch/alpha/include/timetc.h
>sys/arch/alpha/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/alpha/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c
>> index 7a1dcb4ad75..5839fa15d6c 100644
>> --- sys/arch/amd64/amd64/tsc.c
>> +++ sys/arch/amd64/amd64/tsc.c
>> @@ -42,7 +42,7 @@ int64_t tsc_drift_observed;
>>  volatile int64_t tsc_sync_val;
>>  volatile struct cpu_info *tsc_sync_cpu;
>>  
>> -uint tsc_get_timecount(struct timecounter *tc);
>> +u_int tsc_get_timecount(struct timecounter *tc);
>>  
>>  #include "lapic.h"
>>  #if NLAPIC > 0
>> @@ -50,7 +50,7 @@ extern u_int32_t lapic_per_second;
>>  #endif
>>  
>>  struct timecounter tsc_timecounter = {
>> - tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL
>> + tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, TC_TSC
>>  };
>>  
>>  uint64_t
>> @@ -244,6 +244,7 @@ tsc_timecounter_init(struct cpu_info *ci,
>uint64_t cpufreq)
>>   printf("ERROR: %lld cycle TSC drift observed\n",
>>      (long long)tsc_drift_observed);
>>   tsc_timecounter.tc_quality = -1000;
>> + tsc_timecounter.tc_user = 0;
>>   tsc_is_invariant = 0;
>>   }
>>  
>> diff --git sys/arch/amd64/include/timetc.h
>sys/arch/amd64/include/timetc.h
>> new file mode 100644
>> index 00000000000..c2d40bcd1e7
>> --- /dev/null
>> +++ sys/arch/amd64/include/timetc.h
>> @@ -0,0 +1,24 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_TSC 1
>> +#define TC_LAST 2
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c
>> index 613f7ee0e0f..00da0c6a8d0 100644
>> --- sys/arch/amd64/isa/clock.c
>> +++ sys/arch/amd64/isa/clock.c
>> @@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter
>*tc);
>>  u_int i8254_simple_get_timecount(struct timecounter *tc);
>>  
>>  static struct timecounter i8254_timecounter = {
>> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
>> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
>>  };
>>  
>>  int clockintr(void *);
>> diff --git sys/arch/arm/include/timetc.h
>sys/arch/arm/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/arm/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c
>> index 11196b5c60d..1a2106ef94c 100644
>> --- sys/arch/arm64/dev/agtimer.c
>> +++ sys/arch/arm64/dev/agtimer.c
>> @@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY;
>>  u_int agtimer_get_timecount(struct timecounter *);
>>  
>>  static struct timecounter agtimer_timecounter = {
>> - agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL
>> + agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0
>>  };
>>  
>>  struct agtimer_pcpu_softc {
>> diff --git sys/arch/arm64/include/timetc.h
>sys/arch/arm64/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/arm64/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/armv7/include/timetc.h
>sys/arch/armv7/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/armv7/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/armv7/omap/gptimer.c
>sys/arch/armv7/omap/gptimer.c
>> index 7605845d5e2..061542d532f 100644
>> --- sys/arch/armv7/omap/gptimer.c
>> +++ sys/arch/armv7/omap/gptimer.c
>> @@ -117,7 +117,7 @@ int gptimer_irq = 0;
>>  u_int gptimer_get_timecount(struct timecounter *);
>>  
>>  static struct timecounter gptimer_timecounter = {
>> - gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
>> + gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0
>>  };
>>  
>>  volatile u_int32_t nexttickevent;
>> diff --git sys/arch/armv7/sunxi/sxitimer.c
>sys/arch/armv7/sunxi/sxitimer.c
>> index 14a243c78d0..41028f9a602 100644
>> --- sys/arch/armv7/sunxi/sxitimer.c
>> +++ sys/arch/armv7/sunxi/sxitimer.c
>> @@ -89,7 +89,7 @@ void sxitimer_delay(u_int);
>>  u_int sxitimer_get_timecount(struct timecounter *);
>>  
>>  static struct timecounter sxitimer_timecounter = {
>> - sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL
>> + sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0
>>  };
>>  
>>  bus_space_tag_t sxitimer_iot;
>> diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c
>> index 4c594ab5ec7..8cce6c3a893 100644
>> --- sys/arch/hppa/dev/clock.c
>> +++ sys/arch/hppa/dev/clock.c
>> @@ -47,7 +47,7 @@ int cpu_hardclock(void *);
>>  u_int itmr_get_timecount(struct timecounter *);
>>  
>>  struct timecounter itmr_timecounter = {
>> - itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
>> + itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0
>>  };
>>  
>>  extern todr_chip_handle_t todr_handle;
>> diff --git sys/arch/hppa/include/timetc.h
>sys/arch/hppa/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/hppa/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/i386/include/timetc.h
>sys/arch/i386/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/i386/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c
>> index 09a6db983f2..dd74bd425ad 100644
>> --- sys/arch/i386/isa/clock.c
>> +++ sys/arch/i386/isa/clock.c
>> @@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter
>*tc);
>>  u_int i8254_simple_get_timecount(struct timecounter *tc);
>>  
>>  static struct timecounter i8254_timecounter = {
>> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
>> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
>>  };
>>  struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
>>  u_long rtclock_tval;
>> diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
>> index 9d9f061eef9..bb8e4c7f9ae 100644
>> --- sys/arch/i386/pci/geodesc.c
>> +++ sys/arch/i386/pci/geodesc.c
>> @@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = {
>>   0xffffffff, /* counter_mask */
>>   27000000, /* frequency */
>>   "GEOTSC", /* name */
>> - 2000 /* quality */
>> + 2000, /* quality */
>> + NULL, /* private bits */
>> + 0 /* expose to user */
>>  };
>>  
>>  int
>> diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c
>> index 8b8aa4ac430..a6f324e66f3 100644
>> --- sys/arch/i386/pci/gscpm.c
>> +++ sys/arch/i386/pci/gscpm.c
>> @@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = {
>>   0xffffff, /* counter_mask */
>>   3579545, /* frequency */
>>   "GSCPM", /* name */
>> - 1000 /* quality */
>> + 1000, /* quality */
>> + NULL, /* private bits */
>> + 0 /* expose to user */
>>  };
>>  
>>  struct cfattach gscpm_ca = {
>> diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c
>> index 6abf1627de2..629a86a14ff 100644
>> --- sys/arch/i386/pci/ichpcib.c
>> +++ sys/arch/i386/pci/ichpcib.c
>> @@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = {
>>   0xffffff, /* counter_mask */
>>   3579545, /* frequency */
>>   "ICHPM", /* name */
>> - 1000 /* quality */
>> + 1000, /* quality */
>> + NULL, /* private bits */
>> + 0 /* expose to user */
>>  };
>>  
>>  struct cfattach ichpcib_ca = {
>> diff --git sys/arch/landisk/include/timetc.h
>sys/arch/landisk/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/landisk/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/loongson/include/timetc.h
>sys/arch/loongson/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/loongson/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/loongson/loongson/generic3a_machdep.c
>sys/arch/loongson/loongson/generic3a_machdep.c
>> index ac3f1db6ccd..53489b07549 100644
>> --- sys/arch/loongson/loongson/generic3a_machdep.c
>> +++ sys/arch/loongson/loongson/generic3a_machdep.c
>> @@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = {
>>   .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */
>>   .tc_frequency = HPET_FREQ,
>>   .tc_name = "hpet",
>> - .tc_quality = 100
>> + .tc_quality = 100,
>> + .tc_priv = NULL,
>> + .tc_user = 0,
>>  };
>>  
>>  /* Firmware entry points */
>> diff --git sys/arch/luna88k/include/timetc.h
>sys/arch/luna88k/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/luna88k/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/luna88k/luna88k/clock.c
>sys/arch/luna88k/luna88k/clock.c
>> index a04120987e0..6580a4a46bf 100644
>> --- sys/arch/luna88k/luna88k/clock.c
>> +++ sys/arch/luna88k/luna88k/clock.c
>> @@ -112,7 +112,9 @@ struct timecounter clock_tc = {
>>   .tc_counter_mask = 0xffffffff,
>>   .tc_frequency = 0, /* will be filled in */
>>   .tc_name = "clock",
>> - .tc_quality = 0
>> + .tc_quality = 0,
>> + .tc_priv = NULL,
>> + .tc_user = 0,
>>  };
>>  
>>  /*
>> diff --git sys/arch/m88k/include/timetc.h
>sys/arch/m88k/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/m88k/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/macppc/include/timetc.h
>sys/arch/macppc/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/macppc/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/macppc/macppc/clock.c
>sys/arch/macppc/macppc/clock.c
>> index 4a44a92cfc0..8c3ad620be8 100644
>> --- sys/arch/macppc/macppc/clock.c
>> +++ sys/arch/macppc/macppc/clock.c
>> @@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320;
>>  static int32_t ticks_per_intr;
>>  
>>  static struct timecounter tb_timecounter = {
>> - tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
>> + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0
>>  };
>>  
>>  /* calibrate the timecounter frequency for the listed models */
>> diff --git sys/arch/mips64/include/timetc.h
>sys/arch/mips64/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/mips64/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/mips64/mips64/mips64_machdep.c
>sys/arch/mips64/mips64/mips64_machdep.c
>> index d4a42ed5acc..5c4dbadb5bb 100644
>> --- sys/arch/mips64/mips64/mips64_machdep.c
>> +++ sys/arch/mips64/mips64/mips64_machdep.c
>> @@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = {
>>   0xffffffff, /* counter_mask */
>>   0, /* frequency */
>>   "CP0", /* name */
>> - 0 /* quality */
>> + 0, /* quality */
>> + NULL, /* private bits */
>> + 0, /* expose to user */
>>  };
>>  
>>  u_int
>> diff --git sys/arch/octeon/include/timetc.h
>sys/arch/octeon/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/octeon/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/octeon/octeon/machdep.c
>sys/arch/octeon/octeon/machdep.c
>> index 902e462d53f..d8377653abe 100644
>> --- sys/arch/octeon/octeon/machdep.c
>> +++ sys/arch/octeon/octeon/machdep.c
>> @@ -151,8 +151,9 @@ struct timecounter ioclock_timecounter = {
>>   .tc_name = "ioclock",
>>   .tc_quality = 0, /* ioclock can be overridden
>>   * by cp0 counter */
>> - .tc_priv = 0 /* clock register,
>> + .tc_priv = 0, /* clock register,
>>   * determined at runtime */
>> + .tc_user = 0, /* expose to user */
>>  };
>>  
>>  static int
>> diff --git sys/arch/powerpc/include/timetc.h
>sys/arch/powerpc/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/powerpc/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/powerpc64/include/timetc.h
>sys/arch/powerpc64/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/powerpc64/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/sgi/include/timetc.h
>sys/arch/sgi/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/sgi/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/sgi/sgi/ip27_machdep.c
>sys/arch/sgi/sgi/ip27_machdep.c
>> index ba7fa558b96..2a2cc144242 100644
>> --- sys/arch/sgi/sgi/ip27_machdep.c
>> +++ sys/arch/sgi/sgi/ip27_machdep.c
>> @@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = {
>>   .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */
>>   .tc_frequency = 1250000,
>>   .tc_name = "hubrt",
>> - .tc_quality = 100
>> + .tc_quality = 100,
>> + .tc_priv = 0,
>> + .tc_user = 0,
>>  };
>>  
>>  volatile uint64_t ip27_spinup_a0;
>> diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c
>> index 56b29915c70..827775512ac 100644
>> --- sys/arch/sgi/xbow/xheart.c
>> +++ sys/arch/sgi/xbow/xheart.c
>> @@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = {
>>   .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit
>*/
>>   .tc_frequency = 12500000,
>>   .tc_name = "heart",
>> - .tc_quality = 100
>> + .tc_quality = 100,
>> + .tc_priv = NULL,
>> + .tc_user = 0,
>>  };
>>  
>>  extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *);
>> diff --git sys/arch/sh/include/timetc.h sys/arch/sh/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/sh/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/sparc64/dev/psycho.c
>sys/arch/sparc64/dev/psycho.c
>> index e24f804dff6..1a7a1afa8c2 100644
>> --- sys/arch/sparc64/dev/psycho.c
>> +++ sys/arch/sparc64/dev/psycho.c
>> @@ -127,7 +127,7 @@ extern struct sparc_pci_chipset
>_sparc_pci_chipset;
>>  u_int stick_get_timecount(struct timecounter *);
>>  
>>  struct timecounter stick_timecounter = {
>> - stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
>> + stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0
>>  };
>>  
>>  /*
>> diff --git sys/arch/sparc64/include/timetc.h
>sys/arch/sparc64/include/timetc.h
>> new file mode 100644
>> index 00000000000..e58a7fb4faa
>> --- /dev/null
>> +++ sys/arch/sparc64/include/timetc.h
>> @@ -0,0 +1,23 @@
>> +/* $OpenBSD$ */
>> +/*
>> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> + *
>> + * Permission to use, copy, modify, and distribute this software for
>any
>> + * purpose with or without fee is hereby granted, provided that the
>above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
>IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
>OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef _MACHINE_TIMETC_H_
>> +#define _MACHINE_TIMETC_H_
>> +
>> +#define TC_LAST 0
>> +
>> +#endif /* _MACHINE_TIMETC_H_ */
>> diff --git sys/arch/sparc64/sparc64/clock.c
>sys/arch/sparc64/sparc64/clock.c
>> index fd5e8a9c15b..5c2e47d386b 100644
>> --- sys/arch/sparc64/sparc64/clock.c
>> +++ sys/arch/sparc64/sparc64/clock.c
>> @@ -109,13 +109,13 @@ struct cfdriver clock_cd = {
>>  u_int tick_get_timecount(struct timecounter *);
>>  
>>  struct timecounter tick_timecounter = {
>> - tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL
>> + tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0
>>  };
>>  
>>  u_int sys_tick_get_timecount(struct timecounter *);
>>  
>>  struct timecounter sys_tick_timecounter = {
>> - sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL
>> + sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0
>>  };
>>  
>>  /*
>> diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c
>> index d0ee72cec9b..13177a909da 100644
>> --- sys/dev/acpi/acpihpet.c
>> +++ sys/dev/acpi/acpihpet.c
>> @@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = {
>>   0xffffffff, /* counter_mask (32 bits) */
>>   0, /* frequency */
>>   0, /* name */
>> - 1000 /* quality */
>> + 1000, /* quality */
>> + NULL, /* private bits */
>> + 0, /* expose to user */
>>  };
>>  
>>  #define HPET_TIMERS 3
>> diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c
>> index cdc8c99a17a..89b5a397e47 100644
>> --- sys/dev/acpi/acpitimer.c
>> +++ sys/dev/acpi/acpitimer.c
>> @@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = {
>>   0x00ffffff, /* counter_mask (24 bits) */
>>   ACPI_FREQUENCY, /* frequency */
>>   0, /* name */
>> - 1000 /* quality */
>> + 1000, /* quality */
>> + NULL, /* private bits */
>> + 0, /* expose to user */
>>  };
>>  
>>  struct acpitimer_softc {
>> diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c
>> index 6df82858016..9610d5bc1f0 100644
>> --- sys/dev/pci/amdpm.c
>> +++ sys/dev/pci/amdpm.c
>> @@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = {
>>   0xffffff, /* counter_mask */
>>   AMDPM_FREQUENCY, /* frequency */
>>   "AMDPM", /* name */
>> - 1000 /* quality */
>> + 1000, /* quality */
>> + NULL, /* private bits */
>> + 0, /* expose to user */
>>  };
>>  
>>  #define AMDPM_CONFREG 0x40
>> diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c
>> index db806eedf80..ce33cd175e6 100644
>> --- sys/dev/pci/viapm.c
>> +++ sys/dev/pci/viapm.c
>> @@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = {
>>   0xffffff, /* counter_mask */
>>   VIAPM_FREQUENCY, /* frequency */
>>   "VIAPM", /* name */
>> - 1000 /* quality */
>> + 1000, /* quality */
>> + NULL, /* private bits */
>> + 0, /* expose to user */
>>  };
>>  
>>  struct timeout viapm_timeout;
>> diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c
>> index b32facdacb1..b9ee2feec4c 100644
>> --- sys/dev/pv/hyperv.c
>> +++ sys/dev/pv/hyperv.c
>> @@ -141,7 +141,7 @@ struct {
>>  };
>>  
>>  struct timecounter hv_timecounter = {
>> - hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001
>> + hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0
>>  };
>>  
>>  struct cfdriver hyperv_cd = {
>> diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c
>> index 6b242f7448d..b80e4d2a484 100644
>> --- sys/dev/pv/pvclock.c
>> +++ sys/dev/pv/pvclock.c
>> @@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = {
>>  };
>>  
>>  struct timecounter pvclock_timecounter = {
>> - pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL
>> + pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0
>>  };
>>  
>>  int
>> diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c
>> index 9b5b8eb3acf..59bc923a6fb 100644
>> --- sys/kern/exec_elf.c
>> +++ sys/kern/exec_elf.c
>> @@ -124,7 +124,7 @@ extern char *syscallnames[];
>>  /*
>>   * How many entries are in the AuxInfo array we pass to the process?
>>   */
>> -#define ELF_AUX_ENTRIES 8
>> +#define ELF_AUX_ENTRIES 9
>>  
>>  /*
>>   * This is the OpenBSD ELF emul
>> @@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct
>exec_package *epp)
>>   a->au_v = ap->arg_entry;
>>   a++;
>>  
>> + a->au_id = AUX_openbsd_timekeep;
>> + a->au_v = p->p_p->ps_timekeep;
>> + a++;
>> +
>>   a->au_id = AUX_null;
>>   a->au_v = 0;
>>   a++;
>> diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
>> index 20480c2fc28..222450607d5 100644
>> --- sys/kern/kern_exec.c
>> +++ sys/kern/kern_exec.c
>> @@ -64,6 +64,11 @@
>>  #include <uvm/uvm_extern.h>
>>  #include <machine/tcb.h>
>>  
>> +#include <sys/timetc.h>
>> +
>> +struct uvm_object *timekeep_object;
>> +struct timekeep* timekeep;
>> +
>>  void unveil_destroy(struct process *ps);
>>  
>>  const struct kmem_va_mode kv_exec = {
>> @@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = {
>>   */
>>  int exec_sigcode_map(struct process *, struct emul *);
>>  
>> +/*
>> + * Map the shared timekeep page.
>> + */
>> +int exec_timekeep_map(struct process *);
>> +
>>  /*
>>   * If non-zero, stackgap_random specifies the upper limit of the
>random gap size
>>   * added to the fixed stack position. Must be n^2.
>> @@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t
>*retval)
>>   /* map the process's signal trampoline code */
>>   if (exec_sigcode_map(pr, pack.ep_emul))
>>   goto free_pack_abort;
>> + /* map the process's timekeep page */
>> + if (exec_timekeep_map(pr))
>> + goto free_pack_abort;
>>  
>>  #ifdef __HAVE_EXEC_MD_MAP
>>   /* perform md specific mappings that process might need */
>> @@ -863,3 +876,40 @@ exec_sigcode_map(struct process *pr, struct emul
>*e)
>>  
>>   return (0);
>>  }
>> +
>> +int
>> +exec_timekeep_map(struct process *pr)
>> +{
>> + size_t timekeep_sz = sizeof(struct timekeep);
>> +
>> + /*
>> + * Similar to the sigcode object, except that there is a single
>> + * timekeep object, and not one per emulation.
>> + */
>> + if (timekeep_object == NULL) {
>> + vaddr_t va;
>> +
>> + timekeep_object = uao_create(timekeep_sz, 0);
>> + uao_reference(timekeep_object);
>> +
>> + if (uvm_map(kernel_map, &va, round_page(timekeep_sz),
>timekeep_object,
>> +    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ |
>PROT_WRITE,
>> +    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
>> + uao_detach(timekeep_object);
>> + return (ENOMEM);
>> + }
>> +
>> + timekeep = (struct timekeep *)va;
>> + timekeep->tk_version = TK_VERSION;
>> + }
>> +
>> + uao_reference(timekeep_object);
>> + if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep,
>round_page(timekeep_sz),
>> +    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
>> +    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
>> + uao_detach(timekeep_object);
>> + return (ENOMEM);
>> + }
>> +
>> + return (0);
>> +}
>> diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
>> index 88d4a3379f9..47efbdd0b78 100644
>> --- sys/kern/kern_tc.c
>> +++ sys/kern/kern_tc.c
>> @@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc)
>>  }
>>  
>>  static struct timecounter dummy_timecounter = {
>> - dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
>> + dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0
>>  };
>>  
>>  /*
>> @@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts)
>>  #endif
>>  }
>>  
>> +void
>> +tc_update_timekeep(void)
>> +{
>> + static struct timecounter *last_tc = NULL;
>> + struct timehands *th;
>> +
>> + if (timekeep == NULL)
>> + return;
>> +
>> + th = timehands;
>> + timekeep->tk_generation = 0;
>> + membar_producer();
>> + timekeep->tk_scale = th->th_scale;
>> + timekeep->tk_offset_count = th->th_offset_count;
>> + timekeep->tk_offset = th->th_offset;
>> + timekeep->tk_naptime = th->th_naptime;
>> + timekeep->tk_boottime = th->th_boottime;
>> + if (last_tc != th->th_counter) {
>> + timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
>> + timekeep->tk_user = th->th_counter->tc_user;
>> + last_tc = th->th_counter;
>> + }
>> + membar_producer();
>> + timekeep->tk_generation = th->th_generation;
>> +
>> + return;
>> +}
>> +
>>  /*
>>   * Initialize the next struct timehands in the ring and make
>>   * it the active timehands.  Along the way we might switch to a
>different
>> @@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct
>bintime *new_offset,
>>   time_uptime = th->th_offset.sec;
>>   membar_producer();
>>   timehands = th;
>> +
>> + tc_update_timekeep();
>>  }
>>  
>>  /* Report or change the active timecounter hardware. */
>> diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h
>> index a40e0510273..3084ed595a6 100644
>> --- sys/sys/exec_elf.h
>> +++ sys/sys/exec_elf.h
>> @@ -691,7 +691,8 @@ enum AuxID {
>>   AUX_sun_uid = 2000, /* euid */
>>   AUX_sun_ruid = 2001, /* ruid */
>>   AUX_sun_gid = 2002, /* egid */
>> - AUX_sun_rgid = 2003 /* rgid */
>> + AUX_sun_rgid = 2003, /* rgid */
>> + AUX_openbsd_timekeep = 4000, /* userland clock_gettime */
>>  };
>>  
>>  struct elf_args {
>> diff --git sys/sys/proc.h sys/sys/proc.h
>> index 357c0c0d52c..c6d54572bdd 100644
>> --- sys/sys/proc.h
>> +++ sys/sys/proc.h
>> @@ -242,6 +242,7 @@ struct process {
>>   char ps_comm[MAXCOMLEN+1];
>>  
>>   vaddr_t ps_strings; /* User pointers to argv/env */
>> + vaddr_t ps_timekeep; /* User pointer to timekeep */
>>   vaddr_t ps_sigcode; /* User pointer to the signal code */
>>   vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */
>>   u_long ps_sigcookie;
>> diff --git sys/sys/time.h sys/sys/time.h
>> index e758a64ce07..bcd3acd034d 100644
>> --- sys/sys/time.h
>> +++ sys/sys/time.h
>> @@ -163,7 +163,7 @@ struct clockinfo {
>>  };
>>  #endif /* __BSD_VISIBLE */
>>  
>> -#if defined(_KERNEL) || defined(_STANDALONE)
>> +#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC)
>>  #include <sys/_time.h>
>>  
>>  /* Time expressed as seconds and fractions of a second + operations
>on it. */
>> @@ -171,6 +171,9 @@ struct bintime {
>>   time_t sec;
>>   uint64_t frac;
>>  };
>> +#endif
>> +
>> +#if defined(_KERNEL) || defined(_STANDALONE)
>>  
>>  #define bintimecmp(btp, ctp, cmp) \
>>   ((btp)->sec == (ctp)->sec ? \
>> diff --git sys/sys/timetc.h sys/sys/timetc.h
>> index ce81c3475a0..c5ad27695ba 100644
>> --- sys/sys/timetc.h
>> +++ sys/sys/timetc.h
>> @@ -24,10 +24,11 @@
>>  #ifndef _SYS_TIMETC_H_
>>  #define _SYS_TIMETC_H_
>>  
>> -#ifndef _KERNEL
>> +#if !defined(_KERNEL) && !defined(_LIBC)
>>  #error "no user-serviceable parts inside"
>>  #endif
>>  
>> +#include <machine/timetc.h>
>>  #include <sys/queue.h>
>>  
>>  /*-
>> @@ -80,6 +81,8 @@ struct timecounter {
>>   */
>>   void *tc_priv; /* [I] */
>>   /* Pointer to the timecounter's private parts. */
>> + int tc_user; /* [I] */
>> + /* Expose this timecounter to userland. */
>>   SLIST_ENTRY(timecounter) tc_next; /* [I] */
>>   /* Pointer to the next timecounter. */
>>   int64_t tc_freq_adj; /* [tw] */
>> @@ -88,11 +91,32 @@ struct timecounter {
>>   /* Precision of the counter.  Computed in tc_init(). */
>>  };
>>  
>> +struct timekeep {
>> + /* set at initialization */
>> + uint32_t tk_version; /* version number */
>> +
>> + /* timehands members */
>> + uint64_t tk_scale;
>> + u_int tk_offset_count;
>> + struct bintime tk_offset;
>> + struct bintime tk_naptime;
>> + struct bintime tk_boottime;
>> + volatile u_int tk_generation;
>> +
>> + /* timecounter members */
>> + int tk_user;
>> + u_int tk_counter_mask;
>> +};
>> +#define TK_VERSION 0
>> +
>>  struct rwlock;
>>  extern struct rwlock tc_lock;
>>  
>>  extern struct timecounter *timecounter;
>>  
>> +extern struct uvm_object *timekeep_object;
>> +extern struct timekeep *timekeep;
>> +
>>  u_int64_t tc_getfrequency(void);
>>  u_int64_t tc_getprecision(void);
>>  void tc_init(struct timecounter *tc);
>>

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Mark Kettenis
> Date: Fri, 19 Jun 2020 23:16:26 +0300
> From: Paul Irofti <[hidden email]>
>
> În 19 iunie 2020 22:49:32 EEST, Mark Kettenis <[hidden email]> a scris:
> >> Date: Fri, 19 Jun 2020 20:28:58 +0300
> >> From: Paul Irofti <[hidden email]>
> >>
> >> On Fri, Jun 19, 2020 at 06:52:40PM +0200, Mark Kettenis wrote:
> >> > > Date: Fri, 19 Jun 2020 14:31:17 +0300
> >> > > From: Paul Irofti <[hidden email]>
> >> > >
> >> > > Hi,
> >> > >
> >> > > Here is another iteration of the diff that addresses all issues
> >raised
> >> > > in the meantime:
> >> > >
> >> > >   - Switch tc to uint
> >> >
> >> > The request was to use u_int, like we de in the kernel.  The uint
> >type
> >> > should not be used in OpenBSD code.
> >> >
> >> > >   - Check for version at init and switch to machite/timetc.h defs
> >> > >   - Remove tk_nclocks
> >> > >   - Switch to single version and ditch minor/major
> >> > >   - Do not enable user TSC for large skew values
> >> > >   - Add amd64 clocks and use the define in TSC
> >> > >   - Include and add machine/timetc.h
> >> > >
> >> > > As we have seen most architectures have support for clocks now
> >and the
> >> > > above addresses Mark's last concerns.
> >> > >
> >> > > Unless other blocking issues arise, this time around I am looking
> >for
> >> > > OKs to commit. Theo? Mark?
> >> >
> >> > There is one other issue that I wanted to raise.  An that is
> >whether
> >> > we really need to implement CLOCK_UPTINME as a userland clock.  If
> >we
> >> > don't do that we can drop tk_naptime from the shared struct.  I
> >> > mention this because th_naptime was only recently added to struct
> >> > timehands and much more an implementation detail than the other
> >fields.
> >> >
> >> > I don't expect userland processes to call CLOCK_UPTIME in a loop
> >like
> >> > they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
> >> > doesn't have it ;).
> >>
> >> I don't care eitherway about this. But I don't see why we would not
> >have
> >> this functionality if it is easy to offer. Maybe someone can help us
> >> grep the ports tree for this? Stuart? :)
> >>
> >> > We're getting there...
> >>
> >> I have addressed your comments bellow, except for the CPU skew one.
> >That
> >> code disables TSC for all CPUs, not just for PRIMARY. Would you like
> >to
> >> walk and add code for every CPU to check the drift and then disable
> >the
> >> TSC? It seems a little too much...
> >
> >Still uses uint instead of u_int in places.
>
> Ok. I will check that again.
>
> > Still has the pointless
> >extra NULL and 0 for timecounters in files that are otherwise
>
> I am not fixing that. If there's a null present before my diff, then
> there can be a 0 afterwards. If anything my diff unifies this. This
> is silly.

I'll let others judge that.

> >And regarding the TSC.  That issue is a show-stopper.  We can tolerate
> >a small amout of skew, but not a large amount.  Because otherwise a
> >multithreaded process might observe time going backwards.
>
> I don't see how this is still an issue with my diff, which is what I
> said last time. I am stopping the TSC when the drift is larger than
> a random value that I defined a year ago. What more is needed? Can
> you describe in more details?

I'm talking about *skew*, not drift.  If there is a significant drift
you already knock out the TSC.

What's needed is:

1. A bit of research of what an acceptable skew is.  My hypothesis is
   that on many machines with a single socket the TSCs are actually in
   synch.  But the way we measure the skew isn't 100% accurate so we
   still get a small skew.  If we sample these values on a couple of
   machines across a couple of reboots we can probably tell what the
   uncertainty in the measurement of the skew is and define a cutoff
   based on that.

2. When the absolute value of ci->ci_tsc_skew is above this cutoff for
   any CPU, you set tsc_timecounter.tc_user to zero.  I think you can
   do that check in tsc_timecounter_init() but I'm not 100% sure.



> >> diff --git lib/libc/arch/aarch64/gen/Makefile.inc
> >lib/libc/arch/aarch64/gen/Makefile.inc
> >> index a7b1b73f3ef..ee198f5d611 100644
> >> --- lib/libc/arch/aarch64/gen/Makefile.inc
> >> +++ lib/libc/arch/aarch64/gen/Makefile.inc
> >> @@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
> >>  SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
> >>  SRCS+= fpclassifyl.c
> >>  SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
> >> -SRCS+= signbitl.c
> >> +SRCS+= signbitl.c usertc.c
> >> diff --git lib/libc/arch/aarch64/gen/usertc.c
> >lib/libc/arch/aarch64/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/aarch64/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/alpha/gen/Makefile.inc
> >lib/libc/arch/alpha/gen/Makefile.inc
> >> index a44599d2cab..2a8abd32b61 100644
> >> --- lib/libc/arch/alpha/gen/Makefile.inc
> >> +++ lib/libc/arch/alpha/gen/Makefile.inc
> >> @@ -3,5 +3,5 @@
> >>  
> >>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
> >fpsetmask.c \
> >> - fpsetround.c fpsetsticky.c
> >> + fpsetround.c fpsetsticky.c usertc.c
> >>  SRCS+= sigsetjmp.S
> >> diff --git lib/libc/arch/alpha/gen/usertc.c
> >lib/libc/arch/alpha/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/alpha/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/amd64/gen/Makefile.inc
> >lib/libc/arch/amd64/gen/Makefile.inc
> >> index e995309ed71..f6349e2b974 100644
> >> --- lib/libc/arch/amd64/gen/Makefile.inc
> >> +++ lib/libc/arch/amd64/gen/Makefile.inc
> >> @@ -2,6 +2,7 @@
> >>  
> >>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
> >>   sigsetjmp.S
> >> -SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
> >signbitl.c
> >> +SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
> >signbitl.c \
> >> + usertc.c
> >>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S
> >fpsetmask.S \
> >>   fpsetround.S fpsetsticky.S
> >> diff --git lib/libc/arch/amd64/gen/usertc.c
> >lib/libc/arch/amd64/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..742fb0cc458
> >> --- /dev/null
> >> +++ lib/libc/arch/amd64/gen/usertc.c
> >> @@ -0,0 +1,41 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +static inline uint
> >> +rdtsc(void)
> >> +{
> >> + uint32_t hi, lo;
> >> + asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
> >> + return ((uint64_t)lo)|(((uint64_t)hi)<<32);
> >> +}
> >> +
> >> +int
> >> +tc_get_timecount(struct timekeep *tk, u_int *tc)
> >> +{
> >> + int tk_user = tk->tk_user;
> >> +
> >> + if (tk_user < 1 || tk_user >= TC_LAST)
> >> + return -1;
> >> +
> >> + *tc = rdtsc();
> >> + return 0;
> >> +}
> >> +int (*const _tc_get_timecount)(struct timekeep *tk, u_int *tc)
> >> + = tc_get_timecount;
> >> diff --git lib/libc/arch/arm/gen/Makefile.inc
> >lib/libc/arch/arm/gen/Makefile.inc
> >> index 1b4ab2f3ae7..27090a0d9dc 100644
> >> --- lib/libc/arch/arm/gen/Makefile.inc
> >> +++ lib/libc/arch/arm/gen/Makefile.inc
> >> @@ -2,5 +2,5 @@
> >>  # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
> >>  
> >>  SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c
> >infinity.c
> >> -SRCS+= ldexp.c modf.c nan.c
> >> +SRCS+= ldexp.c modf.c nan.c usertc.c
> >>  SRCS+= setjmp.S _setjmp.S sigsetjmp.S
> >> diff --git lib/libc/arch/arm/gen/usertc.c
> >lib/libc/arch/arm/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/arm/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/hppa/gen/Makefile.inc
> >lib/libc/arch/hppa/gen/Makefile.inc
> >> index e0c864242fe..1fde24670f1 100644
> >> --- lib/libc/arch/hppa/gen/Makefile.inc
> >> +++ lib/libc/arch/hppa/gen/Makefile.inc
> >> @@ -2,6 +2,6 @@
> >>  
> >>  SRCS+= setjmp.S
> >>  SRCS+= fabs.c
> >> -SRCS+= infinity.c ldexp.c modf.c nan.c
> >> +SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
> >fpsetmask.c \
> >>   fpsetround.c fpsetsticky.c
> >> diff --git lib/libc/arch/hppa/gen/usertc.c
> >lib/libc/arch/hppa/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/hppa/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/i386/gen/Makefile.inc
> >lib/libc/arch/i386/gen/Makefile.inc
> >> index 4c18e059581..b7dd30adccd 100644
> >> --- lib/libc/arch/i386/gen/Makefile.inc
> >> +++ lib/libc/arch/i386/gen/Makefile.inc
> >> @@ -1,6 +1,6 @@
> >>  # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
> >>  
> >> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
> >> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
> >>   modf.S nan.c setjmp.S sigsetjmp.S
> >>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
> >signbitl.c
> >>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S
> >fpsetmask.S \
> >> diff --git lib/libc/arch/i386/gen/usertc.c
> >lib/libc/arch/i386/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/i386/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/m88k/gen/Makefile.inc
> >lib/libc/arch/m88k/gen/Makefile.inc
> >> index cff75b8d425..d66f66af4af 100644
> >> --- lib/libc/arch/m88k/gen/Makefile.inc
> >> +++ lib/libc/arch/m88k/gen/Makefile.inc
> >> @@ -1,7 +1,7 @@
> >>  # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
> >>  # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
> >>  
> >> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
> >> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
> >fpsetmask.c \
> >>   fpsetround.c fpsetsticky.c
> >>  SRCS+= setjmp.S sigsetjmp.S
> >> diff --git lib/libc/arch/m88k/gen/usertc.c
> >lib/libc/arch/m88k/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/m88k/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/mips64/gen/Makefile.inc
> >lib/libc/arch/mips64/gen/Makefile.inc
> >> index 8cf1fc2d28a..839241a2069 100644
> >> --- lib/libc/arch/mips64/gen/Makefile.inc
> >> +++ lib/libc/arch/mips64/gen/Makefile.inc
> >> @@ -1,6 +1,6 @@
> >>  # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
> >>  
> >> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
> >> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
> >fpsetmask.c \
> >>   fpsetround.c fpsetsticky.c
> >>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
> >signbitl.c
> >> diff --git lib/libc/arch/mips64/gen/usertc.c
> >lib/libc/arch/mips64/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/mips64/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/powerpc/gen/Makefile.inc
> >lib/libc/arch/powerpc/gen/Makefile.inc
> >> index 6b2e4613ee8..d4d7b00bff7 100644
> >> --- lib/libc/arch/powerpc/gen/Makefile.inc
> >> +++ lib/libc/arch/powerpc/gen/Makefile.inc
> >> @@ -1,5 +1,5 @@
> >>  SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c
> >nan.c
> >> -SRCS+= fabs.c
> >> +SRCS+= fabs.c usertc.c
> >>  SRCS+= fpgetmask.c fpsetmask.c
> >>  SRCS+= fpgetround.c fpsetround.c
> >>  SRCS+= fpgetsticky.c fpsetsticky.c
> >> diff --git lib/libc/arch/powerpc/gen/usertc.c
> >lib/libc/arch/powerpc/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/powerpc/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/sh/gen/Makefile.inc
> >lib/libc/arch/sh/gen/Makefile.inc
> >> index 55de1973b30..4724fb3a6a8 100644
> >> --- lib/libc/arch/sh/gen/Makefile.inc
> >> +++ lib/libc/arch/sh/gen/Makefile.inc
> >> @@ -3,4 +3,4 @@
> >>  SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S
> >_setjmp.S
> >>  SRCS+= sigsetjmp.S
> >>  SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
> >> - fpsetmask.c fpsetround.c fpsetsticky.c
> >> + fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
> >> diff --git lib/libc/arch/sh/gen/usertc.c
> >lib/libc/arch/sh/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/sh/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/arch/sparc64/gen/Makefile.inc
> >lib/libc/arch/sparc64/gen/Makefile.inc
> >> index 58259cedef6..a908e022954 100644
> >> --- lib/libc/arch/sparc64/gen/Makefile.inc
> >> +++ lib/libc/arch/sparc64/gen/Makefile.inc
> >> @@ -3,5 +3,5 @@
> >>  SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
> >>   fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
> >>   fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
> >> - isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
> >> + isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
> >>   mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
> >> diff --git lib/libc/arch/sparc64/gen/usertc.c
> >lib/libc/arch/sparc64/gen/usertc.c
> >> new file mode 100644
> >> index 00000000000..6551854a010
> >> --- /dev/null
> >> +++ lib/libc/arch/sparc64/gen/usertc.c
> >> @@ -0,0 +1,21 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
> >> diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
> >> index 131da4b2190..40e84771f86 100644
> >> --- lib/libc/asr/asr.c
> >> +++ lib/libc/asr/asr.c
> >> @@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds,
> >int timeout)
> >>   struct timespec pollstart, pollend, elapsed;
> >>   int r;
> >>  
> >> - if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
> >>   return -1;
> >>  
> >>   while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
> >> - if (clock_gettime(CLOCK_MONOTONIC, &pollend))
> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
> >>   return -1;
> >>   timespecsub(&pollend, &pollstart, &elapsed);
> >>   timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
> >> @@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
> >>   asr->a_rtime = 0;
> >>   }
> >>  
> >> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
> >>   return;
> >>  
> >>   if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
> >> diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
> >> index 82de8fa33b7..02fd3013cc1 100644
> >> --- lib/libc/crypt/bcrypt.c
> >> +++ lib/libc/crypt/bcrypt.c
> >> @@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
> >>   char buf[_PASSWORD_LEN];
> >>   int duration;
> >>  
> >> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
> >> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
> >>   bcrypt_newhash("testpassword", r, buf, sizeof(buf));
> >> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
> >> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
> >>  
> >>   duration = after.tv_sec - before.tv_sec;
> >>   duration *= 1000000;
> >> diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
> >> index 270f54aada5..d2632455f11 100644
> >> --- lib/libc/dlfcn/init.c
> >> +++ lib/libc/dlfcn/init.c
> >> @@ -20,6 +20,7 @@
> >>  
> >>  #include <sys/types.h>
> >>  #include <sys/syscall.h>
> >> +#include <sys/timetc.h> /* timekeep */
> >>  
> >>  #ifndef PIC
> >>  #include <sys/mman.h>
> >> @@ -45,8 +46,9 @@
> >>  /* XXX should be in an include file shared with csu */
> >>  char ***_csu_finish(char **_argv, char **_envp, void
> >(*_cleanup)(void));
> >>  
> >> -/* provide definition for this */
> >> +/* provide definitions for these */
> >>  int _pagesize = 0;
> >> +struct timekeep *_timekeep;
> >>  
> >>  /*
> >>   * In dynamicly linked binaries environ and __progname are overriden
> >by
> >> @@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char
> >**envp, dl_cb_cb *cb)
> >>   phnum = aux->au_v;
> >>   break;
> >>  #endif /* !PIC */
> >> + case AUX_openbsd_timekeep:
> >> + if (_tc_get_timecount) {
> >> + _timekeep = (void *)aux->au_v;
> >> + if (_timekeep->tk_version != TK_VERSION)
> >> + _timekeep = NULL;
> >> + }
> >> + break;
> >>   }
> >>   }
> >>  
> >> diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
> >> index 1286a96fe40..32f86eda50f 100644
> >> --- lib/libc/gen/auth_subr.c
> >> +++ lib/libc/gen/auth_subr.c
> >> @@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
> >>  
> >>   if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
> >>   if (as->now.tv_sec == 0)
> >> - gettimeofday(&as->now, NULL);
> >> + WRAP(gettimeofday)(&as->now, NULL);
> >>   if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
> >>   as->state &= ~AUTH_ALLOW;
> >>   as->state |= AUTH_EXPIRED;
> >> @@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
> >>  
> >>   if (as->pwd && (quad_t)as->pwd->pw_change) {
> >>   if (as->now.tv_sec == 0)
> >> - gettimeofday(&as->now, NULL);
> >> + WRAP(gettimeofday)(&as->now, NULL);
> >>   if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
> >>   as->state &= ~AUTH_ALLOW;
> >>   as->state |= AUTH_PWEXPIRED;
> >> diff --git lib/libc/gen/time.c lib/libc/gen/time.c
> >> index 3bbd0d733d1..b3ce9a800f1 100644
> >> --- lib/libc/gen/time.c
> >> +++ lib/libc/gen/time.c
> >> @@ -36,7 +36,7 @@ time(time_t *t)
> >>  {
> >>   struct timeval tt;
> >>  
> >> - if (gettimeofday(&tt, NULL) == -1)
> >> + if (WRAP(gettimeofday)(&tt, NULL) == -1)
> >>   return (-1);
> >>   if (t)
> >>   *t = (time_t)tt.tv_sec;
> >> diff --git lib/libc/gen/times.c lib/libc/gen/times.c
> >> index 02e4dd44b5c..36841810d1b 100644
> >> --- lib/libc/gen/times.c
> >> +++ lib/libc/gen/times.c
> >> @@ -52,7 +52,7 @@ times(struct tms *tp)
> >>   return ((clock_t)-1);
> >>   tp->tms_cutime = CONVTCK(ru.ru_utime);
> >>   tp->tms_cstime = CONVTCK(ru.ru_stime);
> >> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
> >>   return ((clock_t)-1);
> >>   return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK));
> >>  }
> >> diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
> >> index 520a5954025..845cbe80356 100644
> >> --- lib/libc/gen/timespec_get.c
> >> +++ lib/libc/gen/timespec_get.c
> >> @@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
> >>  {
> >>   switch (base) {
> >>   case TIME_UTC:
> >> - if (clock_gettime(CLOCK_REALTIME, ts) == -1)
> >> + if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
> >>   return 0;
> >>   break;
> >>   default:
> >> diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
> >> index ed112320fa2..df717021cab 100644
> >> --- lib/libc/hidden/sys/time.h
> >> +++ lib/libc/hidden/sys/time.h
> >> @@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
> >>  PROTO_NORMAL(adjtime);
> >>  PROTO_NORMAL(futimes);
> >>  PROTO_NORMAL(getitimer);
> >> -PROTO_NORMAL(gettimeofday);
> >> +PROTO_WRAP(gettimeofday);
> >>  PROTO_NORMAL(setitimer);
> >>  PROTO_NORMAL(settimeofday);
> >>  PROTO_NORMAL(utimes);
> >> diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h
> >> new file mode 100644
> >> index 00000000000..bbdaa2d0d4c
> >> --- /dev/null
> >> +++ lib/libc/hidden/sys/timetc.h
> >> @@ -0,0 +1,38 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _LIBC_SYS_TIMETC_H_
> >> +#define _LIBC_SYS_TIMETC_H_
> >> +
> >> +#define _LIBC
> >> +#include <sys/types.h>
> >> +#include <sys/time.h>
> >> +
> >> +#include_next <sys/timetc.h>
> >> +
> >> +__BEGIN_HIDDEN_DECLS
> >> +extern struct timekeep *_timekeep;
> >> +
> >> +extern int (*const _tc_get_timecount)(struct timekeep *, u_int *);
> >> +
> >> +int _microtime(struct timeval *, struct timekeep *);
> >> +int _nanotime(struct timespec *, struct timekeep *);
> >> +int _nanoruntime(struct timespec *, struct timekeep *);
> >> +int _nanouptime(struct timespec *, struct timekeep *);
> >> +__END_HIDDEN_DECLS
> >> +
> >> +#endif /* !_LIBC_SYS_TIMETC_H_ */
> >> diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h
> >> index 18c49f8fcb9..d8e1e0caf64 100644
> >> --- lib/libc/hidden/time.h
> >> +++ lib/libc/hidden/time.h
> >> @@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r);
> >>  PROTO_STD_DEPRECATED(clock);
> >>  PROTO_DEPRECATED(clock_getcpuclockid);
> >>  PROTO_NORMAL(clock_getres);
> >> -PROTO_NORMAL(clock_gettime);
> >> +PROTO_WRAP(clock_gettime);
> >>  PROTO_NORMAL(clock_settime);
> >>  PROTO_STD_DEPRECATED(ctime);
> >>  PROTO_DEPRECATED(ctime_r);
> >> diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c
> >> index 763e420bb88..9babb28470a 100644
> >> --- lib/libc/net/res_random.c
> >> +++ lib/libc/net/res_random.c
> >> @@ -219,7 +219,7 @@ res_initid(void)
> >>   if (ru_prf != NULL)
> >>   arc4random_buf(ru_prf, sizeof(*ru_prf));
> >>  
> >> - clock_gettime(CLOCK_MONOTONIC, &ts);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
> >>   ru_reseed = ts.tv_sec + RU_OUT;
> >>   ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
> >>  }
> >> @@ -232,7 +232,7 @@ __res_randomid(void)
> >>   u_int r;
> >>   static void *randomid_mutex;
> >>  
> >> - clock_gettime(CLOCK_MONOTONIC, &ts);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
> >>   pid = getpid();
> >>  
> >>   _MUTEX_LOCK(&randomid_mutex);
> >> diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c
> >> index 402d98cede4..917a6d42b8a 100644
> >> --- lib/libc/rpc/auth_unix.c
> >> +++ lib/libc/rpc/auth_unix.c
> >> @@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid,
> >int len, int *aup_gids)
> >>   /*
> >>   * fill in param struct from the given params
> >>   */
> >> - (void)gettimeofday(&now,  NULL);
> >> + (void)WRAP(gettimeofday)(&now,  NULL);
> >>   aup.aup_time = now.tv_sec;
> >>   aup.aup_machname = machname;
> >>   aup.aup_uid = uid;
> >> @@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth)
> >>   goto done;
> >>  
> >>   /* update the time and serialize in place */
> >> - (void)gettimeofday(&now, NULL);
> >> + (void)WRAP(gettimeofday)(&now, NULL);
> >>   aup.aup_time = now.tv_sec;
> >>   xdrs.x_op = XDR_ENCODE;
> >>   XDR_SETPOS(&xdrs, 0);
> >> diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c
> >> index 8e6ef515b0e..927b4bf2028 100644
> >> --- lib/libc/rpc/clnt_tcp.c
> >> +++ lib/libc/rpc/clnt_tcp.c
> >> @@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int
> >len)
> >>   pfd[0].events = POLLIN;
> >>   TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait);
> >>   delta = wait;
> >> - clock_gettime(CLOCK_MONOTONIC, &start);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
> >>   for (;;) {
> >>   r = ppoll(pfd, 1, &delta, NULL);
> >>   save_errno = errno;
> >>  
> >> - clock_gettime(CLOCK_MONOTONIC, &after);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
> >>   timespecsub(&start, &after, &duration);
> >>   timespecsub(&wait, &duration, &delta);
> >>   if (delta.tv_sec < 0 || !timespecisset(&delta))
> >> diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c
> >> index 68d01674410..92e1d5c350d 100644
> >> --- lib/libc/rpc/clnt_udp.c
> >> +++ lib/libc/rpc/clnt_udp.c
> >> @@ -265,7 +265,7 @@ send_again:
> >>   reply_msg.acpted_rply.ar_results.where = resultsp;
> >>   reply_msg.acpted_rply.ar_results.proc = xresults;
> >>  
> >> - clock_gettime(CLOCK_MONOTONIC, &start);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
> >>   for (;;) {
> >>   switch (ppoll(pfd, 1, &wait, NULL)) {
> >>   case 0:
> >> @@ -283,7 +283,7 @@ send_again:
> >>   /* FALLTHROUGH */
> >>   case -1:
> >>   if (errno == EINTR) {
> >> - clock_gettime(CLOCK_MONOTONIC, &after);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
> >>   timespecsub(&after, &start, &duration);
> >>   timespecadd(&time_waited, &duration, &time_waited);
> >>   if (timespeccmp(&time_waited, &timeout, <))
> >> diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c
> >> index f9d7a70938f..6c99db84359 100644
> >> --- lib/libc/rpc/svc_tcp.c
> >> +++ lib/libc/rpc/svc_tcp.c
> >> @@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
> >>   * A timeout is fatal for the connection.
> >>   */
> >>   delta = wait_per_try;
> >> - clock_gettime(CLOCK_MONOTONIC, &start);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
> >>   pfd[0].fd = sock;
> >>   pfd[0].events = POLLIN;
> >>   do {
> >> @@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
> >>   case -1:
> >>   if (errno != EINTR)
> >>   goto fatal_err;
> >> - clock_gettime(CLOCK_MONOTONIC, &after);
> >> + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
> >>   timespecsub(&after, &start, &duration);
> >>   timespecsub(&wait_per_try, &duration, &delta);
> >>   if (delta.tv_sec < 0 || !timespecisset(&delta))
> >> diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc
> >> index 34769576ced..d57418d81bf 100644
> >> --- lib/libc/sys/Makefile.inc
> >> +++ lib/libc/sys/Makefile.inc
> >> @@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \
> >>  
> >>  # glue to offer userland wrappers for some syscalls
> >>  SRCS+= posix_madvise.c pthread_sigmask.c \
> >> - w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c
> >> + w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \
> >> + w_clock_gettime.c w_gettimeofday.c microtime.c
> >>  
> >>  # glue for compat with old syscall interfaces.
> >>  SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c
> >truncate.c \
> >> @@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c
> >w_pwrite.c w_pwritev.c
> >>  ASM= __semctl.o __syscall.o __thrsigdivert.o \
> >>   access.o acct.o adjfreq.o adjtime.o \
> >>   bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \
> >> - clock_getres.o clock_gettime.o clock_settime.o \
> >> + clock_getres.o clock_settime.o \
> >>   dup.o dup2.o dup3.o \
> >>   execve.o \
> >>   faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \
> >> @@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \
> >>   getgroups.o getitimer.o getpeername.o getpgid.o \
> >>   getpriority.o getresgid.o getresuid.o \
> >>   getrlimit.o getrusage.o getsid.o getsockname.o \
> >> - getsockopt.o gettimeofday.o ioctl.o \
> >> + getsockopt.o ioctl.o \
> >>   kevent.o kill.o kqueue.o ktrace.o lchown.o \
> >>   link.o linkat.o listen.o lstat.o madvise.o \
> >>   minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
> >> @@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po}
> >>  SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so}
> >>  DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do}
> >>  
> >> -HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o
> >${CANCEL:=.o}
> >> +HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o
> >${CANCEL:=.o} \
> >> + clock_gettime.o gettimeofday.o
> >>  PHIDDEN=${HIDDEN:.o=.po}
> >>  SHIDDEN=${HIDDEN:.o=.so}
> >>  DHIDDEN=${HIDDEN:.o=.do}
> >> diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c
> >> new file mode 100644
> >> index 00000000000..5191b5b2606
> >> --- /dev/null
> >> +++ lib/libc/sys/microtime.c
> >> @@ -0,0 +1,181 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2000 Poul-Henning Kamp <[hidden email]>
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/types.h>
> >> +#include <sys/atomic.h>
> >> +#include <sys/timetc.h>
> >> +
> >> +#include <time.h>
> >> +
> >> +/*
> >> + * Return the difference between the timehands' counter value now
> >and what
> >> + * was when we copied it to the timehands' offset_count.
> >> + */
> >> +static inline int
> >> +tc_delta(struct timekeep *tk, u_int *delta)
> >> +{
> >> + uint tc;
> >> +
> >> + if (_tc_get_timecount(tk, &tc))
> >> + return -1;
> >> + *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
> >> + return 0;
> >> +}
> >> +
> >> +static inline void
> >> +bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime
> >*ct)
> >> +{
> >> + ct->sec = bt->sec;
> >> + if (bt->frac > bt->frac + x)
> >> + ct->sec++;
> >> + ct->frac = bt->frac + x;
> >> +}
> >> +
> >> +static inline void
> >> +BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts)
> >> +{
> >> + ts->tv_sec = bt->sec;
> >> + ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >>
> >32)) >> 32);
> >> +}
> >> +
> >> +static inline void
> >> +BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv)
> >> +{
> >> + tv->tv_sec = bt->sec;
> >> + tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >>
> >32)) >> 32);
> >> +}
> >> +
> >> +static int
> >> +binuptime(struct bintime *bt, struct timekeep *tk)
> >> +{
> >> + u_int gen, delta;
> >> +
> >> + do {
> >> + gen = tk->tk_generation;
> >> + membar_consumer();
> >> + *bt = tk->tk_offset;
> >> + if (tc_delta(tk, &delta))
> >> + return -1;
> >> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
> >> + membar_consumer();
> >> + } while (gen == 0 || gen != tk->tk_generation);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static inline void
> >> +bintimeadd(const struct bintime *bt, const struct bintime *ct,
> >> +    struct bintime *dt)
> >> +{
> >> + dt->sec = bt->sec + ct->sec;
> >> + if (bt->frac > bt->frac + ct->frac)
> >> + dt->sec++;
> >> + dt->frac = bt->frac + ct->frac;
> >> +}
> >> +
> >> +static inline void
> >> +bintimesub(const struct bintime *bt, const struct bintime *ct,
> >> +    struct bintime *dt)
> >> +{
> >> + dt->sec = bt->sec - ct->sec;
> >> + if (bt->frac < bt->frac - ct->frac)
> >> + dt->sec--;
> >> + dt->frac = bt->frac - ct->frac;
> >> +}
> >> +
> >> +static int
> >> +binruntime(struct bintime *bt, struct timekeep *tk)
> >> +{
> >> + u_int gen, delta;
> >> +
> >> + do {
> >> + gen = tk->tk_generation;
> >> + membar_consumer();
> >> + if (tc_delta(tk, &delta))
> >> + return -1;
> >> + bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt);
> >> + bintimesub(bt, &tk->tk_naptime, bt);
> >> + membar_consumer();
> >> + } while (gen == 0 || gen != tk->tk_generation);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static int
> >> +bintime(struct bintime *bt, struct timekeep *tk)
> >> +{
> >> + u_int gen, delta;
> >> +
> >> + do {
> >> + gen = tk->tk_generation;
> >> + membar_consumer();
> >> + *bt = tk->tk_offset;
> >> + if (tc_delta(tk, &delta))
> >> + return -1;
> >> + bintimeaddfrac(bt, tk->tk_scale * delta, bt);
> >> + bintimeadd(bt, &tk->tk_boottime, bt);
> >> + membar_consumer();
> >> + } while (gen == 0 || gen != tk->tk_generation);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +int
> >> +_microtime(struct timeval *tvp, struct timekeep *tk)
> >> +{
> >> + struct bintime bt;
> >> +
> >> + if (bintime(&bt, tk))
> >> + return -1;
> >> + BINTIME_TO_TIMEVAL(&bt, tvp);
> >> + return 0;
> >> +}
> >> +
> >> +int
> >> +_nanotime(struct timespec *tsp, struct timekeep *tk)
> >> +{
> >> + struct bintime bt;
> >> +
> >> + if (bintime(&bt, tk))
> >> + return -1;
> >> + BINTIME_TO_TIMESPEC(&bt, tsp);
> >> + return 0;
> >> +}
> >> +
> >> +int
> >> +_nanoruntime(struct timespec *ts, struct timekeep *tk)
> >> +{
> >> + struct bintime bt;
> >> +
> >> + if (binruntime(&bt, tk))
> >> + return -1;
> >> + BINTIME_TO_TIMESPEC(&bt, ts);
> >> + return 0;
> >> +}
> >> +
> >> +
> >> +int
> >> +_nanouptime(struct timespec *tsp, struct timekeep *tk)
> >> +{
> >> + struct bintime bt;
> >> +
> >> + if (binuptime(&bt, tk))
> >> + return -1;
> >> + BINTIME_TO_TIMESPEC(&bt, tsp);
> >> + return 0;
> >> +}
> >> diff --git lib/libc/sys/w_clock_gettime.c
> >lib/libc/sys/w_clock_gettime.c
> >> new file mode 100644
> >> index 00000000000..6e6478bd131
> >> --- /dev/null
> >> +++ lib/libc/sys/w_clock_gettime.c
> >> @@ -0,0 +1,51 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/timetc.h>
> >> +
> >> +#include <time.h>
> >> +
> >> +int
> >> +WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp)
> >> +{
> >> + int rc = 0;
> >> + struct timekeep *timekeep = _timekeep;
> >> +
> >> + if (timekeep == NULL || timekeep->tk_user == 0)
> >> + return clock_gettime(clock_id, tp);
> >> +
> >> + switch (clock_id) {
> >> + case CLOCK_REALTIME:
> >> + rc = _nanotime(tp, timekeep);
> >> + break;
> >> + case CLOCK_UPTIME:
> >> + rc = _nanoruntime(tp, timekeep);
> >> + break;
> >> + case CLOCK_MONOTONIC:
> >> + case CLOCK_BOOTTIME:
> >> + rc = _nanouptime(tp, timekeep);
> >> + break;
> >> + default:
> >> + return clock_gettime(clock_id, tp);
> >> + }
> >> +
> >> + if (rc)
> >> + return clock_gettime(clock_id, tp);
> >> +
> >> + return 0;
> >> +}
> >> +DEF_WRAP(clock_gettime);
> >> diff --git lib/libc/sys/w_gettimeofday.c
> >lib/libc/sys/w_gettimeofday.c
> >> new file mode 100644
> >> index 00000000000..f44edfbb1ad
> >> --- /dev/null
> >> +++ lib/libc/sys/w_gettimeofday.c
> >> @@ -0,0 +1,40 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Robert Nagy <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/timetc.h>
> >> +
> >> +int
> >> +WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp)
> >> +{
> >> + int rc = 0;
> >> + struct timekeep *timekeep = _timekeep;
> >> + static struct timezone zerotz = { 0, 0 };
> >> +
> >> + if (timekeep == NULL || timekeep->tk_user == 0)
> >> + return gettimeofday(tp, tzp);
> >> +
> >> + if (tp)
> >> + rc = _microtime(tp, timekeep);
> >> + if (rc)
> >> + return gettimeofday(tp, tzp);
> >> +
> >> + if (tzp)
> >> + *tzp = zerotz;
> >> +
> >> + return 0;
> >> +}
> >> +DEF_WRAP(gettimeofday);
> >> diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h
> >> index 788890add89..df2239438d2 100644
> >> --- lib/libc/thread/synch.h
> >> +++ lib/libc/thread/synch.h
> >> @@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t
> >clockid, const struct timespec *
> >>   if (abs == NULL)
> >>   return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
> >>  
> >> - if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
> >> + if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid,
> >&rel))
> >>   return (EINVAL);
> >>  
> >>   rel.tv_sec = abs->tv_sec - rel.tv_sec;
> >> diff --git regress/lib/libc/timekeep/Makefile
> >regress/lib/libc/timekeep/Makefile
> >> new file mode 100644
> >> index 00000000000..a7f3080290d
> >> --- /dev/null
> >> +++ regress/lib/libc/timekeep/Makefile
> >> @@ -0,0 +1,5 @@
> >> +# $OpenBSD$
> >> +
> >> +PROGS= test_clock_gettime test_time_skew test_gettimeofday
> >> +
> >> +.include <bsd.regress.mk>
> >> diff --git regress/lib/libc/timekeep/test_clock_gettime.c
> >regress/lib/libc/timekeep/test_clock_gettime.c
> >> new file mode 100644
> >> index 00000000000..859ec368215
> >> --- /dev/null
> >> +++ regress/lib/libc/timekeep/test_clock_gettime.c
> >> @@ -0,0 +1,43 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <assert.h>
> >> +#include <time.h>
> >> +
> >> +#define ASSERT_EQ(a, b) assert((a) == (b))
> >> +
> >> +void
> >> +check()
> >> +{
> >> + struct timespec tp = {0};
> >> +
> >> + ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp));
> >> + ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp));
> >> + ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp));
> >> + ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp));
> >> +
> >> +
> >> + ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp));
> >> + ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp));
> >> +
> >> +}
> >> +
> >> +int main()
> >> +{
> >> + check();
> >> + return 0;
> >> +}
> >> diff --git regress/lib/libc/timekeep/test_gettimeofday.c
> >regress/lib/libc/timekeep/test_gettimeofday.c
> >> new file mode 100644
> >> index 00000000000..ea90a1be7e0
> >> --- /dev/null
> >> +++ regress/lib/libc/timekeep/test_gettimeofday.c
> >> @@ -0,0 +1,37 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <assert.h>
> >> +#include <sys/time.h>
> >> +
> >> +#define ASSERT_EQ(a, b) assert((a) == (b))
> >> +
> >> +void
> >> +check()
> >> +{
> >> + struct timeval tv = {0};
> >> + struct timezone tzp;
> >> +
> >> + ASSERT_EQ(0, gettimeofday(&tv, NULL));
> >> + ASSERT_EQ(0, gettimeofday(&tv, &tzp));
> >> +}
> >> +
> >> +int main()
> >> +{
> >> + check();
> >> + return 0;
> >> +}
> >> diff --git regress/lib/libc/timekeep/test_time_skew.c
> >regress/lib/libc/timekeep/test_time_skew.c
> >> new file mode 100644
> >> index 00000000000..dfa9481c091
> >> --- /dev/null
> >> +++ regress/lib/libc/timekeep/test_time_skew.c
> >> @@ -0,0 +1,55 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#include <sys/time.h>
> >> +
> >> +#include <assert.h>
> >> +#include <time.h>
> >> +#include <stdlib.h>
> >> +#include <stdio.h>
> >> +
> >> +#define ASSERT_EQ(a, b) assert((a) == (b))
> >> +#define ASSERT_NE(a, b) assert((a) != (b))
> >> +
> >> +void
> >> +check()
> >> +{
> >> +         struct timespec tp1, tp2, tout;
> >> +
> >> +         tout.tv_sec = 0;
> >> +         tout.tv_nsec = 100000;
> >> +
> >> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1));
> >> +
> >> +         nanosleep(&tout, NULL);
> >> +
> >> +         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2));
> >> +
> >> +         /* tp1 should never be larger than tp2 */
> >> +         ASSERT_NE(1, timespeccmp(&tp1, &tp2, >));
> >> +}
> >> +
> >> +int
> >> +main(void)
> >> +{
> >> + int i;
> >> +
> >> + for (i = 0; i < 1000; i++)
> >> + check();
> >> +
> >> + return 0;
> >> +}
> >> diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c
> >> index 3f5f2c5b42b..6eaf8b107c6 100644
> >> --- sys/arch/alpha/alpha/clock.c
> >> +++ sys/arch/alpha/alpha/clock.c
> >> @@ -64,7 +64,7 @@ int clk_irq = 0;
> >>  
> >>  u_int rpcc_get_timecount(struct timecounter *);
> >>  struct timecounter rpcc_timecounter = {
> >> - rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
> >> + rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0
> >>  };
> >>  
> >>  extern todr_chip_handle_t todr_handle;
> >> diff --git sys/arch/alpha/include/timetc.h
> >sys/arch/alpha/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/alpha/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c
> >> index 7a1dcb4ad75..5839fa15d6c 100644
> >> --- sys/arch/amd64/amd64/tsc.c
> >> +++ sys/arch/amd64/amd64/tsc.c
> >> @@ -42,7 +42,7 @@ int64_t tsc_drift_observed;
> >>  volatile int64_t tsc_sync_val;
> >>  volatile struct cpu_info *tsc_sync_cpu;
> >>  
> >> -uint tsc_get_timecount(struct timecounter *tc);
> >> +u_int tsc_get_timecount(struct timecounter *tc);
> >>  
> >>  #include "lapic.h"
> >>  #if NLAPIC > 0
> >> @@ -50,7 +50,7 @@ extern u_int32_t lapic_per_second;
> >>  #endif
> >>  
> >>  struct timecounter tsc_timecounter = {
> >> - tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL
> >> + tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, TC_TSC
> >>  };
> >>  
> >>  uint64_t
> >> @@ -244,6 +244,7 @@ tsc_timecounter_init(struct cpu_info *ci,
> >uint64_t cpufreq)
> >>   printf("ERROR: %lld cycle TSC drift observed\n",
> >>      (long long)tsc_drift_observed);
> >>   tsc_timecounter.tc_quality = -1000;
> >> + tsc_timecounter.tc_user = 0;
> >>   tsc_is_invariant = 0;
> >>   }
> >>  
> >> diff --git sys/arch/amd64/include/timetc.h
> >sys/arch/amd64/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..c2d40bcd1e7
> >> --- /dev/null
> >> +++ sys/arch/amd64/include/timetc.h
> >> @@ -0,0 +1,24 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_TSC 1
> >> +#define TC_LAST 2
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c
> >> index 613f7ee0e0f..00da0c6a8d0 100644
> >> --- sys/arch/amd64/isa/clock.c
> >> +++ sys/arch/amd64/isa/clock.c
> >> @@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter
> >*tc);
> >>  u_int i8254_simple_get_timecount(struct timecounter *tc);
> >>  
> >>  static struct timecounter i8254_timecounter = {
> >> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
> >> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
> >>  };
> >>  
> >>  int clockintr(void *);
> >> diff --git sys/arch/arm/include/timetc.h
> >sys/arch/arm/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/arm/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c
> >> index 11196b5c60d..1a2106ef94c 100644
> >> --- sys/arch/arm64/dev/agtimer.c
> >> +++ sys/arch/arm64/dev/agtimer.c
> >> @@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY;
> >>  u_int agtimer_get_timecount(struct timecounter *);
> >>  
> >>  static struct timecounter agtimer_timecounter = {
> >> - agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL
> >> + agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0
> >>  };
> >>  
> >>  struct agtimer_pcpu_softc {
> >> diff --git sys/arch/arm64/include/timetc.h
> >sys/arch/arm64/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/arm64/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/armv7/include/timetc.h
> >sys/arch/armv7/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/armv7/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/armv7/omap/gptimer.c
> >sys/arch/armv7/omap/gptimer.c
> >> index 7605845d5e2..061542d532f 100644
> >> --- sys/arch/armv7/omap/gptimer.c
> >> +++ sys/arch/armv7/omap/gptimer.c
> >> @@ -117,7 +117,7 @@ int gptimer_irq = 0;
> >>  u_int gptimer_get_timecount(struct timecounter *);
> >>  
> >>  static struct timecounter gptimer_timecounter = {
> >> - gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
> >> + gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0
> >>  };
> >>  
> >>  volatile u_int32_t nexttickevent;
> >> diff --git sys/arch/armv7/sunxi/sxitimer.c
> >sys/arch/armv7/sunxi/sxitimer.c
> >> index 14a243c78d0..41028f9a602 100644
> >> --- sys/arch/armv7/sunxi/sxitimer.c
> >> +++ sys/arch/armv7/sunxi/sxitimer.c
> >> @@ -89,7 +89,7 @@ void sxitimer_delay(u_int);
> >>  u_int sxitimer_get_timecount(struct timecounter *);
> >>  
> >>  static struct timecounter sxitimer_timecounter = {
> >> - sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL
> >> + sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0
> >>  };
> >>  
> >>  bus_space_tag_t sxitimer_iot;
> >> diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c
> >> index 4c594ab5ec7..8cce6c3a893 100644
> >> --- sys/arch/hppa/dev/clock.c
> >> +++ sys/arch/hppa/dev/clock.c
> >> @@ -47,7 +47,7 @@ int cpu_hardclock(void *);
> >>  u_int itmr_get_timecount(struct timecounter *);
> >>  
> >>  struct timecounter itmr_timecounter = {
> >> - itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
> >> + itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0
> >>  };
> >>  
> >>  extern todr_chip_handle_t todr_handle;
> >> diff --git sys/arch/hppa/include/timetc.h
> >sys/arch/hppa/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/hppa/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/i386/include/timetc.h
> >sys/arch/i386/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/i386/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c
> >> index 09a6db983f2..dd74bd425ad 100644
> >> --- sys/arch/i386/isa/clock.c
> >> +++ sys/arch/i386/isa/clock.c
> >> @@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter
> >*tc);
> >>  u_int i8254_simple_get_timecount(struct timecounter *tc);
> >>  
> >>  static struct timecounter i8254_timecounter = {
> >> - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
> >> + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
> >>  };
> >>  struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
> >>  u_long rtclock_tval;
> >> diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
> >> index 9d9f061eef9..bb8e4c7f9ae 100644
> >> --- sys/arch/i386/pci/geodesc.c
> >> +++ sys/arch/i386/pci/geodesc.c
> >> @@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = {
> >>   0xffffffff, /* counter_mask */
> >>   27000000, /* frequency */
> >>   "GEOTSC", /* name */
> >> - 2000 /* quality */
> >> + 2000, /* quality */
> >> + NULL, /* private bits */
> >> + 0 /* expose to user */
> >>  };
> >>  
> >>  int
> >> diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c
> >> index 8b8aa4ac430..a6f324e66f3 100644
> >> --- sys/arch/i386/pci/gscpm.c
> >> +++ sys/arch/i386/pci/gscpm.c
> >> @@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = {
> >>   0xffffff, /* counter_mask */
> >>   3579545, /* frequency */
> >>   "GSCPM", /* name */
> >> - 1000 /* quality */
> >> + 1000, /* quality */
> >> + NULL, /* private bits */
> >> + 0 /* expose to user */
> >>  };
> >>  
> >>  struct cfattach gscpm_ca = {
> >> diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c
> >> index 6abf1627de2..629a86a14ff 100644
> >> --- sys/arch/i386/pci/ichpcib.c
> >> +++ sys/arch/i386/pci/ichpcib.c
> >> @@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = {
> >>   0xffffff, /* counter_mask */
> >>   3579545, /* frequency */
> >>   "ICHPM", /* name */
> >> - 1000 /* quality */
> >> + 1000, /* quality */
> >> + NULL, /* private bits */
> >> + 0 /* expose to user */
> >>  };
> >>  
> >>  struct cfattach ichpcib_ca = {
> >> diff --git sys/arch/landisk/include/timetc.h
> >sys/arch/landisk/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/landisk/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/loongson/include/timetc.h
> >sys/arch/loongson/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/loongson/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/loongson/loongson/generic3a_machdep.c
> >sys/arch/loongson/loongson/generic3a_machdep.c
> >> index ac3f1db6ccd..53489b07549 100644
> >> --- sys/arch/loongson/loongson/generic3a_machdep.c
> >> +++ sys/arch/loongson/loongson/generic3a_machdep.c
> >> @@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = {
> >>   .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */
> >>   .tc_frequency = HPET_FREQ,
> >>   .tc_name = "hpet",
> >> - .tc_quality = 100
> >> + .tc_quality = 100,
> >> + .tc_priv = NULL,
> >> + .tc_user = 0,
> >>  };
> >>  
> >>  /* Firmware entry points */
> >> diff --git sys/arch/luna88k/include/timetc.h
> >sys/arch/luna88k/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/luna88k/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/luna88k/luna88k/clock.c
> >sys/arch/luna88k/luna88k/clock.c
> >> index a04120987e0..6580a4a46bf 100644
> >> --- sys/arch/luna88k/luna88k/clock.c
> >> +++ sys/arch/luna88k/luna88k/clock.c
> >> @@ -112,7 +112,9 @@ struct timecounter clock_tc = {
> >>   .tc_counter_mask = 0xffffffff,
> >>   .tc_frequency = 0, /* will be filled in */
> >>   .tc_name = "clock",
> >> - .tc_quality = 0
> >> + .tc_quality = 0,
> >> + .tc_priv = NULL,
> >> + .tc_user = 0,
> >>  };
> >>  
> >>  /*
> >> diff --git sys/arch/m88k/include/timetc.h
> >sys/arch/m88k/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/m88k/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/macppc/include/timetc.h
> >sys/arch/macppc/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/macppc/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/macppc/macppc/clock.c
> >sys/arch/macppc/macppc/clock.c
> >> index 4a44a92cfc0..8c3ad620be8 100644
> >> --- sys/arch/macppc/macppc/clock.c
> >> +++ sys/arch/macppc/macppc/clock.c
> >> @@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320;
> >>  static int32_t ticks_per_intr;
> >>  
> >>  static struct timecounter tb_timecounter = {
> >> - tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
> >> + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0
> >>  };
> >>  
> >>  /* calibrate the timecounter frequency for the listed models */
> >> diff --git sys/arch/mips64/include/timetc.h
> >sys/arch/mips64/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/mips64/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/mips64/mips64/mips64_machdep.c
> >sys/arch/mips64/mips64/mips64_machdep.c
> >> index d4a42ed5acc..5c4dbadb5bb 100644
> >> --- sys/arch/mips64/mips64/mips64_machdep.c
> >> +++ sys/arch/mips64/mips64/mips64_machdep.c
> >> @@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = {
> >>   0xffffffff, /* counter_mask */
> >>   0, /* frequency */
> >>   "CP0", /* name */
> >> - 0 /* quality */
> >> + 0, /* quality */
> >> + NULL, /* private bits */
> >> + 0, /* expose to user */
> >>  };
> >>  
> >>  u_int
> >> diff --git sys/arch/octeon/include/timetc.h
> >sys/arch/octeon/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/octeon/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/octeon/octeon/machdep.c
> >sys/arch/octeon/octeon/machdep.c
> >> index 902e462d53f..d8377653abe 100644
> >> --- sys/arch/octeon/octeon/machdep.c
> >> +++ sys/arch/octeon/octeon/machdep.c
> >> @@ -151,8 +151,9 @@ struct timecounter ioclock_timecounter = {
> >>   .tc_name = "ioclock",
> >>   .tc_quality = 0, /* ioclock can be overridden
> >>   * by cp0 counter */
> >> - .tc_priv = 0 /* clock register,
> >> + .tc_priv = 0, /* clock register,
> >>   * determined at runtime */
> >> + .tc_user = 0, /* expose to user */
> >>  };
> >>  
> >>  static int
> >> diff --git sys/arch/powerpc/include/timetc.h
> >sys/arch/powerpc/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/powerpc/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/powerpc64/include/timetc.h
> >sys/arch/powerpc64/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/powerpc64/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/sgi/include/timetc.h
> >sys/arch/sgi/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/sgi/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/sgi/sgi/ip27_machdep.c
> >sys/arch/sgi/sgi/ip27_machdep.c
> >> index ba7fa558b96..2a2cc144242 100644
> >> --- sys/arch/sgi/sgi/ip27_machdep.c
> >> +++ sys/arch/sgi/sgi/ip27_machdep.c
> >> @@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = {
> >>   .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */
> >>   .tc_frequency = 1250000,
> >>   .tc_name = "hubrt",
> >> - .tc_quality = 100
> >> + .tc_quality = 100,
> >> + .tc_priv = 0,
> >> + .tc_user = 0,
> >>  };
> >>  
> >>  volatile uint64_t ip27_spinup_a0;
> >> diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c
> >> index 56b29915c70..827775512ac 100644
> >> --- sys/arch/sgi/xbow/xheart.c
> >> +++ sys/arch/sgi/xbow/xheart.c
> >> @@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = {
> >>   .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit
> >*/
> >>   .tc_frequency = 12500000,
> >>   .tc_name = "heart",
> >> - .tc_quality = 100
> >> + .tc_quality = 100,
> >> + .tc_priv = NULL,
> >> + .tc_user = 0,
> >>  };
> >>  
> >>  extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *);
> >> diff --git sys/arch/sh/include/timetc.h sys/arch/sh/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/sh/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/sparc64/dev/psycho.c
> >sys/arch/sparc64/dev/psycho.c
> >> index e24f804dff6..1a7a1afa8c2 100644
> >> --- sys/arch/sparc64/dev/psycho.c
> >> +++ sys/arch/sparc64/dev/psycho.c
> >> @@ -127,7 +127,7 @@ extern struct sparc_pci_chipset
> >_sparc_pci_chipset;
> >>  u_int stick_get_timecount(struct timecounter *);
> >>  
> >>  struct timecounter stick_timecounter = {
> >> - stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
> >> + stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0
> >>  };
> >>  
> >>  /*
> >> diff --git sys/arch/sparc64/include/timetc.h
> >sys/arch/sparc64/include/timetc.h
> >> new file mode 100644
> >> index 00000000000..e58a7fb4faa
> >> --- /dev/null
> >> +++ sys/arch/sparc64/include/timetc.h
> >> @@ -0,0 +1,23 @@
> >> +/* $OpenBSD$ */
> >> +/*
> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
> >> + *
> >> + * Permission to use, copy, modify, and distribute this software for
> >any
> >> + * purpose with or without fee is hereby granted, provided that the
> >above
> >> + * copyright notice and this permission notice appear in all copies.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> >WARRANTIES
> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
> >LIABLE FOR
> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
> >DAMAGES
> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
> >IN AN
> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
> >OUT OF
> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> >> + */
> >> +
> >> +#ifndef _MACHINE_TIMETC_H_
> >> +#define _MACHINE_TIMETC_H_
> >> +
> >> +#define TC_LAST 0
> >> +
> >> +#endif /* _MACHINE_TIMETC_H_ */
> >> diff --git sys/arch/sparc64/sparc64/clock.c
> >sys/arch/sparc64/sparc64/clock.c
> >> index fd5e8a9c15b..5c2e47d386b 100644
> >> --- sys/arch/sparc64/sparc64/clock.c
> >> +++ sys/arch/sparc64/sparc64/clock.c
> >> @@ -109,13 +109,13 @@ struct cfdriver clock_cd = {
> >>  u_int tick_get_timecount(struct timecounter *);
> >>  
> >>  struct timecounter tick_timecounter = {
> >> - tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL
> >> + tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0
> >>  };
> >>  
> >>  u_int sys_tick_get_timecount(struct timecounter *);
> >>  
> >>  struct timecounter sys_tick_timecounter = {
> >> - sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL
> >> + sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0
> >>  };
> >>  
> >>  /*
> >> diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c
> >> index d0ee72cec9b..13177a909da 100644
> >> --- sys/dev/acpi/acpihpet.c
> >> +++ sys/dev/acpi/acpihpet.c
> >> @@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = {
> >>   0xffffffff, /* counter_mask (32 bits) */
> >>   0, /* frequency */
> >>   0, /* name */
> >> - 1000 /* quality */
> >> + 1000, /* quality */
> >> + NULL, /* private bits */
> >> + 0, /* expose to user */
> >>  };
> >>  
> >>  #define HPET_TIMERS 3
> >> diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c
> >> index cdc8c99a17a..89b5a397e47 100644
> >> --- sys/dev/acpi/acpitimer.c
> >> +++ sys/dev/acpi/acpitimer.c
> >> @@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = {
> >>   0x00ffffff, /* counter_mask (24 bits) */
> >>   ACPI_FREQUENCY, /* frequency */
> >>   0, /* name */
> >> - 1000 /* quality */
> >> + 1000, /* quality */
> >> + NULL, /* private bits */
> >> + 0, /* expose to user */
> >>  };
> >>  
> >>  struct acpitimer_softc {
> >> diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c
> >> index 6df82858016..9610d5bc1f0 100644
> >> --- sys/dev/pci/amdpm.c
> >> +++ sys/dev/pci/amdpm.c
> >> @@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = {
> >>   0xffffff, /* counter_mask */
> >>   AMDPM_FREQUENCY, /* frequency */
> >>   "AMDPM", /* name */
> >> - 1000 /* quality */
> >> + 1000, /* quality */
> >> + NULL, /* private bits */
> >> + 0, /* expose to user */
> >>  };
> >>  
> >>  #define AMDPM_CONFREG 0x40
> >> diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c
> >> index db806eedf80..ce33cd175e6 100644
> >> --- sys/dev/pci/viapm.c
> >> +++ sys/dev/pci/viapm.c
> >> @@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = {
> >>   0xffffff, /* counter_mask */
> >>   VIAPM_FREQUENCY, /* frequency */
> >>   "VIAPM", /* name */
> >> - 1000 /* quality */
> >> + 1000, /* quality */
> >> + NULL, /* private bits */
> >> + 0, /* expose to user */
> >>  };
> >>  
> >>  struct timeout viapm_timeout;
> >> diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c
> >> index b32facdacb1..b9ee2feec4c 100644
> >> --- sys/dev/pv/hyperv.c
> >> +++ sys/dev/pv/hyperv.c
> >> @@ -141,7 +141,7 @@ struct {
> >>  };
> >>  
> >>  struct timecounter hv_timecounter = {
> >> - hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001
> >> + hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0
> >>  };
> >>  
> >>  struct cfdriver hyperv_cd = {
> >> diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c
> >> index 6b242f7448d..b80e4d2a484 100644
> >> --- sys/dev/pv/pvclock.c
> >> +++ sys/dev/pv/pvclock.c
> >> @@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = {
> >>  };
> >>  
> >>  struct timecounter pvclock_timecounter = {
> >> - pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL
> >> + pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0
> >>  };
> >>  
> >>  int
> >> diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c
> >> index 9b5b8eb3acf..59bc923a6fb 100644
> >> --- sys/kern/exec_elf.c
> >> +++ sys/kern/exec_elf.c
> >> @@ -124,7 +124,7 @@ extern char *syscallnames[];
> >>  /*
> >>   * How many entries are in the AuxInfo array we pass to the process?
> >>   */
> >> -#define ELF_AUX_ENTRIES 8
> >> +#define ELF_AUX_ENTRIES 9
> >>  
> >>  /*
> >>   * This is the OpenBSD ELF emul
> >> @@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct
> >exec_package *epp)
> >>   a->au_v = ap->arg_entry;
> >>   a++;
> >>  
> >> + a->au_id = AUX_openbsd_timekeep;
> >> + a->au_v = p->p_p->ps_timekeep;
> >> + a++;
> >> +
> >>   a->au_id = AUX_null;
> >>   a->au_v = 0;
> >>   a++;
> >> diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
> >> index 20480c2fc28..222450607d5 100644
> >> --- sys/kern/kern_exec.c
> >> +++ sys/kern/kern_exec.c
> >> @@ -64,6 +64,11 @@
> >>  #include <uvm/uvm_extern.h>
> >>  #include <machine/tcb.h>
> >>  
> >> +#include <sys/timetc.h>
> >> +
> >> +struct uvm_object *timekeep_object;
> >> +struct timekeep* timekeep;
> >> +
> >>  void unveil_destroy(struct process *ps);
> >>  
> >>  const struct kmem_va_mode kv_exec = {
> >> @@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = {
> >>   */
> >>  int exec_sigcode_map(struct process *, struct emul *);
> >>  
> >> +/*
> >> + * Map the shared timekeep page.
> >> + */
> >> +int exec_timekeep_map(struct process *);
> >> +
> >>  /*
> >>   * If non-zero, stackgap_random specifies the upper limit of the
> >random gap size
> >>   * added to the fixed stack position. Must be n^2.
> >> @@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t
> >*retval)
> >>   /* map the process's signal trampoline code */
> >>   if (exec_sigcode_map(pr, pack.ep_emul))
> >>   goto free_pack_abort;
> >> + /* map the process's timekeep page */
> >> + if (exec_timekeep_map(pr))
> >> + goto free_pack_abort;
> >>  
> >>  #ifdef __HAVE_EXEC_MD_MAP
> >>   /* perform md specific mappings that process might need */
> >> @@ -863,3 +876,40 @@ exec_sigcode_map(struct process *pr, struct emul
> >*e)
> >>  
> >>   return (0);
> >>  }
> >> +
> >> +int
> >> +exec_timekeep_map(struct process *pr)
> >> +{
> >> + size_t timekeep_sz = sizeof(struct timekeep);
> >> +
> >> + /*
> >> + * Similar to the sigcode object, except that there is a single
> >> + * timekeep object, and not one per emulation.
> >> + */
> >> + if (timekeep_object == NULL) {
> >> + vaddr_t va;
> >> +
> >> + timekeep_object = uao_create(timekeep_sz, 0);
> >> + uao_reference(timekeep_object);
> >> +
> >> + if (uvm_map(kernel_map, &va, round_page(timekeep_sz),
> >timekeep_object,
> >> +    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ |
> >PROT_WRITE,
> >> +    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
> >> + uao_detach(timekeep_object);
> >> + return (ENOMEM);
> >> + }
> >> +
> >> + timekeep = (struct timekeep *)va;
> >> + timekeep->tk_version = TK_VERSION;
> >> + }
> >> +
> >> + uao_reference(timekeep_object);
> >> + if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep,
> >round_page(timekeep_sz),
> >> +    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
> >> +    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
> >> + uao_detach(timekeep_object);
> >> + return (ENOMEM);
> >> + }
> >> +
> >> + return (0);
> >> +}
> >> diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
> >> index 88d4a3379f9..47efbdd0b78 100644
> >> --- sys/kern/kern_tc.c
> >> +++ sys/kern/kern_tc.c
> >> @@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc)
> >>  }
> >>  
> >>  static struct timecounter dummy_timecounter = {
> >> - dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
> >> + dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0
> >>  };
> >>  
> >>  /*
> >> @@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts)
> >>  #endif
> >>  }
> >>  
> >> +void
> >> +tc_update_timekeep(void)
> >> +{
> >> + static struct timecounter *last_tc = NULL;
> >> + struct timehands *th;
> >> +
> >> + if (timekeep == NULL)
> >> + return;
> >> +
> >> + th = timehands;
> >> + timekeep->tk_generation = 0;
> >> + membar_producer();
> >> + timekeep->tk_scale = th->th_scale;
> >> + timekeep->tk_offset_count = th->th_offset_count;
> >> + timekeep->tk_offset = th->th_offset;
> >> + timekeep->tk_naptime = th->th_naptime;
> >> + timekeep->tk_boottime = th->th_boottime;
> >> + if (last_tc != th->th_counter) {
> >> + timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
> >> + timekeep->tk_user = th->th_counter->tc_user;
> >> + last_tc = th->th_counter;
> >> + }
> >> + membar_producer();
> >> + timekeep->tk_generation = th->th_generation;
> >> +
> >> + return;
> >> +}
> >> +
> >>  /*
> >>   * Initialize the next struct timehands in the ring and make
> >>   * it the active timehands.  Along the way we might switch to a
> >different
> >> @@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct
> >bintime *new_offset,
> >>   time_uptime = th->th_offset.sec;
> >>   membar_producer();
> >>   timehands = th;
> >> +
> >> + tc_update_timekeep();
> >>  }
> >>  
> >>  /* Report or change the active timecounter hardware. */
> >> diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h
> >> index a40e0510273..3084ed595a6 100644
> >> --- sys/sys/exec_elf.h
> >> +++ sys/sys/exec_elf.h
> >> @@ -691,7 +691,8 @@ enum AuxID {
> >>   AUX_sun_uid = 2000, /* euid */
> >>   AUX_sun_ruid = 2001, /* ruid */
> >>   AUX_sun_gid = 2002, /* egid */
> >> - AUX_sun_rgid = 2003 /* rgid */
> >> + AUX_sun_rgid = 2003, /* rgid */
> >> + AUX_openbsd_timekeep = 4000, /* userland clock_gettime */
> >>  };
> >>  
> >>  struct elf_args {
> >> diff --git sys/sys/proc.h sys/sys/proc.h
> >> index 357c0c0d52c..c6d54572bdd 100644
> >> --- sys/sys/proc.h
> >> +++ sys/sys/proc.h
> >> @@ -242,6 +242,7 @@ struct process {
> >>   char ps_comm[MAXCOMLEN+1];
> >>  
> >>   vaddr_t ps_strings; /* User pointers to argv/env */
> >> + vaddr_t ps_timekeep; /* User pointer to timekeep */
> >>   vaddr_t ps_sigcode; /* User pointer to the signal code */
> >>   vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */
> >>   u_long ps_sigcookie;
> >> diff --git sys/sys/time.h sys/sys/time.h
> >> index e758a64ce07..bcd3acd034d 100644
> >> --- sys/sys/time.h
> >> +++ sys/sys/time.h
> >> @@ -163,7 +163,7 @@ struct clockinfo {
> >>  };
> >>  #endif /* __BSD_VISIBLE */
> >>  
> >> -#if defined(_KERNEL) || defined(_STANDALONE)
> >> +#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC)
> >>  #include <sys/_time.h>
> >>  
> >>  /* Time expressed as seconds and fractions of a second + operations
> >on it. */
> >> @@ -171,6 +171,9 @@ struct bintime {
> >>   time_t sec;
> >>   uint64_t frac;
> >>  };
> >> +#endif
> >> +
> >> +#if defined(_KERNEL) || defined(_STANDALONE)
> >>  
> >>  #define bintimecmp(btp, ctp, cmp) \
> >>   ((btp)->sec == (ctp)->sec ? \
> >> diff --git sys/sys/timetc.h sys/sys/timetc.h
> >> index ce81c3475a0..c5ad27695ba 100644
> >> --- sys/sys/timetc.h
> >> +++ sys/sys/timetc.h
> >> @@ -24,10 +24,11 @@
> >>  #ifndef _SYS_TIMETC_H_
> >>  #define _SYS_TIMETC_H_
> >>  
> >> -#ifndef _KERNEL
> >> +#if !defined(_KERNEL) && !defined(_LIBC)
> >>  #error "no user-serviceable parts inside"
> >>  #endif
> >>  
> >> +#include <machine/timetc.h>
> >>  #include <sys/queue.h>
> >>  
> >>  /*-
> >> @@ -80,6 +81,8 @@ struct timecounter {
> >>   */
> >>   void *tc_priv; /* [I] */
> >>   /* Pointer to the timecounter's private parts. */
> >> + int tc_user; /* [I] */
> >> + /* Expose this timecounter to userland. */
> >>   SLIST_ENTRY(timecounter) tc_next; /* [I] */
> >>   /* Pointer to the next timecounter. */
> >>   int64_t tc_freq_adj; /* [tw] */
> >> @@ -88,11 +91,32 @@ struct timecounter {
> >>   /* Precision of the counter.  Computed in tc_init(). */
> >>  };
> >>  
> >> +struct timekeep {
> >> + /* set at initialization */
> >> + uint32_t tk_version; /* version number */
> >> +
> >> + /* timehands members */
> >> + uint64_t tk_scale;
> >> + u_int tk_offset_count;
> >> + struct bintime tk_offset;
> >> + struct bintime tk_naptime;
> >> + struct bintime tk_boottime;
> >> + volatile u_int tk_generation;
> >> +
> >> + /* timecounter members */
> >> + int tk_user;
> >> + u_int tk_counter_mask;
> >> +};
> >> +#define TK_VERSION 0
> >> +
> >>  struct rwlock;
> >>  extern struct rwlock tc_lock;
> >>  
> >>  extern struct timecounter *timecounter;
> >>  
> >> +extern struct uvm_object *timekeep_object;
> >> +extern struct timekeep *timekeep;
> >> +
> >>  u_int64_t tc_getfrequency(void);
> >>  u_int64_t tc_getprecision(void);
> >>  void tc_init(struct timecounter *tc);
> >>
>

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Paul Irofti-4


În 19 iunie 2020 23:37:28 EEST, Mark Kettenis <[hidden email]> a scris:

>> Date: Fri, 19 Jun 2020 23:16:26 +0300
>> From: Paul Irofti <[hidden email]>
>>
>> În 19 iunie 2020 22:49:32 EEST, Mark Kettenis
><[hidden email]> a scris:
>> >> Date: Fri, 19 Jun 2020 20:28:58 +0300
>> >> From: Paul Irofti <[hidden email]>
>> >>
>> >> On Fri, Jun 19, 2020 at 06:52:40PM +0200, Mark Kettenis wrote:
>> >> > > Date: Fri, 19 Jun 2020 14:31:17 +0300
>> >> > > From: Paul Irofti <[hidden email]>
>> >> > >
>> >> > > Hi,
>> >> > >
>> >> > > Here is another iteration of the diff that addresses all
>issues
>> >raised
>> >> > > in the meantime:
>> >> > >
>> >> > >   - Switch tc to uint
>> >> >
>> >> > The request was to use u_int, like we de in the kernel.  The
>uint
>> >type
>> >> > should not be used in OpenBSD code.
>> >> >
>> >> > >   - Check for version at init and switch to machite/timetc.h
>defs
>> >> > >   - Remove tk_nclocks
>> >> > >   - Switch to single version and ditch minor/major
>> >> > >   - Do not enable user TSC for large skew values
>> >> > >   - Add amd64 clocks and use the define in TSC
>> >> > >   - Include and add machine/timetc.h
>> >> > >
>> >> > > As we have seen most architectures have support for clocks now
>> >and the
>> >> > > above addresses Mark's last concerns.
>> >> > >
>> >> > > Unless other blocking issues arise, this time around I am
>looking
>> >for
>> >> > > OKs to commit. Theo? Mark?
>> >> >
>> >> > There is one other issue that I wanted to raise.  An that is
>> >whether
>> >> > we really need to implement CLOCK_UPTINME as a userland clock.
>If
>> >we
>> >> > don't do that we can drop tk_naptime from the shared struct.  I
>> >> > mention this because th_naptime was only recently added to
>struct
>> >> > timehands and much more an implementation detail than the other
>> >fields.
>> >> >
>> >> > I don't expect userland processes to call CLOCK_UPTIME in a loop
>> >like
>> >> > they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.
>Linux
>> >> > doesn't have it ;).
>> >>
>> >> I don't care eitherway about this. But I don't see why we would
>not
>> >have
>> >> this functionality if it is easy to offer. Maybe someone can help
>us
>> >> grep the ports tree for this? Stuart? :)
>> >>
>> >> > We're getting there...
>> >>
>> >> I have addressed your comments bellow, except for the CPU skew
>one.
>> >That
>> >> code disables TSC for all CPUs, not just for PRIMARY. Would you
>like
>> >to
>> >> walk and add code for every CPU to check the drift and then
>disable
>> >the
>> >> TSC? It seems a little too much...
>> >
>> >Still uses uint instead of u_int in places.
>>
>> Ok. I will check that again.
>>
>> > Still has the pointless
>> >extra NULL and 0 for timecounters in files that are otherwise
>>
>> I am not fixing that. If there's a null present before my diff, then
>> there can be a 0 afterwards. If anything my diff unifies this. This
>> is silly.
>
>I'll let others judge that.
>
>> >And regarding the TSC.  That issue is a show-stopper.  We can
>tolerate
>> >a small amout of skew, but not a large amount.  Because otherwise a
>> >multithreaded process might observe time going backwards.
>>
>> I don't see how this is still an issue with my diff, which is what I
>> said last time. I am stopping the TSC when the drift is larger than
>> a random value that I defined a year ago. What more is needed? Can
>> you describe in more details?
>
>I'm talking about *skew*, not drift.  If there is a significant drift
>you already knock out the TSC.
>
>What's needed is:
>
>1. A bit of research of what an acceptable skew is.  My hypothesis is
>   that on many machines with a single socket the TSCs are actually in
>   synch.  But the way we measure the skew isn't 100% accurate so we
>   still get a small skew.  If we sample these values on a couple of
>   machines across a couple of reboots we can probably tell what the
>   uncertainty in the measurement of the skew is and define a cutoff
>   based on that.
>
>2. When the absolute value of ci->ci_tsc_skew is above this cutoff for
>   any CPU, you set tsc_timecounter.tc_user to zero.  I think you can
>   do that check in tsc_timecounter_init() but I'm not 100% sure.
>

Ok. I understand. I will not do that. If somebody wants to,  please let us know and continue this discussion with Kettenis until he is satisfied.

If the consensus is that this is a blocking issue and nobody wants to step up and do it, then consider the diff abandoned.

>
>> >> diff --git lib/libc/arch/aarch64/gen/Makefile.inc
>> >lib/libc/arch/aarch64/gen/Makefile.inc
>> >> index a7b1b73f3ef..ee198f5d611 100644
>> >> --- lib/libc/arch/aarch64/gen/Makefile.inc
>> >> +++ lib/libc/arch/aarch64/gen/Makefile.inc
>> >> @@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
>> >>  SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
>> >>  SRCS+= fpclassifyl.c
>> >>  SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
>> >> -SRCS+= signbitl.c
>> >> +SRCS+= signbitl.c usertc.c
>> >> diff --git lib/libc/arch/aarch64/gen/usertc.c
>> >lib/libc/arch/aarch64/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/aarch64/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/alpha/gen/Makefile.inc
>> >lib/libc/arch/alpha/gen/Makefile.inc
>> >> index a44599d2cab..2a8abd32b61 100644
>> >> --- lib/libc/arch/alpha/gen/Makefile.inc
>> >> +++ lib/libc/arch/alpha/gen/Makefile.inc
>> >> @@ -3,5 +3,5 @@
>> >>  
>> >>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
>> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>> >fpsetmask.c \
>> >> - fpsetround.c fpsetsticky.c
>> >> + fpsetround.c fpsetsticky.c usertc.c
>> >>  SRCS+= sigsetjmp.S
>> >> diff --git lib/libc/arch/alpha/gen/usertc.c
>> >lib/libc/arch/alpha/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/alpha/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/amd64/gen/Makefile.inc
>> >lib/libc/arch/amd64/gen/Makefile.inc
>> >> index e995309ed71..f6349e2b974 100644
>> >> --- lib/libc/arch/amd64/gen/Makefile.inc
>> >> +++ lib/libc/arch/amd64/gen/Makefile.inc
>> >> @@ -2,6 +2,7 @@
>> >>  
>> >>  SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S
>\
>> >>   sigsetjmp.S
>> >> -SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>> >signbitl.c
>> >> +SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>> >signbitl.c \
>> >> + usertc.c
>> >>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S
>> >fpsetmask.S \
>> >>   fpsetround.S fpsetsticky.S
>> >> diff --git lib/libc/arch/amd64/gen/usertc.c
>> >lib/libc/arch/amd64/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..742fb0cc458
>> >> --- /dev/null
>> >> +++ lib/libc/arch/amd64/gen/usertc.c
>> >> @@ -0,0 +1,41 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +static inline uint
>> >> +rdtsc(void)
>> >> +{
>> >> + uint32_t hi, lo;
>> >> + asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
>> >> + return ((uint64_t)lo)|(((uint64_t)hi)<<32);
>> >> +}
>> >> +
>> >> +int
>> >> +tc_get_timecount(struct timekeep *tk, u_int *tc)
>> >> +{
>> >> + int tk_user = tk->tk_user;
>> >> +
>> >> + if (tk_user < 1 || tk_user >= TC_LAST)
>> >> + return -1;
>> >> +
>> >> + *tc = rdtsc();
>> >> + return 0;
>> >> +}
>> >> +int (*const _tc_get_timecount)(struct timekeep *tk, u_int *tc)
>> >> + = tc_get_timecount;
>> >> diff --git lib/libc/arch/arm/gen/Makefile.inc
>> >lib/libc/arch/arm/gen/Makefile.inc
>> >> index 1b4ab2f3ae7..27090a0d9dc 100644
>> >> --- lib/libc/arch/arm/gen/Makefile.inc
>> >> +++ lib/libc/arch/arm/gen/Makefile.inc
>> >> @@ -2,5 +2,5 @@
>> >>  # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
>> >>  
>> >>  SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c
>> >infinity.c
>> >> -SRCS+= ldexp.c modf.c nan.c
>> >> +SRCS+= ldexp.c modf.c nan.c usertc.c
>> >>  SRCS+= setjmp.S _setjmp.S sigsetjmp.S
>> >> diff --git lib/libc/arch/arm/gen/usertc.c
>> >lib/libc/arch/arm/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/arm/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/hppa/gen/Makefile.inc
>> >lib/libc/arch/hppa/gen/Makefile.inc
>> >> index e0c864242fe..1fde24670f1 100644
>> >> --- lib/libc/arch/hppa/gen/Makefile.inc
>> >> +++ lib/libc/arch/hppa/gen/Makefile.inc
>> >> @@ -2,6 +2,6 @@
>> >>  
>> >>  SRCS+= setjmp.S
>> >>  SRCS+= fabs.c
>> >> -SRCS+= infinity.c ldexp.c modf.c nan.c
>> >> +SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
>> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>> >fpsetmask.c \
>> >>   fpsetround.c fpsetsticky.c
>> >> diff --git lib/libc/arch/hppa/gen/usertc.c
>> >lib/libc/arch/hppa/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/hppa/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/i386/gen/Makefile.inc
>> >lib/libc/arch/i386/gen/Makefile.inc
>> >> index 4c18e059581..b7dd30adccd 100644
>> >> --- lib/libc/arch/i386/gen/Makefile.inc
>> >> +++ lib/libc/arch/i386/gen/Makefile.inc
>> >> @@ -1,6 +1,6 @@
>> >>  # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
>> >>  
>> >> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
>> >> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
>> >>   modf.S nan.c setjmp.S sigsetjmp.S
>> >>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>> >signbitl.c
>> >>  SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S
>> >fpsetmask.S \
>> >> diff --git lib/libc/arch/i386/gen/usertc.c
>> >lib/libc/arch/i386/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/i386/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/m88k/gen/Makefile.inc
>> >lib/libc/arch/m88k/gen/Makefile.inc
>> >> index cff75b8d425..d66f66af4af 100644
>> >> --- lib/libc/arch/m88k/gen/Makefile.inc
>> >> +++ lib/libc/arch/m88k/gen/Makefile.inc
>> >> @@ -1,7 +1,7 @@
>> >>  # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
>> >>  # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
>> >>  
>> >> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
>> >> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
>> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>> >fpsetmask.c \
>> >>   fpsetround.c fpsetsticky.c
>> >>  SRCS+= setjmp.S sigsetjmp.S
>> >> diff --git lib/libc/arch/m88k/gen/usertc.c
>> >lib/libc/arch/m88k/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/m88k/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/mips64/gen/Makefile.inc
>> >lib/libc/arch/mips64/gen/Makefile.inc
>> >> index 8cf1fc2d28a..839241a2069 100644
>> >> --- lib/libc/arch/mips64/gen/Makefile.inc
>> >> +++ lib/libc/arch/mips64/gen/Makefile.inc
>> >> @@ -1,6 +1,6 @@
>> >>  # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
>> >>  
>> >> -SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
>> >> +SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
>> >>  SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c
>> >fpsetmask.c \
>> >>   fpsetround.c fpsetsticky.c
>> >>  SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c
>> >signbitl.c
>> >> diff --git lib/libc/arch/mips64/gen/usertc.c
>> >lib/libc/arch/mips64/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/mips64/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/powerpc/gen/Makefile.inc
>> >lib/libc/arch/powerpc/gen/Makefile.inc
>> >> index 6b2e4613ee8..d4d7b00bff7 100644
>> >> --- lib/libc/arch/powerpc/gen/Makefile.inc
>> >> +++ lib/libc/arch/powerpc/gen/Makefile.inc
>> >> @@ -1,5 +1,5 @@
>> >>  SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c
>modf.c
>> >nan.c
>> >> -SRCS+= fabs.c
>> >> +SRCS+= fabs.c usertc.c
>> >>  SRCS+= fpgetmask.c fpsetmask.c
>> >>  SRCS+= fpgetround.c fpsetround.c
>> >>  SRCS+= fpgetsticky.c fpsetsticky.c
>> >> diff --git lib/libc/arch/powerpc/gen/usertc.c
>> >lib/libc/arch/powerpc/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/powerpc/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/sh/gen/Makefile.inc
>> >lib/libc/arch/sh/gen/Makefile.inc
>> >> index 55de1973b30..4724fb3a6a8 100644
>> >> --- lib/libc/arch/sh/gen/Makefile.inc
>> >> +++ lib/libc/arch/sh/gen/Makefile.inc
>> >> @@ -3,4 +3,4 @@
>> >>  SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S
>> >_setjmp.S
>> >>  SRCS+= sigsetjmp.S
>> >>  SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
>> >> - fpsetmask.c fpsetround.c fpsetsticky.c
>> >> + fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
>> >> diff --git lib/libc/arch/sh/gen/usertc.c
>> >lib/libc/arch/sh/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/sh/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/arch/sparc64/gen/Makefile.inc
>> >lib/libc/arch/sparc64/gen/Makefile.inc
>> >> index 58259cedef6..a908e022954 100644
>> >> --- lib/libc/arch/sparc64/gen/Makefile.inc
>> >> +++ lib/libc/arch/sparc64/gen/Makefile.inc
>> >> @@ -3,5 +3,5 @@
>> >>  SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
>> >>   fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
>> >>   fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
>> >> - isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
>> >> + isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
>> >>   mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
>> >> diff --git lib/libc/arch/sparc64/gen/usertc.c
>> >lib/libc/arch/sparc64/gen/usertc.c
>> >> new file mode 100644
>> >> index 00000000000..6551854a010
>> >> --- /dev/null
>> >> +++ lib/libc/arch/sparc64/gen/usertc.c
>> >> @@ -0,0 +1,21 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >> + */
>> >> +
>> >> +#include <sys/types.h>
>> >> +#include <sys/timetc.h>
>> >> +
>> >> +int (*const _tc_get_timecount)(struct timekeep *, u_int *) =
>NULL;
>> >> diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
>> >> index 131da4b2190..40e84771f86 100644
>> >> --- lib/libc/asr/asr.c
>> >> +++ lib/libc/asr/asr.c
>> >> @@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t
>nfds,
>> >int timeout)
>> >>   struct timespec pollstart, pollend, elapsed;
>> >>   int r;
>> >>  
>> >> - if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
>> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
>> >>   return -1;
>> >>  
>> >>   while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
>> >> - if (clock_gettime(CLOCK_MONOTONIC, &pollend))
>> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
>> >>   return -1;
>> >>   timespecsub(&pollend, &pollstart, &elapsed);
>> >>   timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
>> >> @@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
>> >>   asr->a_rtime = 0;
>> >>   }
>> >>  
>> >> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
>> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>> >>   return;
>> >>  
>> >>   if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime !=
>0)
>> >> diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
>> >> index 82de8fa33b7..02fd3013cc1 100644
>> >> --- lib/libc/crypt/bcrypt.c
>> >> +++ lib/libc/crypt/bcrypt.c
>> >> @@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
>> >>   char buf[_PASSWORD_LEN];
>> >>   int duration;
>> >>  
>> >> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
>> >> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
>> >>   bcrypt_newhash("testpassword", r, buf, sizeof(buf));
>> >> - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
>> >> + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
>> >>  
>> >>   duration = after.tv_sec - before.tv_sec;
>> >>   duration *= 1000000;
>> >> diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
>> >> index 270f54aada5..d2632455f11 100644
>> >> --- lib/libc/dlfcn/init.c
>> >> +++ lib/libc/dlfcn/init.c
>> >> @@ -20,6 +20,7 @@
>> >>  
>> >>  #include <sys/types.h>
>> >>  #include <sys/syscall.h>
>> >> +#include <sys/timetc.h> /* timekeep */
>> >>  
>> >>  #ifndef PIC
>> >>  #include <sys/mman.h>
>> >> @@ -45,8 +46,9 @@
>> >>  /* XXX should be in an include file shared with csu */
>> >>  char ***_csu_finish(char **_argv, char **_envp, void
>> >(*_cleanup)(void));
>> >>  
>> >> -/* provide definition for this */
>> >> +/* provide definitions for these */
>> >>  int _pagesize = 0;
>> >> +struct timekeep *_timekeep;
>> >>  
>> >>  /*
>> >>   * In dynamicly linked binaries environ and __progname are
>overriden
>> >by
>> >> @@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char
>> >**envp, dl_cb_cb *cb)
>> >>   phnum = aux->au_v;
>> >>   break;
>> >>  #endif /* !PIC */
>> >> + case AUX_openbsd_timekeep:
>> >> + if (_tc_get_timecount) {
>> >> + _timekeep = (void *)aux->au_v;
>> >> + if (_timekeep->tk_version != TK_VERSION)
>> >> + _timekeep = NULL;
>> >> + }
>> >> + break;
>> >>   }
>> >>   }
>> >>  
>> >> diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
>> >> index 1286a96fe40..32f86eda50f 100644
>> >> --- lib/libc/gen/auth_subr.c
>> >> +++ lib/libc/gen/auth_subr.c
>> >> @@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
>> >>  
>> >>   if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
>> >>   if (as->now.tv_sec == 0)
>> >> - gettimeofday(&as->now, NULL);
>> >> + WRAP(gettimeofday)(&as->now, NULL);
>> >>   if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
>> >>   as->state &= ~AUTH_ALLOW;
>> >>   as->state |= AUTH_EXPIRED;
>> >> @@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
>> >>  
>> >>   if (as->pwd && (quad_t)as->pwd->pw_change) {
>> >>   if (as->now.tv_sec == 0)
>> >> - gettimeofday(&as->now, NULL);
>> >> + WRAP(gettimeofday)(&as->now, NULL);
>> >>   if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
>> >>   as->state &= ~AUTH_ALLOW;
>> >>   as->state |= AUTH_PWEXPIRED;
>> >> diff --git lib/libc/gen/time.c lib/libc/gen/time.c
>> >> index 3bbd0d733d1..b3ce9a800f1 100644
>> >> --- lib/libc/gen/time.c
>> >> +++ lib/libc/gen/time.c
>> >> @@ -36,7 +36,7 @@ time(time_t *t)
>> >>  {
>> >>   struct timeval tt;
>> >>  
>> >> - if (gettimeofday(&tt, NULL) == -1)
>> >> + if (WRAP(gettimeofday)(&tt, NULL) == -1)
>> >>   return (-1);
>> >>   if (t)
>> >>   *t = (time_t)tt.tv_sec;
>> >> diff --git lib/libc/gen/times.c lib/libc/gen/times.c
>> >> index 02e4dd44b5c..36841810d1b 100644
>> >> --- lib/libc/gen/times.c
>> >> +++ lib/libc/gen/times.c
>> >> @@ -52,7 +52,7 @@ times(struct tms *tp)
>> >>   return ((clock_t)-1);
>> >>   tp->tms_cutime = CONVTCK(ru.ru_utime);
>> >>   tp->tms_cstime = CONVTCK(ru.ru_stime);
>> >> - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
>> >> + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
>> >>   return ((clock_t)-1);
>> >>   return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 /
>CLK_TCK));
>> >>  }
>> >> diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
>> >> index 520a5954025..845cbe80356 100644
>> >> --- lib/libc/gen/timespec_get.c
>> >> +++ lib/libc/gen/timespec_get.c
>> >> @@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
>> >>  {
>> >>   switch (base) {
>> >>   case TIME_UTC:
>> >> - if (clock_gettime(CLOCK_REALTIME, ts) == -1)
>> >> + if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
>> >>   return 0;
>> >>   break;
>> >>   default:
>> >> diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
>> >> index ed112320fa2..df717021cab 100644
>> >> --- lib/libc/hidden/sys/time.h
>> >> +++ lib/libc/hidden/sys/time.h
>> >> @@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
>> >>  PROTO_NORMAL(adjtime);
>> >>  PROTO_NORMAL(futimes);
>> >>  PROTO_NORMAL(getitimer);
>> >> -PROTO_NORMAL(gettimeofday);
>> >> +PROTO_WRAP(gettimeofday);
>> >>  PROTO_NORMAL(setitimer);
>> >>  PROTO_NORMAL(settimeofday);
>> >>  PROTO_NORMAL(utimes);
>> >> diff --git lib/libc/hidden/sys/timetc.h
>lib/libc/hidden/sys/timetc.h
>> >> new file mode 100644
>> >> index 00000000000..bbdaa2d0d4c
>> >> --- /dev/null
>> >> +++ lib/libc/hidden/sys/timetc.h
>> >> @@ -0,0 +1,38 @@
>> >> +/* $OpenBSD$ */
>> >> +/*
>> >> + * Copyright (c) 2020 Paul Irofti <[hidden email]>
>> >> + *
>> >> + * Permission to use, copy, modify, and distribute this software
>for
>> >any
>> >> + * purpose with or without fee is hereby granted, provided that
>the
>> >above
>> >> + * copyright notice and this permission notice appear in all
>copies.
>> >> + *
>> >> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
>> >WARRANTIES
>> >> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
>OF
>> >> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
>> >LIABLE FOR
>> >> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
>> >DAMAGES
>> >> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
>WHETHER
>> >IN AN
>> >> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
>ARISING
>> >OUT OF
>> >> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> >

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Stuart Henderson
In reply to this post by Paul Irofti-4
On 2020/06/19 20:28, Paul Irofti wrote:
> On Fri, Jun 19, 2020 at 06:52:40PM +0200, Mark Kettenis wrote:
> > I don't expect userland processes to call CLOCK_UPTIME in a loop like
> > they tend to do do for CLOCK_MONOTONIC and CLOCK_REALTIME.  Linux
> > doesn't have it ;).
>
> I don't care eitherway about this. But I don't see why we would not have
> this functionality if it is easy to offer. Maybe someone can help us
> grep the ports tree for this? Stuart? :)

I don't have time to run a grep at the moment but have looked at
https://codesearch.debian.net/search?q=CLOCK_UPTIME&literal=1 which
I think is good enough to show anything important. Most occurrences
are constants in languages. There are a couple of small uses in
code but not much e.g.

https://sources.debian.org/src/rsyslog/8.2004.0-1/runtime/msg.c/?hl=3857#L3857
https://sources.debian.org/src/mactelnet/0.4.4-4/src/mactelnetd.c/?hl=837#L837

The important ones are gettimeofday/CLOCK_MONOTONIC and to a lesser
extent CLOCK_REALTIME.

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Scott Cheloha
In reply to this post by Paul Irofti-4
> On Jun 19, 2020, at 12:40, Paul Irofti <[hidden email]> wrote:
>
> [...]
>
> +
> +static inline void
> +bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct)
> +{
> +    ct->sec = bt->sec;
> +    if (bt->frac > bt->frac + x)
> +        ct->sec++;
> +    ct->frac = bt->frac + x;
> +}
> +
> +static inline void
> +BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts)
> +{
> +    ts->tv_sec = bt->sec;
> +    ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32);
> +}
> +
> +static inline void
> +BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv)
> +{
> +    tv->tv_sec = bt->sec;
> +    tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32);
> +}

Is it possible to use the definitions in
sys/time.h for these?

> +
> +static inline void
> +bintimeadd(const struct bintime *bt, const struct bintime *ct,
> +    struct bintime *dt)
> +{
> +    dt->sec = bt->sec + ct->sec;
> +    if (bt->frac > bt->frac + ct->frac)
> +        dt->sec++;
> +    dt->frac = bt->frac + ct->frac;
> +}
> +
> +static inline void
> +bintimesub(const struct bintime *bt, const struct bintime *ct,
> +    struct bintime *dt)
> +{
> +    dt->sec = bt->sec - ct->sec;
> +    if (bt->frac < bt->frac - ct->frac)
> +        dt->sec--;
> +    dt->frac = bt->frac - ct->frac;
> +}

Same thing here.

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Christian Weisgerber
In reply to this post by Mark Kettenis
On 2020-06-19, Mark Kettenis <[hidden email]> wrote:

> I'm talking about *skew*, not drift.  If there is a significant drift
> you already knock out the TSC.
>
> What's needed is:
>
> 1. A bit of research of what an acceptable skew is.  My hypothesis is
>    that on many machines with a single socket the TSCs are actually in
>    synch.  But the way we measure the skew isn't 100% accurate so we
>    still get a small skew.  If we sample these values on a couple of
>    machines across a couple of reboots we can probably tell what the
>    uncertainty in the measurement of the skew is and define a cutoff
>    based on that.

So we need amd64 snapshots to enable TSC_DEBUG, maybe a bit prettier
like below, and then reports:

cpu0: Intel(R) Xeon(R) CPU E3-1225 v3 @ 3.20GHz, 3392.69 MHz, 06-3c-03

cpu0: TSC skew=0 observed drift=0
cpu1: TSC skew=-24 observed drift=0
cpu2: TSC skew=-27 observed drift=0
cpu3: TSC skew=-25 observed drift=0

cpu0: TSC skew=0 observed drift=0
cpu1: TSC skew=-1 observed drift=0
cpu2: TSC skew=0 observed drift=0
cpu3: TSC skew=25 observed drift=0

cpu0: TSC skew=0 observed drift=0
cpu1: TSC skew=-30 observed drift=0
cpu2: TSC skew=-39 observed drift=0
cpu3: TSC skew=-41 observed drift=0

cpu0: TSC skew=0 observed drift=0
cpu1: TSC skew=-31 observed drift=0
cpu2: TSC skew=-37 observed drift=0
cpu3: TSC skew=-39 observed drift=0

cpu0: TSC skew=0 observed drift=0
cpu1: TSC skew=-31 observed drift=0
cpu2: TSC skew=-34 observed drift=0
cpu3: TSC skew=-23 observed drift=0


Index: sys/arch/amd64/amd64/tsc.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/tsc.c,v
retrieving revision 1.16
diff -u -p -r1.16 tsc.c
--- sys/arch/amd64/amd64/tsc.c 6 Apr 2020 00:01:08 -0000 1.16
+++ sys/arch/amd64/amd64/tsc.c 19 Jun 2020 23:49:06 -0000
@@ -217,7 +217,7 @@ void
 tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
 {
 #ifdef TSC_DEBUG
- printf("%s: TSC skew=%lld observed drift=%lld\n", __func__,
+ printf("%s: TSC skew=%lld observed drift=%lld\n", ci->ci_dev->dv_xname,
     (long long)ci->ci_tsc_skew, (long long)tsc_drift_observed);
 #endif
 
--
Christian "naddy" Weisgerber                          [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Mark Kettenis
> From: Christian Weisgerber <[hidden email]>
> Date: Sat, 20 Jun 2020 01:20:33 -0000 (UTC)
>
> On 2020-06-19, Mark Kettenis <[hidden email]> wrote:
>
> > I'm talking about *skew*, not drift.  If there is a significant drift
> > you already knock out the TSC.
> >
> > What's needed is:
> >
> > 1. A bit of research of what an acceptable skew is.  My hypothesis is
> >    that on many machines with a single socket the TSCs are actually in
> >    synch.  But the way we measure the skew isn't 100% accurate so we
> >    still get a small skew.  If we sample these values on a couple of
> >    machines across a couple of reboots we can probably tell what the
> >    uncertainty in the measurement of the skew is and define a cutoff
> >    based on that.
>
> So we need amd64 snapshots to enable TSC_DEBUG, maybe a bit prettier
> like below, and then reports:
>
> cpu0: Intel(R) Xeon(R) CPU E3-1225 v3 @ 3.20GHz, 3392.69 MHz, 06-3c-03
>
> cpu0: TSC skew=0 observed drift=0
> cpu1: TSC skew=-24 observed drift=0
> cpu2: TSC skew=-27 observed drift=0
> cpu3: TSC skew=-25 observed drift=0
>
> cpu0: TSC skew=0 observed drift=0
> cpu1: TSC skew=-1 observed drift=0
> cpu2: TSC skew=0 observed drift=0
> cpu3: TSC skew=25 observed drift=0
>
> cpu0: TSC skew=0 observed drift=0
> cpu1: TSC skew=-30 observed drift=0
> cpu2: TSC skew=-39 observed drift=0
> cpu3: TSC skew=-41 observed drift=0
>
> cpu0: TSC skew=0 observed drift=0
> cpu1: TSC skew=-31 observed drift=0
> cpu2: TSC skew=-37 observed drift=0
> cpu3: TSC skew=-39 observed drift=0
>
> cpu0: TSC skew=0 observed drift=0
> cpu1: TSC skew=-31 observed drift=0
> cpu2: TSC skew=-34 observed drift=0
> cpu3: TSC skew=-23 observed drift=0

Yes, enabling that for a bit would help us get an idea.  We probably
should have it print the TSC frequency as well though.

> Index: sys/arch/amd64/amd64/tsc.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/amd64/tsc.c,v
> retrieving revision 1.16
> diff -u -p -r1.16 tsc.c
> --- sys/arch/amd64/amd64/tsc.c 6 Apr 2020 00:01:08 -0000 1.16
> +++ sys/arch/amd64/amd64/tsc.c 19 Jun 2020 23:49:06 -0000
> @@ -217,7 +217,7 @@ void
>  tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
>  {
>  #ifdef TSC_DEBUG
> - printf("%s: TSC skew=%lld observed drift=%lld\n", __func__,
> + printf("%s: TSC skew=%lld observed drift=%lld\n", ci->ci_dev->dv_xname,
>      (long long)ci->ci_tsc_skew, (long long)tsc_drift_observed);
>  #endif
>  
> --
> Christian "naddy" Weisgerber                          [hidden email]
>
>

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Christian Weisgerber
In reply to this post by Paul Irofti-4
On 2020-06-19, Paul Irofti <[hidden email]> wrote:

> I have addressed your comments bellow, except for the CPU skew one. That
> code disables TSC for all CPUs, not just for PRIMARY. Would you like to
> walk and add code for every CPU to check the drift and then disable the
> TSC? It seems a little too much...
>
> [diff]

I can't get this revision of the diff to work on amd64:
* patch source
* build and install kernel, reboot
* make build
* reboot -> "Process (pid 1) got signal 11"

I'm at a loss.  As part of the "make build", the new libc is installed
and dynamically linked programs should already be using the userland
gettime calls.  Clearly this works.  So why does init fail on the
next reboot?

--
Christian "naddy" Weisgerber                          [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Mark Kettenis
> From: Christian Weisgerber <[hidden email]>
> Date: Sat, 20 Jun 2020 19:57:06 -0000 (UTC)
>
> On 2020-06-19, Paul Irofti <[hidden email]> wrote:
>
> > I have addressed your comments bellow, except for the CPU skew one. That
> > code disables TSC for all CPUs, not just for PRIMARY. Would you like to
> > walk and add code for every CPU to check the drift and then disable the
> > TSC? It seems a little too much...
> >
> > [diff]
>
> I can't get this revision of the diff to work on amd64:
> * patch source
> * build and install kernel, reboot
> * make build
> * reboot -> "Process (pid 1) got signal 11"
>
> I'm at a loss.  As part of the "make build", the new libc is installed
> and dynamically linked programs should already be using the userland
> gettime calls.  Clearly this works.  So why does init fail on the
> next reboot?

Do other static binaries work after your make build finishes?

Maybe this is because the _timekeep = NULL -> _timekeep change I
suggested that Paul added?

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Christian Weisgerber
In reply to this post by Christian Weisgerber
On 2020-06-20, Christian Weisgerber <[hidden email]> wrote:

> I can't get this revision of the diff to work on amd64:
> * patch source
> * build and install kernel, reboot
> * make build
> * reboot -> "Process (pid 1) got signal 11"
>
> I'm at a loss.  As part of the "make build", the new libc is installed
> and dynamically linked programs should already be using the userland
> gettime calls.  Clearly this works.  So why does init fail on the
> next reboot?

I can recover by extracting ./sbin/init from a snapshot in the
installer.  After that, the system comes up fine in multiuser mode.
Nothing else appears to be affected, apart from init.

For a while, I had a reproducible situation.

When you call init(8) as a normal user in multiuser mode, it will
just exit with "init: Operation not permitted".  Instead it would
segfault!  I kept tweaking lib/libc/dlfcn/init.c, rebuilding and
reinstalling libc.a, rebuilding init, and watching it segfault.
None of the debug write(2)s I inserted would produce any output,
it seemed to die before ever reaching _libc_preinit().  I finally
ktraced it:

 12420 ktrace   RET   ktrace 0
 12420 ktrace   CALL  execve(0x7f7ffffec412,0x7f7ffffec298,0x7f7ffffec2a8)
 12420 ktrace   NAMI  "./obj/init"
 12420 ktrace   ARGS  
        [0] = "./obj/init"
 12420 init     RET   execve 0
 12420 init     PSIG  SIGSEGV SIG_DFL code SEGV_MAPERR<1> addr=0x0 trapno=6
 12420 init     NAMI  "init.core"

There's not even a kbind(2) there.

Then I removed the clearly useless debug write()s... and since then
I have a hard time reproducing the problem.

It doesn't make any sense.

--
Christian "naddy" Weisgerber                          [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: userland clock_gettime proof of concept

Paul Irofti-4
In reply to this post by Paul Irofti-4
Hi,

New iteration that addresses the issues raised by Scott and Mark.

  a) Use sys/time.h defs by adding _LIBC
  b) Revert _timekeep init (breaks naddy@'s machine)
  c) Add TSC_SKEW_MAX thresholding when enabling tc_user
  d) uint->u_int

Item c) adds the code needed for what Mark requested. The value is
randomly set at 1,000. As I said earlier I won't do the "research" for
this number, but I see a couple other people started to look into it and
are discussing with Mark. Good.

Paul


diff --git lib/libc/arch/aarch64/gen/Makefile.inc lib/libc/arch/aarch64/gen/Makefile.inc
index a7b1b73f3ef..ee198f5d611 100644
--- lib/libc/arch/aarch64/gen/Makefile.inc
+++ lib/libc/arch/aarch64/gen/Makefile.inc
@@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c
 SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c
 SRCS+= fpclassifyl.c
 SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c
-SRCS+= signbitl.c
+SRCS+= signbitl.c usertc.c
diff --git lib/libc/arch/aarch64/gen/usertc.c lib/libc/arch/aarch64/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/aarch64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/alpha/gen/Makefile.inc lib/libc/arch/alpha/gen/Makefile.inc
index a44599d2cab..2a8abd32b61 100644
--- lib/libc/arch/alpha/gen/Makefile.inc
+++ lib/libc/arch/alpha/gen/Makefile.inc
@@ -3,5 +3,5 @@
 
 SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
- fpsetround.c fpsetsticky.c
+ fpsetround.c fpsetsticky.c usertc.c
 SRCS+= sigsetjmp.S
diff --git lib/libc/arch/alpha/gen/usertc.c lib/libc/arch/alpha/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/alpha/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/amd64/gen/Makefile.inc lib/libc/arch/amd64/gen/Makefile.inc
index e995309ed71..f6349e2b974 100644
--- lib/libc/arch/amd64/gen/Makefile.inc
+++ lib/libc/arch/amd64/gen/Makefile.inc
@@ -2,6 +2,7 @@
 
 SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
  sigsetjmp.S
-SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
+SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \
+ usertc.c
 SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
  fpsetround.S fpsetsticky.S
diff --git lib/libc/arch/amd64/gen/usertc.c lib/libc/arch/amd64/gen/usertc.c
new file mode 100644
index 00000000000..56016c8eca1
--- /dev/null
+++ lib/libc/arch/amd64/gen/usertc.c
@@ -0,0 +1,41 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+static inline u_int
+rdtsc(void)
+{
+ uint32_t hi, lo;
+ asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((uint64_t)lo)|(((uint64_t)hi)<<32);
+}
+
+int
+tc_get_timecount(struct timekeep *tk, u_int *tc)
+{
+ int tk_user = tk->tk_user;
+
+ if (tk_user < 1 || tk_user >= TC_LAST)
+ return -1;
+
+ *tc = rdtsc();
+ return 0;
+}
+int (*const _tc_get_timecount)(struct timekeep *tk, u_int *tc)
+ = tc_get_timecount;
diff --git lib/libc/arch/arm/gen/Makefile.inc lib/libc/arch/arm/gen/Makefile.inc
index 1b4ab2f3ae7..27090a0d9dc 100644
--- lib/libc/arch/arm/gen/Makefile.inc
+++ lib/libc/arch/arm/gen/Makefile.inc
@@ -2,5 +2,5 @@
 # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $
 
 SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c infinity.c
-SRCS+= ldexp.c modf.c nan.c
+SRCS+= ldexp.c modf.c nan.c usertc.c
 SRCS+= setjmp.S _setjmp.S sigsetjmp.S
diff --git lib/libc/arch/arm/gen/usertc.c lib/libc/arch/arm/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/arm/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/hppa/gen/Makefile.inc lib/libc/arch/hppa/gen/Makefile.inc
index e0c864242fe..1fde24670f1 100644
--- lib/libc/arch/hppa/gen/Makefile.inc
+++ lib/libc/arch/hppa/gen/Makefile.inc
@@ -2,6 +2,6 @@
 
 SRCS+= setjmp.S
 SRCS+= fabs.c
-SRCS+= infinity.c ldexp.c modf.c nan.c
+SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
diff --git lib/libc/arch/hppa/gen/usertc.c lib/libc/arch/hppa/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/hppa/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/i386/gen/Makefile.inc lib/libc/arch/i386/gen/Makefile.inc
index 4c18e059581..b7dd30adccd 100644
--- lib/libc/arch/i386/gen/Makefile.inc
+++ lib/libc/arch/i386/gen/Makefile.inc
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
  modf.S nan.c setjmp.S sigsetjmp.S
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
 SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
diff --git lib/libc/arch/i386/gen/usertc.c lib/libc/arch/i386/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/i386/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/m88k/gen/Makefile.inc lib/libc/arch/m88k/gen/Makefile.inc
index cff75b8d425..d66f66af4af 100644
--- lib/libc/arch/m88k/gen/Makefile.inc
+++ lib/libc/arch/m88k/gen/Makefile.inc
@@ -1,7 +1,7 @@
 # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $
 # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
 SRCS+= setjmp.S sigsetjmp.S
diff --git lib/libc/arch/m88k/gen/usertc.c lib/libc/arch/m88k/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/m88k/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/mips64/gen/Makefile.inc lib/libc/arch/mips64/gen/Makefile.inc
index 8cf1fc2d28a..839241a2069 100644
--- lib/libc/arch/mips64/gen/Makefile.inc
+++ lib/libc/arch/mips64/gen/Makefile.inc
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
diff --git lib/libc/arch/mips64/gen/usertc.c lib/libc/arch/mips64/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/mips64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/powerpc/gen/Makefile.inc lib/libc/arch/powerpc/gen/Makefile.inc
index 6b2e4613ee8..d4d7b00bff7 100644
--- lib/libc/arch/powerpc/gen/Makefile.inc
+++ lib/libc/arch/powerpc/gen/Makefile.inc
@@ -1,5 +1,5 @@
 SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c nan.c
-SRCS+= fabs.c
+SRCS+= fabs.c usertc.c
 SRCS+= fpgetmask.c fpsetmask.c
 SRCS+= fpgetround.c fpsetround.c
 SRCS+= fpgetsticky.c fpsetsticky.c
diff --git lib/libc/arch/powerpc/gen/usertc.c lib/libc/arch/powerpc/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/powerpc/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/sh/gen/Makefile.inc lib/libc/arch/sh/gen/Makefile.inc
index 55de1973b30..4724fb3a6a8 100644
--- lib/libc/arch/sh/gen/Makefile.inc
+++ lib/libc/arch/sh/gen/Makefile.inc
@@ -3,4 +3,4 @@
 SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S _setjmp.S
 SRCS+= sigsetjmp.S
 SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \
- fpsetmask.c fpsetround.c fpsetsticky.c
+ fpsetmask.c fpsetround.c fpsetsticky.c usertc.c
diff --git lib/libc/arch/sh/gen/usertc.c lib/libc/arch/sh/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/sh/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/arch/sparc64/gen/Makefile.inc lib/libc/arch/sparc64/gen/Makefile.inc
index 58259cedef6..a908e022954 100644
--- lib/libc/arch/sparc64/gen/Makefile.inc
+++ lib/libc/arch/sparc64/gen/Makefile.inc
@@ -3,5 +3,5 @@
 SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
  fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
  fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
- isinfl.c isnanl.c isnormall.c ldexp.c modf.S \
+ isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
  mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
diff --git lib/libc/arch/sparc64/gen/usertc.c lib/libc/arch/sparc64/gen/usertc.c
new file mode 100644
index 00000000000..6551854a010
--- /dev/null
+++ lib/libc/arch/sparc64/gen/usertc.c
@@ -0,0 +1,21 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/timetc.h>
+
+int (*const _tc_get_timecount)(struct timekeep *, u_int *) = NULL;
diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c
index 131da4b2190..40e84771f86 100644
--- lib/libc/asr/asr.c
+++ lib/libc/asr/asr.c
@@ -198,11 +198,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds, int timeout)
  struct timespec pollstart, pollend, elapsed;
  int r;
 
- if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart))
  return -1;
 
  while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) {
- if (clock_gettime(CLOCK_MONOTONIC, &pollend))
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend))
  return -1;
  timespecsub(&pollend, &pollstart, &elapsed);
  timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000;
@@ -420,7 +420,7 @@ asr_check_reload(struct asr *asr)
  asr->a_rtime = 0;
  }
 
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
  return;
 
  if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0)
diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c
index 82de8fa33b7..02fd3013cc1 100644
--- lib/libc/crypt/bcrypt.c
+++ lib/libc/crypt/bcrypt.c
@@ -248,9 +248,9 @@ _bcrypt_autorounds(void)
  char buf[_PASSWORD_LEN];
  int duration;
 
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before);
+ WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before);
  bcrypt_newhash("testpassword", r, buf, sizeof(buf));
- clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after);
+ WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after);
 
  duration = after.tv_sec - before.tv_sec;
  duration *= 1000000;
diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c
index 270f54aada5..6f535853335 100644
--- lib/libc/dlfcn/init.c
+++ lib/libc/dlfcn/init.c
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 #include <sys/syscall.h>
+#include <sys/timetc.h> /* timekeep */
 
 #ifndef PIC
 #include <sys/mman.h>
@@ -45,8 +46,9 @@
 /* XXX should be in an include file shared with csu */
 char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void));
 
-/* provide definition for this */
+/* provide definitions for these */
 int _pagesize = 0;
+struct timekeep *_timekeep = NULL;
 
 /*
  * In dynamicly linked binaries environ and __progname are overriden by
@@ -105,6 +107,13 @@ _libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb)
  phnum = aux->au_v;
  break;
 #endif /* !PIC */
+ case AUX_openbsd_timekeep:
+ if (_tc_get_timecount) {
+ _timekeep = (void *)aux->au_v;
+ if (_timekeep->tk_version != TK_VERSION)
+ _timekeep = NULL;
+ }
+ break;
  }
  }
 
diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c
index 1286a96fe40..32f86eda50f 100644
--- lib/libc/gen/auth_subr.c
+++ lib/libc/gen/auth_subr.c
@@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as)
 
  if (as->pwd && (quad_t)as->pwd->pw_expire != 0) {
  if (as->now.tv_sec == 0)
- gettimeofday(&as->now, NULL);
+ WRAP(gettimeofday)(&as->now, NULL);
  if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) {
  as->state &= ~AUTH_ALLOW;
  as->state |= AUTH_EXPIRED;
@@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as)
 
  if (as->pwd && (quad_t)as->pwd->pw_change) {
  if (as->now.tv_sec == 0)
- gettimeofday(&as->now, NULL);
+ WRAP(gettimeofday)(&as->now, NULL);
  if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) {
  as->state &= ~AUTH_ALLOW;
  as->state |= AUTH_PWEXPIRED;
diff --git lib/libc/gen/time.c lib/libc/gen/time.c
index 3bbd0d733d1..b3ce9a800f1 100644
--- lib/libc/gen/time.c
+++ lib/libc/gen/time.c
@@ -36,7 +36,7 @@ time(time_t *t)
 {
  struct timeval tt;
 
- if (gettimeofday(&tt, NULL) == -1)
+ if (WRAP(gettimeofday)(&tt, NULL) == -1)
  return (-1);
  if (t)
  *t = (time_t)tt.tv_sec;
diff --git lib/libc/gen/times.c lib/libc/gen/times.c
index 02e4dd44b5c..36841810d1b 100644
--- lib/libc/gen/times.c
+++ lib/libc/gen/times.c
@@ -52,7 +52,7 @@ times(struct tms *tp)
  return ((clock_t)-1);
  tp->tms_cutime = CONVTCK(ru.ru_utime);
  tp->tms_cstime = CONVTCK(ru.ru_stime);
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1)
  return ((clock_t)-1);
  return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK));
 }
diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c
index 520a5954025..845cbe80356 100644
--- lib/libc/gen/timespec_get.c
+++ lib/libc/gen/timespec_get.c
@@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base)
 {
  switch (base) {
  case TIME_UTC:
- if (clock_gettime(CLOCK_REALTIME, ts) == -1)
+ if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1)
  return 0;
  break;
  default:
diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h
index ed112320fa2..df717021cab 100644
--- lib/libc/hidden/sys/time.h
+++ lib/libc/hidden/sys/time.h
@@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq);
 PROTO_NORMAL(adjtime);
 PROTO_NORMAL(futimes);
 PROTO_NORMAL(getitimer);
-PROTO_NORMAL(gettimeofday);
+PROTO_WRAP(gettimeofday);
 PROTO_NORMAL(setitimer);
 PROTO_NORMAL(settimeofday);
 PROTO_NORMAL(utimes);
diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h
new file mode 100644
index 00000000000..bbdaa2d0d4c
--- /dev/null
+++ lib/libc/hidden/sys/timetc.h
@@ -0,0 +1,38 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBC_SYS_TIMETC_H_
+#define _LIBC_SYS_TIMETC_H_
+
+#define _LIBC
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include_next <sys/timetc.h>
+
+__BEGIN_HIDDEN_DECLS
+extern struct timekeep *_timekeep;
+
+extern int (*const _tc_get_timecount)(struct timekeep *, u_int *);
+
+int _microtime(struct timeval *, struct timekeep *);
+int _nanotime(struct timespec *, struct timekeep *);
+int _nanoruntime(struct timespec *, struct timekeep *);
+int _nanouptime(struct timespec *, struct timekeep *);
+__END_HIDDEN_DECLS
+
+#endif /* !_LIBC_SYS_TIMETC_H_ */
diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h
index 18c49f8fcb9..d8e1e0caf64 100644
--- lib/libc/hidden/time.h
+++ lib/libc/hidden/time.h
@@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r);
 PROTO_STD_DEPRECATED(clock);
 PROTO_DEPRECATED(clock_getcpuclockid);
 PROTO_NORMAL(clock_getres);
-PROTO_NORMAL(clock_gettime);
+PROTO_WRAP(clock_gettime);
 PROTO_NORMAL(clock_settime);
 PROTO_STD_DEPRECATED(ctime);
 PROTO_DEPRECATED(ctime_r);
diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c
index 763e420bb88..9babb28470a 100644
--- lib/libc/net/res_random.c
+++ lib/libc/net/res_random.c
@@ -219,7 +219,7 @@ res_initid(void)
  if (ru_prf != NULL)
  arc4random_buf(ru_prf, sizeof(*ru_prf));
 
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
  ru_reseed = ts.tv_sec + RU_OUT;
  ru_msb = ru_msb == 0x8000 ? 0 : 0x8000;
 }
@@ -232,7 +232,7 @@ __res_randomid(void)
  u_int r;
  static void *randomid_mutex;
 
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts);
  pid = getpid();
 
  _MUTEX_LOCK(&randomid_mutex);
diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c
index 402d98cede4..917a6d42b8a 100644
--- lib/libc/rpc/auth_unix.c
+++ lib/libc/rpc/auth_unix.c
@@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
  /*
  * fill in param struct from the given params
  */
- (void)gettimeofday(&now,  NULL);
+ (void)WRAP(gettimeofday)(&now,  NULL);
  aup.aup_time = now.tv_sec;
  aup.aup_machname = machname;
  aup.aup_uid = uid;
@@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth)
  goto done;
 
  /* update the time and serialize in place */
- (void)gettimeofday(&now, NULL);
+ (void)WRAP(gettimeofday)(&now, NULL);
  aup.aup_time = now.tv_sec;
  xdrs.x_op = XDR_ENCODE;
  XDR_SETPOS(&xdrs, 0);
diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c
index 8e6ef515b0e..927b4bf2028 100644
--- lib/libc/rpc/clnt_tcp.c
+++ lib/libc/rpc/clnt_tcp.c
@@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int len)
  pfd[0].events = POLLIN;
  TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait);
  delta = wait;
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  for (;;) {
  r = ppoll(pfd, 1, &delta, NULL);
  save_errno = errno;
 
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&start, &after, &duration);
  timespecsub(&wait, &duration, &delta);
  if (delta.tv_sec < 0 || !timespecisset(&delta))
diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c
index 68d01674410..92e1d5c350d 100644
--- lib/libc/rpc/clnt_udp.c
+++ lib/libc/rpc/clnt_udp.c
@@ -265,7 +265,7 @@ send_again:
  reply_msg.acpted_rply.ar_results.where = resultsp;
  reply_msg.acpted_rply.ar_results.proc = xresults;
 
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  for (;;) {
  switch (ppoll(pfd, 1, &wait, NULL)) {
  case 0:
@@ -283,7 +283,7 @@ send_again:
  /* FALLTHROUGH */
  case -1:
  if (errno == EINTR) {
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&after, &start, &duration);
  timespecadd(&time_waited, &duration, &time_waited);
  if (timespeccmp(&time_waited, &timeout, <))
diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c
index f9d7a70938f..6c99db84359 100644
--- lib/libc/rpc/svc_tcp.c
+++ lib/libc/rpc/svc_tcp.c
@@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
  * A timeout is fatal for the connection.
  */
  delta = wait_per_try;
- clock_gettime(CLOCK_MONOTONIC, &start);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &start);
  pfd[0].fd = sock;
  pfd[0].events = POLLIN;
  do {
@@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len)
  case -1:
  if (errno != EINTR)
  goto fatal_err;
- clock_gettime(CLOCK_MONOTONIC, &after);
+ WRAP(clock_gettime)(CLOCK_MONOTONIC, &after);
  timespecsub(&after, &start, &duration);
  timespecsub(&wait_per_try, &duration, &delta);
  if (delta.tv_sec < 0 || !timespecisset(&delta))
diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc
index 34769576ced..d57418d81bf 100644
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \
 
 # glue to offer userland wrappers for some syscalls
 SRCS+= posix_madvise.c pthread_sigmask.c \
- w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c
+ w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \
+ w_clock_gettime.c w_gettimeofday.c microtime.c
 
 # glue for compat with old syscall interfaces.
 SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c truncate.c \
@@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c w_pwrite.c w_pwritev.c
 ASM= __semctl.o __syscall.o __thrsigdivert.o \
  access.o acct.o adjfreq.o adjtime.o \
  bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \
- clock_getres.o clock_gettime.o clock_settime.o \
+ clock_getres.o clock_settime.o \
  dup.o dup2.o dup3.o \
  execve.o \
  faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \
@@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \
  getgroups.o getitimer.o getpeername.o getpgid.o \
  getpriority.o getresgid.o getresuid.o \
  getrlimit.o getrusage.o getsid.o getsockname.o \
- getsockopt.o gettimeofday.o ioctl.o \
+ getsockopt.o ioctl.o \
  kevent.o kill.o kqueue.o ktrace.o lchown.o \
  link.o linkat.o listen.o lstat.o madvise.o \
  minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
@@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po}
 SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so}
 DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do}
 
-HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o}
+HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o} \
+ clock_gettime.o gettimeofday.o
 PHIDDEN=${HIDDEN:.o=.po}
 SHIDDEN=${HIDDEN:.o=.so}
 DHIDDEN=${HIDDEN:.o=.do}
diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c
new file mode 100644
index 00000000000..a3015a44c73
--- /dev/null
+++ lib/libc/sys/microtime.c
@@ -0,0 +1,138 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2000 Poul-Henning Kamp <[hidden email]>
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/atomic.h>
+#include <sys/timetc.h>
+
+#include <time.h>
+
+/*
+ * Return the difference between the timehands' counter value now and what
+ * was when we copied it to the timehands' offset_count.
+ */
+static inline int
+tc_delta(struct timekeep *tk, u_int *delta)
+{
+ u_int tc;
+
+ if (_tc_get_timecount(tk, &tc))
+ return -1;
+ *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask;
+ return 0;
+}
+
+static int
+binuptime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ *bt = tk->tk_offset;
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(bt, tk->tk_scale * delta, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+static int
+binruntime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt);
+ bintimesub(bt, &tk->tk_naptime, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+static int
+bintime(struct bintime *bt, struct timekeep *tk)
+{
+ u_int gen, delta;
+
+ do {
+ gen = tk->tk_generation;
+ membar_consumer();
+ *bt = tk->tk_offset;
+ if (tc_delta(tk, &delta))
+ return -1;
+ bintimeaddfrac(bt, tk->tk_scale * delta, bt);
+ bintimeadd(bt, &tk->tk_boottime, bt);
+ membar_consumer();
+ } while (gen == 0 || gen != tk->tk_generation);
+
+ return 0;
+}
+
+int
+_microtime(struct timeval *tvp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (bintime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMEVAL(&bt, tvp);
+ return 0;
+}
+
+int
+_nanotime(struct timespec *tsp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (bintime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, tsp);
+ return 0;
+}
+
+int
+_nanoruntime(struct timespec *ts, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (binruntime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, ts);
+ return 0;
+}
+
+
+int
+_nanouptime(struct timespec *tsp, struct timekeep *tk)
+{
+ struct bintime bt;
+
+ if (binuptime(&bt, tk))
+ return -1;
+ BINTIME_TO_TIMESPEC(&bt, tsp);
+ return 0;
+}
diff --git lib/libc/sys/w_clock_gettime.c lib/libc/sys/w_clock_gettime.c
new file mode 100644
index 00000000000..6e6478bd131
--- /dev/null
+++ lib/libc/sys/w_clock_gettime.c
@@ -0,0 +1,51 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/timetc.h>
+
+#include <time.h>
+
+int
+WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp)
+{
+ int rc = 0;
+ struct timekeep *timekeep = _timekeep;
+
+ if (timekeep == NULL || timekeep->tk_user == 0)
+ return clock_gettime(clock_id, tp);
+
+ switch (clock_id) {
+ case CLOCK_REALTIME:
+ rc = _nanotime(tp, timekeep);
+ break;
+ case CLOCK_UPTIME:
+ rc = _nanoruntime(tp, timekeep);
+ break;
+ case CLOCK_MONOTONIC:
+ case CLOCK_BOOTTIME:
+ rc = _nanouptime(tp, timekeep);
+ break;
+ default:
+ return clock_gettime(clock_id, tp);
+ }
+
+ if (rc)
+ return clock_gettime(clock_id, tp);
+
+ return 0;
+}
+DEF_WRAP(clock_gettime);
diff --git lib/libc/sys/w_gettimeofday.c lib/libc/sys/w_gettimeofday.c
new file mode 100644
index 00000000000..f44edfbb1ad
--- /dev/null
+++ lib/libc/sys/w_gettimeofday.c
@@ -0,0 +1,40 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Robert Nagy <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/timetc.h>
+
+int
+WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp)
+{
+ int rc = 0;
+ struct timekeep *timekeep = _timekeep;
+ static struct timezone zerotz = { 0, 0 };
+
+ if (timekeep == NULL || timekeep->tk_user == 0)
+ return gettimeofday(tp, tzp);
+
+ if (tp)
+ rc = _microtime(tp, timekeep);
+ if (rc)
+ return gettimeofday(tp, tzp);
+
+ if (tzp)
+ *tzp = zerotz;
+
+ return 0;
+}
+DEF_WRAP(gettimeofday);
diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h
index 788890add89..df2239438d2 100644
--- lib/libc/thread/synch.h
+++ lib/libc/thread/synch.h
@@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *
  if (abs == NULL)
  return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL);
 
- if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel))
+ if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel))
  return (EINVAL);
 
  rel.tv_sec = abs->tv_sec - rel.tv_sec;
diff --git regress/lib/libc/timekeep/Makefile regress/lib/libc/timekeep/Makefile
new file mode 100644
index 00000000000..a7f3080290d
--- /dev/null
+++ regress/lib/libc/timekeep/Makefile
@@ -0,0 +1,5 @@
+# $OpenBSD$
+
+PROGS= test_clock_gettime test_time_skew test_gettimeofday
+
+.include <bsd.regress.mk>
diff --git regress/lib/libc/timekeep/test_clock_gettime.c regress/lib/libc/timekeep/test_clock_gettime.c
new file mode 100644
index 00000000000..859ec368215
--- /dev/null
+++ regress/lib/libc/timekeep/test_clock_gettime.c
@@ -0,0 +1,43 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <time.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+
+void
+check()
+{
+ struct timespec tp = {0};
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp));
+
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp));
+ ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp));
+
+}
+
+int main()
+{
+ check();
+ return 0;
+}
diff --git regress/lib/libc/timekeep/test_gettimeofday.c regress/lib/libc/timekeep/test_gettimeofday.c
new file mode 100644
index 00000000000..ea90a1be7e0
--- /dev/null
+++ regress/lib/libc/timekeep/test_gettimeofday.c
@@ -0,0 +1,37 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <sys/time.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+
+void
+check()
+{
+ struct timeval tv = {0};
+ struct timezone tzp;
+
+ ASSERT_EQ(0, gettimeofday(&tv, NULL));
+ ASSERT_EQ(0, gettimeofday(&tv, &tzp));
+}
+
+int main()
+{
+ check();
+ return 0;
+}
diff --git regress/lib/libc/timekeep/test_time_skew.c regress/lib/libc/timekeep/test_time_skew.c
new file mode 100644
index 00000000000..dfa9481c091
--- /dev/null
+++ regress/lib/libc/timekeep/test_time_skew.c
@@ -0,0 +1,55 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/time.h>
+
+#include <assert.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+#define ASSERT_NE(a, b) assert((a) != (b))
+
+void
+check()
+{
+         struct timespec tp1, tp2, tout;
+
+         tout.tv_sec = 0;
+         tout.tv_nsec = 100000;
+
+         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1));
+
+         nanosleep(&tout, NULL);
+
+         ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2));
+
+         /* tp1 should never be larger than tp2 */
+         ASSERT_NE(1, timespeccmp(&tp1, &tp2, >));
+}
+
+int
+main(void)
+{
+ int i;
+
+ for (i = 0; i < 1000; i++)
+ check();
+
+ return 0;
+}
diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c
index 3f5f2c5b42b..6eaf8b107c6 100644
--- sys/arch/alpha/alpha/clock.c
+++ sys/arch/alpha/alpha/clock.c
@@ -64,7 +64,7 @@ int clk_irq = 0;
 
 u_int rpcc_get_timecount(struct timecounter *);
 struct timecounter rpcc_timecounter = {
- rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL
+ rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0
 };
 
 extern todr_chip_handle_t todr_handle;
diff --git sys/arch/alpha/include/timetc.h sys/arch/alpha/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/alpha/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c
index 7a1dcb4ad75..1567e5e6ee8 100644
--- sys/arch/amd64/amd64/tsc.c
+++ sys/arch/amd64/amd64/tsc.c
@@ -37,12 +37,13 @@ uint64_t tsc_frequency;
 int tsc_is_invariant;
 
 #define TSC_DRIFT_MAX 250
+#define TSC_SKEW_MAX 1000
 int64_t tsc_drift_observed;
 
 volatile int64_t tsc_sync_val;
 volatile struct cpu_info *tsc_sync_cpu;
 
-uint tsc_get_timecount(struct timecounter *tc);
+u_int tsc_get_timecount(struct timecounter *tc);
 
 #include "lapic.h"
 #if NLAPIC > 0
@@ -50,7 +51,7 @@ extern u_int32_t lapic_per_second;
 #endif
 
 struct timecounter tsc_timecounter = {
- tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL
+ tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, TC_TSC
 };
 
 uint64_t
@@ -216,6 +217,8 @@ tsc_get_timecount(struct timecounter *tc)
 void
 tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
 {
+ CPU_INFO_ITERATOR cii;
+
 #ifdef TSC_DEBUG
  printf("%s: TSC skew=%lld observed drift=%lld\n", __func__,
     (long long)ci->ci_tsc_skew, (long long)tsc_drift_observed);
@@ -244,8 +247,15 @@ tsc_timecounter_init(struct cpu_info *ci, uint64_t cpufreq)
  printf("ERROR: %lld cycle TSC drift observed\n",
     (long long)tsc_drift_observed);
  tsc_timecounter.tc_quality = -1000;
+ tsc_timecounter.tc_user = 0;
  tsc_is_invariant = 0;
  }
+ CPU_INFO_FOREACH(cii, ci) {
+ if (ci->ci_tsc_skew > TSC_SKEW_MAX) {
+ tsc_timecounter.tc_user = 0;
+ break;
+ }
+ }
 
  tc_init(&tsc_timecounter);
 }
diff --git sys/arch/amd64/include/timetc.h sys/arch/amd64/include/timetc.h
new file mode 100644
index 00000000000..c2d40bcd1e7
--- /dev/null
+++ sys/arch/amd64/include/timetc.h
@@ -0,0 +1,24 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_TSC 1
+#define TC_LAST 2
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c
index 613f7ee0e0f..00da0c6a8d0 100644
--- sys/arch/amd64/isa/clock.c
+++ sys/arch/amd64/isa/clock.c
@@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
 u_int i8254_simple_get_timecount(struct timecounter *tc);
 
 static struct timecounter i8254_timecounter = {
- i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
 };
 
 int clockintr(void *);
diff --git sys/arch/arm/include/timetc.h sys/arch/arm/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/arm/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c
index 11196b5c60d..1a2106ef94c 100644
--- sys/arch/arm64/dev/agtimer.c
+++ sys/arch/arm64/dev/agtimer.c
@@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY;
 u_int agtimer_get_timecount(struct timecounter *);
 
 static struct timecounter agtimer_timecounter = {
- agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL
+ agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0
 };
 
 struct agtimer_pcpu_softc {
diff --git sys/arch/arm64/include/timetc.h sys/arch/arm64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/arm64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/armv7/include/timetc.h sys/arch/armv7/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/armv7/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/armv7/omap/gptimer.c sys/arch/armv7/omap/gptimer.c
index 7605845d5e2..061542d532f 100644
--- sys/arch/armv7/omap/gptimer.c
+++ sys/arch/armv7/omap/gptimer.c
@@ -117,7 +117,7 @@ int gptimer_irq = 0;
 u_int gptimer_get_timecount(struct timecounter *);
 
 static struct timecounter gptimer_timecounter = {
- gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL
+ gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0
 };
 
 volatile u_int32_t nexttickevent;
diff --git sys/arch/armv7/sunxi/sxitimer.c sys/arch/armv7/sunxi/sxitimer.c
index 14a243c78d0..41028f9a602 100644
--- sys/arch/armv7/sunxi/sxitimer.c
+++ sys/arch/armv7/sunxi/sxitimer.c
@@ -89,7 +89,7 @@ void sxitimer_delay(u_int);
 u_int sxitimer_get_timecount(struct timecounter *);
 
 static struct timecounter sxitimer_timecounter = {
- sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL
+ sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0
 };
 
 bus_space_tag_t sxitimer_iot;
diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c
index 4c594ab5ec7..8cce6c3a893 100644
--- sys/arch/hppa/dev/clock.c
+++ sys/arch/hppa/dev/clock.c
@@ -47,7 +47,7 @@ int cpu_hardclock(void *);
 u_int itmr_get_timecount(struct timecounter *);
 
 struct timecounter itmr_timecounter = {
- itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
+ itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0
 };
 
 extern todr_chip_handle_t todr_handle;
diff --git sys/arch/hppa/include/timetc.h sys/arch/hppa/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/hppa/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/i386/include/timetc.h sys/arch/i386/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/i386/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c
index 09a6db983f2..dd74bd425ad 100644
--- sys/arch/i386/isa/clock.c
+++ sys/arch/i386/isa/clock.c
@@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter *tc);
 u_int i8254_simple_get_timecount(struct timecounter *tc);
 
 static struct timecounter i8254_timecounter = {
- i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0
 };
 struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
 u_long rtclock_tval;
diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
index 9d9f061eef9..bb8e4c7f9ae 100644
--- sys/arch/i386/pci/geodesc.c
+++ sys/arch/i386/pci/geodesc.c
@@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = {
  0xffffffff, /* counter_mask */
  27000000, /* frequency */
  "GEOTSC", /* name */
- 2000 /* quality */
+ 2000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 int
diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c
index 8b8aa4ac430..a6f324e66f3 100644
--- sys/arch/i386/pci/gscpm.c
+++ sys/arch/i386/pci/gscpm.c
@@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = {
  0xffffff, /* counter_mask */
  3579545, /* frequency */
  "GSCPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 struct cfattach gscpm_ca = {
diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c
index 6abf1627de2..629a86a14ff 100644
--- sys/arch/i386/pci/ichpcib.c
+++ sys/arch/i386/pci/ichpcib.c
@@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = {
  0xffffff, /* counter_mask */
  3579545, /* frequency */
  "ICHPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0 /* expose to user */
 };
 
 struct cfattach ichpcib_ca = {
diff --git sys/arch/landisk/include/timetc.h sys/arch/landisk/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/landisk/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/loongson/include/timetc.h sys/arch/loongson/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/loongson/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/loongson/loongson/generic3a_machdep.c sys/arch/loongson/loongson/generic3a_machdep.c
index ac3f1db6ccd..53489b07549 100644
--- sys/arch/loongson/loongson/generic3a_machdep.c
+++ sys/arch/loongson/loongson/generic3a_machdep.c
@@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = {
  .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */
  .tc_frequency = HPET_FREQ,
  .tc_name = "hpet",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 /* Firmware entry points */
diff --git sys/arch/luna88k/include/timetc.h sys/arch/luna88k/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/luna88k/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/luna88k/luna88k/clock.c sys/arch/luna88k/luna88k/clock.c
index a04120987e0..6580a4a46bf 100644
--- sys/arch/luna88k/luna88k/clock.c
+++ sys/arch/luna88k/luna88k/clock.c
@@ -112,7 +112,9 @@ struct timecounter clock_tc = {
  .tc_counter_mask = 0xffffffff,
  .tc_frequency = 0, /* will be filled in */
  .tc_name = "clock",
- .tc_quality = 0
+ .tc_quality = 0,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 /*
diff --git sys/arch/m88k/include/timetc.h sys/arch/m88k/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/m88k/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/macppc/include/timetc.h sys/arch/macppc/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/macppc/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/macppc/macppc/clock.c sys/arch/macppc/macppc/clock.c
index 4a44a92cfc0..8c3ad620be8 100644
--- sys/arch/macppc/macppc/clock.c
+++ sys/arch/macppc/macppc/clock.c
@@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320;
 static int32_t ticks_per_intr;
 
 static struct timecounter tb_timecounter = {
- tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
+ tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0
 };
 
 /* calibrate the timecounter frequency for the listed models */
diff --git sys/arch/mips64/include/timetc.h sys/arch/mips64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/mips64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/mips64/mips64/mips64_machdep.c sys/arch/mips64/mips64/mips64_machdep.c
index d4a42ed5acc..5c4dbadb5bb 100644
--- sys/arch/mips64/mips64/mips64_machdep.c
+++ sys/arch/mips64/mips64/mips64_machdep.c
@@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = {
  0xffffffff, /* counter_mask */
  0, /* frequency */
  "CP0", /* name */
- 0 /* quality */
+ 0, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 u_int
diff --git sys/arch/octeon/include/timetc.h sys/arch/octeon/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/octeon/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/octeon/octeon/machdep.c sys/arch/octeon/octeon/machdep.c
index 902e462d53f..d8377653abe 100644
--- sys/arch/octeon/octeon/machdep.c
+++ sys/arch/octeon/octeon/machdep.c
@@ -151,8 +151,9 @@ struct timecounter ioclock_timecounter = {
  .tc_name = "ioclock",
  .tc_quality = 0, /* ioclock can be overridden
  * by cp0 counter */
- .tc_priv = 0 /* clock register,
+ .tc_priv = 0, /* clock register,
  * determined at runtime */
+ .tc_user = 0, /* expose to user */
 };
 
 static int
diff --git sys/arch/powerpc/include/timetc.h sys/arch/powerpc/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/powerpc/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/powerpc64/include/timetc.h sys/arch/powerpc64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/powerpc64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sgi/include/timetc.h sys/arch/sgi/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sgi/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sgi/sgi/ip27_machdep.c sys/arch/sgi/sgi/ip27_machdep.c
index ba7fa558b96..2a2cc144242 100644
--- sys/arch/sgi/sgi/ip27_machdep.c
+++ sys/arch/sgi/sgi/ip27_machdep.c
@@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = {
  .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */
  .tc_frequency = 1250000,
  .tc_name = "hubrt",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = 0,
+ .tc_user = 0,
 };
 
 volatile uint64_t ip27_spinup_a0;
diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c
index 56b29915c70..827775512ac 100644
--- sys/arch/sgi/xbow/xheart.c
+++ sys/arch/sgi/xbow/xheart.c
@@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = {
  .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit */
  .tc_frequency = 12500000,
  .tc_name = "heart",
- .tc_quality = 100
+ .tc_quality = 100,
+ .tc_priv = NULL,
+ .tc_user = 0,
 };
 
 extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *);
diff --git sys/arch/sh/include/timetc.h sys/arch/sh/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sh/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sparc64/dev/psycho.c sys/arch/sparc64/dev/psycho.c
index e24f804dff6..1a7a1afa8c2 100644
--- sys/arch/sparc64/dev/psycho.c
+++ sys/arch/sparc64/dev/psycho.c
@@ -127,7 +127,7 @@ extern struct sparc_pci_chipset _sparc_pci_chipset;
 u_int stick_get_timecount(struct timecounter *);
 
 struct timecounter stick_timecounter = {
- stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL
+ stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0
 };
 
 /*
diff --git sys/arch/sparc64/include/timetc.h sys/arch/sparc64/include/timetc.h
new file mode 100644
index 00000000000..e58a7fb4faa
--- /dev/null
+++ sys/arch/sparc64/include/timetc.h
@@ -0,0 +1,23 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Paul Irofti <[hidden email]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_TIMETC_H_
+#define _MACHINE_TIMETC_H_
+
+#define TC_LAST 0
+
+#endif /* _MACHINE_TIMETC_H_ */
diff --git sys/arch/sparc64/sparc64/clock.c sys/arch/sparc64/sparc64/clock.c
index fd5e8a9c15b..5c2e47d386b 100644
--- sys/arch/sparc64/sparc64/clock.c
+++ sys/arch/sparc64/sparc64/clock.c
@@ -109,13 +109,13 @@ struct cfdriver clock_cd = {
 u_int tick_get_timecount(struct timecounter *);
 
 struct timecounter tick_timecounter = {
- tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL
+ tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0
 };
 
 u_int sys_tick_get_timecount(struct timecounter *);
 
 struct timecounter sys_tick_timecounter = {
- sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL
+ sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0
 };
 
 /*
diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c
index d0ee72cec9b..13177a909da 100644
--- sys/dev/acpi/acpihpet.c
+++ sys/dev/acpi/acpihpet.c
@@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = {
  0xffffffff, /* counter_mask (32 bits) */
  0, /* frequency */
  0, /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 #define HPET_TIMERS 3
diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c
index cdc8c99a17a..89b5a397e47 100644
--- sys/dev/acpi/acpitimer.c
+++ sys/dev/acpi/acpitimer.c
@@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = {
  0x00ffffff, /* counter_mask (24 bits) */
  ACPI_FREQUENCY, /* frequency */
  0, /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 struct acpitimer_softc {
diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c
index 6df82858016..9610d5bc1f0 100644
--- sys/dev/pci/amdpm.c
+++ sys/dev/pci/amdpm.c
@@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = {
  0xffffff, /* counter_mask */
  AMDPM_FREQUENCY, /* frequency */
  "AMDPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 #define AMDPM_CONFREG 0x40
diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c
index db806eedf80..ce33cd175e6 100644
--- sys/dev/pci/viapm.c
+++ sys/dev/pci/viapm.c
@@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = {
  0xffffff, /* counter_mask */
  VIAPM_FREQUENCY, /* frequency */
  "VIAPM", /* name */
- 1000 /* quality */
+ 1000, /* quality */
+ NULL, /* private bits */
+ 0, /* expose to user */
 };
 
 struct timeout viapm_timeout;
diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c
index b32facdacb1..b9ee2feec4c 100644
--- sys/dev/pv/hyperv.c
+++ sys/dev/pv/hyperv.c
@@ -141,7 +141,7 @@ struct {
 };
 
 struct timecounter hv_timecounter = {
- hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001
+ hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0
 };
 
 struct cfdriver hyperv_cd = {
diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c
index 6b242f7448d..b80e4d2a484 100644
--- sys/dev/pv/pvclock.c
+++ sys/dev/pv/pvclock.c
@@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = {
 };
 
 struct timecounter pvclock_timecounter = {
- pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL
+ pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0
 };
 
 int
diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c
index 9b5b8eb3acf..59bc923a6fb 100644
--- sys/kern/exec_elf.c
+++ sys/kern/exec_elf.c
@@ -124,7 +124,7 @@ extern char *syscallnames[];
 /*
  * How many entries are in the AuxInfo array we pass to the process?
  */
-#define ELF_AUX_ENTRIES 8
+#define ELF_AUX_ENTRIES 9
 
 /*
  * This is the OpenBSD ELF emul
@@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct exec_package *epp)
  a->au_v = ap->arg_entry;
  a++;
 
+ a->au_id = AUX_openbsd_timekeep;
+ a->au_v = p->p_p->ps_timekeep;
+ a++;
+
  a->au_id = AUX_null;
  a->au_v = 0;
  a++;
diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c
index 20480c2fc28..222450607d5 100644
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -64,6 +64,11 @@
 #include <uvm/uvm_extern.h>
 #include <machine/tcb.h>
 
+#include <sys/timetc.h>
+
+struct uvm_object *timekeep_object;
+struct timekeep* timekeep;
+
 void unveil_destroy(struct process *ps);
 
 const struct kmem_va_mode kv_exec = {
@@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = {
  */
 int exec_sigcode_map(struct process *, struct emul *);
 
+/*
+ * Map the shared timekeep page.
+ */
+int exec_timekeep_map(struct process *);
+
 /*
  * If non-zero, stackgap_random specifies the upper limit of the random gap size
  * added to the fixed stack position. Must be n^2.
@@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t *retval)
  /* map the process's signal trampoline code */
  if (exec_sigcode_map(pr, pack.ep_emul))
  goto free_pack_abort;
+ /* map the process's timekeep page */
+ if (exec_timekeep_map(pr))
+ goto free_pack_abort;
 
 #ifdef __HAVE_EXEC_MD_MAP
  /* perform md specific mappings that process might need */
@@ -863,3 +876,40 @@ exec_sigcode_map(struct process *pr, struct emul *e)
 
  return (0);
 }
+
+int
+exec_timekeep_map(struct process *pr)
+{
+ size_t timekeep_sz = sizeof(struct timekeep);
+
+ /*
+ * Similar to the sigcode object, except that there is a single
+ * timekeep object, and not one per emulation.
+ */
+ if (timekeep_object == NULL) {
+ vaddr_t va;
+
+ timekeep_object = uao_create(timekeep_sz, 0);
+ uao_reference(timekeep_object);
+
+ if (uvm_map(kernel_map, &va, round_page(timekeep_sz), timekeep_object,
+    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
+    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
+ uao_detach(timekeep_object);
+ return (ENOMEM);
+ }
+
+ timekeep = (struct timekeep *)va;
+ timekeep->tk_version = TK_VERSION;
+ }
+
+ uao_reference(timekeep_object);
+ if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, round_page(timekeep_sz),
+    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
+    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
+ uao_detach(timekeep_object);
+ return (ENOMEM);
+ }
+
+ return (0);
+}
diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c
index 88d4a3379f9..47efbdd0b78 100644
--- sys/kern/kern_tc.c
+++ sys/kern/kern_tc.c
@@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc)
 }
 
 static struct timecounter dummy_timecounter = {
- dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
+ dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0
 };
 
 /*
@@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts)
 #endif
 }
 
+void
+tc_update_timekeep(void)
+{
+ static struct timecounter *last_tc = NULL;
+ struct timehands *th;
+
+ if (timekeep == NULL)
+ return;
+
+ th = timehands;
+ timekeep->tk_generation = 0;
+ membar_producer();
+ timekeep->tk_scale = th->th_scale;
+ timekeep->tk_offset_count = th->th_offset_count;
+ timekeep->tk_offset = th->th_offset;
+ timekeep->tk_naptime = th->th_naptime;
+ timekeep->tk_boottime = th->th_boottime;
+ if (last_tc != th->th_counter) {
+ timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
+ timekeep->tk_user = th->th_counter->tc_user;
+ last_tc = th->th_counter;
+ }
+ membar_producer();
+ timekeep->tk_generation = th->th_generation;
+
+ return;
+}
+
 /*
  * Initialize the next struct timehands in the ring and make
  * it the active timehands.  Along the way we might switch to a different
@@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
  time_uptime = th->th_offset.sec;
  membar_producer();
  timehands = th;
+
+ tc_update_timekeep();
 }
 
 /* Report or change the active timecounter hardware. */
diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h
index a40e0510273..3084ed595a6 100644
--- sys/sys/exec_elf.h
+++ sys/sys/exec_elf.h
@@ -691,7 +691,8 @@ enum AuxID {
  AUX_sun_uid = 2000, /* euid */
  AUX_sun_ruid = 2001, /* ruid */
  AUX_sun_gid = 2002, /* egid */
- AUX_sun_rgid = 2003 /* rgid */
+ AUX_sun_rgid = 2003, /* rgid */
+ AUX_openbsd_timekeep = 4000, /* userland clock_get