dom0: vchan version for stubdom

This commit is contained in:
Marek Marczykowski 2012-02-22 17:54:58 +01:00
parent 277cdd9173
commit 0c811322c5
4 changed files with 146 additions and 9 deletions

36
vchan/Makefile.stubdom Normal file
View File

@ -0,0 +1,36 @@
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2012 Marek Marczykowski <marmarek@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
# Assume it is placed as xen-root/tools/vchan
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
CFLAGS+=-Wall -I$(XEN_ROOT)/tools/libxc -DCONFIG_STUBDOM
all: libvchan.a
libvchan.a: init.o io.o
$(AR) rc $@ $^
clean:
rm -f *.o *so *~ client server node node-select

View File

@ -19,6 +19,9 @@
* *
*/ */
#include <sys/types.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@ -29,25 +32,38 @@
#include <xenctrl.h> #include <xenctrl.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <mm.h>
#include "libvchan.h" #include "libvchan.h"
#ifndef CONFIG_STUBDOM
#include "../u2mfn/u2mfnlib.h" #include "../u2mfn/u2mfnlib.h"
#endif
static int ring_init(struct libvchan *ctrl) static int ring_init(struct libvchan *ctrl)
{ {
int u2mfn = open("/proc/u2mfn", O_RDONLY);
int mfn; int mfn;
struct vchan_interface *ring; struct vchan_interface *ring;
#ifdef CONFIG_STUBDOM
ring = (struct vchan_interface *) memalign(XC_PAGE_SIZE, sizeof(*ring));
if (!ring)
return -1;
mfn = virtual_to_mfn(ring);
#else
int u2mfn = open("/proc/u2mfn", O_RDONLY);
ring = (struct vchan_interface *) u2mfn_alloc_kpage (); ring = (struct vchan_interface *) u2mfn_alloc_kpage ();
if (ring == MAP_FAILED) if (ring == MAP_FAILED)
return -1; return -1;
ctrl->ring = ring;
if (u2mfn_get_last_mfn (&mfn) < 0) if (u2mfn_get_last_mfn (&mfn) < 0)
return -1; return -1;
ctrl->ring_ref = mfn;
close(u2mfn); close(u2mfn);
#endif
ctrl->ring = ring;
ctrl->ring_ref = mfn;
ring->cons_in = ring->prod_in = ring->cons_out = ring->prod_out = ring->cons_in = ring->prod_in = ring->cons_out = ring->prod_out =
0; 0;
ring->server_closed = ring->client_closed = 0; ring->server_closed = ring->client_closed = 0;
@ -65,13 +81,18 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
struct xs_handle *xs; struct xs_handle *xs;
char buf[64]; char buf[64];
char ref[16]; char ref[16];
/* XXX temp hack begin */
char *domid_s;
int domid = 0;
unsigned int len;
/* XXX temp hack end */
#ifdef XENCTRL_HAS_XC_INTERFACE #ifdef XENCTRL_HAS_XC_INTERFACE
xc_evtchn *evfd; xc_evtchn *evfd;
#else #else
int evfd; int evfd;
#endif #endif
evtchn_port_or_error_t port; evtchn_port_or_error_t port;
xs = xs_domain_open(); xs = xs_daemon_open();
if (!xs) { if (!xs) {
return ret; return ret;
} }
@ -90,20 +111,41 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
if (port < 0) if (port < 0)
goto fail2; goto fail2;
ctrl->evport = port; ctrl->evport = port;
ctrl->devno = devno;
// stubdom debug HACK XXX
domid_s = xs_read(xs, 0, "domid", &len);
if (domid_s)
domid = atoi(domid_s);
snprintf(ref, sizeof ref, "%d", ctrl->ring_ref); snprintf(ref, sizeof ref, "%d", ctrl->ring_ref);
snprintf(buf, sizeof buf, "device/vchan/%d/ring-ref", devno); snprintf(buf, sizeof buf, "device/vchan/%d/ring-ref", devno);
if (!xs_write(xs, 0, buf, ref, strlen(ref))) if (!xs_write(xs, 0, buf, ref, strlen(ref)))
#ifdef CONFIG_STUBDOM
// TEMP HACK XXX FIXME goto fail2;
fprintf(stderr, "xenstore-write /local/domain/%d/%s %s\n", domid, buf, ref);
#else
goto fail2; goto fail2;
#endif
snprintf(ref, sizeof ref, "%d", ctrl->evport); snprintf(ref, sizeof ref, "%d", ctrl->evport);
snprintf(buf, sizeof buf, "device/vchan/%d/event-channel", devno); snprintf(buf, sizeof buf, "device/vchan/%d/event-channel", devno);
if (!xs_write(xs, 0, buf, ref, strlen(ref))) if (!xs_write(xs, 0, buf, ref, strlen(ref)))
#ifdef CONFIG_STUBDOM
// TEMP HACK XXX FIXME goto fail2;
fprintf(stderr, "xenstore-write /local/domain/%d/%s %s\n", domid, buf, ref);
#else
goto fail2; goto fail2;
#endif
// do not block in stubdom - libvchan_server_handle_connected will be
// called on first input
#ifndef CONFIG_STUBDOM
// wait for the peer to arrive // wait for the peer to arrive
if (xc_evtchn_pending(evfd) == -1) if (xc_evtchn_pending(evfd) == -1)
goto fail2; goto fail2;
xc_evtchn_unmask(ctrl->evfd, ctrl->evport); xc_evtchn_unmask(ctrl->evfd, ctrl->evport);
snprintf(buf, sizeof buf, "device/vchan/%d", devno); snprintf(buf, sizeof buf, "device/vchan/%d", devno);
xs_rm(xs, 0, buf); xs_rm(xs, 0, buf);
#endif
ret = 0; ret = 0;
fail2: fail2:
@ -129,8 +171,8 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
ctrl->rd_ring_size = sizeof(ctrl->ring->buf_##dir2) ctrl->rd_ring_size = sizeof(ctrl->ring->buf_##dir2)
/** /**
Run in AppVM (any domain). Run in AppVM (any domain).
Sleeps until the connection is established. Sleeps until the connection is established. (unless in stubdom)
\param devno something like a well-known port. \param devno something like a well-known port.
\returns NULL on failure, handle on success \returns NULL on failure, handle on success
*/ */
@ -156,6 +198,39 @@ struct libvchan *libvchan_server_init(int devno)
return ctrl; return ctrl;
} }
int libvchan_server_handle_connected(struct libvchan *ctrl)
{
struct xs_handle *xs;
char buf[64];
int ret = -1;
int libvchan_fd;
fd_set rfds;
xs = xs_daemon_open();
if (!xs) {
return ret;
}
// clear the pending flag
xc_evtchn_pending(ctrl->evfd);
snprintf(buf, sizeof buf, "device/vchan/%d", ctrl->devno);
xs_rm(xs, 0, buf);
ret = 0;
#if 0
fail2:
if (ret)
#ifdef XENCTRL_HAS_XC_INTERFACE
xc_evtchn_close(ctrl->evfd);
#else
close(ctrl->evfd);
#endif
#endif
xs_daemon_close(xs);
return ret;
}
/** /**
retrieves ring-ref and event-channel numbers from xenstore (if retrieves ring-ref and event-channel numbers from xenstore (if
they don't exist, return error, because nobody seems to listen); they don't exist, return error, because nobody seems to listen);
@ -250,7 +325,7 @@ static int client_interface_init(struct libvchan *ctrl, int domain, int devno)
/** /**
Run on the client side of connection (currently, must be dom0). Run on the client side of connection (currently, must be dom0).
\returns NULL on failure (e.g. noone listening), handle on success \returns NULL on failure (e.g. noone listening), handle on success
*/ */
struct libvchan *libvchan_client_init(int domain, int devno) struct libvchan *libvchan_client_init(int domain, int devno)
{ {
struct libvchan *ctrl = struct libvchan *ctrl =

View File

@ -22,6 +22,8 @@
#include "libvchan.h" #include "libvchan.h"
#include <xenctrl.h> #include <xenctrl.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <sys/select.h>
/** /**
\return How much data is immediately available for reading \return How much data is immediately available for reading
*/ */
@ -67,7 +69,24 @@ int libvchan_is_eof(struct libvchan *ctrl)
int libvchan_wait(struct libvchan *ctrl) int libvchan_wait(struct libvchan *ctrl)
{ {
int ret; int ret;
#ifndef CONFIG_STUBDOM
ret = xc_evtchn_pending(ctrl->evfd); ret = xc_evtchn_pending(ctrl->evfd);
#else
int vchan_fd = libvchan_fd_for_select(ctrl);
fd_set rfds;
libvchan_prepare_to_select(ctrl);
while ((ret = xc_evtchn_pending(ctrl->evfd)) < 0) {
FD_ZERO(&rfds);
FD_SET(0, &rfds);
FD_SET(vchan_fd, &rfds);
ret = select(vchan_fd + 1, &rfds, NULL, NULL, NULL);
if (ret < 0 && errno != EINTR) {
perror("select");
return ret;
}
}
#endif
if (ret!=-1 && xc_evtchn_unmask(ctrl->evfd, ctrl->evport)) if (ret!=-1 && xc_evtchn_unmask(ctrl->evfd, ctrl->evport))
return -1; return -1;
if (ret!=-1 && libvchan_is_eof(ctrl)) if (ret!=-1 && libvchan_is_eof(ctrl))

View File

@ -19,6 +19,9 @@
* *
*/ */
#ifndef _LIBVCHAN_H
#define _LIBVCHAN_H
#include <stdint.h> #include <stdint.h>
#include <xenctrl.h> #include <xenctrl.h>
typedef uint32_t VCHAN_RING_IDX; typedef uint32_t VCHAN_RING_IDX;
@ -44,6 +47,7 @@ struct libvchan {
int evfd; int evfd;
#endif #endif
int evport; int evport;
int devno;
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod; VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
char *rd_ring, *wr_ring; char *rd_ring, *wr_ring;
int rd_ring_size, wr_ring_size; int rd_ring_size, wr_ring_size;
@ -51,6 +55,7 @@ struct libvchan {
}; };
struct libvchan *libvchan_server_init(int devno); struct libvchan *libvchan_server_init(int devno);
int libvchan_server_handle_connected(struct libvchan *ctrl);
struct libvchan *libvchan_client_init(int domain, int devno); struct libvchan *libvchan_client_init(int domain, int devno);
@ -63,3 +68,5 @@ int libvchan_fd_for_select(struct libvchan *ctrl);
int libvchan_is_eof(struct libvchan *ctrl); int libvchan_is_eof(struct libvchan *ctrl);
int libvchan_data_ready(struct libvchan *ctrl); int libvchan_data_ready(struct libvchan *ctrl);
int libvchan_buffer_space(struct libvchan *ctrl); int libvchan_buffer_space(struct libvchan *ctrl);
#endif /* _LIBVCHAN_H */