Author: sephe
Date: Tue Feb 21 03:14:05 2017
New Revision: 314018
URL: https://svnweb.freebsd.org/changeset/base/314018

Log:
  MFC 311743
  
      hyperv: Add method to read 64bit Hyper-V specific time value.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D9057

Modified:
  stable/10/sys/dev/hyperv/include/hyperv.h
  stable/10/sys/dev/hyperv/utilities/vmbus_timesync.c
  stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
  stable/10/sys/dev/hyperv/vmbus/hyperv.c
  stable/10/sys/dev/hyperv/vmbus/vmbus_et.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/include/hyperv.h
==============================================================================
--- stable/10/sys/dev/hyperv/include/hyperv.h   Tue Feb 21 03:00:33 2017        
(r314017)
+++ stable/10/sys/dev/hyperv/include/hyperv.h   Tue Feb 21 03:14:05 2017        
(r314018)
@@ -79,9 +79,17 @@ struct hyperv_guid {
 
 #define HYPERV_GUID_STRLEN             40
 
-int            hyperv_guid2str(const struct hyperv_guid *, char *, size_t);
+typedef uint64_t                       (*hyperv_tc64_t)(void);
 
-extern u_int   hyperv_features;        /* CPUID_HV_MSR_ */
+int                    hyperv_guid2str(const struct hyperv_guid *, char *,
+                           size_t);
+
+/*
+ * hyperv_tc64 could be NULL, if there were no suitable Hyper-V
+ * specific timecounter.
+ */
+extern hyperv_tc64_t   hyperv_tc64;
+extern u_int           hyperv_features;        /* CPUID_HV_MSR_ */
 
 #endif /* _KERNEL */
 

Modified: stable/10/sys/dev/hyperv/utilities/vmbus_timesync.c
==============================================================================
--- stable/10/sys/dev/hyperv/utilities/vmbus_timesync.c Tue Feb 21 03:00:33 
2017        (r314017)
+++ stable/10/sys/dev/hyperv/utilities/vmbus_timesync.c Tue Feb 21 03:14:05 
2017        (r314018)
@@ -52,8 +52,7 @@ __FBSDID("$FreeBSD$");
        VMBUS_ICVER_LE(VMBUS_IC_VERSION(4, 0), (sc)->ic_msgver)
 
 #define VMBUS_TIMESYNC_DORTT(sc)       \
-       (VMBUS_TIMESYNC_MSGVER4((sc)) &&\
-        (hyperv_features & CPUID_HV_MSR_TIME_REFCNT))
+       (VMBUS_TIMESYNC_MSGVER4((sc)) && hyperv_tc64 != NULL)
 
 static int                     vmbus_timesync_probe(device_t);
 static int                     vmbus_timesync_attach(device_t);
@@ -117,7 +116,7 @@ vmbus_timesync(struct vmbus_ic_softc *sc
        uint64_t hv_ns, vm_ns, rtt = 0;
 
        if (VMBUS_TIMESYNC_DORTT(sc))
-               rtt = rdmsr(MSR_HV_TIME_REF_COUNT) - sent_tc;
+               rtt = hyperv_tc64() - sent_tc;
 
        hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE + rtt) * HYPERV_TIMER_NS_FACTOR;
        nanotime(&vm_ts);

Modified: stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c       Tue Feb 21 
03:00:33 2017        (r314017)
+++ stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c       Tue Feb 21 
03:14:05 2017        (r314018)
@@ -118,8 +118,8 @@ hyperv_tsc_mmap(struct cdev *dev __unuse
 }
 
 #define HYPERV_TSC_TIMECOUNT(fence)                                    \
-static u_int                                                           \
-hyperv_tsc_timecount_##fence(struct timecounter *tc)                   \
+static uint64_t                                                                
\
+hyperv_tc64_tsc_##fence(void)                                          \
 {                                                                      \
        struct hyperv_reftsc *tsc_ref = hyperv_ref_tsc.tsc_ref;         \
        uint32_t seq;                                                   \
@@ -150,6 +150,13 @@ hyperv_tsc_timecount_##fence(struct time
        /* Fallback to the generic timecounter, i.e. rdmsr. */          \
        return (rdmsr(MSR_HV_TIME_REF_COUNT));                          \
 }                                                                      \
+                                                                       \
+static u_int                                                           \
+hyperv_tsc_timecount_##fence(struct timecounter *tc __unused)          \
+{                                                                      \
+                                                                       \
+       return (hyperv_tc64_tsc_##fence());                             \
+}                                                                      \
 struct __hack
 
 HYPERV_TSC_TIMECOUNT(lfence);
@@ -158,6 +165,7 @@ HYPERV_TSC_TIMECOUNT(mfence);
 static void
 hyperv_tsc_tcinit(void *dummy __unused)
 {
+       hyperv_tc64_t tc64 = NULL;
        uint64_t val, orig;
 
        if ((hyperv_features &
@@ -170,11 +178,13 @@ hyperv_tsc_tcinit(void *dummy __unused)
        case CPU_VENDOR_AMD:
                hyperv_tsc_timecounter.tc_get_timecount =
                    hyperv_tsc_timecount_mfence;
+               tc64 = hyperv_tc64_tsc_mfence;
                break;
 
        case CPU_VENDOR_INTEL:
                hyperv_tsc_timecounter.tc_get_timecount =
                    hyperv_tsc_timecount_lfence;
+               tc64 = hyperv_tc64_tsc_lfence;
                break;
 
        default:
@@ -199,6 +209,10 @@ hyperv_tsc_tcinit(void *dummy __unused)
        /* Register "enlightened" timecounter. */
        tc_init(&hyperv_tsc_timecounter);
 
+       /* Install 64 bits timecounter method for other modules to use. */
+       KASSERT(tc64 != NULL, ("tc64 is not set"));
+       hyperv_tc64 = tc64;
+
        /* Add device for mmap(2). */
        make_dev(&hyperv_tsc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0444,
            HYPERV_REFTSC_DEVNAME);

Modified: stable/10/sys/dev/hyperv/vmbus/hyperv.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/hyperv.c     Tue Feb 21 03:00:33 2017        
(r314017)
+++ stable/10/sys/dev/hyperv/vmbus/hyperv.c     Tue Feb 21 03:14:05 2017        
(r314018)
@@ -77,6 +77,8 @@ u_int                         hyperv_recommends;
 static u_int                   hyperv_pm_features;
 static u_int                   hyperv_features3;
 
+hyperv_tc64_t                  hyperv_tc64;
+
 static struct timecounter      hyperv_timecounter = {
        .tc_get_timecount       = hyperv_get_timecount,
        .tc_poll_pps            = NULL,
@@ -96,6 +98,13 @@ hyperv_get_timecount(struct timecounter 
        return rdmsr(MSR_HV_TIME_REF_COUNT);
 }
 
+static uint64_t
+hyperv_tc64_rdmsr(void)
+{
+
+       return (rdmsr(MSR_HV_TIME_REF_COUNT));
+}
+
 uint64_t
 hypercall_post_message(bus_addr_t msg_paddr)
 {
@@ -232,6 +241,12 @@ hyperv_init(void *dummy __unused)
        if (hyperv_features & CPUID_HV_MSR_TIME_REFCNT) {
                /* Register Hyper-V timecounter */
                tc_init(&hyperv_timecounter);
+
+               /*
+                * Install 64 bits timecounter method for other modules
+                * to use.
+                */
+               hyperv_tc64 = hyperv_tc64_rdmsr;
        }
 }
 SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init,

Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_et.c
==============================================================================
--- stable/10/sys/dev/hyperv/vmbus/vmbus_et.c   Tue Feb 21 03:00:33 2017        
(r314017)
+++ stable/10/sys/dev/hyperv/vmbus/vmbus_et.c   Tue Feb 21 03:14:05 2017        
(r314018)
@@ -50,13 +50,10 @@ __FBSDID("$FreeBSD$");
         MSR_HV_STIMER_CFG_SINT_MASK)
 
 /*
- * Two additionally required features:
+ * Additionally required feature:
  * - SynIC is needed for interrupt generation.
- * - Time reference counter is needed to set ABS reference count to
- *   STIMER0_COUNT.
  */
-#define CPUID_HV_ET_MASK               (CPUID_HV_MSR_TIME_REFCNT |     \
-                                        CPUID_HV_MSR_SYNIC |           \
+#define CPUID_HV_ET_MASK               (CPUID_HV_MSR_SYNIC |           \
                                         CPUID_HV_MSR_SYNTIMER)
 
 static void                    vmbus_et_identify(driver_t *, device_t);
@@ -104,7 +101,7 @@ vmbus_et_start(struct eventtimer *et __u
 {
        uint64_t current;
 
-       current = rdmsr(MSR_HV_TIME_REF_COUNT);
+       current = hyperv_tc64();
        current += hyperv_sbintime2count(first);
        wrmsr(MSR_HV_STIMER0_COUNT, current);
 
@@ -133,7 +130,8 @@ vmbus_et_identify(driver_t *driver, devi
 {
        if (device_get_unit(parent) != 0 ||
            device_find_child(parent, VMBUS_ET_NAME, -1) != NULL ||
-           (hyperv_features & CPUID_HV_ET_MASK) != CPUID_HV_ET_MASK)
+           (hyperv_features & CPUID_HV_ET_MASK) != CPUID_HV_ET_MASK ||
+           hyperv_tc64 == NULL)
                return;
 
        device_add_child(parent, VMBUS_ET_NAME, -1);
@@ -189,9 +187,8 @@ vmbus_et_attach(device_t dev)
        vmbus_et.et_start = vmbus_et_start;
 
        /*
-        * Delay a bit to make sure that MSR_HV_TIME_REF_COUNT will
-        * not return 0, since writing 0 to STIMER0_COUNT will disable
-        * STIMER0.
+        * Delay a bit to make sure that hyperv_tc64 will not return 0,
+        * since writing 0 to STIMER0_COUNT will disable STIMER0.
         */
        DELAY(100);
        smp_rendezvous(NULL, vmbus_et_config, NULL, NULL);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to