Page MenuHomeFreeBSD

D8789.id22905.diff
No OneTemporary

D8789.id22905.diff

Index: lib/libc/x86/sys/__vdso_gettc.c
===================================================================
--- lib/libc/x86/sys/__vdso_gettc.c
+++ lib/libc/x86/sys/__vdso_gettc.c
@@ -45,6 +45,10 @@
#include <machine/cpufunc.h>
#include <machine/specialreg.h>
#include <dev/acpica/acpi_hpet.h>
+#ifdef __amd64__
+#include <machine/atomic.h>
+#include <dev/hyperv/hyperv.h>
+#endif
#include "libc_private.h"
static void
@@ -144,6 +148,58 @@
_close(fd);
}
+#ifdef __amd64__
+
+#define HYPERV_REFTSC_DEVPATH "/dev/" HYPERV_REFTSC_DEVNAME
+
+static struct hyperv_reftsc *hyperv_ref_tsc = MAP_FAILED;
+
+static void
+__vdso_init_hyperv_tsc(void)
+{
+ int fd;
+
+ fd = _open(HYPERV_REFTSC_DEVPATH, O_RDONLY);
+ if (fd < 0)
+ return;
+ hyperv_ref_tsc = mmap(NULL, sizeof(*hyperv_ref_tsc), PROT_READ,
+ MAP_SHARED, fd, 0);
+ _close(fd);
+}
+
+static int
+__vdso_hyperv_tsc(struct hyperv_reftsc *tsc_ref, u_int *tc)
+{
+ uint32_t seq;
+
+ while ((seq = atomic_load_acq_int(&tsc_ref->tsc_seq)) != 0) {
+ uint64_t disc, ret, tsc;
+ uint64_t scale = tsc_ref->tsc_scale;
+ int64_t ofs = tsc_ref->tsc_ofs;
+
+ /* XXX mfence for AMD cpus. */
+ lfence_mb();
+ tsc = rdtsc();
+
+ /* ret = ((tsc * scale) >> 64) + ofs */
+ __asm__ __volatile__ ("mulq %3" :
+ "=d" (ret), "=a" (disc) :
+ "a" (tsc), "r" (scale));
+ ret += ofs;
+
+ atomic_thread_fence_acq();
+ if (tsc_ref->tsc_seq == seq) {
+ *tc = ret;
+ return (0);
+ }
+
+ /* Sequence changed; re-sync. */
+ }
+ return (ENOSYS);
+}
+
+#endif /* __amd64__ */
+
#pragma weak __vdso_gettc
int
__vdso_gettc(const struct vdso_timehands *th, u_int *tc)
@@ -165,6 +221,15 @@
return (ENOSYS);
*tc = *(volatile uint32_t *)(hpet_dev_map + HPET_MAIN_COUNTER);
return (0);
+#ifdef __amd64__
+ case VDSO_TH_ALGO_X86_HVTSC:
+ if (hyperv_ref_tsc == MAP_FAILED) {
+ __vdso_init_hyperv_tsc();
+ if (hyperv_ref_tsc == MAP_FAILED)
+ return (ENOSYS);
+ }
+ return (__vdso_hyperv_tsc(hyperv_ref_tsc, tc));
+#endif
default:
return (ENOSYS);
}
Index: sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
===================================================================
--- sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
+++ sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
@@ -33,6 +33,7 @@
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/timetc.h>
+#include <sys/vdso.h>
#include <machine/cpufunc.h>
#include <machine/cputypes.h>
@@ -52,18 +53,28 @@
struct hyperv_dma tsc_ref_dma;
};
+static uint32_t hyperv_tsc_vdso_timehands(
+ struct vdso_timehands *,
+ struct timecounter *);
+#ifdef COMPAT_FREEBSD32
+static uint32_t hyperv_tsc_vdso_timehands32(
+ struct vdso_timehands32 *,
+ struct timecounter *);
+#endif
+
static d_open_t hyperv_tsc_open;
static d_mmap_t hyperv_tsc_mmap;
static struct timecounter hyperv_tsc_timecounter = {
.tc_get_timecount = NULL, /* based on CPU vendor. */
- .tc_poll_pps = NULL,
.tc_counter_mask = 0xffffffff,
.tc_frequency = HYPERV_TIMER_FREQ,
.tc_name = "Hyper-V-TSC",
.tc_quality = 3000,
- .tc_flags = 0,
- .tc_priv = NULL
+ .tc_fill_vdso_timehands = hyperv_tsc_vdso_timehands,
+#ifdef COMPAT_FREEBSD32
+ .tc_fill_vdso_timehands32 = hyperv_tsc_vdso_timehands32
+#endif
};
static struct cdevsw hyperv_tsc_cdevsw = {
@@ -117,6 +128,32 @@
return (0);
}
+static uint32_t
+hyperv_tsc_vdso_timehands(struct vdso_timehands *vdso_th,
+ struct timecounter *tc __unused)
+{
+
+ vdso_th->th_algo = VDSO_TH_ALGO_X86_HVTSC;
+ vdso_th->th_x86_shift = 0;
+ vdso_th->th_x86_hpet_idx = 0xffffffff;
+ bzero(vdso_th->th_res, sizeof(vdso_th->th_res));
+ return (1);
+}
+
+#ifdef COMPAT_FREEBSD32
+static uint32_t
+hyperv_tsc_vdso_timehands32(struct vdso_timehands32 *vdso_th32,
+ struct timecounter *tc __unused)
+{
+
+ vdso_th32->th_algo = VDSO_TH_ALGO_X86_HVTSC;
+ vdso_th32->th_x86_shift = 0;
+ vdso_th32->th_x86_hpet_idx = 0xffffffff;
+ bzero(vdso_th32->th_res, sizeof(vdso_th32->th_res));
+ return (1);
+}
+#endif /* COMPAT_FREEBSD32 */
+
#define HYPERV_TSC_TIMECOUNT(fence) \
static u_int \
hyperv_tsc_timecount_##fence(struct timecounter *tc) \
Index: sys/sys/vdso.h
===================================================================
--- sys/sys/vdso.h
+++ sys/sys/vdso.h
@@ -54,6 +54,8 @@
#define VDSO_TK_VER_CURR VDSO_TK_VER_1
#define VDSO_TH_ALGO_1 0x1
#define VDSO_TH_ALGO_2 0x2
+#define VDSO_TH_ALGO_3 0x3
+#define VDSO_TH_ALGO_4 0x4
#ifndef _KERNEL
Index: sys/x86/include/vdso.h
===================================================================
--- sys/x86/include/vdso.h
+++ sys/x86/include/vdso.h
@@ -39,6 +39,7 @@
#define VDSO_TH_ALGO_X86_TSC VDSO_TH_ALGO_1
#define VDSO_TH_ALGO_X86_HPET VDSO_TH_ALGO_2
+#define VDSO_TH_ALGO_X86_HVTSC VDSO_TH_ALGO_3 /* Hyper-V ref. TSC */
#ifdef _KERNEL
#ifdef COMPAT_FREEBSD32

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 21, 2:15 PM (18 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31915082
Default Alt Text
D8789.id22905.diff (4 KB)

Event Timeline