Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153340605
D8789.id22905.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D8789.id22905.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D8789: hyperv: Implement userspace gettimeofday(2) with Hyper-V reference TSC
Attached
Detach File
Event Timeline
Log In to Comment