diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c index dc36007f82f2..fdebc9d34b2c 100644 --- a/sys/dev/xen/blkfront/blkfront.c +++ b/sys/dev/xen/blkfront/blkfront.c @@ -40,10 +40,10 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include -#include -#include +#include +#include #include #include #include @@ -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; } diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c index 5b556c250490..a3d616a74856 100644 --- a/sys/dev/xen/console/console.c +++ b/sys/dev/xen/console/console.c @@ -15,8 +15,8 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include +#include +#include #include #include #include @@ -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")); } diff --git a/sys/dev/xen/console/xencons_ring.c b/sys/dev/xen/console/xencons_ring.c index 3d2323765c8e..596b5de48d36 100644 --- a/sys/dev/xen/console/xencons_ring.c +++ b/sys/dev/xen/console/xencons_ring.c @@ -15,19 +15,20 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include +#include +#include #include #include -#include +#include #include #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 diff --git a/sys/dev/xen/evtchn/evtchn_dev.c b/sys/dev/xen/evtchn/evtchn_dev.c index a20670857197..6925a22a17ae 100644 --- a/sys/dev/xen/evtchn/evtchn_dev.c +++ b/sys/dev/xen/evtchn/evtchn_dev.c @@ -26,13 +26,13 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #include #include #include #include -#include +#include typedef struct evtchn_sotfc { diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c index 607628f9f2be..7efeb2007f35 100644 --- a/sys/dev/xen/netfront/netfront.c +++ b/sys/dev/xen/netfront/netfront.c @@ -62,9 +62,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -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; } diff --git a/sys/i386/conf/XEN b/sys/i386/conf/XEN index 92958440a4e0..7ddc776d8cb7 100644 --- a/sys/i386/conf/XEN +++ b/sys/i386/conf/XEN @@ -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 diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c index 059e2ab394c2..7c6acf0ee5ad 100644 --- a/sys/i386/i386/genassym.c +++ b/sys/i386/i386/genassym.c @@ -234,7 +234,7 @@ ASSYM(BUS_SPACE_HANDLE_IAT, offsetof(struct bus_space_handle, bsh_iat)); #endif #ifdef XEN -#include +#include ASSYM(PC_CR3, offsetof(struct pcpu, pc_cr3)); ASSYM(HYPERVISOR_VIRT_START, __HYPERVISOR_VIRT_START); #endif diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index d824b26dea9f..803d8d15b0f7 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -144,11 +144,11 @@ uint32_t arch_i386_xbox_memsize = 0; #ifdef XEN /* XEN includes */ #include -#include +#include #include #include #include -#include +#include void Xhypervisor_callback(void); void failsafe_callback(void); diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index 502be4d47385..15233c5a6cf3 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -89,7 +89,7 @@ __FBSDID("$FreeBSD$"); #include #ifdef XEN -#include +#include #endif #ifdef PC98 #include diff --git a/sys/i386/include/xen/xenfunc.h b/sys/i386/include/xen/xenfunc.h index e1a707d74629..2851709cb955 100644 --- a/sys/i386/include/xen/xenfunc.h +++ b/sys/i386/include/xen/xenfunc.h @@ -33,7 +33,7 @@ #define _XEN_XENFUNC_H_ #include -#include +#include #include #include #include diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 6be3da9ac7a9..29dc2ca9702f 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$"); #include #ifdef XEN #include -#include +#include #endif #ifdef DEV_ISA diff --git a/sys/i386/xen/clock.c b/sys/i386/xen/clock.c index 3b4b6f3b8a19..db5b09cb75b6 100644 --- a/sys/i386/xen/clock.c +++ b/sys/i386/xen/clock.c @@ -78,11 +78,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include #include -#include +#include #include #include #include @@ -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); } diff --git a/sys/i386/xen/mp_machdep.c b/sys/i386/xen/mp_machdep.c index 4b6c77c107ac..874cde886b51 100644 --- a/sys/i386/xen/mp_machdep.c +++ b/sys/i386/xen/mp_machdep.c @@ -85,9 +85,9 @@ __FBSDID("$FreeBSD$"); #include -#include -#include -#include +#include +#include +#include #include #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; } diff --git a/sys/i386/xen/mptable.c b/sys/i386/xen/mptable.c index 99edc50e31cf..c6c7d53ccb5e 100644 --- a/sys/i386/xen/mptable.c +++ b/sys/i386/xen/mptable.c @@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include #include diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index d6464583ad45..6ad67ffd7653 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -154,7 +154,7 @@ __FBSDID("$FreeBSD$"); #endif #include -#include +#include #include #include #include diff --git a/sys/i386/xen/xen_machdep.c b/sys/i386/xen/xen_machdep.c index 9f487025d32b..0c86c62b2fe1 100644 --- a/sys/i386/xen/xen_machdep.c +++ b/sys/i386/xen/xen_machdep.c @@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$"); -#include +#include #include #include #include diff --git a/sys/i386/include/xen/evtchn.h b/sys/xen/evtchn.h similarity index 98% rename from sys/i386/include/xen/evtchn.h rename to sys/xen/evtchn.h index f86a8abc0e79..721742f6de40 100644 --- a/sys/i386/include/xen/evtchn.h +++ b/sys/xen/evtchn.h @@ -12,7 +12,7 @@ #ifndef __ASM_EVTCHN_H__ #define __ASM_EVTCHN_H__ #include -#include +#include #include #include diff --git a/sys/xen/evtchn/evtchn.c b/sys/xen/evtchn/evtchn.c index b28315cb548f..884270c666a6 100644 --- a/sys/xen/evtchn/evtchn.c +++ b/sys/xen/evtchn/evtchn.c @@ -23,10 +23,10 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #include -#include -#include +#include +#include #include @@ -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); } diff --git a/sys/xen/evtchn/evtchn_dev.c b/sys/xen/evtchn/evtchn_dev.c index 111b066b4bcf..ea12860dbefb 100644 --- a/sys/xen/evtchn/evtchn_dev.c +++ b/sys/xen/evtchn/evtchn_dev.c @@ -26,13 +26,13 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #include #include #include #include -#include -#include +#include +#include typedef struct evtchn_sotfc { diff --git a/sys/xen/features.c b/sys/xen/features.c index 51d68990e98f..876a7d1e568f 100644 --- a/sys/xen/features.c +++ b/sys/xen/features.c @@ -3,7 +3,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include uint8_t xen_features[XENFEAT_NR_SUBMAPS * 32] /* __read_mostly */; diff --git a/sys/xen/gnttab.c b/sys/xen/gnttab.c index fdd3d1b2356c..967565506dfc 100644 --- a/sys/xen/gnttab.c +++ b/sys/xen/gnttab.c @@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include @@ -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 @@ ini_nomem: for (i--; i >= 0; i--) free(gnttab_list[i], M_DEVBUF); free(gnttab_list, M_DEVBUF); - return -ENOMEM; + return (ENOMEM); } diff --git a/sys/xen/gnttab.h b/sys/xen/gnttab.h index d1abe14c9fb7..bcefbbc131bf 100644 --- a/sys/xen/gnttab.h +++ b/sys/xen/gnttab.h @@ -36,10 +36,9 @@ #ifndef __ASM_GNTTAB_H__ -#include +#include #include #include -#include #include 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 diff --git a/sys/i386/include/xen/hypervisor.h b/sys/xen/hypervisor.h similarity index 99% rename from sys/i386/include/xen/hypervisor.h rename to sys/xen/hypervisor.h index 7f7ca20fc828..369b0c4d5b6c 100644 --- a/sys/i386/include/xen/hypervisor.h +++ b/sys/xen/hypervisor.h @@ -4,6 +4,8 @@ * Linux-specific hypervisor handling. * * Copyright (c) 2002, K A Fraser + * + * $FreeBSD$ */ #ifndef __HYPERVISOR_H__ diff --git a/sys/i386/include/xen/xen_intr.h b/sys/xen/xen_intr.h similarity index 85% rename from sys/i386/include/xen/xen_intr.h rename to sys/xen/xen_intr.h index a0e6c8844404..528fa7f40d80 100644 --- a/sys/i386/include/xen/xen_intr.h +++ b/sys/xen/xen_intr.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; diff --git a/sys/xen/xenbus/xenbus_client.c b/sys/xen/xenbus/xenbus_client.c index d8a1a3f4a488..740d66409e14 100644 --- a/sys/xen/xenbus/xenbus_client.c +++ b/sys/xen/xenbus/xenbus_client.c @@ -44,19 +44,14 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include +#include #include #include #include - -#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: - */ diff --git a/sys/xen/xenbus/xenbus_comms.c b/sys/xen/xenbus/xenbus_comms.c index 90f0ea94f6ab..2f0395517921 100644 --- a/sys/xen/xenbus/xenbus_comms.c +++ b/sys/xen/xenbus/xenbus_comms.c @@ -33,217 +33,194 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include +#include +#include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include -#include +#include + +#include +#include #include +#include -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: - */ diff --git a/sys/xen/xenbus/xenbus_comms.h b/sys/xen/xenbus/xenbus_comms.h index 94a57dc58c43..fa4733109d99 100644 --- a/sys/xen/xenbus/xenbus_comms.h +++ b/sys/xen/xenbus/xenbus_comms.h @@ -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: - */ diff --git a/sys/xen/xenbus/xenbus_dev.c b/sys/xen/xenbus/xenbus_dev.c index 52e0b67cb0ac..ac3f103e1fae 100644 --- a/sys/xen/xenbus/xenbus_dev.c +++ b/sys/xen/xenbus/xenbus_dev.c @@ -45,19 +45,10 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include -#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); diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c index e57e6e3ef5fc..3d2cb4bb81ca 100644 --- a/sys/xen/xenbus/xenbus_probe.c +++ b/sys/xen/xenbus/xenbus_probe.c @@ -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 */ diff --git a/sys/xen/xenbus/xenbus_probe_backend.c b/sys/xen/xenbus/xenbus_probe_backend.c index af83fe6fee83..20cc49f82293 100644 --- a/sys/xen/xenbus/xenbus_probe_backend.c +++ b/sys/xen/xenbus/xenbus_probe_backend.c @@ -57,10 +57,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include +#include +#include #include +#include #include #define BUG_ON PANIC_IF diff --git a/sys/xen/xenbus/xenbus_xs.c b/sys/xen/xenbus/xenbus_xs.c index 332a509f1f0f..9e0f7798fcf7 100644 --- a/sys/xen/xenbus/xenbus_xs.c +++ b/sys/xen/xenbus/xenbus_xs.c @@ -33,91 +33,77 @@ __FBSDID("$FreeBSD$"); #include -#include -#include -#include -#include #include #include -#include #include #include #include -#include #include #include -#include #include #include #include +#include #include -#include +#include #include #include #include +#include + +#include +#include + static int xs_process_msg(enum xsd_sockmsg_type *type); -#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK) -#define BUG_ON PANIC_IF -#define DEFINE_SPINLOCK(lock) struct mtx 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 streq(a, b) (strcmp((a), (b)) == 0) int xenwatch_running = 0; int xenbus_running = 0; - -struct kvec { - const void *iov_base; - size_t iov_len; -}; +int xen_store_evtchn; struct xs_stored_msg { - TAILQ_ENTRY(xs_stored_msg) list; + TAILQ_ENTRY(xs_stored_msg) list; - struct xsd_sockmsg hdr; + struct xsd_sockmsg hdr; - union { - /* Queued replies. */ - struct { - char *body; - } reply; + union { + /* Queued replies. */ + struct { + char *body; + } reply; - /* Queued watch events. */ - struct { - struct xenbus_watch *handle; - char **vec; - unsigned int vec_size; - } watch; - } u; + /* Queued watch events. */ + struct { + struct xenbus_watch *handle; + char **vec; + unsigned int vec_size; + } watch; + } u; }; struct xs_handle { - /* A list of replies. Currently only one will ever be outstanding. */ - TAILQ_HEAD(xs_handle_list, xs_stored_msg) reply_list; - struct mtx reply_lock; - int reply_waitq; + /* A list of replies. Currently only one will ever be outstanding. */ + TAILQ_HEAD(xs_handle_list, xs_stored_msg) reply_list; + struct mtx reply_lock; + int reply_waitq; - /* One request at a time. */ - struct sx request_mutex; + /* One request at a time. */ + struct sx request_mutex; - /* Protect transactions against save/restore. */ - struct sx suspend_mutex; + /* Protect transactions against save/restore. */ + struct sx suspend_mutex; }; static struct xs_handle xs_state; /* List of registered watches, and a lock to protect it. */ static LIST_HEAD(watch_list_head, xenbus_watch) watches; -static DEFINE_SPINLOCK(watches_lock); +static struct mtx watches_lock; /* List of pending watch callback events, and a lock to protect it. */ static TAILQ_HEAD(event_list_head, xs_stored_msg) watch_events; -static DEFINE_SPINLOCK(watch_events_lock); +static struct mtx watch_events_lock; + /* * Details of the xenwatch callback kernel thread. The thread waits on the * watch_events_waitq for work to do (queued on watch_events list). When it @@ -128,831 +114,814 @@ static pid_t xenwatch_pid; struct sx xenwatch_mutex; static int watch_events_waitq; -static int get_error(const char *errorstring) -{ - unsigned int i; +#define xsd_error_count (sizeof(xsd_errors) / sizeof(xsd_errors[0])) - for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) { - if (i == ARRAY_SIZE(xsd_errors) - 1) { - log(LOG_WARNING, "XENBUS xen store gave: unknown error %s", - errorstring); - return EINVAL; - } - } - return xsd_errors[i].errnum; +static int +xs_get_error(const char *errorstring) +{ + unsigned int i; + + for (i = 0; i < xsd_error_count; i++) { + if (!strcmp(errorstring, xsd_errors[i].errstring)) + return (xsd_errors[i].errnum); + } + log(LOG_WARNING, "XENBUS xen store gave: unknown error %s", + errorstring); + return (EINVAL); } -extern void idle_block(void); extern void kdb_backtrace(void); -static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) +static int +xs_read_reply(enum xsd_sockmsg_type *type, unsigned int *len, void **result) { - struct xs_stored_msg *msg; - char *body; - int i, err; - enum xsd_sockmsg_type itype = *type; + struct xs_stored_msg *msg; + char *body; + int error; - printf("read_reply "); - if (xenbus_running == 0) { - /* - * Give other domain time to run :-/ - */ - for (i = 0; i < 1000000 && (xenbus_running == 0); i++) { - err = xs_process_msg(type); - - if ((err == 0) - && (*type != XS_WATCH_EVENT)) - break; - - HYPERVISOR_yield(); + mtx_lock(&xs_state.reply_lock); + + while (TAILQ_EMPTY(&xs_state.reply_list)) { + while (TAILQ_EMPTY(&xs_state.reply_list)) { + error = mtx_sleep(&xs_state.reply_waitq, + &xs_state.reply_lock, + PCATCH, "xswait", hz/10); + if (error && error != EWOULDBLOCK) { + mtx_unlock(&xs_state.reply_lock); + return (error); } - if (list_empty(&xs_state.reply_list)) { - printf("giving up and returning an error type=%d\n", - *type); - kdb_backtrace(); - return (ERR_PTR(-1)); - } + } + } - mtx_lock(&xs_state.reply_lock); - if (xenbus_running) { - while (list_empty(&xs_state.reply_list)) { - mtx_unlock(&xs_state.reply_lock); - wait_event_interruptible(&xs_state.reply_waitq, - !list_empty(&xs_state.reply_list)); - - mtx_lock(&xs_state.reply_lock); - } - } - msg = TAILQ_FIRST(&xs_state.reply_list); - list_del(&xs_state.reply_list, msg); + msg = TAILQ_FIRST(&xs_state.reply_list); + TAILQ_REMOVE(&xs_state.reply_list, msg, list); - mtx_unlock(&xs_state.reply_lock); + mtx_unlock(&xs_state.reply_lock); - printf("itype=%d htype=%d ", itype, msg->hdr.type); - *type = msg->hdr.type; - if (len) - *len = msg->hdr.len; - body = msg->u.reply.body; + *type = msg->hdr.type; + if (len) + *len = msg->hdr.len; + body = msg->u.reply.body; - kfree(msg); - if (len) - printf("len=%d\n", *len); - else - printf("len=NULL\n"); - return body; + free(msg, M_DEVBUF); + *result = body; + return (0); } #if 0 /* Emergency write. UNUSED*/ void xenbus_debug_write(const char *str, unsigned int count) { - struct xsd_sockmsg msg = { 0 }; + struct xsd_sockmsg msg = { 0 }; - msg.type = XS_DEBUG; - msg.len = sizeof("print") + count + 1; + msg.type = XS_DEBUG; + msg.len = sizeof("print") + count + 1; - sx_xlock(&xs_state.request_mutex); - xb_write(&msg, sizeof(msg)); - xb_write("print", sizeof("print")); - xb_write(str, count); - xb_write("", 1); - sx_xunlock(&xs_state.request_mutex); + sx_xlock(&xs_state.request_mutex); + xb_write(&msg, sizeof(msg)); + xb_write("print", sizeof("print")); + xb_write(str, count); + xb_write("", 1); + sx_xunlock(&xs_state.request_mutex); } #endif -void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) + +int +xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **result) { - void *ret; - struct xsd_sockmsg req_msg = *msg; - int err; + struct xsd_sockmsg req_msg = *msg; + int error; - if (req_msg.type == XS_TRANSACTION_START) - sx_slock(&xs_state.suspend_mutex); + if (req_msg.type == XS_TRANSACTION_START) + sx_slock(&xs_state.suspend_mutex); - sx_xlock(&xs_state.request_mutex); + sx_xlock(&xs_state.request_mutex); - err = xb_write(msg, sizeof(*msg) + msg->len); - if (err) { - msg->type = XS_ERROR; - ret = ERR_PTR(err); - } else { - ret = read_reply(&msg->type, &msg->len); - } + error = xb_write(msg, sizeof(*msg) + msg->len, &xs_state.request_mutex.lock_object); + if (error) { + msg->type = XS_ERROR; + } else { + error = xs_read_reply(&msg->type, &msg->len, result); + } - sx_xunlock(&xs_state.request_mutex); + sx_xunlock(&xs_state.request_mutex); - if ((msg->type == XS_TRANSACTION_END) || - ((req_msg.type == XS_TRANSACTION_START) && - (msg->type == XS_ERROR))) - sx_sunlock(&xs_state.suspend_mutex); + if ((msg->type == XS_TRANSACTION_END) || + ((req_msg.type == XS_TRANSACTION_START) && + (msg->type == XS_ERROR))) + sx_sunlock(&xs_state.suspend_mutex); - return ret; + return (error); } -static int xenwatch_inline; - -/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ -static void *xs_talkv(struct xenbus_transaction t, - enum xsd_sockmsg_type type, - const struct kvec *iovec, - unsigned int num_vecs, - unsigned int *len) +/* + * Send message to xs. The reply is returned in *result and should be + * fred with free(*result, M_DEVBUF). Return zero on success or an + * error code on failure. + */ +static int +xs_talkv(struct xenbus_transaction t, enum xsd_sockmsg_type type, + const struct iovec *iovec, unsigned int num_vecs, + unsigned int *len, void **result) { - struct xsd_sockmsg msg; - void *ret = NULL; - unsigned int i; - int err; + struct xsd_sockmsg msg; + void *ret = NULL; + unsigned int i; + int error; - msg.tx_id = t.id; - msg.req_id = 0; - msg.type = type; - msg.len = 0; - for (i = 0; i < num_vecs; i++) - msg.len += iovec[i].iov_len; + msg.tx_id = t.id; + msg.req_id = 0; + msg.type = type; + msg.len = 0; + for (i = 0; i < num_vecs; i++) + msg.len += iovec[i].iov_len; - printf("xs_talkv "); - - sx_xlock(&xs_state.request_mutex); - - err = xb_write(&msg, sizeof(msg)); - if (err) { - sx_xunlock(&xs_state.request_mutex); - printf("xs_talkv failed %d\n", err); - return ERR_PTR(err); - } - - for (i = 0; i < num_vecs; i++) { - err = xb_write(iovec[i].iov_base, iovec[i].iov_len);; - if (err) { - sx_xunlock(&xs_state.request_mutex); - printf("xs_talkv failed %d\n", err); - return ERR_PTR(err); - } - } - - ret = read_reply(&msg.type, len); + sx_xlock(&xs_state.request_mutex); + error = xb_write(&msg, sizeof(msg), &xs_state.request_mutex.lock_object); + if (error) { sx_xunlock(&xs_state.request_mutex); + printf("xs_talkv failed %d\n", error); + return (error); + } - if (IS_ERR(ret)) - return ret; - - if (msg.type == XS_ERROR) { - err = get_error(ret); - kfree(ret); - return ERR_PTR(-err); + for (i = 0; i < num_vecs; i++) { + error = xb_write(iovec[i].iov_base, iovec[i].iov_len, &xs_state.request_mutex.lock_object); + if (error) { + sx_xunlock(&xs_state.request_mutex); + printf("xs_talkv failed %d\n", error); + return (error); } + } - if ((xenwatch_running == 0) && (xenwatch_inline == 0)) { - xenwatch_inline = 1; - while (!TAILQ_EMPTY(&watch_events) - && xenwatch_running == 0) { + error = xs_read_reply(&msg.type, len, &ret); + + sx_xunlock(&xs_state.request_mutex); + + if (error) + return (error); + + if (msg.type == XS_ERROR) { + error = xs_get_error(ret); + free(ret, M_DEVBUF); + return (error); + } + +#if 0 + if ((xenwatch_running == 0) && (xenwatch_inline == 0)) { + xenwatch_inline = 1; + while (!TAILQ_EMPTY(&watch_events) + && xenwatch_running == 0) { - struct xs_stored_msg *wmsg = TAILQ_FIRST(&watch_events); - list_del(&watch_events, wmsg); - printf("handling %p ...", wmsg->u.watch.handle->callback); + struct xs_stored_msg *wmsg = TAILQ_FIRST(&watch_events); + TAILQ_REMOVE(&watch_events, wmsg, list); - wmsg->u.watch.handle->callback( - wmsg->u.watch.handle, - (const char **)wmsg->u.watch.vec, - wmsg->u.watch.vec_size); - printf("... %p done\n", wmsg->u.watch.handle->callback); - kfree(wmsg->u.watch.vec); - kfree(wmsg); - } - xenwatch_inline = 0; + wmsg->u.watch.handle->callback( + wmsg->u.watch.handle, + (const char **)wmsg->u.watch.vec, + wmsg->u.watch.vec_size); + free(wmsg->u.watch.vec, M_DEVBUF); + free(wmsg, M_DEVBUF); } - BUG_ON(msg.type != type); + xenwatch_inline = 0; + } +#endif + KASSERT(msg.type == type, ("bad xenstore message type")); - return ret; + if (result) + *result = ret; + else + free(ret, M_DEVBUF); + + return (0); } /* Simplified version of xs_talkv: single message. */ -static void *xs_single(struct xenbus_transaction t, - enum xsd_sockmsg_type type, - const char *string, - unsigned int *len) +static int +xs_single(struct xenbus_transaction t, enum xsd_sockmsg_type type, + const char *string, unsigned int *len, void **result) { - struct kvec iovec; + struct iovec iovec; - printf("xs_single %s ", string); - iovec.iov_base = (const void *)string; - iovec.iov_len = strlen(string) + 1; - return xs_talkv(t, type, &iovec, 1, len); + iovec.iov_base = (void *)(uintptr_t) string; + iovec.iov_len = strlen(string) + 1; + + return (xs_talkv(t, type, &iovec, 1, len, result)); } -/* Many commands only need an ack, don't care what it says. */ -static int xs_error(char *reply) +static unsigned int +count_strings(const char *strings, unsigned int len) { - if (IS_ERR(reply)) - return PTR_ERR(reply); - kfree(reply); - return 0; -} + unsigned int num; + const char *p; -static unsigned int count_strings(const char *strings, unsigned int len) -{ - unsigned int num; - const char *p; + for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) + num++; - for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) - num++; - - return num; + return num; } /* Return the path to dir with /name appended. Buffer must be kfree()'ed. */ -static char *join(const char *dir, const char *name) +static char * +join(const char *dir, const char *name) { - char *buffer; + char *buffer; - buffer = kmalloc(strlen(dir) + strlen("/") + strlen(name) + 1, - GFP_KERNEL); - if (buffer == NULL) - return ERR_PTR(-ENOMEM); + buffer = malloc(strlen(dir) + strlen("/") + strlen(name) + 1, + M_DEVBUF, M_WAITOK); - strcpy(buffer, dir); - if (!streq(name, "")) { - strcat(buffer, "/"); - strcat(buffer, name); - } + strcpy(buffer, dir); + if (strcmp(name, "")) { + strcat(buffer, "/"); + strcat(buffer, name); + } - return buffer; + return (buffer); } -static char **split(char *strings, unsigned int len, unsigned int *num) +static char ** +split(char *strings, unsigned int len, unsigned int *num) { - char *p, **ret; + char *p, **ret; - /* Count the strings. */ - *num = count_strings(strings, len) + 1; + /* Count the strings. */ + *num = count_strings(strings, len) + 1; - /* Transfer to one big alloc for easy freeing. */ - ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL); - if (!ret) { - kfree(strings); - return ERR_PTR(-ENOMEM); - } - memcpy(&ret[*num], strings, len); - kfree(strings); + /* Transfer to one big alloc for easy freeing. */ + ret = malloc(*num * sizeof(char *) + len, M_DEVBUF, M_WAITOK); + memcpy(&ret[*num], strings, len); + free(strings, M_DEVBUF); - strings = (char *)&ret[*num]; - for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) - ret[(*num)++] = p; + strings = (char *)&ret[*num]; + for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) + ret[(*num)++] = p; - ret[*num] = strings + len; + ret[*num] = strings + len; - return ret; + return ret; } -char **xenbus_directory(struct xenbus_transaction t, - const char *dir, const char *node, unsigned int *num) -{ - char *strings, *path; - unsigned int len = 0; - - path = join(dir, node); - if (IS_ERR(path)) - return (char **)path; - - strings = xs_single(t, XS_DIRECTORY, path, &len); - kfree(path); - if (IS_ERR(strings)) - return (char **)strings; - - return split(strings, len, num); -} -EXPORT_SYMBOL(xenbus_directory); - -/* Check if a path exists. Return 1 if it does. */ -int xenbus_exists(struct xenbus_transaction t, - const char *dir, const char *node) -{ - char **d; - int dir_n; - - d = xenbus_directory(t, dir, node, &dir_n); - if (IS_ERR(d)) - return 0; - kfree(d); - return 1; -} -EXPORT_SYMBOL(xenbus_exists); - -/* Get the value of a single file. - * Returns a kmalloced value: call free() on it after use. - * len indicates length in bytes. +/* + * Return the contents of a directory in *result which should be freed + * with free(*result, M_DEVBUF). */ -void *xenbus_read(struct xenbus_transaction t, - const char *dir, const char *node, unsigned int *len) +int +xenbus_directory(struct xenbus_transaction t, const char *dir, + const char *node, unsigned int *num, char ***result) { - char *path; - void *ret; + char *strings, *path; + unsigned int len = 0; + int error; - path = join(dir, node); - if (IS_ERR(path)) - return (void *)path; + path = join(dir, node); + error = xs_single(t, XS_DIRECTORY, path, &len, (void **) &strings); + free(path, M_DEVBUF); + if (error) + return (error); - printf("xs_read "); - ret = xs_single(t, XS_READ, path, len); - kfree(path); - return ret; + *result = split(strings, len, num); + return (0); } -EXPORT_SYMBOL(xenbus_read); -/* Write the value of a single file. - * Returns -err on failure. +/* + * Check if a path exists. Return 1 if it does. */ -int xenbus_write(struct xenbus_transaction t, - const char *dir, const char *node, const char *string) +int +xenbus_exists(struct xenbus_transaction t, const char *dir, const char *node) { - char *path; - struct kvec iovec[2]; - int ret; + char **d; + int error, dir_n; - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - iovec[0].iov_base = path; - iovec[0].iov_len = strlen(path) + 1; - iovec[1].iov_base = string; - iovec[1].iov_len = strlen(string); - - printf("xenbus_write dir=%s val=%s ", dir, string); - ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); - kfree(path); - return ret; + error = xenbus_directory(t, dir, node, &dir_n, &d); + if (error) + return (0); + free(d, M_DEVBUF); + return (1); } -EXPORT_SYMBOL(xenbus_write); -/* Create a new directory. */ -int xenbus_mkdir(struct xenbus_transaction t, - const char *dir, const char *node) +/* + * Get the value of a single file. Returns the contents in *result + * which should be freed with free(*result, M_DEVBUF) after use. + * The length of the value in bytes is returned in *len. + */ +int +xenbus_read(struct xenbus_transaction t, const char *dir, const char *node, + unsigned int *len, void **result) { - char *path; - int ret; + char *path; + void *ret; + int error; - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - ret = xs_error(xs_single(t, XS_MKDIR, path, NULL)); - kfree(path); - return ret; + path = join(dir, node); + error = xs_single(t, XS_READ, path, len, &ret); + free(path, M_DEVBUF); + if (error) + return (error); + *result = ret; + return (0); } -EXPORT_SYMBOL(xenbus_mkdir); -/* Destroy a file or directory (directories must be empty). */ -int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node) +/* + * Write the value of a single file. Returns error on failure. + */ +int +xenbus_write(struct xenbus_transaction t, const char *dir, const char *node, + const char *string) { - char *path; - int ret; + char *path; + struct iovec iovec[2]; + int error; - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); + path = join(dir, node); - ret = xs_error(xs_single(t, XS_RM, path, NULL)); - kfree(path); - return ret; + iovec[0].iov_base = (void *)(uintptr_t) path; + iovec[0].iov_len = strlen(path) + 1; + iovec[1].iov_base = (void *)(uintptr_t) string; + iovec[1].iov_len = strlen(string); + + error = xs_talkv(t, XS_WRITE, iovec, 2, NULL, NULL); + free(path, M_DEVBUF); + + return (error); } -EXPORT_SYMBOL(xenbus_rm); -/* Start a transaction: changes by others will not be seen during this +/* + * Create a new directory. + */ +int +xenbus_mkdir(struct xenbus_transaction t, const char *dir, const char *node) +{ + char *path; + int ret; + + path = join(dir, node); + ret = xs_single(t, XS_MKDIR, path, NULL, NULL); + free(path, M_DEVBUF); + + return (ret); +} + +/* + * Destroy a file or directory (directories must be empty). + */ +int +xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node) +{ + char *path; + int ret; + + path = join(dir, node); + ret = xs_single(t, XS_RM, path, NULL, NULL); + free(path, M_DEVBUF); + + return (ret); +} + +/* + * Start a transaction: changes by others will not be seen during this * transaction, and changes will not be visible to others until end. */ -int xenbus_transaction_start(struct xenbus_transaction *t) +int +xenbus_transaction_start(struct xenbus_transaction *t) { - char *id_str; + char *id_str; + int error; - sx_slock(&xs_state.suspend_mutex); - id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL); - if (IS_ERR(id_str)) { - sx_sunlock(&xs_state.suspend_mutex); - return PTR_ERR(id_str); - } + sx_slock(&xs_state.suspend_mutex); + error = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL, + (void **) &id_str); + if (error) { + sx_sunlock(&xs_state.suspend_mutex); + return (error); + } - t->id = simple_strtoul(id_str, NULL, 0); - kfree(id_str); + t->id = strtoul(id_str, NULL, 0); + free(id_str, M_DEVBUF); - return 0; + return (0); } -EXPORT_SYMBOL(xenbus_transaction_start); -/* End a transaction. - * If abandon is true, transaction is discarded instead of committed. +/* + * End a transaction. If abandon is true, transaction is discarded + * instead of committed. */ int xenbus_transaction_end(struct xenbus_transaction t, int abort) { - char abortstr[2]; - int err; + char abortstr[2]; + int error; - if (abort) - strcpy(abortstr, "F"); - else - strcpy(abortstr, "T"); + if (abort) + strcpy(abortstr, "F"); + else + strcpy(abortstr, "T"); - printf("xenbus_transaction_end "); - err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); + error = xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL); - sx_sunlock(&xs_state.suspend_mutex); + sx_sunlock(&xs_state.suspend_mutex); - return err; + return (error); } -EXPORT_SYMBOL(xenbus_transaction_end); -/* Single read and scanf: returns -errno or num scanned. */ -int xenbus_scanf(struct xenbus_transaction t, - const char *dir, const char *node, const char *fmt, ...) +/* Single read and scanf: returns zero or errno. */ +int +xenbus_scanf(struct xenbus_transaction t, + const char *dir, const char *node, int *scancountp, const char *fmt, ...) { - va_list ap; - int ret; - char *val; + va_list ap; + int error, ns; + char *val; - val = xenbus_read(t, dir, node, NULL); - if (IS_ERR(val)) - return PTR_ERR(val); + error = xenbus_read(t, dir, node, NULL, (void **) &val); + if (error) + return (error); - va_start(ap, fmt); - ret = vsscanf(val, fmt, ap); - va_end(ap); - kfree(val); - /* Distinctive errno. */ - if (ret == 0) - return -ERANGE; - return ret; + va_start(ap, fmt); + ns = vsscanf(val, fmt, ap); + va_end(ap); + free(val, M_DEVBUF); + /* Distinctive errno. */ + if (ns == 0) + return (ERANGE); + if (scancountp) + *scancountp = ns; + return (0); } -EXPORT_SYMBOL(xenbus_scanf); -/* Single printf and write: returns -errno or 0. */ -int xenbus_printf(struct xenbus_transaction t, - const char *dir, const char *node, const char *fmt, ...) +/* Single printf and write: returns zero or errno. */ +int +xenbus_printf(struct xenbus_transaction t, + const char *dir, const char *node, const char *fmt, ...) { - va_list ap; - int ret; + va_list ap; + int error, ret; #define PRINTF_BUFFER_SIZE 4096 - char *printf_buffer; + char *printf_buffer; - printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); - if (printf_buffer == NULL) - return -ENOMEM; + printf_buffer = malloc(PRINTF_BUFFER_SIZE, M_DEVBUF, M_WAITOK); - va_start(ap, fmt); - ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); - va_end(ap); + va_start(ap, fmt); + ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); + va_end(ap); - BUG_ON(ret > PRINTF_BUFFER_SIZE-1); - ret = xenbus_write(t, dir, node, printf_buffer); + KASSERT(ret <= PRINTF_BUFFER_SIZE-1, ("xenbus_printf: message too large")); + error = xenbus_write(t, dir, node, printf_buffer); - kfree(printf_buffer); + free(printf_buffer, M_DEVBUF); - return ret; + return (error); } -EXPORT_SYMBOL(xenbus_printf); /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ -int xenbus_gather(struct xenbus_transaction t, const char *dir, ...) +int +xenbus_gather(struct xenbus_transaction t, const char *dir, ...) { - va_list ap; - const char *name; - int i, ret = 0; + va_list ap; + const char *name; + int error, i; - for (i = 0; i < 10000; i++) - HYPERVISOR_yield(); + for (i = 0; i < 10000; i++) + HYPERVISOR_yield(); - printf("gather "); - va_start(ap, dir); - while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { - const char *fmt = va_arg(ap, char *); - void *result = va_arg(ap, void *); - char *p; + va_start(ap, dir); + error = 0; + while (error == 0 && (name = va_arg(ap, char *)) != NULL) { + const char *fmt = va_arg(ap, char *); + void *result = va_arg(ap, void *); + char *p; - p = xenbus_read(t, dir, name, NULL); - if (IS_ERR(p)) { - ret = PTR_ERR(p); - break; - } - printf(" %s ", p); - if (fmt) { - if (sscanf(p, fmt, result) == 0) - ret = -EINVAL; - kfree(p); - } else - *(char **)result = p; - } - va_end(ap); - printf("\n"); - return ret; -} -EXPORT_SYMBOL(xenbus_gather); + error = xenbus_read(t, dir, name, NULL, (void **) &p); + if (error) + break; -static int xs_watch(const char *path, const char *token) -{ - struct kvec iov[2]; + if (fmt) { + if (sscanf(p, fmt, result) == 0) + error = EINVAL; + free(p, M_DEVBUF); + } else + *(char **)result = p; + } + va_end(ap); - iov[0].iov_base = path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = token; - iov[1].iov_len = strlen(token) + 1; - - return xs_error(xs_talkv(XBT_NIL, XS_WATCH, iov, - ARRAY_SIZE(iov), NULL)); + return (error); } -static int xs_unwatch(const char *path, const char *token) +static int +xs_watch(const char *path, const char *token) { - struct kvec iov[2]; + struct iovec iov[2]; - iov[0].iov_base = path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = token; - iov[1].iov_len = strlen(token) + 1; + iov[0].iov_base = (void *)(uintptr_t) path; + iov[0].iov_len = strlen(path) + 1; + iov[1].iov_base = (void *)(uintptr_t) token; + iov[1].iov_len = strlen(token) + 1; - return xs_error(xs_talkv(XBT_NIL, XS_UNWATCH, iov, - ARRAY_SIZE(iov), NULL)); + return (xs_talkv(XBT_NIL, XS_WATCH, iov, 2, NULL, NULL)); } -static struct xenbus_watch *find_watch(const char *token) +static int +xs_unwatch(const char *path, const char *token) { - struct xenbus_watch *i, *cmp; + struct iovec iov[2]; - cmp = (void *)simple_strtoul(token, NULL, 16); + iov[0].iov_base = (void *)(uintptr_t) path; + iov[0].iov_len = strlen(path) + 1; + iov[1].iov_base = (void *)(uintptr_t) token; + iov[1].iov_len = strlen(token) + 1; - LIST_FOREACH(i, &watches, list) - if (i == cmp) - return i; + return (xs_talkv(XBT_NIL, XS_UNWATCH, iov, 2, NULL, NULL)); +} - return NULL; +static struct xenbus_watch * +find_watch(const char *token) +{ + struct xenbus_watch *i, *cmp; + + cmp = (void *)strtoul(token, NULL, 16); + + LIST_FOREACH(i, &watches, list) + if (i == cmp) + return (i); + + return (NULL); } /* Register callback to watch this node. */ -int register_xenbus_watch(struct xenbus_watch *watch) +int +register_xenbus_watch(struct xenbus_watch *watch) { - /* Pointer in ascii is the token. */ - char token[sizeof(watch) * 2 + 1]; - int err; + /* Pointer in ascii is the token. */ + char token[sizeof(watch) * 2 + 1]; + int error; - sprintf(token, "%lX", (long)watch); + sprintf(token, "%lX", (long)watch); - sx_slock(&xs_state.suspend_mutex); + sx_slock(&xs_state.suspend_mutex); - mtx_lock(&watches_lock); - BUG_ON(find_watch(token) != NULL); - LIST_INSERT_HEAD(&watches, watch, list); - mtx_unlock(&watches_lock); + mtx_lock(&watches_lock); + KASSERT(find_watch(token) == NULL, ("watch already registered")); + LIST_INSERT_HEAD(&watches, watch, list); + mtx_unlock(&watches_lock); - err = xs_watch(watch->node, token); + error = xs_watch(watch->node, token); - /* Ignore errors due to multiple registration. */ - if ((err != 0) && (err != -EEXIST)) { - mtx_lock(&watches_lock); - LIST_REMOVE(watch, list); - mtx_unlock(&watches_lock); - } - - sx_sunlock(&xs_state.suspend_mutex); - - return err; -} -EXPORT_SYMBOL(register_xenbus_watch); - -void unregister_xenbus_watch(struct xenbus_watch *watch) -{ - struct xs_stored_msg *msg, *tmp; - char token[sizeof(watch) * 2 + 1]; - int err; - - sprintf(token, "%lX", (long)watch); - - sx_slock(&xs_state.suspend_mutex); - + /* Ignore errors due to multiple registration. */ + if (error == EEXIST) { mtx_lock(&watches_lock); - BUG_ON(!find_watch(token)); LIST_REMOVE(watch, list); mtx_unlock(&watches_lock); + } - err = xs_unwatch(watch->node, token); - if (err) - log(LOG_WARNING, "XENBUS Failed to release watch %s: %i\n", - watch->node, err); + sx_sunlock(&xs_state.suspend_mutex); - sx_sunlock(&xs_state.suspend_mutex); + return (error); +} + +void +unregister_xenbus_watch(struct xenbus_watch *watch) +{ + struct xs_stored_msg *msg, *tmp; + char token[sizeof(watch) * 2 + 1]; + int error; + + sprintf(token, "%lX", (long)watch); + + sx_slock(&xs_state.suspend_mutex); + + mtx_lock(&watches_lock); + KASSERT(find_watch(token), ("watch not registered")); + LIST_REMOVE(watch, list); + mtx_unlock(&watches_lock); + + error = xs_unwatch(watch->node, token); + if (error) + log(LOG_WARNING, "XENBUS Failed to release watch %s: %i\n", + watch->node, error); + + sx_sunlock(&xs_state.suspend_mutex); + + /* Cancel pending watch events. */ + mtx_lock(&watch_events_lock); + TAILQ_FOREACH_SAFE(msg, &watch_events, list, tmp) { + if (msg->u.watch.handle != watch) + continue; + TAILQ_REMOVE(&watch_events, msg, list); + free(msg->u.watch.vec, M_DEVBUF); + free(msg, M_DEVBUF); + } + mtx_unlock(&watch_events_lock); + + /* Flush any currently-executing callback, unless we are it. :-) */ + if (curproc->p_pid != xenwatch_pid) { + sx_xlock(&xenwatch_mutex); + sx_xunlock(&xenwatch_mutex); + } +} + +void +xs_suspend(void) +{ + + sx_xlock(&xs_state.suspend_mutex); + sx_xlock(&xs_state.request_mutex); +} + +void +xs_resume(void) +{ + struct xenbus_watch *watch; + char token[sizeof(watch) * 2 + 1]; + + sx_xunlock(&xs_state.request_mutex); + + /* No need for watches_lock: the suspend_mutex is sufficient. */ + LIST_FOREACH(watch, &watches, list) { + sprintf(token, "%lX", (long)watch); + xs_watch(watch->node, token); + } + + sx_xunlock(&xs_state.suspend_mutex); +} + +static void +xenwatch_thread(void *unused) +{ + struct xs_stored_msg *msg; + + for (;;) { - /* Cancel pending watch events. */ mtx_lock(&watch_events_lock); - TAILQ_FOREACH_SAFE(msg, &watch_events, list, tmp) { - if (msg->u.watch.handle != watch) - continue; - list_del(&watch_events, msg); - kfree(msg->u.watch.vec); - kfree(msg); - } + while (TAILQ_EMPTY(&watch_events)) + mtx_sleep(&watch_events_waitq, + &watch_events_lock, + PWAIT | PCATCH, "waitev", hz/10); + + mtx_unlock(&watch_events_lock); + sx_xlock(&xenwatch_mutex); + + mtx_lock(&watch_events_lock); + msg = TAILQ_FIRST(&watch_events); + if (msg) + TAILQ_REMOVE(&watch_events, msg, list); mtx_unlock(&watch_events_lock); - /* Flush any currently-executing callback, unless we are it. :-) */ - if (curproc->p_pid != xenwatch_pid) { - sx_xlock(&xenwatch_mutex); - sx_xunlock(&xenwatch_mutex); + if (msg != NULL) { + msg->u.watch.handle->callback( + msg->u.watch.handle, + (const char **)msg->u.watch.vec, + msg->u.watch.vec_size); + free(msg->u.watch.vec, M_DEVBUF); + free(msg, M_DEVBUF); } -} -EXPORT_SYMBOL(unregister_xenbus_watch); -void xs_suspend(void) -{ - sx_xlock(&xs_state.suspend_mutex); - sx_xlock(&xs_state.request_mutex); + sx_xunlock(&xenwatch_mutex); + } } -void xs_resume(void) +static int +xs_process_msg(enum xsd_sockmsg_type *type) { - struct xenbus_watch *watch; - char token[sizeof(watch) * 2 + 1]; - - sx_xunlock(&xs_state.request_mutex); - - /* No need for watches_lock: the suspend_mutex is sufficient. */ - LIST_FOREACH(watch, &watches, list) { - sprintf(token, "%lX", (long)watch); - xs_watch(watch->node, token); - } - - sx_xunlock(&xs_state.suspend_mutex); -} - -static void xenwatch_thread(void *unused) -{ - struct xs_stored_msg *msg; - - DELAY(100000); - while (xenwatch_inline) { - printf("xenwatch inline still running\n"); - DELAY(100000); - } + struct xs_stored_msg *msg; + char *body; + int error; - - for (;;) { + msg = malloc(sizeof(*msg), M_DEVBUF, M_WAITOK); + mtx_lock(&xs_state.reply_lock); + error = xb_read(&msg->hdr, sizeof(msg->hdr), &xs_state.reply_lock.lock_object); + mtx_unlock(&xs_state.reply_lock); + if (error) { + free(msg, M_DEVBUF); + return (error); + } - while (list_empty(&watch_events)) - tsleep(&watch_events_waitq, - PWAIT | PCATCH, "waitev", hz/10); + body = malloc(msg->hdr.len + 1, M_DEVBUF, M_WAITOK); + mtx_lock(&xs_state.reply_lock); + error = xb_read(body, msg->hdr.len, &xs_state.reply_lock.lock_object); + mtx_unlock(&xs_state.reply_lock); + if (error) { + free(body, M_DEVBUF); + free(msg, M_DEVBUF); + return (error); + } + body[msg->hdr.len] = '\0'; + + *type = msg->hdr.type; + if (msg->hdr.type == XS_WATCH_EVENT) { + msg->u.watch.vec = split(body, msg->hdr.len, + &msg->u.watch.vec_size); - sx_xlock(&xenwatch_mutex); - - mtx_lock(&watch_events_lock); - msg = TAILQ_FIRST(&watch_events); - if (msg) - list_del(&watch_events, msg); - mtx_unlock(&watch_events_lock); - - if (msg != NULL) { - msg->u.watch.handle->callback( - msg->u.watch.handle, - (const char **)msg->u.watch.vec, - msg->u.watch.vec_size); - kfree(msg->u.watch.vec); - kfree(msg); - } - - sx_xunlock(&xenwatch_mutex); - } -} - -static int xs_process_msg(enum xsd_sockmsg_type *type) -{ - struct xs_stored_msg *msg; - char *body; - int err; - - msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (msg == NULL) - return -ENOMEM; - - err = xb_read(&msg->hdr, sizeof(msg->hdr)); - if (err) { - kfree(msg); - return err; - } - - body = kmalloc(msg->hdr.len + 1, GFP_KERNEL); - if (body == NULL) { - kfree(msg); - return -ENOMEM; - } - - err = xb_read(body, msg->hdr.len); - if (err) { - kfree(body); - kfree(msg); - return err; - } - body[msg->hdr.len] = '\0'; - - *type = msg->hdr.type; - if (msg->hdr.type == XS_WATCH_EVENT) { - msg->u.watch.vec = split(body, msg->hdr.len, - &msg->u.watch.vec_size); - if (IS_ERR(msg->u.watch.vec)) { - kfree(msg); - return PTR_ERR(msg->u.watch.vec); - } - - mtx_lock(&watches_lock); - msg->u.watch.handle = find_watch( - msg->u.watch.vec[XS_WATCH_TOKEN]); - if (msg->u.watch.handle != NULL) { - mtx_lock(&watch_events_lock); - TAILQ_INSERT_TAIL(&watch_events, msg, list); - wakeup(&watch_events_waitq); - mtx_unlock(&watch_events_lock); - } else { - kfree(msg->u.watch.vec); - kfree(msg); - } - mtx_unlock(&watches_lock); + mtx_lock(&watches_lock); + msg->u.watch.handle = find_watch( + msg->u.watch.vec[XS_WATCH_TOKEN]); + if (msg->u.watch.handle != NULL) { + mtx_lock(&watch_events_lock); + TAILQ_INSERT_TAIL(&watch_events, msg, list); + wakeup(&watch_events_waitq); + mtx_unlock(&watch_events_lock); } else { - printf("event=%d ", *type); - msg->u.reply.body = body; - mtx_lock(&xs_state.reply_lock); - TAILQ_INSERT_TAIL(&xs_state.reply_list, msg, list); - wakeup(&xs_state.reply_waitq); - mtx_unlock(&xs_state.reply_lock); + free(msg->u.watch.vec, M_DEVBUF); + free(msg, M_DEVBUF); } - if (*type == XS_WATCH_EVENT) - printf("\n"); + mtx_unlock(&watches_lock); + } else { + msg->u.reply.body = body; + mtx_lock(&xs_state.reply_lock); + TAILQ_INSERT_TAIL(&xs_state.reply_list, msg, list); + wakeup(&xs_state.reply_waitq); + mtx_unlock(&xs_state.reply_lock); + } - return 0; + return 0; } -static void xenbus_thread(void *unused) +static void +xenbus_thread(void *unused) { - int err; - enum xsd_sockmsg_type type; + int error; + enum xsd_sockmsg_type type; + xenbus_running = 1; - DELAY(10000); - xenbus_running = 1; - pause("xenbus", hz/10); - - for (;;) { - err = xs_process_msg(&type); - if (err) - printf("XENBUS error %d while reading " - "message\n", err); - - } + for (;;) { + error = xs_process_msg(&type); + if (error) + printf("XENBUS error %d while reading message\n", + error); + } } -int xs_init(void) -{ - int err; - struct proc *p; +#ifdef XENHVM +static unsigned long xen_store_mfn; +char *xen_store; - TAILQ_INIT(&xs_state.reply_list); - TAILQ_INIT(&watch_events); - sx_init(&xenwatch_mutex, "xenwatch"); +static inline unsigned long +hvm_get_parameter(int index) +{ + struct xen_hvm_param xhv; + int error; + + xhv.domid = DOMID_SELF; + xhv.index = index; + error = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv); + if (error) { + printf("hvm_get_parameter: failed to get %d, error %d\n", + index, error); + return (0); + } + return (xhv.value); +} + +#endif + +int +xs_init(void) +{ + int error; + struct proc *p; + +#ifdef XENHVM + xen_store_evtchn = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN); + xen_store_mfn = hvm_get_parameter(HVM_PARAM_STORE_PFN); + xen_store = pmap_mapdev(xen_store_mfn * PAGE_SIZE, PAGE_SIZE); +#else + xen_store_evtchn = xen_start_info->store_evtchn; +#endif + + TAILQ_INIT(&xs_state.reply_list); + TAILQ_INIT(&watch_events); + sx_init(&xenwatch_mutex, "xenwatch"); - mtx_init(&xs_state.reply_lock, "state reply", NULL, MTX_DEF); - sx_init(&xs_state.request_mutex, "xenstore request"); - sx_init(&xs_state.suspend_mutex, "xenstore suspend"); + mtx_init(&xs_state.reply_lock, "state reply", NULL, MTX_DEF); + sx_init(&xs_state.request_mutex, "xenstore request"); + sx_init(&xs_state.suspend_mutex, "xenstore suspend"); #if 0 - mtx_init(&xs_state.suspend_mutex, "xenstore suspend", NULL, MTX_DEF); - sema_init(&xs_state.request_mutex, 1, "xenstore request"); - sema_init(&xenwatch_mutex, 1, "xenwatch"); + mtx_init(&xs_state.suspend_mutex, "xenstore suspend", NULL, MTX_DEF); + sema_init(&xs_state.request_mutex, 1, "xenstore request"); + sema_init(&xenwatch_mutex, 1, "xenwatch"); #endif - mtx_init(&watches_lock, "watches", NULL, MTX_DEF); - mtx_init(&watch_events_lock, "watch events", NULL, MTX_DEF); + mtx_init(&watches_lock, "watches", NULL, MTX_DEF); + mtx_init(&watch_events_lock, "watch events", NULL, MTX_DEF); - /* Initialize the shared memory rings to talk to xenstored */ - err = xb_init_comms(); - if (err) - return err; + /* Initialize the shared memory rings to talk to xenstored */ + error = xb_init_comms(); + if (error) + return (error); - err = kproc_create(xenwatch_thread, NULL, &p, - RFHIGHPID, 0, "xenwatch"); - if (err) - return err; - xenwatch_pid = p->p_pid; + xenwatch_running = 1; + error = kproc_create(xenwatch_thread, NULL, &p, + RFHIGHPID, 0, "xenwatch"); + if (error) + return (error); + xenwatch_pid = p->p_pid; - err = kproc_create(xenbus_thread, NULL, NULL, - RFHIGHPID, 0, "xenbus"); + error = kproc_create(xenbus_thread, NULL, NULL, + RFHIGHPID, 0, "xenbus"); - return err; + return (error); } - - -/* - * Local variables: - * c-file-style: "bsd" - * indent-tabs-mode: t - * c-indent-level: 4 - * c-basic-offset: 8 - * tab-width: 4 - * End: - */ diff --git a/sys/xen/xenbus/xenbusvar.h b/sys/xen/xenbus/xenbusvar.h index 1331c4377fe0..651166421eab 100644 --- a/sys/xen/xenbus/xenbusvar.h +++ b/sys/xen/xenbus/xenbusvar.h @@ -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);