Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137598411
D8763.id22837.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D8763.id22837.diff
View Options
Index: sys/dev/hyperv/include/hyperv.h
===================================================================
--- sys/dev/hyperv/include/hyperv.h
+++ sys/dev/hyperv/include/hyperv.h
@@ -45,6 +45,7 @@
#define CPUID_HV_MSR_HYPERCALL 0x0020 /* MSR_HV_GUEST_OS_ID
* MSR_HV_HYPERCALL */
#define CPUID_HV_MSR_VP_INDEX 0x0040 /* MSR_HV_VP_INDEX */
+#define CPUID_HV_MSR_REFERENCE_TSC 0x0200 /* MSR_HV_REFERENCE_TSC */
#define CPUID_HV_MSR_GUEST_IDLE 0x0400 /* MSR_HV_GUEST_IDLE */
#ifndef NANOSEC
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
@@ -28,7 +28,37 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/timetc.h>
+
+#include <machine/cpufunc.h>
+#include <machine/cputypes.h>
+#include <machine/md_var.h>
+
+#include <dev/hyperv/include/hyperv.h>
+#include <dev/hyperv/include/hyperv_busdma.h>
#include <dev/hyperv/vmbus/hyperv_machdep.h>
+#include <dev/hyperv/vmbus/hyperv_reg.h>
+#include <dev/hyperv/vmbus/hyperv_var.h>
+
+struct hyperv_reftsc_ctx {
+ struct hyperv_reftsc *tsc_ref;
+ struct hyperv_dma tsc_ref_dma;
+};
+
+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
+};
+
+static struct hyperv_reftsc_ctx hyperv_ref_tsc;
uint64_t
hypercall_md(volatile void *hc_addr, uint64_t in_val,
@@ -41,3 +71,84 @@
"c" (in_val), "d" (in_paddr), "m" (hc_addr));
return (status);
}
+
+#define HYPERV_TSC_TIMECOUNT(fence) \
+static u_int \
+hyperv_tsc_timecount_##fence(struct timecounter *tc) \
+{ \
+ struct hyperv_reftsc *tsc_ref = hyperv_ref_tsc.tsc_ref; \
+ uint32_t seq; \
+ \
+ while ((seq = tsc_ref->tsc_seq) != 0) { \
+ uint64_t disc, ret, tsc; \
+ uint64_t scale = tsc_ref->tsc_scale; \
+ int64_t ofs = tsc_ref->tsc_ofs; \
+ \
+ fence(); \
+ tsc = rdtsc(); \
+ \
+ /* ret = ((tsc * scale) >> 64) + ofs */ \
+ __asm__ __volatile__ ("mulq %3" : \
+ "=d" (ret), "=a" (disc) : \
+ "a" (tsc), "r" (scale)); \
+ ret += ofs; \
+ \
+ if (tsc_ref->tsc_seq == seq) \
+ return (ret); \
+ \
+ /* Sequence changed; re-sync. */ \
+ } \
+ /* Fallback to the generic timecounter, i.e. rdmsr. */ \
+ return (hyperv_get_timecount(tc)); \
+} \
+struct __hack
+
+HYPERV_TSC_TIMECOUNT(lfence);
+HYPERV_TSC_TIMECOUNT(mfence);
+
+static void
+hyperv_tsc_tcinit(void *dummy __unused)
+{
+ uint64_t val, orig;
+
+ if ((hyperv_features &
+ (CPUID_HV_MSR_TIME_REFCNT | CPUID_HV_MSR_REFERENCE_TSC)) !=
+ (CPUID_HV_MSR_TIME_REFCNT | CPUID_HV_MSR_REFERENCE_TSC) &&
+ (cpu_feature & CPUID_SSE2)) /* for mfence/lfence */
+ return;
+
+ switch (cpu_vendor_id) {
+ case CPU_VENDOR_AMD:
+ hyperv_tsc_timecounter.tc_get_timecount =
+ hyperv_tsc_timecount_mfence;
+ break;
+
+ case CPU_VENDOR_INTEL:
+ hyperv_tsc_timecounter.tc_get_timecount =
+ hyperv_tsc_timecount_lfence;
+ break;
+
+ default:
+ /* Unsupport CPU vendors. */
+ return;
+ }
+
+ hyperv_ref_tsc.tsc_ref = hyperv_dmamem_alloc(NULL, PAGE_SIZE, 0,
+ sizeof(struct hyperv_reftsc), &hyperv_ref_tsc.tsc_ref_dma,
+ BUS_DMA_WAITOK | BUS_DMA_ZERO);
+ if (hyperv_ref_tsc.tsc_ref == NULL) {
+ printf("hyperv: reftsc page allocation failed\n");
+ return;
+ }
+
+ orig = rdmsr(MSR_HV_REFERENCE_TSC);
+ val = MSR_HV_REFTSC_ENABLE | (orig & MSR_HV_REFTSC_RSVD_MASK) |
+ ((hyperv_ref_tsc.tsc_ref_dma.hv_paddr >> PAGE_SHIFT) <<
+ MSR_HV_REFTSC_PGSHIFT);
+ wrmsr(MSR_HV_REFERENCE_TSC, val);
+
+ /* Register "enlightened" timecounter. */
+ tc_init(&hyperv_tsc_timecounter);
+}
+SYSINIT(hyperv_tsc_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, hyperv_tsc_tcinit,
+ NULL);
Index: sys/dev/hyperv/vmbus/hyperv.c
===================================================================
--- sys/dev/hyperv/vmbus/hyperv.c
+++ sys/dev/hyperv/vmbus/hyperv.c
@@ -67,7 +67,6 @@
struct hyperv_dma hc_dma;
};
-static u_int hyperv_get_timecount(struct timecounter *);
static bool hyperv_identify(void);
static void hypercall_memfree(void);
@@ -90,7 +89,7 @@
static struct hypercall_ctx hypercall_context;
-static u_int
+u_int
hyperv_get_timecount(struct timecounter *tc __unused)
{
return rdmsr(MSR_HV_TIME_REF_COUNT);
Index: sys/dev/hyperv/vmbus/hyperv_reg.h
===================================================================
--- sys/dev/hyperv/vmbus/hyperv_reg.h
+++ sys/dev/hyperv/vmbus/hyperv_reg.h
@@ -57,6 +57,11 @@
#define MSR_HV_VP_INDEX 0x40000002
+#define MSR_HV_REFERENCE_TSC 0x40000021
+#define MSR_HV_REFTSC_ENABLE 0x0001ULL
+#define MSR_HV_REFTSC_RSVD_MASK 0x0ffeULL
+#define MSR_HV_REFTSC_PGSHIFT 12
+
#define MSR_HV_SCONTROL 0x40000080
#define MSR_HV_SCTRL_ENABLE 0x0001ULL
#define MSR_HV_SCTRL_RSVD_MASK 0xfffffffffffffffeULL
@@ -124,6 +129,17 @@
#define CPUID_LEAF_HV_HWFEATURES 0x40000006
/*
+ * Hyper-V Reference TSC
+ */
+struct hyperv_reftsc {
+ volatile uint32_t tsc_seq;
+ volatile uint32_t tsc_rsvd1;
+ volatile uint64_t tsc_scale;
+ volatile int64_t tsc_ofs;
+} __packed __aligned(PAGE_SIZE);
+CTASSERT(sizeof(struct hyperv_reftsc) == PAGE_SIZE);
+
+/*
* Hyper-V Monitor Notification Facility
*/
struct hyperv_mon_param {
Index: sys/dev/hyperv/vmbus/hyperv_var.h
===================================================================
--- sys/dev/hyperv/vmbus/hyperv_var.h
+++ sys/dev/hyperv/vmbus/hyperv_var.h
@@ -29,9 +29,13 @@
#ifndef _HYPERV_VAR_H_
#define _HYPERV_VAR_H_
+struct timecounter;
+
extern u_int hyperv_recommends;
uint64_t hypercall_post_message(bus_addr_t msg_paddr);
uint64_t hypercall_signal_event(bus_addr_t monprm_paddr);
+u_int hyperv_get_timecount(struct timecounter *);
+
#endif /* !_HYPERV_VAR_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Nov 25, 1:17 PM (7 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26135580
Default Alt Text
D8763.id22837.diff (5 KB)
Attached To
Mode
D8763: hyperv: Implement "enlightened" time counter, which is rdtsc based.
Attached
Detach File
Event Timeline
Log In to Comment