示例#1
0
void
xenconscn_putc(dev_t dev, int c)
{
    int s = spltty();
    XENCONS_RING_IDX cons, prod;

    if (xendomain_is_dom0()) {
        u_char buf[1];

        buf[0] = c;
        (void)HYPERVISOR_console_io(CONSOLEIO_write, 1, buf);
    } else {
        XENPRINTK(("xenconscn_putc(%c)\n", c));

        cons = xencons_interface->out_cons;
        prod = xencons_interface->out_prod;
        xen_rmb();
        while (prod == cons + sizeof(xencons_interface->out)) {
            cons = xencons_interface->out_cons;
            prod = xencons_interface->out_prod;
            xen_rmb();
        }
        xencons_interface->out[MASK_XENCONS_IDX(xencons_interface->out_prod,
                                                xencons_interface->out)] = c;
        xen_rmb();
        xencons_interface->out_prod++;
        xen_rmb();
        hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn);
        splx(s);
    }
}
示例#2
0
int
xb_read(void *data, unsigned len)
{
	struct xenstore_domain_interface *intf = xenstore_domain_interface();
	XENSTORE_RING_IDX cons, prod;

	int s = spltty();

	while (len != 0) {
		unsigned int avail;
		const char *src;

		while (intf->rsp_cons == intf->rsp_prod)
			tsleep(&xenstore_interface, PRIBIO, "rdst", 0);

		/* Read indexes, then verify. */
		cons = intf->rsp_cons;
		prod = intf->rsp_prod;
		xen_rmb();
		if (!check_indexes(cons, prod)) {
			XENPRINTF(("xb_read EIO\n"));
			splx(s);
			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. */
		xen_rmb();

		memcpy(data, src, avail);
		data = (char *)data + avail;
		len -= avail;

		/* Other side must not see free space until we've copied out */
		xen_rmb();
		intf->rsp_cons += avail;
		xen_rmb();

		XENPRINTF(("Finished read of %i bytes (%i to go)\n",
		    avail, len));

		hypervisor_notify_via_evtchn(xen_start_info.store_evtchn);
	}

	splx(s);
	return 0;
}
示例#3
0
int
xb_write(const void *data, unsigned len)
{
	struct xenstore_domain_interface *intf = xenstore_domain_interface();
	XENSTORE_RING_IDX cons, prod;

	int s = spltty();

	while (len != 0) {
		void *dst;
		unsigned int avail;

		while ((intf->req_prod - intf->req_cons) == XENSTORE_RING_SIZE) {
			XENPRINTF(("xb_write tsleep\n"));
			tsleep(&xenstore_interface, PRIBIO, "wrst", 0);
			XENPRINTF(("xb_write tsleep done\n"));
		}

		/* Read indexes, then verify. */
		cons = intf->req_cons;
		prod = intf->req_prod;
		xen_rmb();
		if (!check_indexes(cons, prod)) {
			splx(s);
			return EIO;
		}

		dst = get_output_chunk(cons, prod, intf->req, &avail);
		if (avail == 0)
			continue;
		if (avail > len)
			avail = len;

		memcpy(dst, data, avail);
		data = (const char *)data + avail;
		len -= avail;

		/* Other side must not see new header until data is there. */
		xen_rmb();
		intf->req_prod += avail;
		xen_rmb();

		hypervisor_notify_via_evtchn(xen_start_info.store_evtchn);
	}

	splx(s);
	return 0;
}
示例#4
0
/* Non-privileged console interrupt routine */
static int
xencons_handler(void *arg)
{
    struct xencons_softc *sc = arg;
    XENCONS_RING_IDX cons, prod, len;
    int s = spltty();

    if (sc->polling) {
        splx(s);
        return 1;
    }


#define XNC_IN (xencons_interface->in)

    cons = xencons_interface->in_cons;
    prod = xencons_interface->in_prod;
    xen_rmb();
    while (cons != prod) {
        if (MASK_XENCONS_IDX(cons, XNC_IN) <
                MASK_XENCONS_IDX(prod, XNC_IN))
            len = MASK_XENCONS_IDX(prod, XNC_IN) -
                  MASK_XENCONS_IDX(cons, XNC_IN);
        else
            len = sizeof(XNC_IN) - MASK_XENCONS_IDX(cons, XNC_IN);

        xencons_tty_input(sc, __UNVOLATILE(
                              &XNC_IN[MASK_XENCONS_IDX(cons, XNC_IN)]), len);
        if (__predict_false(xencons_interface->in_cons != cons)) {
            /* catch up with xenconscn_getc() */
            cons = xencons_interface->in_cons;
            prod = xencons_interface->in_prod;
            xen_rmb();
        } else {
            cons += len;
            xen_wmb();
            xencons_interface->in_cons = cons;
            xen_wmb();
        }
    }
    hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn);
    splx(s);
    return 1;
#undef XNC_IN
}
示例#5
0
static int
xenevt_fioctl(struct file *fp, u_long cmd, void *addr)
{
	struct xenevt_d *d = fp->f_data;
	evtchn_op_t op = { .cmd = 0 };
	int error;

	switch(cmd) {
	case EVTCHN_RESET:
	case IOCTL_EVTCHN_RESET:
		mutex_enter(&d->lock);
		d->ring_read = d->ring_write = 0;
		d->flags = 0;
		mutex_exit(&d->lock);
		break;
	case IOCTL_EVTCHN_BIND_VIRQ:
	{
		struct ioctl_evtchn_bind_virq *bind_virq = addr;
		op.cmd = EVTCHNOP_bind_virq;
		op.u.bind_virq.virq = bind_virq->virq;
		op.u.bind_virq.vcpu = 0;
		if ((error = HYPERVISOR_event_channel_op(&op))) {
			printf("IOCTL_EVTCHN_BIND_VIRQ failed: virq %d error %d\n", bind_virq->virq, error);
			return -error;
		}
		bind_virq->port = op.u.bind_virq.port;
		mutex_enter(&devevent_lock);
		KASSERT(devevent[bind_virq->port] == NULL);
		devevent[bind_virq->port] = d;
		mutex_exit(&devevent_lock);
		xen_atomic_set_bit(&d->ci->ci_evtmask[0], bind_virq->port);
		hypervisor_unmask_event(bind_virq->port);
		break;
	}
	case IOCTL_EVTCHN_BIND_INTERDOMAIN:
	{
		struct ioctl_evtchn_bind_interdomain *bind_intd = addr;
		op.cmd = EVTCHNOP_bind_interdomain;
		op.u.bind_interdomain.remote_dom = bind_intd->remote_domain;
		op.u.bind_interdomain.remote_port = bind_intd->remote_port;
		if ((error = HYPERVISOR_event_channel_op(&op)))
			return -error;
		bind_intd->port = op.u.bind_interdomain.local_port;
		mutex_enter(&devevent_lock);
		KASSERT(devevent[bind_intd->port] == NULL);
		devevent[bind_intd->port] = d;
		mutex_exit(&devevent_lock);
		xen_atomic_set_bit(&d->ci->ci_evtmask[0], bind_intd->port);
		hypervisor_unmask_event(bind_intd->port);
		break;
	}
	case IOCTL_EVTCHN_BIND_UNBOUND_PORT:
	{
		struct ioctl_evtchn_bind_unbound_port *bind_unbound = addr;
		op.cmd = EVTCHNOP_alloc_unbound;
		op.u.alloc_unbound.dom = DOMID_SELF;
		op.u.alloc_unbound.remote_dom = bind_unbound->remote_domain;
		if ((error = HYPERVISOR_event_channel_op(&op)))
			return -error;
		bind_unbound->port = op.u.alloc_unbound.port;
		mutex_enter(&devevent_lock);
		KASSERT(devevent[bind_unbound->port] == NULL);
		devevent[bind_unbound->port] = d;
		mutex_exit(&devevent_lock);
		xen_atomic_set_bit(&d->ci->ci_evtmask[0], bind_unbound->port);
		hypervisor_unmask_event(bind_unbound->port);
		break;
	}
	case IOCTL_EVTCHN_UNBIND:
	{
		struct ioctl_evtchn_unbind *unbind = addr;
		
		if (unbind->port > NR_EVENT_CHANNELS)
			return EINVAL;
		mutex_enter(&devevent_lock);
		if (devevent[unbind->port] != d) {
			mutex_exit(&devevent_lock);
			return ENOTCONN;
		}
		devevent[unbind->port] = NULL;
		mutex_exit(&devevent_lock);
		hypervisor_mask_event(unbind->port);
		xen_atomic_clear_bit(&d->ci->ci_evtmask[0], unbind->port);
		op.cmd = EVTCHNOP_close;
		op.u.close.port = unbind->port;
		if ((error = HYPERVISOR_event_channel_op(&op)))
			return -error;
		break;
	}
	case IOCTL_EVTCHN_NOTIFY:
	{
		struct ioctl_evtchn_notify *notify = addr;
		
		if (notify->port > NR_EVENT_CHANNELS)
			return EINVAL;
		mutex_enter(&devevent_lock);
		if (devevent[notify->port] != d) {
			mutex_exit(&devevent_lock);
			return ENOTCONN;
		}
		hypervisor_notify_via_evtchn(notify->port);
		mutex_exit(&devevent_lock);
		break;
	}
	case FIONBIO:
		break;
	default:
		return EINVAL;
	}
	return 0;
}

