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