Date: Mon, 5 Jan 2009 10:43:49 +0000 (UTC) From: Doug Rabson <dfr@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r186767 - user/dfr/xenhvm/6/sys/dev/xen/xenpci Message-ID: <200901051043.n05Ahnij093789@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dfr Date: Mon Jan 5 10:43:48 2009 New Revision: 186767 URL: http://svn.freebsd.org/changeset/base/186767 Log: Tidy this up a lot and improve the comments somewhat. Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c ============================================================================== --- user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c Mon Jan 5 10:41:54 2009 (r186766) +++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c Mon Jan 5 10:43:48 2009 (r186767) @@ -1,5 +1,5 @@ /* - * Copyright (c) [year] [your name] + * Copyright (c) 2008 Citrix Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,101 +68,12 @@ shared_info_t *HYPERVISOR_shared_info; static vm_paddr_t shared_info_pa; /* - * The softc is automatically allocated by the parent bus using the - * size specified in the driver_t declaration below. + * This is used to find our platform device instance. */ -#define DEVICE2SOFTC(dev) ((struct xenpci_softc *) device_get_softc(dev)) - -/* Function prototypes (these should all be static). */ -static int xenpci_deallocate_resources(device_t device); -static int xenpci_allocate_resources(device_t device); -static int xenpci_attach(device_t device, struct xenpci_softc *scp); -static int xenpci_detach(device_t device, struct xenpci_softc *scp); - -static int xenpci_alloc_space_int(struct xenpci_softc *scp, size_t sz, - u_long *pa); - static devclass_t xenpci_devclass; -static int xenpci_pci_probe(device_t); -static int xenpci_pci_attach(device_t); -static int xenpci_pci_detach(device_t); -static int xenpci_pci_resume(device_t); - -static device_method_t xenpci_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, xenpci_pci_probe), - DEVMETHOD(device_attach, xenpci_pci_attach), - DEVMETHOD(device_detach, xenpci_pci_detach), - DEVMETHOD(device_resume, xenpci_pci_resume), - - /* Bus interface */ - DEVMETHOD(bus_add_child, bus_generic_add_child), - - { 0, 0 } -}; - -static driver_t xenpci_pci_driver = { - "xenpci", - xenpci_pci_methods, - sizeof(struct xenpci_softc), -}; - -DRIVER_MODULE(xenpci, pci, xenpci_pci_driver, xenpci_devclass, 0, 0); - -static struct _pcsid -{ - u_int32_t type; - const char *desc; -} pci_ids[] = { - { 0x00015853, "Xen Platform Device" }, - { 0x00000000, NULL } -}; - -static int -xenpci_pci_probe (device_t device) -{ - u_int32_t type = pci_get_devid(device); - struct _pcsid *ep = pci_ids; - - while (ep->type && ep->type != type) - ++ep; - if (ep->desc) { - device_set_desc(device, ep->desc); - return (bus_generic_probe(device)); - } else - return (ENXIO); -} - -static int -xenpci_pci_attach(device_t device) -{ - int error; - struct xenpci_softc *scp = DEVICE2SOFTC(device); - - error = xenpci_attach(device, scp); - if (error) - xenpci_pci_detach(device); - return (error); -} - -static int -xenpci_pci_detach (device_t device) -{ - struct xenpci_softc *scp = DEVICE2SOFTC(device); - - return (xenpci_detach(device, scp)); -} - -static int -xenpci_pci_resume(device_t device) -{ - - return (bus_generic_resume(device)); -} - /* - * Common Attachment sub-functions + * Return the CPUID base address for Xen functions. */ static uint32_t xenpci_cpuid_base(void) @@ -178,21 +89,24 @@ xenpci_cpuid_base(void) return (0); } +/* + * Allocate and fill in the hypcall page. + */ static int -xenpci_init_hypercall_stubs(device_t device, struct xenpci_softc * scp) +xenpci_init_hypercall_stubs(device_t dev, struct xenpci_softc * scp) { uint32_t base, regs[4]; int i; base = xenpci_cpuid_base(); if (!base) { - device_printf(device, "Xen platform device but not Xen VMM\n"); + device_printf(dev, "Xen platform device but not Xen VMM\n"); return (EINVAL); } if (bootverbose) { do_cpuid(base + 1, regs); - device_printf(device, "Xen version %d.%d.\n", + device_printf(dev, "Xen version %d.%d.\n", regs[0] >> 16, regs[0] & 0xffff); } @@ -210,8 +124,11 @@ xenpci_init_hypercall_stubs(device_t dev return (0); } +/* + * After a resume, re-initialise the hypercall page. + */ static void -xenpci_resume_hypercall_stubs(device_t device, struct xenpci_softc * scp) +xenpci_resume_hypercall_stubs(device_t dev, struct xenpci_softc * scp) { uint32_t base, regs[4]; int i; @@ -224,19 +141,22 @@ xenpci_resume_hypercall_stubs(device_t d } } +/* + * Tell the hypervisor how to contact us for event channel callbacks. + */ static void -xenpci_set_callback(device_t device) +xenpci_set_callback(device_t dev) { int irq; uint64_t callback; struct xen_hvm_param xhp; - irq = pci_get_irq(device); + irq = pci_get_irq(dev); if (irq < 16) { callback = irq; } else { - callback = (pci_get_intpin(device) - 1) & 3; - callback |= pci_get_slot(device) << 11; + callback = (pci_get_intpin(dev) - 1) & 3; + callback |= pci_get_slot(dev) << 11; callback |= 1ull << 56; } @@ -247,135 +167,62 @@ xenpci_set_callback(device_t device) panic("Can't set evtchn callback"); } -static int -xenpci_attach(device_t device, struct xenpci_softc * scp) -{ - struct xen_add_to_physmap xatp; - vm_offset_t shared_va; - - if (xenpci_allocate_resources(device)) - goto errexit; - - scp->phys_next = rman_get_start(scp->res_memory); - - if (xenpci_init_hypercall_stubs(device, scp)) - goto errexit; - - setup_xen_features(); - - xenpci_alloc_space_int(scp, PAGE_SIZE, &shared_info_pa); - - xatp.domid = DOMID_SELF; - xatp.idx = 0; - xatp.space = XENMAPSPACE_shared_info; - xatp.gpfn = shared_info_pa >> PAGE_SHIFT; - if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) - panic("HYPERVISOR_memory_op failed"); - - shared_va = kmem_alloc_nofault(kernel_map, PAGE_SIZE); - pmap_kenter(shared_va, shared_info_pa); - HYPERVISOR_shared_info = (void *) shared_va; - - /* - * Hook the irq up to evtchn - */ - xenpci_irq_init(device, scp); - xenpci_set_callback(device); - - return (bus_generic_attach(device)); - -errexit: - /* - * Undo anything we may have done. - */ - xenpci_detach(device, scp); - return (ENXIO); -} +/* + * Deallocate anything allocated by xenpci_allocate_resources. + */ static int -xenpci_detach(device_t device, struct xenpci_softc *scp) +xenpci_deallocate_resources(device_t dev) { - device_t parent = device_get_parent(device); + struct xenpci_softc *scp = device_get_softc(dev); - /* - * Take our interrupt handler out of the list of handlers - * that can handle this irq. - */ - if (scp->intr_cookie != NULL) { - if (BUS_TEARDOWN_INTR(parent, device, - scp->res_irq, scp->intr_cookie) != 0) - printf("intr teardown failed.. continuing\n"); - scp->intr_cookie = NULL; + if (scp->res_irq != 0) { + bus_deactivate_resource(dev, SYS_RES_IRQ, + scp->rid_irq, scp->res_irq); + bus_release_resource(dev, SYS_RES_IRQ, + scp->rid_irq, scp->res_irq); + scp->res_irq = 0; + } + if (scp->res_memory != 0) { + bus_deactivate_resource(dev, SYS_RES_MEMORY, + scp->rid_memory, scp->res_memory); + bus_release_resource(dev, SYS_RES_MEMORY, + scp->rid_memory, scp->res_memory); + scp->res_memory = 0; } - /* - * Deallocate any system resources we may have - * allocated on behalf of this driver. - */ - return xenpci_deallocate_resources(device); + return (0); } +/* + * Allocate irq and memory resources. + */ static int -xenpci_allocate_resources(device_t device) +xenpci_allocate_resources(device_t dev) { - int error; - struct xenpci_softc *scp = DEVICE2SOFTC(device); + struct xenpci_softc *scp = device_get_softc(dev); - scp->res_irq = bus_alloc_resource_any(device, SYS_RES_IRQ, + scp->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &scp->rid_irq, RF_SHAREABLE|RF_ACTIVE); if (scp->res_irq == NULL) goto errexit; - scp->rid_ioport = PCIR_BAR(0); - scp->res_ioport = bus_alloc_resource_any(device, SYS_RES_IOPORT, - &scp->rid_ioport, RF_ACTIVE); - if (scp->res_ioport == NULL) - goto errexit; - scp->rid_memory = PCIR_BAR(1); - scp->res_memory = bus_alloc_resource_any(device, SYS_RES_MEMORY, + scp->res_memory = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &scp->rid_memory, RF_ACTIVE); if (scp->res_memory == NULL) goto errexit; return (0); errexit: - error = ENXIO; /* Cleanup anything we may have assigned. */ - xenpci_deallocate_resources(device); + xenpci_deallocate_resources(dev); return (ENXIO); /* For want of a better idea. */ } -static int -xenpci_deallocate_resources(device_t device) -{ - struct xenpci_softc *scp = DEVICE2SOFTC(device); - - if (scp->res_irq != 0) { - bus_deactivate_resource(device, SYS_RES_IRQ, - scp->rid_irq, scp->res_irq); - bus_release_resource(device, SYS_RES_IRQ, - scp->rid_irq, scp->res_irq); - scp->res_irq = 0; - } - if (scp->res_ioport != 0) { - bus_deactivate_resource(device, SYS_RES_IOPORT, - scp->rid_ioport, scp->res_ioport); - bus_release_resource(device, SYS_RES_IOPORT, - scp->rid_ioport, scp->res_ioport); - scp->res_ioport = 0; - } - if (scp->res_memory != 0) { - bus_deactivate_resource(device, SYS_RES_MEMORY, - scp->rid_memory, scp->res_memory); - bus_release_resource(device, SYS_RES_MEMORY, - scp->rid_memory, scp->res_memory); - scp->res_memory = 0; - } - - return (0); -} - +/* + * Allocate a physical address range from our mmio region. + */ static int xenpci_alloc_space_int(struct xenpci_softc *scp, size_t sz, vm_paddr_t *pa) @@ -391,27 +238,35 @@ xenpci_alloc_space_int(struct xenpci_sof return (0); } +/* + * Allocate a physical address range from our mmio region. + */ int xenpci_alloc_space(size_t sz, vm_paddr_t *pa) { - device_t device = devclass_get_device(xenpci_devclass, 0); + device_t dev = devclass_get_device(xenpci_devclass, 0); - if (device) { - return (xenpci_alloc_space_int(DEVICE2SOFTC(device), + if (dev) { + return (xenpci_alloc_space_int(device_get_softc(dev), sz, pa)); } else { return (ENOMEM); } } +/* + * Called very early in the resume sequence - reinitialise the various + * bits of Xen machinery including the hypercall page and the shared + * info page. + */ void xenpci_resume() { - device_t device = devclass_get_device(xenpci_devclass, 0); - struct xenpci_softc *scp = DEVICE2SOFTC(device); + device_t dev = devclass_get_device(xenpci_devclass, 0); + struct xenpci_softc *scp = device_get_softc(dev); struct xen_add_to_physmap xatp; - xenpci_resume_hypercall_stubs(device, scp); + xenpci_resume_hypercall_stubs(dev, scp); xatp.domid = DOMID_SELF; xatp.idx = 0; @@ -422,9 +277,123 @@ xenpci_resume() pmap_kenter((vm_offset_t) HYPERVISOR_shared_info, shared_info_pa); - xenpci_set_callback(device); + xenpci_set_callback(dev); gnttab_resume(); irq_resume(); } +/* + * Probe - just check device ID. + */ +static int +xenpci_probe(device_t dev) +{ + + if (pci_get_devid(dev) != 0x00015853) + return (ENXIO); + + device_set_desc(dev, "Xen Platform Device"); + return (bus_generic_probe(dev)); +} + +/* + * Attach - find resources and talk to Xen. + */ +static int +xenpci_attach(device_t dev) +{ + int error; + struct xenpci_softc *scp = device_get_softc(dev); + struct xen_add_to_physmap xatp; + vm_offset_t shared_va; + + error = xenpci_allocate_resources(dev); + if (error) + goto errexit; + + scp->phys_next = rman_get_start(scp->res_memory); + + error = xenpci_init_hypercall_stubs(dev, scp); + if (error) + goto errexit; + + setup_xen_features(); + + xenpci_alloc_space_int(scp, PAGE_SIZE, &shared_info_pa); + + xatp.domid = DOMID_SELF; + xatp.idx = 0; + xatp.space = XENMAPSPACE_shared_info; + xatp.gpfn = shared_info_pa >> PAGE_SHIFT; + if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) + panic("HYPERVISOR_memory_op failed"); + + shared_va = kmem_alloc_nofault(kernel_map, PAGE_SIZE); + pmap_kenter(shared_va, shared_info_pa); + HYPERVISOR_shared_info = (void *) shared_va; + + /* + * Hook the irq up to evtchn + */ + xenpci_irq_init(dev, scp); + xenpci_set_callback(dev); + + return (bus_generic_attach(dev)); + +errexit: + /* + * Undo anything we may have done. + */ + xenpci_deallocate_resources(dev); + return (error); +} + +/* + * Detach - reverse anything done by attach. + */ +static int +xenpci_detach(device_t dev) +{ + struct xenpci_softc *scp = device_get_softc(dev); + device_t parent = device_get_parent(dev); + + /* + * Take our interrupt handler out of the list of handlers + * that can handle this irq. + */ + if (scp->intr_cookie != NULL) { + if (BUS_TEARDOWN_INTR(parent, dev, + scp->res_irq, scp->intr_cookie) != 0) + printf("intr teardown failed.. continuing\n"); + scp->intr_cookie = NULL; + } + + /* + * Deallocate any system resources we may have + * allocated on behalf of this driver. + */ + return (xenpci_deallocate_resources(dev)); +} + +static device_method_t xenpci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, xenpci_probe), + DEVMETHOD(device_attach, xenpci_attach), + DEVMETHOD(device_detach, xenpci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_add_child, bus_generic_add_child), + + { 0, 0 } +}; + +static driver_t xenpci_driver = { + "xenpci", + xenpci_methods, + sizeof(struct xenpci_softc), +}; + +DRIVER_MODULE(xenpci, pci, xenpci_driver, xenpci_devclass, 0, 0); Modified: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h ============================================================================== --- user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h Mon Jan 5 10:41:54 2009 (r186766) +++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h Mon Jan 5 10:43:48 2009 (r186767) @@ -1,5 +1,5 @@ /* - * Copyright (c) [year] [your name] + * Copyright (c) 2008 Citrix Systems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,7 +31,6 @@ struct xenpci_softc { int rid_ioport; int rid_memory; int rid_irq; - struct resource* res_ioport; /* Resource for port range. */ struct resource* res_memory; /* Resource for mem range. */ struct resource* res_irq; /* Resource for irq range. */ void *intr_cookie;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901051043.n05Ahnij093789>