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