145de427dSSepherosa Ziehau /*-
245de427dSSepherosa Ziehau * Copyright (c) 2009-2012,2016 Microsoft Corp.
345de427dSSepherosa Ziehau * Copyright (c) 2012 NetApp Inc.
445de427dSSepherosa Ziehau * Copyright (c) 2012 Citrix Inc.
545de427dSSepherosa Ziehau * All rights reserved.
645de427dSSepherosa Ziehau *
745de427dSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
845de427dSSepherosa Ziehau * modification, are permitted provided that the following conditions
945de427dSSepherosa Ziehau * are met:
1045de427dSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright
1145de427dSSepherosa Ziehau * notice unmodified, this list of conditions, and the following
1245de427dSSepherosa Ziehau * disclaimer.
1345de427dSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
1445de427dSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the
1545de427dSSepherosa Ziehau * documentation and/or other materials provided with the distribution.
1645de427dSSepherosa Ziehau *
1745de427dSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1845de427dSSepherosa Ziehau * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1945de427dSSepherosa Ziehau * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2045de427dSSepherosa Ziehau * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2145de427dSSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2245de427dSSepherosa Ziehau * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2345de427dSSepherosa Ziehau * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2445de427dSSepherosa Ziehau * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2545de427dSSepherosa Ziehau * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2645de427dSSepherosa Ziehau * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2745de427dSSepherosa Ziehau */
2845de427dSSepherosa Ziehau
2945de427dSSepherosa Ziehau #include "opt_acpi.h"
3045de427dSSepherosa Ziehau
3145de427dSSepherosa Ziehau #include <sys/param.h>
3245de427dSSepherosa Ziehau #include <sys/bus.h>
3345de427dSSepherosa Ziehau #include <sys/kernel.h>
34e2164e29Szrj #include <sys/malloc.h>
3545de427dSSepherosa Ziehau #include <sys/module.h>
36e3c41896SSepherosa Ziehau #include <sys/rman.h>
37e3c41896SSepherosa Ziehau #include <sys/systimer.h>
38e3c41896SSepherosa Ziehau #include <sys/thread.h>
39e3c41896SSepherosa Ziehau #include <sys/thread2.h>
4045de427dSSepherosa Ziehau
41e3c41896SSepherosa Ziehau #include <machine/intr_machdep.h>
42e3c41896SSepherosa Ziehau #include <machine/smp.h>
43e3c41896SSepherosa Ziehau
44cb60f91bSSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_busdma.h>
4582b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_machdep.h>
4682b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_reg.h>
4782b77854SSepherosa Ziehau #include <dev/virtual/hyperv/hyperv_var.h>
48e3c41896SSepherosa Ziehau #include <dev/virtual/hyperv/vmbus/vmbus_reg.h>
49e3c41896SSepherosa Ziehau #include <dev/virtual/hyperv/vmbus/vmbus_var.h>
5045de427dSSepherosa Ziehau
5145de427dSSepherosa Ziehau #include "acpi.h"
5245de427dSSepherosa Ziehau #include "acpi_if.h"
53e3c41896SSepherosa Ziehau #include "pcib_if.h"
54e3c41896SSepherosa Ziehau
55e3c41896SSepherosa Ziehau #define MSR_HV_STIMER0_CFG_SINT \
56e3c41896SSepherosa Ziehau ((((uint64_t)VMBUS_SINT_TIMER) << MSR_HV_STIMER_CFG_SINT_SHIFT) & \
57e3c41896SSepherosa Ziehau MSR_HV_STIMER_CFG_SINT_MASK)
58e3c41896SSepherosa Ziehau
59e3c41896SSepherosa Ziehau /*
606bc7b4f2SSepherosa Ziehau * Additionally required feature:
6105ec79ddSSepherosa Ziehau * - SynIC is needed for interrupt generation.
6205ec79ddSSepherosa Ziehau */
636bc7b4f2SSepherosa Ziehau #define CPUID_HV_TIMER_MASK (CPUID_HV_MSR_SYNIC | \
6405ec79ddSSepherosa Ziehau CPUID_HV_MSR_SYNTIMER)
6505ec79ddSSepherosa Ziehau
6605ec79ddSSepherosa Ziehau /*
67e3c41896SSepherosa Ziehau * NOTE: DO NOT CHANGE THIS.
68e3c41896SSepherosa Ziehau */
69e3c41896SSepherosa Ziehau #define VMBUS_SINT_MESSAGE 2
70e3c41896SSepherosa Ziehau /*
71e3c41896SSepherosa Ziehau * NOTE:
72e3c41896SSepherosa Ziehau * - DO NOT set it to the same value as VMBUS_SINT_MESSAGE.
73e3c41896SSepherosa Ziehau * - DO NOT set it to 0.
74e3c41896SSepherosa Ziehau */
75e3c41896SSepherosa Ziehau #define VMBUS_SINT_TIMER 4
76e3c41896SSepherosa Ziehau
77e3c41896SSepherosa Ziehau /*
78e3c41896SSepherosa Ziehau * NOTE: DO NOT CHANGE THESE
79e3c41896SSepherosa Ziehau */
80e3c41896SSepherosa Ziehau #define VMBUS_CONNID_MESSAGE 1
81e3c41896SSepherosa Ziehau #define VMBUS_CONNID_EVENT 2
82e3c41896SSepherosa Ziehau
83e3c41896SSepherosa Ziehau struct vmbus_msghc {
84e3c41896SSepherosa Ziehau struct hypercall_postmsg_in *mh_inprm;
85e3c41896SSepherosa Ziehau struct hypercall_postmsg_in mh_inprm_save;
86e3c41896SSepherosa Ziehau struct hyperv_dma mh_inprm_dma;
87e3c41896SSepherosa Ziehau
88e3c41896SSepherosa Ziehau struct vmbus_message *mh_resp;
89e3c41896SSepherosa Ziehau struct vmbus_message mh_resp0;
90e3c41896SSepherosa Ziehau };
91e3c41896SSepherosa Ziehau
92e3c41896SSepherosa Ziehau struct vmbus_msghc_ctx {
93e3c41896SSepherosa Ziehau struct vmbus_msghc *mhc_free;
94e3c41896SSepherosa Ziehau struct lwkt_token mhc_free_token;
95e3c41896SSepherosa Ziehau uint32_t mhc_flags;
96e3c41896SSepherosa Ziehau
97e3c41896SSepherosa Ziehau struct vmbus_msghc *mhc_active;
98e3c41896SSepherosa Ziehau struct lwkt_token mhc_active_token;
99e3c41896SSepherosa Ziehau };
100e3c41896SSepherosa Ziehau
101e3c41896SSepherosa Ziehau #define VMBUS_MSGHC_CTXF_DESTROY 0x0001
10245de427dSSepherosa Ziehau
10345de427dSSepherosa Ziehau static int vmbus_probe(device_t);
10445de427dSSepherosa Ziehau static int vmbus_attach(device_t);
10545de427dSSepherosa Ziehau static int vmbus_detach(device_t);
106e3c41896SSepherosa Ziehau static void vmbus_intr(void *);
107e3c41896SSepherosa Ziehau static void vmbus_timer_intr_reload(struct cputimer_intr *,
108e3c41896SSepherosa Ziehau sysclock_t);
109e3c41896SSepherosa Ziehau static void vmbus_timer_intr_pcpuhand(
110e3c41896SSepherosa Ziehau struct cputimer_intr *);
111e3c41896SSepherosa Ziehau static void vmbus_timer_intr_restart(
112e3c41896SSepherosa Ziehau struct cputimer_intr *);
113e3c41896SSepherosa Ziehau
114e3c41896SSepherosa Ziehau static int vmbus_dma_alloc(struct vmbus_softc *);
115e3c41896SSepherosa Ziehau static void vmbus_dma_free(struct vmbus_softc *);
116e3c41896SSepherosa Ziehau static int vmbus_intr_setup(struct vmbus_softc *);
117e3c41896SSepherosa Ziehau static void vmbus_intr_teardown(struct vmbus_softc *);
118e3c41896SSepherosa Ziehau static void vmbus_synic_setup(void *);
119e3c41896SSepherosa Ziehau static void vmbus_synic_teardown(void *);
120e3c41896SSepherosa Ziehau static void vmbus_timer_stop(void *);
121e3c41896SSepherosa Ziehau static void vmbus_timer_config(void *);
122e3c41896SSepherosa Ziehau static int vmbus_init(struct vmbus_softc *);
123e3c41896SSepherosa Ziehau static int vmbus_init_contact(struct vmbus_softc *,
124e3c41896SSepherosa Ziehau uint32_t);
125e3c41896SSepherosa Ziehau static void vmbus_timer_restart(void *);
126e3c41896SSepherosa Ziehau static void vmbus_timer_msgintr(struct vmbus_pcpu_data *);
127e3c41896SSepherosa Ziehau
128e3c41896SSepherosa Ziehau static void vmbus_chan_msgproc(struct vmbus_softc *,
129e3c41896SSepherosa Ziehau const struct vmbus_message *);
130e3c41896SSepherosa Ziehau
131e3c41896SSepherosa Ziehau static struct vmbus_msghc_ctx *vmbus_msghc_ctx_create(bus_dma_tag_t);
132e3c41896SSepherosa Ziehau static void vmbus_msghc_ctx_destroy(
133e3c41896SSepherosa Ziehau struct vmbus_msghc_ctx *);
134e3c41896SSepherosa Ziehau static void vmbus_msghc_ctx_free(struct vmbus_msghc_ctx *);
135e3c41896SSepherosa Ziehau static struct vmbus_msghc *vmbus_msghc_alloc(bus_dma_tag_t);
136e3c41896SSepherosa Ziehau static void vmbus_msghc_free(struct vmbus_msghc *);
137e3c41896SSepherosa Ziehau static struct vmbus_msghc *vmbus_msghc_get1(struct vmbus_msghc_ctx *,
138e3c41896SSepherosa Ziehau uint32_t);
13945de427dSSepherosa Ziehau
14045de427dSSepherosa Ziehau static device_method_t vmbus_methods[] = {
14145de427dSSepherosa Ziehau /* Device interface */
14245de427dSSepherosa Ziehau DEVMETHOD(device_probe, vmbus_probe),
14345de427dSSepherosa Ziehau DEVMETHOD(device_attach, vmbus_attach),
14445de427dSSepherosa Ziehau DEVMETHOD(device_detach, vmbus_detach),
14545de427dSSepherosa Ziehau DEVMETHOD(device_shutdown, bus_generic_shutdown),
14645de427dSSepherosa Ziehau DEVMETHOD(device_suspend, bus_generic_suspend),
14745de427dSSepherosa Ziehau DEVMETHOD(device_resume, bus_generic_resume),
14845de427dSSepherosa Ziehau
14945de427dSSepherosa Ziehau DEVMETHOD_END
15045de427dSSepherosa Ziehau };
15145de427dSSepherosa Ziehau
15245de427dSSepherosa Ziehau static driver_t vmbus_driver = {
15345de427dSSepherosa Ziehau "vmbus",
15445de427dSSepherosa Ziehau vmbus_methods,
155e3c41896SSepherosa Ziehau sizeof(struct vmbus_softc)
15645de427dSSepherosa Ziehau };
15745de427dSSepherosa Ziehau
15845de427dSSepherosa Ziehau static devclass_t vmbus_devclass;
15945de427dSSepherosa Ziehau
16045de427dSSepherosa Ziehau DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, NULL, NULL);
16145de427dSSepherosa Ziehau MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
16245de427dSSepherosa Ziehau MODULE_VERSION(vmbus, 1);
16345de427dSSepherosa Ziehau
164e3c41896SSepherosa Ziehau static struct cputimer_intr vmbus_cputimer_intr = {
165e3c41896SSepherosa Ziehau .freq = HYPERV_TIMER_FREQ,
166e3c41896SSepherosa Ziehau .reload = vmbus_timer_intr_reload,
167e3c41896SSepherosa Ziehau .enable = cputimer_intr_default_enable,
168e3c41896SSepherosa Ziehau .config = cputimer_intr_default_config,
169e3c41896SSepherosa Ziehau .restart = vmbus_timer_intr_restart,
170e3c41896SSepherosa Ziehau .pmfixup = cputimer_intr_default_pmfixup,
171e3c41896SSepherosa Ziehau .initclock = cputimer_intr_default_initclock,
172e3c41896SSepherosa Ziehau .pcpuhand = vmbus_timer_intr_pcpuhand,
173e3c41896SSepherosa Ziehau .next = SLIST_ENTRY_INITIALIZER,
174e3c41896SSepherosa Ziehau .name = "hyperv",
175e3c41896SSepherosa Ziehau .type = CPUTIMER_INTR_VMM,
176e3c41896SSepherosa Ziehau .prio = CPUTIMER_INTR_PRIO_VMM,
177e3c41896SSepherosa Ziehau .caps = CPUTIMER_INTR_CAP_PS,
178e3c41896SSepherosa Ziehau .priv = NULL
179e3c41896SSepherosa Ziehau };
180e3c41896SSepherosa Ziehau
181e3c41896SSepherosa Ziehau static const uint32_t vmbus_version[] = {
182e3c41896SSepherosa Ziehau VMBUS_VERSION_WIN8_1,
183e3c41896SSepherosa Ziehau VMBUS_VERSION_WIN8,
184e3c41896SSepherosa Ziehau VMBUS_VERSION_WIN7,
185e3c41896SSepherosa Ziehau VMBUS_VERSION_WS2008
186e3c41896SSepherosa Ziehau };
187e3c41896SSepherosa Ziehau
188e3c41896SSepherosa Ziehau static int vmbus_timer_intr_enable = 1;
189e3c41896SSepherosa Ziehau TUNABLE_INT("hw.vmbus.timer_intr.enable", &vmbus_timer_intr_enable);
190e3c41896SSepherosa Ziehau
19145de427dSSepherosa Ziehau static int
vmbus_probe(device_t dev)19245de427dSSepherosa Ziehau vmbus_probe(device_t dev)
19345de427dSSepherosa Ziehau {
19445de427dSSepherosa Ziehau char *id[] = { "VMBUS", NULL };
19545de427dSSepherosa Ziehau
19645de427dSSepherosa Ziehau if (ACPI_ID_PROBE(device_get_parent(dev), dev, id) == NULL ||
19745de427dSSepherosa Ziehau device_get_unit(dev) != 0 || vmm_guest != VMM_GUEST_HYPERV ||
19845de427dSSepherosa Ziehau (hyperv_features & CPUID_HV_MSR_SYNIC) == 0)
19945de427dSSepherosa Ziehau return (ENXIO);
20045de427dSSepherosa Ziehau
20145de427dSSepherosa Ziehau device_set_desc(dev, "Hyper-V vmbus");
20245de427dSSepherosa Ziehau
20345de427dSSepherosa Ziehau return (0);
20445de427dSSepherosa Ziehau }
20545de427dSSepherosa Ziehau
20645de427dSSepherosa Ziehau static int
vmbus_attach(device_t dev)20745de427dSSepherosa Ziehau vmbus_attach(device_t dev)
20845de427dSSepherosa Ziehau {
209e3c41896SSepherosa Ziehau struct vmbus_softc *sc = device_get_softc(dev);
21005ec79ddSSepherosa Ziehau int error, cpu, use_timer;
211e3c41896SSepherosa Ziehau
21205ec79ddSSepherosa Ziehau /*
21305ec79ddSSepherosa Ziehau * Basic setup.
21405ec79ddSSepherosa Ziehau */
215e3c41896SSepherosa Ziehau sc->vmbus_dev = dev;
216e3c41896SSepherosa Ziehau for (cpu = 0; cpu < ncpus; ++cpu) {
217e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, cpu);
218e3c41896SSepherosa Ziehau
219e3c41896SSepherosa Ziehau psc->sc = sc;
220e3c41896SSepherosa Ziehau psc->cpuid = cpu;
221e3c41896SSepherosa Ziehau psc->timer_last = UINT64_MAX;
222e3c41896SSepherosa Ziehau }
22305ec79ddSSepherosa Ziehau
22405ec79ddSSepherosa Ziehau /*
22505ec79ddSSepherosa Ziehau * Should we use interrupt timer?
22605ec79ddSSepherosa Ziehau */
22705ec79ddSSepherosa Ziehau use_timer = 0;
22805ec79ddSSepherosa Ziehau if (device_get_unit(dev) == 0 &&
2296bc7b4f2SSepherosa Ziehau (hyperv_features & CPUID_HV_TIMER_MASK) == CPUID_HV_TIMER_MASK &&
2306bc7b4f2SSepherosa Ziehau hyperv_tc64 != NULL)
23105ec79ddSSepherosa Ziehau use_timer = 1;
232e3c41896SSepherosa Ziehau
233e3c41896SSepherosa Ziehau /*
234e3c41896SSepherosa Ziehau * Create context for "post message" Hypercalls
235e3c41896SSepherosa Ziehau */
236e3c41896SSepherosa Ziehau sc->vmbus_msg_hc = vmbus_msghc_ctx_create(
237e3c41896SSepherosa Ziehau bus_get_dma_tag(sc->vmbus_dev));
238e3c41896SSepherosa Ziehau if (sc->vmbus_msg_hc == NULL)
239e3c41896SSepherosa Ziehau return ENXIO;
240e3c41896SSepherosa Ziehau
241e3c41896SSepherosa Ziehau /*
242e3c41896SSepherosa Ziehau * Allocate DMA stuffs.
243e3c41896SSepherosa Ziehau */
244e3c41896SSepherosa Ziehau error = vmbus_dma_alloc(sc);
245e3c41896SSepherosa Ziehau if (error)
246e3c41896SSepherosa Ziehau goto failed;
247e3c41896SSepherosa Ziehau
248e3c41896SSepherosa Ziehau /*
249e3c41896SSepherosa Ziehau * Setup interrupt.
250e3c41896SSepherosa Ziehau */
251e3c41896SSepherosa Ziehau error = vmbus_intr_setup(sc);
252e3c41896SSepherosa Ziehau if (error)
253e3c41896SSepherosa Ziehau goto failed;
254e3c41896SSepherosa Ziehau
25505ec79ddSSepherosa Ziehau if (use_timer) {
256e3c41896SSepherosa Ziehau /*
25705ec79ddSSepherosa Ziehau * Make sure that interrupt timer is stopped.
258e3c41896SSepherosa Ziehau */
259e3c41896SSepherosa Ziehau lwkt_cpusync_simple(smp_active_mask, vmbus_timer_stop, sc);
260e3c41896SSepherosa Ziehau }
261e3c41896SSepherosa Ziehau
262e3c41896SSepherosa Ziehau /*
263e3c41896SSepherosa Ziehau * Setup SynIC.
264e3c41896SSepherosa Ziehau */
265e3c41896SSepherosa Ziehau lwkt_cpusync_simple(smp_active_mask, vmbus_synic_setup, sc);
266e3c41896SSepherosa Ziehau sc->vmbus_flags |= VMBUS_FLAG_SYNIC;
267e3c41896SSepherosa Ziehau
268e3c41896SSepherosa Ziehau /*
269e3c41896SSepherosa Ziehau * Initialize vmbus.
270e3c41896SSepherosa Ziehau */
271e3c41896SSepherosa Ziehau error = vmbus_init(sc);
272e3c41896SSepherosa Ziehau if (error)
273e3c41896SSepherosa Ziehau goto failed;
274e3c41896SSepherosa Ziehau
27505ec79ddSSepherosa Ziehau if (use_timer) {
276e3c41896SSepherosa Ziehau /*
27705ec79ddSSepherosa Ziehau * Configure and register vmbus interrupt timer.
278e3c41896SSepherosa Ziehau */
279e3c41896SSepherosa Ziehau lwkt_cpusync_simple(smp_active_mask, vmbus_timer_config, sc);
280e3c41896SSepherosa Ziehau vmbus_cputimer_intr.priv = sc;
281e3c41896SSepherosa Ziehau cputimer_intr_register(&vmbus_cputimer_intr);
282e3c41896SSepherosa Ziehau if (vmbus_timer_intr_enable)
283e3c41896SSepherosa Ziehau cputimer_intr_select(&vmbus_cputimer_intr, 0);
284e3c41896SSepherosa Ziehau }
285e3c41896SSepherosa Ziehau
286e3c41896SSepherosa Ziehau return 0;
287e3c41896SSepherosa Ziehau failed:
288e3c41896SSepherosa Ziehau vmbus_detach(dev);
289e3c41896SSepherosa Ziehau return error;
29045de427dSSepherosa Ziehau }
29145de427dSSepherosa Ziehau
29245de427dSSepherosa Ziehau static int
vmbus_detach(device_t dev)29345de427dSSepherosa Ziehau vmbus_detach(device_t dev)
29445de427dSSepherosa Ziehau {
295e3c41896SSepherosa Ziehau struct vmbus_softc *sc = device_get_softc(dev);
296e3c41896SSepherosa Ziehau
297e3c41896SSepherosa Ziehau /* TODO: uninitialize vmbus. */
298e3c41896SSepherosa Ziehau /* TODO: stop and deregister timer */
299e3c41896SSepherosa Ziehau
300e3c41896SSepherosa Ziehau if (sc->vmbus_flags & VMBUS_FLAG_SYNIC)
301e3c41896SSepherosa Ziehau lwkt_cpusync_simple(smp_active_mask, vmbus_synic_teardown, sc);
302e3c41896SSepherosa Ziehau vmbus_intr_teardown(sc);
303e3c41896SSepherosa Ziehau vmbus_dma_free(sc);
304e3c41896SSepherosa Ziehau
305e3c41896SSepherosa Ziehau if (sc->vmbus_msg_hc != NULL) {
306e3c41896SSepherosa Ziehau vmbus_msghc_ctx_destroy(sc->vmbus_msg_hc);
307e3c41896SSepherosa Ziehau sc->vmbus_msg_hc = NULL;
308e3c41896SSepherosa Ziehau }
30945de427dSSepherosa Ziehau return (0);
31045de427dSSepherosa Ziehau }
311e3c41896SSepherosa Ziehau
3121f260e2cSSepherosa Ziehau static __inline void
vmbus_msg_reset(volatile struct vmbus_message * msg)3131f260e2cSSepherosa Ziehau vmbus_msg_reset(volatile struct vmbus_message *msg)
3141f260e2cSSepherosa Ziehau {
3151f260e2cSSepherosa Ziehau msg->msg_type = HYPERV_MSGTYPE_NONE;
3161f260e2cSSepherosa Ziehau /*
3171f260e2cSSepherosa Ziehau * Make sure that the write to msg_type (i.e. set to
3181f260e2cSSepherosa Ziehau * HYPERV_MSGTYPE_NONE) happens before we read the
3191f260e2cSSepherosa Ziehau * msg_flags and send EOM to the hypervisor.
3201f260e2cSSepherosa Ziehau */
3211f260e2cSSepherosa Ziehau cpu_mfence();
3221f260e2cSSepherosa Ziehau if (msg->msg_flags & VMBUS_MSGFLAG_PENDING) {
3231f260e2cSSepherosa Ziehau /*
3241f260e2cSSepherosa Ziehau * Ask the hypervisor to rescan message queue,
3251f260e2cSSepherosa Ziehau * and deliver new message if any.
3261f260e2cSSepherosa Ziehau */
3271f260e2cSSepherosa Ziehau wrmsr(MSR_HV_EOM, 0);
3281f260e2cSSepherosa Ziehau }
3291f260e2cSSepherosa Ziehau }
3301f260e2cSSepherosa Ziehau
331e3c41896SSepherosa Ziehau static void
vmbus_intr(void * xpsc)332e3c41896SSepherosa Ziehau vmbus_intr(void *xpsc)
333e3c41896SSepherosa Ziehau {
334e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = xpsc;
335e3c41896SSepherosa Ziehau volatile struct vmbus_message *msg;
336e3c41896SSepherosa Ziehau
337e3c41896SSepherosa Ziehau msg = psc->message + VMBUS_SINT_MESSAGE;
338e3c41896SSepherosa Ziehau while (__predict_false(msg->msg_type != HYPERV_MSGTYPE_NONE)) {
339e3c41896SSepherosa Ziehau if (msg->msg_type == HYPERV_MSGTYPE_CHANNEL) {
340e3c41896SSepherosa Ziehau /* Channel message */
341e3c41896SSepherosa Ziehau vmbus_chan_msgproc(psc->sc,
342e3c41896SSepherosa Ziehau __DEVOLATILE(const struct vmbus_message *, msg));
343e3c41896SSepherosa Ziehau }
3441f260e2cSSepherosa Ziehau vmbus_msg_reset(msg);
345e3c41896SSepherosa Ziehau }
346e3c41896SSepherosa Ziehau }
347e3c41896SSepherosa Ziehau
348e3c41896SSepherosa Ziehau static __inline void
vmbus_timer_oneshot(struct vmbus_pcpu_data * psc,uint64_t current)349e3c41896SSepherosa Ziehau vmbus_timer_oneshot(struct vmbus_pcpu_data *psc, uint64_t current)
350e3c41896SSepherosa Ziehau {
351e3c41896SSepherosa Ziehau psc->timer_last = current;
352e3c41896SSepherosa Ziehau wrmsr(MSR_HV_STIMER0_COUNT, current);
353e3c41896SSepherosa Ziehau }
354e3c41896SSepherosa Ziehau
355e3c41896SSepherosa Ziehau static void
vmbus_timer_intr_reload(struct cputimer_intr * cti,sysclock_t reload)356e3c41896SSepherosa Ziehau vmbus_timer_intr_reload(struct cputimer_intr *cti, sysclock_t reload)
357e3c41896SSepherosa Ziehau {
358e3c41896SSepherosa Ziehau struct globaldata *gd = mycpu;
359e3c41896SSepherosa Ziehau struct vmbus_softc *sc = cti->priv;
360e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, gd->gd_cpuid);
361e3c41896SSepherosa Ziehau uint64_t current;
362e3c41896SSepherosa Ziehau
363*feadd4aeSMatthew Dillon if ((ssysclock_t)reload < 0) /* neg value */
364*feadd4aeSMatthew Dillon reload = 1;
3658fbc264dSMatthew Dillon reload = muldivu64(reload, cti->freq, sys_cputimer->freq);
366a4413ab2SSepherosa Ziehau current = hyperv_tc64() + reload;
367e3c41896SSepherosa Ziehau
368e3c41896SSepherosa Ziehau if (gd->gd_timer_running) {
369e3c41896SSepherosa Ziehau if (current < psc->timer_last)
370e3c41896SSepherosa Ziehau vmbus_timer_oneshot(psc, current);
371e3c41896SSepherosa Ziehau } else {
372e3c41896SSepherosa Ziehau gd->gd_timer_running = 1;
373e3c41896SSepherosa Ziehau vmbus_timer_oneshot(psc, current);
374e3c41896SSepherosa Ziehau }
375e3c41896SSepherosa Ziehau }
376e3c41896SSepherosa Ziehau
377e3c41896SSepherosa Ziehau static void
vmbus_timer_intr_pcpuhand(struct cputimer_intr * cti)378e3c41896SSepherosa Ziehau vmbus_timer_intr_pcpuhand(struct cputimer_intr *cti)
379e3c41896SSepherosa Ziehau {
380e3c41896SSepherosa Ziehau struct vmbus_softc *sc = cti->priv;
381e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, mycpuid);
382e3c41896SSepherosa Ziehau
383e3c41896SSepherosa Ziehau vmbus_timer_msgintr(psc);
384e3c41896SSepherosa Ziehau }
385e3c41896SSepherosa Ziehau
386e3c41896SSepherosa Ziehau static void
vmbus_timer_intr_restart(struct cputimer_intr * cti)387e3c41896SSepherosa Ziehau vmbus_timer_intr_restart(struct cputimer_intr *cti)
388e3c41896SSepherosa Ziehau {
389e3c41896SSepherosa Ziehau lwkt_send_ipiq_mask(smp_active_mask, vmbus_timer_restart, cti->priv);
390e3c41896SSepherosa Ziehau }
391e3c41896SSepherosa Ziehau
392e3c41896SSepherosa Ziehau static struct vmbus_msghc *
vmbus_msghc_alloc(bus_dma_tag_t parent_dtag)393e3c41896SSepherosa Ziehau vmbus_msghc_alloc(bus_dma_tag_t parent_dtag)
394e3c41896SSepherosa Ziehau {
395e3c41896SSepherosa Ziehau struct vmbus_msghc *mh;
396e3c41896SSepherosa Ziehau
397e3c41896SSepherosa Ziehau mh = kmalloc(sizeof(*mh), M_DEVBUF, M_WAITOK | M_ZERO);
398e3c41896SSepherosa Ziehau
399e3c41896SSepherosa Ziehau mh->mh_inprm = hyperv_dmamem_alloc(parent_dtag,
400e3c41896SSepherosa Ziehau HYPERCALL_POSTMSGIN_ALIGN, 0, HYPERCALL_POSTMSGIN_SIZE,
401e3c41896SSepherosa Ziehau &mh->mh_inprm_dma, BUS_DMA_WAITOK);
402e3c41896SSepherosa Ziehau if (mh->mh_inprm == NULL) {
403e3c41896SSepherosa Ziehau kfree(mh, M_DEVBUF);
404e3c41896SSepherosa Ziehau return NULL;
405e3c41896SSepherosa Ziehau }
406e3c41896SSepherosa Ziehau return mh;
407e3c41896SSepherosa Ziehau }
408e3c41896SSepherosa Ziehau
409e3c41896SSepherosa Ziehau static void
vmbus_msghc_free(struct vmbus_msghc * mh)410e3c41896SSepherosa Ziehau vmbus_msghc_free(struct vmbus_msghc *mh)
411e3c41896SSepherosa Ziehau {
412e3c41896SSepherosa Ziehau hyperv_dmamem_free(&mh->mh_inprm_dma, mh->mh_inprm);
413e3c41896SSepherosa Ziehau kfree(mh, M_DEVBUF);
414e3c41896SSepherosa Ziehau }
415e3c41896SSepherosa Ziehau
416e3c41896SSepherosa Ziehau static void
vmbus_msghc_ctx_free(struct vmbus_msghc_ctx * mhc)417e3c41896SSepherosa Ziehau vmbus_msghc_ctx_free(struct vmbus_msghc_ctx *mhc)
418e3c41896SSepherosa Ziehau {
419e3c41896SSepherosa Ziehau KASSERT(mhc->mhc_active == NULL, ("still have active msg hypercall"));
420e3c41896SSepherosa Ziehau KASSERT(mhc->mhc_free == NULL, ("still have hypercall msg"));
421e3c41896SSepherosa Ziehau
422e3c41896SSepherosa Ziehau lwkt_token_uninit(&mhc->mhc_free_token);
423e3c41896SSepherosa Ziehau lwkt_token_uninit(&mhc->mhc_active_token);
424e3c41896SSepherosa Ziehau kfree(mhc, M_DEVBUF);
425e3c41896SSepherosa Ziehau }
426e3c41896SSepherosa Ziehau
427e3c41896SSepherosa Ziehau static struct vmbus_msghc_ctx *
vmbus_msghc_ctx_create(bus_dma_tag_t parent_dtag)428e3c41896SSepherosa Ziehau vmbus_msghc_ctx_create(bus_dma_tag_t parent_dtag)
429e3c41896SSepherosa Ziehau {
430e3c41896SSepherosa Ziehau struct vmbus_msghc_ctx *mhc;
431e3c41896SSepherosa Ziehau
432e3c41896SSepherosa Ziehau mhc = kmalloc(sizeof(*mhc), M_DEVBUF, M_WAITOK | M_ZERO);
433e3c41896SSepherosa Ziehau lwkt_token_init(&mhc->mhc_free_token, "msghcf");
434e3c41896SSepherosa Ziehau lwkt_token_init(&mhc->mhc_active_token, "msghca");
435e3c41896SSepherosa Ziehau
436e3c41896SSepherosa Ziehau mhc->mhc_free = vmbus_msghc_alloc(parent_dtag);
437e3c41896SSepherosa Ziehau if (mhc->mhc_free == NULL) {
438e3c41896SSepherosa Ziehau vmbus_msghc_ctx_free(mhc);
439e3c41896SSepherosa Ziehau return NULL;
440e3c41896SSepherosa Ziehau }
441e3c41896SSepherosa Ziehau return mhc;
442e3c41896SSepherosa Ziehau }
443e3c41896SSepherosa Ziehau
444e3c41896SSepherosa Ziehau static struct vmbus_msghc *
vmbus_msghc_get1(struct vmbus_msghc_ctx * mhc,uint32_t dtor_flag)445e3c41896SSepherosa Ziehau vmbus_msghc_get1(struct vmbus_msghc_ctx *mhc, uint32_t dtor_flag)
446e3c41896SSepherosa Ziehau {
447e3c41896SSepherosa Ziehau struct vmbus_msghc *mh;
448e3c41896SSepherosa Ziehau
449e3c41896SSepherosa Ziehau lwkt_gettoken(&mhc->mhc_free_token);
450e3c41896SSepherosa Ziehau
451e3c41896SSepherosa Ziehau while ((mhc->mhc_flags & dtor_flag) == 0 && mhc->mhc_free == NULL)
452e3c41896SSepherosa Ziehau tsleep(&mhc->mhc_free, 0, "gmsghc", 0);
453e3c41896SSepherosa Ziehau if (mhc->mhc_flags & dtor_flag) {
454e3c41896SSepherosa Ziehau /* Being destroyed */
455e3c41896SSepherosa Ziehau mh = NULL;
456e3c41896SSepherosa Ziehau } else {
457e3c41896SSepherosa Ziehau mh = mhc->mhc_free;
458e3c41896SSepherosa Ziehau KASSERT(mh != NULL, ("no free hypercall msg"));
459e3c41896SSepherosa Ziehau KASSERT(mh->mh_resp == NULL,
460e3c41896SSepherosa Ziehau ("hypercall msg has pending response"));
461e3c41896SSepherosa Ziehau mhc->mhc_free = NULL;
462e3c41896SSepherosa Ziehau }
463e3c41896SSepherosa Ziehau
464e3c41896SSepherosa Ziehau lwkt_reltoken(&mhc->mhc_free_token);
465e3c41896SSepherosa Ziehau
466e3c41896SSepherosa Ziehau return mh;
467e3c41896SSepherosa Ziehau }
468e3c41896SSepherosa Ziehau
469e3c41896SSepherosa Ziehau struct vmbus_msghc *
vmbus_msghc_get(struct vmbus_softc * sc,size_t dsize)470e3c41896SSepherosa Ziehau vmbus_msghc_get(struct vmbus_softc *sc, size_t dsize)
471e3c41896SSepherosa Ziehau {
472e3c41896SSepherosa Ziehau struct hypercall_postmsg_in *inprm;
473e3c41896SSepherosa Ziehau struct vmbus_msghc *mh;
474e3c41896SSepherosa Ziehau
475e3c41896SSepherosa Ziehau if (dsize > HYPERCALL_POSTMSGIN_DSIZE_MAX)
476e3c41896SSepherosa Ziehau return NULL;
477e3c41896SSepherosa Ziehau
478e3c41896SSepherosa Ziehau mh = vmbus_msghc_get1(sc->vmbus_msg_hc, VMBUS_MSGHC_CTXF_DESTROY);
479e3c41896SSepherosa Ziehau if (mh == NULL)
480e3c41896SSepherosa Ziehau return NULL;
481e3c41896SSepherosa Ziehau
482e3c41896SSepherosa Ziehau inprm = mh->mh_inprm;
483e3c41896SSepherosa Ziehau memset(inprm, 0, HYPERCALL_POSTMSGIN_SIZE);
484e3c41896SSepherosa Ziehau inprm->hc_connid = VMBUS_CONNID_MESSAGE;
485e3c41896SSepherosa Ziehau inprm->hc_msgtype = HYPERV_MSGTYPE_CHANNEL;
486e3c41896SSepherosa Ziehau inprm->hc_dsize = dsize;
487e3c41896SSepherosa Ziehau
488e3c41896SSepherosa Ziehau return mh;
489e3c41896SSepherosa Ziehau }
490e3c41896SSepherosa Ziehau
491e3c41896SSepherosa Ziehau void
vmbus_msghc_put(struct vmbus_softc * sc,struct vmbus_msghc * mh)492e3c41896SSepherosa Ziehau vmbus_msghc_put(struct vmbus_softc *sc, struct vmbus_msghc *mh)
493e3c41896SSepherosa Ziehau {
494e3c41896SSepherosa Ziehau struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
495e3c41896SSepherosa Ziehau
496e3c41896SSepherosa Ziehau KASSERT(mhc->mhc_active == NULL, ("msg hypercall is active"));
497e3c41896SSepherosa Ziehau mh->mh_resp = NULL;
498e3c41896SSepherosa Ziehau
499e3c41896SSepherosa Ziehau lwkt_gettoken(&mhc->mhc_free_token);
500e3c41896SSepherosa Ziehau KASSERT(mhc->mhc_free == NULL, ("has free hypercall msg"));
501e3c41896SSepherosa Ziehau mhc->mhc_free = mh;
502e3c41896SSepherosa Ziehau lwkt_reltoken(&mhc->mhc_free_token);
503e3c41896SSepherosa Ziehau wakeup(&mhc->mhc_free);
504e3c41896SSepherosa Ziehau }
505e3c41896SSepherosa Ziehau
506e3c41896SSepherosa Ziehau void *
vmbus_msghc_dataptr(struct vmbus_msghc * mh)507e3c41896SSepherosa Ziehau vmbus_msghc_dataptr(struct vmbus_msghc *mh)
508e3c41896SSepherosa Ziehau {
509e3c41896SSepherosa Ziehau return mh->mh_inprm->hc_data;
510e3c41896SSepherosa Ziehau }
511e3c41896SSepherosa Ziehau
512e3c41896SSepherosa Ziehau static void
vmbus_msghc_ctx_destroy(struct vmbus_msghc_ctx * mhc)513e3c41896SSepherosa Ziehau vmbus_msghc_ctx_destroy(struct vmbus_msghc_ctx *mhc)
514e3c41896SSepherosa Ziehau {
515e3c41896SSepherosa Ziehau struct vmbus_msghc *mh;
516e3c41896SSepherosa Ziehau
517e3c41896SSepherosa Ziehau lwkt_gettoken(&mhc->mhc_free_token);
518e3c41896SSepherosa Ziehau mhc->mhc_flags |= VMBUS_MSGHC_CTXF_DESTROY;
519e3c41896SSepherosa Ziehau lwkt_reltoken(&mhc->mhc_free_token);
520e3c41896SSepherosa Ziehau wakeup(&mhc->mhc_free);
521e3c41896SSepherosa Ziehau
522e3c41896SSepherosa Ziehau mh = vmbus_msghc_get1(mhc, 0);
523e3c41896SSepherosa Ziehau if (mh == NULL)
524e3c41896SSepherosa Ziehau panic("can't get msghc");
525e3c41896SSepherosa Ziehau
526e3c41896SSepherosa Ziehau vmbus_msghc_free(mh);
527e3c41896SSepherosa Ziehau vmbus_msghc_ctx_free(mhc);
528e3c41896SSepherosa Ziehau }
529e3c41896SSepherosa Ziehau
530e3c41896SSepherosa Ziehau int
vmbus_msghc_exec_noresult(struct vmbus_msghc * mh)531e3c41896SSepherosa Ziehau vmbus_msghc_exec_noresult(struct vmbus_msghc *mh)
532e3c41896SSepherosa Ziehau {
533e3c41896SSepherosa Ziehau int i, wait_ticks = 1;
534e3c41896SSepherosa Ziehau
535e3c41896SSepherosa Ziehau /*
536e3c41896SSepherosa Ziehau * Save the input parameter so that we could restore the input
537e3c41896SSepherosa Ziehau * parameter if the Hypercall failed.
538e3c41896SSepherosa Ziehau *
539e3c41896SSepherosa Ziehau * XXX
540e3c41896SSepherosa Ziehau * Is this really necessary?! i.e. Will the Hypercall ever
541e3c41896SSepherosa Ziehau * overwrite the input parameter?
542e3c41896SSepherosa Ziehau */
543e3c41896SSepherosa Ziehau memcpy(&mh->mh_inprm_save, mh->mh_inprm, HYPERCALL_POSTMSGIN_SIZE);
544e3c41896SSepherosa Ziehau
545e3c41896SSepherosa Ziehau /*
546e3c41896SSepherosa Ziehau * In order to cope with transient failures, e.g. insufficient
547e3c41896SSepherosa Ziehau * resources on host side, we retry the post message Hypercall
548e3c41896SSepherosa Ziehau * several times. 20 retries seem sufficient.
549e3c41896SSepherosa Ziehau */
550e3c41896SSepherosa Ziehau #define HC_RETRY_MAX 20
551e3c41896SSepherosa Ziehau
552e3c41896SSepherosa Ziehau for (i = 0; i < HC_RETRY_MAX; ++i) {
553e3c41896SSepherosa Ziehau uint64_t status;
554e3c41896SSepherosa Ziehau
555e3c41896SSepherosa Ziehau status = hypercall_post_message(mh->mh_inprm_dma.hv_paddr);
556e3c41896SSepherosa Ziehau if (status == HYPERCALL_STATUS_SUCCESS)
557e3c41896SSepherosa Ziehau return 0;
558e3c41896SSepherosa Ziehau
559e3c41896SSepherosa Ziehau tsleep(&status, 0, "hcpmsg", wait_ticks);
560e3c41896SSepherosa Ziehau if (wait_ticks < hz)
561e3c41896SSepherosa Ziehau wait_ticks *= 2;
562e3c41896SSepherosa Ziehau
563e3c41896SSepherosa Ziehau /* Restore input parameter and try again */
564e3c41896SSepherosa Ziehau memcpy(mh->mh_inprm, &mh->mh_inprm_save,
565e3c41896SSepherosa Ziehau HYPERCALL_POSTMSGIN_SIZE);
566e3c41896SSepherosa Ziehau }
567e3c41896SSepherosa Ziehau
568e3c41896SSepherosa Ziehau #undef HC_RETRY_MAX
569e3c41896SSepherosa Ziehau
570e3c41896SSepherosa Ziehau return EIO;
571e3c41896SSepherosa Ziehau }
572e3c41896SSepherosa Ziehau
573e3c41896SSepherosa Ziehau int
vmbus_msghc_exec(struct vmbus_softc * sc,struct vmbus_msghc * mh)574e3c41896SSepherosa Ziehau vmbus_msghc_exec(struct vmbus_softc *sc, struct vmbus_msghc *mh)
575e3c41896SSepherosa Ziehau {
576e3c41896SSepherosa Ziehau struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
577e3c41896SSepherosa Ziehau int error;
578e3c41896SSepherosa Ziehau
579e3c41896SSepherosa Ziehau KASSERT(mh->mh_resp == NULL, ("hypercall msg has pending response"));
580e3c41896SSepherosa Ziehau
581e3c41896SSepherosa Ziehau lwkt_gettoken(&mhc->mhc_active_token);
582e3c41896SSepherosa Ziehau KASSERT(mhc->mhc_active == NULL, ("pending active msg hypercall"));
583e3c41896SSepherosa Ziehau mhc->mhc_active = mh;
584e3c41896SSepherosa Ziehau lwkt_reltoken(&mhc->mhc_active_token);
585e3c41896SSepherosa Ziehau
586e3c41896SSepherosa Ziehau error = vmbus_msghc_exec_noresult(mh);
587e3c41896SSepherosa Ziehau if (error) {
588e3c41896SSepherosa Ziehau lwkt_gettoken(&mhc->mhc_active_token);
589e3c41896SSepherosa Ziehau KASSERT(mhc->mhc_active == mh, ("msghc mismatch"));
590e3c41896SSepherosa Ziehau mhc->mhc_active = NULL;
591e3c41896SSepherosa Ziehau lwkt_reltoken(&mhc->mhc_active_token);
592e3c41896SSepherosa Ziehau }
593e3c41896SSepherosa Ziehau return error;
594e3c41896SSepherosa Ziehau }
595e3c41896SSepherosa Ziehau
596e3c41896SSepherosa Ziehau const struct vmbus_message *
vmbus_msghc_wait_result(struct vmbus_softc * sc,struct vmbus_msghc * mh)597e3c41896SSepherosa Ziehau vmbus_msghc_wait_result(struct vmbus_softc *sc, struct vmbus_msghc *mh)
598e3c41896SSepherosa Ziehau {
599e3c41896SSepherosa Ziehau struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
600e3c41896SSepherosa Ziehau
601e3c41896SSepherosa Ziehau lwkt_gettoken(&mhc->mhc_active_token);
602e3c41896SSepherosa Ziehau
603e3c41896SSepherosa Ziehau KASSERT(mhc->mhc_active == mh, ("msghc mismatch"));
604e3c41896SSepherosa Ziehau while (mh->mh_resp == NULL)
605e3c41896SSepherosa Ziehau tsleep(&mhc->mhc_active, 0, "wmsghc", 0);
606e3c41896SSepherosa Ziehau mhc->mhc_active = NULL;
607e3c41896SSepherosa Ziehau
608e3c41896SSepherosa Ziehau lwkt_reltoken(&mhc->mhc_active_token);
609e3c41896SSepherosa Ziehau
610e3c41896SSepherosa Ziehau return mh->mh_resp;
611e3c41896SSepherosa Ziehau }
612e3c41896SSepherosa Ziehau
613e3c41896SSepherosa Ziehau void
vmbus_msghc_wakeup(struct vmbus_softc * sc,const struct vmbus_message * msg)614e3c41896SSepherosa Ziehau vmbus_msghc_wakeup(struct vmbus_softc *sc, const struct vmbus_message *msg)
615e3c41896SSepherosa Ziehau {
616e3c41896SSepherosa Ziehau struct vmbus_msghc_ctx *mhc = sc->vmbus_msg_hc;
617e3c41896SSepherosa Ziehau struct vmbus_msghc *mh;
618e3c41896SSepherosa Ziehau
619e3c41896SSepherosa Ziehau lwkt_gettoken(&mhc->mhc_active_token);
620e3c41896SSepherosa Ziehau
621e3c41896SSepherosa Ziehau mh = mhc->mhc_active;
622e3c41896SSepherosa Ziehau KASSERT(mh != NULL, ("no pending msg hypercall"));
623e3c41896SSepherosa Ziehau memcpy(&mh->mh_resp0, msg, sizeof(mh->mh_resp0));
624e3c41896SSepherosa Ziehau mh->mh_resp = &mh->mh_resp0;
625e3c41896SSepherosa Ziehau
626e3c41896SSepherosa Ziehau lwkt_reltoken(&mhc->mhc_active_token);
627e3c41896SSepherosa Ziehau wakeup(&mhc->mhc_active);
628e3c41896SSepherosa Ziehau }
629e3c41896SSepherosa Ziehau
630e3c41896SSepherosa Ziehau static int
vmbus_dma_alloc(struct vmbus_softc * sc)631e3c41896SSepherosa Ziehau vmbus_dma_alloc(struct vmbus_softc *sc)
632e3c41896SSepherosa Ziehau {
633e3c41896SSepherosa Ziehau bus_dma_tag_t parent_dtag;
634e3c41896SSepherosa Ziehau uint8_t *evtflags;
635e3c41896SSepherosa Ziehau int cpu;
636e3c41896SSepherosa Ziehau
637e3c41896SSepherosa Ziehau parent_dtag = bus_get_dma_tag(sc->vmbus_dev);
638e3c41896SSepherosa Ziehau for (cpu = 0; cpu < ncpus; ++cpu) {
639e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, cpu);
640e3c41896SSepherosa Ziehau
641e3c41896SSepherosa Ziehau /*
642e3c41896SSepherosa Ziehau * Per-cpu messages and event flags.
643e3c41896SSepherosa Ziehau */
644e3c41896SSepherosa Ziehau psc->message = hyperv_dmamem_alloc(parent_dtag,
645e3c41896SSepherosa Ziehau PAGE_SIZE, 0, PAGE_SIZE, &psc->message_dma,
646e3c41896SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO);
647e3c41896SSepherosa Ziehau if (psc->message == NULL)
648e3c41896SSepherosa Ziehau return ENOMEM;
649e3c41896SSepherosa Ziehau
650e3c41896SSepherosa Ziehau psc->event_flags = hyperv_dmamem_alloc(parent_dtag,
651e3c41896SSepherosa Ziehau PAGE_SIZE, 0, PAGE_SIZE, &psc->event_flags_dma,
652e3c41896SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO);
653e3c41896SSepherosa Ziehau if (psc->event_flags == NULL)
654e3c41896SSepherosa Ziehau return ENOMEM;
655e3c41896SSepherosa Ziehau }
656e3c41896SSepherosa Ziehau
657e3c41896SSepherosa Ziehau evtflags = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
658e3c41896SSepherosa Ziehau PAGE_SIZE, &sc->vmbus_evtflags_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
659e3c41896SSepherosa Ziehau if (evtflags == NULL)
660e3c41896SSepherosa Ziehau return ENOMEM;
661e3c41896SSepherosa Ziehau sc->vmbus_rx_evtflags = (u_long *)evtflags;
662e3c41896SSepherosa Ziehau sc->vmbus_tx_evtflags = (u_long *)(evtflags + (PAGE_SIZE / 2));
663e3c41896SSepherosa Ziehau sc->vmbus_evtflags = evtflags;
664e3c41896SSepherosa Ziehau
665e3c41896SSepherosa Ziehau sc->vmbus_mnf1 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
666e3c41896SSepherosa Ziehau PAGE_SIZE, &sc->vmbus_mnf1_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
667e3c41896SSepherosa Ziehau if (sc->vmbus_mnf1 == NULL)
668e3c41896SSepherosa Ziehau return ENOMEM;
669e3c41896SSepherosa Ziehau
670e3c41896SSepherosa Ziehau sc->vmbus_mnf2 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0,
671e3c41896SSepherosa Ziehau PAGE_SIZE, &sc->vmbus_mnf2_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO);
672e3c41896SSepherosa Ziehau if (sc->vmbus_mnf2 == NULL)
673e3c41896SSepherosa Ziehau return ENOMEM;
674e3c41896SSepherosa Ziehau
675e3c41896SSepherosa Ziehau return 0;
676e3c41896SSepherosa Ziehau }
677e3c41896SSepherosa Ziehau
678e3c41896SSepherosa Ziehau static void
vmbus_dma_free(struct vmbus_softc * sc)679e3c41896SSepherosa Ziehau vmbus_dma_free(struct vmbus_softc *sc)
680e3c41896SSepherosa Ziehau {
681e3c41896SSepherosa Ziehau int cpu;
682e3c41896SSepherosa Ziehau
683e3c41896SSepherosa Ziehau if (sc->vmbus_evtflags != NULL) {
684e3c41896SSepherosa Ziehau hyperv_dmamem_free(&sc->vmbus_evtflags_dma, sc->vmbus_evtflags);
685e3c41896SSepherosa Ziehau sc->vmbus_evtflags = NULL;
686e3c41896SSepherosa Ziehau sc->vmbus_rx_evtflags = NULL;
687e3c41896SSepherosa Ziehau sc->vmbus_tx_evtflags = NULL;
688e3c41896SSepherosa Ziehau }
689e3c41896SSepherosa Ziehau if (sc->vmbus_mnf1 != NULL) {
690e3c41896SSepherosa Ziehau hyperv_dmamem_free(&sc->vmbus_mnf1_dma, sc->vmbus_mnf1);
691e3c41896SSepherosa Ziehau sc->vmbus_mnf1 = NULL;
692e3c41896SSepherosa Ziehau }
693e3c41896SSepherosa Ziehau if (sc->vmbus_mnf2 != NULL) {
694e3c41896SSepherosa Ziehau hyperv_dmamem_free(&sc->vmbus_mnf2_dma, sc->vmbus_mnf2);
695e3c41896SSepherosa Ziehau sc->vmbus_mnf2 = NULL;
696e3c41896SSepherosa Ziehau }
697e3c41896SSepherosa Ziehau
698e3c41896SSepherosa Ziehau for (cpu = 0; cpu < ncpus; ++cpu) {
699e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, cpu);
700e3c41896SSepherosa Ziehau
701e3c41896SSepherosa Ziehau if (psc->message != NULL) {
702e3c41896SSepherosa Ziehau hyperv_dmamem_free(&psc->message_dma, psc->message);
703e3c41896SSepherosa Ziehau psc->message = NULL;
704e3c41896SSepherosa Ziehau }
705e3c41896SSepherosa Ziehau if (psc->event_flags != NULL) {
706e3c41896SSepherosa Ziehau hyperv_dmamem_free(&psc->event_flags_dma,
707e3c41896SSepherosa Ziehau psc->event_flags);
708e3c41896SSepherosa Ziehau psc->event_flags = NULL;
709e3c41896SSepherosa Ziehau }
710e3c41896SSepherosa Ziehau }
711e3c41896SSepherosa Ziehau }
712e3c41896SSepherosa Ziehau
713e3c41896SSepherosa Ziehau static int
vmbus_intr_setup(struct vmbus_softc * sc)714e3c41896SSepherosa Ziehau vmbus_intr_setup(struct vmbus_softc *sc)
715e3c41896SSepherosa Ziehau {
716e3c41896SSepherosa Ziehau device_t dev = sc->vmbus_dev;
717ae7ab5b6SSepherosa Ziehau device_t bus = device_get_parent(device_get_parent(dev));
718e3c41896SSepherosa Ziehau int rid, cpu;
719e3c41896SSepherosa Ziehau
720e3c41896SSepherosa Ziehau rid = 0;
721e3c41896SSepherosa Ziehau for (cpu = 0; cpu < ncpus; ++cpu) {
722e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, cpu);
723e3c41896SSepherosa Ziehau uint64_t msi_addr;
724e3c41896SSepherosa Ziehau uint32_t msi_data;
725ae7ab5b6SSepherosa Ziehau int error;
726e3c41896SSepherosa Ziehau
727ae7ab5b6SSepherosa Ziehau error = PCIB_ALLOC_MSIX(bus, dev, &psc->intr_irq, cpu);
728e3c41896SSepherosa Ziehau if (error) {
729e3c41896SSepherosa Ziehau device_printf(dev, "alloc vector on cpu%d failed: %d\n",
730e3c41896SSepherosa Ziehau cpu, error);
731e3c41896SSepherosa Ziehau return ENXIO;
732e3c41896SSepherosa Ziehau }
733ae7ab5b6SSepherosa Ziehau psc->intr_rid = ++rid;
734e3c41896SSepherosa Ziehau
735ae7ab5b6SSepherosa Ziehau psc->intr_res = BUS_ALLOC_RESOURCE(bus, dev, SYS_RES_IRQ,
736ae7ab5b6SSepherosa Ziehau &psc->intr_rid, psc->intr_irq, psc->intr_irq, 1,
737ae7ab5b6SSepherosa Ziehau RF_ACTIVE, cpu);
738ae7ab5b6SSepherosa Ziehau if (psc->intr_res == NULL) {
739e3c41896SSepherosa Ziehau device_printf(dev, "alloc irq on cpu%d failed: %d\n",
740e3c41896SSepherosa Ziehau cpu, error);
741e3c41896SSepherosa Ziehau return ENXIO;
742e3c41896SSepherosa Ziehau }
743e3c41896SSepherosa Ziehau
744ae7ab5b6SSepherosa Ziehau error = PCIB_MAP_MSI(bus, dev, rman_get_start(psc->intr_res),
745e3c41896SSepherosa Ziehau &msi_addr, &msi_data, cpu);
746e3c41896SSepherosa Ziehau if (error) {
747e3c41896SSepherosa Ziehau device_printf(dev, "map irq on cpu%d failed: %d\n",
748e3c41896SSepherosa Ziehau cpu, error);
749e3c41896SSepherosa Ziehau return ENXIO;
750e3c41896SSepherosa Ziehau }
751e3c41896SSepherosa Ziehau psc->intr_vec = hyperv_msi2vector(msi_addr, msi_data);
752e3c41896SSepherosa Ziehau
753e3c41896SSepherosa Ziehau if (bootverbose) {
754e3c41896SSepherosa Ziehau device_printf(dev, "vector %d irq %d on cpu%d\n",
755ae7ab5b6SSepherosa Ziehau psc->intr_vec, psc->intr_irq, cpu);
756e3c41896SSepherosa Ziehau }
757e3c41896SSepherosa Ziehau
758e3c41896SSepherosa Ziehau ksnprintf(psc->intr_desc, sizeof(psc->intr_desc), "%s cpu%d",
759e3c41896SSepherosa Ziehau device_get_nameunit(dev), cpu);
760ae7ab5b6SSepherosa Ziehau error = bus_setup_intr_descr(dev, psc->intr_res, INTR_MPSAFE,
761ae7ab5b6SSepherosa Ziehau vmbus_intr, psc, &psc->intr_hand, NULL, psc->intr_desc);
762e3c41896SSepherosa Ziehau if (error) {
763e3c41896SSepherosa Ziehau device_printf(dev, "setup intr on cpu%d failed: %d\n",
764e3c41896SSepherosa Ziehau cpu, error);
765e3c41896SSepherosa Ziehau return ENXIO;
766e3c41896SSepherosa Ziehau }
767e3c41896SSepherosa Ziehau }
768e3c41896SSepherosa Ziehau return 0;
769e3c41896SSepherosa Ziehau }
770e3c41896SSepherosa Ziehau
771e3c41896SSepherosa Ziehau static void
vmbus_intr_teardown(struct vmbus_softc * sc)772e3c41896SSepherosa Ziehau vmbus_intr_teardown(struct vmbus_softc *sc)
773e3c41896SSepherosa Ziehau {
774e3c41896SSepherosa Ziehau device_t dev = sc->vmbus_dev;
775ae7ab5b6SSepherosa Ziehau device_t bus = device_get_parent(device_get_parent(dev));
776e3c41896SSepherosa Ziehau int cpu;
777e3c41896SSepherosa Ziehau
778e3c41896SSepherosa Ziehau for (cpu = 0; cpu < ncpus; ++cpu) {
779e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, cpu);
780e3c41896SSepherosa Ziehau
781e3c41896SSepherosa Ziehau if (psc->intr_hand != NULL) {
782e3c41896SSepherosa Ziehau bus_teardown_intr(dev, psc->intr_res, psc->intr_hand);
783e3c41896SSepherosa Ziehau psc->intr_hand = NULL;
784e3c41896SSepherosa Ziehau }
785e3c41896SSepherosa Ziehau
786e3c41896SSepherosa Ziehau if (psc->intr_res != NULL) {
787ae7ab5b6SSepherosa Ziehau BUS_RELEASE_RESOURCE(bus, dev, SYS_RES_IRQ,
788ae7ab5b6SSepherosa Ziehau psc->intr_rid, psc->intr_res);
789e3c41896SSepherosa Ziehau psc->intr_res = NULL;
790e3c41896SSepherosa Ziehau }
791e3c41896SSepherosa Ziehau
792e3c41896SSepherosa Ziehau if (psc->intr_rid != 0) {
793ae7ab5b6SSepherosa Ziehau PCIB_RELEASE_MSIX(bus, dev, psc->intr_irq, psc->cpuid);
794e3c41896SSepherosa Ziehau psc->intr_rid = 0;
795e3c41896SSepherosa Ziehau }
796e3c41896SSepherosa Ziehau }
797e3c41896SSepherosa Ziehau }
798e3c41896SSepherosa Ziehau
799e3c41896SSepherosa Ziehau static void
vmbus_synic_setup(void * xsc)800e3c41896SSepherosa Ziehau vmbus_synic_setup(void *xsc)
801e3c41896SSepherosa Ziehau {
802e3c41896SSepherosa Ziehau struct vmbus_softc *sc = xsc;
803e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, mycpuid);
804e3c41896SSepherosa Ziehau uint64_t val, orig;
805e3c41896SSepherosa Ziehau uint32_t sint;
806e3c41896SSepherosa Ziehau
807e3c41896SSepherosa Ziehau if (hyperv_features & CPUID_HV_MSR_VP_INDEX) {
808e3c41896SSepherosa Ziehau /*
809e3c41896SSepherosa Ziehau * Save virtual processor id.
810e3c41896SSepherosa Ziehau */
811e3c41896SSepherosa Ziehau psc->vcpuid = rdmsr(MSR_HV_VP_INDEX);
812e3c41896SSepherosa Ziehau } else {
813e3c41896SSepherosa Ziehau /*
814e3c41896SSepherosa Ziehau * XXX
815e3c41896SSepherosa Ziehau * Virtual processoor id is only used by a pretty broken
816e3c41896SSepherosa Ziehau * channel selection code from storvsc. It's nothing
817e3c41896SSepherosa Ziehau * critical even if CPUID_HV_MSR_VP_INDEX is not set; keep
818e3c41896SSepherosa Ziehau * moving on.
819e3c41896SSepherosa Ziehau */
820e3c41896SSepherosa Ziehau psc->vcpuid = mycpuid;
821e3c41896SSepherosa Ziehau }
822e3c41896SSepherosa Ziehau
823e3c41896SSepherosa Ziehau /*
824e3c41896SSepherosa Ziehau * Setup the SynIC message.
825e3c41896SSepherosa Ziehau */
826e3c41896SSepherosa Ziehau orig = rdmsr(MSR_HV_SIMP);
827e3c41896SSepherosa Ziehau val = MSR_HV_SIMP_ENABLE | (orig & MSR_HV_SIMP_RSVD_MASK) |
828e3c41896SSepherosa Ziehau ((psc->message_dma.hv_paddr >> PAGE_SHIFT) << MSR_HV_SIMP_PGSHIFT);
829e3c41896SSepherosa Ziehau wrmsr(MSR_HV_SIMP, val);
830e3c41896SSepherosa Ziehau
831e3c41896SSepherosa Ziehau /*
832e3c41896SSepherosa Ziehau * Setup the SynIC event flags.
833e3c41896SSepherosa Ziehau */
834e3c41896SSepherosa Ziehau orig = rdmsr(MSR_HV_SIEFP);
835e3c41896SSepherosa Ziehau val = MSR_HV_SIEFP_ENABLE | (orig & MSR_HV_SIEFP_RSVD_MASK) |
836e3c41896SSepherosa Ziehau ((psc->event_flags_dma.hv_paddr >> PAGE_SHIFT) <<
837e3c41896SSepherosa Ziehau MSR_HV_SIEFP_PGSHIFT);
838e3c41896SSepherosa Ziehau wrmsr(MSR_HV_SIEFP, val);
839e3c41896SSepherosa Ziehau
840e3c41896SSepherosa Ziehau
841e3c41896SSepherosa Ziehau /*
842e3c41896SSepherosa Ziehau * Configure and unmask SINT for message and event flags.
843e3c41896SSepherosa Ziehau */
844e3c41896SSepherosa Ziehau sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
845e3c41896SSepherosa Ziehau orig = rdmsr(sint);
846e3c41896SSepherosa Ziehau val = psc->intr_vec | /* MSR_HV_SINT_AUTOEOI | notyet */
847e3c41896SSepherosa Ziehau (orig & MSR_HV_SINT_RSVD_MASK);
848e3c41896SSepherosa Ziehau wrmsr(sint, val);
849e3c41896SSepherosa Ziehau
850e3c41896SSepherosa Ziehau /*
851e3c41896SSepherosa Ziehau * Configure and unmask SINT for timer.
852e3c41896SSepherosa Ziehau */
853e3c41896SSepherosa Ziehau sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
854e3c41896SSepherosa Ziehau orig = rdmsr(sint);
855e3c41896SSepherosa Ziehau val = XTIMER_OFFSET | /* MSR_HV_SINT_AUTOEOI | notyet */
856e3c41896SSepherosa Ziehau (orig & MSR_HV_SINT_RSVD_MASK);
857e3c41896SSepherosa Ziehau wrmsr(sint, val);
858e3c41896SSepherosa Ziehau
859e3c41896SSepherosa Ziehau /*
860e3c41896SSepherosa Ziehau * All done; enable SynIC.
861e3c41896SSepherosa Ziehau */
862e3c41896SSepherosa Ziehau orig = rdmsr(MSR_HV_SCONTROL);
863e3c41896SSepherosa Ziehau val = MSR_HV_SCTRL_ENABLE | (orig & MSR_HV_SCTRL_RSVD_MASK);
864e3c41896SSepherosa Ziehau wrmsr(MSR_HV_SCONTROL, val);
865e3c41896SSepherosa Ziehau }
866e3c41896SSepherosa Ziehau
867e3c41896SSepherosa Ziehau static void
vmbus_timer_stop(void * arg __unused)868e3c41896SSepherosa Ziehau vmbus_timer_stop(void *arg __unused)
869e3c41896SSepherosa Ziehau {
870e3c41896SSepherosa Ziehau for (;;) {
871e3c41896SSepherosa Ziehau uint64_t val;
872e3c41896SSepherosa Ziehau
873e3c41896SSepherosa Ziehau /* Stop counting, and this also implies disabling STIMER0 */
874e3c41896SSepherosa Ziehau wrmsr(MSR_HV_STIMER0_COUNT, 0);
875e3c41896SSepherosa Ziehau
876e3c41896SSepherosa Ziehau val = rdmsr(MSR_HV_STIMER0_CONFIG);
877e3c41896SSepherosa Ziehau if ((val & MSR_HV_STIMER_CFG_ENABLE) == 0)
878e3c41896SSepherosa Ziehau break;
879e3c41896SSepherosa Ziehau cpu_pause();
880e3c41896SSepherosa Ziehau }
881e3c41896SSepherosa Ziehau }
882e3c41896SSepherosa Ziehau
883e3c41896SSepherosa Ziehau static void
vmbus_timer_config(void * arg __unused)884e3c41896SSepherosa Ziehau vmbus_timer_config(void *arg __unused)
885e3c41896SSepherosa Ziehau {
886e3c41896SSepherosa Ziehau /*
887e3c41896SSepherosa Ziehau * Make sure that STIMER0 is really disabled before writing
888e3c41896SSepherosa Ziehau * to STIMER0_CONFIG.
889e3c41896SSepherosa Ziehau *
890e3c41896SSepherosa Ziehau * "Writing to the configuration register of a timer that
891e3c41896SSepherosa Ziehau * is already enabled may result in undefined behaviour."
892e3c41896SSepherosa Ziehau */
893e3c41896SSepherosa Ziehau vmbus_timer_stop(arg);
894e3c41896SSepherosa Ziehau wrmsr(MSR_HV_STIMER0_CONFIG,
895e3c41896SSepherosa Ziehau MSR_HV_STIMER_CFG_AUTOEN | MSR_HV_STIMER0_CFG_SINT);
896e3c41896SSepherosa Ziehau }
897e3c41896SSepherosa Ziehau
898e3c41896SSepherosa Ziehau static void
vmbus_timer_msgintr(struct vmbus_pcpu_data * psc)899e3c41896SSepherosa Ziehau vmbus_timer_msgintr(struct vmbus_pcpu_data *psc)
900e3c41896SSepherosa Ziehau {
901e3c41896SSepherosa Ziehau volatile struct vmbus_message *msg;
902e3c41896SSepherosa Ziehau
903e3c41896SSepherosa Ziehau msg = psc->message + VMBUS_SINT_TIMER;
9041f260e2cSSepherosa Ziehau if (msg->msg_type == HYPERV_MSGTYPE_TIMER_EXPIRED)
9051f260e2cSSepherosa Ziehau vmbus_msg_reset(msg);
906e3c41896SSepherosa Ziehau }
907e3c41896SSepherosa Ziehau
908e3c41896SSepherosa Ziehau static void
vmbus_timer_restart(void * xsc)909e3c41896SSepherosa Ziehau vmbus_timer_restart(void *xsc)
910e3c41896SSepherosa Ziehau {
911e3c41896SSepherosa Ziehau struct vmbus_softc *sc = xsc;
912e3c41896SSepherosa Ziehau struct vmbus_pcpu_data *psc = VMBUS_PCPU(sc, mycpuid);
913e3c41896SSepherosa Ziehau
914e3c41896SSepherosa Ziehau crit_enter();
915e3c41896SSepherosa Ziehau vmbus_timer_msgintr(psc);
916a4413ab2SSepherosa Ziehau vmbus_timer_oneshot(psc, hyperv_tc64() + 1);
917e3c41896SSepherosa Ziehau crit_exit();
918e3c41896SSepherosa Ziehau }
919e3c41896SSepherosa Ziehau
920e3c41896SSepherosa Ziehau static void
vmbus_synic_teardown(void * arg __unused)921e3c41896SSepherosa Ziehau vmbus_synic_teardown(void *arg __unused)
922e3c41896SSepherosa Ziehau {
923e3c41896SSepherosa Ziehau uint64_t orig;
924e3c41896SSepherosa Ziehau uint32_t sint;
925e3c41896SSepherosa Ziehau
926e3c41896SSepherosa Ziehau /*
927e3c41896SSepherosa Ziehau * Disable SynIC.
928e3c41896SSepherosa Ziehau */
929e3c41896SSepherosa Ziehau orig = rdmsr(MSR_HV_SCONTROL);
930e3c41896SSepherosa Ziehau wrmsr(MSR_HV_SCONTROL, (orig & MSR_HV_SCTRL_RSVD_MASK));
931e3c41896SSepherosa Ziehau
932e3c41896SSepherosa Ziehau /*
933e3c41896SSepherosa Ziehau * Mask message and event flags SINT.
934e3c41896SSepherosa Ziehau */
935e3c41896SSepherosa Ziehau sint = MSR_HV_SINT0 + VMBUS_SINT_MESSAGE;
936e3c41896SSepherosa Ziehau orig = rdmsr(sint);
937e3c41896SSepherosa Ziehau wrmsr(sint, orig | MSR_HV_SINT_MASKED);
938e3c41896SSepherosa Ziehau
939e3c41896SSepherosa Ziehau /*
940e3c41896SSepherosa Ziehau * Mask timer SINT.
941e3c41896SSepherosa Ziehau */
942e3c41896SSepherosa Ziehau sint = MSR_HV_SINT0 + VMBUS_SINT_TIMER;
943e3c41896SSepherosa Ziehau orig = rdmsr(sint);
944e3c41896SSepherosa Ziehau wrmsr(sint, orig | MSR_HV_SINT_MASKED);
945e3c41896SSepherosa Ziehau
946e3c41896SSepherosa Ziehau /*
947e3c41896SSepherosa Ziehau * Teardown SynIC message.
948e3c41896SSepherosa Ziehau */
949e3c41896SSepherosa Ziehau orig = rdmsr(MSR_HV_SIMP);
950e3c41896SSepherosa Ziehau wrmsr(MSR_HV_SIMP, (orig & MSR_HV_SIMP_RSVD_MASK));
951e3c41896SSepherosa Ziehau
952e3c41896SSepherosa Ziehau /*
953e3c41896SSepherosa Ziehau * Teardown SynIC event flags.
954e3c41896SSepherosa Ziehau */
955e3c41896SSepherosa Ziehau orig = rdmsr(MSR_HV_SIEFP);
956e3c41896SSepherosa Ziehau wrmsr(MSR_HV_SIEFP, (orig & MSR_HV_SIEFP_RSVD_MASK));
957e3c41896SSepherosa Ziehau }
958e3c41896SSepherosa Ziehau
959e3c41896SSepherosa Ziehau static int
vmbus_init_contact(struct vmbus_softc * sc,uint32_t version)960e3c41896SSepherosa Ziehau vmbus_init_contact(struct vmbus_softc *sc, uint32_t version)
961e3c41896SSepherosa Ziehau {
962e3c41896SSepherosa Ziehau struct vmbus_chanmsg_init_contact *req;
963e3c41896SSepherosa Ziehau const struct vmbus_chanmsg_version_resp *resp;
964e3c41896SSepherosa Ziehau const struct vmbus_message *msg;
965e3c41896SSepherosa Ziehau struct vmbus_msghc *mh;
966e3c41896SSepherosa Ziehau int error, supp = 0;
967e3c41896SSepherosa Ziehau
968e3c41896SSepherosa Ziehau mh = vmbus_msghc_get(sc, sizeof(*req));
969e3c41896SSepherosa Ziehau if (mh == NULL)
970e3c41896SSepherosa Ziehau return ENXIO;
971e3c41896SSepherosa Ziehau
972e3c41896SSepherosa Ziehau req = vmbus_msghc_dataptr(mh);
973e3c41896SSepherosa Ziehau req->chm_hdr.chm_type = VMBUS_CHANMSG_TYPE_INIT_CONTACT;
974e3c41896SSepherosa Ziehau req->chm_ver = version;
975e3c41896SSepherosa Ziehau req->chm_evtflags = sc->vmbus_evtflags_dma.hv_paddr;
976e3c41896SSepherosa Ziehau req->chm_mnf1 = sc->vmbus_mnf1_dma.hv_paddr;
977e3c41896SSepherosa Ziehau req->chm_mnf2 = sc->vmbus_mnf2_dma.hv_paddr;
978e3c41896SSepherosa Ziehau
979e3c41896SSepherosa Ziehau error = vmbus_msghc_exec(sc, mh);
980e3c41896SSepherosa Ziehau if (error) {
981e3c41896SSepherosa Ziehau vmbus_msghc_put(sc, mh);
982e3c41896SSepherosa Ziehau return error;
983e3c41896SSepherosa Ziehau }
984e3c41896SSepherosa Ziehau
985e3c41896SSepherosa Ziehau msg = vmbus_msghc_wait_result(sc, mh);
986e3c41896SSepherosa Ziehau resp = (const struct vmbus_chanmsg_version_resp *)msg->msg_data;
987e3c41896SSepherosa Ziehau supp = resp->chm_supp;
988e3c41896SSepherosa Ziehau
989e3c41896SSepherosa Ziehau vmbus_msghc_put(sc, mh);
990e3c41896SSepherosa Ziehau
991e3c41896SSepherosa Ziehau return (supp ? 0 : EOPNOTSUPP);
992e3c41896SSepherosa Ziehau }
993e3c41896SSepherosa Ziehau
994e3c41896SSepherosa Ziehau static int
vmbus_init(struct vmbus_softc * sc)995e3c41896SSepherosa Ziehau vmbus_init(struct vmbus_softc *sc)
996e3c41896SSepherosa Ziehau {
997e3c41896SSepherosa Ziehau int i;
998e3c41896SSepherosa Ziehau
999e3c41896SSepherosa Ziehau for (i = 0; i < nitems(vmbus_version); ++i) {
1000e3c41896SSepherosa Ziehau int error;
1001e3c41896SSepherosa Ziehau
1002e3c41896SSepherosa Ziehau error = vmbus_init_contact(sc, vmbus_version[i]);
1003e3c41896SSepherosa Ziehau if (!error) {
1004e3c41896SSepherosa Ziehau sc->vmbus_version = vmbus_version[i];
1005e3c41896SSepherosa Ziehau device_printf(sc->vmbus_dev, "version %u.%u\n",
1006e3c41896SSepherosa Ziehau (sc->vmbus_version >> 16),
1007e3c41896SSepherosa Ziehau (sc->vmbus_version & 0xffff));
1008e3c41896SSepherosa Ziehau return 0;
1009e3c41896SSepherosa Ziehau }
1010e3c41896SSepherosa Ziehau }
1011e3c41896SSepherosa Ziehau return ENXIO;
1012e3c41896SSepherosa Ziehau }
1013e3c41896SSepherosa Ziehau
1014e3c41896SSepherosa Ziehau static void
vmbus_chan_msgproc(struct vmbus_softc * sc,const struct vmbus_message * msg)1015e3c41896SSepherosa Ziehau vmbus_chan_msgproc(struct vmbus_softc *sc, const struct vmbus_message *msg)
1016e3c41896SSepherosa Ziehau {
1017e3c41896SSepherosa Ziehau const struct vmbus_chanmsg_hdr *hdr;
1018e3c41896SSepherosa Ziehau
1019e3c41896SSepherosa Ziehau hdr = (const struct vmbus_chanmsg_hdr *)msg->msg_data;
1020e3c41896SSepherosa Ziehau
1021e3c41896SSepherosa Ziehau /* TODO */
1022e3c41896SSepherosa Ziehau if (hdr->chm_type == VMBUS_CHANMSG_TYPE_VERSION_RESP)
1023e3c41896SSepherosa Ziehau vmbus_msghc_wakeup(sc, msg);
1024e3c41896SSepherosa Ziehau }
1025