@ -37,13 +37,16 @@
# define SD_MAJOR_1 1
# define SD_VERSION_1 (SD_MAJOR_1 << 16 | SD_MINOR)
# define TS_MAJOR 3
# define TS_MAJOR 4
# define TS_MINOR 0
# define TS_VERSION (TS_MAJOR << 16 | TS_MINOR)
# define TS_MAJOR_1 1
# define TS_VERSION_1 (TS_MAJOR_1 << 16 | TS_MINOR)
# define TS_MAJOR_3 3
# define TS_VERSION_3 (TS_MAJOR_3 << 16 | TS_MINOR)
# define HB_MAJOR 3
# define HB_MINOR 0
# define HB_VERSION (HB_MAJOR << 16 | HB_MINOR)
@ -160,20 +163,6 @@ static void shutdown_onchannelcallback(void *context)
schedule_work ( & shutdown_work ) ;
}
/*
* Set guest time to host UTC time .
*/
static inline void do_adj_guesttime ( u64 hosttime )
{
s64 host_tns ;
struct timespec host_ts ;
host_tns = ( hosttime - WLTIMEDELTA ) * 100 ;
host_ts = ns_to_timespec ( host_tns ) ;
do_settimeofday ( & host_ts ) ;
}
/*
* Set the host time in a process context .
*/
@ -181,14 +170,37 @@ static inline void do_adj_guesttime(u64 hosttime)
struct adj_time_work {
struct work_struct work ;
u64 host_time ;
u64 ref_time ;
u8 flags ;
} ;
static void hv_set_host_time ( struct work_struct * work )
{
struct adj_time_work * wrk ;
s64 host_tns ;
u64 newtime ;
struct timespec host_ts ;
wrk = container_of ( work , struct adj_time_work , work ) ;
do_adj_guesttime ( wrk - > host_time ) ;
newtime = wrk - > host_time ;
if ( ts_srv_version > TS_VERSION_3 ) {
/*
* Some latency has been introduced since Hyper - V generated
* its time sample . Take that latency into account before
* using TSC reference time sample from Hyper - V .
*
* This sample is given by TimeSync v4 and above hosts .
*/
u64 current_tick ;
rdmsrl ( HV_X64_MSR_TIME_REF_COUNT , current_tick ) ;
newtime + = ( current_tick - wrk - > ref_time ) ;
}
host_tns = ( newtime - WLTIMEDELTA ) * 100 ;
host_ts = ns_to_timespec ( host_tns ) ;
do_settimeofday ( & host_ts ) ;
kfree ( wrk ) ;
}
@ -205,7 +217,7 @@ static void hv_set_host_time(struct work_struct *work)
* typically used as a hint to the guest . The guest is under no obligation
* to discipline the clock .
*/
static inline void adj_guesttime ( u64 hosttime , u8 flags )
static inline void adj_guesttime ( u64 hosttime , u64 reftime , u 8 flags )
{
struct adj_time_work * wrk ;
@ -214,6 +226,8 @@ static inline void adj_guesttime(u64 hosttime, u8 flags)
return ;
wrk - > host_time = hosttime ;
wrk - > ref_time = reftime ;
wrk - > flags = flags ;
if ( ( flags & ( ICTIMESYNCFLAG_SYNC | ICTIMESYNCFLAG_SAMPLE ) ) ! = 0 ) {
INIT_WORK ( & wrk - > work , hv_set_host_time ) ;
schedule_work ( & wrk - > work ) ;
@ -231,6 +245,7 @@ static void timesync_onchannelcallback(void *context)
u64 requestid ;
struct icmsg_hdr * icmsghdrp ;
struct ictimesync_data * timedatap ;
struct ictimesync_ref_data * refdata ;
u8 * time_txf_buf = util_timesynch . recv_buffer ;
struct icmsg_negotiate * negop = NULL ;
@ -246,11 +261,27 @@ static void timesync_onchannelcallback(void *context)
time_txf_buf ,
util_fw_version ,
ts_srv_version ) ;
pr_info ( " Using TimeSync version %d.%d \n " ,
ts_srv_version > > 16 , ts_srv_version & 0xFFFF ) ;
} else {
timedatap = ( struct ictimesync_data * ) & time_txf_buf [
sizeof ( struct vmbuspipe_hdr ) +
sizeof ( struct icmsg_hdr ) ] ;
adj_guesttime ( timedatap - > parenttime , timedatap - > flags ) ;
if ( ts_srv_version > TS_VERSION_3 ) {
refdata = ( struct ictimesync_ref_data * )
& time_txf_buf [
sizeof ( struct vmbuspipe_hdr ) +
sizeof ( struct icmsg_hdr ) ] ;
adj_guesttime ( refdata - > parenttime ,
refdata - > vmreferencetime ,
refdata - > flags ) ;
} else {
timedatap = ( struct ictimesync_data * )
& time_txf_buf [
sizeof ( struct vmbuspipe_hdr ) +
sizeof ( struct icmsg_hdr ) ] ;
adj_guesttime ( timedatap - > parenttime ,
0 ,
timedatap - > flags ) ;
}
}
icmsghdrp - > icflags = ICMSGHDRFLAG_TRANSACTION
@ -348,12 +379,17 @@ static int util_probe(struct hv_device *dev,
ts_srv_version = TS_VERSION_1 ;
hb_srv_version = HB_VERSION_1 ;
break ;
default :
case ( VERSION_WIN10 ) :
util_fw_version = UTIL_FW_VERSION ;
sd_srv_version = SD_VERSION ;
ts_srv_version = TS_VERSION ;
hb_srv_version = HB_VERSION ;
break ;
default :
util_fw_version = UTIL_FW_VERSION ;
sd_srv_version = SD_VERSION ;
ts_srv_version = TS_VERSION_3 ;
hb_srv_version = HB_VERSION ;
}
ret = vmbus_open ( dev - > channel , 4 * PAGE_SIZE , 4 * PAGE_SIZE , NULL , 0 ,