Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2010, Microsoft Corporation.
  4 *
 
 
 
 
 
 
 
 
 
 
 
 
 
  5 * Authors:
  6 *   Haiyang Zhang <haiyangz@microsoft.com>
  7 *   Hank Janssen  <hjanssen@microsoft.com>
  8 */
  9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 10
 11#include <linux/kernel.h>
 12#include <linux/init.h>
 13#include <linux/module.h>
 14#include <linux/slab.h>
 15#include <linux/sysctl.h>
 16#include <linux/reboot.h>
 17#include <linux/hyperv.h>
 18#include <linux/clockchips.h>
 19#include <linux/ptp_clock_kernel.h>
 20#include <clocksource/hyperv_timer.h>
 21#include <asm/mshyperv.h>
 22
 23#include "hyperv_vmbus.h"
 24
 25#define SD_MAJOR	3
 26#define SD_MINOR	0
 27#define SD_VERSION	(SD_MAJOR << 16 | SD_MINOR)
 28
 29#define SD_MAJOR_1	1
 30#define SD_VERSION_1	(SD_MAJOR_1 << 16 | SD_MINOR)
 31
 32#define TS_MAJOR	4
 33#define TS_MINOR	0
 34#define TS_VERSION	(TS_MAJOR << 16 | TS_MINOR)
 35
 36#define TS_MAJOR_1	1
 37#define TS_VERSION_1	(TS_MAJOR_1 << 16 | TS_MINOR)
 38
 39#define TS_MAJOR_3	3
 40#define TS_VERSION_3	(TS_MAJOR_3 << 16 | TS_MINOR)
 41
 42#define HB_MAJOR	3
 43#define HB_MINOR	0
 44#define HB_VERSION	(HB_MAJOR << 16 | HB_MINOR)
 45
 46#define HB_MAJOR_1	1
 47#define HB_VERSION_1	(HB_MAJOR_1 << 16 | HB_MINOR)
 48
 49static int sd_srv_version;
 50static int ts_srv_version;
 51static int hb_srv_version;
 52
 53#define SD_VER_COUNT 2
 54static const int sd_versions[] = {
 55	SD_VERSION,
 56	SD_VERSION_1
 57};
 58
 59#define TS_VER_COUNT 3
 60static const int ts_versions[] = {
 61	TS_VERSION,
 62	TS_VERSION_3,
 63	TS_VERSION_1
 64};
 65
 66#define HB_VER_COUNT 2
 67static const int hb_versions[] = {
 68	HB_VERSION,
 69	HB_VERSION_1
 70};
 71
 72#define FW_VER_COUNT 2
 73static const int fw_versions[] = {
 74	UTIL_FW_VERSION,
 75	UTIL_WS2K8_FW_VERSION
 76};
 77
 78static void shutdown_onchannelcallback(void *context);
 79static struct hv_util_service util_shutdown = {
 80	.util_cb = shutdown_onchannelcallback,
 81};
 82
 83static int hv_timesync_init(struct hv_util_service *srv);
 84static void hv_timesync_deinit(void);
 85
 86static void timesync_onchannelcallback(void *context);
 87static struct hv_util_service util_timesynch = {
 88	.util_cb = timesync_onchannelcallback,
 89	.util_init = hv_timesync_init,
 90	.util_deinit = hv_timesync_deinit,
 91};
 92
 93static void heartbeat_onchannelcallback(void *context);
 94static struct hv_util_service util_heartbeat = {
 95	.util_cb = heartbeat_onchannelcallback,
 96};
 97
 98static struct hv_util_service util_kvp = {
 99	.util_cb = hv_kvp_onchannelcallback,
100	.util_init = hv_kvp_init,
101	.util_deinit = hv_kvp_deinit,
102};
103
104static struct hv_util_service util_vss = {
105	.util_cb = hv_vss_onchannelcallback,
106	.util_init = hv_vss_init,
107	.util_deinit = hv_vss_deinit,
108};
109
110static struct hv_util_service util_fcopy = {
111	.util_cb = hv_fcopy_onchannelcallback,
112	.util_init = hv_fcopy_init,
113	.util_deinit = hv_fcopy_deinit,
114};
115
116static void perform_shutdown(struct work_struct *dummy)
117{
118	orderly_poweroff(true);
119}
120
121/*
122 * Perform the shutdown operation in a thread context.
123 */
124static DECLARE_WORK(shutdown_work, perform_shutdown);
125
126static void shutdown_onchannelcallback(void *context)
127{
128	struct vmbus_channel *channel = context;
129	u32 recvlen;
130	u64 requestid;
131	bool execute_shutdown = false;
132	u8  *shut_txf_buf = util_shutdown.recv_buffer;
133
134	struct shutdown_msg_data *shutdown_msg;
135
136	struct icmsg_hdr *icmsghdrp;
137
138	vmbus_recvpacket(channel, shut_txf_buf,
139			 PAGE_SIZE, &recvlen, &requestid);
140
141	if (recvlen > 0) {
142		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
143			sizeof(struct vmbuspipe_hdr)];
144
145		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
146			if (vmbus_prep_negotiate_resp(icmsghdrp, shut_txf_buf,
147					fw_versions, FW_VER_COUNT,
148					sd_versions, SD_VER_COUNT,
149					NULL, &sd_srv_version)) {
150				pr_info("Shutdown IC version %d.%d\n",
151					sd_srv_version >> 16,
152					sd_srv_version & 0xFFFF);
153			}
154		} else {
155			shutdown_msg =
156				(struct shutdown_msg_data *)&shut_txf_buf[
157					sizeof(struct vmbuspipe_hdr) +
158					sizeof(struct icmsg_hdr)];
159
160			switch (shutdown_msg->flags) {
161			case 0:
162			case 1:
163				icmsghdrp->status = HV_S_OK;
164				execute_shutdown = true;
165
166				pr_info("Shutdown request received -"
167					    " graceful shutdown initiated\n");
168				break;
169			default:
170				icmsghdrp->status = HV_E_FAIL;
171				execute_shutdown = false;
172
173				pr_info("Shutdown request received -"
174					    " Invalid request\n");
175				break;
176			}
177		}
178
179		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
180			| ICMSGHDRFLAG_RESPONSE;
181
182		vmbus_sendpacket(channel, shut_txf_buf,
183				       recvlen, requestid,
184				       VM_PKT_DATA_INBAND, 0);
185	}
186
187	if (execute_shutdown == true)
188		schedule_work(&shutdown_work);
189}
190
191/*
192 * Set the host time in a process context.
193 */
194static struct work_struct adj_time_work;
195
196/*
197 * The last time sample, received from the host. PTP device responds to
198 * requests by using this data and the current partition-wide time reference
199 * count.
200 */
201static struct {
202	u64				host_time;
203	u64				ref_time;
204	spinlock_t			lock;
205} host_ts;
206
207static struct timespec64 hv_get_adj_host_time(void)
208{
209	struct timespec64 ts;
210	u64 newtime, reftime;
211	unsigned long flags;
212
213	spin_lock_irqsave(&host_ts.lock, flags);
214	reftime = hyperv_cs->read(hyperv_cs);
215	newtime = host_ts.host_time + (reftime - host_ts.ref_time);
216	ts = ns_to_timespec64((newtime - WLTIMEDELTA) * 100);
217	spin_unlock_irqrestore(&host_ts.lock, flags);
218
219	return ts;
220}
221
222static void hv_set_host_time(struct work_struct *work)
223{
224	struct timespec64 ts = hv_get_adj_host_time();
225
226	do_settimeofday64(&ts);
227}
228
229/*
230 * Synchronize time with host after reboot, restore, etc.
231 *
232 * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
233 * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
234 * message after the timesync channel is opened. Since the hv_utils module is
235 * loaded after hv_vmbus, the first message is usually missed. This bit is
236 * considered a hard request to discipline the clock.
237 *
238 * ICTIMESYNCFLAG_SAMPLE bit indicates a time sample from host. This is
239 * typically used as a hint to the guest. The guest is under no obligation
240 * to discipline the clock.
241 */
242static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags)
243{
244	unsigned long flags;
245	u64 cur_reftime;
246
247	/*
248	 * Save the adjusted time sample from the host and the snapshot
249	 * of the current system time.
250	 */
251	spin_lock_irqsave(&host_ts.lock, flags);
252
253	cur_reftime = hyperv_cs->read(hyperv_cs);
254	host_ts.host_time = hosttime;
255	host_ts.ref_time = cur_reftime;
256
257	/*
258	 * TimeSync v4 messages contain reference time (guest's Hyper-V
259	 * clocksource read when the time sample was generated), we can
260	 * improve the precision by adding the delta between now and the
261	 * time of generation. For older protocols we set
262	 * reftime == cur_reftime on call.
263	 */
264	host_ts.host_time += (cur_reftime - reftime);
265
266	spin_unlock_irqrestore(&host_ts.lock, flags);
267
268	/* Schedule work to do do_settimeofday64() */
269	if (adj_flags & ICTIMESYNCFLAG_SYNC)
270		schedule_work(&adj_time_work);
271}
272
273/*
274 * Time Sync Channel message handler.
275 */
276static void timesync_onchannelcallback(void *context)
277{
278	struct vmbus_channel *channel = context;
279	u32 recvlen;
280	u64 requestid;
281	struct icmsg_hdr *icmsghdrp;
282	struct ictimesync_data *timedatap;
283	struct ictimesync_ref_data *refdata;
284	u8 *time_txf_buf = util_timesynch.recv_buffer;
285
286	vmbus_recvpacket(channel, time_txf_buf,
287			 PAGE_SIZE, &recvlen, &requestid);
288
289	if (recvlen > 0) {
290		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
291				sizeof(struct vmbuspipe_hdr)];
292
293		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
294			if (vmbus_prep_negotiate_resp(icmsghdrp, time_txf_buf,
295						fw_versions, FW_VER_COUNT,
296						ts_versions, TS_VER_COUNT,
297						NULL, &ts_srv_version)) {
298				pr_info("TimeSync IC version %d.%d\n",
299					ts_srv_version >> 16,
300					ts_srv_version & 0xFFFF);
301			}
302		} else {
303			if (ts_srv_version > TS_VERSION_3) {
304				refdata = (struct ictimesync_ref_data *)
305					&time_txf_buf[
306					sizeof(struct vmbuspipe_hdr) +
307					sizeof(struct icmsg_hdr)];
308
309				adj_guesttime(refdata->parenttime,
310						refdata->vmreferencetime,
311						refdata->flags);
312			} else {
313				timedatap = (struct ictimesync_data *)
314					&time_txf_buf[
315					sizeof(struct vmbuspipe_hdr) +
316					sizeof(struct icmsg_hdr)];
317				adj_guesttime(timedatap->parenttime,
318					      hyperv_cs->read(hyperv_cs),
319					      timedatap->flags);
320			}
321		}
322
323		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
324			| ICMSGHDRFLAG_RESPONSE;
325
326		vmbus_sendpacket(channel, time_txf_buf,
327				recvlen, requestid,
328				VM_PKT_DATA_INBAND, 0);
329	}
330}
331
332/*
333 * Heartbeat functionality.
334 * Every two seconds, Hyper-V send us a heartbeat request message.
335 * we respond to this message, and Hyper-V knows we are alive.
336 */
337static void heartbeat_onchannelcallback(void *context)
338{
339	struct vmbus_channel *channel = context;
340	u32 recvlen;
341	u64 requestid;
342	struct icmsg_hdr *icmsghdrp;
343	struct heartbeat_msg_data *heartbeat_msg;
344	u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
345
346	while (1) {
347
348		vmbus_recvpacket(channel, hbeat_txf_buf,
349				 PAGE_SIZE, &recvlen, &requestid);
350
351		if (!recvlen)
352			break;
353
354		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
355				sizeof(struct vmbuspipe_hdr)];
356
357		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
358			if (vmbus_prep_negotiate_resp(icmsghdrp,
359					hbeat_txf_buf,
360					fw_versions, FW_VER_COUNT,
361					hb_versions, HB_VER_COUNT,
362					NULL, &hb_srv_version)) {
363
364				pr_info("Heartbeat IC version %d.%d\n",
365					hb_srv_version >> 16,
366					hb_srv_version & 0xFFFF);
367			}
368		} else {
369			heartbeat_msg =
370				(struct heartbeat_msg_data *)&hbeat_txf_buf[
371					sizeof(struct vmbuspipe_hdr) +
372					sizeof(struct icmsg_hdr)];
373
374			heartbeat_msg->seq_num += 1;
375		}
376
377		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
378			| ICMSGHDRFLAG_RESPONSE;
379
380		vmbus_sendpacket(channel, hbeat_txf_buf,
381				       recvlen, requestid,
382				       VM_PKT_DATA_INBAND, 0);
383	}
384}
385
386static int util_probe(struct hv_device *dev,
387			const struct hv_vmbus_device_id *dev_id)
388{
389	struct hv_util_service *srv =
390		(struct hv_util_service *)dev_id->driver_data;
391	int ret;
392
393	srv->recv_buffer = kmalloc(PAGE_SIZE * 4, GFP_KERNEL);
394	if (!srv->recv_buffer)
395		return -ENOMEM;
396	srv->channel = dev->channel;
397	if (srv->util_init) {
398		ret = srv->util_init(srv);
399		if (ret) {
400			ret = -ENODEV;
401			goto error1;
402		}
403	}
404
405	/*
406	 * The set of services managed by the util driver are not performance
407	 * critical and do not need batched reading. Furthermore, some services
408	 * such as KVP can only handle one message from the host at a time.
409	 * Turn off batched reading for all util drivers before we open the
410	 * channel.
411	 */
412	set_channel_read_mode(dev->channel, HV_CALL_DIRECT);
413
414	hv_set_drvdata(dev, srv);
415
416	ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
417			srv->util_cb, dev->channel);
418	if (ret)
419		goto error;
420
421	return 0;
422
423error:
424	if (srv->util_deinit)
425		srv->util_deinit();
426error1:
427	kfree(srv->recv_buffer);
428	return ret;
429}
430
431static int util_remove(struct hv_device *dev)
432{
433	struct hv_util_service *srv = hv_get_drvdata(dev);
434
435	if (srv->util_deinit)
436		srv->util_deinit();
437	vmbus_close(dev->channel);
438	kfree(srv->recv_buffer);
439
440	return 0;
441}
442
443static const struct hv_vmbus_device_id id_table[] = {
444	/* Shutdown guid */
445	{ HV_SHUTDOWN_GUID,
446	  .driver_data = (unsigned long)&util_shutdown
447	},
448	/* Time synch guid */
449	{ HV_TS_GUID,
450	  .driver_data = (unsigned long)&util_timesynch
451	},
452	/* Heartbeat guid */
453	{ HV_HEART_BEAT_GUID,
454	  .driver_data = (unsigned long)&util_heartbeat
455	},
456	/* KVP guid */
457	{ HV_KVP_GUID,
458	  .driver_data = (unsigned long)&util_kvp
459	},
460	/* VSS GUID */
461	{ HV_VSS_GUID,
462	  .driver_data = (unsigned long)&util_vss
463	},
464	/* File copy GUID */
465	{ HV_FCOPY_GUID,
466	  .driver_data = (unsigned long)&util_fcopy
467	},
468	{ },
469};
470
471MODULE_DEVICE_TABLE(vmbus, id_table);
472
473/* The one and only one */
474static  struct hv_driver util_drv = {
475	.name = "hv_utils",
476	.id_table = id_table,
477	.probe =  util_probe,
478	.remove =  util_remove,
479	.driver = {
480		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
481	},
482};
483
484static int hv_ptp_enable(struct ptp_clock_info *info,
485			 struct ptp_clock_request *request, int on)
486{
487	return -EOPNOTSUPP;
488}
489
490static int hv_ptp_settime(struct ptp_clock_info *p, const struct timespec64 *ts)
491{
492	return -EOPNOTSUPP;
493}
494
495static int hv_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
496{
497	return -EOPNOTSUPP;
498}
499static int hv_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
500{
501	return -EOPNOTSUPP;
502}
503
504static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
505{
506	*ts = hv_get_adj_host_time();
507
508	return 0;
509}
510
511static struct ptp_clock_info ptp_hyperv_info = {
512	.name		= "hyperv",
513	.enable         = hv_ptp_enable,
514	.adjtime        = hv_ptp_adjtime,
515	.adjfreq        = hv_ptp_adjfreq,
516	.gettime64      = hv_ptp_gettime,
517	.settime64      = hv_ptp_settime,
518	.owner		= THIS_MODULE,
519};
520
521static struct ptp_clock *hv_ptp_clock;
522
523static int hv_timesync_init(struct hv_util_service *srv)
524{
525	/* TimeSync requires Hyper-V clocksource. */
526	if (!hyperv_cs)
527		return -ENODEV;
528
529	spin_lock_init(&host_ts.lock);
530
531	INIT_WORK(&adj_time_work, hv_set_host_time);
532
533	/*
534	 * ptp_clock_register() returns NULL when CONFIG_PTP_1588_CLOCK is
535	 * disabled but the driver is still useful without the PTP device
536	 * as it still handles the ICTIMESYNCFLAG_SYNC case.
537	 */
538	hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL);
539	if (IS_ERR_OR_NULL(hv_ptp_clock)) {
540		pr_err("cannot register PTP clock: %ld\n",
541		       PTR_ERR(hv_ptp_clock));
542		hv_ptp_clock = NULL;
543	}
544
545	return 0;
546}
547
548static void hv_timesync_deinit(void)
549{
550	if (hv_ptp_clock)
551		ptp_clock_unregister(hv_ptp_clock);
552	cancel_work_sync(&adj_time_work);
553}
554
555static int __init init_hyperv_utils(void)
556{
557	pr_info("Registering HyperV Utility Driver\n");
558
559	return vmbus_driver_register(&util_drv);
560}
561
562static void exit_hyperv_utils(void)
563{
564	pr_info("De-Registered HyperV Utility Driver\n");
565
566	vmbus_driver_unregister(&util_drv);
567}
568
569module_init(init_hyperv_utils);
570module_exit(exit_hyperv_utils);
571
572MODULE_DESCRIPTION("Hyper-V Utilities");
573MODULE_LICENSE("GPL");
v4.17
 
  1/*
  2 * Copyright (c) 2010, Microsoft Corporation.
  3 *
  4 * This program is free software; you can redistribute it and/or modify it
  5 * under the terms and conditions of the GNU General Public License,
  6 * version 2, as published by the Free Software Foundation.
  7 *
  8 * This program is distributed in the hope it will be useful, but WITHOUT
  9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 11 * more details.
 12 *
 13 * You should have received a copy of the GNU General Public License along with
 14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 15 * Place - Suite 330, Boston, MA 02111-1307 USA.
 16 *
 17 * Authors:
 18 *   Haiyang Zhang <haiyangz@microsoft.com>
 19 *   Hank Janssen  <hjanssen@microsoft.com>
 20 */
 21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 22
 23#include <linux/kernel.h>
 24#include <linux/init.h>
 25#include <linux/module.h>
 26#include <linux/slab.h>
 27#include <linux/sysctl.h>
 28#include <linux/reboot.h>
 29#include <linux/hyperv.h>
 30#include <linux/clockchips.h>
 31#include <linux/ptp_clock_kernel.h>
 
 32#include <asm/mshyperv.h>
 33
 34#include "hyperv_vmbus.h"
 35
 36#define SD_MAJOR	3
 37#define SD_MINOR	0
 38#define SD_VERSION	(SD_MAJOR << 16 | SD_MINOR)
 39
 40#define SD_MAJOR_1	1
 41#define SD_VERSION_1	(SD_MAJOR_1 << 16 | SD_MINOR)
 42
 43#define TS_MAJOR	4
 44#define TS_MINOR	0
 45#define TS_VERSION	(TS_MAJOR << 16 | TS_MINOR)
 46
 47#define TS_MAJOR_1	1
 48#define TS_VERSION_1	(TS_MAJOR_1 << 16 | TS_MINOR)
 49
 50#define TS_MAJOR_3	3
 51#define TS_VERSION_3	(TS_MAJOR_3 << 16 | TS_MINOR)
 52
 53#define HB_MAJOR	3
 54#define HB_MINOR	0
 55#define HB_VERSION	(HB_MAJOR << 16 | HB_MINOR)
 56
 57#define HB_MAJOR_1	1
 58#define HB_VERSION_1	(HB_MAJOR_1 << 16 | HB_MINOR)
 59
 60static int sd_srv_version;
 61static int ts_srv_version;
 62static int hb_srv_version;
 63
 64#define SD_VER_COUNT 2
 65static const int sd_versions[] = {
 66	SD_VERSION,
 67	SD_VERSION_1
 68};
 69
 70#define TS_VER_COUNT 3
 71static const int ts_versions[] = {
 72	TS_VERSION,
 73	TS_VERSION_3,
 74	TS_VERSION_1
 75};
 76
 77#define HB_VER_COUNT 2
 78static const int hb_versions[] = {
 79	HB_VERSION,
 80	HB_VERSION_1
 81};
 82
 83#define FW_VER_COUNT 2
 84static const int fw_versions[] = {
 85	UTIL_FW_VERSION,
 86	UTIL_WS2K8_FW_VERSION
 87};
 88
 89static void shutdown_onchannelcallback(void *context);
 90static struct hv_util_service util_shutdown = {
 91	.util_cb = shutdown_onchannelcallback,
 92};
 93
 94static int hv_timesync_init(struct hv_util_service *srv);
 95static void hv_timesync_deinit(void);
 96
 97static void timesync_onchannelcallback(void *context);
 98static struct hv_util_service util_timesynch = {
 99	.util_cb = timesync_onchannelcallback,
100	.util_init = hv_timesync_init,
101	.util_deinit = hv_timesync_deinit,
102};
103
104static void heartbeat_onchannelcallback(void *context);
105static struct hv_util_service util_heartbeat = {
106	.util_cb = heartbeat_onchannelcallback,
107};
108
109static struct hv_util_service util_kvp = {
110	.util_cb = hv_kvp_onchannelcallback,
111	.util_init = hv_kvp_init,
112	.util_deinit = hv_kvp_deinit,
113};
114
115static struct hv_util_service util_vss = {
116	.util_cb = hv_vss_onchannelcallback,
117	.util_init = hv_vss_init,
118	.util_deinit = hv_vss_deinit,
119};
120
121static struct hv_util_service util_fcopy = {
122	.util_cb = hv_fcopy_onchannelcallback,
123	.util_init = hv_fcopy_init,
124	.util_deinit = hv_fcopy_deinit,
125};
126
127static void perform_shutdown(struct work_struct *dummy)
128{
129	orderly_poweroff(true);
130}
131
132/*
133 * Perform the shutdown operation in a thread context.
134 */
135static DECLARE_WORK(shutdown_work, perform_shutdown);
136
137static void shutdown_onchannelcallback(void *context)
138{
139	struct vmbus_channel *channel = context;
140	u32 recvlen;
141	u64 requestid;
142	bool execute_shutdown = false;
143	u8  *shut_txf_buf = util_shutdown.recv_buffer;
144
145	struct shutdown_msg_data *shutdown_msg;
146
147	struct icmsg_hdr *icmsghdrp;
148
149	vmbus_recvpacket(channel, shut_txf_buf,
150			 PAGE_SIZE, &recvlen, &requestid);
151
152	if (recvlen > 0) {
153		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
154			sizeof(struct vmbuspipe_hdr)];
155
156		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
157			if (vmbus_prep_negotiate_resp(icmsghdrp, shut_txf_buf,
158					fw_versions, FW_VER_COUNT,
159					sd_versions, SD_VER_COUNT,
160					NULL, &sd_srv_version)) {
161				pr_info("Shutdown IC version %d.%d\n",
162					sd_srv_version >> 16,
163					sd_srv_version & 0xFFFF);
164			}
165		} else {
166			shutdown_msg =
167				(struct shutdown_msg_data *)&shut_txf_buf[
168					sizeof(struct vmbuspipe_hdr) +
169					sizeof(struct icmsg_hdr)];
170
171			switch (shutdown_msg->flags) {
172			case 0:
173			case 1:
174				icmsghdrp->status = HV_S_OK;
175				execute_shutdown = true;
176
177				pr_info("Shutdown request received -"
178					    " graceful shutdown initiated\n");
179				break;
180			default:
181				icmsghdrp->status = HV_E_FAIL;
182				execute_shutdown = false;
183
184				pr_info("Shutdown request received -"
185					    " Invalid request\n");
186				break;
187			}
188		}
189
190		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
191			| ICMSGHDRFLAG_RESPONSE;
192
193		vmbus_sendpacket(channel, shut_txf_buf,
194				       recvlen, requestid,
195				       VM_PKT_DATA_INBAND, 0);
196	}
197
198	if (execute_shutdown == true)
199		schedule_work(&shutdown_work);
200}
201
202/*
203 * Set the host time in a process context.
204 */
205static struct work_struct adj_time_work;
206
207/*
208 * The last time sample, received from the host. PTP device responds to
209 * requests by using this data and the current partition-wide time reference
210 * count.
211 */
212static struct {
213	u64				host_time;
214	u64				ref_time;
215	spinlock_t			lock;
216} host_ts;
217
218static struct timespec64 hv_get_adj_host_time(void)
219{
220	struct timespec64 ts;
221	u64 newtime, reftime;
222	unsigned long flags;
223
224	spin_lock_irqsave(&host_ts.lock, flags);
225	reftime = hyperv_cs->read(hyperv_cs);
226	newtime = host_ts.host_time + (reftime - host_ts.ref_time);
227	ts = ns_to_timespec64((newtime - WLTIMEDELTA) * 100);
228	spin_unlock_irqrestore(&host_ts.lock, flags);
229
230	return ts;
231}
232
233static void hv_set_host_time(struct work_struct *work)
234{
235	struct timespec64 ts = hv_get_adj_host_time();
236
237	do_settimeofday64(&ts);
238}
239
240/*
241 * Synchronize time with host after reboot, restore, etc.
242 *
243 * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
244 * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
245 * message after the timesync channel is opened. Since the hv_utils module is
246 * loaded after hv_vmbus, the first message is usually missed. This bit is
247 * considered a hard request to discipline the clock.
248 *
249 * ICTIMESYNCFLAG_SAMPLE bit indicates a time sample from host. This is
250 * typically used as a hint to the guest. The guest is under no obligation
251 * to discipline the clock.
252 */
253static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags)
254{
255	unsigned long flags;
256	u64 cur_reftime;
257
258	/*
259	 * Save the adjusted time sample from the host and the snapshot
260	 * of the current system time.
261	 */
262	spin_lock_irqsave(&host_ts.lock, flags);
263
264	cur_reftime = hyperv_cs->read(hyperv_cs);
265	host_ts.host_time = hosttime;
266	host_ts.ref_time = cur_reftime;
267
268	/*
269	 * TimeSync v4 messages contain reference time (guest's Hyper-V
270	 * clocksource read when the time sample was generated), we can
271	 * improve the precision by adding the delta between now and the
272	 * time of generation. For older protocols we set
273	 * reftime == cur_reftime on call.
274	 */
275	host_ts.host_time += (cur_reftime - reftime);
276
277	spin_unlock_irqrestore(&host_ts.lock, flags);
278
279	/* Schedule work to do do_settimeofday64() */
280	if (adj_flags & ICTIMESYNCFLAG_SYNC)
281		schedule_work(&adj_time_work);
282}
283
284/*
285 * Time Sync Channel message handler.
286 */
287static void timesync_onchannelcallback(void *context)
288{
289	struct vmbus_channel *channel = context;
290	u32 recvlen;
291	u64 requestid;
292	struct icmsg_hdr *icmsghdrp;
293	struct ictimesync_data *timedatap;
294	struct ictimesync_ref_data *refdata;
295	u8 *time_txf_buf = util_timesynch.recv_buffer;
296
297	vmbus_recvpacket(channel, time_txf_buf,
298			 PAGE_SIZE, &recvlen, &requestid);
299
300	if (recvlen > 0) {
301		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
302				sizeof(struct vmbuspipe_hdr)];
303
304		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
305			if (vmbus_prep_negotiate_resp(icmsghdrp, time_txf_buf,
306						fw_versions, FW_VER_COUNT,
307						ts_versions, TS_VER_COUNT,
308						NULL, &ts_srv_version)) {
309				pr_info("TimeSync IC version %d.%d\n",
310					ts_srv_version >> 16,
311					ts_srv_version & 0xFFFF);
312			}
313		} else {
314			if (ts_srv_version > TS_VERSION_3) {
315				refdata = (struct ictimesync_ref_data *)
316					&time_txf_buf[
317					sizeof(struct vmbuspipe_hdr) +
318					sizeof(struct icmsg_hdr)];
319
320				adj_guesttime(refdata->parenttime,
321						refdata->vmreferencetime,
322						refdata->flags);
323			} else {
324				timedatap = (struct ictimesync_data *)
325					&time_txf_buf[
326					sizeof(struct vmbuspipe_hdr) +
327					sizeof(struct icmsg_hdr)];
328				adj_guesttime(timedatap->parenttime,
329					      hyperv_cs->read(hyperv_cs),
330					      timedatap->flags);
331			}
332		}
333
334		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
335			| ICMSGHDRFLAG_RESPONSE;
336
337		vmbus_sendpacket(channel, time_txf_buf,
338				recvlen, requestid,
339				VM_PKT_DATA_INBAND, 0);
340	}
341}
342
343/*
344 * Heartbeat functionality.
345 * Every two seconds, Hyper-V send us a heartbeat request message.
346 * we respond to this message, and Hyper-V knows we are alive.
347 */
348static void heartbeat_onchannelcallback(void *context)
349{
350	struct vmbus_channel *channel = context;
351	u32 recvlen;
352	u64 requestid;
353	struct icmsg_hdr *icmsghdrp;
354	struct heartbeat_msg_data *heartbeat_msg;
355	u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
356
357	while (1) {
358
359		vmbus_recvpacket(channel, hbeat_txf_buf,
360				 PAGE_SIZE, &recvlen, &requestid);
361
362		if (!recvlen)
363			break;
364
365		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
366				sizeof(struct vmbuspipe_hdr)];
367
368		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
369			if (vmbus_prep_negotiate_resp(icmsghdrp,
370					hbeat_txf_buf,
371					fw_versions, FW_VER_COUNT,
372					hb_versions, HB_VER_COUNT,
373					NULL, &hb_srv_version)) {
374
375				pr_info("Heartbeat IC version %d.%d\n",
376					hb_srv_version >> 16,
377					hb_srv_version & 0xFFFF);
378			}
379		} else {
380			heartbeat_msg =
381				(struct heartbeat_msg_data *)&hbeat_txf_buf[
382					sizeof(struct vmbuspipe_hdr) +
383					sizeof(struct icmsg_hdr)];
384
385			heartbeat_msg->seq_num += 1;
386		}
387
388		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
389			| ICMSGHDRFLAG_RESPONSE;
390
391		vmbus_sendpacket(channel, hbeat_txf_buf,
392				       recvlen, requestid,
393				       VM_PKT_DATA_INBAND, 0);
394	}
395}
396
397static int util_probe(struct hv_device *dev,
398			const struct hv_vmbus_device_id *dev_id)
399{
400	struct hv_util_service *srv =
401		(struct hv_util_service *)dev_id->driver_data;
402	int ret;
403
404	srv->recv_buffer = kmalloc(PAGE_SIZE * 4, GFP_KERNEL);
405	if (!srv->recv_buffer)
406		return -ENOMEM;
407	srv->channel = dev->channel;
408	if (srv->util_init) {
409		ret = srv->util_init(srv);
410		if (ret) {
411			ret = -ENODEV;
412			goto error1;
413		}
414	}
415
416	/*
417	 * The set of services managed by the util driver are not performance
418	 * critical and do not need batched reading. Furthermore, some services
419	 * such as KVP can only handle one message from the host at a time.
420	 * Turn off batched reading for all util drivers before we open the
421	 * channel.
422	 */
423	set_channel_read_mode(dev->channel, HV_CALL_DIRECT);
424
425	hv_set_drvdata(dev, srv);
426
427	ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
428			srv->util_cb, dev->channel);
429	if (ret)
430		goto error;
431
432	return 0;
433
434error:
435	if (srv->util_deinit)
436		srv->util_deinit();
437error1:
438	kfree(srv->recv_buffer);
439	return ret;
440}
441
442static int util_remove(struct hv_device *dev)
443{
444	struct hv_util_service *srv = hv_get_drvdata(dev);
445
446	if (srv->util_deinit)
447		srv->util_deinit();
448	vmbus_close(dev->channel);
449	kfree(srv->recv_buffer);
450
451	return 0;
452}
453
454static const struct hv_vmbus_device_id id_table[] = {
455	/* Shutdown guid */
456	{ HV_SHUTDOWN_GUID,
457	  .driver_data = (unsigned long)&util_shutdown
458	},
459	/* Time synch guid */
460	{ HV_TS_GUID,
461	  .driver_data = (unsigned long)&util_timesynch
462	},
463	/* Heartbeat guid */
464	{ HV_HEART_BEAT_GUID,
465	  .driver_data = (unsigned long)&util_heartbeat
466	},
467	/* KVP guid */
468	{ HV_KVP_GUID,
469	  .driver_data = (unsigned long)&util_kvp
470	},
471	/* VSS GUID */
472	{ HV_VSS_GUID,
473	  .driver_data = (unsigned long)&util_vss
474	},
475	/* File copy GUID */
476	{ HV_FCOPY_GUID,
477	  .driver_data = (unsigned long)&util_fcopy
478	},
479	{ },
480};
481
482MODULE_DEVICE_TABLE(vmbus, id_table);
483
484/* The one and only one */
485static  struct hv_driver util_drv = {
486	.name = "hv_util",
487	.id_table = id_table,
488	.probe =  util_probe,
489	.remove =  util_remove,
 
 
 
490};
491
492static int hv_ptp_enable(struct ptp_clock_info *info,
493			 struct ptp_clock_request *request, int on)
494{
495	return -EOPNOTSUPP;
496}
497
498static int hv_ptp_settime(struct ptp_clock_info *p, const struct timespec64 *ts)
499{
500	return -EOPNOTSUPP;
501}
502
503static int hv_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
504{
505	return -EOPNOTSUPP;
506}
507static int hv_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
508{
509	return -EOPNOTSUPP;
510}
511
512static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
513{
514	*ts = hv_get_adj_host_time();
515
516	return 0;
517}
518
519static struct ptp_clock_info ptp_hyperv_info = {
520	.name		= "hyperv",
521	.enable         = hv_ptp_enable,
522	.adjtime        = hv_ptp_adjtime,
523	.adjfreq        = hv_ptp_adjfreq,
524	.gettime64      = hv_ptp_gettime,
525	.settime64      = hv_ptp_settime,
526	.owner		= THIS_MODULE,
527};
528
529static struct ptp_clock *hv_ptp_clock;
530
531static int hv_timesync_init(struct hv_util_service *srv)
532{
533	/* TimeSync requires Hyper-V clocksource. */
534	if (!hyperv_cs)
535		return -ENODEV;
536
537	spin_lock_init(&host_ts.lock);
538
539	INIT_WORK(&adj_time_work, hv_set_host_time);
540
541	/*
542	 * ptp_clock_register() returns NULL when CONFIG_PTP_1588_CLOCK is
543	 * disabled but the driver is still useful without the PTP device
544	 * as it still handles the ICTIMESYNCFLAG_SYNC case.
545	 */
546	hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL);
547	if (IS_ERR_OR_NULL(hv_ptp_clock)) {
548		pr_err("cannot register PTP clock: %ld\n",
549		       PTR_ERR(hv_ptp_clock));
550		hv_ptp_clock = NULL;
551	}
552
553	return 0;
554}
555
556static void hv_timesync_deinit(void)
557{
558	if (hv_ptp_clock)
559		ptp_clock_unregister(hv_ptp_clock);
560	cancel_work_sync(&adj_time_work);
561}
562
563static int __init init_hyperv_utils(void)
564{
565	pr_info("Registering HyperV Utility Driver\n");
566
567	return vmbus_driver_register(&util_drv);
568}
569
570static void exit_hyperv_utils(void)
571{
572	pr_info("De-Registered HyperV Utility Driver\n");
573
574	vmbus_driver_unregister(&util_drv);
575}
576
577module_init(init_hyperv_utils);
578module_exit(exit_hyperv_utils);
579
580MODULE_DESCRIPTION("Hyper-V Utilities");
581MODULE_LICENSE("GPL");