aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/xen
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/xen')
-rw-r--r--sys/dev/xen/balloon/balloon.c11
-rw-r--r--sys/dev/xen/blkback/blkback.c52
-rw-r--r--sys/dev/xen/blkfront/blkfront.c37
-rw-r--r--sys/dev/xen/blkfront/block.h2
-rw-r--r--sys/dev/xen/console/console.c18
-rw-r--r--sys/dev/xen/console/xencons_ring.c18
-rw-r--r--sys/dev/xen/control/control.c17
-rw-r--r--sys/dev/xen/netback/netback.c34
-rw-r--r--sys/dev/xen/netfront/netfront.c51
-rw-r--r--sys/dev/xen/xenpci/evtchn.c467
-rw-r--r--sys/dev/xen/xenpci/xenpci.c226
-rw-r--r--sys/dev/xen/xenpci/xenpcivar.h5
12 files changed, 184 insertions, 754 deletions
diff --git a/sys/dev/xen/balloon/balloon.c b/sys/dev/xen/balloon/balloon.c
index d4f94ab9ee00..9021abb1172d 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 4208702c4016..33f6fafc6d27 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 969c3d8caf1a..7d70f42ce1cb 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 0f7d6cb124d8..9c803bc2eacf 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 6281bf2165e0..65a0e7dad961 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 077d286f3fe0..3701551ea101 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 18f42bbe653b..649f28160407 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 9463bad7a8b1..8f0286c31f06 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 68b3bf9be826..f9c72e6fc49a 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 2d9dd6d664d1..000000000000
--- 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 2d7467691577..0b1762df03b4 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", &regs[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 a57c080b31d3..527a291c8801 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);