cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hv_util.c (20117B)


      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 <asm/mshyperv.h>
     21
     22#include "hyperv_vmbus.h"
     23
     24#define SD_MAJOR	3
     25#define SD_MINOR	0
     26#define SD_MINOR_1	1
     27#define SD_MINOR_2	2
     28#define SD_VERSION_3_1	(SD_MAJOR << 16 | SD_MINOR_1)
     29#define SD_VERSION_3_2	(SD_MAJOR << 16 | SD_MINOR_2)
     30#define SD_VERSION	(SD_MAJOR << 16 | SD_MINOR)
     31
     32#define SD_MAJOR_1	1
     33#define SD_VERSION_1	(SD_MAJOR_1 << 16 | SD_MINOR)
     34
     35#define TS_MAJOR	4
     36#define TS_MINOR	0
     37#define TS_VERSION	(TS_MAJOR << 16 | TS_MINOR)
     38
     39#define TS_MAJOR_1	1
     40#define TS_VERSION_1	(TS_MAJOR_1 << 16 | TS_MINOR)
     41
     42#define TS_MAJOR_3	3
     43#define TS_VERSION_3	(TS_MAJOR_3 << 16 | TS_MINOR)
     44
     45#define HB_MAJOR	3
     46#define HB_MINOR	0
     47#define HB_VERSION	(HB_MAJOR << 16 | HB_MINOR)
     48
     49#define HB_MAJOR_1	1
     50#define HB_VERSION_1	(HB_MAJOR_1 << 16 | HB_MINOR)
     51
     52static int sd_srv_version;
     53static int ts_srv_version;
     54static int hb_srv_version;
     55
     56#define SD_VER_COUNT 4
     57static const int sd_versions[] = {
     58	SD_VERSION_3_2,
     59	SD_VERSION_3_1,
     60	SD_VERSION,
     61	SD_VERSION_1
     62};
     63
     64#define TS_VER_COUNT 3
     65static const int ts_versions[] = {
     66	TS_VERSION,
     67	TS_VERSION_3,
     68	TS_VERSION_1
     69};
     70
     71#define HB_VER_COUNT 2
     72static const int hb_versions[] = {
     73	HB_VERSION,
     74	HB_VERSION_1
     75};
     76
     77#define FW_VER_COUNT 2
     78static const int fw_versions[] = {
     79	UTIL_FW_VERSION,
     80	UTIL_WS2K8_FW_VERSION
     81};
     82
     83/*
     84 * Send the "hibernate" udev event in a thread context.
     85 */
     86struct hibernate_work_context {
     87	struct work_struct work;
     88	struct hv_device *dev;
     89};
     90
     91static struct hibernate_work_context hibernate_context;
     92static bool hibernation_supported;
     93
     94static void send_hibernate_uevent(struct work_struct *work)
     95{
     96	char *uevent_env[2] = { "EVENT=hibernate", NULL };
     97	struct hibernate_work_context *ctx;
     98
     99	ctx = container_of(work, struct hibernate_work_context, work);
    100
    101	kobject_uevent_env(&ctx->dev->device.kobj, KOBJ_CHANGE, uevent_env);
    102
    103	pr_info("Sent hibernation uevent\n");
    104}
    105
    106static int hv_shutdown_init(struct hv_util_service *srv)
    107{
    108	struct vmbus_channel *channel = srv->channel;
    109
    110	INIT_WORK(&hibernate_context.work, send_hibernate_uevent);
    111	hibernate_context.dev = channel->device_obj;
    112
    113	hibernation_supported = hv_is_hibernation_supported();
    114
    115	return 0;
    116}
    117
    118static void shutdown_onchannelcallback(void *context);
    119static struct hv_util_service util_shutdown = {
    120	.util_cb = shutdown_onchannelcallback,
    121	.util_init = hv_shutdown_init,
    122};
    123
    124static int hv_timesync_init(struct hv_util_service *srv);
    125static int hv_timesync_pre_suspend(void);
    126static void hv_timesync_deinit(void);
    127
    128static void timesync_onchannelcallback(void *context);
    129static struct hv_util_service util_timesynch = {
    130	.util_cb = timesync_onchannelcallback,
    131	.util_init = hv_timesync_init,
    132	.util_pre_suspend = hv_timesync_pre_suspend,
    133	.util_deinit = hv_timesync_deinit,
    134};
    135
    136static void heartbeat_onchannelcallback(void *context);
    137static struct hv_util_service util_heartbeat = {
    138	.util_cb = heartbeat_onchannelcallback,
    139};
    140
    141static struct hv_util_service util_kvp = {
    142	.util_cb = hv_kvp_onchannelcallback,
    143	.util_init = hv_kvp_init,
    144	.util_pre_suspend = hv_kvp_pre_suspend,
    145	.util_pre_resume = hv_kvp_pre_resume,
    146	.util_deinit = hv_kvp_deinit,
    147};
    148
    149static struct hv_util_service util_vss = {
    150	.util_cb = hv_vss_onchannelcallback,
    151	.util_init = hv_vss_init,
    152	.util_pre_suspend = hv_vss_pre_suspend,
    153	.util_pre_resume = hv_vss_pre_resume,
    154	.util_deinit = hv_vss_deinit,
    155};
    156
    157static struct hv_util_service util_fcopy = {
    158	.util_cb = hv_fcopy_onchannelcallback,
    159	.util_init = hv_fcopy_init,
    160	.util_pre_suspend = hv_fcopy_pre_suspend,
    161	.util_pre_resume = hv_fcopy_pre_resume,
    162	.util_deinit = hv_fcopy_deinit,
    163};
    164
    165static void perform_shutdown(struct work_struct *dummy)
    166{
    167	orderly_poweroff(true);
    168}
    169
    170static void perform_restart(struct work_struct *dummy)
    171{
    172	orderly_reboot();
    173}
    174
    175/*
    176 * Perform the shutdown operation in a thread context.
    177 */
    178static DECLARE_WORK(shutdown_work, perform_shutdown);
    179
    180/*
    181 * Perform the restart operation in a thread context.
    182 */
    183static DECLARE_WORK(restart_work, perform_restart);
    184
    185static void shutdown_onchannelcallback(void *context)
    186{
    187	struct vmbus_channel *channel = context;
    188	struct work_struct *work = NULL;
    189	u32 recvlen;
    190	u64 requestid;
    191	u8  *shut_txf_buf = util_shutdown.recv_buffer;
    192
    193	struct shutdown_msg_data *shutdown_msg;
    194
    195	struct icmsg_hdr *icmsghdrp;
    196
    197	if (vmbus_recvpacket(channel, shut_txf_buf, HV_HYP_PAGE_SIZE, &recvlen, &requestid)) {
    198		pr_err_ratelimited("Shutdown request received. Could not read into shut txf buf\n");
    199		return;
    200	}
    201
    202	if (!recvlen)
    203		return;
    204
    205	/* Ensure recvlen is big enough to read header data */
    206	if (recvlen < ICMSG_HDR) {
    207		pr_err_ratelimited("Shutdown request received. Packet length too small: %d\n",
    208				   recvlen);
    209		return;
    210	}
    211
    212	icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[sizeof(struct vmbuspipe_hdr)];
    213
    214	if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
    215		if (vmbus_prep_negotiate_resp(icmsghdrp,
    216				shut_txf_buf, recvlen,
    217				fw_versions, FW_VER_COUNT,
    218				sd_versions, SD_VER_COUNT,
    219				NULL, &sd_srv_version)) {
    220			pr_info("Shutdown IC version %d.%d\n",
    221				sd_srv_version >> 16,
    222				sd_srv_version & 0xFFFF);
    223		}
    224	} else if (icmsghdrp->icmsgtype == ICMSGTYPE_SHUTDOWN) {
    225		/* Ensure recvlen is big enough to contain shutdown_msg_data struct */
    226		if (recvlen < ICMSG_HDR + sizeof(struct shutdown_msg_data)) {
    227			pr_err_ratelimited("Invalid shutdown msg data. Packet length too small: %u\n",
    228					   recvlen);
    229			return;
    230		}
    231
    232		shutdown_msg = (struct shutdown_msg_data *)&shut_txf_buf[ICMSG_HDR];
    233
    234		/*
    235		 * shutdown_msg->flags can be 0(shut down), 2(reboot),
    236		 * or 4(hibernate). It may bitwise-OR 1, which means
    237		 * performing the request by force. Linux always tries
    238		 * to perform the request by force.
    239		 */
    240		switch (shutdown_msg->flags) {
    241		case 0:
    242		case 1:
    243			icmsghdrp->status = HV_S_OK;
    244			work = &shutdown_work;
    245			pr_info("Shutdown request received - graceful shutdown initiated\n");
    246			break;
    247		case 2:
    248		case 3:
    249			icmsghdrp->status = HV_S_OK;
    250			work = &restart_work;
    251			pr_info("Restart request received - graceful restart initiated\n");
    252			break;
    253		case 4:
    254		case 5:
    255			pr_info("Hibernation request received\n");
    256			icmsghdrp->status = hibernation_supported ?
    257				HV_S_OK : HV_E_FAIL;
    258			if (hibernation_supported)
    259				work = &hibernate_context.work;
    260			break;
    261		default:
    262			icmsghdrp->status = HV_E_FAIL;
    263			pr_info("Shutdown request received - Invalid request\n");
    264			break;
    265		}
    266	} else {
    267		icmsghdrp->status = HV_E_FAIL;
    268		pr_err_ratelimited("Shutdown request received. Invalid msg type: %d\n",
    269				   icmsghdrp->icmsgtype);
    270	}
    271
    272	icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
    273		| ICMSGHDRFLAG_RESPONSE;
    274
    275	vmbus_sendpacket(channel, shut_txf_buf,
    276			 recvlen, requestid,
    277			 VM_PKT_DATA_INBAND, 0);
    278
    279	if (work)
    280		schedule_work(work);
    281}
    282
    283/*
    284 * Set the host time in a process context.
    285 */
    286static struct work_struct adj_time_work;
    287
    288/*
    289 * The last time sample, received from the host. PTP device responds to
    290 * requests by using this data and the current partition-wide time reference
    291 * count.
    292 */
    293static struct {
    294	u64				host_time;
    295	u64				ref_time;
    296	spinlock_t			lock;
    297} host_ts;
    298
    299static inline u64 reftime_to_ns(u64 reftime)
    300{
    301	return (reftime - WLTIMEDELTA) * 100;
    302}
    303
    304/*
    305 * Hard coded threshold for host timesync delay: 600 seconds
    306 */
    307static const u64 HOST_TIMESYNC_DELAY_THRESH = 600 * (u64)NSEC_PER_SEC;
    308
    309static int hv_get_adj_host_time(struct timespec64 *ts)
    310{
    311	u64 newtime, reftime, timediff_adj;
    312	unsigned long flags;
    313	int ret = 0;
    314
    315	spin_lock_irqsave(&host_ts.lock, flags);
    316	reftime = hv_read_reference_counter();
    317
    318	/*
    319	 * We need to let the caller know that last update from host
    320	 * is older than the max allowable threshold. clock_gettime()
    321	 * and PTP ioctl do not have a documented error that we could
    322	 * return for this specific case. Use ESTALE to report this.
    323	 */
    324	timediff_adj = reftime - host_ts.ref_time;
    325	if (timediff_adj * 100 > HOST_TIMESYNC_DELAY_THRESH) {
    326		pr_warn_once("TIMESYNC IC: Stale time stamp, %llu nsecs old\n",
    327			     (timediff_adj * 100));
    328		ret = -ESTALE;
    329	}
    330
    331	newtime = host_ts.host_time + timediff_adj;
    332	*ts = ns_to_timespec64(reftime_to_ns(newtime));
    333	spin_unlock_irqrestore(&host_ts.lock, flags);
    334
    335	return ret;
    336}
    337
    338static void hv_set_host_time(struct work_struct *work)
    339{
    340
    341	struct timespec64 ts;
    342
    343	if (!hv_get_adj_host_time(&ts))
    344		do_settimeofday64(&ts);
    345}
    346
    347/*
    348 * Synchronize time with host after reboot, restore, etc.
    349 *
    350 * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
    351 * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
    352 * message after the timesync channel is opened. Since the hv_utils module is
    353 * loaded after hv_vmbus, the first message is usually missed. This bit is
    354 * considered a hard request to discipline the clock.
    355 *
    356 * ICTIMESYNCFLAG_SAMPLE bit indicates a time sample from host. This is
    357 * typically used as a hint to the guest. The guest is under no obligation
    358 * to discipline the clock.
    359 */
    360static inline void adj_guesttime(u64 hosttime, u64 reftime, u8 adj_flags)
    361{
    362	unsigned long flags;
    363	u64 cur_reftime;
    364
    365	/*
    366	 * Save the adjusted time sample from the host and the snapshot
    367	 * of the current system time.
    368	 */
    369	spin_lock_irqsave(&host_ts.lock, flags);
    370
    371	cur_reftime = hv_read_reference_counter();
    372	host_ts.host_time = hosttime;
    373	host_ts.ref_time = cur_reftime;
    374
    375	/*
    376	 * TimeSync v4 messages contain reference time (guest's Hyper-V
    377	 * clocksource read when the time sample was generated), we can
    378	 * improve the precision by adding the delta between now and the
    379	 * time of generation. For older protocols we set
    380	 * reftime == cur_reftime on call.
    381	 */
    382	host_ts.host_time += (cur_reftime - reftime);
    383
    384	spin_unlock_irqrestore(&host_ts.lock, flags);
    385
    386	/* Schedule work to do do_settimeofday64() */
    387	if (adj_flags & ICTIMESYNCFLAG_SYNC)
    388		schedule_work(&adj_time_work);
    389}
    390
    391/*
    392 * Time Sync Channel message handler.
    393 */
    394static void timesync_onchannelcallback(void *context)
    395{
    396	struct vmbus_channel *channel = context;
    397	u32 recvlen;
    398	u64 requestid;
    399	struct icmsg_hdr *icmsghdrp;
    400	struct ictimesync_data *timedatap;
    401	struct ictimesync_ref_data *refdata;
    402	u8 *time_txf_buf = util_timesynch.recv_buffer;
    403
    404	/*
    405	 * Drain the ring buffer and use the last packet to update
    406	 * host_ts
    407	 */
    408	while (1) {
    409		int ret = vmbus_recvpacket(channel, time_txf_buf,
    410					   HV_HYP_PAGE_SIZE, &recvlen,
    411					   &requestid);
    412		if (ret) {
    413			pr_err_ratelimited("TimeSync IC pkt recv failed (Err: %d)\n",
    414					   ret);
    415			break;
    416		}
    417
    418		if (!recvlen)
    419			break;
    420
    421		/* Ensure recvlen is big enough to read header data */
    422		if (recvlen < ICMSG_HDR) {
    423			pr_err_ratelimited("Timesync request received. Packet length too small: %d\n",
    424					   recvlen);
    425			break;
    426		}
    427
    428		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
    429				sizeof(struct vmbuspipe_hdr)];
    430
    431		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
    432			if (vmbus_prep_negotiate_resp(icmsghdrp,
    433						time_txf_buf, recvlen,
    434						fw_versions, FW_VER_COUNT,
    435						ts_versions, TS_VER_COUNT,
    436						NULL, &ts_srv_version)) {
    437				pr_info("TimeSync IC version %d.%d\n",
    438					ts_srv_version >> 16,
    439					ts_srv_version & 0xFFFF);
    440			}
    441		} else if (icmsghdrp->icmsgtype == ICMSGTYPE_TIMESYNC) {
    442			if (ts_srv_version > TS_VERSION_3) {
    443				/* Ensure recvlen is big enough to read ictimesync_ref_data */
    444				if (recvlen < ICMSG_HDR + sizeof(struct ictimesync_ref_data)) {
    445					pr_err_ratelimited("Invalid ictimesync ref data. Length too small: %u\n",
    446							   recvlen);
    447					break;
    448				}
    449				refdata = (struct ictimesync_ref_data *)&time_txf_buf[ICMSG_HDR];
    450
    451				adj_guesttime(refdata->parenttime,
    452						refdata->vmreferencetime,
    453						refdata->flags);
    454			} else {
    455				/* Ensure recvlen is big enough to read ictimesync_data */
    456				if (recvlen < ICMSG_HDR + sizeof(struct ictimesync_data)) {
    457					pr_err_ratelimited("Invalid ictimesync data. Length too small: %u\n",
    458							   recvlen);
    459					break;
    460				}
    461				timedatap = (struct ictimesync_data *)&time_txf_buf[ICMSG_HDR];
    462
    463				adj_guesttime(timedatap->parenttime,
    464					      hv_read_reference_counter(),
    465					      timedatap->flags);
    466			}
    467		} else {
    468			icmsghdrp->status = HV_E_FAIL;
    469			pr_err_ratelimited("Timesync request received. Invalid msg type: %d\n",
    470					   icmsghdrp->icmsgtype);
    471		}
    472
    473		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
    474			| ICMSGHDRFLAG_RESPONSE;
    475
    476		vmbus_sendpacket(channel, time_txf_buf,
    477				 recvlen, requestid,
    478				 VM_PKT_DATA_INBAND, 0);
    479	}
    480}
    481
    482/*
    483 * Heartbeat functionality.
    484 * Every two seconds, Hyper-V send us a heartbeat request message.
    485 * we respond to this message, and Hyper-V knows we are alive.
    486 */
    487static void heartbeat_onchannelcallback(void *context)
    488{
    489	struct vmbus_channel *channel = context;
    490	u32 recvlen;
    491	u64 requestid;
    492	struct icmsg_hdr *icmsghdrp;
    493	struct heartbeat_msg_data *heartbeat_msg;
    494	u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
    495
    496	while (1) {
    497
    498		if (vmbus_recvpacket(channel, hbeat_txf_buf, HV_HYP_PAGE_SIZE,
    499				     &recvlen, &requestid)) {
    500			pr_err_ratelimited("Heartbeat request received. Could not read into hbeat txf buf\n");
    501			return;
    502		}
    503
    504		if (!recvlen)
    505			break;
    506
    507		/* Ensure recvlen is big enough to read header data */
    508		if (recvlen < ICMSG_HDR) {
    509			pr_err_ratelimited("Heartbeat request received. Packet length too small: %d\n",
    510					   recvlen);
    511			break;
    512		}
    513
    514		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
    515				sizeof(struct vmbuspipe_hdr)];
    516
    517		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
    518			if (vmbus_prep_negotiate_resp(icmsghdrp,
    519					hbeat_txf_buf, recvlen,
    520					fw_versions, FW_VER_COUNT,
    521					hb_versions, HB_VER_COUNT,
    522					NULL, &hb_srv_version)) {
    523
    524				pr_info("Heartbeat IC version %d.%d\n",
    525					hb_srv_version >> 16,
    526					hb_srv_version & 0xFFFF);
    527			}
    528		} else if (icmsghdrp->icmsgtype == ICMSGTYPE_HEARTBEAT) {
    529			/*
    530			 * Ensure recvlen is big enough to read seq_num. Reserved area is not
    531			 * included in the check as the host may not fill it up entirely
    532			 */
    533			if (recvlen < ICMSG_HDR + sizeof(u64)) {
    534				pr_err_ratelimited("Invalid heartbeat msg data. Length too small: %u\n",
    535						   recvlen);
    536				break;
    537			}
    538			heartbeat_msg = (struct heartbeat_msg_data *)&hbeat_txf_buf[ICMSG_HDR];
    539
    540			heartbeat_msg->seq_num += 1;
    541		} else {
    542			icmsghdrp->status = HV_E_FAIL;
    543			pr_err_ratelimited("Heartbeat request received. Invalid msg type: %d\n",
    544					   icmsghdrp->icmsgtype);
    545		}
    546
    547		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
    548			| ICMSGHDRFLAG_RESPONSE;
    549
    550		vmbus_sendpacket(channel, hbeat_txf_buf,
    551				 recvlen, requestid,
    552				 VM_PKT_DATA_INBAND, 0);
    553	}
    554}
    555
    556#define HV_UTIL_RING_SEND_SIZE VMBUS_RING_SIZE(3 * HV_HYP_PAGE_SIZE)
    557#define HV_UTIL_RING_RECV_SIZE VMBUS_RING_SIZE(3 * HV_HYP_PAGE_SIZE)
    558
    559static int util_probe(struct hv_device *dev,
    560			const struct hv_vmbus_device_id *dev_id)
    561{
    562	struct hv_util_service *srv =
    563		(struct hv_util_service *)dev_id->driver_data;
    564	int ret;
    565
    566	srv->recv_buffer = kmalloc(HV_HYP_PAGE_SIZE * 4, GFP_KERNEL);
    567	if (!srv->recv_buffer)
    568		return -ENOMEM;
    569	srv->channel = dev->channel;
    570	if (srv->util_init) {
    571		ret = srv->util_init(srv);
    572		if (ret) {
    573			ret = -ENODEV;
    574			goto error1;
    575		}
    576	}
    577
    578	/*
    579	 * The set of services managed by the util driver are not performance
    580	 * critical and do not need batched reading. Furthermore, some services
    581	 * such as KVP can only handle one message from the host at a time.
    582	 * Turn off batched reading for all util drivers before we open the
    583	 * channel.
    584	 */
    585	set_channel_read_mode(dev->channel, HV_CALL_DIRECT);
    586
    587	hv_set_drvdata(dev, srv);
    588
    589	ret = vmbus_open(dev->channel, HV_UTIL_RING_SEND_SIZE,
    590			 HV_UTIL_RING_RECV_SIZE, NULL, 0, srv->util_cb,
    591			 dev->channel);
    592	if (ret)
    593		goto error;
    594
    595	return 0;
    596
    597error:
    598	if (srv->util_deinit)
    599		srv->util_deinit();
    600error1:
    601	kfree(srv->recv_buffer);
    602	return ret;
    603}
    604
    605static int util_remove(struct hv_device *dev)
    606{
    607	struct hv_util_service *srv = hv_get_drvdata(dev);
    608
    609	if (srv->util_deinit)
    610		srv->util_deinit();
    611	vmbus_close(dev->channel);
    612	kfree(srv->recv_buffer);
    613
    614	return 0;
    615}
    616
    617/*
    618 * When we're in util_suspend(), all the userspace processes have been frozen
    619 * (refer to hibernate() -> freeze_processes()). The userspace is thawed only
    620 * after the whole resume procedure, including util_resume(), finishes.
    621 */
    622static int util_suspend(struct hv_device *dev)
    623{
    624	struct hv_util_service *srv = hv_get_drvdata(dev);
    625	int ret = 0;
    626
    627	if (srv->util_pre_suspend) {
    628		ret = srv->util_pre_suspend();
    629		if (ret)
    630			return ret;
    631	}
    632
    633	vmbus_close(dev->channel);
    634
    635	return 0;
    636}
    637
    638static int util_resume(struct hv_device *dev)
    639{
    640	struct hv_util_service *srv = hv_get_drvdata(dev);
    641	int ret = 0;
    642
    643	if (srv->util_pre_resume) {
    644		ret = srv->util_pre_resume();
    645		if (ret)
    646			return ret;
    647	}
    648
    649	ret = vmbus_open(dev->channel, HV_UTIL_RING_SEND_SIZE,
    650			 HV_UTIL_RING_RECV_SIZE, NULL, 0, srv->util_cb,
    651			 dev->channel);
    652	return ret;
    653}
    654
    655static const struct hv_vmbus_device_id id_table[] = {
    656	/* Shutdown guid */
    657	{ HV_SHUTDOWN_GUID,
    658	  .driver_data = (unsigned long)&util_shutdown
    659	},
    660	/* Time synch guid */
    661	{ HV_TS_GUID,
    662	  .driver_data = (unsigned long)&util_timesynch
    663	},
    664	/* Heartbeat guid */
    665	{ HV_HEART_BEAT_GUID,
    666	  .driver_data = (unsigned long)&util_heartbeat
    667	},
    668	/* KVP guid */
    669	{ HV_KVP_GUID,
    670	  .driver_data = (unsigned long)&util_kvp
    671	},
    672	/* VSS GUID */
    673	{ HV_VSS_GUID,
    674	  .driver_data = (unsigned long)&util_vss
    675	},
    676	/* File copy GUID */
    677	{ HV_FCOPY_GUID,
    678	  .driver_data = (unsigned long)&util_fcopy
    679	},
    680	{ },
    681};
    682
    683MODULE_DEVICE_TABLE(vmbus, id_table);
    684
    685/* The one and only one */
    686static  struct hv_driver util_drv = {
    687	.name = "hv_utils",
    688	.id_table = id_table,
    689	.probe =  util_probe,
    690	.remove =  util_remove,
    691	.suspend = util_suspend,
    692	.resume =  util_resume,
    693	.driver = {
    694		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
    695	},
    696};
    697
    698static int hv_ptp_enable(struct ptp_clock_info *info,
    699			 struct ptp_clock_request *request, int on)
    700{
    701	return -EOPNOTSUPP;
    702}
    703
    704static int hv_ptp_settime(struct ptp_clock_info *p, const struct timespec64 *ts)
    705{
    706	return -EOPNOTSUPP;
    707}
    708
    709static int hv_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
    710{
    711	return -EOPNOTSUPP;
    712}
    713static int hv_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
    714{
    715	return -EOPNOTSUPP;
    716}
    717
    718static int hv_ptp_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
    719{
    720	return hv_get_adj_host_time(ts);
    721}
    722
    723static struct ptp_clock_info ptp_hyperv_info = {
    724	.name		= "hyperv",
    725	.enable         = hv_ptp_enable,
    726	.adjtime        = hv_ptp_adjtime,
    727	.adjfreq        = hv_ptp_adjfreq,
    728	.gettime64      = hv_ptp_gettime,
    729	.settime64      = hv_ptp_settime,
    730	.owner		= THIS_MODULE,
    731};
    732
    733static struct ptp_clock *hv_ptp_clock;
    734
    735static int hv_timesync_init(struct hv_util_service *srv)
    736{
    737	spin_lock_init(&host_ts.lock);
    738
    739	INIT_WORK(&adj_time_work, hv_set_host_time);
    740
    741	/*
    742	 * ptp_clock_register() returns NULL when CONFIG_PTP_1588_CLOCK is
    743	 * disabled but the driver is still useful without the PTP device
    744	 * as it still handles the ICTIMESYNCFLAG_SYNC case.
    745	 */
    746	hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL);
    747	if (IS_ERR_OR_NULL(hv_ptp_clock)) {
    748		pr_err("cannot register PTP clock: %d\n",
    749		       PTR_ERR_OR_ZERO(hv_ptp_clock));
    750		hv_ptp_clock = NULL;
    751	}
    752
    753	return 0;
    754}
    755
    756static void hv_timesync_cancel_work(void)
    757{
    758	cancel_work_sync(&adj_time_work);
    759}
    760
    761static int hv_timesync_pre_suspend(void)
    762{
    763	hv_timesync_cancel_work();
    764	return 0;
    765}
    766
    767static void hv_timesync_deinit(void)
    768{
    769	if (hv_ptp_clock)
    770		ptp_clock_unregister(hv_ptp_clock);
    771
    772	hv_timesync_cancel_work();
    773}
    774
    775static int __init init_hyperv_utils(void)
    776{
    777	pr_info("Registering HyperV Utility Driver\n");
    778
    779	return vmbus_driver_register(&util_drv);
    780}
    781
    782static void exit_hyperv_utils(void)
    783{
    784	pr_info("De-Registered HyperV Utility Driver\n");
    785
    786	vmbus_driver_unregister(&util_drv);
    787}
    788
    789module_init(init_hyperv_utils);
    790module_exit(exit_hyperv_utils);
    791
    792MODULE_DESCRIPTION("Hyper-V Utilities");
    793MODULE_LICENSE("GPL");