dom0: vchan version for stubdom
This commit is contained in:
parent
277cdd9173
commit
0c811322c5
36
vchan/Makefile.stubdom
Normal file
36
vchan/Makefile.stubdom
Normal 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
|
||||||
|
|
||||||
|
|
93
vchan/init.c
93
vchan/init.c
@ -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 =
|
||||||
|
19
vchan/io.c
19
vchan/io.c
@ -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))
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user