hyperv/timesync: Support "sent TC" to improve accuracy.

MFC after:	1 week
Sponsored by:	Microsoft
Differential Revision:	https://reviews.freebsd.org/D8723
This commit is contained in:
sephe 2016-12-08 05:37:39 +00:00
parent 092f1602f5
commit 6091327a9b
6 changed files with 38 additions and 29 deletions

View File

@ -36,6 +36,23 @@
#include <vm/vm.h>
#include <vm/pmap.h>
#define MSR_HV_TIME_REF_COUNT 0x40000020
#define CPUID_HV_MSR_TIME_REFCNT 0x0002 /* MSR_HV_TIME_REF_COUNT */
#define CPUID_HV_MSR_SYNIC 0x0004 /* MSRs for SynIC */
#define CPUID_HV_MSR_SYNTIMER 0x0008 /* MSRs for SynTimer */
#define CPUID_HV_MSR_APIC 0x0010 /* MSR_HV_{EOI,ICR,TPR} */
#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_GUEST_IDLE 0x0400 /* MSR_HV_GUEST_IDLE */
#ifndef NANOSEC
#define NANOSEC 1000000000ULL
#endif
#define HYPERV_TIMER_NS_FACTOR 100ULL
#define HYPERV_TIMER_FREQ (NANOSEC / HYPERV_TIMER_NS_FACTOR)
struct hyperv_guid {
uint8_t hv_guid[16];
} __packed;
@ -44,4 +61,6 @@ struct hyperv_guid {
int hyperv_guid2str(const struct hyperv_guid *, char *, size_t);
extern u_int hyperv_features; /* CPUID_HV_MSR_ */
#endif /* _HYPERV_H_ */

View File

@ -46,10 +46,14 @@ __FBSDID("$FreeBSD$");
#define VMBUS_TIMESYNC_FWVER \
VMBUS_IC_VERSION(VMBUS_TIMESYNC_FWVER_MAJOR, 0)
#define VMBUS_TIMESYNC_MSGVER_MAJOR 3
#define VMBUS_TIMESYNC_MSGVER_MAJOR 4
#define VMBUS_TIMESYNC_MSGVER \
VMBUS_IC_VERSION(VMBUS_TIMESYNC_MSGVER_MAJOR, 0)
#define VMBUS_TIMESYNC_DORTT(sc) \
((sc)->ic_msgver >= VMBUS_IC_VERSION(4, 0) && \
(hyperv_features & CPUID_HV_MSR_TIME_REFCNT))
static const struct vmbus_ic_desc vmbus_timesync_descs[] = {
{
.ic_guid = { .hv_guid = {
@ -81,12 +85,16 @@ SYSCTL_INT(_hw_hvtimesync, OID_AUTO, sample_verbose, CTLFLAG_RWTUN,
&vmbus_ts_sample_verbose, 0, "Increase sample request verbosity.");
static void
vmbus_timesync(struct hv_util_sc *sc, uint64_t hvtime, uint8_t tsflags)
vmbus_timesync(struct hv_util_sc *sc, uint64_t hvtime, uint64_t sent_tc,
uint8_t tsflags)
{
struct timespec vm_ts;
uint64_t hv_ns, vm_ns;
uint64_t hv_ns, vm_ns, rtt = 0;
hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE) * VMBUS_ICMSG_TS_FACTOR;
if (VMBUS_TIMESYNC_DORTT(sc))
rtt = rdmsr(MSR_HV_TIME_REF_COUNT) - sent_tc;
hv_ns = (hvtime - VMBUS_ICMSG_TS_BASE + rtt) * HYPERV_TIMER_NS_FACTOR;
nanotime(&vm_ts);
vm_ns = (vm_ts.tv_sec * NANOSEC) + vm_ts.tv_nsec;
@ -174,6 +182,8 @@ vmbus_timesync_cb(struct vmbus_channel *chan, void *xsc)
VMBUS_TIMESYNC_FWVER, VMBUS_TIMESYNC_MSGVER);
if (error)
return;
if (VMBUS_TIMESYNC_DORTT(sc))
device_printf(sc->ic_dev, "RTT\n");
break;
case VMBUS_ICMSG_TYPE_TIMESYNC:
@ -183,7 +193,8 @@ vmbus_timesync_cb(struct vmbus_channel *chan, void *xsc)
return;
}
msg = data;
vmbus_timesync(sc, msg->ic_hvtime, msg->ic_tsflags);
vmbus_timesync(sc, msg->ic_hvtime, msg->ic_sent_tc,
msg->ic_tsflags);
break;
default:

View File

@ -114,18 +114,13 @@ struct vmbus_icmsg_timesync {
struct vmbus_icmsg_hdr ic_hdr;
uint64_t ic_hvtime;
uint64_t ic_vmtime;
uint64_t ic_rtt;
uint64_t ic_sent_tc;
uint8_t ic_tsflags; /* VMBUS_ICMSG_TS_FLAG_ */
} __packed;
#define VMBUS_ICMSG_TS_FLAG_SYNC 0x01
#define VMBUS_ICMSG_TS_FLAG_SAMPLE 0x02
/* XXX consolidate w/ hyperv */
#define VMBUS_ICMSG_TS_BASE 116444736000000000ULL
#define VMBUS_ICMSG_TS_FACTOR 100ULL
#ifndef NANOSEC
#define NANOSEC 1000000000ULL
#endif
#endif /* !_VMBUS_ICREG_H_ */

View File

@ -57,8 +57,6 @@
#define MSR_HV_VP_INDEX 0x40000002
#define MSR_HV_TIME_REF_COUNT 0x40000020
#define MSR_HV_SCONTROL 0x40000080
#define MSR_HV_SCTRL_ENABLE 0x0001ULL
#define MSR_HV_SCTRL_RSVD_MASK 0xfffffffffffffffeULL
@ -106,15 +104,7 @@
#define CPUID_LEAF_HV_IDENTITY 0x40000002
#define CPUID_LEAF_HV_FEATURES 0x40000003
/* EAX: features */
#define CPUID_HV_MSR_TIME_REFCNT 0x0002 /* MSR_HV_TIME_REF_COUNT */
#define CPUID_HV_MSR_SYNIC 0x0004 /* MSRs for SynIC */
#define CPUID_HV_MSR_SYNTIMER 0x0008 /* MSRs for SynTimer */
#define CPUID_HV_MSR_APIC 0x0010 /* MSR_HV_{EOI,ICR,TPR} */
#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_GUEST_IDLE 0x0400 /* MSR_HV_GUEST_IDLE */
/* EAX: features include/hyperv.h CPUID_HV_MSR */
/* ECX: power management features */
#define CPUPM_HV_CSTATE_MASK 0x000f /* deepest C-state */
#define CPUPM_HV_C3_HPET 0x0010 /* C3 requires HPET */

View File

@ -29,13 +29,6 @@
#ifndef _HYPERV_VAR_H_
#define _HYPERV_VAR_H_
#ifndef NANOSEC
#define NANOSEC 1000000000ULL
#endif
#define HYPERV_TIMER_NS_FACTOR 100ULL
#define HYPERV_TIMER_FREQ (NANOSEC / HYPERV_TIMER_NS_FACTOR)
extern u_int hyperv_features;
extern u_int hyperv_recommends;
uint64_t hypercall_post_message(bus_addr_t msg_paddr);

View File

@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/timeet.h>
#include <dev/hyperv/include/hyperv.h>
#include <dev/hyperv/vmbus/hyperv_reg.h>
#include <dev/hyperv/vmbus/hyperv_var.h>
#include <dev/hyperv/vmbus/vmbus_var.h>