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:
Kip Macy 2008-12-29 06:31:03 +00:00
parent 42d866dd69
commit 3a6d1fcf9c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=186557
32 changed files with 1347 additions and 1436 deletions

View File

@ -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;
}

View File

@ -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"));
}

View File

@ -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

View File

@ -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 {

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);
}

View File

@ -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 {

View File

@ -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 */;

View File

@ -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);
}

View File

@ -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

View File

@ -4,6 +4,8 @@
* Linux-specific hypervisor handling.
*
* Copyright (c) 2002, K A Fraser
*
* $FreeBSD$
*/
#ifndef __HYPERVISOR_H__

View File

@ -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;

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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);