]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/hyperv/vmbus/vmbus.c
MFC 308664,308742,308743
[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/mutex.h>
42 #include <sys/proc.h>
43 #include <sys/smp.h>
44 #include <sys/sysctl.h>
45 #include <sys/systm.h>
46 #include <sys/taskqueue.h>
47
48 #include <machine/bus.h>
49 #include <machine/intr_machdep.h>
50 #include <machine/resource.h>
51 #include <machine/apicvar.h>
52 #include <machine/md_var.h>
53
54 #include <contrib/dev/acpica/include/acpi.h>
55 #include <dev/acpica/acpivar.h>
56
57 #include <dev/hyperv/include/hyperv.h>
58 #include <dev/hyperv/include/vmbus_xact.h>
59 #include <dev/hyperv/vmbus/hyperv_reg.h>
60 #include <dev/hyperv/vmbus/hyperv_var.h>
61 #include <dev/hyperv/vmbus/vmbus_reg.h>
62 #include <dev/hyperv/vmbus/vmbus_var.h>
63 #include <dev/hyperv/vmbus/vmbus_chanvar.h>
64
65 #include "acpi_if.h"
66 #include "pcib_if.h"
67 #include "vmbus_if.h"
68
69 #define VMBUS_GPADL_START               0xe1e10
70
71 struct vmbus_msghc {
72         struct vmbus_xact               *mh_xact;
73         struct hypercall_postmsg_in     mh_inprm_save;
74 };
75
76 static int                      vmbus_probe(device_t);
77 static int                      vmbus_attach(device_t);
78 static int                      vmbus_detach(device_t);
79 static int                      vmbus_read_ivar(device_t, device_t, int,
80                                     uintptr_t *);
81 static int                      vmbus_child_pnpinfo_str(device_t, device_t,
82                                     char *, size_t);
83 static struct resource          *vmbus_alloc_resource(device_t dev,
84                                     device_t child, int type, int *rid,
85                                     rman_res_t start, rman_res_t end,
86                                     rman_res_t count, u_int flags);
87 static int                      vmbus_alloc_msi(device_t bus, device_t dev,
88                                     int count, int maxcount, int *irqs);
89 static int                      vmbus_release_msi(device_t bus, device_t dev,
90                                     int count, int *irqs);
91 static int                      vmbus_alloc_msix(device_t bus, device_t dev,
92                                     int *irq);
93 static int                      vmbus_release_msix(device_t bus, device_t dev,
94                                     int irq);
95 static int                      vmbus_map_msi(device_t bus, device_t dev,
96                                     int irq, uint64_t *addr, uint32_t *data);
97 static uint32_t                 vmbus_get_version_method(device_t, device_t);
98 static int                      vmbus_probe_guid_method(device_t, device_t,
99                                     const struct hyperv_guid *);
100 static uint32_t                 vmbus_get_vcpu_id_method(device_t bus,
101                                     device_t dev, int cpu);
102
103 static int                      vmbus_init(struct vmbus_softc *);
104 static int                      vmbus_connect(struct vmbus_softc *, uint32_t);
105 static int                      vmbus_req_channels(struct vmbus_softc *sc);
106 static void                     vmbus_disconnect(struct vmbus_softc *);
107 static int                      vmbus_scan(struct vmbus_softc *);
108 static void                     vmbus_scan_teardown(struct vmbus_softc *);
109 static void                     vmbus_scan_done(struct vmbus_softc *,
110                                     const struct vmbus_message *);
111 static void                     vmbus_chanmsg_handle(struct vmbus_softc *,
112                                     const struct vmbus_message *);
113 static void                     vmbus_msg_task(void *, int);
114 static void                     vmbus_synic_setup(void *);
115 static void                     vmbus_synic_teardown(void *);
116 static int                      vmbus_sysctl_version(SYSCTL_HANDLER_ARGS);
117 static int                      vmbus_dma_alloc(struct vmbus_softc *);
118 static void                     vmbus_dma_free(struct vmbus_softc *);
119 static int                      vmbus_intr_setup(struct vmbus_softc *);
120 static void                     vmbus_intr_teardown(struct vmbus_softc *);
121 static int                      vmbus_doattach(struct vmbus_softc *);
122 static void                     vmbus_event_proc_dummy(struct vmbus_softc *,
123                                     int);
124
125 static struct vmbus_softc       *vmbus_sc;
126
127 extern inthand_t IDTVEC(rsvd), IDTVEC(vmbus_isr);
128
129 static const uint32_t           vmbus_version[] = {
130         VMBUS_VERSION_WIN8_1,
131         VMBUS_VERSION_WIN8,
132         VMBUS_VERSION_WIN7,
133         VMBUS_VERSION_WS2008
134 };
135
136 static const vmbus_chanmsg_proc_t
137 vmbus_chanmsg_handlers[VMBUS_CHANMSG_TYPE_MAX] = {
138         VMBUS_CHANMSG_PROC(CHOFFER_DONE, vmbus_scan_done),
139         VMBUS_CHANMSG_PROC_WAKEUP(CONNECT_RESP)
140 };
141
142 static device_method_t vmbus_methods[] = {
143         /* Device interface */
144         DEVMETHOD(device_probe,                 vmbus_probe),
145         DEVMETHOD(device_attach,                vmbus_attach),
146         DEVMETHOD(device_detach,                vmbus_detach),
147         DEVMETHOD(device_shutdown,              bus_generic_shutdown),
148         DEVMETHOD(device_suspend,               bus_generic_suspend),
149         DEVMETHOD(device_resume,                bus_generic_resume),
150
151         /* Bus interface */
152         DEVMETHOD(bus_add_child,                bus_generic_add_child),
153         DEVMETHOD(bus_print_child,              bus_generic_print_child),
154         DEVMETHOD(bus_read_ivar,                vmbus_read_ivar),
155         DEVMETHOD(bus_child_pnpinfo_str,        vmbus_child_pnpinfo_str),
156         DEVMETHOD(bus_alloc_resource,           vmbus_alloc_resource),
157         DEVMETHOD(bus_release_resource,         bus_generic_release_resource),
158         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
159         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
160         DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
161         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
162 #if __FreeBSD_version >= 1100000
163         DEVMETHOD(bus_get_cpus,                 bus_generic_get_cpus),
164 #endif
165
166         /* pcib interface */
167         DEVMETHOD(pcib_alloc_msi,               vmbus_alloc_msi),
168         DEVMETHOD(pcib_release_msi,             vmbus_release_msi),
169         DEVMETHOD(pcib_alloc_msix,              vmbus_alloc_msix),
170         DEVMETHOD(pcib_release_msix,            vmbus_release_msix),
171         DEVMETHOD(pcib_map_msi,                 vmbus_map_msi),
172
173         /* Vmbus interface */
174         DEVMETHOD(vmbus_get_version,            vmbus_get_version_method),
175         DEVMETHOD(vmbus_probe_guid,             vmbus_probe_guid_method),
176         DEVMETHOD(vmbus_get_vcpu_id,            vmbus_get_vcpu_id_method),
177
178         DEVMETHOD_END
179 };
180
181 static driver_t vmbus_driver = {
182         "vmbus",
183         vmbus_methods,
184         sizeof(struct vmbus_softc)
185 };
186
187 static devclass_t vmbus_devclass;
188
189 DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, NULL, NULL);
190 MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
191 MODULE_DEPEND(vmbus, pci, 1, 1, 1);
192 MODULE_VERSION(vmbus, 1);
193
194 static __inline struct vmbus_softc *
195 vmbus_get_softc(void)
196 {
197         return vmbus_sc;
198 }
199
200 void
201 vmbus_msghc_reset(struct vmbus_msghc *mh, size_t dsize)
202 {
203         struct hypercall_postmsg_in *inprm;
204
205         if (dsize > HYPERCALL_POSTMSGIN_DSIZE_MAX)
206                 panic("invalid data size %zu", dsize);
207
208         inprm = vmbus_xact_req_data(mh->mh_xact);
209         memset(inprm, 0, HYPERCALL_POSTMSGIN_SIZE);
210         inprm->hc_connid = VMBUS_CONNID_MESSAGE;
211         inprm->hc_msgtype = HYPERV_MSGTYPE_CHANNEL;
212         inprm->hc_dsize = dsize;
213 }
214
215 struct vmbus_msghc *
216 vmbus_msghc_get(struct vmbus_softc *sc, size_t dsize)
217 {
218         struct vmbus_msghc *mh;
219         struct vmbus_xact *xact;
220
221         if (dsize > HYPERCALL_POSTMSGIN_DSIZE_MAX)
222                 panic("invalid data size %zu", dsize);
223
224         xact = vmbus_xact_get(sc->vmbus_xc,
225             dsize + __offsetof(struct hypercall_postmsg_in, hc_data[0]));
226         if (xact == NULL)
227                 return (NULL);
228
229         mh = vmbus_xact_priv(xact, sizeof(*mh));
230         mh->mh_xact = xact;
231
232         vmbus_msghc_reset(mh, dsize);
233         return (mh);
234 }
235
236 void
237 vmbus_msghc_put(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh)
238 {
239
240         vmbus_xact_put(mh->mh_xact);
241 }
242
243 void *
244 vmbus_msghc_dataptr(struct vmbus_msghc *mh)
245 {
246         struct hypercall_postmsg_in *inprm;
247
248         inprm = vmbus_xact_req_data(mh->mh_xact);
249         return (inprm->hc_data);
250 }
251
252 int
253 vmbus_msghc_exec_noresult(struct vmbus_msghc *mh)
254 {
255         sbintime_t time = SBT_1MS;
256         struct hypercall_postmsg_in *inprm;
257         bus_addr_t inprm_paddr;
258         int i;
259
260         inprm = vmbus_xact_req_data(mh->mh_xact);
261         inprm_paddr = vmbus_xact_req_paddr(mh->mh_xact);
262
263         /*
264          * Save the input parameter so that we could restore the input
265          * parameter if the Hypercall failed.
266          *
267          * XXX
268          * Is this really necessary?!  i.e. Will the Hypercall ever
269          * overwrite the input parameter?
270          */
271         memcpy(&mh->mh_inprm_save, inprm, HYPERCALL_POSTMSGIN_SIZE);
272
273         /*
274          * In order to cope with transient failures, e.g. insufficient
275          * resources on host side, we retry the post message Hypercall
276          * several times.  20 retries seem sufficient.
277          */
278 #define HC_RETRY_MAX    20
279
280         for (i = 0; i < HC_RETRY_MAX; ++i) {
281                 uint64_t status;
282
283                 status = hypercall_post_message(inprm_paddr);
284                 if (status == HYPERCALL_STATUS_SUCCESS)
285                         return 0;
286
287                 pause_sbt("hcpmsg", time, 0, C_HARDCLOCK);
288                 if (time < SBT_1S * 2)
289                         time *= 2;
290
291                 /* Restore input parameter and try again */
292                 memcpy(inprm, &mh->mh_inprm_save, HYPERCALL_POSTMSGIN_SIZE);
293         }
294
295 #undef HC_RETRY_MAX
296
297         return EIO;
298 }
299
300 int
301 vmbus_msghc_exec(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh)
302 {
303         int error;
304
305         vmbus_xact_activate(mh->mh_xact);
306         error = vmbus_msghc_exec_noresult(mh);
307         if (error)
308                 vmbus_xact_deactivate(mh->mh_xact);
309         return error;
310 }
311
312 const struct vmbus_message *
313 vmbus_msghc_wait_result(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh)
314 {
315         size_t resp_len;
316
317         return (vmbus_xact_wait(mh->mh_xact, &resp_len));
318 }
319
320 void
321 vmbus_msghc_wakeup(struct vmbus_softc *sc, const struct vmbus_message *msg)
322 {
323
324         vmbus_xact_ctx_wakeup(sc->vmbus_xc, msg, sizeof(*msg));
325 }
326
327 uint32_t
328 vmbus_gpadl_alloc(struct vmbus_softc *sc)
329 {
330         return atomic_fetchadd_int(&sc->vmbus_gpadl, 1);
331 }
332
333 static int
334 vmbus_connect(struct vmbus_softc *sc, uint32_t version)
335 {
336         struct vmbus_chanmsg_connect *req;
337         const struct vmbus_message *msg;
338         struct vmbus_msghc *mh;
339         int error, done = 0;
340
341         mh = vmbus_msghc_get(sc, sizeof(*req));
342         if (mh == NULL)
343                 return ENXIO;
344
345         req = vmbus_msghc_dataptr(mh);
346         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CONNECT;
347         req->chm_ver = version;
348         req->chm_evtflags = sc->vmbus_evtflags_dma.hv_paddr;
349         req->chm_mnf1 = sc->vmbus_mnf1_dma.hv_paddr;
350         req->chm_mnf2 = sc->vmbus_mnf2_dma.hv_paddr;
351
352         error = vmbus_msghc_exec(sc, mh);
353         if (error) {
354                 vmbus_msghc_put(sc, mh);
355                 return error;
356         }
357
358         msg = vmbus_msghc_wait_result(sc, mh);
359         done = ((const struct vmbus_chanmsg_connect_resp *)
360             msg->msg_data)->chm_done;
361
362         vmbus_msghc_put(sc, mh);
363
364         return (done ? 0 : EOPNOTSUPP);
365 }
366
367 static int
368 vmbus_init(struct vmbus_softc *sc)
369 {
370         int i;
371
372         for (i = 0; i < nitems(vmbus_version); ++i) {
373                 int error;
374
375                 error = vmbus_connect(sc, vmbus_version[i]);
376                 if (!error) {
377                         sc->vmbus_version = vmbus_version[i];
378                         device_printf(sc->vmbus_dev, "version %u.%u\n",
379                             VMBUS_VERSION_MAJOR(sc->vmbus_version),
380                             VMBUS_VERSION_MINOR(sc->vmbus_version));
381                         return 0;
382                 }
383         }
384         return ENXIO;
385 }
386
387 static void
388 vmbus_disconnect(struct vmbus_softc *sc)
389 {
390         struct vmbus_chanmsg_disconnect *req;
391         struct vmbus_msghc *mh;
392         int error;
393
394         mh = vmbus_msghc_get(sc, sizeof(*req));
395         if (mh == NULL) {
396                 device_printf(sc->vmbus_dev,
397                     "can not get msg hypercall for disconnect\n");
398                 return;
399         }
400
401         req = vmbus_msghc_dataptr(mh);
402         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_DISCONNECT;
403
404         error = vmbus_msghc_exec_noresult(mh);
405         vmbus_msghc_put(sc, mh);
406
407         if (error) {
408                 device_printf(sc->vmbus_dev,
409                     "disconnect msg hypercall failed\n");
410         }
411 }
412
413 static int
414 vmbus_req_channels(struct vmbus_softc *sc)
415 {
416         struct vmbus_chanmsg_chrequest *req;
417         struct vmbus_msghc *mh;
418         int error;
419
420         mh = vmbus_msghc_get(sc, sizeof(*req));
421         if (mh == NULL)
422                 return ENXIO;
423
424         req = vmbus_msghc_dataptr(mh);
425         req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_CHREQUEST;
426
427         error = vmbus_msghc_exec_noresult(mh);
428         vmbus_msghc_put(sc, mh);
429
430         return error;
431 }
432
433 static void
434 vmbus_scan_done_task(void *xsc, int pending __unused)
435 {
436         struct vmbus_softc *sc = xsc;
437
438         mtx_lock(&Giant);
439         sc->vmbus_scandone = true;
440         mtx_unlock(&Giant);
441         wakeup(&sc->vmbus_scandone);
442 }
443
444 static void
445 vmbus_scan_done(struct vmbus_softc *sc,
446     const struct vmbus_message *msg __unused)
447 {
448
449         taskqueue_enqueue(sc->vmbus_devtq, &sc->vmbus_scandone_task);
450 }
451
452 static int
453 vmbus_scan(struct vmbus_softc *sc)
454 {
455         int error;
456
457         /*
458          * Identify, probe and attach for non-channel devices.
459          */
460         bus_generic_probe(sc->vmbus_dev);
461         bus_generic_attach(sc->vmbus_dev);
462
463         /*
464          * This taskqueue serializes vmbus devices' attach and detach
465          * for channel offer and rescind messages.
466          */
467         sc->vmbus_devtq = taskqueue_create("vmbus dev", M_WAITOK,
468             taskqueue_thread_enqueue, &sc->vmbus_devtq);
469         taskqueue_start_threads(&sc->vmbus_devtq, 1, PI_NET, "vmbusdev");
470         TASK_INIT(&sc->vmbus_scandone_task, 0, vmbus_scan_done_task, sc);
471
472         /*
473          * This taskqueue handles sub-channel detach, so that vmbus
474          * device's detach running in vmbus_devtq can drain its sub-
475          * channels.
476          */
477         sc->vmbus_subchtq = taskqueue_create("vmbus subch", M_WAITOK,
478             taskqueue_thread_enqueue, &sc->vmbus_subchtq);
479         taskqueue_start_threads(&sc->vmbus_subchtq, 1, PI_NET, "vmbussch");
480
481         /*
482          * Start vmbus scanning.
483          */
484         error = vmbus_req_channels(sc);
485         if (error) {
486                 device_printf(sc->vmbus_dev, "channel request failed: %d\n",
487                     error);
488                 return (error);
489         }
490
491         /*
492          * Wait for all vmbus devices from the initial channel offers to be
493          * attached.
494          */
495         GIANT_REQUIRED;
496         while (!sc->vmbus_scandone)
497                 mtx_sleep(&sc->vmbus_scandone, &Giant, 0, "vmbusdev", 0);
498
499         if (bootverbose) {
500                 device_printf(sc->vmbus_dev, "device scan, probe and attach "
501                     "done\n");
502         }
503         return (0);
504 }
505
506 static void
507 vmbus_scan_teardown(struct vmbus_softc *sc)
508 {
509
510         GIANT_REQUIRED;
511         if (sc->vmbus_devtq != NULL) {
512                 mtx_unlock(&Giant);
513                 taskqueue_free(sc->vmbus_devtq);
514                 mtx_lock(&Giant);
515                 sc->vmbus_devtq = NULL;
516         }
517         if (sc->vmbus_subchtq != NULL) {
518                 mtx_unlock(&Giant);
519                 taskqueue_free(sc->vmbus_subchtq);
520                 mtx_lock(&Giant);
521                 sc->vmbus_subchtq = NULL;
522         }
523 }
524
525 static void
526 vmbus_chanmsg_handle(struct vmbus_softc *sc, const struct vmbus_message *msg)
527 {
528         vmbus_chanmsg_proc_t msg_proc;
529         uint32_t msg_type;
530
531         msg_type = ((const struct vmbus_chanmsg_hdr *)msg->msg_data)->chm_type;
532         if (msg_type >= VMBUS_CHANMSG_TYPE_MAX) {
533                 device_printf(sc->vmbus_dev, "unknown message type 0x%x\n",
534                     msg_type);
535                 return;
536         }
537
538         msg_proc = vmbus_chanmsg_handlers[msg_type];
539         if (msg_proc != NULL)
540                 msg_proc(sc, msg);
541
542         /* Channel specific processing */
543         vmbus_chan_msgproc(sc, msg);
544 }
545
546 static void
547 vmbus_msg_task(void *xsc, int pending __unused)
548 {
549         struct vmbus_softc *sc = xsc;
550         volatile struct vmbus_message *msg;
551
552         msg = VMBUS_PCPU_GET(sc, message, curcpu) + VMBUS_SINT_MESSAGE;
553         for (;;) {
554                 if (msg->msg_type == HYPERV_MSGTYPE_NONE) {
555                         /* No message */
556                         break;
557                 } else if (msg->msg_type == HYPERV_MSGTYPE_CHANNEL) {
558                         /* Channel message */
559                         vmbus_chanmsg_handle(sc,
560                             __DEVOLATILE(const struct vmbus_message *, msg));
561                 }
562
563                 msg->msg_type = HYPERV_MSGTYPE_NONE;
564                 /*
565                  * Make sure the write to msg_type (i.e. set to
566                  * HYPERV_MSGTYPE_NONE) happens before we read the
567                  * msg_flags and EOMing. Otherwise, the EOMing will
568                  * not deliver any more messages since there is no
569                  * empty slot
570                  *
571                  * NOTE:
572                  * mb() is used here, since atomic_thread_fence_seq_cst()
573                  * will become compiler fence on UP kernel.
574                  */
575                 mb();
576                 if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
577                         /*
578                          * This will cause message queue rescan to possibly
579                          * deliver another msg from the hypervisor
580                          */
581                         wrmsr(MSR_HV_EOM, 0);
582                 }
583         }
584 }
585
586 static __inline int
587 vmbus_handle_intr1(struct vmbus_softc *sc, struct trapframe *frame, int cpu)
588 {
589         volatile struct vmbus_message *msg;
590         struct vmbus_message *msg_base;
591
592         msg_base = VMBUS_PCPU_GET(sc, message, cpu);
593
594         /*
595          * Check event timer.
596          *
597          * TODO: move this to independent IDT vector.
598          */
599         msg = msg_base + VMBUS_SINT_TIMER;
600         if (msg->msg_type == HYPERV_MSGTYPE_TIMER_EXPIRED) {
601                 msg->msg_type = HYPERV_MSGTYPE_NONE;
602
603                 vmbus_et_intr(frame);
604
605                 /*
606                  * Make sure the write to msg_type (i.e. set to
607                  * HYPERV_MSGTYPE_NONE) happens before we read the
608                  * msg_flags and EOMing. Otherwise, the EOMing will
609                  * not deliver any more messages since there is no
610                  * empty slot
611                  *
612                  * NOTE:
613                  * mb() is used here, since atomic_thread_fence_seq_cst()
614                  * will become compiler fence on UP kernel.
615                  */
616                 mb();
617                 if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
618                         /*
619                          * This will cause message queue rescan to possibly
620                          * deliver another msg from the hypervisor
621                          */
622                         wrmsr(MSR_HV_EOM, 0);
623                 }
624         }
625
626         /*
627          * Check events.  Hot path for network and storage I/O data; high rate.
628          *
629          * NOTE:
630          * As recommended by the Windows guest fellows, we check events before
631          * checking messages.
632          */
633         sc->vmbus_event_proc(sc, cpu);
634
635         /*
636          * Check messages.  Mainly management stuffs; ultra low rate.
637          */
638         msg = msg_base + VMBUS_SINT_MESSAGE;
639         if (__predict_false(msg->msg_type != HYPERV_MSGTYPE_NONE)) {
640                 taskqueue_enqueue(VMBUS_PCPU_GET(sc, message_tq, cpu),
641                     VMBUS_PCPU_PTR(sc, message_task, cpu));
642         }
643
644         return (FILTER_HANDLED);
645 }
646
647 void
648 vmbus_handle_intr(struct trapframe *trap_frame)
649 {
650         struct vmbus_softc *sc = vmbus_get_softc();
651         int cpu = curcpu;
652
653         /*
654          * Disable preemption.
655          */
656         critical_enter();
657
658         /*
659          * Do a little interrupt counting.
660          */
661         (*VMBUS_PCPU_GET(sc, intr_cnt, cpu))++;
662
663         vmbus_handle_intr1(sc, trap_frame, cpu);
664
665         /*
666          * Enable preemption.
667          */
668         critical_exit();
669 }
670
671 static void
672 vmbus_synic_setup(void *xsc)
673 {
674         struct vmbus_softc *sc = xsc;
675         int cpu = curcpu;
676         uint64_t val, orig;
677         uint32_t sint;
678
679         if (hyperv_features & CPUID_HV_MSR_VP_INDEX) {
680                 /* Save virtual processor id. */
681                 VMBUS_PCPU_GET(sc, vcpuid, cpu) = rdmsr(MSR_HV_VP_INDEX);
682         } else {
683                 /* Set virtual processor id to 0 for compatibility. */
684                 VMBUS_PCPU_GET(sc, vcpuid, cpu) = 0;
685         }
686
687         /*
688          * Setup the SynIC message.
689          */
690         orig = rdmsr(MSR_HV_SIMP);
691         val = MSR_HV_SIMP_ENABLE | (orig & MSR_HV_SIMP_RSVD_MASK) |
692             ((VMBUS_PCPU_GET(sc, message_dma.hv_paddr, cpu) >> PAGE_SHIFT) <<
693              MSR_HV_SIMP_PGSHIFT);
694         wrmsr(MSR_HV_SIMP, val);
695
696         /*
697          * Setup the SynIC event flags.
698          */
699         orig = rdmsr(MSR_HV_SIEFP);
700         val = MSR_HV_SIEFP_ENABLE | (orig & MSR_HV_SIEFP_RSVD_MASK) |
701             ((VMBUS_PCPU_GET(sc, event_flags_dma.hv_paddr, cpu)
702               >> PAGE_SHIFT) << MSR_HV_SIEFP_PGSHIFT);
703         wrmsr(MSR_HV_SIEFP, val);
704
705
706         /*
707          * Configure and unmask SINT for message and event flags.
708          */
709         sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
710         orig = rdmsr(sint);
711         val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
712             (orig & MSR_HV_SINT_RSVD_MASK);
713         wrmsr(sint, val);
714
715         /*
716          * Configure and unmask SINT for timer.
717          */
718         sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
719         orig = rdmsr(sint);
720         val = sc->vmbus_idtvec | MSR_HV_SINT_AUTOEOI |
721             (orig & MSR_HV_SINT_RSVD_MASK);
722         wrmsr(sint, val);
723
724         /*
725          * All done; enable SynIC.
726          */
727         orig = rdmsr(MSR_HV_SCONTROL);
728         val = MSR_HV_SCTRL_ENABLE | (orig & MSR_HV_SCTRL_RSVD_MASK);
729         wrmsr(MSR_HV_SCONTROL, val);
730 }
731
732 static void
733 vmbus_synic_teardown(void *arg)
734 {
735         uint64_t orig;
736         uint32_t sint;
737
738         /*
739          * Disable SynIC.
740          */
741         orig = rdmsr(MSR_HV_SCONTROL);
742         wrmsr(MSR_HV_SCONTROL, (orig & MSR_HV_SCTRL_RSVD_MASK));
743
744         /*
745          * Mask message and event flags SINT.
746          */
747         sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
748         orig = rdmsr(sint);
749         wrmsr(sint, orig | MSR_HV_SINT_MASKED);
750
751         /*
752          * Mask timer SINT.
753          */
754         sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
755         orig = rdmsr(sint);
756         wrmsr(sint, orig | MSR_HV_SINT_MASKED);
757
758         /*
759          * Teardown SynIC message.
760          */
761         orig = rdmsr(MSR_HV_SIMP);
762         wrmsr(MSR_HV_SIMP, (orig & MSR_HV_SIMP_RSVD_MASK));
763
764         /*
765          * Teardown SynIC event flags.
766          */
767         orig = rdmsr(MSR_HV_SIEFP);
768         wrmsr(MSR_HV_SIEFP, (orig & MSR_HV_SIEFP_RSVD_MASK));
769 }
770
771 static int
772 vmbus_dma_alloc(struct vmbus_softc *sc)
773 {
774         bus_dma_tag_t parent_dtag;
775         uint8_t *evtflags;
776         int cpu;
777
778         parent_dtag = bus_get_dma_tag(sc->vmbus_dev);
779         CPU_FOREACH(cpu) {
780                 void *ptr;
781
782                 /*
783                  * Per-cpu messages and event flags.
784                  */
785                 ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
786                     PAGE_SIZE, VMBUS_PCPU_PTR(sc, message_dma, cpu),
787                     BUS_DMA_WAITOK | BUS_DMA_ZERO);
788                 if (ptr == NULL)
789                         return ENOMEM;
790                 VMBUS_PCPU_GET(sc, message, cpu) = ptr;
791
792                 ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
793                     PAGE_SIZE, VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
794                     BUS_DMA_WAITOK | BUS_DMA_ZERO);
795                 if (ptr == NULL)
796                         return ENOMEM;
797                 VMBUS_PCPU_GET(sc, event_flags, cpu) = ptr;
798         }
799
800         evtflags = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
801             PAGE_SIZE, &sc->vmbus_evtflags_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
802         if (evtflags == NULL)
803                 return ENOMEM;
804         sc->vmbus_rx_evtflags = (u_long *)evtflags;
805         sc->vmbus_tx_evtflags = (u_long *)(evtflags + (PAGE_SIZE / 2));
806         sc->vmbus_evtflags = evtflags;
807
808         sc->vmbus_mnf1 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
809             PAGE_SIZE, &sc->vmbus_mnf1_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
810         if (sc->vmbus_mnf1 == NULL)
811                 return ENOMEM;
812
813         sc->vmbus_mnf2 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
814             sizeof(struct vmbus_mnf), &sc->vmbus_mnf2_dma,
815             BUS_DMA_WAITOK | BUS_DMA_ZERO);
816         if (sc->vmbus_mnf2 == NULL)
817                 return ENOMEM;
818
819         return 0;
820 }
821
822 static void
823 vmbus_dma_free(struct vmbus_softc *sc)
824 {
825         int cpu;
826
827         if (sc->vmbus_evtflags != NULL) {
828                 hyperv_dmamem_free(&sc->vmbus_evtflags_dma, sc->vmbus_evtflags);
829                 sc->vmbus_evtflags = NULL;
830                 sc->vmbus_rx_evtflags = NULL;
831                 sc->vmbus_tx_evtflags = NULL;
832         }
833         if (sc->vmbus_mnf1 != NULL) {
834                 hyperv_dmamem_free(&sc->vmbus_mnf1_dma, sc->vmbus_mnf1);
835                 sc->vmbus_mnf1 = NULL;
836         }
837         if (sc->vmbus_mnf2 != NULL) {
838                 hyperv_dmamem_free(&sc->vmbus_mnf2_dma, sc->vmbus_mnf2);
839                 sc->vmbus_mnf2 = NULL;
840         }
841
842         CPU_FOREACH(cpu) {
843                 if (VMBUS_PCPU_GET(sc, message, cpu) != NULL) {
844                         hyperv_dmamem_free(
845                             VMBUS_PCPU_PTR(sc, message_dma, cpu),
846                             VMBUS_PCPU_GET(sc, message, cpu));
847                         VMBUS_PCPU_GET(sc, message, cpu) = NULL;
848                 }
849                 if (VMBUS_PCPU_GET(sc, event_flags, cpu) != NULL) {
850                         hyperv_dmamem_free(
851                             VMBUS_PCPU_PTR(sc, event_flags_dma, cpu),
852                             VMBUS_PCPU_GET(sc, event_flags, cpu));
853                         VMBUS_PCPU_GET(sc, event_flags, cpu) = NULL;
854                 }
855         }
856 }
857
858 /**
859  * @brief Find a free IDT slot and setup the interrupt handler.
860  */
861 static int
862 vmbus_vector_alloc(void)
863 {
864         int vector;
865         uintptr_t func;
866         struct gate_descriptor *ip;
867
868         /*
869          * Search backwards form the highest IDT vector available for use
870          * as vmbus channel callback vector. We install 'vmbus_isr'
871          * handler at that vector and use it to interrupt vcpus.
872          */
873         vector = APIC_SPURIOUS_INT;
874         while (--vector >= APIC_IPI_INTS) {
875                 ip = &idt[vector];
876                 func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
877                 if (func == (uintptr_t)&IDTVEC(rsvd)) {
878 #ifdef __i386__
879                         setidt(vector , IDTVEC(vmbus_isr), SDT_SYS386IGT,
880                             SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
881 #else
882                         setidt(vector , IDTVEC(vmbus_isr), SDT_SYSIGT,
883                             SEL_KPL, 0);
884 #endif
885
886                         return (vector);
887                 }
888         }
889         return (0);
890 }
891
892 /**
893  * @brief Restore the IDT slot to rsvd.
894  */
895 static void
896 vmbus_vector_free(int vector)
897 {
898         uintptr_t func;
899         struct gate_descriptor *ip;
900
901         if (vector == 0)
902                 return;
903
904         KASSERT(vector >= APIC_IPI_INTS && vector < APIC_SPURIOUS_INT,
905             ("invalid vector %d", vector));
906
907         ip = &idt[vector];
908         func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset);
909         KASSERT(func == (uintptr_t)&IDTVEC(vmbus_isr),
910             ("invalid vector %d", vector));
911
912         setidt(vector, IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
913 }
914
915 static void
916 vmbus_cpuset_setthread_task(void *xmask, int pending __unused)
917 {
918         cpuset_t *mask = xmask;
919         int error;
920
921         error = cpuset_setthread(curthread->td_tid, mask);
922         if (error) {
923                 panic("curthread=%ju: can't pin; error=%d",
924                     (uintmax_t)curthread->td_tid, error);
925         }
926 }
927
928 static int
929 vmbus_intr_setup(struct vmbus_softc *sc)
930 {
931         int cpu;
932
933         CPU_FOREACH(cpu) {
934                 struct task cpuset_task;
935                 char buf[MAXCOMLEN + 1];
936                 cpuset_t cpu_mask;
937
938                 /* Allocate an interrupt counter for Hyper-V interrupt */
939                 snprintf(buf, sizeof(buf), "cpu%d:hyperv", cpu);
940                 intrcnt_add(buf, VMBUS_PCPU_PTR(sc, intr_cnt, cpu));
941
942                 /*
943                  * Setup taskqueue to handle events.  Task will be per-
944                  * channel.
945                  */
946                 VMBUS_PCPU_GET(sc, event_tq, cpu) = taskqueue_create_fast(
947                     "hyperv event", M_WAITOK, taskqueue_thread_enqueue,
948                     VMBUS_PCPU_PTR(sc, event_tq, cpu));
949                 taskqueue_start_threads(VMBUS_PCPU_PTR(sc, event_tq, cpu),
950                     1, PI_NET, "hvevent%d", cpu);
951
952                 CPU_SETOF(cpu, &cpu_mask);
953                 TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
954                     &cpu_mask);
955                 taskqueue_enqueue(VMBUS_PCPU_GET(sc, event_tq, cpu),
956                     &cpuset_task);
957                 taskqueue_drain(VMBUS_PCPU_GET(sc, event_tq, cpu),
958                     &cpuset_task);
959
960                 /*
961                  * Setup tasks and taskqueues to handle messages.
962                  */
963                 VMBUS_PCPU_GET(sc, message_tq, cpu) = taskqueue_create_fast(
964                     "hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
965                     VMBUS_PCPU_PTR(sc, message_tq, cpu));
966                 taskqueue_start_threads(VMBUS_PCPU_PTR(sc, message_tq, cpu), 1,
967                     PI_NET, "hvmsg%d", cpu);
968                 TASK_INIT(VMBUS_PCPU_PTR(sc, message_task, cpu), 0,
969                     vmbus_msg_task, sc);
970
971                 CPU_SETOF(cpu, &cpu_mask);
972                 TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task,
973                     &cpu_mask);
974                 taskqueue_enqueue(VMBUS_PCPU_GET(sc, message_tq, cpu),
975                     &cpuset_task);
976                 taskqueue_drain(VMBUS_PCPU_GET(sc, message_tq, cpu),
977                     &cpuset_task);
978         }
979
980         /*
981          * All Hyper-V ISR required resources are setup, now let's find a
982          * free IDT vector for Hyper-V ISR and set it up.
983          */
984         sc->vmbus_idtvec = vmbus_vector_alloc();
985         if (sc->vmbus_idtvec == 0) {
986                 device_printf(sc->vmbus_dev, "cannot find free IDT vector\n");
987                 return ENXIO;
988         }
989         if (bootverbose) {
990                 device_printf(sc->vmbus_dev, "vmbus IDT vector %d\n",
991                     sc->vmbus_idtvec);
992         }
993         return 0;
994 }
995
996 static void
997 vmbus_intr_teardown(struct vmbus_softc *sc)
998 {
999         int cpu;
1000
1001         vmbus_vector_free(sc->vmbus_idtvec);
1002
1003         CPU_FOREACH(cpu) {
1004                 if (VMBUS_PCPU_GET(sc, event_tq, cpu) != NULL) {
1005                         taskqueue_free(VMBUS_PCPU_GET(sc, event_tq, cpu));
1006                         VMBUS_PCPU_GET(sc, event_tq, cpu) = NULL;
1007                 }
1008                 if (VMBUS_PCPU_GET(sc, message_tq, cpu) != NULL) {
1009                         taskqueue_drain(VMBUS_PCPU_GET(sc, message_tq, cpu),
1010                             VMBUS_PCPU_PTR(sc, message_task, cpu));
1011                         taskqueue_free(VMBUS_PCPU_GET(sc, message_tq, cpu));
1012                         VMBUS_PCPU_GET(sc, message_tq, cpu) = NULL;
1013                 }
1014         }
1015 }
1016
1017 static int
1018 vmbus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
1019 {
1020         return (ENOENT);
1021 }
1022
1023 static int
1024 vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)
1025 {
1026         const struct vmbus_channel *chan;
1027         char guidbuf[HYPERV_GUID_STRLEN];
1028
1029         chan = vmbus_get_channel(child);
1030         if (chan == NULL) {
1031                 /* Event timer device, which does not belong to a channel */
1032                 return (0);
1033         }
1034
1035         strlcat(buf, "classid=", buflen);
1036         hyperv_guid2str(&chan->ch_guid_type, guidbuf, sizeof(guidbuf));
1037         strlcat(buf, guidbuf, buflen);
1038
1039         strlcat(buf, " deviceid=", buflen);
1040         hyperv_guid2str(&chan->ch_guid_inst, guidbuf, sizeof(guidbuf));
1041         strlcat(buf, guidbuf, buflen);
1042
1043         return (0);
1044 }
1045
1046 int
1047 vmbus_add_child(struct vmbus_channel *chan)
1048 {
1049         struct vmbus_softc *sc = chan->ch_vmbus;
1050         device_t parent = sc->vmbus_dev;
1051
1052         mtx_lock(&Giant);
1053
1054         chan->ch_dev = device_add_child(parent, NULL, -1);
1055         if (chan->ch_dev == NULL) {
1056                 mtx_unlock(&Giant);
1057                 device_printf(parent, "device_add_child for chan%u failed\n",
1058                     chan->ch_id);
1059                 return (ENXIO);
1060         }
1061         device_set_ivars(chan->ch_dev, chan);
1062         device_probe_and_attach(chan->ch_dev);
1063
1064         mtx_unlock(&Giant);
1065         return (0);
1066 }
1067
1068 int
1069 vmbus_delete_child(struct vmbus_channel *chan)
1070 {
1071         int error = 0;
1072
1073         mtx_lock(&Giant);
1074         if (chan->ch_dev != NULL) {
1075                 error = device_delete_child(chan->ch_vmbus->vmbus_dev,
1076                     chan->ch_dev);
1077                 chan->ch_dev = NULL;
1078         }
1079         mtx_unlock(&Giant);
1080         return (error);
1081 }
1082
1083 static int
1084 vmbus_sysctl_version(SYSCTL_HANDLER_ARGS)
1085 {
1086         struct vmbus_softc *sc = arg1;
1087         char verstr[16];
1088
1089         snprintf(verstr, sizeof(verstr), "%u.%u",
1090             VMBUS_VERSION_MAJOR(sc->vmbus_version),
1091             VMBUS_VERSION_MINOR(sc->vmbus_version));
1092         return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
1093 }
1094
1095 /*
1096  * We need the function to make sure the MMIO resource is allocated from the
1097  * ranges found in _CRS.
1098  *
1099  * For the release function, we can use bus_generic_release_resource().
1100  */
1101 static struct resource *
1102 vmbus_alloc_resource(device_t dev, device_t child, int type, int *rid,
1103     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
1104 {
1105         device_t parent = device_get_parent(dev);
1106         struct resource *res;
1107
1108 #ifdef NEW_PCIB
1109         if (type == SYS_RES_MEMORY) {
1110                 struct vmbus_softc *sc = device_get_softc(dev);
1111
1112                 res = pcib_host_res_alloc(&sc->vmbus_mmio_res, child, type,
1113                     rid, start, end, count, flags);
1114         } else
1115 #endif
1116         {
1117                 res = BUS_ALLOC_RESOURCE(parent, child, type, rid, start,
1118                     end, count, flags);
1119         }
1120
1121         return (res);
1122 }
1123
1124 static device_t
1125 get_nexus(device_t vmbus)
1126 {
1127         device_t acpi = device_get_parent(vmbus);
1128         device_t nexus = device_get_parent(acpi);
1129         return (nexus);
1130 }
1131
1132 static int
1133 vmbus_alloc_msi(device_t bus, device_t dev, int count, int maxcount, int *irqs)
1134 {
1135         return (PCIB_ALLOC_MSI(get_nexus(bus), dev, count, maxcount, irqs));
1136 }
1137
1138 static int
1139 vmbus_release_msi(device_t bus, device_t dev, int count, int *irqs)
1140 {
1141         return (PCIB_RELEASE_MSI(get_nexus(bus), dev, count, irqs));
1142 }
1143
1144 static int
1145 vmbus_alloc_msix(device_t bus, device_t dev, int *irq)
1146 {
1147         return (PCIB_ALLOC_MSIX(get_nexus(bus), dev, irq));
1148 }
1149
1150 static int
1151 vmbus_release_msix(device_t bus, device_t dev, int irq)
1152 {
1153         return (PCIB_RELEASE_MSIX(get_nexus(bus), dev, irq));
1154 }
1155
1156 static int
1157 vmbus_map_msi(device_t bus, device_t dev, int irq, uint64_t *addr,
1158         uint32_t *data)
1159 {
1160         return (PCIB_MAP_MSI(get_nexus(bus), dev, irq, addr, data));
1161 }
1162
1163 static uint32_t
1164 vmbus_get_version_method(device_t bus, device_t dev)
1165 {
1166         struct vmbus_softc *sc = device_get_softc(bus);
1167
1168         return sc->vmbus_version;
1169 }
1170
1171 static int
1172 vmbus_probe_guid_method(device_t bus, device_t dev,
1173     const struct hyperv_guid *guid)
1174 {
1175         const struct vmbus_channel *chan = vmbus_get_channel(dev);
1176
1177         if (memcmp(&chan->ch_guid_type, guid, sizeof(struct hyperv_guid)) == 0)
1178                 return 0;
1179         return ENXIO;
1180 }
1181
1182 static uint32_t
1183 vmbus_get_vcpu_id_method(device_t bus, device_t dev, int cpu)
1184 {
1185         const struct vmbus_softc *sc = device_get_softc(bus);
1186
1187         return (VMBUS_PCPU_GET(sc, vcpuid, cpu));
1188 }
1189
1190 #ifdef NEW_PCIB
1191 #define VTPM_BASE_ADDR 0xfed40000
1192 #define FOUR_GB (1ULL << 32)
1193
1194 enum parse_pass { parse_64, parse_32 };
1195
1196 struct parse_context {
1197         device_t vmbus_dev;
1198         enum parse_pass pass;
1199 };
1200
1201 static ACPI_STATUS
1202 parse_crs(ACPI_RESOURCE *res, void *ctx)
1203 {
1204         const struct parse_context *pc = ctx;
1205         device_t vmbus_dev = pc->vmbus_dev;
1206
1207         struct vmbus_softc *sc = device_get_softc(vmbus_dev);
1208         UINT64 start, end;
1209
1210         switch (res->Type) {
1211         case ACPI_RESOURCE_TYPE_ADDRESS32:
1212                 start = res->Data.Address32.Address.Minimum;
1213                 end = res->Data.Address32.Address.Maximum;
1214                 break;
1215
1216         case ACPI_RESOURCE_TYPE_ADDRESS64:
1217                 start = res->Data.Address64.Address.Minimum;
1218                 end = res->Data.Address64.Address.Maximum;
1219                 break;
1220
1221         default:
1222                 /* Unused types. */
1223                 return (AE_OK);
1224         }
1225
1226         /*
1227          * We don't use <1MB addresses.
1228          */
1229         if (end < 0x100000)
1230                 return (AE_OK);
1231
1232         /* Don't conflict with vTPM. */
1233         if (end >= VTPM_BASE_ADDR && start < VTPM_BASE_ADDR)
1234                 end = VTPM_BASE_ADDR - 1;
1235
1236         if ((pc->pass == parse_32 && start < FOUR_GB) ||
1237             (pc->pass == parse_64 && start >= FOUR_GB))
1238                 pcib_host_res_decodes(&sc->vmbus_mmio_res, SYS_RES_MEMORY,
1239                     start, end, 0);
1240
1241         return (AE_OK);
1242 }
1243
1244 static void
1245 vmbus_get_crs(device_t dev, device_t vmbus_dev, enum parse_pass pass)
1246 {
1247         struct parse_context pc;
1248         ACPI_STATUS status;
1249
1250         if (bootverbose)
1251                 device_printf(dev, "walking _CRS, pass=%d\n", pass);
1252
1253         pc.vmbus_dev = vmbus_dev;
1254         pc.pass = pass;
1255         status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
1256                         parse_crs, &pc);
1257
1258         if (bootverbose && ACPI_FAILURE(status))
1259                 device_printf(dev, "_CRS: not found, pass=%d\n", pass);
1260 }
1261
1262 static void
1263 vmbus_get_mmio_res_pass(device_t dev, enum parse_pass pass)
1264 {
1265         device_t acpi0, pcib0 = NULL;
1266         device_t *children;
1267         int i, count;
1268
1269         /* Try to find _CRS on VMBus device */
1270         vmbus_get_crs(dev, dev, pass);
1271
1272         /* Try to find _CRS on VMBus device's parent */
1273         acpi0 = device_get_parent(dev);
1274         vmbus_get_crs(acpi0, dev, pass);
1275
1276         /* Try to locate pcib0 and find _CRS on it */
1277         if (device_get_children(acpi0, &children, &count) != 0)
1278                 return;
1279
1280         for (i = 0; i < count; i++) {
1281                 if (!device_is_attached(children[i]))
1282                         continue;
1283
1284                 if (strcmp("pcib0", device_get_nameunit(children[i])))
1285                         continue;
1286
1287                 pcib0 = children[i];
1288                 break;
1289         }
1290
1291         if (pcib0)
1292                 vmbus_get_crs(pcib0, dev, pass);
1293
1294         free(children, M_TEMP);
1295 }
1296
1297 static void
1298 vmbus_get_mmio_res(device_t dev)
1299 {
1300         struct vmbus_softc *sc = device_get_softc(dev);
1301         /*
1302          * We walk the resources twice to make sure that: in the resource
1303          * list, the 32-bit resources appear behind the 64-bit resources.
1304          * NB: resource_list_add() uses INSERT_TAIL. This way, when we
1305          * iterate through the list to find a range for a 64-bit BAR in
1306          * vmbus_alloc_resource(), we can make sure we try to use >4GB
1307          * ranges first.
1308          */
1309         pcib_host_res_init(dev, &sc->vmbus_mmio_res);
1310
1311         vmbus_get_mmio_res_pass(dev, parse_64);
1312         vmbus_get_mmio_res_pass(dev, parse_32);
1313 }
1314
1315 static void
1316 vmbus_free_mmio_res(device_t dev)
1317 {
1318         struct vmbus_softc *sc = device_get_softc(dev);
1319
1320         pcib_host_res_free(dev, &sc->vmbus_mmio_res);
1321 }
1322 #endif  /* NEW_PCIB */
1323
1324 static int
1325 vmbus_probe(device_t dev)
1326 {
1327         char *id[] = { "VMBUS", NULL };
1328
1329         if (ACPI_ID_PROBE(device_get_parent(dev), dev, id) == NULL ||
1330             device_get_unit(dev) != 0 || vm_guest != VM_GUEST_HV ||
1331             (hyperv_features & CPUID_HV_MSR_SYNIC) == 0)
1332                 return (ENXIO);
1333
1334         device_set_desc(dev, "Hyper-V Vmbus");
1335
1336         return (BUS_PROBE_DEFAULT);
1337 }
1338
1339 /**
1340  * @brief Main vmbus driver initialization routine.
1341  *
1342  * Here, we
1343  * - initialize the vmbus driver context
1344  * - setup various driver entry points
1345  * - invoke the vmbus hv main init routine
1346  * - get the irq resource
1347  * - invoke the vmbus to add the vmbus root device
1348  * - setup the vmbus root device
1349  * - retrieve the channel offers
1350  */
1351 static int
1352 vmbus_doattach(struct vmbus_softc *sc)
1353 {
1354         struct sysctl_oid_list *child;
1355         struct sysctl_ctx_list *ctx;
1356         int ret;
1357
1358         if (sc->vmbus_flags & VMBUS_FLAG_ATTACHED)
1359                 return (0);
1360
1361 #ifdef NEW_PCIB
1362         vmbus_get_mmio_res(sc->vmbus_dev);
1363 #endif
1364
1365         sc->vmbus_flags |= VMBUS_FLAG_ATTACHED;
1366
1367         sc->vmbus_gpadl = VMBUS_GPADL_START;
1368         mtx_init(&sc->vmbus_prichan_lock, "vmbus prichan", NULL, MTX_DEF);
1369         TAILQ_INIT(&sc->vmbus_prichans);
1370         mtx_init(&sc->vmbus_chan_lock, "vmbus channel", NULL, MTX_DEF);
1371         TAILQ_INIT(&sc->vmbus_chans);
1372         sc->vmbus_chmap = malloc(
1373             sizeof(struct vmbus_channel *) * VMBUS_CHAN_MAX, M_DEVBUF,
1374             M_WAITOK | M_ZERO);
1375
1376         /*
1377          * Create context for "post message" Hypercalls
1378          */
1379         sc->vmbus_xc = vmbus_xact_ctx_create(bus_get_dma_tag(sc->vmbus_dev),
1380             HYPERCALL_POSTMSGIN_SIZE, VMBUS_MSG_SIZE,
1381             sizeof(struct vmbus_msghc));
1382         if (sc->vmbus_xc == NULL) {
1383                 ret = ENXIO;
1384                 goto cleanup;
1385         }
1386
1387         /*
1388          * Allocate DMA stuffs.
1389          */
1390         ret = vmbus_dma_alloc(sc);
1391         if (ret != 0)
1392                 goto cleanup;
1393
1394         /*
1395          * Setup interrupt.
1396          */
1397         ret = vmbus_intr_setup(sc);
1398         if (ret != 0)
1399                 goto cleanup;
1400
1401         /*
1402          * Setup SynIC.
1403          */
1404         if (bootverbose)
1405                 device_printf(sc->vmbus_dev, "smp_started = %d\n", smp_started);
1406         smp_rendezvous(NULL, vmbus_synic_setup, NULL, sc);
1407         sc->vmbus_flags |= VMBUS_FLAG_SYNIC;
1408
1409         /*
1410          * Initialize vmbus, e.g. connect to Hypervisor.
1411          */
1412         ret = vmbus_init(sc);
1413         if (ret != 0)
1414                 goto cleanup;
1415
1416         if (sc->vmbus_version == VMBUS_VERSION_WS2008 ||
1417             sc->vmbus_version == VMBUS_VERSION_WIN7)
1418                 sc->vmbus_event_proc = vmbus_event_proc_compat;
1419         else
1420                 sc->vmbus_event_proc = vmbus_event_proc;
1421
1422         ret = vmbus_scan(sc);
1423         if (ret != 0)
1424                 goto cleanup;
1425
1426         ctx = device_get_sysctl_ctx(sc->vmbus_dev);
1427         child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->vmbus_dev));
1428         SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "version",
1429             CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
1430             vmbus_sysctl_version, "A", "vmbus version");
1431
1432         return (ret);
1433
1434 cleanup:
1435         vmbus_scan_teardown(sc);
1436         vmbus_intr_teardown(sc);
1437         vmbus_dma_free(sc);
1438         if (sc->vmbus_xc != NULL) {
1439                 vmbus_xact_ctx_destroy(sc->vmbus_xc);
1440                 sc->vmbus_xc = NULL;
1441         }
1442         free(sc->vmbus_chmap, M_DEVBUF);
1443         mtx_destroy(&sc->vmbus_prichan_lock);
1444         mtx_destroy(&sc->vmbus_chan_lock);
1445
1446         return (ret);
1447 }
1448
1449 static void
1450 vmbus_event_proc_dummy(struct vmbus_softc *sc __unused, int cpu __unused)
1451 {
1452 }
1453
1454 static int
1455 vmbus_attach(device_t dev)
1456 {
1457         vmbus_sc = device_get_softc(dev);
1458         vmbus_sc->vmbus_dev = dev;
1459
1460         /*
1461          * Event processing logic will be configured:
1462          * - After the vmbus protocol version negotiation.
1463          * - Before we request channel offers.
1464          */
1465         vmbus_sc->vmbus_event_proc = vmbus_event_proc_dummy;
1466
1467         /* 
1468          * If the system has already booted and thread
1469          * scheduling is possible indicated by the global
1470          * cold set to zero, we just call the driver
1471          * initialization directly.
1472          */
1473         if (!cold)
1474                 vmbus_doattach(vmbus_sc);
1475
1476         return (0);
1477 }
1478
1479 static int
1480 vmbus_detach(device_t dev)
1481 {
1482         struct vmbus_softc *sc = device_get_softc(dev);
1483
1484         bus_generic_detach(dev);
1485         vmbus_chan_destroy_all(sc);
1486
1487         vmbus_scan_teardown(sc);
1488
1489         vmbus_disconnect(sc);
1490
1491         if (sc->vmbus_flags & VMBUS_FLAG_SYNIC) {
1492                 sc->vmbus_flags &= ~VMBUS_FLAG_SYNIC;
1493                 smp_rendezvous(NULL, vmbus_synic_teardown, NULL, NULL);
1494         }
1495
1496         vmbus_intr_teardown(sc);
1497         vmbus_dma_free(sc);
1498
1499         if (sc->vmbus_xc != NULL) {
1500                 vmbus_xact_ctx_destroy(sc->vmbus_xc);
1501                 sc->vmbus_xc = NULL;
1502         }
1503
1504         free(sc->vmbus_chmap, M_DEVBUF);
1505         mtx_destroy(&sc->vmbus_prichan_lock);
1506         mtx_destroy(&sc->vmbus_chan_lock);
1507
1508 #ifdef NEW_PCIB
1509         vmbus_free_mmio_res(dev);
1510 #endif
1511
1512         return (0);
1513 }
1514
1515 static void
1516 vmbus_sysinit(void *arg __unused)
1517 {
1518         struct vmbus_softc *sc = vmbus_get_softc();
1519
1520         if (vm_guest != VM_GUEST_HV || sc == NULL)
1521                 return;
1522
1523         /* 
1524          * If the system has already booted and thread
1525          * scheduling is possible, as indicated by the
1526          * global cold set to zero, we just call the driver
1527          * initialization directly.
1528          */
1529         if (!cold) 
1530                 vmbus_doattach(sc);
1531 }
1532 /*
1533  * NOTE:
1534  * We have to start as the last step of SI_SUB_SMP, i.e. after SMP is
1535  * initialized.
1536  */
1537 SYSINIT(vmbus_initialize, SI_SUB_SMP, SI_ORDER_ANY, vmbus_sysinit, NULL);