Date: Fri, 28 Nov 2008 15:50:35 +0000 (UTC) From: Doug Rabson <dfr@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r185387 - user/dfr/xenhvm/6/sys/dev/xen/xenpci Message-ID: <200811281550.mASFoZtx022889@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dfr Date: Fri Nov 28 15:50:35 2008 New Revision: 185387 URL: http://svn.freebsd.org/changeset/base/185387 Log: Add a driver the the Xen HVM special platform device. Added: user/dfr/xenhvm/6/sys/dev/xen/xenpci/ user/dfr/xenhvm/6/sys/dev/xen/xenpci/evtchn.c user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h Added: user/dfr/xenhvm/6/sys/dev/xen/xenpci/evtchn.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/evtchn.c Fri Nov 28 15:50:35 2008 (r185387) @@ -0,0 +1,377 @@ +/****************************************************************************** + * evtchn.c + * + * A simplified event channel for para-drivers in unmodified linux + * + * Copyright (c) 2002-2005, K A Fraser + * Copyright (c) 2005, Intel Corporation <xiaofeng.ling@intel.com> + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: user/dfr/xenhvm/6/sys/xen/evtchn/evtchn.c 184235 2008-10-25 00:25:25Z kmacy $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/interrupt.h> +#include <sys/pcpu.h> + +#include <machine/cpufunc.h> +#include <machine/intr_machdep.h> + +#include <machine/xen/xen-os.h> +#include <machine/xen/xenvar.h> +#include <machine/xen/xen_intr.h> +#include <machine/xen/synch_bitops.h> +#include <machine/xen/evtchn.h> +#include <machine/xen/hypervisor.h> +#include <sys/smp.h> + +#include <dev/xen/xenpci/xenpcivar.h> + +static inline unsigned long __ffs(unsigned long word) +{ + __asm__("bsfq %1,%0" + :"=r" (word) + :"rm" (word)); + return word; +} + +#define is_valid_evtchn(x) ((x) != 0) +#define evtchn_from_irq(x) (irq_evtchn[irq].evtchn) + +static struct { + struct mtx lock; + driver_intr_t *handler; + void *arg; + int evtchn; + int close:1; /* close on unbind_from_irqhandler()? */ + int inuse:1; + int in_handler:1; +} irq_evtchn[256]; +static int evtchn_to_irq[NR_EVENT_CHANNELS] = { + [0 ... NR_EVENT_CHANNELS-1] = -1 }; + +static struct mtx irq_alloc_lock; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +static int alloc_xen_irq(void) +{ + static int warned; + int irq; + + mtx_lock(&irq_alloc_lock); + + for (irq = 1; irq < ARRAY_SIZE(irq_evtchn); irq++) { + if (irq_evtchn[irq].inuse) + continue; + irq_evtchn[irq].inuse = 1; + mtx_unlock(&irq_alloc_lock); + return irq; + } + + if (!warned) { + warned = 1; + printf("alloc_xen_irq: No available IRQ to bind to: " + "increase irq_evtchn[] size in evtchn.c.\n"); + } + + mtx_unlock(&irq_alloc_lock); + + return -ENOSPC; +} + +static void free_xen_irq(int irq) +{ + mtx_lock(&irq_alloc_lock); + irq_evtchn[irq].inuse = 0; + mtx_unlock(&irq_alloc_lock); +} + +int irq_to_evtchn_port(int irq) +{ + return irq_evtchn[irq].evtchn; +} + +void mask_evtchn(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + synch_set_bit(port, &s->evtchn_mask[0]); +} + +void unmask_evtchn(int port) +{ + evtchn_unmask_t op = { .port = port }; + HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &op); +} + +int bind_listening_port_to_irqhandler( + unsigned int remote_domain, + const char *devname, + driver_intr_t handler, + void *arg, + unsigned long irqflags, + void **cookiep) +{ + struct evtchn_alloc_unbound alloc_unbound; + int err, irq; + + irq = alloc_xen_irq(); + if (irq < 0) + return irq; + + mtx_lock(&irq_evtchn[irq].lock); + + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = remote_domain; + err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, + &alloc_unbound); + if (err) { + mtx_unlock(&irq_evtchn[irq].lock); + free_xen_irq(irq); + return err; + } + + irq_evtchn[irq].handler = handler; + irq_evtchn[irq].arg = arg; + irq_evtchn[irq].evtchn = alloc_unbound.port; + irq_evtchn[irq].close = 1; + + evtchn_to_irq[alloc_unbound.port] = irq; + + unmask_evtchn(alloc_unbound.port); + + mtx_unlock(&irq_evtchn[irq].lock); + + return irq; +} + +int bind_caller_port_to_irqhandler( + unsigned int caller_port, + const char *devname, + driver_intr_t handler, + void *arg, + unsigned long irqflags, + void **cookiep) +{ + int irq; + + irq = alloc_xen_irq(); + if (irq < 0) + return irq; + + mtx_lock(&irq_evtchn[irq].lock); + + irq_evtchn[irq].handler = handler; + irq_evtchn[irq].arg = arg; + irq_evtchn[irq].evtchn = caller_port; + irq_evtchn[irq].close = 0; + + evtchn_to_irq[caller_port] = irq; + + unmask_evtchn(caller_port); + + mtx_unlock(&irq_evtchn[irq].lock); + + return irq; +} + +void unbind_from_irqhandler(unsigned int irq, void *dev_id) +{ + int evtchn; + + mtx_lock(&irq_evtchn[irq].lock); + + evtchn = evtchn_from_irq(irq); + + if (is_valid_evtchn(evtchn)) { + evtchn_to_irq[evtchn] = -1; + mask_evtchn(evtchn); + if (irq_evtchn[irq].close) { + struct evtchn_close close = { .port = evtchn }; + if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) + panic("EVTCHNOP_close failed"); + } + } + + irq_evtchn[irq].handler = NULL; + irq_evtchn[irq].evtchn = 0; + + mtx_unlock(&irq_evtchn[irq].lock); + + while (irq_evtchn[irq].in_handler) + cpu_relax(); + + free_xen_irq(irq); +} + +void notify_remote_via_irq(int irq) +{ + int evtchn; + + evtchn = evtchn_from_irq(irq); + if (is_valid_evtchn(evtchn)) + notify_remote_via_evtchn(evtchn); +} + +static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh, + unsigned int idx) +{ + return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]); +} + +static void +evtchn_interrupt(void *arg) +{ + unsigned int l1i, l2i, port; + unsigned long masked_l1, masked_l2; + /* XXX: All events are bound to vcpu0 but irq may be redirected. */ + int cpu = 0; /*smp_processor_id();*/ + driver_intr_t *handler; + void *handler_arg; + int irq; + shared_info_t *s = HYPERVISOR_shared_info; + vcpu_info_t *v = &s->vcpu_info[cpu]; + unsigned long l1, l2; + + v->evtchn_upcall_pending = 0; + +#if 0 +#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ + /* Clear master flag /before/ clearing selector flag. */ + wmb(); +#endif +#endif + + l1 = atomic_readandclear_long(&v->evtchn_pending_sel); + + l1i = per_cpu(last_processed_l1i, cpu); + l2i = per_cpu(last_processed_l2i, cpu); + + while (l1 != 0) { + + l1i = (l1i + 1) % BITS_PER_LONG; + masked_l1 = l1 & ((~0UL) << l1i); + + if (masked_l1 == 0) { /* if we masked out all events, wrap around to the beginning */ + l1i = BITS_PER_LONG - 1; + l2i = BITS_PER_LONG - 1; + continue; + } + l1i = __ffs(masked_l1); + + do { + l2 = active_evtchns(cpu, s, l1i); + + l2i = (l2i + 1) % BITS_PER_LONG; + masked_l2 = l2 & ((~0UL) << l2i); + + if (masked_l2 == 0) { /* if we masked out all events, move on */ + l2i = BITS_PER_LONG - 1; + break; + } + l2i = __ffs(masked_l2); + + /* process port */ + port = (l1i * BITS_PER_LONG) + l2i; + synch_clear_bit(port, &s->evtchn_pending[0]); + + irq = evtchn_to_irq[port]; + if (irq < 0) + continue; + + mtx_lock(&irq_evtchn[irq].lock); + handler = irq_evtchn[irq].handler; + handler_arg = irq_evtchn[irq].arg; + if (unlikely(handler == NULL)) { + printk("Xen IRQ%d (port %d) has no handler!\n", + irq, port); + mtx_unlock(&irq_evtchn[irq].lock); + continue; + } + irq_evtchn[irq].in_handler = 1; + mtx_unlock(&irq_evtchn[irq].lock); + + //local_irq_enable(); + handler(handler_arg); + //local_irq_disable(); + + mtx_lock(&irq_evtchn[irq].lock); + irq_evtchn[irq].in_handler = 0; + mtx_unlock(&irq_evtchn[irq].lock); + + /* if this is the final port processed, we'll pick up here+1 next time */ + per_cpu(last_processed_l1i, cpu) = l1i; + per_cpu(last_processed_l2i, cpu) = l2i; + + } while (l2i != BITS_PER_LONG - 1); + + l2 = active_evtchns(cpu, s, l1i); + if (l2 == 0) /* we handled all ports, so we can clear the selector bit */ + l1 &= ~(1UL << l1i); + } +} + +void irq_resume(void) +{ + int evtchn, irq; + + for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) { + mask_evtchn(evtchn); + evtchn_to_irq[evtchn] = -1; + } + + for (irq = 0; irq < ARRAY_SIZE(irq_evtchn); irq++) + irq_evtchn[irq].evtchn = 0; +} + +int +xenpci_irq_init(device_t device, struct xenpci_softc *scp) +{ + int irq, cpu; + int error; + + mtx_init(&irq_alloc_lock, "xen-irq-lock", NULL, MTX_DEF); + + for (irq = 0; irq < ARRAY_SIZE(irq_evtchn); irq++) + mtx_init(&irq_evtchn[irq].lock, "irq-evtchn", NULL, MTX_DEF); + + for (cpu = 0; cpu < mp_ncpus; cpu++) { + per_cpu(last_processed_l1i, cpu) = BITS_PER_LONG - 1; + per_cpu(last_processed_l2i, cpu) = BITS_PER_LONG - 1; + } + + error = BUS_SETUP_INTR(device_get_parent(device), device, + scp->res_irq, INTR_TYPE_MISC, evtchn_interrupt, NULL, + &scp->intr_cookie); + if (error) + return (error); + + return (0); +} Added: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpci.c Fri Nov 28 15:50:35 2008 (r185387) @@ -0,0 +1,413 @@ +/* + * Copyright (c) [year] [your name] + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/time.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> + +#include <machine/stdarg.h> +#include <machine/xen/features.h> +#include <machine/xen/hypervisor.h> +#include <xen/interface/memory.h> +#include <xen/interface/hvm/params.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <dev/xen/xenpci/xenpcivar.h> + +/* + * These variables are used by the rest of the kernel to access the + * hypervisor. + */ +char *hypercall_stubs; +shared_info_t *HYPERVISOR_shared_info; + +/* + * The softc is automatically allocated by the parent bus using the + * size specified in the driver_t declaration below. + */ +#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_resume(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), + { 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, "XenSource, Inc. 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 (0); + } 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) +{ + struct xenpci_softc *scp = DEVICE2SOFTC(device); + + return (xenpci_resume(device, scp)); +} + +/* + * Common Attachment sub-functions + */ +static uint32_t +xenpci_cpuid_base(void) +{ + uint32_t base, regs[4]; + + for (base = 0x40000000; base < 0x40001000; base += 0x100) { + do_cpuid(base, regs); + if (!memcmp("XenVMMXenVMM", ®s[1], 12) + && (regs[0] - base) >= 2) + return (base); + } + return (0); +} + +static int +xenpci_init_hypercall_stubs(device_t device, 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"); + return (EINVAL); + } + + if (bootverbose) { + do_cpuid(base + 1, regs); + device_printf(device, "Xen version %d.%d.\n", + regs[0] >> 16, regs[0] & 0xffff); + } + + /* + * Find the hypercall pages. + */ + do_cpuid(base + 2, regs); + + hypercall_stubs = malloc(regs[0] * PAGE_SIZE, M_TEMP, M_WAITOK); + + for (i = 0; i < regs[0]; i++) { + wrmsr(regs[1], vtophys(hypercall_stubs + i * PAGE_SIZE) + i); + } + + return (0); +} + +static void +xenpci_resume_hypercall_stubs(device_t device, struct xenpci_softc * scp) +{ + uint32_t base, regs[4]; + int i; + + base = xenpci_cpuid_base(); + + do_cpuid(base + 2, regs); + for (i = 0; i < regs[0]; i++) { + wrmsr(regs[1], vtophys(hypercall_stubs + i * PAGE_SIZE) + i); + } +} + +static void +xenpci_set_callback(device_t device) +{ + int irq; + uint64_t callback; + struct xen_hvm_param xhp; + + irq = pci_get_irq(device); + if (irq < 16) { + callback = irq; + } else { + callback = (pci_get_intpin(device) - 1) & 3; + callback |= pci_get_slot(device) << 11; + callback |= 1ull << 56; + } + + xhp.domid = DOMID_SELF; + xhp.index = HVM_PARAM_CALLBACK_IRQ; + xhp.value = callback; + if (HYPERVISOR_hvm_op(HVMOP_set_param, &xhp)) + panic("Can't set evtchn callback"); +} + +static int +xenpci_attach(device_t device, struct xenpci_softc * scp) +{ + struct xen_add_to_physmap xatp; + u_long shared_pa; + + 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_pa); + + xatp.domid = DOMID_SELF; + xatp.idx = 0; + xatp.space = XENMAPSPACE_shared_info; + xatp.gpfn = shared_pa >> PAGE_SHIFT; + if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) + panic("HYPERVISOR_memory_op failed"); + + HYPERVISOR_shared_info = pmap_mapdev(shared_pa, PAGE_SIZE); + + /* + * Hook the irq up to evtchn + */ + xenpci_irq_init(device, scp); + xenpci_set_callback(device); + + device_add_child(device, "xenbus", 0); + + return (bus_generic_attach(device)); + +errexit: + /* + * Undo anything we may have done. + */ + xenpci_detach(device, scp); + return (ENXIO); +} + +static int +xenpci_detach(device_t device, struct xenpci_softc *scp) +{ + device_t parent = device_get_parent(device); + + /* + * 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; + } + + /* + * Deallocate any system resources we may have + * allocated on behalf of this driver. + */ + return xenpci_deallocate_resources(device); +} + +static int +xenpci_resume(device_t device, struct xenpci_softc *scp) +{ + + xenpci_resume_hypercall_stubs(device, scp); +} + +static int +xenpci_allocate_resources(device_t device) +{ + int error; + struct xenpci_softc *scp = DEVICE2SOFTC(device); + + scp->res_irq = bus_alloc_resource_any(device, 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->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); + 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); +} + +static int +xenpci_alloc_space_int(struct xenpci_softc *scp, size_t sz, u_long *pa) +{ + + if (scp->phys_next + sz > rman_get_end(scp->res_memory)) { + return (ENOMEM); + } + + *pa = scp->phys_next; + scp->phys_next += sz; + + return (0); +} + +int +xenpci_alloc_space(size_t sz, u_long *pa) +{ + device_t device = devclass_get_device(xenpci_devclass, 0); + + if (device) { + return (xenpci_alloc_space_int(DEVICE2SOFTC(device), + sz, pa)); + } else { + return (ENOMEM); + } +} + +void +printk(const char *fmt, ...) +{ + __va_list ap; + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} Added: user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/dfr/xenhvm/6/sys/dev/xen/xenpci/xenpcivar.h Fri Nov 28 15:50:35 2008 (r185387) @@ -0,0 +1,43 @@ +/* + * Copyright (c) [year] [your name] + * 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. + */ + +/* + * One of these per allocated device. + */ +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; + + u_long phys_next; /* next page from mem range */ +}; + +extern int xenpci_irq_init(device_t device, struct xenpci_softc *scp); +extern int xenpci_alloc_space(size_t sz, u_long *pa);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811281550.mASFoZtx022889>