/*      
 * Support for poll() system call  
 *
 * Return true if the specific operation will not block indefinitely.
 */      

static int
xenevt_fpoll(struct file *fp, int events)
{
	struct xenevt_d *d = fp->f_data;
	int revents = events & (POLLOUT | POLLWRNORM); /* we can always write */

	mutex_enter(&d->lock);
	if (events & (POLLIN | POLLRDNORM)) {
		if (d->ring_read != d->ring_write) {
			revents |= events & (POLLIN | POLLRDNORM);
		} else {
			/* Record that someone is waiting */
			selrecord(curlwp, &d->sel);
		}
	}
	mutex_exit(&d->lock);
	return (revents);
}
示例#6
0
void
xencons_start(struct tty *tp)
{
    struct clist *cl;
    int s;

    s = spltty();
    if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
        goto out;
    tp->t_state |= TS_BUSY;
    splx(s);

    /*
     * We need to do this outside spl since it could be fairly
     * expensive and we don't want our serial ports to overflow.
     */
    cl = &tp->t_outq;
    if (xendomain_is_dom0()) {
        int len, r;
        u_char buf[XENCONS_BURST+1];

        len = q_to_b(cl, buf, XENCONS_BURST);
        while (len > 0) {
            r = HYPERVISOR_console_io(CONSOLEIO_write, len, buf);
            if (r <= 0)
                break;
            len -= r;
        }
    } else {
        XENCONS_RING_IDX cons, prod, len;

#define XNC_OUT (xencons_interface->out)
        cons = xencons_interface->out_cons;
        prod = xencons_interface->out_prod;
        xen_rmb();
        while (prod != cons + sizeof(xencons_interface->out)) {
            if (MASK_XENCONS_IDX(prod, XNC_OUT) <
                    MASK_XENCONS_IDX(cons, XNC_OUT)) {
                len = MASK_XENCONS_IDX(cons, XNC_OUT) -
                      MASK_XENCONS_IDX(prod, XNC_OUT);
            } else {
                len = sizeof(XNC_OUT) -
                      MASK_XENCONS_IDX(prod, XNC_OUT);
            }
            len = q_to_b(cl, __UNVOLATILE(
                             &XNC_OUT[MASK_XENCONS_IDX(prod, XNC_OUT)]), len);
            if (len == 0)
                break;
            prod = prod + len;
        }
        xen_wmb();
        xencons_interface->out_prod = prod;
        xen_wmb();
        hypervisor_notify_via_evtchn(xen_start_info.console.domU.evtchn);
#undef XNC_OUT
    }

    s = spltty();
    tp->t_state &= ~TS_BUSY;
    if (ttypull(tp)) {
        tp->t_state |= TS_TIMEOUT;
        callout_schedule(&tp->t_rstrt_ch, 1);
    }
out:
    splx(s);
}