Example #1
0
static int evtchn_suspend(checkpoint_state* s)
{
    int rc;

    rc = xc_evtchn_notify(s->xce, s->suspend_evtchn);
    if (rc < 0) {
	snprintf(errbuf, sizeof(errbuf),
		 "failed to notify suspend event channel: %d", rc);
	s->errstr = errbuf;

	return -1;
    }

    do
	if (!(rc = pollfd(s, xc_evtchn_fd(s->xce))))
	    rc = xc_evtchn_pending(s->xce);
    while (rc >= 0 && rc != s->suspend_evtchn);
    if (rc <= 0)
	return -1;

    if (xc_evtchn_unmask(s->xce, s->suspend_evtchn) < 0) {
	snprintf(errbuf, sizeof(errbuf),
		 "failed to unmask suspend notification channel: %d", rc);
	s->errstr = errbuf;

	return -1;
    }

    return 0;
}
Example #2
0
File: io.c Project: CPFL/gxen
void libxenvchan_close(struct libxenvchan *ctrl)
{
	if (!ctrl)
		return;
	if (ctrl->read.order >= PAGE_SHIFT)
		munmap(ctrl->read.buffer, 1 << ctrl->read.order);
	if (ctrl->write.order >= PAGE_SHIFT)
		munmap(ctrl->write.buffer, 1 << ctrl->write.order);
	if (ctrl->ring) {
		if (ctrl->is_server) {
			ctrl->ring->srv_live = 0;
			xc_gntshr_munmap(ctrl->gntshr, ctrl->ring, PAGE_SIZE);
		} else {
			ctrl->ring->cli_live = 0;
			xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, PAGE_SIZE);
		}
	}
	if (ctrl->event) {
		if (ctrl->event_port >= 0 && ctrl->ring)
			xc_evtchn_notify(ctrl->event, ctrl->event_port);
		xc_evtchn_close(ctrl->event);
	}
	if (ctrl->is_server) {
		if (ctrl->gntshr)
			xc_gntshr_close(ctrl->gntshr);
	} else {
		if (ctrl->gnttab)
			xc_gnttab_close(ctrl->gnttab);
	}
	free(ctrl);
}
Example #3
0
static void handle_aio_events(struct fs_mount *mount)
{
    int fd, ret, count, i, notify;
    evtchn_port_t port;
    /* AIO control block for the evtchn file destriptor */
    struct aiocb evtchn_cb;
    const struct aiocb * cb_list[mount->nr_entries];
    int request_ids[mount->nr_entries];

    /* Prepare the AIO control block for evtchn */ 
    fd = xc_evtchn_fd(mount->evth); 
    bzero(&evtchn_cb, sizeof(struct aiocb));
    evtchn_cb.aio_fildes = fd;
    evtchn_cb.aio_nbytes = sizeof(port);
    evtchn_cb.aio_buf = &port;
    assert(aio_read(&evtchn_cb) == 0);

wait_again:   
    /* Create list of active AIO requests */
    count = 0;
    for(i=0; i<mount->nr_entries; i++)
        if(mount->requests[i].active)
        {
            cb_list[count] = &mount->requests[i].aiocb;
            request_ids[count] = i;
            count++;
        }
    /* Add the event channel at the end of the list. Event channel needs to be
     * handled last as it exits this function. */
    cb_list[count] = &evtchn_cb;
    request_ids[count] = -1;
    count++;

    /* Block till an AIO requset finishes, or we get an event */ 
    while(1) {
	int ret = aio_suspend(cb_list, count, NULL);
	if (!ret)
	    break;
	assert(errno == EINTR);
    }
    for(i=0; i<count; i++)
        if(aio_error(cb_list[i]) != EINPROGRESS)
        {
            if(request_ids[i] >= 0)
                dispatch_response(mount, request_ids[i]);
            else
                goto read_event_channel;
        }
 
    RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
    printf("Pushed responces and notify=%d\n", notify);
    if(notify)
        xc_evtchn_notify(mount->evth, mount->local_evtchn);
    
    goto wait_again;

read_event_channel:    
    assert(aio_return(&evtchn_cb) == sizeof(evtchn_port_t)); 
    assert(xc_evtchn_unmask(mount->evth, mount->local_evtchn) >= 0);
}
CAMLprim value stub_eventchn_notify(value xce, value port)
{
  if(xc_evtchn_notify(_H(xce), Int_val(port)) == -1)
    caml_failwith("evtchn notify failed");

  return Val_unit;
}
Example #5
0
static void xenfb_on_kbd_event(struct xenfb *xenfb)
{
	struct xenkbd_page *page = xenfb->kbd.page;

	/* We don't understand any keyboard events, so just ignore them. */
	if (page->out_prod == page->out_cons)
		return;
	page->out_cons = page->out_prod;
	xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
}
CAMLprim value stub_eventchn_notify(value xce, value port)
{
  CAMLparam2(xce, port);
  if(xc_evtchn_notify(_H(xce), Int_val(port)) == -1)
    {
      perror("xc_evtchn_notify");
      caml_failwith(strerror(errno));
    }

  CAMLreturn(Val_unit);
}
CAMLprim value stub_eventchn_notify(value xce, value port)
{
	CAMLparam2(xce, port);
	int rc;

	rc = xc_evtchn_notify(_H(xce), Int_val(port));
	if (rc == -1)
		caml_failwith("evtchn notify failed");

	CAMLreturn(Val_unit);
}
Example #8
0
File: io.c Project: CPFL/gxen
static inline int send_notify(struct libxenvchan *ctrl, uint8_t bit)
{
	uint8_t *notify, prev;
	xen_mb(); /* caller updates indexes /before/ we decode to notify */
	notify = ctrl->is_server ? &ctrl->ring->srv_notify : &ctrl->ring->cli_notify;
	prev = __sync_fetch_and_and(notify, ~bit);
	if (prev & bit)
		return xc_evtchn_notify(ctrl->event, ctrl->event_port);
	else
		return 0;
}
Example #9
0
static void xenfb_on_fb_event(struct xenfb *xenfb)
{
	uint32_t prod, cons;
	struct xenfb_page *page = xenfb->fb.page;

	prod = page->out_prod;
	if (prod == page->out_cons)
		return;
	xen_rmb();		/* ensure we see ring contents up to prod */
	for (cons = page->out_cons; cons != prod; cons++) {
		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
		int x, y, w, h;

		switch (event->type) {
		case XENFB_TYPE_UPDATE:
			x = MAX(event->update.x, 0);
			y = MAX(event->update.y, 0);
			w = MIN(event->update.width, xenfb->width - x);
			h = MIN(event->update.height, xenfb->height - y);
			if (w < 0 || h < 0) {
				fprintf(stderr, "%s bogus update ignored\n",
					xenfb->fb.nodename);
				break;
			}
			if (x != event->update.x || y != event->update.y
			    || w != event->update.width
			    || h != event->update.height) {
				fprintf(stderr, "%s bogus update clipped\n",
					xenfb->fb.nodename);
			}
			xenfb_guest_copy(xenfb, x, y, w, h);
			break;
		case XENFB_TYPE_RESIZE:
			if (xenfb_configure_fb(xenfb, xenfb->fb_len,
					       event->resize.width,
					       event->resize.height,
					       event->resize.depth,
					       xenfb->fb_len,
					       event->resize.offset,
					       event->resize.stride) < 0)
				break;
			if (xenfb->ds->dpy_resize_shared)
			    dpy_resize_shared(xenfb->ds, xenfb->width, xenfb->height, xenfb->depth, xenfb->row_stride, xenfb->pixels + xenfb->offset);
			else
			    dpy_resize(xenfb->ds, xenfb->width, xenfb->height);
			xenfb_invalidate(xenfb);
			break;
		}
	}
	xen_mb();		/* ensure we're done with ring contents */
	page->out_cons = cons;
	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
}
Example #10
0
static void xenfb_send_event(struct xenfb *xenfb, union xenfb_in_event *event)
{
	uint32_t prod;
	struct xenfb_page *page = xenfb->fb.page;

	prod = page->in_prod;
	/* caller ensures !xenfb_queue_full() */
	xen_mb();                   /* ensure ring space available */
	XENFB_IN_RING_REF(page, prod) = *event;
	xen_wmb();                  /* ensure ring contents visible */
	page->in_prod = prod + 1;

	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
}
Example #11
0
static void writeRaw(ivc_connection_t *con, void *buffer, uint32_t size)
{
  uint32_t off = con->output->produced % con->outsize;
  void *basep = (void*)((uintptr_t)con->outbuf + off);

  if(off + size > con->outsize) {
    uint32_t part1sz = con->outsize - off;
    memcpy(basep, buffer, part1sz);
    memcpy(con->outbuf, (void*)((uintptr_t)buffer + part1sz), size - part1sz);
  } else {
    memcpy(basep, buffer, size);
  }
  con->output->produced = (con->output->produced + size) % con->outmod;
  __sync_synchronize();
  xc_evtchn_notify(con->iface->ec, con->port);
}
Example #12
0
static int process_render(struct userdata *u) {
    pa_assert(u);


    if (u->memchunk.length <= 0)
        pa_sink_render(u->sink, ioring->usable_buffer_space, &u->memchunk);


    pa_assert(u->memchunk.length > 0);

    xc_evtchn_notify(xce, xen_evtchn_port);
    for (;;) {
        ssize_t l;
        void *p;

        p = pa_memblock_acquire(u->memchunk.memblock);
	    /* xen: write data to ring buffer & notify backend */
        l = ring_write(ioring, (uint8_t*)p + u->memchunk.index, u->memchunk.length);

        pa_memblock_release(u->memchunk.memblock);

        pa_assert(l != 0);

        if (l < 0) {
            if (errno == EINTR)
                continue;
            else if (errno == EAGAIN)
                return 0;
            else {
                pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
                return -1;
            }

        } else {

            u->memchunk.index += (size_t) l;
            u->memchunk.length -= (size_t) l;

            if (u->memchunk.length <= 0) {
                pa_memblock_unref(u->memchunk.memblock);
                pa_memchunk_reset(&u->memchunk);
            }
        }

        return 0;
    }
}
Example #13
0
static int suspend_guest(xc_interface *xch, xc_evtchn *xce, int domid,
                         int *evtchn, int *lockfd)
{
    int port, rc, suspend_evtchn = -1;

    *lockfd = -1;

    if (!evtchn)
        return -1;

    port = xs_suspend_evtchn_port(domid);
    if (port < 0)
    {
        fprintf(stderr, "DOM%d: No suspend port, try live migration\n", domid);
        goto failed;
    }
    suspend_evtchn = xc_suspend_evtchn_init_exclusive(xch, xce, domid,
                                                      port, lockfd);
    if (suspend_evtchn < 0)
    {
        fprintf(stderr, "Suspend evtchn initialization failed\n");
        goto failed;
    }
    *evtchn = suspend_evtchn;

    rc = xc_evtchn_notify(xce, suspend_evtchn);
    if (rc < 0)
    {
        fprintf(stderr, "Failed to notify suspend channel: errno %d\n", rc);
        goto failed;
    }
    if (xc_await_suspend(xch, xce, suspend_evtchn) < 0)
    {
        fprintf(stderr, "Suspend Failed\n");
        goto failed;
    }
    return 0;

failed:
    if (suspend_evtchn != -1)
        xc_suspend_evtchn_release(xch, xce, domid,
                                  suspend_evtchn, lockfd);

    return -1;
}
Example #14
0
static void xen_cleanup() {
    char keybuf[64];
    /*XXX hardcoded*/
    munmap((void*)gref.index, 4096);

    set_state(XenbusStateClosing);
    /* send one last event to unblock the backend */
    xc_evtchn_notify(xce, xen_evtchn_port);
    /* close xen interfaces */
    xc_evtchn_close(xce);
    xc_interface_close(xch);

    /* delete xenstore keys */
    publish_param_int("state", XenbusStateClosed);
    snprintf(keybuf, sizeof(keybuf), "device/audio/%d", device_id);
    xs_rm(xsh, 0, keybuf);
    xs_daemon_close(xsh);
}
Example #15
0
static void readRaw(ivc_connection_t *con, void *buffer, uint32_t size)
{
  uint32_t off = con->input->consumed % con->insize;
  void *basep = (void*)((uintptr_t)con->inbuf + off);

  if(off + size > con->insize) {
    /* we need to split this up, as we're wrapping around */
    uint32_t part1sz = con->insize - off;
    memcpy(buffer, basep, part1sz);
    memcpy((void*)((uintptr_t)buffer + part1sz), con->inbuf, size - part1sz);
  } else {
    /* we can just write it in directly here */
    memcpy(buffer, basep, size);
  }
  con->input->consumed = (con->input->consumed + size) % con->inmod;
  __sync_synchronize();
  xc_evtchn_notify(con->iface->ec, con->port);
}
Example #16
0
/* Send an event to the keyboard frontend driver */
static int xenfb_kbd_event(struct xenfb *xenfb,
			   union xenkbd_in_event *event)
{
	uint32_t prod;
	struct xenkbd_page *page = xenfb->kbd.page;

