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 <errno.h>
#include <fcntl.h>
@ -29,25 +32,38 @@
#include <xenctrl.h>
#include <unistd.h>
#include <stdlib.h>
#include <mm.h>
#include "libvchan.h"
#ifndef CONFIG_STUBDOM
#include "../u2mfn/u2mfnlib.h"
#endif
static int ring_init(struct libvchan *ctrl)
{
int u2mfn = open("/proc/u2mfn", O_RDONLY);
int mfn;
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 ();
if (ring == MAP_FAILED)
return -1;
ctrl->ring = ring;
if (u2mfn_get_last_mfn (&mfn) < 0)
return -1;
ctrl->ring_ref = mfn;
close(u2mfn);
#endif
ctrl->ring = ring;
ctrl->ring_ref = mfn;
ring->cons_in = ring->prod_in = ring->cons_out = ring->prod_out =
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;
char buf[64];
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
xc_evtchn *evfd;
#else
int evfd;
#endif
evtchn_port_or_error_t port;
xs = xs_domain_open();
xs = xs_daemon_open();
if (!xs) {
return ret;
}
@ -90,20 +111,41 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
if (port < 0)
goto fail2;
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(buf, sizeof buf, "device/vchan/%d/ring-ref", devno);
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;
#endif
snprintf(ref, sizeof ref, "%d", ctrl->evport);
snprintf(buf, sizeof buf, "device/vchan/%d/event-channel", devno);
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;
#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
if (xc_evtchn_pending(evfd) == -1)
goto fail2;
xc_evtchn_unmask(ctrl->evfd, ctrl->evport);
snprintf(buf, sizeof buf, "device/vchan/%d", devno);
xs_rm(xs, 0, buf);
#endif
ret = 0;
fail2:
@ -130,7 +172,7 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
/**
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.
\returns NULL on failure, handle on success
*/
@ -156,6 +198,39 @@ struct libvchan *libvchan_server_init(int devno)
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
they don't exist, return error, because nobody seems to listen);

View File

@ -22,6 +22,8 @@
#include "libvchan.h"
#include <xenctrl.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>
/**
\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 ret;
#ifndef CONFIG_STUBDOM
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))
return -1;
if (ret!=-1 && libvchan_is_eof(ctrl))

View File

@ -19,6 +19,9 @@
*
*/
#ifndef _LIBVCHAN_H
#define _LIBVCHAN_H
#include <stdint.h>
#include <xenctrl.h>
typedef uint32_t VCHAN_RING_IDX;
@ -44,6 +47,7 @@ struct libvchan {
int evfd;
#endif
int evport;
int devno;
VCHAN_RING_IDX *wr_cons, *wr_prod, *rd_cons, *rd_prod;
char *rd_ring, *wr_ring;
int rd_ring_size, wr_ring_size;
@ -51,6 +55,7 @@ struct libvchan {
};
struct libvchan *libvchan_server_init(int devno);
int libvchan_server_handle_connected(struct libvchan *ctrl);
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_data_ready(struct libvchan *ctrl);
int libvchan_buffer_space(struct libvchan *ctrl);
#endif /* _LIBVCHAN_H */