Index: sys/conf/files.arm64 =================================================================== --- sys/conf/files.arm64 +++ sys/conf/files.arm64 @@ -569,3 +569,6 @@ compile-with "${OBJCOPY} --input-target binary --output-target elf64-littleaarch64 --binary-architecture aarch64 cloudabi64_vdso.o ${.TARGET}" \ no-implicit-rule \ clean "cloudabi64_vdso_blob.o" + +# Xen +dev/xen/devicetree/xen-dt.c optional xenhvm fdt Index: sys/dev/xen/devicetree/xen-dt.c =================================================================== --- /dev/null +++ sys/dev/xen/devicetree/xen-dt.c @@ -0,0 +1,196 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2014 Julien Grall + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + + +DPCPU_DEFINE(struct vcpu_info, vcpu_local_info); +DPCPU_DEFINE(struct vcpu_info *, vcpu_info); + +void xen_early_init(void) +{ + /* + * The device tree contains the node /hypervisor with the compatible + * string "xen,xen" when the OS will run on top of Xen. + */ + if (ofw_bus_node_is_compatible(OF_finddevice("/hypervisor"), "xen,xen") == 0) + return; + + xen_domain_type = XEN_HVM_DOMAIN; + vm_guest = VM_GUEST_XEN; + setup_xen_features(); +} + +static void xen_init_shared_info(const void *arg __unused) +{ + int rc; + struct xen_add_to_physmap xatp; + vm_page_t shared_info; + vm_paddr_t shared_paddr; + + if (!xen_hvm_domain()) + return; + + shared_info = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_ZERO); + KASSERT(shared_info != NULL, ("Unable to allocate shared page\n")); + shared_paddr = VM_PAGE_TO_PHYS(shared_info); + HYPERVISOR_shared_info = pmap_mapdev_attr(shared_paddr, PAGE_SIZE, + VM_MEMATTR_XEN); + + xatp.domid = DOMID_SELF; + xatp.idx = 0; + xatp.space = XENMAPSPACE_shared_info; + xatp.gpfn = shared_paddr >> PAGE_SHIFT; + rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); + KASSERT(rc == 0, ("Unable to map shared info\n")); +} + +C_SYSINIT(xen_init_shared_info, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_init_shared_info, NULL); + + + +struct xen_softc +{ + struct resource *xen_res[2]; + void *intr_cookie; +}; + +#define XEN_RESOURCE_IRQ_EVTCHN 0 +#define XEN_RESOURCE_MEMORY_GNTTAB 1 + +static struct resource_spec xen_spec[] = { + /* RF_SHAREABLE ??? */ + { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Event channel IRQ */ + { SYS_RES_MEMORY, 0, 0}, /* Grant-table */ + { -1, 0, 0 }, +}; + +struct xen_softc *xen_sc = NULL; + +static int +xen_probe(device_t dev) +{ + if (!ofw_bus_is_compatible(dev, "xen,xen")) + return (ENXIO); + + device_set_desc(dev, "Xen ARM device-tree"); + + return (BUS_PROBE_DEFAULT); +} + +static int +xen_intr_filter(void *trap_frame) +{ + xen_intr_handle_upcall(trap_frame); + return (FILTER_HANDLED); +} + +static int +xen_attach(device_t dev) +{ + struct xen_softc *sc; + struct vcpu_register_vcpu_info info; + struct vcpu_info *vcpu_info; + int rc, cpu; + + if (xen_sc != NULL) + return (ENXIO); + + sc = device_get_softc(dev); + + /* TODO: Move to a proper function */ + vcpu_info = DPCPU_PTR(vcpu_local_info); + cpu = PCPU_GET(cpuid); + info.mfn = vtophys(vcpu_info) >> PAGE_SHIFT; + info.offset = vtophys(vcpu_info) - trunc_page(vtophys(vcpu_info)); + + rc = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); + KASSERT(rc == 0, ("Unable to register cpu %u\n", cpu)); + DPCPU_SET(vcpu_info, vcpu_info); + + if (bus_alloc_resources(dev, xen_spec, sc->xen_res)) { + device_printf(dev, "could not allocate resources\n"); + return (ENXIO); + } + + xen_sc = sc; + + /* Setup and enable the event channel interrupt */ + if (bus_setup_intr(dev, sc->xen_res[XEN_RESOURCE_IRQ_EVTCHN], + INTR_TYPE_MISC|INTR_MPSAFE, + xen_intr_filter, NULL, sc, &sc->intr_cookie)) + { + bus_release_resources(dev, xen_spec, sc->xen_res); + device_printf(dev, "could not setup event channel interrupt\n"); + return (ENXIO); + } + + return (0); +} + +static device_method_t xen_methods[] = { + DEVMETHOD(device_probe, xen_probe), + DEVMETHOD(device_attach, xen_attach), + { 0, 0 } +}; + +static driver_t xen_driver = { + "xen-dt", + xen_methods, + sizeof(struct xen_softc), +}; + +static devclass_t xen_devclass; + +DRIVER_MODULE(xen, simplebus, xen_driver, xen_devclass, 0, 0); +DRIVER_MODULE(xen, ofwbus, xen_driver, xen_devclass, 0, 0);