diff options
Diffstat (limited to 'sys/dev/xen')
-rw-r--r-- | sys/dev/xen/balloon/balloon.c | 11 | ||||
-rw-r--r-- | sys/dev/xen/blkback/blkback.c | 52 | ||||
-rw-r--r-- | sys/dev/xen/blkfront/blkfront.c | 37 | ||||
-rw-r--r-- | sys/dev/xen/blkfront/block.h | 2 | ||||
-rw-r--r-- | sys/dev/xen/console/console.c | 18 | ||||
-rw-r--r-- | sys/dev/xen/console/xencons_ring.c | 18 | ||||
-rw-r--r-- | sys/dev/xen/control/control.c | 17 | ||||
-rw-r--r-- | sys/dev/xen/netback/netback.c | 34 | ||||
-rw-r--r-- | sys/dev/xen/netfront/netfront.c | 51 | ||||
-rw-r--r-- | sys/dev/xen/xenpci/evtchn.c | 467 | ||||
-rw-r--r-- | sys/dev/xen/xenpci/xenpci.c | 226 | ||||
-rw-r--r-- | sys/dev/xen/xenpci/xenpcivar.h | 5 |
12 files changed, 184 insertions, 754 deletions
diff --git a/sys/dev/xen/balloon/balloon.c b/sys/dev/xen/balloon/balloon.c index d4f94ab..9021abb 100644 --- a/sys/dev/xen/balloon/balloon.c +++ b/sys/dev/xen/balloon/balloon.c @@ -40,14 +40,15 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/sysctl.h> -#include <machine/xen/xen-os.h> -#include <machine/xen/xenvar.h> -#include <machine/xen/xenfunc.h> +#include <vm/vm.h> +#include <vm/vm_page.h> + +#include <xen/xen-os.h> #include <xen/hypervisor.h> +#include <xen/features.h> #include <xen/xenstore/xenstorevar.h> -#include <vm/vm.h> -#include <vm/vm_page.h> +#include <machine/xen/xenvar.h> static MALLOC_DEFINE(M_BALLOON, "Balloon", "Xen Balloon Driver"); diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index 4208702..33f6faf 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -70,14 +70,13 @@ __FBSDID("$FreeBSD$"); #include <geom/geom.h> #include <machine/_inttypes.h> -#include <machine/xen/xen-os.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> +#include <xen/xen-os.h> #include <xen/blkif.h> -#include <xen/evtchn.h> #include <xen/gnttab.h> #include <xen/xen_intr.h> @@ -682,7 +681,7 @@ struct xbb_softc { blkif_back_rings_t rings; /** IRQ mapping for the communication ring event channel. */ - int irq; + xen_intr_handle_t xen_intr_handle; /** * \brief Backend access mode flags (e.g. write, or read-only). @@ -1347,7 +1346,7 @@ xbb_send_response(struct xbb_softc *xbb, struct xbb_xen_req *req, int status) taskqueue_enqueue(xbb->io_taskqueue, &xbb->io_task); if (notify) - notify_remote_via_irq(xbb->irq); + xen_intr_signal(xbb->xen_intr_handle); } /** @@ -1616,8 +1615,8 @@ xbb_dispatch_io(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist) sg = NULL; /* Check that number of segments is sane. */ - if (unlikely(nseg == 0) - || unlikely(nseg > xbb->max_request_segments)) { + if (__predict_false(nseg == 0) + || __predict_false(nseg > xbb->max_request_segments)) { DPRINTF("Bad number of segments in request (%d)\n", nseg); reqlist->status = BLKIF_RSP_ERROR; @@ -1734,7 +1733,7 @@ xbb_dispatch_io(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist) for (seg_idx = 0, map = xbb->maps; seg_idx < reqlist->nr_segments; seg_idx++, map++){ - if (unlikely(map->status != 0)) { + if (__predict_false(map->status != 0)) { DPRINTF("invalid buffer -- could not remap " "it (%d)\n", map->status); DPRINTF("Mapping(%d): Host Addr 0x%lx, flags " @@ -2026,14 +2025,16 @@ xbb_run_queue(void *context, int pending) * \param arg Callback argument registerd during event channel * binding - the xbb_softc for this instance. */ -static void -xbb_intr(void *arg) +static int +xbb_filter(void *arg) { struct xbb_softc *xbb; - /* Defer to kernel thread. */ + /* Defer to taskqueue thread. */ xbb = (struct xbb_softc *)arg; taskqueue_enqueue(xbb->io_taskqueue, &xbb->io_task); + + return (FILTER_HANDLED); } SDT_PROVIDER_DEFINE(xbb); @@ -2081,7 +2082,7 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, if (operation == BIO_FLUSH) { nreq = STAILQ_FIRST(&reqlist->contig_req_list); bio = g_new_bio(); - if (unlikely(bio == NULL)) { + if (__predict_false(bio == NULL)) { DPRINTF("Unable to allocate bio for BIO_FLUSH\n"); error = ENOMEM; return (error); @@ -2143,7 +2144,7 @@ xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, } bio = bios[nbio++] = g_new_bio(); - if (unlikely(bio == NULL)) { + if (__predict_false(bio == NULL)) { error = ENOMEM; goto fail_free_bios; } @@ -2811,10 +2812,7 @@ xbb_disconnect(struct xbb_softc *xbb) if ((xbb->flags & XBBF_RING_CONNECTED) == 0) return (0); - if (xbb->irq != 0) { - unbind_from_irqhandler(xbb->irq); - xbb->irq = 0; - } + xen_intr_unbind(&xbb->xen_intr_handle); mtx_unlock(&xbb->lock); taskqueue_drain(xbb->io_taskqueue, &xbb->io_task); @@ -2966,13 +2964,14 @@ xbb_connect_ring(struct xbb_softc *xbb) xbb->flags |= XBBF_RING_CONNECTED; - error = - bind_interdomain_evtchn_to_irqhandler(xbb->otherend_id, - xbb->ring_config.evtchn, - device_get_nameunit(xbb->dev), - xbb_intr, /*arg*/xbb, - INTR_TYPE_BIO | INTR_MPSAFE, - &xbb->irq); + error = xen_intr_bind_remote_port(xbb->dev, + xbb->otherend_id, + xbb->ring_config.evtchn, + xbb_filter, + /*ithread_handler*/NULL, + /*arg*/xbb, + INTR_TYPE_BIO | INTR_MPSAFE, + &xbb->xen_intr_handle); if (error) { (void)xbb_disconnect(xbb); xenbus_dev_fatal(xbb->dev, error, "binding event channel"); @@ -3791,9 +3790,10 @@ xbb_attach(device_t dev) * Create a taskqueue for doing work that must occur from a * thread context. */ - xbb->io_taskqueue = taskqueue_create(device_get_nameunit(dev), M_NOWAIT, - taskqueue_thread_enqueue, - /*context*/&xbb->io_taskqueue); + xbb->io_taskqueue = taskqueue_create_fast(device_get_nameunit(dev), + M_NOWAIT, + taskqueue_thread_enqueue, + /*contxt*/&xbb->io_taskqueue); if (xbb->io_taskqueue == NULL) { xbb_attach_failed(xbb, error, "Unable to create taskqueue"); return (ENOMEM); diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c index 969c3d8..7d70f42 100644 --- a/sys/dev/xen/blkfront/blkfront.c +++ b/sys/dev/xen/blkfront/blkfront.c @@ -51,19 +51,17 @@ __FBSDID("$FreeBSD$"); #include <machine/vmparam.h> #include <sys/bus_dma.h> -#include <machine/_inttypes.h> -#include <machine/xen/xen-os.h> -#include <machine/xen/xenvar.h> -#include <machine/xen/xenfunc.h> - +#include <xen/xen-os.h> #include <xen/hypervisor.h> #include <xen/xen_intr.h> -#include <xen/evtchn.h> #include <xen/gnttab.h> #include <xen/interface/grant_table.h> #include <xen/interface/io/protocols.h> #include <xen/xenbus/xenbusvar.h> +#include <machine/_inttypes.h> +#include <machine/xen/xenvar.h> + #include <geom/geom_disk.h> #include <dev/xen/blkfront/block.h> @@ -139,7 +137,7 @@ xbd_flush_requests(struct xbd_softc *sc) RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->xbd_ring, notify); if (notify) - notify_remote_via_irq(sc->xbd_irq); + xen_intr_signal(sc->xen_intr_handle); } static void @@ -310,7 +308,7 @@ xbd_bio_command(struct xbd_softc *sc) struct xbd_command *cm; struct bio *bp; - if (unlikely(sc->xbd_state != XBD_STATE_CONNECTED)) + if (__predict_false(sc->xbd_state != XBD_STATE_CONNECTED)) return (NULL); bp = xbd_dequeue_bio(sc); @@ -437,7 +435,7 @@ xbd_bio_complete(struct xbd_softc *sc, struct xbd_command *cm) bp = cm->cm_bp; - if (unlikely(cm->cm_status != BLKIF_RSP_OKAY)) { + if (__predict_false(cm->cm_status != BLKIF_RSP_OKAY)) { disk_err(bp, "disk error" , -1, 0); printf(" status: %x\n", cm->cm_status); bp->bio_flags |= BIO_ERROR; @@ -470,7 +468,7 @@ xbd_int(void *xsc) mtx_lock(&sc->xbd_io_lock); - if (unlikely(sc->xbd_state == XBD_STATE_DISCONNECTED)) { + if (__predict_false(sc->xbd_state == XBD_STATE_DISCONNECTED)) { mtx_unlock(&sc->xbd_io_lock); return; } @@ -531,7 +529,7 @@ xbd_int(void *xsc) xbd_startio(sc); - if (unlikely(sc->xbd_state == XBD_STATE_SUSPENDED)) + if (__predict_false(sc->xbd_state == XBD_STATE_SUSPENDED)) wakeup(&sc->xbd_cm_q[XBD_Q_BUSY]); mtx_unlock(&sc->xbd_io_lock); @@ -782,13 +780,12 @@ xbd_alloc_ring(struct xbd_softc *sc) } } - error = bind_listening_port_to_irqhandler( - xenbus_get_otherend_id(sc->xbd_dev), - "xbd", (driver_intr_t *)xbd_int, sc, - INTR_TYPE_BIO | INTR_MPSAFE, &sc->xbd_irq); + error = xen_intr_alloc_and_bind_local_port(sc->xbd_dev, + xenbus_get_otherend_id(sc->xbd_dev), NULL, xbd_int, sc, + INTR_TYPE_BIO | INTR_MPSAFE, &sc->xen_intr_handle); if (error) { xenbus_dev_fatal(sc->xbd_dev, error, - "bind_evtchn_to_irqhandler failed"); + "xen_intr_alloc_and_bind_local_port failed"); return (error); } @@ -1042,10 +1039,8 @@ xbd_free(struct xbd_softc *sc) xbd_initq_cm(sc, XBD_Q_COMPLETE); } - if (sc->xbd_irq) { - unbind_from_irqhandler(sc->xbd_irq); - sc->xbd_irq = 0; - } + xen_intr_unbind(&sc->xen_intr_handle); + } /*--------------------------- State Change Handlers --------------------------*/ @@ -1277,7 +1272,7 @@ xbd_initialize(struct xbd_softc *sc) } error = xs_printf(XST_NIL, node_path, "event-channel", - "%u", irq_to_evtchn_port(sc->xbd_irq)); + "%u", xen_intr_port(sc->xen_intr_handle)); if (error) { xenbus_dev_fatal(sc->xbd_dev, error, "writing %s/event-channel", diff --git a/sys/dev/xen/blkfront/block.h b/sys/dev/xen/blkfront/block.h index 0f7d6cb..9c803bc 100644 --- a/sys/dev/xen/blkfront/block.h +++ b/sys/dev/xen/blkfront/block.h @@ -179,7 +179,7 @@ struct xbd_softc { uint32_t xbd_max_request_size; grant_ref_t xbd_ring_ref[XBD_MAX_RING_PAGES]; blkif_front_ring_t xbd_ring; - unsigned int xbd_irq; + xen_intr_handle_t xen_intr_handle; struct gnttab_free_callback xbd_callback; xbd_cm_q_t xbd_cm_q[XBD_Q_COUNT]; bus_dma_tag_t xbd_io_dmat; diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c index 6281bf2..65a0e7d 100644 --- a/sys/dev/xen/console/console.c +++ b/sys/dev/xen/console/console.c @@ -15,7 +15,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/bus.h> #include <machine/stdarg.h> -#include <machine/xen/xen-os.h> +#include <xen/xen-os.h> #include <xen/hypervisor.h> #include <xen/xen_intr.h> #include <sys/cons.h> @@ -71,6 +71,8 @@ static char rbuf[RBUF_SIZE]; static int rc, rp; static unsigned int cnsl_evt_reg; static unsigned int wc, wp; /* write_cons, write_prod */ +xen_intr_handle_t xen_intr_handle; +device_t xencons_dev; #ifdef KDB static int xc_altbrk; @@ -232,6 +234,7 @@ xc_attach(device_t dev) { int error; + xencons_dev = dev; xccons = tty_alloc(&xc_ttydevsw, NULL); tty_makedev(xccons, NULL, "xc%r", 0); @@ -243,15 +246,10 @@ xc_attach(device_t dev) callout_reset(&xc_callout, XC_POLLTIME, xc_timeout, xccons); if (xen_start_info->flags & SIF_INITDOMAIN) { - error = bind_virq_to_irqhandler( - VIRQ_CONSOLE, - 0, - "console", - NULL, - xencons_priv_interrupt, NULL, - INTR_TYPE_TTY, NULL); - - KASSERT(error >= 0, ("can't register console interrupt")); + error = xen_intr_bind_virq(dev, VIRQ_CONSOLE, 0, NULL, + xencons_priv_interrupt, NULL, + INTR_TYPE_TTY, &xen_intr_handle); + KASSERT(error >= 0, ("can't register console interrupt")); } /* register handler to flush console on shutdown */ diff --git a/sys/dev/xen/console/xencons_ring.c b/sys/dev/xen/console/xencons_ring.c index 077d286..3701551 100644 --- a/sys/dev/xen/console/xencons_ring.c +++ b/sys/dev/xen/console/xencons_ring.c @@ -16,7 +16,8 @@ __FBSDID("$FreeBSD$"); #include <sys/cons.h> #include <machine/stdarg.h> -#include <machine/xen/xen-os.h> + +#include <xen/xen-os.h> #include <xen/hypervisor.h> #include <xen/xen_intr.h> #include <sys/cons.h> @@ -30,9 +31,10 @@ __FBSDID("$FreeBSD$"); #include <xen/interface/io/console.h> #define console_evtchn console.domU.evtchn -static unsigned int console_irq; +xen_intr_handle_t console_handle; extern char *console_page; extern struct mtx cn_mtx; +extern device_t xencons_dev; static inline struct xencons_interface * xencons_interface(void) @@ -74,7 +76,7 @@ xencons_ring_send(const char *data, unsigned len) wmb(); intf->out_prod = prod; - notify_remote_via_evtchn(xen_start_info->console_evtchn); + xen_intr_signal(console_handle); return sent; @@ -106,7 +108,7 @@ xencons_handle_input(void *unused) intf->in_cons = cons; CN_LOCK(cn_mtx); - notify_remote_via_evtchn(xen_start_info->console_evtchn); + xen_intr_signal(console_handle); xencons_tx(); CN_UNLOCK(cn_mtx); @@ -126,9 +128,9 @@ xencons_ring_init(void) if (!xen_start_info->console_evtchn) return 0; - err = bind_caller_port_to_irqhandler(xen_start_info->console_evtchn, - "xencons", xencons_handle_input, NULL, - INTR_TYPE_MISC | INTR_MPSAFE, &console_irq); + err = xen_intr_bind_local_port(xencons_dev, + xen_start_info->console_evtchn, NULL, xencons_handle_input, NULL, + INTR_TYPE_MISC | INTR_MPSAFE, &console_handle); if (err) { return err; } @@ -146,7 +148,7 @@ xencons_suspend(void) if (!xen_start_info->console_evtchn) return; - unbind_from_irqhandler(console_irq); + xen_intr_unbind(&console_handle); } void diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c index 18f42bb..649f281 100644 --- a/sys/dev/xen/control/control.c +++ b/sys/dev/xen/control/control.c @@ -128,12 +128,13 @@ __FBSDID("$FreeBSD$"); #include <geom/geom.h> #include <machine/_inttypes.h> -#include <machine/xen/xen-os.h> +#include <machine/intr_machdep.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> +#include <xen/xen-os.h> #include <xen/blkif.h> #include <xen/evtchn.h> #include <xen/gnttab.h> @@ -144,6 +145,9 @@ __FBSDID("$FreeBSD$"); #include <xen/xenbus/xenbusvar.h> +#include <machine/xen/xenvar.h> +#include <machine/xen/xenfunc.h> + /*--------------------------- Forward Declarations --------------------------*/ /** Function signature for shutdown event handlers. */ typedef void (xctrl_shutdown_handler_t)(void); @@ -242,6 +246,7 @@ xctrl_suspend() xencons_suspend(); gnttab_suspend(); + intr_suspend(); max_pfn = HYPERVISOR_shared_info->arch.max_pfn; @@ -282,7 +287,7 @@ xctrl_suspend() HYPERVISOR_shared_info->arch.max_pfn = max_pfn; gnttab_resume(); - irq_resume(); + intr_resume(); local_irq_enable(); xencons_resume(); @@ -352,13 +357,11 @@ xctrl_suspend() * Prevent any races with evtchn_interrupt() handler. */ disable_intr(); - irq_suspend(); + intr_suspend(); suspend_cancelled = HYPERVISOR_suspend(0); - if (suspend_cancelled) - irq_resume(); - else - xenpci_resume(); + + intr_resume(); /* * Re-enable interrupts and put the scheduler back to normal. diff --git a/sys/dev/xen/netback/netback.c b/sys/dev/xen/netback/netback.c index 9463bad..8f0286c 100644 --- a/sys/dev/xen/netback/netback.c +++ b/sys/dev/xen/netback/netback.c @@ -79,14 +79,15 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_kern.h> #include <machine/_inttypes.h> -#include <machine/xen/xen-os.h> -#include <machine/xen/xenvar.h> -#include <xen/evtchn.h> +#include <xen/xen-os.h> +#include <xen/hypervisor.h> #include <xen/xen_intr.h> #include <xen/interface/io/netif.h> #include <xen/xenbus/xenbusvar.h> +#include <machine/xen/xenvar.h> + /*--------------------------- Compile-time Tunables --------------------------*/ /*---------------------------------- Macros ----------------------------------*/ @@ -433,8 +434,8 @@ struct xnb_softc { /** Xen device handle.*/ long handle; - /** IRQ mapping for the communication ring event channel. */ - int irq; + /** Handle to the communication ring event channel. */ + xen_intr_handle_t xen_intr_handle; /** * \brief Cached value of the front-end's domain id. @@ -647,10 +648,7 @@ xnb_disconnect(struct xnb_softc *xnb) int error; int i; - if (xnb->irq != 0) { - unbind_from_irqhandler(xnb->irq); - xnb->irq = 0; - } + xen_intr_unbind(xnb->xen_intr_handle); /* * We may still have another thread currently processing requests. We @@ -773,13 +771,13 @@ xnb_connect_comms(struct xnb_softc *xnb) xnb->flags |= XNBF_RING_CONNECTED; - error = - bind_interdomain_evtchn_to_irqhandler(xnb->otherend_id, - xnb->evtchn, - device_get_nameunit(xnb->dev), - xnb_intr, /*arg*/xnb, - INTR_TYPE_BIO | INTR_MPSAFE, - &xnb->irq); + error = xen_intr_bind_remote_port(xnb->dev, + xnb->otherend_id, + xnb->evtchn, + /*filter*/NULL, + xnb_intr, /*arg*/xnb, + INTR_TYPE_BIO | INTR_MPSAFE, + &xnb->xen_intr_handle); if (error != 0) { (void)xnb_disconnect(xnb); xenbus_dev_fatal(xnb->dev, error, "binding event channel"); @@ -1448,7 +1446,7 @@ xnb_intr(void *arg) RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(txb, notify); if (notify != 0) - notify_remote_via_irq(xnb->irq); + xen_intr_signal(xnb->xen_intr_handle); txb->sring->req_event = txb->req_cons + 1; xen_mb(); @@ -2361,7 +2359,7 @@ xnb_start_locked(struct ifnet *ifp) RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(rxb, notify); if ((notify != 0) || (out_of_space != 0)) - notify_remote_via_irq(xnb->irq); + xen_intr_signal(xnb->xen_intr_handle); rxb->sring->req_event = req_prod_local + 1; xen_mb(); } while (rxb->sring->req_prod != req_prod_local) ; diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c index 68b3bf9..f9c72e6 100644 --- a/sys/dev/xen/netfront/netfront.c +++ b/sys/dev/xen/netfront/netfront.c @@ -76,17 +76,16 @@ __FBSDID("$FreeBSD$"); #include <machine/intr_machdep.h> -#include <machine/xen/xen-os.h> -#include <machine/xen/xenfunc.h> -#include <machine/xen/xenvar.h> +#include <xen/xen-os.h> #include <xen/hypervisor.h> #include <xen/xen_intr.h> -#include <xen/evtchn.h> #include <xen/gnttab.h> #include <xen/interface/memory.h> #include <xen/interface/io/netif.h> #include <xen/xenbus/xenbusvar.h> +#include <machine/xen/xenvar.h> + #include <dev/xen/netfront/mbufq.h> #include "xenbus_if.h" @@ -257,8 +256,7 @@ struct netfront_info { struct mtx rx_lock; struct mtx sc_lock; - u_int handle; - u_int irq; + xen_intr_handle_t xen_intr_handle; u_int copying_receiver; u_int carrier; u_int maxfrags; @@ -547,7 +545,8 @@ talk_to_backend(device_t dev, struct netfront_info *info) goto abort_transaction; } err = xs_printf(xst, node, - "event-channel", "%u", irq_to_evtchn_port(info->irq)); + "event-channel", "%u", + xen_intr_port(info->xen_intr_handle)); if (err) { message = "writing event-channel"; goto abort_transaction; @@ -609,7 +608,6 @@ setup_device(device_t dev, struct netfront_info *info) info->rx_ring_ref = GRANT_REF_INVALID; info->rx.sring = NULL; info->tx.sring = NULL; - info->irq = 0; txs = (netif_tx_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO); if (!txs) { @@ -636,12 +634,13 @@ setup_device(device_t dev, struct netfront_info *info) if (error) goto fail; - error = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev), - "xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, &info->irq); + error = xen_intr_alloc_and_bind_local_port(dev, + xenbus_get_otherend_id(dev), /*filter*/NULL, xn_intr, info, + INTR_TYPE_NET | INTR_MPSAFE | INTR_ENTROPY, &info->xen_intr_handle); if (error) { xenbus_dev_fatal(dev, error, - "bind_evtchn_to_irqhandler failed"); + "xen_intr_alloc_and_bind_local_port failed"); goto fail; } @@ -806,7 +805,7 @@ network_alloc_rx_buffers(struct netfront_info *sc) req_prod = sc->rx.req_prod_pvt; - if (unlikely(sc->carrier == 0)) + if (__predict_false(sc->carrier == 0)) return; /* @@ -946,7 +945,7 @@ refill: /* Zap PTEs and give away pages in one big multicall. */ (void)HYPERVISOR_multicall(sc->rx_mcl, i+1); - if (unlikely(sc->rx_mcl[i].result != i || + if (__predict_false(sc->rx_mcl[i].result != i || HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation) != i)) panic("%s: unable to reduce memory " @@ -961,7 +960,7 @@ refill: push: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->rx, notify); if (notify) - notify_remote_via_irq(sc->irq); + xen_intr_signal(sc->xen_intr_handle); } static void @@ -1003,7 +1002,7 @@ xn_rxeof(struct netfront_info *np) err = xennet_get_responses(np, &rinfo, rp, &i, &m, &pages_flipped); - if (unlikely(err)) { + if (__predict_false(err)) { if (m) mbufq_tail(&errq, m); np->stats.rx_errors++; @@ -1151,7 +1150,7 @@ xn_txeof(struct netfront_info *np) */ if (!m->m_next) ifp->if_opackets++; - if (unlikely(gnttab_query_foreign_access( + if (__predict_false(gnttab_query_foreign_access( np->grant_tx_ref[id]) != 0)) { panic("%s: grant id %u still in use by the " "backend", __func__, id); @@ -1249,7 +1248,7 @@ xennet_get_extras(struct netfront_info *np, struct mbuf *m; grant_ref_t ref; - if (unlikely(*cons + 1 == rp)) { + if (__predict_false(*cons + 1 == rp)) { #if 0 if (net_ratelimit()) WPRINTK("Missing extra info\n"); @@ -1261,7 +1260,7 @@ xennet_get_extras(struct netfront_info *np, extra = (struct netif_extra_info *) RING_GET_RESPONSE(&np->rx, ++(*cons)); - if (unlikely(!extra->type || + if (__predict_false(!extra->type || extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { #if 0 if (net_ratelimit()) @@ -1317,7 +1316,7 @@ xennet_get_responses(struct netfront_info *np, DPRINTK("rx->status=%hd rx->offset=%hu frags=%u\n", rx->status, rx->offset, frags); #endif - if (unlikely(rx->status < 0 || + if (__predict_false(rx->status < 0 || rx->offset + rx->status > PAGE_SIZE)) { #if 0 @@ -1679,7 +1678,7 @@ xn_start_locked(struct ifnet *ifp) RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->tx, notify); if (notify) - notify_remote_via_irq(sc->irq); + xen_intr_signal(sc->xen_intr_handle); if (RING_FULL(&sc->tx)) { sc->tx_full = 1; @@ -1961,7 +1960,7 @@ network_connect(struct netfront_info *np) * packets. */ netfront_carrier_on(np); - notify_remote_via_irq(np->irq); + xen_intr_signal(np->xen_intr_handle); XN_TX_LOCK(np); xn_txeof(np); XN_TX_UNLOCK(np); @@ -2050,8 +2049,9 @@ xn_configure_features(struct netfront_info *np) return (err); } -/** Create a network device. - * @param handle device handle +/** + * Create a network device. + * @param dev Newbus device representing this virtual NIC. */ int create_netdev(device_t dev) @@ -2198,10 +2198,7 @@ netif_disconnect_backend(struct netfront_info *info) free_ring(&info->tx_ring_ref, &info->tx.sring); free_ring(&info->rx_ring_ref, &info->rx.sring); - if (info->irq) - unbind_from_irqhandler(info->irq); - - info->irq = 0; + xen_intr_unbind(&info->xen_intr_handle); } static void diff --git a/sys/dev/xen/xenpci/evtchn.c b/sys/dev/xen/xenpci/evtchn.c deleted file mode 100644 index 2d9dd6d..0000000 --- a/sys/dev/xen/xenpci/evtchn.c +++ /dev/null @@ -1,467 +0,0 @@ -/****************************************************************************** - * 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$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/limits.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/interrupt.h> -#include <sys/pcpu.h> - -#include <machine/xen/xen-os.h> -#include <machine/xen/xenvar.h> -#include <xen/hypervisor.h> -#include <xen/xen_intr.h> -#include <xen/evtchn.h> -#include <sys/smp.h> - -#include <dev/xen/xenpci/xenpcivar.h> - -#if defined(__i386__) -#define __ffs(word) (ffs(word) - 1) -#elif defined(__amd64__) -static inline unsigned long __ffs(unsigned long word) -{ - __asm__("bsfq %1,%0" - :"=r" (word) - :"rm" (word)); /* XXXRW: why no "cc"? */ - return word; -} -#else -#error "evtchn: unsupported architecture" -#endif - -#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; - int mpsafe:1; -} irq_evtchn[256]; -static int evtchn_to_irq[NR_EVENT_CHANNELS] = { - [0 ... NR_EVENT_CHANNELS-1] = -1 }; - -static struct mtx irq_alloc_lock; -static device_t xenpci_device; - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) - -static unsigned int -alloc_xen_irq(void) -{ - static int warned; - unsigned 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, unsigned int *irqp) -{ - struct evtchn_alloc_unbound alloc_unbound; - unsigned int irq; - int error; - - 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; - error = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, - &alloc_unbound); - if (error) { - mtx_unlock(&irq_evtchn[irq].lock); - free_xen_irq(irq); - return (-error); - } - - irq_evtchn[irq].handler = handler; - irq_evtchn[irq].arg = arg; - irq_evtchn[irq].evtchn = alloc_unbound.port; - irq_evtchn[irq].close = 1; - irq_evtchn[irq].mpsafe = (irqflags & INTR_MPSAFE) != 0; - - evtchn_to_irq[alloc_unbound.port] = irq; - - unmask_evtchn(alloc_unbound.port); - - mtx_unlock(&irq_evtchn[irq].lock); - - if (irqp) - *irqp = irq; - return (0); -} - -int -bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, - unsigned int remote_port, const char *devname, driver_intr_t handler, - void *arg, unsigned long irqflags, unsigned int *irqp) -{ - struct evtchn_bind_interdomain bind_interdomain; - unsigned int irq; - int error; - - irq = alloc_xen_irq(); - if (irq < 0) - return irq; - - mtx_lock(&irq_evtchn[irq].lock); - - bind_interdomain.remote_dom = remote_domain; - bind_interdomain.remote_port = remote_port; - error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, - &bind_interdomain); - if (error) { - mtx_unlock(&irq_evtchn[irq].lock); - free_xen_irq(irq); - return (-error); - } - - irq_evtchn[irq].handler = handler; - irq_evtchn[irq].arg = arg; - irq_evtchn[irq].evtchn = bind_interdomain.local_port; - irq_evtchn[irq].close = 1; - irq_evtchn[irq].mpsafe = (irqflags & INTR_MPSAFE) != 0; - - evtchn_to_irq[bind_interdomain.local_port] = irq; - - unmask_evtchn(bind_interdomain.local_port); - - mtx_unlock(&irq_evtchn[irq].lock); - - if (irqp) - *irqp = irq; - return (0); -} - - -int -bind_caller_port_to_irqhandler(unsigned int caller_port, - const char *devname, driver_intr_t handler, void *arg, - unsigned long irqflags, unsigned int *irqp) -{ - unsigned 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; - irq_evtchn[irq].mpsafe = (irqflags & INTR_MPSAFE) != 0; - - evtchn_to_irq[caller_port] = irq; - - unmask_evtchn(caller_port); - - mtx_unlock(&irq_evtchn[irq].lock); - - if (irqp) - *irqp = irq; - return (0); -} - -void -unbind_from_irqhandler(unsigned int irq) -{ - 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, handler_mpsafe; - shared_info_t *s = HYPERVISOR_shared_info; - vcpu_info_t *v = &s->vcpu_info[cpu]; - struct pcpu *pc = pcpu_find(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 = pc->pc_last_processed_l1i; - l2i = pc->pc_last_processed_l2i; - - while (l1 != 0) { - - l1i = (l1i + 1) % LONG_BIT; - masked_l1 = l1 & ((~0UL) << l1i); - - if (masked_l1 == 0) { /* if we masked out all events, wrap around to the beginning */ - l1i = LONG_BIT - 1; - l2i = LONG_BIT - 1; - continue; - } - l1i = __ffs(masked_l1); - - do { - l2 = active_evtchns(cpu, s, l1i); - - l2i = (l2i + 1) % LONG_BIT; - masked_l2 = l2 & ((~0UL) << l2i); - - if (masked_l2 == 0) { /* if we masked out all events, move on */ - l2i = LONG_BIT - 1; - break; - } - l2i = __ffs(masked_l2); - - /* process port */ - port = (l1i * LONG_BIT) + 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; - handler_mpsafe = irq_evtchn[irq].mpsafe; - if (unlikely(handler == NULL)) { - printf("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(); - if (!handler_mpsafe) - mtx_lock(&Giant); - handler(handler_arg); - if (!handler_mpsafe) - mtx_unlock(&Giant); - //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 */ - pc->pc_last_processed_l1i = l1i; - pc->pc_last_processed_l2i = l2i; - - } while (l2i != LONG_BIT - 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_suspend(void) -{ - struct xenpci_softc *scp = device_get_softc(xenpci_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(device_get_parent(xenpci_device), - xenpci_device, scp->res_irq, scp->intr_cookie) != 0) - printf("intr teardown failed.. continuing\n"); - scp->intr_cookie = NULL; - } -} - -void -irq_resume(void) -{ - struct xenpci_softc *scp = device_get_softc(xenpci_device); - 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; - - BUS_SETUP_INTR(device_get_parent(xenpci_device), - xenpci_device, scp->res_irq, INTR_TYPE_MISC, - NULL, evtchn_interrupt, NULL, &scp->intr_cookie); -} - -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++) { - pcpu_find(cpu)->pc_last_processed_l1i = LONG_BIT - 1; - pcpu_find(cpu)->pc_last_processed_l2i = LONG_BIT - 1; - } - - error = BUS_SETUP_INTR(device_get_parent(device), device, - scp->res_irq, INTR_MPSAFE|INTR_TYPE_MISC, NULL, evtchn_interrupt, - NULL, &scp->intr_cookie); - if (error) - return (error); - - xenpci_device = device; - - return (0); -} diff --git a/sys/dev/xen/xenpci/xenpci.c b/sys/dev/xen/xenpci/xenpci.c index 2d74676..0b1762d 100644 --- a/sys/dev/xen/xenpci/xenpci.c +++ b/sys/dev/xen/xenpci/xenpci.c @@ -32,40 +32,25 @@ __FBSDID("$FreeBSD$"); #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/xen-os.h> + +#include <xen/xen-os.h> #include <xen/features.h> #include <xen/hypervisor.h> -#include <xen/gnttab.h> -#include <xen/xen_intr.h> -#include <xen/interface/memory.h> -#include <xen/interface/hvm/params.h> +#include <xen/hvm.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> -#include <vm/vm.h> -#include <vm/vm_extern.h> -#include <vm/vm_kern.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; -static vm_paddr_t shared_info_pa; +extern void xen_intr_handle_upcall(struct trapframe *trap_frame); + static device_t nexus; /* @@ -73,103 +58,42 @@ static device_t nexus; */ static devclass_t xenpci_devclass; -/* - * Return the CPUID base address for Xen functions. - */ -static uint32_t -xenpci_cpuid_base(void) +static int +xenpci_intr_filter(void *trap_frame) { - uint32_t base, regs[4]; - - for (base = 0x40000000; base < 0x40010000; base += 0x100) { - do_cpuid(base, regs); - if (!memcmp("XenVMMXenVMM", ®s[1], 12) - && (regs[0] - base) >= 2) - return (base); - } - return (0); + xen_intr_handle_upcall(trap_frame); + return (FILTER_HANDLED); } -/* - * Allocate and fill in the hypcall page. - */ static int -xenpci_init_hypercall_stubs(device_t dev, struct xenpci_softc * scp) +xenpci_irq_init(device_t device, struct xenpci_softc *scp) { - uint32_t base, regs[4]; - int i; - - base = xenpci_cpuid_base(); - if (!base) { - device_printf(dev, "Xen platform device but not Xen VMM\n"); - return (EINVAL); - } + int error; - if (bootverbose) { - do_cpuid(base + 1, regs); - device_printf(dev, "Xen version %d.%d.\n", - regs[0] >> 16, regs[0] & 0xffff); - } + error = BUS_SETUP_INTR(device_get_parent(device), device, + scp->res_irq, INTR_MPSAFE|INTR_TYPE_MISC, + xenpci_intr_filter, NULL, /*trap_frame*/NULL, + &scp->intr_cookie); + if (error) + return error; /* - * Find the hypercall pages. + * When using the PCI event delivery callback we cannot assign + * events to specific vCPUs, so all events are delivered to vCPU#0 by + * Xen. Since the PCI interrupt can fire on any CPU by default, we + * need to bind it to vCPU#0 in order to ensure that + * xen_intr_handle_upcall always gets called on vCPU#0. */ - 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); - } + error = BUS_BIND_INTR(device_get_parent(device), device, + scp->res_irq, 0); + if (error) + return error; + xen_hvm_set_callback(device); return (0); } /* - * After a resume, re-initialise the hypercall page. - */ -static void -xenpci_resume_hypercall_stubs(device_t dev, 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); - } -} - -/* - * Tell the hypervisor how to contact us for event channel callbacks. - */ -static void -xenpci_set_callback(device_t dev) -{ - int irq; - uint64_t callback; - struct xen_hvm_param xhp; - - irq = pci_get_irq(dev); - if (irq < 16) { - callback = irq; - } else { - callback = (pci_get_intpin(dev) - 1) & 3; - callback |= pci_get_slot(dev) << 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"); -} - - -/* * Deallocate anything allocated by xenpci_allocate_resources. */ static int @@ -293,35 +217,6 @@ xenpci_deactivate_resource(device_t dev, device_t child, int type, } /* - * 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 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(dev, scp); - - 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"); - - pmap_kenter((vm_offset_t) HYPERVISOR_shared_info, shared_info_pa); - - xenpci_set_callback(dev); - - gnttab_resume(); - irq_resume(); -} - -/* * Probe - just check device ID. */ static int @@ -341,11 +236,9 @@ xenpci_probe(device_t dev) 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; devclass_t dc; + int error; /* * Find and record nexus0. Since we are not really on the @@ -365,33 +258,15 @@ xenpci_attach(device_t dev) goto errexit; } - error = xenpci_init_hypercall_stubs(dev, scp); - if (error) { - device_printf(dev, "xenpci_init_hypercall_stubs failed(%d).\n", - 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 = kva_alloc(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); + error = xenpci_irq_init(dev, scp); + if (error) { + device_printf(dev, "xenpci_irq_init failed(%d).\n", + error); + goto errexit; + } return (bus_generic_attach(dev)); @@ -431,13 +306,42 @@ xenpci_detach(device_t dev) return (xenpci_deallocate_resources(dev)); } +static int +xenpci_suspend(device_t dev) +{ + struct xenpci_softc *scp = device_get_softc(dev); + device_t parent = device_get_parent(dev); + + 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; + } + + return (bus_generic_suspend(dev)); +} + +static int +xenpci_resume(device_t dev) +{ + struct xenpci_softc *scp = device_get_softc(dev); + device_t parent = device_get_parent(dev); + + BUS_SETUP_INTR(parent, dev, scp->res_irq, + INTR_MPSAFE|INTR_TYPE_MISC, xenpci_intr_filter, NULL, + /*trap_frame*/NULL, &scp->intr_cookie); + xen_hvm_set_callback(dev); + return (bus_generic_resume(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), + DEVMETHOD(device_suspend, xenpci_suspend), + DEVMETHOD(device_resume, xenpci_resume), /* Bus interface */ DEVMETHOD(bus_add_child, bus_generic_add_child), diff --git a/sys/dev/xen/xenpci/xenpcivar.h b/sys/dev/xen/xenpci/xenpcivar.h index a57c080..527a291 100644 --- a/sys/dev/xen/xenpci/xenpcivar.h +++ b/sys/dev/xen/xenpci/xenpcivar.h @@ -22,6 +22,8 @@ * 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. + * + * $FreeBSD$ */ /* @@ -38,7 +40,4 @@ struct xenpci_softc { vm_paddr_t 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, vm_paddr_t *pa); -extern void xenpci_resume(void); -extern void xen_suspend(void); |