vmbus.c revision 307018
1/*-
2 * Copyright (c) 2009-2012,2016 Microsoft Corp.
3 * Copyright (c) 2012 NetApp Inc.
4 * Copyright (c) 2012 Citrix Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice unmodified, this list of conditions, and the following
12 *    disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * VM Bus Driver Implementation
31 */
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: stable/10/sys/dev/hyperv/vmbus/vmbus.c 307018 2016-10-11 06:35:29Z sephe $");
34
35#include <sys/param.h>
36#include <sys/bus.h>
37#include <sys/kernel.h>
38#include <sys/lock.h>
39#include <sys/malloc.h>
40#include <sys/module.h>
41#include <sys/proc.h>
42#include <sys/sysctl.h>
43#include <sys/syslog.h>
44#include <sys/systm.h>
45#include <sys/rtprio.h>
46#include <sys/interrupt.h>
47#include <sys/sx.h>
48#include <sys/taskqueue.h>
49#include <sys/mutex.h>
50#include <sys/smp.h>
51
52#include <machine/resource.h>
53#include <sys/rman.h>
54
55#include <machine/stdarg.h>
56#include <machine/intr_machdep.h>
57#include <machine/md_var.h>
58#include <machine/segments.h>
59#include <sys/pcpu.h>
60#include <machine/apicvar.h>
61
62#include <dev/hyperv/include/hyperv.h>
63#include <dev/hyperv/vmbus/hv_vmbus_priv.h>
64#include <dev/hyperv/vmbus/hyperv_reg.h>
65#include <dev/hyperv/vmbus/hyperv_var.h>
66#include <dev/hyperv/vmbus/vmbus_reg.h>
67#include <dev/hyperv/vmbus/vmbus_var.h>
68
69#include <contrib/dev/acpica/include/acpi.h>
70#include "acpi_if.h"
71#include "vmbus_if.h"
72
73#define VMBUS_GPADL_START		0xe1e10
74
75struct vmbus_msghc {
76	struct hypercall_postmsg_in	*mh_inprm;
77	struct hypercall_postmsg_in	mh_inprm_save;
78	struct hyperv_dma		mh_inprm_dma;
79
80	struct vmbus_message		*mh_resp;
81	struct vmbus_message		mh_resp0;
82};
83
84struct vmbus_msghc_ctx {
85	struct vmbus_msghc		*mhc_free;
86	struct mtx			mhc_free_lock;
87	uint32_t			mhc_flags;
88
89	struct vmbus_msghc		*mhc_active;
90	struct mtx			mhc_active_lock;
91};
92
93#define VMBUS_MSGHC_CTXF_DESTROY	0x0001
94
95static int			vmbus_init(struct vmbus_softc *);
96static int			vmbus_connect(struct vmbus_softc *, uint32_t);
97static int			vmbus_req_channels(struct vmbus_softc *sc);
98static void			vmbus_disconnect(struct vmbus_softc *);
99static int			vmbus_scan(struct vmbus_softc *);
100static void			vmbus_scan_wait(struct vmbus_softc *);
101static void			vmbus_scan_newdev(struct vmbus_softc *);
102
103static int			vmbus_sysctl_version(SYSCTL_HANDLER_ARGS);
104
105static struct vmbus_msghc_ctx	*vmbus_msghc_ctx_create(bus_dma_tag_t);
106static void			vmbus_msghc_ctx_destroy(
107				    struct vmbus_msghc_ctx *);
108static void			vmbus_msghc_ctx_free(struct vmbus_msghc_ctx *);
109static struct vmbus_msghc	*vmbus_msghc_alloc(bus_dma_tag_t);
110static void			vmbus_msghc_free(struct vmbus_msghc *);
111static struct vmbus_msghc	*vmbus_msghc_get1(struct vmbus_msghc_ctx *,
112				    uint32_t);
113
114struct vmbus_softc	*vmbus_sc;
115
116extern inthand_t IDTVEC(rsvd), IDTVEC(vmbus_isr);
117
118static const uint32_t		vmbus_version[] = {
119	VMBUS_VERSION_WIN8_1,
120	VMBUS_VERSION_WIN8,
121	VMBUS_VERSION_WIN7,
122	VMBUS_VERSION_WS2008
123};
124
125static struct vmbus_msghc *
126vmbus_msghc_alloc(bus_dma_tag_t parent_dtag)
127{
128	struct vmbus_msghc *mh;
129
130	mh = malloc(sizeof(*mh), M_DEVBUF, M_WAITOK | M_ZERO);
131
132	mh->mh_inprm = hyperv_dmamem_alloc(parent_dtag,
133	    HYPERCALL_POSTMSGIN_ALIGN, 0, HYPERCALL_POSTMSGIN_SIZE,
134	    &mh->mh_inprm_dma, BUS_DMA_WAITOK);
135	if (mh->mh_inprm == NULL) {
136		free(mh, M_DEVBUF);
137		return NULL;
138	}
139	return mh;
140}
141
142static void
143vmbus_msghc_free(struct vmbus_msghc *mh)
144{
145	hyperv_dmamem_free(&mh->mh_inprm_dma, mh->mh_inprm);
146	free(mh, M_DEVBUF);
147}
148
149static void
150vmbus_msghc_ctx_free(struct vmbus_msghc_ctx *mhc)
151{
152	KASSERT(mhc->mhc_active == NULL, ("still have active msg hypercall"));
153	KASSERT(mhc->mhc_free == NULL, ("still have hypercall msg"));
154
155	mtx_destroy(&mhc->mhc_free_lock);
156	mtx_destroy(&mhc->mhc_active_lock);
157	free(mhc, M_DEVBUF);
158}
159
160static struct vmbus_msghc_ctx *
161vmbus_msghc_ctx_create(bus_dma_tag_t parent_dtag)
162{
163	struct vmbus_msghc_ctx *mhc;
164
165	mhc = malloc(sizeof(*mhc), M_DEVBUF, M_WAITOK | M_ZERO);
166	mtx_init(&mhc->mhc_free_lock, "vmbus msghc free", NULL, MTX_DEF);
167	mtx_init(&mhc->mhc_active_lock, "vmbus msghc act", NULL, MTX_DEF);
168
169	mhc->mhc_free = vmbus_msghc_alloc(parent_dtag);
170	if (mhc->mhc_free == NULL) {
171		vmbus_msghc_ctx_free(mhc);
172		return NULL;
173	}
174	return mhc;
175}
176
177static struct vmbus_msghc *
178vmbus_msghc_get1(struct vmbus_msghc_ctx *mhc, uint32_t dtor_flag)
179{
180	struct vmbus_msghc *mh;
181
182	mtx_lock(&mhc->mhc_free_lock);
183
184	while ((mhc->mhc_flags & dtor_flag) == 0 && mhc->mhc_free == NULL) {
185		mtx_sleep(&mhc->mhc_free, &mhc->mhc_free_lock, 0,
186		    "gmsghc", 0);
187	}
188	if (mhc->mhc_flags & dtor_flag) {
189		/* Being destroyed */
190		mh = NULL;
191	} else {
192		mh = mhc->mhc_free;
193		KASSERT(mh != NULL, ("no free hypercall msg"));
194		KASSERT(mh->mh_resp == NULL,
195		    ("hypercall msg has pending response"));
196		mhc->mhc_free = NULL;
197	}
198
199	mtx_unlock(&mhc->mhc_free_lock);
200
201	return mh;
202}
203
204void
205vmbus_msghc_reset(struct vmbus_msghc *mh, size_t dsize)
206{
207	struct hypercall_postmsg_in *inprm;
208
209	if (dsize > HYPERCALL_POSTMSGIN_DSIZE_MAX)
210		panic("invalid data size %zu", dsize);
211
212	inprm = mh->mh_inprm;
213	memset(inprm, 0, HYPERCALL_POSTMSGIN_SIZE);
214	inprm->hc_connid = VMBUS_CONNID_MESSAGE;
215	inprm->hc_msgtype = HYPERV_MSGTYPE_CHANNEL;
216	inprm->hc_dsize = dsize;
217}
218
219struct vmbus_msghc *
220vmbus_msghc_get(struct vmbus_softc *sc, size_t dsize)
221{
222	struct vmbus_msghc *mh;
223
224	if (dsize > HYPERCALL_POSTMSGIN_DSIZE_MAX)
225		panic("invalid data size %zu", dsize);
226
227	mh = vmbus_msghc_get1(sc->vmbus_msg_hc, VMBUS_MSGHC_CTXF_DESTROY);
228	if (mh == NULL)
229		return NULL;
230
231	vmbus_msghc_reset(mh, dsize);
232	return mh;
233}
234
235void
236vmbus_msghc_put(struct vmbus_softc *sc, struct vmbus_msghc *mh)
237{
238	struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
239
240	KASSERT(mhc->mhc_active == NULL, ("msg hypercall is active"));
241	mh->mh_resp = NULL;
242
243	mtx_lock(&mhc->mhc_free_lock);
244	KASSERT(mhc->mhc_free == NULL, ("has free hypercall msg"));
245	mhc->mhc_free = mh;
246	mtx_unlock(&mhc->mhc_free_lock);
247	wakeup(&mhc->mhc_free);
248}
249
250void *
251vmbus_msghc_dataptr(struct vmbus_msghc *mh)
252{
253	return mh->mh_inprm->hc_data;
254}
255
256static void
257vmbus_msghc_ctx_destroy(struct vmbus_msghc_ctx *mhc)
258{
259	struct vmbus_msghc *mh;
260
261	mtx_lock(&mhc->mhc_free_lock);
262	mhc->mhc_flags |= VMBUS_MSGHC_CTXF_DESTROY;
263	mtx_unlock(&mhc->mhc_free_lock);
264	wakeup(&mhc->mhc_free);
265
266	mh = vmbus_msghc_get1(mhc, 0);
267	if (mh == NULL)
268		panic("can't get msghc");
269
270	vmbus_msghc_free(mh);
271	vmbus_msghc_ctx_free(mhc);
272}
273
274int
275vmbus_msghc_exec_noresult(struct vmbus_msghc *mh)
276{
277	sbintime_t time = SBT_1MS;
278	int i;
279
280	/*
281	 * Save the input parameter so that we could restore the input
282	 * parameter if the Hypercall failed.
283	 *
284	 * XXX
285	 * Is this really necessary?!  i.e. Will the Hypercall ever
286	 * overwrite the input parameter?
287	 */
288	memcpy(&mh->mh_inprm_save, mh->mh_inprm, HYPERCALL_POSTMSGIN_SIZE);
289
290	/*
291	 * In order to cope with transient failures, e.g. insufficient
292	 * resources on host side, we retry the post message Hypercall
293	 * several times.  20 retries seem sufficient.
294	 */
295#define HC_RETRY_MAX	20
296
297	for (i = 0; i < HC_RETRY_MAX; ++i) {
298		uint64_t status;
299
300		status = hypercall_post_message(mh->mh_inprm_dma.hv_paddr);
301		if (status == HYPERCALL_STATUS_SUCCESS)
302			return 0;
303
304		pause_sbt("hcpmsg", time, 0, C_HARDCLOCK);
305		if (time < SBT_1S * 2)
306			time *= 2;
307
308		/* Restore input parameter and try again */
309		memcpy(mh->mh_inprm, &mh->mh_inprm_save,
310		    HYPERCALL_POSTMSGIN_SIZE);
311	}
312
313#undef HC_RETRY_MAX
314
315	return EIO;
316}
317
318int
319vmbus_msghc_exec(struct vmbus_softc *sc, struct vmbus_msghc *mh)
320{
321	struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
322	int error;
323
324	KASSERT(mh->mh_resp == NULL, ("hypercall msg has pending response"));
325
326	mtx_lock(&mhc->mhc_active_lock);
327	KASSERT(mhc->mhc_active == NULL, ("pending active msg hypercall"));
328	mhc->mhc_active = mh;
329	mtx_unlock(&mhc->mhc_active_lock);
330
331	error = vmbus_msghc_exec_noresult(mh);
332	if (error) {
333		mtx_lock(&mhc->mhc_active_lock);
334		KASSERT(mhc->mhc_active == mh, ("msghc mismatch"));
335		mhc->mhc_active = NULL;
336		mtx_unlock(&mhc->mhc_active_lock);
337	}
338	return error;
339}
340
341const struct vmbus_message *
342vmbus_msghc_wait_result(struct vmbus_softc *sc, struct vmbus_msghc *mh)
343{
344	struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
345
346	mtx_lock(&mhc->mhc_active_lock);
347
348	KASSERT(mhc->mhc_active == mh, ("msghc mismatch"));
349	while (mh->mh_resp == NULL) {
350		mtx_sleep(&mhc->mhc_active, &mhc->mhc_active_lock, 0,
351		    "wmsghc", 0);
352	}
353	mhc->mhc_active = NULL;
354
355	mtx_unlock(&mhc->mhc_active_lock);
356
357	return mh->mh_resp;
358}
359
360void
361vmbus_msghc_wakeup(struct vmbus_softc *sc, const struct vmbus_message *msg)
362{
363	struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
364	struct vmbus_msghc *mh;
365
366	mtx_lock(&mhc->mhc_active_lock);
367
368	mh = mhc->mhc_active;
369	KASSERT(mh != NULL, ("no pending msg hypercall"));
370	memcpy(&mh->mh_resp0, msg, sizeof(mh->mh_resp0));
371	mh->mh_resp = &mh->mh_resp0;
372
373	mtx_unlock(&mhc->mhc_active_lock);
374	wakeup(&mhc->mhc_active);
375}
376
377uint32_t
378vmbus_gpadl_alloc(struct vmbus_softc *sc)
379{
380	return atomic_fetchadd_int(&sc->vmbus_gpadl, 1);
381}
382
383static int
384vmbus_connect(struct vmbus_softc *sc, uint32_t version)
385{
386	struct vmbus_chanmsg_connect *req;
387	const struct vmbus_message *msg;
388	struct vmbus_msghc *mh;
389	int error, done = 0;
390
391	mh = vmbus_msghc_get(sc, sizeof(*req));
392	if (mh == NULL)
393		return ENXIO;
394
395	req = vmbus_msghc_dataptr(mh);
396	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CONNECT;
397	req->chm_ver = version;
398	req->chm_evtflags = sc->vmbus_evtflags_dma.hv_paddr;
399	req->chm_mnf1 = sc->vmbus_mnf1_dma.hv_paddr;
400	req->chm_mnf2 = sc->vmbus_mnf2_dma.hv_paddr;
401
402	error = vmbus_msghc_exec(sc, mh);
403	if (error) {
404		vmbus_msghc_put(sc, mh);
405		return error;
406	}
407
408	msg = vmbus_msghc_wait_result(sc, mh);
409	done = ((const struct vmbus_chanmsg_connect_resp *)
410	    msg->msg_data)->chm_done;
411
412	vmbus_msghc_put(sc, mh);
413
414	return (done ? 0 : EOPNOTSUPP);
415}
416
417static int
418vmbus_init(struct vmbus_softc *sc)
419{
420	int i;
421
422	for (i = 0; i < nitems(vmbus_version); ++i) {
423		int error;
424
425		error = vmbus_connect(sc, vmbus_version[i]);
426		if (!error) {
427			sc->vmbus_version = vmbus_version[i];
428			device_printf(sc->vmbus_dev, "version %u.%u\n",
429			    VMBUS_VERSION_MAJOR(sc->vmbus_version),
430			    VMBUS_VERSION_MINOR(sc->vmbus_version));
431			return 0;
432		}
433	}
434	return ENXIO;
435}
436
437static void
438vmbus_disconnect(struct vmbus_softc *sc)
439{
440	struct vmbus_chanmsg_disconnect *req;
441	struct vmbus_msghc *mh;
442	int error;
443
444	mh = vmbus_msghc_get(sc, sizeof(*req));
445	if (mh == NULL) {
446		device_printf(sc->vmbus_dev,
447		    "can not get msg hypercall for disconnect\n");
448		return;
449	}
450
451	req = vmbus_msghc_dataptr(mh);
452	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_DISCONNECT;
453
454	error = vmbus_msghc_exec_noresult(mh);
455	vmbus_msghc_put(sc, mh);
456
457	if (error) {
458		device_printf(sc->vmbus_dev,
459		    "disconnect msg hypercall failed\n");
460	}
461}
462
463static int
464vmbus_req_channels(struct vmbus_softc *sc)
465{
466	struct vmbus_chanmsg_chrequest *req;
467	struct vmbus_msghc *mh;
468	int error;
469
470	mh = vmbus_msghc_get(sc, sizeof(*req));
471	if (mh == NULL)
472		return ENXIO;
473
474	req = vmbus_msghc_dataptr(mh);
475	req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHREQUEST;
476
477	error = vmbus_msghc_exec_noresult(mh);
478	vmbus_msghc_put(sc, mh);
479
480	return error;
481}
482
483void
484vmbus_scan_newchan(struct vmbus_softc *sc)
485{
486	mtx_lock(&sc->vmbus_scan_lock);
487	if ((sc->vmbus_scan_chcnt & VMBUS_SCAN_CHCNT_DONE) == 0)
488		sc->vmbus_scan_chcnt++;
489	mtx_unlock(&sc->vmbus_scan_lock);
490}
491
492void
493vmbus_scan_done(struct vmbus_softc *sc)
494{
495	mtx_lock(&sc->vmbus_scan_lock);
496	sc->vmbus_scan_chcnt |= VMBUS_SCAN_CHCNT_DONE;
497	mtx_unlock(&sc->vmbus_scan_lock);
498	wakeup(&sc->vmbus_scan_chcnt);
499}
500
501static void
502vmbus_scan_newdev(struct vmbus_softc *sc)
503{
504	mtx_lock(&sc->vmbus_scan_lock);
505	sc->vmbus_scan_devcnt++;
506	mtx_unlock(&sc->vmbus_scan_lock);
507	wakeup(&sc->vmbus_scan_devcnt);
508}
509
510static void
511vmbus_scan_wait(struct vmbus_softc *sc)
512{
513	uint32_t chancnt;
514
515	mtx_lock(&sc->vmbus_scan_lock);
516	while ((sc->vmbus_scan_chcnt & VMBUS_SCAN_CHCNT_DONE) == 0) {
517		mtx_sleep(&sc->vmbus_scan_chcnt, &sc->vmbus_scan_lock, 0,
518		    "waitch", 0);
519	}
520	chancnt = sc->vmbus_scan_chcnt & ~VMBUS_SCAN_CHCNT_DONE;
521
522	while (sc->vmbus_scan_devcnt != chancnt) {
523		mtx_sleep(&sc->vmbus_scan_devcnt, &sc->vmbus_scan_lock, 0,
524		    "waitdev", 0);
525	}
526	mtx_unlock(&sc->vmbus_scan_lock);
527}
528
529static int
530vmbus_scan(struct vmbus_softc *sc)
531{
532	int error;
533
534	/*
535	 * Start vmbus scanning.
536	 */
537	error = vmbus_req_channels(sc);
538	if (error) {
539		device_printf(sc->vmbus_dev, "channel request failed: %d\n",
540		    error);
541		return error;
542	}
543
544	/*
545	 * Wait for all devices are added to vmbus.
546	 */
547	vmbus_scan_wait(sc);
548
549	/*
550	 * Identify, probe and attach.
551	 */
552	bus_generic_probe(sc->vmbus_dev);
553	bus_generic_attach(sc->vmbus_dev);
554
555	if (bootverbose) {
556		device_printf(sc->vmbus_dev, "device scan, probe and attach "
557		    "done\n");
558	}
559	return 0;
560}
561
562static void
563vmbus_msg_task(void *xsc, int pending __unused)
564{
565	struct vmbus_softc *sc = xsc;
566	volatile struct vmbus_message *msg;
567
568	msg = VMBUS_PCPU_GET(sc, message, curcpu) + VMBUS_SINT_MESSAGE;
569	for (;;) {
570		if (msg->msg_type == HYPERV_MSGTYPE_NONE) {
571			/* No message */
572			break;
573		} else if (msg->msg_type == HYPERV_MSGTYPE_CHANNEL) {
574			/* Channel message */
575			vmbus_chan_msgproc(sc,
576			    __DEVOLATILE(const struct vmbus_message *, msg));
577		}
578
579		msg->msg_type = HYPERV_MSGTYPE_NONE;
580		/*
581		 * Make sure the write to msg_type (i.e. set to
582		 * HYPERV_MSGTYPE_NONE) happens before we read the
583		 * msg_flags and EOMing. Otherwise, the EOMing will
584		 * not deliver any more messages since there is no
585		 * empty slot
586		 *
587		 * NOTE:
588		 * mb() is used here, since atomic_thread_fence_seq_cst()
589		 * will become compiler fence on UP kernel.
590		 */
591		mb();
592		if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
593			/*
594			 * This will cause message queue rescan to possibly
595			 * deliver another msg from the hypervisor
596			 */
597			wrmsr(MSR_HV_EOM, 0);
598		}
599	}
600}
601
602static __inline int
603vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
604{
605	volatile struct vmbus_message *msg;
606	struct vmbus_message *msg_base;
607
608	msg_base = VMBUS_PCPU_GET(sc, message, cpu);
609
610	/*
611	 * Check event timer.
612	 *
613	 * TODO: move this to independent IDT vector.
614	 */
615	msg = msg_base + VMBUS_SINT_TIMER;
616	if (msg->msg_type == HYPERV_MSGTYPE_TIMER_EXPIRED) {
617		msg->msg_type = HYPERV_MSGTYPE_NONE;
618
619		vmbus_et_intr(frame);
620
621		/*
622		 * Make sure the write to msg_type (i.e. set to
623		 * HYPERV_MSGTYPE_NONE) happens before we read the
624		 * msg_flags and EOMing. Otherwise, the EOMing will
625		 * not deliver any more messages since there is no
626		 * empty slot
627		 *
628		 * NOTE:
629		 * mb() is used here, since atomic_thread_fence_seq_cst()
630		 * will become compiler fence on UP kernel.
631		 */
632		mb();
633		if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
634			/*
635			 * This will cause message queue rescan to possibly
636			 * deliver another msg from the hypervisor
637			 */
638			wrmsr(MSR_HV_EOM, 0);
639		}
640	}
641
642	/*
643	 * Check events.  Hot path for network and storage I/O data; high rate.
644	 *
645	 * NOTE:
646	 * As recommended by the Windows guest fellows, we check events before
647	 * checking messages.
648	 */
649	sc->vmbus_event_proc(sc, cpu);
650
651	/*
652	 * Check messages.  Mainly management stuffs; ultra low rate.
653	 */
654	msg = msg_base + VMBUS_SINT_MESSAGE;
655	if (__predict_false(msg->msg_type != HYPERV_MSGTYPE_NONE)) {
656		taskqueue_enqueue(VMBUS_PCPU_GET(sc, message_tq, cpu),
657		    VMBUS_PCPU_PTR(sc, message_task, cpu));
658	}
659
660	return (FILTER_HANDLED);
661}
662
663void
664vmbus_handle_intr(struct trapframe *trap_frame)
665{
666	struct vmbus_softc *sc = vmbus_get_softc();
667	int cpu = curcpu;
668
669	/*
670	 * Disable preemption.
671	 */
672	critical_enter();
673
674	/*
675	 * Do a little interrupt counting.
676	 */
677	(*VMBUS_PCPU_GET(sc, intr_cnt, cpu))++;
678
679	vmbus_handle_intr1(sc, trap_frame, cpu);
680
681	/*
682	 * Enable preemption.
683	 */
684	critical_exit();
685}
686
687static void
688vmbus_synic_setup(void *xsc)
689{
690	struct vmbus_softc *sc = xsc;
691	int cpu = curcpu;
692	uint64_t val, orig;
693	uint32_t sint;
694
695	if (hyperv_features & CPUID_HV_MSR_VP_INDEX) {
696		/*
697		 * Save virtual processor id.
698		 */
699		VMBUS_PCPU_GET(sc, vcpuid, cpu) = rdmsr(MSR_HV_VP_INDEX);
700	} else {
701		/*
702		 * XXX
703		 * Virtual processoor id is only used by a pretty broken
704		 * channel selection code from storvsc.  It's nothing
705		 * critical even if CPUID_HV_MSR_VP_INDEX is not set; keep
706		 * moving on.
707		 */
708		VMBUS_PCPU_GET(sc, vcpuid, cpu) = cpu;
709	}
710
711	/*
712	 * Setup the SynIC message.
713	 */
714	orig = rdmsr(MSR_HV_SIMP);
715	val = MSR_HV_SIMP_ENABLE | (orig & MSR_HV_SIMP_RSVD_MASK) |
716	    ((VMBUS_PCPU_GET(sc, message_dma.hv_paddr, cpu) >> PAGE_SHIFT) <<
717	     MSR_HV_SIMP_PGSHIFT);
718	wrmsr(MSR_HV_SIMP, val);
719
720	/*
721	 * Setup the SynIC event flags.
722	 */
723	orig = rdmsr(MSR_HV_SIEFP);
724	val = MSR_HV_SIEFP_ENABLE | (orig & MSR_HV_SIEFP_RSVD_MASK) |
725	    ((VMBUS_PCPU_GET(sc, event_flags_dma.hv_paddr, cpu)
726	      >> PAGE_SHIFT) << MSR_HV_SIEFP_PGSHIFT);
727	wrmsr(MSR_HV_SIEFP, val);
728
729
730	/*
731	 * Configure and unmask SINT for message and event flags.
732	 */
733	sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
734	orig = rdmsr(sint);
735	val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
736	    (orig & MSR_HV_SINT_RSVD_MASK);
737	wrmsr(sint, val);
738
739	/*
740	 * Configure and unmask SINT for timer.
741	 */
742	sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
743	orig = rdmsr(sint);
744	val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
745	    (orig & MSR_HV_SINT_RSVD_MASK);
746	wrmsr(sint, val);
747
748	/*
749	 * All done; enable SynIC.
750	 */
751	orig = rdmsr(MSR_HV_SCONTROL);
752	val = MSR_HV_SCTRL_ENABLE | (orig & MSR_HV_SCTRL_RSVD_MASK);
753	wrmsr(MSR_HV_SCONTROL, val);
754}
755
756static void
757vmbus_synic_teardown(void *arg)
758{
759	uint64_t orig;
760	uint32_t sint;
761
762	/*
763	 * Disable SynIC.
764	 */
765	orig = rdmsr(MSR_HV_SCONTROL);
766	wrmsr(MSR_HV_SCONTROL, (orig & MSR_HV_SCTRL_RSVD_MASK));
767
768	/*
769	 * Mask message and event flags SINT.
770	 */
771	sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
772	orig = rdmsr(sint);
773	wrmsr(sint, orig | MSR_HV_SINT_MASKED);
774
775	/*
776	 * Mask timer SINT.
777	 */
778	sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
779	orig = rdmsr(sint);
780	wrmsr(sint, orig | MSR_HV_SINT_MASKED);
781
782	/*
783	 * Teardown SynIC message.
784	 */
785	orig = rdmsr(MSR_HV_SIMP);
786	wrmsr(MSR_HV_SIMP, (orig & MSR_HV_SIMP_RSVD_MASK));
787
788	/*
789	 * Teardown SynIC event flags.
790	 */
791	orig = rdmsr(MSR_HV_SIEFP);
792	wrmsr(MSR_HV_SIEFP, (orig & MSR_HV_SIEFP_RSVD_MASK));
793}
794
795static int
796vmbus_dma_alloc(struct vmbus_softc *sc)
797{
798	bus_dma_tag_t parent_dtag;
799	uint8_t *evtflags;
800	int cpu;
801
802	parent_dtag = bus_get_dma_tag(sc->vmbus_dev);
803	CPU_FOREACH(cpu) {
804		void *ptr;
805
806		/*
807		 * Per-cpu messages and event flags.
808		 */
809		ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
810		    PAGE_SIZE, VMBUS_PCPU_PTR(sc, message_dma, cpu),
811		    BUS_DMA_WAITOK | BUS_DMA_ZERO);
812		if (ptr == NULL)
813			return ENOMEM;
814		VMBUS_PCPU_GET(sc, message, cpu) = ptr;
815
816		ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
817		    PAGE_SIZE, VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
818		    BUS_DMA_WAITOK | BUS_DMA_ZERO);
819		if (ptr == NULL)
820			return ENOMEM;
821		VMBUS_PCPU_GET(sc, event_flags, cpu) = ptr;
822	}
823
824	evtflags = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
825	    PAGE_SIZE, &sc->vmbus_evtflags_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
826	if (evtflags == NULL)
827		return ENOMEM;
828	sc->vmbus_rx_evtflags = (u_long *)evtflags;
829	sc->vmbus_tx_evtflags = (u_long *)(evtflags + (PAGE_SIZE / 2));
830	sc->vmbus_evtflags = evtflags;
831
832	sc->vmbus_mnf1 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
833	    PAGE_SIZE, &sc->vmbus_mnf1_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
834	if (sc->vmbus_mnf1 == NULL)
835		return ENOMEM;
836
837	sc->vmbus_mnf2 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
838	    PAGE_SIZE, &sc->vmbus_mnf2_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
839	if (sc->vmbus_mnf2 == NULL)
840		return ENOMEM;
841
842	return 0;
843}
844
845static void
846vmbus_dma_free(struct vmbus_softc *sc)
847{
848	int cpu;
849
850	if (sc->vmbus_evtflags != NULL) {
851		hyperv_dmamem_free(&sc->vmbus_evtflags_dma, sc->vmbus_evtflags);
852		sc->vmbus_evtflags = NULL;
853		sc->vmbus_rx_evtflags = NULL;
854		sc->vmbus_tx_evtflags = NULL;
855	}
856	if (sc->vmbus_mnf1 != NULL) {
857		hyperv_dmamem_free(&sc->vmbus_mnf1_dma, sc->vmbus_mnf1);
858		sc->vmbus_mnf1 = NULL;
859	}
860	if (sc->vmbus_mnf2 != NULL) {
861		hyperv_dmamem_free(&sc->vmbus_mnf2_dma, sc->vmbus_mnf2);
862		sc->vmbus_mnf2 = NULL;
863	}
864
865	CPU_FOREACH(cpu) {
866		if (VMBUS_PCPU_GET(sc, message, cpu) != NULL) {
867			hyperv_dmamem_free(
868			    VMBUS_PCPU_PTR(sc, message_dma, cpu),
869			    VMBUS_PCPU_GET(sc, message, cpu));
870			VMBUS_PCPU_GET(sc, message, cpu) = NULL;
871		}
872		if (VMBUS_PCPU_GET(sc, event_flags, cpu) != NULL) {
873			hyperv_dmamem_free(
874			    VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
875			    VMBUS_PCPU_GET(sc, event_flags, cpu));
876			VMBUS_PCPU_GET(sc, event_flags, cpu) = NULL;
877		}
878	}
879}
880
881/**
882 * @brief Find a free IDT slot and setup the interrupt handler.
883 */
884static int
885vmbus_vector_alloc(void)
886{
887	int vector;
888	uintptr_t func;
889	struct gate_descriptor *ip;
890
891	/*
892	 * Search backwards form the highest IDT vector available for use
893	 * as vmbus channel callback vector. We install 'vmbus_isr'
894	 * handler at that vector and use it to interrupt vcpus.
895	 */
896	vector = APIC_SPURIOUS_INT;
897	while (--vector >= APIC_IPI_INTS) {
898		ip = &idt[vector];
899		func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
900		if (func == (uintptr_t)&IDTVEC(rsvd)) {
901#ifdef __i386__
902			setidt(vector , IDTVEC(vmbus_isr), SDT_SYS386IGT,
903			    SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
904#else
905			setidt(vector , IDTVEC(vmbus_isr), SDT_SYSIGT,
906			    SEL_KPL, 0);
907#endif
908
909			return (vector);
910		}
911	}
912	return (0);
913}
914
915/**
916 * @brief Restore the IDT slot to rsvd.
917 */
918static void
919vmbus_vector_free(int vector)
920{
921	uintptr_t func;
922	struct gate_descriptor *ip;
923
924	if (vector == 0)
925		return;
926
927	KASSERT(vector >= APIC_IPI_INTS && vector < APIC_SPURIOUS_INT,
928	    ("invalid vector %d", vector));
929
930	ip = &idt[vector];
931	func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
932	KASSERT(func == (uintptr_t)&IDTVEC(vmbus_isr),
933	    ("invalid vector %d", vector));
934
935	setidt(vector, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
936}
937
938static void
939vmbus_cpuset_setthread_task(void *xmask, int pending __unused)
940{
941	cpuset_t *mask = xmask;
942	int error;
943
944	error = cpuset_setthread(curthread->td_tid, mask);
945	if (error) {
946		panic("curthread=%ju: can't pin; error=%d",
947		    (uintmax_t)curthread->td_tid, error);
948	}
949}
950
951static int
952vmbus_intr_setup(struct vmbus_softc *sc)
953{
954	int cpu;
955
956	CPU_FOREACH(cpu) {
957		struct task cpuset_task;
958		char buf[MAXCOMLEN + 1];
959		cpuset_t cpu_mask;
960
961		/* Allocate an interrupt counter for Hyper-V interrupt */
962		snprintf(buf, sizeof(buf), "cpu%d:hyperv", cpu);
963		intrcnt_add(buf, VMBUS_PCPU_PTR(sc, intr_cnt, cpu));
964
965		/*
966		 * Setup taskqueue to handle events.  Task will be per-
967		 * channel.
968		 */
969		VMBUS_PCPU_GET(sc, event_tq, cpu) = taskqueue_create_fast(
970		    "hyperv event", M_WAITOK, taskqueue_thread_enqueue,
971		    VMBUS_PCPU_PTR(sc, event_tq, cpu));
972		taskqueue_start_threads(VMBUS_PCPU_PTR(sc, event_tq, cpu),
973		    1, PI_NET, "hvevent%d", cpu);
974
975		CPU_SETOF(cpu, &cpu_mask);
976		TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
977		    &cpu_mask);
978		taskqueue_enqueue(VMBUS_PCPU_GET(sc, event_tq, cpu),
979		    &cpuset_task);
980		taskqueue_drain(VMBUS_PCPU_GET(sc, event_tq, cpu),
981		    &cpuset_task);
982
983		/*
984		 * Setup tasks and taskqueues to handle messages.
985		 */
986		VMBUS_PCPU_GET(sc, message_tq, cpu) = taskqueue_create_fast(
987		    "hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
988		    VMBUS_PCPU_PTR(sc, message_tq, cpu));
989		taskqueue_start_threads(VMBUS_PCPU_PTR(sc, message_tq, cpu), 1,
990		    PI_NET, "hvmsg%d", cpu);
991		TASK_INIT(VMBUS_PCPU_PTR(sc, message_task, cpu), 0,
992		    vmbus_msg_task, sc);
993
994		CPU_SETOF(cpu, &cpu_mask);
995		TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
996		    &cpu_mask);
997		taskqueue_enqueue(VMBUS_PCPU_GET(sc, message_tq, cpu),
998		    &cpuset_task);
999		taskqueue_drain(VMBUS_PCPU_GET(sc, message_tq, cpu),
1000		    &cpuset_task);
1001	}
1002
1003	/*
1004	 * All Hyper-V ISR required resources are setup, now let's find a
1005	 * free IDT vector for Hyper-V ISR and set it up.
1006	 */
1007	sc->vmbus_idtvec = vmbus_vector_alloc();
1008	if (sc->vmbus_idtvec == 0) {
1009		device_printf(sc->vmbus_dev, "cannot find free IDT vector\n");
1010		return ENXIO;
1011	}
1012	if(bootverbose) {
1013		device_printf(sc->vmbus_dev, "vmbus IDT vector %d\n",
1014		    sc->vmbus_idtvec);
1015	}
1016	return 0;
1017}
1018
1019static void
1020vmbus_intr_teardown(struct vmbus_softc *sc)
1021{
1022	int cpu;
1023
1024	vmbus_vector_free(sc->vmbus_idtvec);
1025
1026	CPU_FOREACH(cpu) {
1027		if (VMBUS_PCPU_GET(sc, event_tq, cpu) != NULL) {
1028			taskqueue_free(VMBUS_PCPU_GET(sc, event_tq, cpu));
1029			VMBUS_PCPU_GET(sc, event_tq, cpu) = NULL;
1030		}
1031		if (VMBUS_PCPU_GET(sc, message_tq, cpu) != NULL) {
1032			taskqueue_drain(VMBUS_PCPU_GET(sc, message_tq, cpu),
1033			    VMBUS_PCPU_PTR(sc, message_task, cpu));
1034			taskqueue_free(VMBUS_PCPU_GET(sc, message_tq, cpu));
1035			VMBUS_PCPU_GET(sc, message_tq, cpu) = NULL;
1036		}
1037	}
1038}
1039
1040static int
1041vmbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
1042{
1043	struct hv_device *child_dev_ctx = device_get_ivars(child);
1044
1045	switch (index) {
1046	case HV_VMBUS_IVAR_TYPE:
1047		*result = (uintptr_t)&child_dev_ctx->class_id;
1048		return (0);
1049
1050	case HV_VMBUS_IVAR_INSTANCE:
1051		*result = (uintptr_t)&child_dev_ctx->device_id;
1052		return (0);
1053
1054	case HV_VMBUS_IVAR_DEVCTX:
1055		*result = (uintptr_t)child_dev_ctx;
1056		return (0);
1057
1058	case HV_VMBUS_IVAR_NODE:
1059		*result = (uintptr_t)child_dev_ctx->device;
1060		return (0);
1061	}
1062	return (ENOENT);
1063}
1064
1065static int
1066vmbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
1067{
1068	switch (index) {
1069	case HV_VMBUS_IVAR_TYPE:
1070	case HV_VMBUS_IVAR_INSTANCE:
1071	case HV_VMBUS_IVAR_DEVCTX:
1072	case HV_VMBUS_IVAR_NODE:
1073		/* read-only */
1074		return (EINVAL);
1075	}
1076	return (ENOENT);
1077}
1078
1079static int
1080vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)
1081{
1082	struct hv_device *dev_ctx = device_get_ivars(child);
1083	char guidbuf[HYPERV_GUID_STRLEN];
1084
1085	if (dev_ctx == NULL)
1086		return (0);
1087
1088	strlcat(buf, "classid=", buflen);
1089	hyperv_guid2str(&dev_ctx->class_id, guidbuf, sizeof(guidbuf));
1090	strlcat(buf, guidbuf, buflen);
1091
1092	strlcat(buf, " deviceid=", buflen);
1093	hyperv_guid2str(&dev_ctx->device_id, guidbuf, sizeof(guidbuf));
1094	strlcat(buf, guidbuf, buflen);
1095
1096	return (0);
1097}
1098
1099struct hv_device *
1100hv_vmbus_child_device_create(hv_guid type, hv_guid instance,
1101    hv_vmbus_channel *channel)
1102{
1103	hv_device *child_dev;
1104
1105	/*
1106	 * Allocate the new child device
1107	 */
1108	child_dev = malloc(sizeof(hv_device), M_DEVBUF, M_WAITOK | M_ZERO);
1109
1110	child_dev->channel = channel;
1111	memcpy(&child_dev->class_id, &type, sizeof(hv_guid));
1112	memcpy(&child_dev->device_id, &instance, sizeof(hv_guid));
1113
1114	return (child_dev);
1115}
1116
1117void
1118hv_vmbus_child_device_register(struct vmbus_softc *sc,
1119    struct hv_device *child_dev)
1120{
1121	device_t child, parent;
1122
1123	parent = sc->vmbus_dev;
1124	if (bootverbose) {
1125		char name[HYPERV_GUID_STRLEN];
1126
1127		hyperv_guid2str(&child_dev->class_id, name, sizeof(name));
1128		device_printf(parent, "add device, classid: %s\n", name);
1129	}
1130
1131	child = device_add_child(parent, NULL, -1);
1132	child_dev->device = child;
1133	device_set_ivars(child, child_dev);
1134
1135	/* New device was added to vmbus */
1136	vmbus_scan_newdev(sc);
1137}
1138
1139int
1140hv_vmbus_child_device_unregister(struct hv_device *child_dev)
1141{
1142	int ret = 0;
1143	/*
1144	 * XXXKYS: Ensure that this is the opposite of
1145	 * device_add_child()
1146	 */
1147	mtx_lock(&Giant);
1148	ret = device_delete_child(vmbus_get_device(), child_dev->device);
1149	mtx_unlock(&Giant);
1150	return(ret);
1151}
1152
1153static int
1154vmbus_sysctl_version(SYSCTL_HANDLER_ARGS)
1155{
1156	struct vmbus_softc *sc = arg1;
1157	char verstr[16];
1158
1159	snprintf(verstr, sizeof(verstr), "%u.%u",
1160	    VMBUS_VERSION_MAJOR(sc->vmbus_version),
1161	    VMBUS_VERSION_MINOR(sc->vmbus_version));
1162	return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
1163}
1164
1165static uint32_t
1166vmbus_get_version_method(device_t bus, device_t dev)
1167{
1168	struct vmbus_softc *sc = device_get_softc(bus);
1169
1170	return sc->vmbus_version;
1171}
1172
1173static int
1174vmbus_probe(device_t dev)
1175{
1176	char *id[] = { "VMBUS", NULL };
1177
1178	if (ACPI_ID_PROBE(device_get_parent(dev), dev, id) == NULL ||
1179	    device_get_unit(dev) != 0 || vm_guest != VM_GUEST_HV ||
1180	    (hyperv_features & CPUID_HV_MSR_SYNIC) == 0)
1181		return (ENXIO);
1182
1183	device_set_desc(dev, "Hyper-V Vmbus");
1184
1185	return (BUS_PROBE_DEFAULT);
1186}
1187
1188/**
1189 * @brief Main vmbus driver initialization routine.
1190 *
1191 * Here, we
1192 * - initialize the vmbus driver context
1193 * - setup various driver entry points
1194 * - invoke the vmbus hv main init routine
1195 * - get the irq resource
1196 * - invoke the vmbus to add the vmbus root device
1197 * - setup the vmbus root device
1198 * - retrieve the channel offers
1199 */
1200static int
1201vmbus_doattach(struct vmbus_softc *sc)
1202{
1203	struct sysctl_oid_list *child;
1204	struct sysctl_ctx_list *ctx;
1205	int ret;
1206
1207	if (sc->vmbus_flags & VMBUS_FLAG_ATTACHED)
1208		return (0);
1209	sc->vmbus_flags |= VMBUS_FLAG_ATTACHED;
1210
1211	mtx_init(&sc->vmbus_scan_lock, "vmbus scan", NULL, MTX_DEF);
1212	sc->vmbus_gpadl = VMBUS_GPADL_START;
1213	mtx_init(&sc->vmbus_chlist_lock, "vmbus chlist", NULL, MTX_DEF);
1214	TAILQ_INIT(&sc->vmbus_chlist);
1215
1216	/*
1217	 * Create context for "post message" Hypercalls
1218	 */
1219	sc->vmbus_msg_hc = vmbus_msghc_ctx_create(
1220	    bus_get_dma_tag(sc->vmbus_dev));
1221	if (sc->vmbus_msg_hc == NULL) {
1222		ret = ENXIO;
1223		goto cleanup;
1224	}
1225
1226	/*
1227	 * Allocate DMA stuffs.
1228	 */
1229	ret = vmbus_dma_alloc(sc);
1230	if (ret != 0)
1231		goto cleanup;
1232
1233	/*
1234	 * Setup interrupt.
1235	 */
1236	ret = vmbus_intr_setup(sc);
1237	if (ret != 0)
1238		goto cleanup;
1239
1240	/*
1241	 * Setup SynIC.
1242	 */
1243	if (bootverbose)
1244		device_printf(sc->vmbus_dev, "smp_started = %d\n", smp_started);
1245	smp_rendezvous(NULL, vmbus_synic_setup, NULL, sc);
1246	sc->vmbus_flags |= VMBUS_FLAG_SYNIC;
1247
1248	/*
1249	 * Connect to VMBus in the root partition
1250	 */
1251	ret = hv_vmbus_connect(sc);
1252	if (ret != 0)
1253		goto cleanup;
1254
1255	ret = vmbus_init(sc);
1256	if (ret != 0)
1257		goto cleanup;
1258
1259	if (sc->vmbus_version == VMBUS_VERSION_WS2008 ||
1260	    sc->vmbus_version == VMBUS_VERSION_WIN7)
1261		sc->vmbus_event_proc = vmbus_event_proc_compat;
1262	else
1263		sc->vmbus_event_proc = vmbus_event_proc;
1264
1265	ret = vmbus_scan(sc);
1266	if (ret != 0)
1267		goto cleanup;
1268
1269	ctx = device_get_sysctl_ctx(sc->vmbus_dev);
1270	child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->vmbus_dev));
1271	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "version",
1272	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
1273	    vmbus_sysctl_version, "A", "vmbus version");
1274
1275	return (ret);
1276
1277cleanup:
1278	vmbus_intr_teardown(sc);
1279	vmbus_dma_free(sc);
1280	if (sc->vmbus_msg_hc != NULL) {
1281		vmbus_msghc_ctx_destroy(sc->vmbus_msg_hc);
1282		sc->vmbus_msg_hc = NULL;
1283	}
1284	mtx_destroy(&sc->vmbus_scan_lock);
1285
1286	return (ret);
1287}
1288
1289static void
1290vmbus_event_proc_dummy(struct vmbus_softc *sc __unused, int cpu __unused)
1291{
1292}
1293
1294static int
1295vmbus_attach(device_t dev)
1296{
1297	vmbus_sc = device_get_softc(dev);
1298	vmbus_sc->vmbus_dev = dev;
1299
1300	/*
1301	 * Event processing logic will be configured:
1302	 * - After the vmbus protocol version negotiation.
1303	 * - Before we request channel offers.
1304	 */
1305	vmbus_sc->vmbus_event_proc = vmbus_event_proc_dummy;
1306
1307	/*
1308	 * If the system has already booted and thread
1309	 * scheduling is possible indicated by the global
1310	 * cold set to zero, we just call the driver
1311	 * initialization directly.
1312	 */
1313	if (!cold)
1314		vmbus_doattach(vmbus_sc);
1315
1316	return (0);
1317}
1318
1319static void
1320vmbus_sysinit(void *arg __unused)
1321{
1322	struct vmbus_softc *sc = vmbus_get_softc();
1323
1324	if (vm_guest != VM_GUEST_HV || sc == NULL)
1325		return;
1326
1327	/*
1328	 * If the system has already booted and thread
1329	 * scheduling is possible, as indicated by the
1330	 * global cold set to zero, we just call the driver
1331	 * initialization directly.
1332	 */
1333	if (!cold)
1334		vmbus_doattach(sc);
1335}
1336
1337static int
1338vmbus_detach(device_t dev)
1339{
1340	struct vmbus_softc *sc = device_get_softc(dev);
1341
1342	hv_vmbus_release_unattached_channels(sc);
1343
1344	vmbus_disconnect(sc);
1345	hv_vmbus_disconnect();
1346
1347	if (sc->vmbus_flags & VMBUS_FLAG_SYNIC) {
1348		sc->vmbus_flags &= ~VMBUS_FLAG_SYNIC;
1349		smp_rendezvous(NULL, vmbus_synic_teardown, NULL, NULL);
1350	}
1351
1352	vmbus_intr_teardown(sc);
1353	vmbus_dma_free(sc);
1354
1355	if (sc->vmbus_msg_hc != NULL) {
1356		vmbus_msghc_ctx_destroy(sc->vmbus_msg_hc);
1357		sc->vmbus_msg_hc = NULL;
1358	}
1359
1360	mtx_destroy(&sc->vmbus_scan_lock);
1361	return (0);
1362}
1363
1364static device_method_t vmbus_methods[] = {
1365	/* Device interface */
1366	DEVMETHOD(device_probe,			vmbus_probe),
1367	DEVMETHOD(device_attach,		vmbus_attach),
1368	DEVMETHOD(device_detach,		vmbus_detach),
1369	DEVMETHOD(device_shutdown,		bus_generic_shutdown),
1370	DEVMETHOD(device_suspend,		bus_generic_suspend),
1371	DEVMETHOD(device_resume,		bus_generic_resume),
1372
1373	/* Bus interface */
1374	DEVMETHOD(bus_add_child,		bus_generic_add_child),
1375	DEVMETHOD(bus_print_child,		bus_generic_print_child),
1376	DEVMETHOD(bus_read_ivar,		vmbus_read_ivar),
1377	DEVMETHOD(bus_write_ivar,		vmbus_write_ivar),
1378	DEVMETHOD(bus_child_pnpinfo_str,	vmbus_child_pnpinfo_str),
1379
1380	/* Vmbus interface */
1381	DEVMETHOD(vmbus_get_version,		vmbus_get_version_method),
1382
1383	DEVMETHOD_END
1384};
1385
1386static driver_t vmbus_driver = {
1387	"vmbus",
1388	vmbus_methods,
1389	sizeof(struct vmbus_softc)
1390};
1391
1392static devclass_t vmbus_devclass;
1393
1394DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, NULL, NULL);
1395MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
1396MODULE_VERSION(vmbus, 1);
1397
1398/*
1399 * NOTE:
1400 * We have to start as the last step of SI_SUB_SMP, i.e. after SMP is
1401 * initialized.
1402 */
1403SYSINIT(vmbus_initialize, SI_SUB_SMP, SI_ORDER_ANY, vmbus_sysinit, NULL);
1404
1405