1*4d846d26SWarner Losh /*- SPDX-License-Identifier: BSD-2-Clause
26cf00ef8SSouradeep Chakrabarti * Copyright (c) 2009-2012,2016-2017, 2022 Microsoft Corp.
36cf00ef8SSouradeep Chakrabarti * Copyright (c) 2012 NetApp Inc.
46cf00ef8SSouradeep Chakrabarti * Copyright (c) 2012 Citrix Inc.
56cf00ef8SSouradeep Chakrabarti * All rights reserved.
66cf00ef8SSouradeep Chakrabarti *
76cf00ef8SSouradeep Chakrabarti * Redistribution and use in source and binary forms, with or without
86cf00ef8SSouradeep Chakrabarti * modification, are permitted provided that the following conditions
96cf00ef8SSouradeep Chakrabarti * are met:
106cf00ef8SSouradeep Chakrabarti * 1. Redistributions of source code must retain the above copyright
116cf00ef8SSouradeep Chakrabarti * notice unmodified, this list of conditions, and the following
126cf00ef8SSouradeep Chakrabarti * disclaimer.
136cf00ef8SSouradeep Chakrabarti * 2. Redistributions in binary form must reproduce the above copyright
146cf00ef8SSouradeep Chakrabarti * notice, this list of conditions and the following disclaimer in the
156cf00ef8SSouradeep Chakrabarti * documentation and/or other materials provided with the distribution.
166cf00ef8SSouradeep Chakrabarti *
176cf00ef8SSouradeep Chakrabarti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
186cf00ef8SSouradeep Chakrabarti * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
196cf00ef8SSouradeep Chakrabarti * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
206cf00ef8SSouradeep Chakrabarti * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
216cf00ef8SSouradeep Chakrabarti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
226cf00ef8SSouradeep Chakrabarti * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236cf00ef8SSouradeep Chakrabarti * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246cf00ef8SSouradeep Chakrabarti * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256cf00ef8SSouradeep Chakrabarti * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
266cf00ef8SSouradeep Chakrabarti * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276cf00ef8SSouradeep Chakrabarti */
286cf00ef8SSouradeep Chakrabarti
296cf00ef8SSouradeep Chakrabarti /*
306cf00ef8SSouradeep Chakrabarti * VM Bus Driver Implementation
316cf00ef8SSouradeep Chakrabarti */
326cf00ef8SSouradeep Chakrabarti
336cf00ef8SSouradeep Chakrabarti #include <sys/param.h>
346cf00ef8SSouradeep Chakrabarti #include <sys/bus.h>
356cf00ef8SSouradeep Chakrabarti #include <sys/kernel.h>
366cf00ef8SSouradeep Chakrabarti #include <sys/linker.h>
376cf00ef8SSouradeep Chakrabarti #include <sys/lock.h>
386cf00ef8SSouradeep Chakrabarti #include <sys/malloc.h>
396cf00ef8SSouradeep Chakrabarti #include <sys/module.h>
406cf00ef8SSouradeep Chakrabarti #include <sys/mutex.h>
416cf00ef8SSouradeep Chakrabarti #include <sys/sbuf.h>
426cf00ef8SSouradeep Chakrabarti #include <sys/smp.h>
436cf00ef8SSouradeep Chakrabarti #include <sys/sysctl.h>
446cf00ef8SSouradeep Chakrabarti #include <sys/systm.h>
456cf00ef8SSouradeep Chakrabarti #include <sys/taskqueue.h>
466cf00ef8SSouradeep Chakrabarti
476cf00ef8SSouradeep Chakrabarti #include <vm/vm.h>
486cf00ef8SSouradeep Chakrabarti #include <vm/vm_param.h>
496cf00ef8SSouradeep Chakrabarti #include <vm/pmap.h>
506cf00ef8SSouradeep Chakrabarti
516cf00ef8SSouradeep Chakrabarti #include <machine/bus.h>
526cf00ef8SSouradeep Chakrabarti #include <machine/metadata.h>
536cf00ef8SSouradeep Chakrabarti #include <machine/md_var.h>
546cf00ef8SSouradeep Chakrabarti #include <machine/resource.h>
556cf00ef8SSouradeep Chakrabarti #include <contrib/dev/acpica/include/acpi.h>
566cf00ef8SSouradeep Chakrabarti #include <dev/acpica/acpivar.h>
576cf00ef8SSouradeep Chakrabarti
586cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/include/hyperv.h>
596cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/include/vmbus_xact.h>
606cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/vmbus/hyperv_var.h>
616cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/vmbus/vmbus_reg.h>
626cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/vmbus/vmbus_var.h>
636cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/vmbus/vmbus_chanvar.h>
646cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/vmbus/aarch64/hyperv_machdep.h>
656cf00ef8SSouradeep Chakrabarti #include <dev/hyperv/vmbus/aarch64/hyperv_reg.h>
66d16d0b6bSSouradeep Chakrabarti #include <dev/hyperv/vmbus/hyperv_common_reg.h>
676cf00ef8SSouradeep Chakrabarti #include "acpi_if.h"
686cf00ef8SSouradeep Chakrabarti #include "pcib_if.h"
696cf00ef8SSouradeep Chakrabarti #include "vmbus_if.h"
706cf00ef8SSouradeep Chakrabarti
716cf00ef8SSouradeep Chakrabarti static int vmbus_handle_intr_new(void *);
726cf00ef8SSouradeep Chakrabarti
736cf00ef8SSouradeep Chakrabarti void vmbus_handle_timer_intr1(struct vmbus_message *msg_base,
746cf00ef8SSouradeep Chakrabarti struct trapframe *frame);
756cf00ef8SSouradeep Chakrabarti void vmbus_synic_setup1(void *xsc);
766cf00ef8SSouradeep Chakrabarti void vmbus_synic_teardown1(void);
776cf00ef8SSouradeep Chakrabarti int vmbus_setup_intr1(struct vmbus_softc *sc);
786cf00ef8SSouradeep Chakrabarti void vmbus_intr_teardown1(struct vmbus_softc *sc);
796cf00ef8SSouradeep Chakrabarti
806cf00ef8SSouradeep Chakrabarti void
vmbus_handle_timer_intr1(struct vmbus_message * msg_base,struct trapframe * frame)816cf00ef8SSouradeep Chakrabarti vmbus_handle_timer_intr1(struct vmbus_message *msg_base,
826cf00ef8SSouradeep Chakrabarti struct trapframe *frame)
836cf00ef8SSouradeep Chakrabarti {
846cf00ef8SSouradeep Chakrabarti // do nothing for arm64, as we are using generic timer
856cf00ef8SSouradeep Chakrabarti return;
866cf00ef8SSouradeep Chakrabarti }
876cf00ef8SSouradeep Chakrabarti
886cf00ef8SSouradeep Chakrabarti static int
vmbus_handle_intr_new(void * arg)896cf00ef8SSouradeep Chakrabarti vmbus_handle_intr_new(void *arg)
906cf00ef8SSouradeep Chakrabarti {
916cf00ef8SSouradeep Chakrabarti vmbus_handle_intr(NULL);
926cf00ef8SSouradeep Chakrabarti return (FILTER_HANDLED);
936cf00ef8SSouradeep Chakrabarti }
946cf00ef8SSouradeep Chakrabarti
956cf00ef8SSouradeep Chakrabarti void
vmbus_synic_setup1(void * xsc)966cf00ef8SSouradeep Chakrabarti vmbus_synic_setup1(void *xsc)
976cf00ef8SSouradeep Chakrabarti {
986cf00ef8SSouradeep Chakrabarti return;
996cf00ef8SSouradeep Chakrabarti }
1006cf00ef8SSouradeep Chakrabarti
1016cf00ef8SSouradeep Chakrabarti void
vmbus_synic_teardown1(void)1026cf00ef8SSouradeep Chakrabarti vmbus_synic_teardown1(void)
1036cf00ef8SSouradeep Chakrabarti {
1046cf00ef8SSouradeep Chakrabarti return;
1056cf00ef8SSouradeep Chakrabarti }
1066cf00ef8SSouradeep Chakrabarti
1076cf00ef8SSouradeep Chakrabarti int
vmbus_setup_intr1(struct vmbus_softc * sc)1086cf00ef8SSouradeep Chakrabarti vmbus_setup_intr1(struct vmbus_softc *sc)
1096cf00ef8SSouradeep Chakrabarti {
1106cf00ef8SSouradeep Chakrabarti int err;
1116cf00ef8SSouradeep Chakrabarti struct intr_map_data_acpi *irq_data;
1120c38e1c3SSouradeep Chakrabarti device_t dev;
1136cf00ef8SSouradeep Chakrabarti
1140c38e1c3SSouradeep Chakrabarti dev = devclass_get_device(devclass_find("vmbus_res"), 0);
1150c38e1c3SSouradeep Chakrabarti sc->ires = bus_alloc_resource_any(dev,
1166cf00ef8SSouradeep Chakrabarti SYS_RES_IRQ, &sc->vector, RF_ACTIVE | RF_SHAREABLE);
1176cf00ef8SSouradeep Chakrabarti if (sc->ires == NULL) {
1186cf00ef8SSouradeep Chakrabarti device_printf(sc->vmbus_dev, "bus_alloc_resouce_any failed\n");
1196cf00ef8SSouradeep Chakrabarti return (ENXIO);
1206cf00ef8SSouradeep Chakrabarti } else {
1216cf00ef8SSouradeep Chakrabarti device_printf(sc->vmbus_dev, "irq 0x%lx, vector %d end 0x%lx\n",
1226cf00ef8SSouradeep Chakrabarti (uint64_t)rman_get_start(sc->ires), sc->vector,
1236cf00ef8SSouradeep Chakrabarti (uint64_t)rman_get_end(sc->ires));
1246cf00ef8SSouradeep Chakrabarti }
12560286182SSouradeep Chakrabarti err = bus_setup_intr(sc->vmbus_dev, sc->ires, INTR_TYPE_MISC | INTR_MPSAFE,
1266cf00ef8SSouradeep Chakrabarti vmbus_handle_intr_new, NULL, sc, &sc->icookie);
1276cf00ef8SSouradeep Chakrabarti if (err) {
1286cf00ef8SSouradeep Chakrabarti device_printf(sc->vmbus_dev, "failed to setup IRQ %d\n", err);
1296cf00ef8SSouradeep Chakrabarti return (err);
1306cf00ef8SSouradeep Chakrabarti }
1316cf00ef8SSouradeep Chakrabarti irq_data = (struct intr_map_data_acpi *)rman_get_virtual(sc->ires);
1326cf00ef8SSouradeep Chakrabarti device_printf(sc->vmbus_dev, "the irq %u\n", irq_data->irq);
1336cf00ef8SSouradeep Chakrabarti sc->vmbus_idtvec = irq_data->irq;
1346cf00ef8SSouradeep Chakrabarti return 0;
1356cf00ef8SSouradeep Chakrabarti }
1366cf00ef8SSouradeep Chakrabarti
1376cf00ef8SSouradeep Chakrabarti void
vmbus_intr_teardown1(struct vmbus_softc * sc)1386cf00ef8SSouradeep Chakrabarti vmbus_intr_teardown1(struct vmbus_softc *sc)
1396cf00ef8SSouradeep Chakrabarti {
1406cf00ef8SSouradeep Chakrabarti int cpu;
1416cf00ef8SSouradeep Chakrabarti
1426cf00ef8SSouradeep Chakrabarti sc->vmbus_idtvec = -1;
1436cf00ef8SSouradeep Chakrabarti bus_teardown_intr(sc->vmbus_dev, sc->ires, sc->icookie);
1446cf00ef8SSouradeep Chakrabarti
1456cf00ef8SSouradeep Chakrabarti CPU_FOREACH(cpu) {
1466cf00ef8SSouradeep Chakrabarti if (VMBUS_PCPU_GET(sc, event_tq, cpu) != NULL) {
1476cf00ef8SSouradeep Chakrabarti taskqueue_free(VMBUS_PCPU_GET(sc, event_tq, cpu));
1486cf00ef8SSouradeep Chakrabarti VMBUS_PCPU_GET(sc, event_tq, cpu) = NULL;
1496cf00ef8SSouradeep Chakrabarti }
1506cf00ef8SSouradeep Chakrabarti if (VMBUS_PCPU_GET(sc, message_tq, cpu) != NULL) {
1516cf00ef8SSouradeep Chakrabarti taskqueue_drain(VMBUS_PCPU_GET(sc, message_tq, cpu),
1526cf00ef8SSouradeep Chakrabarti VMBUS_PCPU_PTR(sc, message_task, cpu));
1536cf00ef8SSouradeep Chakrabarti taskqueue_free(VMBUS_PCPU_GET(sc, message_tq, cpu));
1546cf00ef8SSouradeep Chakrabarti VMBUS_PCPU_GET(sc, message_tq, cpu) = NULL;
1556cf00ef8SSouradeep Chakrabarti }
1566cf00ef8SSouradeep Chakrabarti }
1576cf00ef8SSouradeep Chakrabarti }
158