	if (xenfb->kbd.state != XenbusStateConnected)
		return 0;

	prod = page->in_prod;
	if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
		errno = EAGAIN;
		return -1;
	}

	xen_mb();		/* ensure ring space available */
	XENKBD_IN_RING_REF(page, prod) = *event;
	xen_wmb();		/* ensure ring contents visible */
	page->in_prod = prod + 1;
	return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
}
Example #17
0
/**
 * Issue a suspend request to a dedicated event channel in the guest, and
 * receive the acknowledgement from the subscribe event channel. */
static int evtchn_suspend(void)
{
    int rc;

    rc = xc_evtchn_notify(si.xce, si.suspend_evtchn);
    if (rc < 0) {
        warnx("failed to notify suspend request channel: %d", rc);
        return 0;
    }

    if (await_suspend() < 0) {
        warnx("suspend failed");
        return 0;
    }

    /* notify xend that it can do device migration */
    printf("suspended\n");
    fflush(stdout);

    return 1;
}
Example #18
0
static void xenfb_on_fb_event(struct xenfb *xenfb)
{
	uint32_t prod, cons;
	struct xenfb_page *page = xenfb->fb.page;

	prod = page->out_prod;
	if (prod == page->out_cons)
		return;
	rmb();			/* ensure we see ring contents up to prod */
	for (cons = page->out_cons; cons != prod; cons++) {
		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
		int x, y, w, h;

		switch (event->type) {
		case XENFB_TYPE_UPDATE:
			x = MAX(event->update.x, 0);
			y = MAX(event->update.y, 0);
			w = MIN(event->update.width, xenfb->width - x);
			h = MIN(event->update.height, xenfb->height - y);
			if (w < 0 || h < 0) {
				fprintf(stderr, "%s bogus update ignored\n",
					xenfb->fb.nodename);
				break;
			}
			if (x != event->update.x || y != event->update.y
			    || w != event->update.width
			    || h != event->update.height) {
				fprintf(stderr, "%s bogus update clipped\n",
					xenfb->fb.nodename);
				break;
			}
			xenfb_guest_copy(xenfb, x, y, w, h);
			break;
		}
	}
	mb();			/* ensure we're done with ring contents */
	page->out_cons = cons;
	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
}
Example #19
0
libvchan_t *libvchan_client_init(int domain, int port) {
    char xs_path[255];
    char xs_path_watch[255];
    libvchan_t *ctrl;
    xc_interface *xc_handle;
    struct xs_handle *xs;
    char **vec;
    unsigned int count, len;
    char *dummy = NULL;
    char *own_domid = NULL;

    xc_handle = xc_interface_open(NULL, NULL, 0);
    if (!xc_handle) {
        /* error already logged by xc_interface_open */
        goto err;
    }

    /* wait for server to appear */
    xs = xs_open(0);
    if (!xs) {
        perror("xs_open");
        goto err_xc;
    }

    len = 0;

    if (!xs_watch(xs, "domid", "domid")) {
        fprintf(stderr, "Cannot setup xenstore watch\n");
        goto err_xs;
    }
    if (!xs_watch(xs, "@releaseDomain", "release")) {
        fprintf(stderr, "Cannot setup xenstore watch\n");
        goto err_xs;
    }
    while (!dummy || !len) {
        vec = xs_read_watch(xs, &count);
        if (vec) {
            if (strcmp(vec[XS_WATCH_TOKEN], "domid") == 0) {
                /* domid have changed */
                if (own_domid) {
                    free(own_domid);
                    own_domid = NULL;
                    xs_unwatch(xs, xs_path_watch, xs_path_watch);
                }
            }
            free(vec);
        }
        if (!own_domid) {
            /* construct xenstore path on first iteration and on every domid
             * change detected (save+restore case) */
            own_domid = xs_read(xs, 0, "domid", &len);
            if (!own_domid) {
                fprintf(stderr, "Cannot get own domid\n");
                goto err_xs;
            }
            if (atoi(own_domid) == domain) {
                fprintf(stderr, "Loopback vchan connection not supported\n");
                free(own_domid);
                goto err_xs;
            }

            snprintf(xs_path, sizeof(xs_path), "/local/domain/%d/data/vchan/%s/%d",
                    domain, own_domid, port);
            /* watch on this key as we might not have access to the whole directory */
            snprintf(xs_path_watch, sizeof(xs_path_watch), "%s/event-channel", xs_path);

            if (!xs_watch(xs, xs_path_watch, xs_path_watch)) {
                fprintf(stderr, "Cannot setup watch on %s\n", xs_path_watch);
                free(own_domid);
                goto err_xs;
            }
        }

        dummy = xs_read(xs, 0, xs_path_watch, &len);
        if (dummy)
            free(dummy);
        else {
            if (!libvchan__check_domain_alive(xc_handle, domain)) {
                fprintf(stderr, "domain dead\n");
                goto err_xs;
            }
        }
    }

    if (own_domid)
        free(own_domid);
    xs_close(xs);

    ctrl = malloc(sizeof(*ctrl));
    if (!ctrl)
        return NULL;
    ctrl->xs_path = NULL;
    ctrl->xenvchan = libxenvchan_client_init(NULL, domain, xs_path);
    if (!ctrl->xenvchan) {
        free(ctrl);
        return NULL;
    }
    ctrl->xenvchan->blocking = 1;
    /* notify server */
    xc_evtchn_notify(ctrl->xenvchan->event, ctrl->xenvchan->event_port);
    ctrl->remote_domain = domain;
    ctrl->xc_handle = xc_handle;
    return ctrl;

err_xs:
    xs_close(xs);
err_xc:
    xc_interface_close(xc_handle);
err:
    return NULL;
}
Example #20
0
static int do_notify(struct libvchan *ctrl)
{
	return xc_evtchn_notify(ctrl->evfd, ctrl->evport);
}
Example #21
0
static void *handle_mount(void *data)
{
    int more, notify;
    struct fs_mount *mount = (struct fs_mount *)data;
    
    printf("Starting a thread for mount: %d\n", mount->mount_id);
    allocate_request_array(mount);

    for(;;)
    {
        int nr_consumed=0;
        RING_IDX cons, rp;
        struct fsif_request *req;

        handle_aio_events(mount);
moretodo:
        rp = mount->ring.sring->req_prod;
        xen_rmb(); /* Ensure we see queued requests up to 'rp'. */

        while ((cons = mount->ring.req_cons) != rp)
        {
            int i;
            struct fs_op *op;

            printf("Got a request at %d (of %d)\n", 
                    cons, RING_SIZE(&mount->ring));
            req = RING_GET_REQUEST(&mount->ring, cons);
            printf("Request type=%d\n", req->type); 
            for(i=0;;i++)
            {
                op = fsops[i];
                if(op == NULL)
                {
                    /* We've reached the end of the array, no appropirate
                     * handler found. Warn, ignore and continue. */
                    printf("WARN: Unknown request type: %d\n", req->type);
                    mount->ring.req_cons++; 
                    break;
                }
                if(op->type == req->type)
                {
                    /* There needs to be a dispatch handler */
                    assert(op->dispatch_handler != NULL);
                    op->dispatch_handler(mount, req);
                    break;
                }
             }

            nr_consumed++;
        }
        printf("Backend consumed: %d requests\n", nr_consumed);
        RING_FINAL_CHECK_FOR_REQUESTS(&mount->ring, more);
        if(more) goto moretodo;

        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&mount->ring, notify);
        printf("Pushed responces and notify=%d\n", notify);
        if(notify)
            xc_evtchn_notify(mount->evth, mount->local_evtchn);
    }
 
    printf("Destroying thread for mount: %d\n", mount->mount_id);
    xc_gnttab_munmap(mount->gnth, mount->ring.sring, 1);
    xc_gnttab_close(mount->gnth);
    xc_evtchn_unbind(mount->evth, mount->local_evtchn);
    xc_evtchn_close(mount->evth);
    free(mount->frontend);
    pthread_exit(NULL);
}
int xen_be_send_notify(struct XenDevice *xendev)
{
    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
}