Changeset View
Standalone View
sys/dev/xen/devicetree/xen-dt.c
- This file was added.
/* | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2014 Julien Grall | |||||
* Copyright (c) 2021 Elliott Mitchell | |||||
andrew: If you've written a significant amount of this file you should add your copyright. | |||||
* | |||||
Done Inline Actions@julien_xen.org Can we drop All rights reserved.? We've been removing it from other files (with copyright holders permission) as it's no longer needed. andrew: @julien_xen.org Can we drop `All rights reserved.`? We've been removing it from other files… | |||||
Done Inline ActionsYes this can be dropped. julien_xen.org: Yes this can be dropped. | |||||
* 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 <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <sys/systm.h> | |||||
#include <sys/bus.h> | |||||
#include <sys/kernel.h> | |||||
#include <sys/pcpu.h> | |||||
#include <sys/rman.h> | |||||
#include <sys/module.h> | |||||
#include <vm/vm.h> | |||||
#include <vm/pmap.h> | |||||
#include <vm/vm_page.h> | |||||
#include <dev/ofw/openfirm.h> | |||||
#include <dev/ofw/ofw_bus.h> | |||||
#include <dev/ofw/ofw_bus_subr.h> | |||||
#include <dev/fdt/fdt_common.h> | |||||
#include <xen/xen-os.h> | |||||
#include <xen/xen_intr.h> | |||||
#include <xen/hypervisor.h> | |||||
#include <xen/interface/vcpu.h> | |||||
#include <xen/features.h> | |||||
DPCPU_DEFINE(struct vcpu_info, vcpu_local_info); | |||||
DPCPU_DEFINE(struct vcpu_info *, vcpu_info); | |||||
int | |||||
xen_dt_probe(void) | |||||
Not Done Inline ActionsMissing a newline after int. The function should also have a FDT specific name. andrew: Missing a newline after `int`. The function should also have a `FDT` specific name. | |||||
Done Inline ActionsI'll be looking through the source trying to figure out what you mean by "FDT specific name". My first guess is FDT files are supposed to include some sort of setting to tell OFW code to load them if device X is seen. Mainly searching for a "/hypervisor" which is compatible with "xen,xen" isn't the way it is supposed to be done (this is based on something originally written in 2014, so I wouldn't be surprised at yet more changes). ehem_freebsd_m5p.com: I'll be looking through the source trying to figure out what you mean by "`FDT` specific name". | |||||
{ | |||||
/* | |||||
* Short-circuit extra attempts at looking for Xen | |||||
*/ | |||||
if (xen_domain()) | |||||
return (1); | |||||
/* | |||||
* 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 (0); | |||||
xen_domain_type = XEN_HVM_DOMAIN; | |||||
vm_guest = VM_GUEST_XEN; | |||||
setup_xen_features(); | |||||
return (1); | |||||
} | |||||
Done Inline ActionsThere is actually a bug here. xen_handle_shared_info() can be called during SI_SUB_HYPERVISOR, but cannot be called during console init. Since xen_dt_probe() will be called during console init unless the system console is completely disabled, this doesn't work. ehem_freebsd_m5p.com: There is actually a bug here. xen_handle_shared_info() can be called during SI_SUB_HYPERVISOR… | |||||
/* in case of console being disabled, probe again as a fallback */ | |||||
C_SYSINIT(xen_probe_fdt, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, (sysinit_cfunc_t)xen_dt_probe, NULL); | |||||
Done Inline ActionsExtra newline after xen_softc andrew: Extra newline after `xen_softc` | |||||
struct xen_softc { | |||||
struct resource *xen_res[2]; | |||||
void *intr_cookie; | |||||
}; | |||||
#define XEN_RESOURCE_IRQ_EVTCHN 0 | |||||
#define XEN_RESOURCE_MEMORY_GNTTAB 1 | |||||
Done Inline ActionsWhat's this comment for? andrew: What's this comment for? | |||||
static struct resource_spec xen_spec[] = { | |||||
{ 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_status_okay(dev)) | |||||
return (ENXIO); | |||||
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_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 = atop(vtophys(vcpu_info)); | |||||
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)) { | |||||
Done Inline ActionsDoes this depend on 4k pages? andrew: Does this depend on 4k pages? | |||||
Done Inline ActionsI don't believe so. I haven't noticed such being hard-coded anywhere, but there could be a lurking gotcha. ehem_freebsd_m5p.com: I don't believe so. I haven't noticed such being hard-coded anywhere, but there could be a… | |||||
Done Inline ActionsActually, presently the ABI assumes 4KB pages ("frames"). There are plans to address this, but such isn't yet available in Xen. Due to this, the update I've got staged includes switches to using PAGE_*_4K. I'm marking this done as next update will include this change. ehem_freebsd_m5p.com: Actually, presently the ABI //assumes// 4KB pages ("frames"). There are plans to address this… | |||||
device_printf(dev, "could not allocate resources\n"); | |||||
return (ENXIO); | |||||
} | |||||
xen_sc = sc; | |||||
/* TODO: return address range to nexus, so xenpv could grab it */ | |||||
Done Inline ActionsThis looks like it's indented too far (although phabricator makes it hard to tell) andrew: This looks like it's indented too far (although phabricator makes it hard to tell) | |||||
/* 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_handle_upcall, 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); | |||||
} | |||||
Done Inline ActionsThis should be indented 1 tab followed by 4 spaces and move the { to the end of the if statement. andrew: This should be indented 1 tab followed by 4 spaces and move the `{` to the end of the `if`… | |||||
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); |
If you've written a significant amount of this file you should add your copyright.