merge 186535, 186537, and 186538 from releng_7_xen
Log: - merge in latest xenbus from dfr's xenhvm - fix race condition in xs_read_reply by converting tsleep to mtx_sleep Log: unmask evtchn in bind_{virq, ipi}_to_irq Log: - remove code for handling case of not being able to sleep - eliminate tsleep - make sleeps atomic
This commit is contained in:
parent
42d866dd69
commit
3a6d1fcf9c
@ -40,10 +40,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/interface/grant_table.h>
|
||||
#include <xen/interface/io/protocols.h>
|
||||
#include <xen/xenbus/xenbusvar.h>
|
||||
@ -214,7 +214,7 @@ xlvbd_add(device_t dev, blkif_sector_t capacity,
|
||||
struct xb_softc *sc;
|
||||
int unit, error = 0;
|
||||
const char *name;
|
||||
|
||||
|
||||
blkfront_vdevice_to_unit(vdevice, &unit, &name);
|
||||
|
||||
sc = (struct xb_softc *)malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
@ -227,12 +227,12 @@ xlvbd_add(device_t dev, blkif_sector_t capacity,
|
||||
|
||||
memset(&sc->xb_disk, 0, sizeof(sc->xb_disk));
|
||||
sc->xb_disk = disk_alloc();
|
||||
sc->xb_disk->d_unit = unit;
|
||||
sc->xb_disk->d_unit = sc->xb_unit;
|
||||
sc->xb_disk->d_open = blkif_open;
|
||||
sc->xb_disk->d_close = blkif_close;
|
||||
sc->xb_disk->d_ioctl = blkif_ioctl;
|
||||
sc->xb_disk->d_strategy = xb_strategy;
|
||||
sc->xb_disk->d_name = "xbd";
|
||||
sc->xb_disk->d_name = name;
|
||||
sc->xb_disk->d_drv1 = sc;
|
||||
sc->xb_disk->d_sectorsize = sector_size;
|
||||
|
||||
@ -329,8 +329,8 @@ blkfront_attach(device_t dev)
|
||||
|
||||
/* FIXME: Use dynamic device id if this is not set. */
|
||||
err = xenbus_scanf(XBT_NIL, xenbus_get_node(dev),
|
||||
"virtual-device", "%i", &vdevice);
|
||||
if (err != 1) {
|
||||
"virtual-device", NULL, "%i", &vdevice);
|
||||
if (err) {
|
||||
xenbus_dev_fatal(dev, err, "reading virtual-device");
|
||||
printf("couldn't find virtual device");
|
||||
return (err);
|
||||
@ -363,9 +363,8 @@ blkfront_attach(device_t dev)
|
||||
info->handle = strtoul(strrchr(xenbus_get_node(dev),'/')+1, NULL, 0);
|
||||
|
||||
err = talk_to_backend(dev, info);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -381,7 +380,8 @@ blkfront_resume(device_t dev)
|
||||
blkif_free(info, 1);
|
||||
|
||||
err = talk_to_backend(dev, info);
|
||||
if (!err)
|
||||
|
||||
if (info->connected == BLKIF_STATE_SUSPENDED && !err)
|
||||
blkif_recover(info);
|
||||
|
||||
return err;
|
||||
@ -427,7 +427,7 @@ talk_to_backend(device_t dev, struct blkfront_info *info)
|
||||
}
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
if (err) {
|
||||
if (err == -EAGAIN)
|
||||
if (err == EAGAIN)
|
||||
goto again;
|
||||
xenbus_dev_fatal(dev, err, "completing transaction");
|
||||
goto destroy_blkring;
|
||||
@ -450,7 +450,7 @@ static int
|
||||
setup_blkring(device_t dev, struct blkfront_info *info)
|
||||
{
|
||||
blkif_sring_t *sring;
|
||||
int err;
|
||||
int error;
|
||||
|
||||
info->ring_ref = GRANT_INVALID_REF;
|
||||
|
||||
@ -462,28 +462,27 @@ setup_blkring(device_t dev, struct blkfront_info *info)
|
||||
SHARED_RING_INIT(sring);
|
||||
FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
|
||||
|
||||
err = xenbus_grant_ring(dev, (vtomach(info->ring.sring) >> PAGE_SHIFT));
|
||||
if (err < 0) {
|
||||
error = xenbus_grant_ring(dev, (vtomach(info->ring.sring) >> PAGE_SHIFT),
|
||||
&info->ring_ref);
|
||||
if (error) {
|
||||
free(sring, M_DEVBUF);
|
||||
info->ring.sring = NULL;
|
||||
goto fail;
|
||||
}
|
||||
info->ring_ref = err;
|
||||
|
||||
err = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev),
|
||||
error = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev),
|
||||
"xbd", (driver_intr_t *)blkif_int, info,
|
||||
INTR_TYPE_BIO | INTR_MPSAFE, NULL);
|
||||
if (err <= 0) {
|
||||
xenbus_dev_fatal(dev, err,
|
||||
INTR_TYPE_BIO | INTR_MPSAFE, &info->irq);
|
||||
if (error) {
|
||||
xenbus_dev_fatal(dev, error,
|
||||
"bind_evtchn_to_irqhandler failed");
|
||||
goto fail;
|
||||
}
|
||||
info->irq = err;
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
fail:
|
||||
blkif_free(info, 0);
|
||||
return err;
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
@ -999,7 +998,7 @@ blkif_free(struct blkfront_info *info, int suspend)
|
||||
info->ring.sring = NULL;
|
||||
}
|
||||
if (info->irq)
|
||||
unbind_from_irqhandler(info->irq, info);
|
||||
unbind_from_irqhandler(info->irq);
|
||||
info->irq = 0;
|
||||
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
#include <machine/stdarg.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
@ -75,17 +75,17 @@ static unsigned int wc, wp; /* write_cons, write_prod */
|
||||
#define XCUNIT(x) (dev2unit(x))
|
||||
#define ISTTYOPEN(tp) ((tp) && ((tp)->t_state & TS_ISOPEN))
|
||||
#define CN_LOCK_INIT(x, _name) \
|
||||
mtx_init(&x, _name, NULL, MTX_SPIN|MTX_RECURSE)
|
||||
mtx_init(&x, _name, NULL, MTX_DEF|MTX_RECURSE)
|
||||
|
||||
#define CN_LOCK(l) \
|
||||
do { \
|
||||
if (panicstr == NULL) \
|
||||
mtx_lock_spin(&(l)); \
|
||||
mtx_lock(&(l)); \
|
||||
} while (0)
|
||||
#define CN_UNLOCK(l) \
|
||||
do { \
|
||||
if (panicstr == NULL) \
|
||||
mtx_unlock_spin(&(l)); \
|
||||
mtx_unlock(&(l)); \
|
||||
} while (0)
|
||||
#define CN_LOCK_ASSERT(x) mtx_assert(&x, MA_OWNED)
|
||||
#define CN_LOCK_DESTROY(x) mtx_destroy(&x)
|
||||
@ -216,6 +216,8 @@ xc_probe(device_t dev)
|
||||
static int
|
||||
xc_attach(device_t dev)
|
||||
{
|
||||
int error;
|
||||
struct xc_softc *sc = (struct xc_softc *)device_get_softc(dev);
|
||||
|
||||
if (xen_start_info->flags & SIF_INITDOMAIN) {
|
||||
xc_consdev.cn_putc = xccnputc_dom0;
|
||||
@ -232,14 +234,15 @@ xc_attach(device_t dev)
|
||||
callout_reset(&xc_callout, XC_POLLTIME, xc_timeout, xccons);
|
||||
|
||||
if (xen_start_info->flags & SIF_INITDOMAIN) {
|
||||
PANIC_IF(bind_virq_to_irqhandler(
|
||||
VIRQ_CONSOLE,
|
||||
0,
|
||||
"console",
|
||||
NULL,
|
||||
xencons_priv_interrupt,
|
||||
INTR_TYPE_TTY) < 0);
|
||||
error = bind_virq_to_irqhandler(
|
||||
VIRQ_CONSOLE,
|
||||
0,
|
||||
"console",
|
||||
NULL,
|
||||
xencons_priv_interrupt,
|
||||
sc, INTR_TYPE_TTY, NULL);
|
||||
|
||||
KASSERT(error >= 0, ("can't register console interrupt"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,19 +15,20 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
#include <machine/stdarg.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <sys/cons.h>
|
||||
|
||||
|
||||
#include <dev/xen/console/xencons_ring.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/interface/io/console.h>
|
||||
|
||||
|
||||
#define console_evtchn console.domU.evtchn
|
||||
extern char *console_page;
|
||||
|
||||
extern struct mtx cn_mtx;
|
||||
|
||||
static inline struct xencons_interface *
|
||||
xencons_interface(void)
|
||||
{
|
||||
@ -82,6 +83,7 @@ xencons_handle_input(void *unused)
|
||||
struct xencons_interface *intf;
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
|
||||
mtx_lock(&cn_mtx);
|
||||
intf = xencons_interface();
|
||||
|
||||
cons = intf->in_cons;
|
||||
@ -99,6 +101,7 @@ xencons_handle_input(void *unused)
|
||||
notify_remote_via_evtchn(xen_start_info->console_evtchn);
|
||||
|
||||
xencons_tx();
|
||||
mtx_unlock(&cn_mtx);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -26,13 +26,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/xen-os.h>
|
||||
#include <machine/xen_intr.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/synch_bitops.h>
|
||||
|
||||
#include <machine/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
|
||||
|
||||
typedef struct evtchn_sotfc {
|
||||
|
@ -62,9 +62,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/intr_machdep.h>
|
||||
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/gnttab.h>
|
||||
#include <xen/interface/memory.h>
|
||||
#include <dev/xen/netfront/mbufq.h>
|
||||
@ -363,24 +363,25 @@ makembuf (struct mbuf *buf)
|
||||
static int
|
||||
xen_net_read_mac(device_t dev, uint8_t mac[])
|
||||
{
|
||||
char *s;
|
||||
int i;
|
||||
char *e;
|
||||
char *macstr = xenbus_read(XBT_NIL, xenbus_get_node(dev), "mac", NULL);
|
||||
if (IS_ERR(macstr)) {
|
||||
return PTR_ERR(macstr);
|
||||
}
|
||||
int error, i;
|
||||
char *s, *e, *macstr;
|
||||
|
||||
error = xenbus_read(XBT_NIL, xenbus_get_node(dev), "mac", NULL,
|
||||
(void **) &macstr);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
s = macstr;
|
||||
for (i = 0; i < ETHER_ADDR_LEN; i++) {
|
||||
mac[i] = strtoul(s, &e, 16);
|
||||
if (s == e || (e[0] != ':' && e[0] != 0)) {
|
||||
free(macstr, M_DEVBUF);
|
||||
return ENOENT;
|
||||
return (ENOENT);
|
||||
}
|
||||
s = &e[1];
|
||||
}
|
||||
free(macstr, M_DEVBUF);
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -422,13 +423,11 @@ netfront_attach(device_t dev)
|
||||
* leave the device-layer structures intact so that this is transparent to the
|
||||
* rest of the kernel.
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
netfront_resume(device_t dev)
|
||||
{
|
||||
struct netfront_info *info = device_get_softc(dev);
|
||||
|
||||
DPRINTK("%s\n", xenbus_get_node(dev));
|
||||
|
||||
|
||||
netif_disconnect_backend(info);
|
||||
return (0);
|
||||
}
|
||||
@ -532,7 +531,7 @@ setup_device(device_t dev, struct netfront_info *info)
|
||||
{
|
||||
netif_tx_sring_t *txs;
|
||||
netif_rx_sring_t *rxs;
|
||||
int err;
|
||||
int error;
|
||||
struct ifnet *ifp;
|
||||
|
||||
ifp = info->xn_ifp;
|
||||
@ -545,51 +544,45 @@ setup_device(device_t dev, struct netfront_info *info)
|
||||
|
||||
txs = (netif_tx_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
if (!txs) {
|
||||
err = ENOMEM;
|
||||
xenbus_dev_fatal(dev, err, "allocating tx ring page");
|
||||
error = ENOMEM;
|
||||
xenbus_dev_fatal(dev, error, "allocating tx ring page");
|
||||
goto fail;
|
||||
}
|
||||
SHARED_RING_INIT(txs);
|
||||
FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
|
||||
err = xenbus_grant_ring(dev, virt_to_mfn(txs));
|
||||
if (err < 0)
|
||||
error = xenbus_grant_ring(dev, virt_to_mfn(txs), &info->tx_ring_ref);
|
||||
if (error)
|
||||
goto fail;
|
||||
info->tx_ring_ref = err;
|
||||
|
||||
rxs = (netif_rx_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
if (!rxs) {
|
||||
err = ENOMEM;
|
||||
xenbus_dev_fatal(dev, err, "allocating rx ring page");
|
||||
error = ENOMEM;
|
||||
xenbus_dev_fatal(dev, error, "allocating rx ring page");
|
||||
goto fail;
|
||||
}
|
||||
SHARED_RING_INIT(rxs);
|
||||
FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
|
||||
|
||||
err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
|
||||
if (err < 0)
|
||||
error = xenbus_grant_ring(dev, virt_to_mfn(rxs), &info->rx_ring_ref);
|
||||
if (error)
|
||||
goto fail;
|
||||
info->rx_ring_ref = err;
|
||||
|
||||
#if 0
|
||||
network_connect(info);
|
||||
#endif
|
||||
err = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev),
|
||||
"xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, NULL);
|
||||
error = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev),
|
||||
"xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, &info->irq);
|
||||
|
||||
if (err <= 0) {
|
||||
xenbus_dev_fatal(dev, err,
|
||||
if (error) {
|
||||
xenbus_dev_fatal(dev, error,
|
||||
"bind_evtchn_to_irqhandler failed");
|
||||
goto fail;
|
||||
}
|
||||
info->irq = err;
|
||||
|
||||
|
||||
show_device(info);
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
netif_free(info);
|
||||
return err;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1225,7 +1218,7 @@ xennet_get_responses(struct netfront_info *np,
|
||||
MULTI_update_va_mapping(mcl, (u_long)vaddr,
|
||||
(((vm_paddr_t)mfn) << PAGE_SHIFT) | PG_RW |
|
||||
PG_V | PG_M | PG_A, 0);
|
||||
pfn = (uint32_t)m->m_ext.ext_arg1;
|
||||
pfn = (uintptr_t)m->m_ext.ext_arg1;
|
||||
mmu->ptr = ((vm_paddr_t)mfn << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE;
|
||||
mmu->val = pfn;
|
||||
@ -1557,18 +1550,18 @@ xn_stop(struct netfront_info *sc)
|
||||
int
|
||||
network_connect(struct netfront_info *np)
|
||||
{
|
||||
int i, requeue_idx, err;
|
||||
int i, requeue_idx, error;
|
||||
grant_ref_t ref;
|
||||
netif_rx_request_t *req;
|
||||
u_int feature_rx_copy, feature_rx_flip;
|
||||
|
||||
err = xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev),
|
||||
"feature-rx-copy", "%u", &feature_rx_copy);
|
||||
if (err != 1)
|
||||
error = xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev),
|
||||
"feature-rx-copy", NULL, "%u", &feature_rx_copy);
|
||||
if (error)
|
||||
feature_rx_copy = 0;
|
||||
err = xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev),
|
||||
"feature-rx-flip", "%u", &feature_rx_flip);
|
||||
if (err != 1)
|
||||
error = xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev),
|
||||
"feature-rx-flip", NULL, "%u", &feature_rx_flip);
|
||||
if (error)
|
||||
feature_rx_flip = 1;
|
||||
|
||||
/*
|
||||
@ -1581,9 +1574,9 @@ network_connect(struct netfront_info *np)
|
||||
|
||||
XN_LOCK(np);
|
||||
/* Recovery procedure: */
|
||||
err = talk_to_backend(np->xbdev, np);
|
||||
if (err)
|
||||
return (err);
|
||||
error = talk_to_backend(np->xbdev, np);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Step 1: Reinitialise variables. */
|
||||
netif_release_tx_bufs(np);
|
||||
@ -1591,6 +1584,7 @@ network_connect(struct netfront_info *np)
|
||||
/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
|
||||
for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
|
||||
struct mbuf *m;
|
||||
u_long pfn;
|
||||
|
||||
if (np->rx_mbufs[i] == NULL)
|
||||
continue;
|
||||
@ -1598,15 +1592,16 @@ network_connect(struct netfront_info *np)
|
||||
m = np->rx_mbufs[requeue_idx] = xennet_get_rx_mbuf(np, i);
|
||||
ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
|
||||
req = RING_GET_REQUEST(&np->rx, requeue_idx);
|
||||
pfn = vtophys(mtod(m, vm_offset_t)) >> PAGE_SHIFT;
|
||||
|
||||
if (!np->copying_receiver) {
|
||||
gnttab_grant_foreign_transfer_ref(ref,
|
||||
xenbus_get_otherend_id(np->xbdev),
|
||||
vtophys(mtod(m, vm_offset_t)));
|
||||
pfn);
|
||||
} else {
|
||||
gnttab_grant_foreign_access_ref(ref,
|
||||
xenbus_get_otherend_id(np->xbdev),
|
||||
vtophys(mtod(m, vm_offset_t)), 0);
|
||||
PFNTOMFN(pfn), 0);
|
||||
}
|
||||
req->gref = ref;
|
||||
req->id = requeue_idx;
|
||||
@ -1707,7 +1702,7 @@ create_netdev(device_t dev)
|
||||
ifp = np->xn_ifp = if_alloc(IFT_ETHER);
|
||||
ifp->if_softc = np;
|
||||
if_initname(ifp, "xn", device_get_unit(dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_ioctl = xn_ioctl;
|
||||
ifp->if_output = ether_output;
|
||||
ifp->if_start = xn_start;
|
||||
@ -1777,11 +1772,14 @@ static void netif_free(struct netfront_info *info)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void netif_disconnect_backend(struct netfront_info *info)
|
||||
{
|
||||
xn_stop(info);
|
||||
XN_RX_LOCK(info);
|
||||
XN_TX_LOCK(info);
|
||||
netfront_carrier_off(info);
|
||||
XN_TX_UNLOCK(info);
|
||||
XN_RX_UNLOCK(info);
|
||||
|
||||
end_access(info->tx_ring_ref, info->tx.sring);
|
||||
end_access(info->rx_ring_ref, info->rx.sring);
|
||||
info->tx_ring_ref = GRANT_INVALID_REF;
|
||||
@ -1789,12 +1787,9 @@ static void netif_disconnect_backend(struct netfront_info *info)
|
||||
info->tx.sring = NULL;
|
||||
info->rx.sring = NULL;
|
||||
|
||||
#if 0
|
||||
if (info->irq)
|
||||
unbind_from_irqhandler(info->irq, info->netdev);
|
||||
#else
|
||||
panic("FIX ME");
|
||||
#endif
|
||||
unbind_from_irqhandler(info->irq);
|
||||
|
||||
info->irq = 0;
|
||||
}
|
||||
|
||||
|
@ -9,9 +9,9 @@ ident XEN
|
||||
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
|
||||
makeoptions MODULES_OVERRIDE=""
|
||||
|
||||
#options SCHED_ULE # ULE scheduler
|
||||
#options PREEMPTION # Enable kernel thread preemption
|
||||
options SCHED_4BSD
|
||||
options SCHED_ULE # ULE scheduler
|
||||
options PREEMPTION # Enable kernel thread preemption
|
||||
#options SCHED_4BSD
|
||||
|
||||
options INET # InterNETworking
|
||||
options INET6 # IPv6 communications protocols
|
||||
|
@ -234,7 +234,7 @@ ASSYM(BUS_SPACE_HANDLE_IAT, offsetof(struct bus_space_handle, bsh_iat));
|
||||
#endif
|
||||
|
||||
#ifdef XEN
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
ASSYM(PC_CR3, offsetof(struct pcpu, pc_cr3));
|
||||
ASSYM(HYPERVISOR_VIRT_START, __HYPERVISOR_VIRT_START);
|
||||
#endif
|
||||
|
@ -144,11 +144,11 @@ uint32_t arch_i386_xbox_memsize = 0;
|
||||
#ifdef XEN
|
||||
/* XEN includes */
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/xenvar.h>
|
||||
#include <machine/xen/xenfunc.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <xen/xen_intr.h>
|
||||
|
||||
void Xhypervisor_callback(void);
|
||||
void failsafe_callback(void);
|
||||
|
@ -89,7 +89,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#ifdef XEN
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#endif
|
||||
#ifdef PC98
|
||||
#include <pc98/cbus/cbus.h>
|
||||
|
@ -33,7 +33,7 @@
|
||||
#define _XEN_XENFUNC_H_
|
||||
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/xenpmap.h>
|
||||
#include <machine/segments.h>
|
||||
#include <sys/pcpu.h>
|
||||
|
@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/intr_machdep.h>
|
||||
#ifdef XEN
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEV_ISA
|
||||
|
@ -78,11 +78,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <i386/isa/isa.h>
|
||||
#include <isa/rtc.h>
|
||||
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/xenfunc.h>
|
||||
#include <xen/interface/vcpu.h>
|
||||
@ -791,18 +791,20 @@ static struct vcpu_set_periodic_timer xen_set_periodic_tick;
|
||||
void
|
||||
cpu_initclocks(void)
|
||||
{
|
||||
int time_irq;
|
||||
|
||||
unsigned int time_irq;
|
||||
int error;
|
||||
|
||||
xen_set_periodic_tick.period_ns = NS_PER_TICK;
|
||||
|
||||
HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
|
||||
&xen_set_periodic_tick);
|
||||
|
||||
if ((time_irq = bind_virq_to_irqhandler(VIRQ_TIMER, 0, "clk",
|
||||
clkintr, NULL,
|
||||
INTR_TYPE_CLK | INTR_FAST)) < 0) {
|
||||
|
||||
error = bind_virq_to_irqhandler(VIRQ_TIMER, 0, "clk",
|
||||
clkintr, NULL, NULL,
|
||||
INTR_TYPE_CLK | INTR_FAST, &time_irq);
|
||||
if (error)
|
||||
panic("failed to register clock interrupt\n");
|
||||
}
|
||||
|
||||
|
||||
/* should fast clock be enabled ? */
|
||||
|
||||
@ -811,18 +813,19 @@ cpu_initclocks(void)
|
||||
int
|
||||
ap_cpu_initclocks(int cpu)
|
||||
{
|
||||
int time_irq;
|
||||
unsigned int time_irq;
|
||||
int error;
|
||||
|
||||
xen_set_periodic_tick.period_ns = NS_PER_TICK;
|
||||
|
||||
HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
|
||||
&xen_set_periodic_tick);
|
||||
|
||||
if ((time_irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, "clk",
|
||||
clkintr2, NULL,
|
||||
INTR_TYPE_CLK | INTR_FAST)) < 0) {
|
||||
error = bind_virq_to_irqhandler(VIRQ_TIMER, 0, "clk",
|
||||
clkintr, NULL, NULL,
|
||||
INTR_TYPE_CLK | INTR_FAST, &time_irq);
|
||||
if (error)
|
||||
panic("failed to register clock interrupt\n");
|
||||
}
|
||||
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -85,9 +85,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/interface/vcpu.h>
|
||||
|
||||
#define stop_cpus_with_nmi 0
|
||||
@ -464,7 +464,8 @@ static int
|
||||
xen_smp_intr_init(unsigned int cpu)
|
||||
{
|
||||
int rc;
|
||||
|
||||
unsigned int irq;
|
||||
|
||||
per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1;
|
||||
|
||||
sprintf(resched_name[cpu], "resched%u", cpu);
|
||||
@ -472,22 +473,22 @@ xen_smp_intr_init(unsigned int cpu)
|
||||
cpu,
|
||||
resched_name[cpu],
|
||||
smp_reschedule_interrupt,
|
||||
INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE);
|
||||
INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE, &irq);
|
||||
|
||||
printf("cpu=%d irq=%d vector=%d\n",
|
||||
cpu, rc, RESCHEDULE_VECTOR);
|
||||
|
||||
per_cpu(resched_irq, cpu) = rc;
|
||||
per_cpu(resched_irq, cpu) = irq;
|
||||
|
||||
sprintf(callfunc_name[cpu], "callfunc%u", cpu);
|
||||
rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR,
|
||||
cpu,
|
||||
callfunc_name[cpu],
|
||||
smp_call_function_interrupt,
|
||||
INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE);
|
||||
INTR_FAST|INTR_TYPE_TTY|INTR_MPSAFE, &irq);
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
per_cpu(callfunc_irq, cpu) = rc;
|
||||
per_cpu(callfunc_irq, cpu) = irq;
|
||||
|
||||
printf("cpu=%d irq=%d vector=%d\n",
|
||||
cpu, rc, CALL_FUNCTION_VECTOR);
|
||||
@ -500,9 +501,9 @@ xen_smp_intr_init(unsigned int cpu)
|
||||
|
||||
fail:
|
||||
if (per_cpu(resched_irq, cpu) >= 0)
|
||||
unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(resched_irq, cpu));
|
||||
if (per_cpu(callfunc_irq, cpu) >= 0)
|
||||
unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL);
|
||||
unbind_from_irqhandler(per_cpu(callfunc_irq, cpu));
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/mptable.h>
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/smp.h>
|
||||
#include <xen/interface/vcpu.h>
|
||||
|
@ -154,7 +154,7 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/hypercall.h>
|
||||
#include <machine/xen/xenvar.h>
|
||||
#include <machine/xen/xenfunc.h>
|
||||
|
@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/xenvar.h>
|
||||
#include <machine/xen/xenfunc.h>
|
||||
#include <machine/xen/xenpmap.h>
|
||||
|
@ -12,7 +12,7 @@
|
||||
#ifndef __ASM_EVTCHN_H__
|
||||
#define __ASM_EVTCHN_H__
|
||||
#include <machine/pcpu.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/synch_bitops.h>
|
||||
#include <machine/frame.h>
|
||||
|
@ -23,10 +23,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <machine/xen/synch_bitops.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <sys/smp.h>
|
||||
|
||||
|
||||
@ -76,6 +76,7 @@ static struct mtx irq_mapping_update_lock;
|
||||
static struct xenpic *xp;
|
||||
struct xenpic_intsrc {
|
||||
struct intsrc xp_intsrc;
|
||||
void *xp_cookie;
|
||||
uint8_t xp_vector;
|
||||
boolean_t xp_masked;
|
||||
};
|
||||
@ -295,6 +296,7 @@ bind_caller_port_to_irq(unsigned int caller_port)
|
||||
}
|
||||
|
||||
irq_bindcount[irq]++;
|
||||
unmask_evtchn(caller_port);
|
||||
|
||||
out:
|
||||
mtx_unlock_spin(&irq_mapping_update_lock);
|
||||
@ -320,6 +322,7 @@ bind_local_port_to_irq(unsigned int local_port)
|
||||
evtchn_to_irq[local_port] = irq;
|
||||
irq_info[irq] = mk_irq_info(IRQT_LOCAL_PORT, 0, local_port);
|
||||
irq_bindcount[irq]++;
|
||||
unmask_evtchn(local_port);
|
||||
|
||||
out:
|
||||
mtx_unlock_spin(&irq_mapping_update_lock);
|
||||
@ -361,7 +364,7 @@ static int
|
||||
bind_virq_to_irq(unsigned int virq, unsigned int cpu)
|
||||
{
|
||||
struct evtchn_bind_virq bind_virq;
|
||||
int evtchn, irq;
|
||||
int evtchn = 0, irq;
|
||||
|
||||
mtx_lock_spin(&irq_mapping_update_lock);
|
||||
|
||||
@ -385,6 +388,7 @@ bind_virq_to_irq(unsigned int virq, unsigned int cpu)
|
||||
}
|
||||
|
||||
irq_bindcount[irq]++;
|
||||
unmask_evtchn(evtchn);
|
||||
out:
|
||||
mtx_unlock_spin(&irq_mapping_update_lock);
|
||||
|
||||
@ -398,8 +402,9 @@ int
|
||||
bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
|
||||
{
|
||||
struct evtchn_bind_ipi bind_ipi;
|
||||
int evtchn, irq;
|
||||
|
||||
int irq;
|
||||
int evtchn = 0;
|
||||
|
||||
mtx_lock_spin(&irq_mapping_update_lock);
|
||||
|
||||
if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) {
|
||||
@ -418,6 +423,7 @@ bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
|
||||
bind_evtchn_to_cpu(evtchn, cpu);
|
||||
}
|
||||
irq_bindcount[irq]++;
|
||||
unmask_evtchn(evtchn);
|
||||
out:
|
||||
|
||||
mtx_unlock_spin(&irq_mapping_update_lock);
|
||||
@ -465,20 +471,25 @@ bind_caller_port_to_irqhandler(unsigned int caller_port,
|
||||
driver_intr_t handler,
|
||||
void *arg,
|
||||
unsigned long irqflags,
|
||||
void **cookiep)
|
||||
unsigned int *irqp)
|
||||
{
|
||||
unsigned int irq;
|
||||
int retval;
|
||||
int error;
|
||||
|
||||
irq = bind_caller_port_to_irq(caller_port);
|
||||
intr_register_source(&xp->xp_pins[irq].xp_intsrc);
|
||||
retval = intr_add_handler(devname, irq, NULL, handler, arg, irqflags, cookiep);
|
||||
if (retval != 0) {
|
||||
error = intr_add_handler(devname, irq, NULL, handler, arg, irqflags,
|
||||
&xp->xp_pins[irq].xp_cookie);
|
||||
|
||||
if (error) {
|
||||
unbind_from_irq(irq);
|
||||
return -retval;
|
||||
return (error);
|
||||
}
|
||||
|
||||
return irq;
|
||||
if (irqp)
|
||||
*irqp = irq;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -488,43 +499,50 @@ bind_listening_port_to_irqhandler(
|
||||
driver_intr_t handler,
|
||||
void *arg,
|
||||
unsigned long irqflags,
|
||||
void **cookiep)
|
||||
unsigned int *irqp)
|
||||
{
|
||||
unsigned int irq;
|
||||
int retval;
|
||||
int error;
|
||||
|
||||
irq = bind_listening_port_to_irq(remote_domain);
|
||||
intr_register_source(&xp->xp_pins[irq].xp_intsrc);
|
||||
retval = intr_add_handler(devname, irq, NULL, handler, arg, irqflags, cookiep);
|
||||
if (retval != 0) {
|
||||
error = intr_add_handler(devname, irq, NULL, handler, arg, irqflags,
|
||||
&xp->xp_pins[irq].xp_cookie);
|
||||
if (error) {
|
||||
unbind_from_irq(irq);
|
||||
return -retval;
|
||||
return (error);
|
||||
}
|
||||
|
||||
return irq;
|
||||
if (irqp)
|
||||
*irqp = irq;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
bind_interdomain_evtchn_to_irqhandler(
|
||||
unsigned int remote_domain,
|
||||
unsigned int remote_port,
|
||||
const char *devname,
|
||||
driver_filter_t filter,
|
||||
driver_intr_t handler,
|
||||
unsigned long irqflags)
|
||||
unsigned int remote_domain,
|
||||
unsigned int remote_port,
|
||||
const char *devname,
|
||||
driver_filter_t filter,
|
||||
driver_intr_t handler,
|
||||
unsigned long irqflags,
|
||||
unsigned int *irqp)
|
||||
{
|
||||
unsigned int irq;
|
||||
int retval;
|
||||
int error;
|
||||
|
||||
irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port);
|
||||
intr_register_source(&xp->xp_pins[irq].xp_intsrc);
|
||||
retval = intr_add_handler(devname, irq, filter, handler, NULL, irqflags, NULL);
|
||||
if (retval != 0) {
|
||||
error = intr_add_handler(devname, irq, filter, handler, NULL,
|
||||
irqflags, &xp->xp_pins[irq].xp_cookie);
|
||||
if (error) {
|
||||
unbind_from_irq(irq);
|
||||
return -retval;
|
||||
return (error);
|
||||
}
|
||||
|
||||
return irq;
|
||||
if (irqp)
|
||||
*irqp = irq;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -533,20 +551,25 @@ bind_virq_to_irqhandler(unsigned int virq,
|
||||
const char *devname,
|
||||
driver_filter_t filter,
|
||||
driver_intr_t handler,
|
||||
unsigned long irqflags)
|
||||
void *arg,
|
||||
unsigned long irqflags,
|
||||
unsigned int *irqp)
|
||||
{
|
||||
unsigned int irq;
|
||||
int retval;
|
||||
int error;
|
||||
|
||||
irq = bind_virq_to_irq(virq, cpu);
|
||||
intr_register_source(&xp->xp_pins[irq].xp_intsrc);
|
||||
retval = intr_add_handler(devname, irq, filter, handler, NULL, irqflags, NULL);
|
||||
if (retval != 0) {
|
||||
error = intr_add_handler(devname, irq, filter, handler,
|
||||
arg, irqflags, &xp->xp_pins[irq].xp_cookie);
|
||||
if (error) {
|
||||
unbind_from_irq(irq);
|
||||
return -retval;
|
||||
return (error);
|
||||
}
|
||||
|
||||
return irq;
|
||||
if (irqp)
|
||||
*irqp = irq;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -554,27 +577,30 @@ bind_ipi_to_irqhandler(unsigned int ipi,
|
||||
unsigned int cpu,
|
||||
const char *devname,
|
||||
driver_filter_t filter,
|
||||
unsigned long irqflags)
|
||||
unsigned long irqflags,
|
||||
unsigned int *irqp)
|
||||
{
|
||||
int irq, retval;
|
||||
unsigned int irq;
|
||||
int error;
|
||||
|
||||
irq = bind_ipi_to_irq(ipi, cpu);
|
||||
intr_register_source(&xp->xp_pins[irq].xp_intsrc);
|
||||
retval = intr_add_handler(devname, irq, filter, NULL,
|
||||
NULL, irqflags, NULL);
|
||||
if (retval != 0) {
|
||||
error = intr_add_handler(devname, irq, filter, NULL,
|
||||
NULL, irqflags, &xp->xp_pins[irq].xp_cookie);
|
||||
if (error) {
|
||||
unbind_from_irq(irq);
|
||||
return -retval;
|
||||
return (error);
|
||||
}
|
||||
|
||||
return irq;
|
||||
if (irqp)
|
||||
*irqp = irq;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
unbind_from_irqhandler(unsigned int irq, void *dev_id)
|
||||
unbind_from_irqhandler(unsigned int irq)
|
||||
{
|
||||
if (dev_id)
|
||||
intr_remove_handler(dev_id); /* XXX */
|
||||
intr_remove_handler(xp->xp_pins[irq].xp_cookie);
|
||||
unbind_from_irq(irq);
|
||||
}
|
||||
|
||||
|
@ -26,13 +26,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <xen/xen_intr.h>
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/xen/synch_bitops.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/evtchn.h>
|
||||
|
||||
|
||||
typedef struct evtchn_sotfc {
|
||||
|
@ -3,7 +3,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/features.h>
|
||||
|
||||
uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32] /* __read_mostly */;
|
||||
|
@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_kern.h>
|
||||
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/synch_bitops.h>
|
||||
#include <xen/gnttab.h>
|
||||
|
||||
@ -70,14 +70,14 @@ static int gnttab_expand(unsigned int req_entries);
|
||||
#define gnttab_entry(entry) (gnttab_list[(entry) / RPP][(entry) % RPP])
|
||||
|
||||
static int
|
||||
get_free_entries(int count)
|
||||
get_free_entries(int count, int *entries)
|
||||
{
|
||||
int ref, rc;
|
||||
grant_ref_t head;
|
||||
|
||||
mtx_lock(&gnttab_list_lock);
|
||||
if ((gnttab_free_count < count) &&
|
||||
((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
|
||||
((rc = gnttab_expand(count - gnttab_free_count)) != 0)) {
|
||||
mtx_unlock(&gnttab_list_lock);
|
||||
return (rc);
|
||||
}
|
||||
@ -88,10 +88,10 @@ get_free_entries(int count)
|
||||
gnttab_free_head = gnttab_entry(head);
|
||||
gnttab_entry(head) = GNTTAB_LIST_END;
|
||||
mtx_unlock(&gnttab_list_lock);
|
||||
return (ref);
|
||||
}
|
||||
|
||||
#define get_free_entry() get_free_entries(1)
|
||||
*entries = ref;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
do_free_callbacks(void)
|
||||
@ -138,19 +138,25 @@ put_free_entry(grant_ref_t ref)
|
||||
*/
|
||||
|
||||
int
|
||||
gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly)
|
||||
gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly,
|
||||
grant_ref_t *result)
|
||||
{
|
||||
int ref;
|
||||
int error, ref;
|
||||
|
||||
if (unlikely((ref = get_free_entry()) == -1))
|
||||
return -ENOSPC;
|
||||
error = get_free_entries(1, &ref);
|
||||
|
||||
if (unlikely(error))
|
||||
return (error);
|
||||
|
||||
shared[ref].frame = frame;
|
||||
shared[ref].domid = domid;
|
||||
wmb();
|
||||
shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
|
||||
|
||||
return ref;
|
||||
if (result)
|
||||
*result = ref;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -209,10 +215,11 @@ gnttab_end_foreign_access(grant_ref_t ref, void *page)
|
||||
int
|
||||
gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
|
||||
{
|
||||
int ref;
|
||||
|
||||
if (unlikely((ref = get_free_entry()) == -1))
|
||||
return -ENOSPC;
|
||||
int error, ref;
|
||||
|
||||
error = get_free_entries(1, &ref);
|
||||
if (unlikely(error))
|
||||
return (error);
|
||||
|
||||
gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
|
||||
|
||||
@ -300,14 +307,14 @@ gnttab_free_grant_references(grant_ref_t head)
|
||||
int
|
||||
gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head)
|
||||
{
|
||||
int h = get_free_entries(count);
|
||||
int ref, error;
|
||||
|
||||
if (h == -1)
|
||||
return -ENOSPC;
|
||||
error = get_free_entries(count, &ref);
|
||||
if (unlikely(error))
|
||||
return (error);
|
||||
|
||||
*head = h;
|
||||
|
||||
return 0;
|
||||
*head = ref;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -322,7 +329,7 @@ gnttab_claim_grant_reference(grant_ref_t *private_head)
|
||||
grant_ref_t g = *private_head;
|
||||
|
||||
if (unlikely(g == GNTTAB_LIST_END))
|
||||
return -ENOSPC;
|
||||
return (ENOSPC);
|
||||
*private_head = gnttab_entry(g);
|
||||
|
||||
return (g);
|
||||
@ -468,7 +475,7 @@ gnttab_map(unsigned int start_idx, unsigned int end_idx)
|
||||
|
||||
frames = malloc(nr_gframes * sizeof(unsigned long), M_DEVBUF, M_NOWAIT);
|
||||
if (!frames)
|
||||
return -ENOMEM;
|
||||
return (ENOMEM);
|
||||
|
||||
setup.dom = DOMID_SELF;
|
||||
setup.nr_frames = nr_gframes;
|
||||
@ -477,7 +484,7 @@ gnttab_map(unsigned int start_idx, unsigned int end_idx)
|
||||
rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
|
||||
if (rc == -ENOSYS) {
|
||||
free(frames, M_DEVBUF);
|
||||
return -ENOSYS;
|
||||
return (ENOSYS);
|
||||
}
|
||||
PANIC_IF(rc || setup.status);
|
||||
|
||||
@ -529,7 +536,7 @@ gnttab_expand(unsigned int req_entries)
|
||||
extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
|
||||
GREFS_PER_GRANT_FRAME);
|
||||
if (cur + extra > max_nr_grant_frames())
|
||||
return -ENOSPC;
|
||||
return (ENOSPC);
|
||||
|
||||
if ((rc = gnttab_map(cur, cur + extra - 1)) == 0)
|
||||
rc = grow_gnttab_list(extra);
|
||||
@ -561,7 +568,7 @@ gnttab_init()
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
|
||||
if (gnttab_list == NULL)
|
||||
return -ENOMEM;
|
||||
return (ENOMEM);
|
||||
|
||||
for (i = 0; i < nr_grant_frames; i++) {
|
||||
gnttab_list[i] = (grant_ref_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
|
||||
@ -569,8 +576,8 @@ gnttab_init()
|
||||
goto ini_nomem;
|
||||
}
|
||||
|
||||
if (gnttab_resume() < 0)
|
||||
return -ENODEV;
|
||||
if (gnttab_resume())
|
||||
return (ENODEV);
|
||||
|
||||
nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
|
||||
|
||||
@ -588,7 +595,7 @@ gnttab_init()
|
||||
for (i--; i >= 0; i--)
|
||||
free(gnttab_list[i], M_DEVBUF);
|
||||
free(gnttab_list, M_DEVBUF);
|
||||
return -ENOMEM;
|
||||
return (ENOMEM);
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,10 +36,9 @@
|
||||
|
||||
#ifndef __ASM_GNTTAB_H__
|
||||
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/interface/grant_table.h>
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <machine/xen/features.h>
|
||||
|
||||
struct gnttab_free_callback {
|
||||
@ -52,7 +51,7 @@ struct gnttab_free_callback {
|
||||
int gnttab_init(void);
|
||||
|
||||
int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
|
||||
int flags);
|
||||
int flags, grant_ref_t *result);
|
||||
|
||||
/*
|
||||
* End access through the given grant reference, iff the grant entry is no
|
||||
|
@ -4,6 +4,8 @@
|
||||
* Linux-specific hypervisor handling.
|
||||
*
|
||||
* Copyright (c) 2002, K A Fraser
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __HYPERVISOR_H__
|
@ -34,28 +34,31 @@ extern void unbind_from_irq(int irq);
|
||||
|
||||
extern int bind_caller_port_to_irqhandler(unsigned int caller_port,
|
||||
const char *devname, driver_intr_t handler, void *arg,
|
||||
unsigned long irqflags, void **cookiep);
|
||||
unsigned long irqflags, unsigned int *irqp);
|
||||
extern int bind_listening_port_to_irqhandler(unsigned int remote_domain,
|
||||
const char *devname, driver_intr_t handler, void *arg, unsigned long irqflags,
|
||||
void **cookiep);
|
||||
extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, const char *devname,
|
||||
driver_filter_t filter, driver_intr_t handler, unsigned long irqflags);
|
||||
unsigned int *irqp);
|
||||
extern int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
|
||||
const char *devname, driver_filter_t filter, driver_intr_t handler,
|
||||
void *arg, unsigned long irqflags, unsigned int *irqp);
|
||||
extern int bind_ipi_to_irqhandler(unsigned int ipi,
|
||||
unsigned int cpu,
|
||||
const char *devname,
|
||||
driver_filter_t handler,
|
||||
unsigned long irqflags);
|
||||
unsigned long irqflags,
|
||||
unsigned int *irqp);
|
||||
|
||||
extern int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
|
||||
unsigned int remote_port,
|
||||
const char *devname,
|
||||
driver_filter_t filter,
|
||||
driver_intr_t handler,
|
||||
unsigned long irqflags);
|
||||
unsigned long irqflags,
|
||||
unsigned int *irqp);
|
||||
|
||||
|
||||
|
||||
extern void unbind_from_irqhandler(unsigned int evtchn, void *dev_id);
|
||||
extern void unbind_from_irqhandler(unsigned int evtchn);
|
||||
static __inline__ int irq_cannonicalize(int irq)
|
||||
{
|
||||
return (irq == 2) ? 9 : irq;
|
@ -44,19 +44,14 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/libkern.h>
|
||||
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/gnttab.h>
|
||||
#include <xen/xenbus/xenbusvar.h>
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
|
||||
#define EXPORT_SYMBOL(x)
|
||||
#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
|
||||
#define kfree(ptr) free(ptr, M_DEVBUF)
|
||||
#define BUG_ON PANIC_IF
|
||||
|
||||
|
||||
const char *xenbus_strstate(XenbusState state)
|
||||
const char *
|
||||
xenbus_strstate(XenbusState state)
|
||||
{
|
||||
static const char *const name[] = {
|
||||
[ XenbusStateUnknown ] = "Unknown",
|
||||
@ -67,121 +62,108 @@ const char *xenbus_strstate(XenbusState state)
|
||||
[ XenbusStateClosing ] = "Closing",
|
||||
[ XenbusStateClosed ] = "Closed",
|
||||
};
|
||||
return (state < (XenbusStateClosed + 1)) ? name[state] : "INVALID";
|
||||
|
||||
return ((state < (XenbusStateClosed + 1)) ? name[state] : "INVALID");
|
||||
}
|
||||
|
||||
int
|
||||
xenbus_watch_path(device_t dev, char *path,
|
||||
struct xenbus_watch *watch,
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char **, unsigned int))
|
||||
xenbus_watch_path(device_t dev, char *path, struct xenbus_watch *watch,
|
||||
void (*callback)(struct xenbus_watch *, const char **, unsigned int))
|
||||
{
|
||||
int err;
|
||||
int error;
|
||||
|
||||
watch->node = path;
|
||||
watch->callback = callback;
|
||||
|
||||
err = register_xenbus_watch(watch);
|
||||
error = register_xenbus_watch(watch);
|
||||
|
||||
if (err) {
|
||||
if (error) {
|
||||
watch->node = NULL;
|
||||
watch->callback = NULL;
|
||||
xenbus_dev_fatal(dev, err, "adding watch on %s", path);
|
||||
xenbus_dev_fatal(dev, error, "adding watch on %s", path);
|
||||
}
|
||||
|
||||
return err;
|
||||
return (error);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_watch_path);
|
||||
|
||||
|
||||
int xenbus_watch_path2(device_t dev, const char *path,
|
||||
const char *path2, struct xenbus_watch *watch,
|
||||
void (*callback)(struct xenbus_watch *,
|
||||
const char **, unsigned int))
|
||||
int
|
||||
xenbus_watch_path2(device_t dev, const char *path,
|
||||
const char *path2, struct xenbus_watch *watch,
|
||||
void (*callback)(struct xenbus_watch *, const char **, unsigned int))
|
||||
{
|
||||
int err;
|
||||
char *state =
|
||||
kmalloc(strlen(path) + 1 + strlen(path2) + 1, GFP_KERNEL);
|
||||
if (!state) {
|
||||
xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
|
||||
return -ENOMEM;
|
||||
}
|
||||
int error;
|
||||
char *state = malloc(strlen(path) + 1 + strlen(path2) + 1,
|
||||
M_DEVBUF, M_WAITOK);
|
||||
|
||||
strcpy(state, path);
|
||||
strcat(state, "/");
|
||||
strcat(state, path2);
|
||||
|
||||
err = xenbus_watch_path(dev, state, watch, callback);
|
||||
|
||||
if (err) {
|
||||
kfree(state);
|
||||
error = xenbus_watch_path(dev, state, watch, callback);
|
||||
if (error) {
|
||||
free(state, M_DEVBUF);
|
||||
}
|
||||
return err;
|
||||
|
||||
return (error);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_watch_path2);
|
||||
|
||||
/**
|
||||
* Return the path to the error node for the given device, or NULL on failure.
|
||||
* If the value returned is non-NULL, then it is the caller's to kfree.
|
||||
*/
|
||||
static char *error_path(device_t dev)
|
||||
static char *
|
||||
error_path(device_t dev)
|
||||
{
|
||||
char *path_buffer = kmalloc(strlen("error/")
|
||||
+ strlen(xenbus_get_node(dev)) +
|
||||
1, GFP_KERNEL);
|
||||
if (path_buffer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
char *path_buffer = malloc(strlen("error/")
|
||||
+ strlen(xenbus_get_node(dev)) + 1, M_DEVBUF, M_WAITOK);
|
||||
|
||||
strcpy(path_buffer, "error/");
|
||||
strcpy(path_buffer + strlen("error/"), xenbus_get_node(dev));
|
||||
|
||||
return path_buffer;
|
||||
return (path_buffer);
|
||||
}
|
||||
|
||||
|
||||
static void _dev_error(device_t dev, int err, const char *fmt,
|
||||
va_list ap)
|
||||
static void
|
||||
_dev_error(device_t dev, int err, const char *fmt, va_list ap)
|
||||
{
|
||||
int ret;
|
||||
unsigned int len;
|
||||
char *printf_buffer = NULL, *path_buffer = NULL;
|
||||
|
||||
#define PRINTF_BUFFER_SIZE 4096
|
||||
printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
|
||||
if (printf_buffer == NULL)
|
||||
goto fail;
|
||||
printf_buffer = malloc(PRINTF_BUFFER_SIZE, M_DEVBUF, M_WAITOK);
|
||||
|
||||
len = sprintf(printf_buffer, "%i ", -err);
|
||||
len = sprintf(printf_buffer, "%i ", err);
|
||||
ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
|
||||
|
||||
BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
|
||||
KASSERT(len + ret <= PRINTF_BUFFER_SIZE-1, ("xenbus error message too big"));
|
||||
#if 0
|
||||
dev_err(&dev->dev, "%s\n", printf_buffer);
|
||||
#endif
|
||||
path_buffer = error_path(dev);
|
||||
|
||||
if (path_buffer == NULL) {
|
||||
printk("xenbus: failed to write error node for %s (%s)\n",
|
||||
printf("xenbus: failed to write error node for %s (%s)\n",
|
||||
xenbus_get_node(dev), printf_buffer);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
|
||||
printk("xenbus: failed to write error node for %s (%s)\n",
|
||||
printf("xenbus: failed to write error node for %s (%s)\n",
|
||||
xenbus_get_node(dev), printf_buffer);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (printf_buffer)
|
||||
kfree(printf_buffer);
|
||||
free(printf_buffer, M_DEVBUF);
|
||||
if (path_buffer)
|
||||
kfree(path_buffer);
|
||||
free(path_buffer, M_DEVBUF);
|
||||
}
|
||||
|
||||
|
||||
void xenbus_dev_error(device_t dev, int err, const char *fmt,
|
||||
...)
|
||||
void
|
||||
xenbus_dev_error(device_t dev, int err, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@ -189,11 +171,9 @@ void xenbus_dev_error(device_t dev, int err, const char *fmt,
|
||||
_dev_error(dev, err, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_dev_error);
|
||||
|
||||
|
||||
void xenbus_dev_fatal(device_t dev, int err, const char *fmt,
|
||||
...)
|
||||
void
|
||||
xenbus_dev_fatal(device_t dev, int err, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
@ -203,21 +183,26 @@ void xenbus_dev_fatal(device_t dev, int err, const char *fmt,
|
||||
|
||||
xenbus_set_state(dev, XenbusStateClosing);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_dev_fatal);
|
||||
|
||||
|
||||
int xenbus_grant_ring(device_t dev, unsigned long ring_mfn)
|
||||
int
|
||||
xenbus_grant_ring(device_t dev, unsigned long ring_mfn, int *refp)
|
||||
{
|
||||
int err = gnttab_grant_foreign_access(
|
||||
xenbus_get_otherend_id(dev), ring_mfn, 0);
|
||||
if (err < 0)
|
||||
xenbus_dev_fatal(dev, err, "granting access to ring page");
|
||||
return err;
|
||||
int error;
|
||||
grant_ref_t ref;
|
||||
|
||||
error = gnttab_grant_foreign_access(
|
||||
xenbus_get_otherend_id(dev), ring_mfn, 0, &ref);
|
||||
if (error) {
|
||||
xenbus_dev_fatal(dev, error, "granting access to ring page");
|
||||
return (error);
|
||||
}
|
||||
|
||||
*refp = ref;
|
||||
return (0);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_grant_ring);
|
||||
|
||||
|
||||
int xenbus_alloc_evtchn(device_t dev, int *port)
|
||||
int
|
||||
xenbus_alloc_evtchn(device_t dev, int *port)
|
||||
{
|
||||
struct evtchn_alloc_unbound alloc_unbound;
|
||||
int err;
|
||||
@ -228,16 +213,16 @@ int xenbus_alloc_evtchn(device_t dev, int *port)
|
||||
err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
|
||||
&alloc_unbound);
|
||||
|
||||
if (err)
|
||||
xenbus_dev_fatal(dev, err, "allocating event channel");
|
||||
else
|
||||
*port = alloc_unbound.port;
|
||||
return err;
|
||||
if (err) {
|
||||
xenbus_dev_fatal(dev, -err, "allocating event channel");
|
||||
return (-err);
|
||||
}
|
||||
*port = alloc_unbound.port;
|
||||
return (0);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_alloc_evtchn);
|
||||
|
||||
|
||||
int xenbus_free_evtchn(device_t dev, int port)
|
||||
int
|
||||
xenbus_free_evtchn(device_t dev, int port)
|
||||
{
|
||||
struct evtchn_close close;
|
||||
int err;
|
||||
@ -245,32 +230,22 @@ int xenbus_free_evtchn(device_t dev, int port)
|
||||
close.port = port;
|
||||
|
||||
err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
|
||||
if (err)
|
||||
xenbus_dev_error(dev, err, "freeing event channel %d", port);
|
||||
return err;
|
||||
if (err) {
|
||||
xenbus_dev_error(dev, -err, "freeing event channel %d", port);
|
||||
return (-err);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_free_evtchn);
|
||||
|
||||
|
||||
XenbusState xenbus_read_driver_state(const char *path)
|
||||
XenbusState
|
||||
xenbus_read_driver_state(const char *path)
|
||||
{
|
||||
XenbusState result;
|
||||
int error;
|
||||
|
||||
int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
|
||||
if (err)
|
||||
error = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
|
||||
if (error)
|
||||
result = XenbusStateClosed;
|
||||
|
||||
return result;
|
||||
return (result);
|
||||
}
|
||||
EXPORT_SYMBOL(xenbus_read_driver_state);
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -33,217 +33,194 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <machine/xen/xen_intr.h>
|
||||
#include <xen/xenbus/xenbus_comms.h>
|
||||
#include <xen/hypervisor.h>
|
||||
|
||||
#include <xen/xen_intr.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/interface/io/xs_wire.h>
|
||||
#include <xen/xenbus/xenbus_comms.h>
|
||||
|
||||
static int xenbus_irq;
|
||||
static unsigned int xenstore_irq;
|
||||
|
||||
extern void xenbus_probe(void *);
|
||||
extern int xenstored_ready;
|
||||
#if 0
|
||||
static DECLARE_WORK(probe_work, xenbus_probe, NULL);
|
||||
#endif
|
||||
int xb_wait;
|
||||
extern char *xen_store;
|
||||
#define wake_up wakeup
|
||||
#define xb_waitq xb_wait
|
||||
#define pr_debug(a,b,c)
|
||||
|
||||
static inline struct xenstore_domain_interface *xenstore_domain_interface(void)
|
||||
static inline struct xenstore_domain_interface *
|
||||
xenstore_domain_interface(void)
|
||||
{
|
||||
return (struct xenstore_domain_interface *)xen_store;
|
||||
|
||||
return (struct xenstore_domain_interface *)xen_store;
|
||||
}
|
||||
|
||||
static void
|
||||
wake_waiting(void * arg __attribute__((unused)))
|
||||
xb_intr(void * arg __attribute__((unused)))
|
||||
{
|
||||
#if 0
|
||||
if (unlikely(xenstored_ready == 0)) {
|
||||
xenstored_ready = 1;
|
||||
schedule_work(&probe_work);
|
||||
}
|
||||
#endif
|
||||
wakeup(&xb_wait);
|
||||
|
||||
wakeup(xen_store);
|
||||
}
|
||||
|
||||
static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
|
||||
static int
|
||||
xb_check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
|
||||
{
|
||||
return ((prod - cons) <= XENSTORE_RING_SIZE);
|
||||
|
||||
return ((prod - cons) <= XENSTORE_RING_SIZE);
|
||||
}
|
||||
|
||||
static void *get_output_chunk(XENSTORE_RING_IDX cons,
|
||||
XENSTORE_RING_IDX prod,
|
||||
char *buf, uint32_t *len)
|
||||
static void *
|
||||
xb_get_output_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
|
||||
char *buf, uint32_t *len)
|
||||
{
|
||||
*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
|
||||
if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
|
||||
*len = XENSTORE_RING_SIZE - (prod - cons);
|
||||
return buf + MASK_XENSTORE_IDX(prod);
|
||||
|
||||
*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
|
||||
if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
|
||||
*len = XENSTORE_RING_SIZE - (prod - cons);
|
||||
return (buf + MASK_XENSTORE_IDX(prod));
|
||||
}
|
||||
|
||||
static const void *get_input_chunk(XENSTORE_RING_IDX cons,
|
||||
XENSTORE_RING_IDX prod,
|
||||
const char *buf, uint32_t *len)
|
||||
static const void *
|
||||
xb_get_input_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
|
||||
const char *buf, uint32_t *len)
|
||||
{
|
||||
*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
|
||||
if ((prod - cons) < *len)
|
||||
*len = prod - cons;
|
||||
return buf + MASK_XENSTORE_IDX(cons);
|
||||
|
||||
*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
|
||||
if ((prod - cons) < *len)
|
||||
*len = prod - cons;
|
||||
return (buf + MASK_XENSTORE_IDX(cons));
|
||||
}
|
||||
|
||||
int xb_write(const void *tdata, unsigned len)
|
||||
int
|
||||
xb_write(const void *tdata, unsigned len, struct lock_object *lock)
|
||||
{
|
||||
struct xenstore_domain_interface *intf = xenstore_domain_interface();
|
||||
XENSTORE_RING_IDX cons, prod;
|
||||
const char *data = (const char *)tdata;
|
||||
struct xenstore_domain_interface *intf = xenstore_domain_interface();
|
||||
XENSTORE_RING_IDX cons, prod;
|
||||
const char *data = (const char *)tdata;
|
||||
int error;
|
||||
|
||||
while (len != 0) {
|
||||
void *dst;
|
||||
unsigned int avail;
|
||||
while (len != 0) {
|
||||
void *dst;
|
||||
unsigned int avail;
|
||||
|
||||
wait_event_interruptible(&xb_waitq,
|
||||
(intf->req_prod - intf->req_cons) !=
|
||||
XENSTORE_RING_SIZE);
|
||||
|
||||
/* Read indexes, then verify. */
|
||||
cons = intf->req_cons;
|
||||
prod = intf->req_prod;
|
||||
mb();
|
||||
if (!check_indexes(cons, prod)) {
|
||||
intf->req_cons = intf->req_prod = 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dst = get_output_chunk(cons, prod, intf->req, &avail);
|
||||
if (avail == 0)
|
||||
continue;
|
||||
if (avail > len)
|
||||
avail = len;
|
||||
mb();
|
||||
|
||||
memcpy(dst, data, avail);
|
||||
data += avail;
|
||||
len -= avail;
|
||||
|
||||
/* Other side must not see new header until data is there. */
|
||||
wmb();
|
||||
intf->req_prod += avail;
|
||||
|
||||
/* This implies mb() before other side sees interrupt. */
|
||||
notify_remote_via_evtchn(xen_start_info->store_evtchn);
|
||||
while ((intf->req_prod - intf->req_cons)
|
||||
== XENSTORE_RING_SIZE) {
|
||||
error = _sleep(intf,
|
||||
lock,
|
||||
PCATCH, "xbwrite", hz/10);
|
||||
if (error && error != EWOULDBLOCK)
|
||||
return (error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
int xb_data_to_read(void)
|
||||
{
|
||||
struct xenstore_domain_interface *intf = xen_store_interface;
|
||||
return (intf->rsp_cons != intf->rsp_prod);
|
||||
}
|
||||
|
||||
int xb_wait_for_data_to_read(void)
|
||||
{
|
||||
return wait_event_interruptible(xb_waitq, xb_data_to_read());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int xb_read(void *tdata, unsigned len)
|
||||
{
|
||||
struct xenstore_domain_interface *intf = xenstore_domain_interface();
|
||||
XENSTORE_RING_IDX cons, prod;
|
||||
char *data = (char *)tdata;
|
||||
|
||||
while (len != 0) {
|
||||
unsigned int avail;
|
||||
const char *src;
|
||||
|
||||
wait_event_interruptible(&xb_waitq,
|
||||
intf->rsp_cons != intf->rsp_prod);
|
||||
|
||||
/* Read indexes, then verify. */
|
||||
cons = intf->rsp_cons;
|
||||
prod = intf->rsp_prod;
|
||||
if (!check_indexes(cons, prod)) {
|
||||
intf->rsp_cons = intf->rsp_prod = 0;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
src = get_input_chunk(cons, prod, intf->rsp, &avail);
|
||||
if (avail == 0)
|
||||
continue;
|
||||
if (avail > len)
|
||||
avail = len;
|
||||
|
||||
/* We must read header before we read data. */
|
||||
rmb();
|
||||
|
||||
memcpy(data, src, avail);
|
||||
data += avail;
|
||||
len -= avail;
|
||||
|
||||
/* Other side must not see free space until we've copied out */
|
||||
mb();
|
||||
intf->rsp_cons += avail;
|
||||
|
||||
pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
|
||||
|
||||
/* Implies mb(): they will see new header. */
|
||||
notify_remote_via_evtchn(xen_start_info->store_evtchn);
|
||||
/* Read indexes, then verify. */
|
||||
cons = intf->req_cons;
|
||||
prod = intf->req_prod;
|
||||
mb();
|
||||
if (!xb_check_indexes(cons, prod)) {
|
||||
intf->req_cons = intf->req_prod = 0;
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
return 0;
|
||||
dst = xb_get_output_chunk(cons, prod, intf->req, &avail);
|
||||
if (avail == 0)
|
||||
continue;
|
||||
if (avail > len)
|
||||
avail = len;
|
||||
mb();
|
||||
|
||||
memcpy(dst, data, avail);
|
||||
data += avail;
|
||||
len -= avail;
|
||||
|
||||
/* Other side must not see new header until data is there. */
|
||||
wmb();
|
||||
intf->req_prod += avail;
|
||||
|
||||
/* This implies mb() before other side sees interrupt. */
|
||||
notify_remote_via_evtchn(xen_store_evtchn);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
xb_read(void *tdata, unsigned len, struct lock_object *lock)
|
||||
{
|
||||
struct xenstore_domain_interface *intf = xenstore_domain_interface();
|
||||
XENSTORE_RING_IDX cons, prod;
|
||||
char *data = (char *)tdata;
|
||||
int error;
|
||||
|
||||
while (len != 0) {
|
||||
unsigned int avail;
|
||||
const char *src;
|
||||
|
||||
while (intf->rsp_cons == intf->rsp_prod) {
|
||||
error = _sleep(intf, lock,
|
||||
PCATCH, "xbread", hz/10);
|
||||
if (error && error != EWOULDBLOCK)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Read indexes, then verify. */
|
||||
cons = intf->rsp_cons;
|
||||
prod = intf->rsp_prod;
|
||||
if (!xb_check_indexes(cons, prod)) {
|
||||
intf->rsp_cons = intf->rsp_prod = 0;
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
src = xb_get_input_chunk(cons, prod, intf->rsp, &avail);
|
||||
if (avail == 0)
|
||||
continue;
|
||||
if (avail > len)
|
||||
avail = len;
|
||||
|
||||
/* We must read header before we read data. */
|
||||
rmb();
|
||||
|
||||
memcpy(data, src, avail);
|
||||
data += avail;
|
||||
len -= avail;
|
||||
|
||||
/* Other side must not see free space until we've copied out */
|
||||
mb();
|
||||
intf->rsp_cons += avail;
|
||||
|
||||
/* Implies mb(): they will see new header. */
|
||||
notify_remote_via_evtchn(xen_store_evtchn);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set up interrupt handler off store event channel. */
|
||||
int xb_init_comms(void)
|
||||
int
|
||||
xb_init_comms(void)
|
||||
{
|
||||
struct xenstore_domain_interface *intf = xenstore_domain_interface();
|
||||
int err;
|
||||
struct xenstore_domain_interface *intf = xenstore_domain_interface();
|
||||
int error;
|
||||
|
||||
if (intf->rsp_prod != intf->rsp_cons) {
|
||||
log(LOG_WARNING, "XENBUS response ring is not quiescent "
|
||||
"(%08x:%08x): fixing up\n",
|
||||
intf->rsp_cons, intf->rsp_prod);
|
||||
intf->rsp_cons = intf->rsp_prod;
|
||||
}
|
||||
if (intf->rsp_prod != intf->rsp_cons) {
|
||||
log(LOG_WARNING, "XENBUS response ring is not quiescent "
|
||||
"(%08x:%08x): fixing up\n",
|
||||
intf->rsp_cons, intf->rsp_prod);
|
||||
intf->rsp_cons = intf->rsp_prod;
|
||||
}
|
||||
|
||||
if (xenbus_irq)
|
||||
unbind_from_irqhandler(xenbus_irq, &xb_waitq);
|
||||
if (xenstore_irq)
|
||||
unbind_from_irqhandler(xenstore_irq);
|
||||
|
||||
err = bind_caller_port_to_irqhandler(
|
||||
xen_start_info->store_evtchn,
|
||||
"xenbus", wake_waiting, NULL, INTR_TYPE_NET, NULL);
|
||||
if (err <= 0) {
|
||||
log(LOG_WARNING, "XENBUS request irq failed %i\n", err);
|
||||
return err;
|
||||
}
|
||||
error = bind_caller_port_to_irqhandler(
|
||||
xen_store_evtchn, "xenbus",
|
||||
xb_intr, NULL, INTR_TYPE_NET, &xenstore_irq);
|
||||
if (error) {
|
||||
log(LOG_WARNING, "XENBUS request irq failed %i\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
xenbus_irq = err;
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "bsd"
|
||||
* indent-tabs-mode: t
|
||||
* c-indent-level: 4
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 4
|
||||
* End:
|
||||
*/
|
||||
|
@ -30,123 +30,19 @@
|
||||
#ifndef _XENBUS_COMMS_H
|
||||
#define _XENBUS_COMMS_H
|
||||
|
||||
struct sx;
|
||||
extern int xen_store_evtchn;
|
||||
extern char *xen_store;
|
||||
|
||||
int xs_init(void);
|
||||
int xb_init_comms(void);
|
||||
|
||||
/* Low level routines. */
|
||||
int xb_write(const void *data, unsigned len);
|
||||
int xb_read(void *data, unsigned len);
|
||||
int xs_input_avail(void);
|
||||
extern int xb_waitq;
|
||||
int xb_write(const void *data, unsigned len, struct lock_object *);
|
||||
int xb_read(void *data, unsigned len, struct lock_object *);
|
||||
extern int xenbus_running;
|
||||
|
||||
#define __wait_event_interruptible(wchan, condition, ret) \
|
||||
do { \
|
||||
for (;;) { \
|
||||
if (xenbus_running == 0) { \
|
||||
break; \
|
||||
} \
|
||||
if (condition) \
|
||||
break; \
|
||||
if ((ret = !tsleep(wchan, PWAIT | PCATCH, "waitev", hz/10))) \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define wait_event_interruptible(wchan, condition) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (!(condition)) \
|
||||
__wait_event_interruptible(wchan, condition, __ret); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
|
||||
|
||||
#define DECLARE_MUTEX(lock) struct sema lock
|
||||
#define semaphore sema
|
||||
#define rw_semaphore sema
|
||||
|
||||
#define down sema_wait
|
||||
#define up sema_post
|
||||
#define down_read sema_wait
|
||||
#define up_read sema_post
|
||||
#define down_write sema_wait
|
||||
#define up_write sema_post
|
||||
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
*
|
||||
* @ptr: the pointer to the member.
|
||||
* @type: the type of the container struct this is embedded in.
|
||||
* @member: the name of the member within the struct.
|
||||
*
|
||||
*/
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
__typeof__( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
|
||||
/*
|
||||
* XXX
|
||||
*
|
||||
*/
|
||||
|
||||
#define GFP_KERNEL 1
|
||||
#define EXPORT_SYMBOL(x)
|
||||
#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
|
||||
#define kfree(ptr) free((void *)(uintptr_t)ptr, M_DEVBUF)
|
||||
#define BUG_ON PANIC_IF
|
||||
#define semaphore sema
|
||||
#define rw_semaphore sema
|
||||
#define DEFINE_SPINLOCK(lock) struct mtx lock
|
||||
#define DECLARE_MUTEX(lock) struct sema lock
|
||||
#define u32 uint32_t
|
||||
#define list_del(head, ent) TAILQ_REMOVE(head, ent, list)
|
||||
#define simple_strtoul strtoul
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
#define list_empty TAILQ_EMPTY
|
||||
#define wake_up wakeup
|
||||
#define BUS_ID_SIZE 128
|
||||
|
||||
struct xen_bus_type
|
||||
{
|
||||
char *root;
|
||||
unsigned int levels;
|
||||
int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename);
|
||||
int (*probe)(const char *type, const char *dir);
|
||||
struct xendev_list_head *bus;
|
||||
int error;
|
||||
#if 0
|
||||
struct bus_type bus;
|
||||
struct device dev;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
void dev_changed(const char *node, struct xen_bus_type *bus);
|
||||
|
||||
int
|
||||
read_otherend_details(struct xenbus_device *xendev, char *id_node,
|
||||
char *path_node);
|
||||
#endif
|
||||
|
||||
char *kasprintf(const char *fmt, ...);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* _XENBUS_COMMS_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
|
@ -45,19 +45,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <xen/xenbus/xenbusvar.h>
|
||||
#include <xen/xenbus/xenbus_comms.h>
|
||||
|
||||
#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
|
||||
#define BUG_ON PANIC_IF
|
||||
#define semaphore sema
|
||||
#define rw_semaphore sema
|
||||
#define DEFINE_SPINLOCK(lock) struct mtx lock
|
||||
#define DECLARE_MUTEX(lock) struct sema lock
|
||||
#define u32 uint32_t
|
||||
#define simple_strtoul strtoul
|
||||
|
||||
struct xenbus_dev_transaction {
|
||||
LIST_ENTRY(xenbus_dev_transaction) list;
|
||||
struct xenbus_transaction handle;
|
||||
@ -78,62 +69,65 @@ struct xenbus_dev_data {
|
||||
#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
|
||||
char read_buffer[PAGE_SIZE];
|
||||
unsigned int read_cons, read_prod;
|
||||
int read_waitq;
|
||||
};
|
||||
#if 0
|
||||
static struct proc_dir_entry *xenbus_dev_intf;
|
||||
#endif
|
||||
|
||||
static int
|
||||
xenbus_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int i = 0;
|
||||
int error;
|
||||
struct xenbus_dev_data *u = dev->si_drv1;
|
||||
|
||||
if (wait_event_interruptible(&u->read_waitq,
|
||||
u->read_prod != u->read_cons))
|
||||
return EINTR;
|
||||
while (u->read_prod == u->read_cons) {
|
||||
error = tsleep(u, PCATCH, "xbdread", hz/10);
|
||||
if (error && error != EWOULDBLOCK)
|
||||
return (error);
|
||||
}
|
||||
|
||||
for (i = 0; i < uio->uio_iov[0].iov_len; i++) {
|
||||
while (uio->uio_resid > 0) {
|
||||
if (u->read_cons == u->read_prod)
|
||||
break;
|
||||
copyout(&u->read_buffer[MASK_READ_IDX(u->read_cons)], (char *)uio->uio_iov[0].iov_base+i, 1);
|
||||
error = uiomove(&u->read_buffer[MASK_READ_IDX(u->read_cons)],
|
||||
1, uio);
|
||||
if (error)
|
||||
return (error);
|
||||
u->read_cons++;
|
||||
uio->uio_resid--;
|
||||
}
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void queue_reply(struct xenbus_dev_data *u,
|
||||
char *data, unsigned int len)
|
||||
static void
|
||||
queue_reply(struct xenbus_dev_data *u, char *data, unsigned int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++, u->read_prod++)
|
||||
u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
|
||||
|
||||
BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
|
||||
KASSERT((u->read_prod - u->read_cons) <= sizeof(u->read_buffer),
|
||||
("xenstore reply too big"));
|
||||
|
||||
wakeup(&u->read_waitq);
|
||||
wakeup(u);
|
||||
}
|
||||
|
||||
static int
|
||||
xenbus_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int err = 0;
|
||||
int error;
|
||||
struct xenbus_dev_data *u = dev->si_drv1;
|
||||
struct xenbus_dev_transaction *trans;
|
||||
void *reply;
|
||||
int len = uio->uio_iov[0].iov_len;
|
||||
int len = uio->uio_resid;
|
||||
|
||||
if ((len + u->len) > sizeof(u->u.buffer))
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
|
||||
if (copyin(u->u.buffer + u->len, uio->uio_iov[0].iov_base, len) != 0)
|
||||
return EFAULT;
|
||||
error = uiomove(u->u.buffer + u->len, len, uio);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
u->len += len;
|
||||
if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
|
||||
return len;
|
||||
return (0);
|
||||
|
||||
switch (u->u.msg.type) {
|
||||
case XS_TRANSACTION_START:
|
||||
@ -147,67 +141,59 @@ xenbus_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
case XS_MKDIR:
|
||||
case XS_RM:
|
||||
case XS_SET_PERMS:
|
||||
reply = xenbus_dev_request_and_reply(&u->u.msg);
|
||||
if (IS_ERR(reply)) {
|
||||
err = PTR_ERR(reply);
|
||||
} else {
|
||||
error = xenbus_dev_request_and_reply(&u->u.msg, &reply);
|
||||
if (!error) {
|
||||
if (u->u.msg.type == XS_TRANSACTION_START) {
|
||||
trans = kmalloc(sizeof(*trans), GFP_KERNEL);
|
||||
trans->handle.id = simple_strtoul(reply, NULL, 0);
|
||||
trans = malloc(sizeof(*trans), M_DEVBUF,
|
||||
M_WAITOK);
|
||||
trans->handle.id = strtoul(reply, NULL, 0);
|
||||
LIST_INSERT_HEAD(&u->transactions, trans, list);
|
||||
} else if (u->u.msg.type == XS_TRANSACTION_END) {
|
||||
LIST_FOREACH(trans, &u->transactions,
|
||||
list)
|
||||
if (trans->handle.id ==
|
||||
u->u.msg.tx_id)
|
||||
LIST_FOREACH(trans, &u->transactions, list)
|
||||
if (trans->handle.id == u->u.msg.tx_id)
|
||||
break;
|
||||
#if 0 /* XXX does this mean the list is empty? */
|
||||
BUG_ON(&trans->list == &u->transactions);
|
||||
#endif
|
||||
LIST_REMOVE(trans, list);
|
||||
kfree(trans);
|
||||
free(trans, M_DEVBUF);
|
||||
}
|
||||
queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
|
||||
queue_reply(u, (char *)reply, u->u.msg.len);
|
||||
kfree(reply);
|
||||
free(reply, M_DEVBUF);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EINVAL;
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
if (error == 0)
|
||||
u->len = 0;
|
||||
err = len;
|
||||
}
|
||||
|
||||
return err;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int xenbus_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
static int
|
||||
xenbus_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
{
|
||||
struct xenbus_dev_data *u;
|
||||
|
||||
if (xen_start_info->store_evtchn == 0)
|
||||
return ENOENT;
|
||||
if (xen_store_evtchn == 0)
|
||||
return (ENOENT);
|
||||
#if 0 /* XXX figure out if equiv needed */
|
||||
nonseekable_open(inode, filp);
|
||||
#endif
|
||||
u = kmalloc(sizeof(*u), GFP_KERNEL);
|
||||
if (u == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
memset(u, 0, sizeof(*u));
|
||||
u = malloc(sizeof(*u), M_DEVBUF, M_WAITOK|M_ZERO);
|
||||
LIST_INIT(&u->transactions);
|
||||
|
||||
dev->si_drv1 = u;
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
|
||||
static int
|
||||
xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
|
||||
{
|
||||
struct xenbus_dev_data *u = dev->si_drv1;
|
||||
struct xenbus_dev_transaction *trans, *tmp;
|
||||
@ -215,11 +201,11 @@ static int xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thr
|
||||
LIST_FOREACH_SAFE(trans, &u->transactions, list, tmp) {
|
||||
xenbus_transaction_end(trans->handle, 1);
|
||||
LIST_REMOVE(trans, list);
|
||||
kfree(trans);
|
||||
free(trans, M_DEVBUF);
|
||||
}
|
||||
|
||||
kfree(u);
|
||||
return 0;
|
||||
free(u, M_DEVBUF);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct cdevsw xenbus_dev_cdevsw = {
|
||||
@ -234,21 +220,10 @@ static struct cdevsw xenbus_dev_cdevsw = {
|
||||
static int
|
||||
xenbus_dev_sysinit(void)
|
||||
{
|
||||
make_dev(&xenbus_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400, "xenbus");
|
||||
make_dev(&xenbus_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400,
|
||||
"xen/xenbus");
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
SYSINIT(xenbus_dev_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, xenbus_dev_sysinit, NULL);
|
||||
/* SYSINIT NEEDED XXX */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
* indent-tabs-mode: t
|
||||
* c-indent-level: 8
|
||||
* c-basic-offset: 8
|
||||
* tab-width: 8
|
||||
* End:
|
||||
*/
|
||||
SYSINIT(xenbus_dev_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE,
|
||||
xenbus_dev_sysinit, NULL);
|
||||
|
@ -88,9 +88,7 @@ kasprintf(const char *fmt, ...)
|
||||
len = vsnprintf(dummy, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
p = kmalloc(len + 1, GFP_KERNEL);
|
||||
if (!p)
|
||||
return NULL;
|
||||
p = malloc(len + 1, M_DEVBUF, M_WAITOK);
|
||||
va_start(ap, fmt);
|
||||
vsprintf(p, fmt, ap);
|
||||
va_end(ap);
|
||||
@ -187,6 +185,7 @@ xenbus_add_device(device_t dev, const char *bus,
|
||||
struct xenbus_device_ivars *ivars;
|
||||
enum xenbus_state state;
|
||||
char *statepath;
|
||||
int error;
|
||||
|
||||
ivars = malloc(sizeof(struct xenbus_device_ivars),
|
||||
M_DEVBUF, M_ZERO|M_WAITOK);
|
||||
@ -217,17 +216,19 @@ xenbus_add_device(device_t dev, const char *bus,
|
||||
/*
|
||||
* Find the backend details
|
||||
*/
|
||||
xenbus_gather(XBT_NIL, ivars->xd_node,
|
||||
error = xenbus_gather(XBT_NIL, ivars->xd_node,
|
||||
"backend-id", "%i", &ivars->xd_otherend_id,
|
||||
"backend", NULL, &ivars->xd_otherend_path,
|
||||
NULL);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
sx_init(&ivars->xd_lock, "xdlock");
|
||||
ivars->xd_type = strdup(type, M_DEVBUF);
|
||||
ivars->xd_state = XenbusStateInitialising;
|
||||
|
||||
statepath = malloc(strlen(ivars->xd_otherend_path)
|
||||
+ strlen("/state") + 1, M_DEVBUF, M_NOWAIT);
|
||||
+ strlen("/state") + 1, M_DEVBUF, M_WAITOK);
|
||||
sprintf(statepath, "%s/state", ivars->xd_otherend_path);
|
||||
|
||||
ivars->xd_otherend_watch.node = statepath;
|
||||
@ -245,10 +246,11 @@ xenbus_enumerate_type(device_t dev, const char *bus, const char *type)
|
||||
{
|
||||
char **dir;
|
||||
unsigned int i, count;
|
||||
int error;
|
||||
|
||||
dir = xenbus_directory(XBT_NIL, bus, type, &count);
|
||||
if (IS_ERR(dir))
|
||||
return (EINVAL);
|
||||
error = xenbus_directory(XBT_NIL, bus, type, &count, &dir);
|
||||
if (error)
|
||||
return (error);
|
||||
for (i = 0; i < count; i++)
|
||||
xenbus_add_device(dev, bus, type, dir[i]);
|
||||
|
||||
@ -262,10 +264,11 @@ xenbus_enumerate_bus(device_t dev, const char *bus)
|
||||
{
|
||||
char **dir;
|
||||
unsigned int i, count;
|
||||
int error;
|
||||
|
||||
dir = xenbus_directory(XBT_NIL, bus, "", &count);
|
||||
if (IS_ERR(dir))
|
||||
return (EINVAL);
|
||||
error = xenbus_directory(XBT_NIL, bus, "", &count, &dir);
|
||||
if (error)
|
||||
return (error);
|
||||
for (i = 0; i < count; i++) {
|
||||
xenbus_enumerate_type(dev, bus, dir[i]);
|
||||
}
|
||||
@ -386,28 +389,90 @@ xenbus_attach(device_t dev)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
xenbus_suspend(device_t dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
DPRINTK("");
|
||||
panic("implement me");
|
||||
#if 0
|
||||
bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
|
||||
bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
|
||||
#endif
|
||||
|
||||
error = bus_generic_suspend(dev);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
xs_suspend();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
xenbus_resume(device_t dev)
|
||||
{
|
||||
device_t *kids;
|
||||
struct xenbus_device_ivars *ivars;
|
||||
int i, count, error;
|
||||
char *statepath;
|
||||
|
||||
xb_init_comms();
|
||||
xs_resume();
|
||||
panic("implement me");
|
||||
|
||||
/*
|
||||
* We must re-examine each device and find the new path for
|
||||
* its backend.
|
||||
*/
|
||||
if (device_get_children(dev, &kids, &count) == 0) {
|
||||
for (i = 0; i < count; i++) {
|
||||
if (device_get_state(kids[i]) == DS_NOTPRESENT)
|
||||
continue;
|
||||
|
||||
ivars = device_get_ivars(kids[i]);
|
||||
|
||||
unregister_xenbus_watch(
|
||||
&ivars->xd_otherend_watch);
|
||||
ivars->xd_state = XenbusStateInitialising;
|
||||
|
||||
/*
|
||||
* Find the new backend details and
|
||||
* re-register our watch.
|
||||
*/
|
||||
free(ivars->xd_otherend_path, M_DEVBUF);
|
||||
error = xenbus_gather(XBT_NIL, ivars->xd_node,
|
||||
"backend-id", "%i", &ivars->xd_otherend_id,
|
||||
"backend", NULL, &ivars->xd_otherend_path,
|
||||
NULL);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
DEVICE_RESUME(kids[i]);
|
||||
|
||||
statepath = malloc(strlen(ivars->xd_otherend_path)
|
||||
+ strlen("/state") + 1, M_DEVBUF, M_WAITOK);
|
||||
sprintf(statepath, "%s/state", ivars->xd_otherend_path);
|
||||
|
||||
free(ivars->xd_otherend_watch.node, M_DEVBUF);
|
||||
ivars->xd_otherend_watch.node = statepath;
|
||||
register_xenbus_watch(
|
||||
&ivars->xd_otherend_watch);
|
||||
|
||||
#if 0
|
||||
bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
|
||||
bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
|
||||
#endif
|
||||
/*
|
||||
* Can't do this yet since we are running in
|
||||
* the xenwatch thread and if we sleep here,
|
||||
* we will stop delivering watch notifications
|
||||
* and the device will never come back online.
|
||||
*/
|
||||
sx_xlock(&ivars->xd_lock);
|
||||
while (ivars->xd_state != XenbusStateClosed
|
||||
&& ivars->xd_state != XenbusStateConnected)
|
||||
sx_sleep(&ivars->xd_state, &ivars->xd_lock,
|
||||
0, "xdresume", 0);
|
||||
sx_xunlock(&ivars->xd_lock);
|
||||
#endif
|
||||
}
|
||||
free(kids, M_TEMP);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -433,9 +498,11 @@ xenbus_read_ivar(device_t dev, device_t child, int index,
|
||||
case XENBUS_IVAR_NODE:
|
||||
*result = (uintptr_t) ivars->xd_node;
|
||||
return (0);
|
||||
|
||||
case XENBUS_IVAR_TYPE:
|
||||
*result = (uintptr_t) ivars->xd_type;
|
||||
return (0);
|
||||
|
||||
case XENBUS_IVAR_STATE:
|
||||
*result = (uintptr_t) ivars->xd_state;
|
||||
return (0);
|
||||
@ -468,8 +535,8 @@ xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
|
||||
goto out;
|
||||
|
||||
error = xenbus_scanf(XBT_NIL, ivars->xd_node, "state",
|
||||
"%d", &currstate);
|
||||
if (error < 0)
|
||||
NULL, "%d", &currstate);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = xenbus_printf(XBT_NIL, ivars->xd_node, "state",
|
||||
@ -494,15 +561,14 @@ xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
|
||||
*/
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
SYSCTL_DECL(_dev);
|
||||
SYSCTL_NODE(_dev, OID_AUTO, xen, CTLFLAG_RD, NULL, "Xen");
|
||||
#if 0
|
||||
SYSCTL_INT(_dev_xen, OID_AUTO, xsd_port, CTLFLAG_RD, &xen_store_evtchn, 0, "");
|
||||
SYSCTL_ULONG(_dev_xen, OID_AUTO, xsd_kva, CTLFLAG_RD, (u_long *) &xen_store, 0, "");
|
||||
#endif
|
||||
|
||||
static device_method_t xenbus_methods[] = {
|
||||
/* Device interface */
|
||||
|
@ -57,10 +57,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sx.h>
|
||||
|
||||
#include <machine/xen/xen-os.h>
|
||||
#include <machine/xen/hypervisor.h>
|
||||
#include <machine/xen/evtchn.h>
|
||||
#include <xen/hypervisor.h>
|
||||
#include <machine/xen/xenbus.h>
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/xenbus/xenbus_comms.h>
|
||||
|
||||
#define BUG_ON PANIC_IF
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -103,32 +103,37 @@ struct xenbus_transaction
|
||||
|
||||
#define XBT_NIL ((struct xenbus_transaction) { 0 })
|
||||
|
||||
char **xenbus_directory(struct xenbus_transaction t,
|
||||
const char *dir, const char *node, unsigned int *num);
|
||||
void *xenbus_read(struct xenbus_transaction t,
|
||||
const char *dir, const char *node, unsigned int *len);
|
||||
int xenbus_write(struct xenbus_transaction t,
|
||||
const char *dir, const char *node, const char *string);
|
||||
int xenbus_mkdir(struct xenbus_transaction t,
|
||||
const char *dir, const char *node);
|
||||
int xenbus_exists(struct xenbus_transaction t,
|
||||
const char *dir, const char *node);
|
||||
int xenbus_directory(struct xenbus_transaction t, const char *dir,
|
||||
const char *node, unsigned int *num, char ***result);
|
||||
int xenbus_read(struct xenbus_transaction t, const char *dir,
|
||||
const char *node, unsigned int *len, void **result);
|
||||
int xenbus_write(struct xenbus_transaction t, const char *dir,
|
||||
const char *node, const char *string);
|
||||
int xenbus_mkdir(struct xenbus_transaction t, const char *dir,
|
||||
const char *node);
|
||||
int xenbus_exists(struct xenbus_transaction t, const char *dir,
|
||||
const char *node);
|
||||
int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node);
|
||||
int xenbus_transaction_start(struct xenbus_transaction *t);
|
||||
int xenbus_transaction_end(struct xenbus_transaction t, int abort);
|
||||
|
||||
/* Single read and scanf: returns -errno or num scanned if > 0. */
|
||||
/*
|
||||
* Single read and scanf: returns errno or zero. If scancountp is
|
||||
* non-null, then number of items scanned is returned in *scanncountp.
|
||||
*/
|
||||
int xenbus_scanf(struct xenbus_transaction t,
|
||||
const char *dir, const char *node, const char *fmt, ...)
|
||||
__attribute__((format(scanf, 4, 5)));
|
||||
const char *dir, const char *node, int *scancountp, const char *fmt, ...)
|
||||
__attribute__((format(scanf, 5, 6)));
|
||||
|
||||
/* Single printf and write: returns -errno or 0. */
|
||||
/* Single printf and write: returns errno or 0. */
|
||||
int xenbus_printf(struct xenbus_transaction t,
|
||||
const char *dir, const char *node, const char *fmt, ...)
|
||||
__attribute__((format(printf, 4, 5)));
|
||||
|
||||
/* Generic read function: NULL-terminated triples of name,
|
||||
* sprintf-style type string, and pointer. Returns 0 or errno.*/
|
||||
/*
|
||||
* Generic read function: NULL-terminated triples of name,
|
||||
* sprintf-style type string, and pointer. Returns 0 or errno.
|
||||
*/
|
||||
int xenbus_gather(struct xenbus_transaction t, const char *dir, ...);
|
||||
|
||||
/* notifer routines for when the xenstore comes up */
|
||||
@ -142,7 +147,9 @@ void xs_suspend(void);
|
||||
void xs_resume(void);
|
||||
|
||||
/* Used by xenbus_dev to borrow kernel's store connection. */
|
||||
void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
|
||||
int xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **result);
|
||||
|
||||
#if 0
|
||||
|
||||
#define XENBUS_IS_ERR_READ(str) ({ \
|
||||
if (!IS_ERR(str) && strlen(str) == 0) { \
|
||||
@ -152,12 +159,15 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
|
||||
IS_ERR(str); \
|
||||
})
|
||||
|
||||
#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
|
||||
#endif
|
||||
|
||||
#define XENBUS_EXIST_ERR(err) ((err) == ENOENT || (err) == ERANGE)
|
||||
|
||||
|
||||
/**
|
||||
* Register a watch on the given path, using the given xenbus_watch structure
|
||||
* for storage, and the given callback function as the callback. Return 0 on
|
||||
* success, or -errno on error. On success, the given path will be saved as
|
||||
* success, or errno on error. On success, the given path will be saved as
|
||||
* watch->node, and remains the caller's to free. On error, watch->node will
|
||||
* be NULL, the device will switch to XenbusStateClosing, and the error will
|
||||
* be saved in the store.
|
||||
@ -171,7 +181,7 @@ int xenbus_watch_path(device_t dev, char *path,
|
||||
/**
|
||||
* Register a watch on the given path/path2, using the given xenbus_watch
|
||||
* structure for storage, and the given callback function as the callback.
|
||||
* Return 0 on success, or -errno on error. On success, the watched path
|
||||
* Return 0 on success, or errno on error. On success, the watched path
|
||||
* (path/path2) will be saved as watch->node, and becomes the caller's to
|
||||
* kfree(). On error, watch->node will be NULL, so the caller has nothing to
|
||||
* free, the device will switch to XenbusStateClosing, and the error will be
|
||||
@ -186,7 +196,7 @@ int xenbus_watch_path2(device_t dev, const char *path,
|
||||
/**
|
||||
* Advertise in the store a change of the given driver to the given new_state.
|
||||
* which case this is performed inside its own transaction. Return 0 on
|
||||
* success, or -errno on error. On error, the device will switch to
|
||||
* success, or errno on error. On error, the device will switch to
|
||||
* XenbusStateClosing, and the error will be saved in the store.
|
||||
*/
|
||||
int xenbus_switch_state(device_t dev,
|
||||
@ -194,16 +204,17 @@ int xenbus_switch_state(device_t dev,
|
||||
|
||||
|
||||
/**
|
||||
* Grant access to the given ring_mfn to the peer of the given device. Return
|
||||
* 0 on success, or -errno on error. On error, the device will switch to
|
||||
* XenbusStateClosing, and the error will be saved in the store.
|
||||
* Grant access to the given ring_mfn to the peer of the given device.
|
||||
* Return 0 on success, or errno on error. On error, the device will
|
||||
* switch to XenbusStateClosing, and the error will be saved in the
|
||||
* store. The grant ring reference is returned in *refp.
|
||||
*/
|
||||
int xenbus_grant_ring(device_t dev, unsigned long ring_mfn);
|
||||
int xenbus_grant_ring(device_t dev, unsigned long ring_mfn, int *refp);
|
||||
|
||||
|
||||
/**
|
||||
* Allocate an event channel for the given xenbus_device, assigning the newly
|
||||
* created local port to *port. Return 0 on success, or -errno on error. On
|
||||
* created local port to *port. Return 0 on success, or errno on error. On
|
||||
* error, the device will switch to XenbusStateClosing, and the error will be
|
||||
* saved in the store.
|
||||
*/
|
||||
@ -211,7 +222,7 @@ int xenbus_alloc_evtchn(device_t dev, int *port);
|
||||
|
||||
|
||||
/**
|
||||
* Free an existing event channel. Returns 0 on success or -errno on error.
|
||||
* Free an existing event channel. Returns 0 on success or errno on error.
|
||||
*/
|
||||
int xenbus_free_evtchn(device_t dev, int port);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user