Merge branch 'hvm' of 10.141.1.101:/var/lib/qubes/git/marmarek/core

This commit is contained in:
Joanna Rutkowska 2012-02-27 13:17:48 +01:00
commit 859c99da5c
10 changed files with 436 additions and 54 deletions

View File

@ -0,0 +1,32 @@
#
# This is a Xen VM config file for Qubes VM
# DO NOT EDIT - autogenerated by qubes tools
#
name = "{name}"
builder='hvm'
memory={mem}
viridian=1
kernel='hvmloader'
#acpi=1
#apic=1
boot='dca'
device_model='stubdom-dm'
#pae=1
usbdevice='tablet'
sdl=0
vnc=0
disk = [ {rootdev}
{otherdevs}
]
vif = [ {netdev} ]
pci = [ {pcidev} ]
vcpus = {vcpus}
#tsc_mode = 2
#xen_extended_power_mgmt=0
on_poweroff = 'destroy'
on_reboot = 'destroy'
on_crash = 'destroy'

View File

@ -21,6 +21,7 @@
#
import sys
import stat
import os
import os.path
import subprocess
@ -78,6 +79,11 @@ default_servicevm_vcpus = 1
default_kernelopts = ""
default_kernelopts_pcidevs = "iommu=soft swiotlb=2048"
default_hvm_disk_size = 20*1024*1024*1024
config_template_pv = '/usr/share/qubes/vm-template.conf'
config_template_hvm = '/usr/share/qubes/vm-template-hvm.conf'
qubes_whitelisted_appmenus = 'whitelisted-appmenus.list'
dom0_update_check_interval = 6*3600
@ -238,6 +244,8 @@ class QubesVm(object):
self.firewall_conf = self.absolute_path(firewall_conf, default_firewall_conf_file)
self.config_file_template = config_template_pv
self.updateable = updateable
self._label = label if label is not None else QubesVmLabels["red"]
if self.dir_path is not None:
@ -788,7 +796,8 @@ class QubesVm(object):
def get_config_params(self, source_template=None):
args = {}
args['name'] = self.name
args['kerneldir'] = self.kernels_dir
if hasattr(self, 'kernels_dir'):
args['kerneldir'] = self.kernels_dir
args['vmdir'] = self.dir_path
args['pcidev'] = str(self.pcidevs).strip('[]')
args['mem'] = str(self.memory)
@ -804,11 +813,13 @@ class QubesVm(object):
args['rootdev'] = self.get_rootdev(source_template=source_template)
args['privatedev'] = "'script:file:{dir}/private.img,xvdb,w',".format(dir=self.dir_path)
args['volatiledev'] = "'script:file:{dir}/volatile.img,xvdc,w',".format(dir=self.dir_path)
modulesmode='r'
if self.is_updateable() and self.kernel is None:
modulesmode='w'
args['otherdevs'] = "'script:file:{dir}/modules.img,xvdd,{mode}',".format(dir=self.kernels_dir, mode=modulesmode)
args['kernelopts'] = self.kernelopts
if hasattr(self, 'kernel'):
modulesmode='r'
if self.is_updateable() and self.kernel is None:
modulesmode='w'
args['otherdevs'] = "'script:file:{dir}/modules.img,xvdd,{mode}',".format(dir=self.kernels_dir, mode=modulesmode)
if hasattr(self, 'kernelopts'):
args['kernelopts'] = self.kernelopts
return args
@ -818,7 +829,7 @@ class QubesVm(object):
if source_template is None:
source_template = self.template_vm
f_conf_template = open('/usr/share/qubes/vm-template.conf', 'r')
f_conf_template = open(self.config_file_template, 'r')
conf_template = f_conf_template.read()
f_conf_template.close()
@ -1163,6 +1174,14 @@ class QubesVm(object):
if notify_function is not None:
notify_function("error", "ERROR: Cannot start the Qubes Clipboard Notifier!")
def start_qrexec_daemon(self, verbose = False):
if verbose:
print >> sys.stderr, "--> Starting the qrexec daemon..."
retcode = subprocess.call ([qrexec_daemon_path, str(xid)])
if (retcode != 0) :
self.force_shutdown()
raise OSError ("ERROR: Cannot execute qrexec_daemon!")
def start(self, debug_console = False, verbose = False, preparing_dvm = False):
if dry_run:
return
@ -1234,12 +1253,7 @@ class QubesVm(object):
qmemman_client.close()
if not preparing_dvm:
if verbose:
print >> sys.stderr, "--> Starting the qrexec daemon..."
retcode = subprocess.call ([qrexec_daemon_path, str(xid)])
if (retcode != 0) :
self.force_shutdown()
raise OSError ("ERROR: Cannot execute qrexec_daemon!")
self.start_qrexec_daemon(verbose=verbose)
if not preparing_dvm and os.path.exists('/var/run/shm.id'):
self.start_guid(verbose=verbose)
@ -1285,26 +1299,20 @@ class QubesVm(object):
attrs["qid"] = str(self.qid)
attrs["name"] = self.name
attrs["dir_path"] = self.dir_path
attrs["conf_file"] = self.relative_path(self.conf_file)
attrs["root_img"] = self.relative_path(self.root_img)
attrs["volatile_img"] = self.relative_path(self.volatile_img)
attrs["private_img"] = self.relative_path(self.private_img)
attrs["uses_default_netvm"] = str(self.uses_default_netvm)
# Simple paths
for prop in ['conf_file', 'root_img', 'volatile_img', 'private_img']:
if hasattr(self, prop):
attrs[prop] = self.relative_path(self.__getattribute__(prop))
# Simple string attrs
for prop in ['memory', 'maxmem', 'pcidevs', 'vcpus', 'internal',\
'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\
'kernelopts', 'services', 'updateable', 'installed_by_rpm',\
'uses_default_netvm' ]:
if hasattr(self, prop):
attrs[prop] = str(self.__getattribute__(prop))
attrs["netvm_qid"] = str(self.netvm_vm.qid) if self.netvm_vm is not None else "none"
attrs["installed_by_rpm"] = str(self.installed_by_rpm)
attrs["template_qid"] = str(self.template_vm.qid) if self.template_vm and not self.is_updateable() else "none"
attrs["updateable"] = str(self.updateable)
attrs["label"] = self.label.name
attrs["memory"] = str(self.memory)
attrs["maxmem"] = str(self.maxmem)
attrs["pcidevs"] = str(self.pcidevs)
attrs["vcpus"] = str(self.vcpus)
attrs["internal"] = str(self.internal)
attrs["uses_default_kernel"] = str(self.uses_default_kernel)
attrs["kernel"] = str(self.kernel)
attrs["uses_default_kernelopts"] = str(self.uses_default_kernelopts)
attrs["kernelopts"] = str(self.kernelopts)
attrs["services"] = str(self.services)
return attrs
def create_xml_element(self):
@ -1988,6 +1996,127 @@ class QubesAppVm(QubesVm):
def post_rename(self, old_name):
self.create_appmenus(False)
class QubesHVm(QubesVm):
"""
A class that represents an HVM. A child of QubesVm.
"""
# FIXME: logically should inherit after QubesAppVm, but none of its methods
# are useful for HVM
def __init__(self, **kwargs):
if "dir_path" not in kwargs or kwargs["dir_path"] is None:
kwargs["dir_path"] = qubes_appvms_dir + "/" + kwargs["name"]
super(QubesHVm, self).__init__(**kwargs)
self.updateable = True
self.config_file_template = config_template_hvm
# remove settings not used by HVM (at least for now)
self.__delattr__('kernel')
self.__delattr__('kernelopts')
self.__delattr__('uses_default_kernel')
self.__delattr__('uses_default_kernelopts')
self.__delattr__('private_img')
self.__delattr__('volatile_img')
# HVM doesn't support dynamic memory management
self.maxmem = self.memory
self.drive = None
if 'drive' in kwargs.keys():
self.drive = kwargs['drive']
@property
def type(self):
return "HVM"
def is_appvm(self):
return True
def create_on_disk(self, verbose, source_template = None):
if dry_run:
return
if verbose:
print >> sys.stderr, "--> Creating directory: {0}".format(self.dir_path)
os.mkdir (self.dir_path)
self.create_config_file()
# create empty disk
f_root = open(self.root_img, "w")
f_root.truncate(default_hvm_disk_size)
f_root.close()
def get_disk_utilization_private_img(self):
return 0
def get_private_img_sz(self):
return 0
def resize_private_img(self, size):
raise NotImplementedError("HVM has no private.img")
def get_config_params(self, source_template=None):
params = super(QubesHVm, self).get_config_params(source_template=source_template)
params['volatiledev'] = ''
params['privatedev'] = ''
if self.drive:
stat_res = os.stat(self.drive)
if stat.S_ISBLK(stat_res.st_mode):
params['otherdevs'] = "'phy:%s,hdc:cdrom,r'," % self.drive
else:
params['otherdevs'] = "'script:file:%s,hdc:cdrom,r'," % self.drive
else:
params['otherdevs'] = ''
return params
def verify_files(self):
if dry_run:
return
if not os.path.exists (self.dir_path):
raise QubesException (
"VM directory doesn't exist: {0}".\
format(self.dir_path))
if self.is_updateable() and not os.path.exists (self.root_img):
raise QubesException (
"VM root image file doesn't exist: {0}".\
format(self.root_img))
return True
def reset_volatile_storage(self, **kwargs):
pass
def run(self, command, **kwargs):
raise NotImplementedError("Needs qrexec agent - TODO")
@property
def stubdom_xid(self):
if not self.is_running():
return -1
return int(xs.read('', '/local/domain/%d/image/device-model-domid' % self.xid))
def start_guid(self, verbose = True, notify_function = None):
if verbose:
print >> sys.stderr, "--> Starting Qubes GUId..."
retcode = subprocess.call ([qubes_guid_path, "-d", str(self.stubdom_xid), "-c", self.label.color, "-i", self.label.icon, "-l", str(self.label.index)])
if (retcode != 0) :
raise QubesException("Cannot start qubes_guid!")
def start_qrexec_daemon(self, **kwargs):
pass
def get_xml_attrs(self):
attrs = super(QubesHVm, self).get_xml_attrs()
attrs["drive"] = str(self.drive)
return attrs
class QubesVmCollection(dict):
"""
@ -2046,6 +2175,20 @@ class QubesVmCollection(dict):
self[vm.qid]=vm
return vm
def add_new_hvm(self, name, label = None):
qid = self.get_new_unused_qid()
vm = QubesHVm (qid=qid, name=name,
netvm_vm = self.get_default_netvm_vm(),
kernel = self.get_default_kernel(),
uses_default_kernel = True,
label=label)
if not self.verify_new_vm (vm):
assert False, "Wrong VM description!"
self[vm.qid]=vm
return vm
def add_new_disposablevm(self, name, template_vm, dispid,
label = None):
@ -2571,6 +2714,20 @@ class QubesVmCollection(dict):
os.path.basename(sys.argv[0]), err))
return False
# And HVMs
for element in tree.findall("QubesHVm"):
try:
kwargs = self.parse_xml_element(element)
vm = QubesHVm(**kwargs)
self[vm.qid] = vm
self.set_netvm_dependency(element)
except (ValueError, LookupError) as err:
print("{0}: import error (QubesHVm): {1}".format(
os.path.basename(sys.argv[0]), err))
return False
# Really finally, read in the DisposableVMs
for element in tree.findall("QubesDisposableVm"):
try:

View File

@ -37,10 +37,14 @@ def main():
help="Specify the label to use for the new VM (e.g. red, yellow, green, ...)")
parser.add_option ("-p", "--proxy", action="store_true", dest="proxyvm", default=False,
help="Create ProxyVM")
parser.add_option ("-H", "--hvm", action="store_true", dest="hvm", default=False,
help="Create HVM (implies --standalone)")
parser.add_option ("-n", "--net", action="store_true", dest="netvm", default=False,
help="Create NetVM")
parser.add_option ("-s", "--standalone", action="store_true", dest="standalone", default=False,
help="Create standalone VM - independent of template ")
parser.add_option ("-r", "--root", dest="root", default=None,
help="Use provided root.img instead of default/empty one (file will be MOVED)")
parser.add_option ("-m", "--mem", dest="mem", default=None,
help="Initial memory size (in MB)")
parser.add_option ("-c", "--vcpus", dest="vcpus", default=None,
@ -82,6 +86,18 @@ def main():
exit (1)
label = QubesVmLabels[options.label]
if options.hvm:
# Only standalone HVMs are supported for now
options.standalone = True
if not options.standalone and options.root is not None:
print >> sys.stderr, "root.img can be specified only for standalone VMs"
exit (1)
if options.root is not None and not os.path.exists(options.root):
print >> sys.stderr, "File specified as root.img does not exists"
exit (1)
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
@ -90,6 +106,7 @@ def main():
print >> sys.stderr, "A VM with the name '{0}' already exists in the system.".format(vmname)
exit(1)
template_vm = None
if options.template is not None:
template_vm = qvm_collection.get_vm_by_name(options.template)
if template_vm is None:
@ -101,7 +118,7 @@ def main():
if (options.verbose):
print "--> Using TemplateVM: {0}".format(template_vm.name)
else:
elif not options.hvm:
if qvm_collection.get_default_template_vm() is None:
print >> sys.stderr, "No default TempleteVM defined!"
exit (1)
@ -120,6 +137,8 @@ def main():
vm = qvm_collection.add_new_netvm(vmname, new_vm_template, label = label, updateable = options.standalone)
elif options.proxyvm:
vm = qvm_collection.add_new_proxyvm(vmname, new_vm_template, label = label, updateable = options.standalone)
elif options.hvm:
vm = qvm_collection.add_new_hvm(vmname, label = label)
else:
vm = qvm_collection.add_new_appvm(vmname, new_vm_template, label = label, updateable = options.standalone)
@ -134,6 +153,9 @@ def main():
try:
vm.create_on_disk(verbose=options.verbose, source_template=template_vm)
if options.root:
os.unlink(vm.root_img)
os.rename(options.root, vm.root_img)
except (IOError, OSError) as err:
print >> sys.stderr, "ERROR: {0}".format(err)

View File

@ -51,22 +51,32 @@ def do_list(vm):
print fmt.format ("root COW img", vm.rootcow_img)
if vm.template_vm is not None:
print fmt.format ("root img", vm.template_vm.root_img)
print fmt.format ("root volatile img", vm.volatile_img)
if hasattr(vm, 'volatile_img'):
print fmt.format ("root volatile img", vm.volatile_img)
print fmt.format ("private img", vm.private_img)
if hasattr(vm, 'private_img'):
print fmt.format ("private img", vm.private_img)
print fmt.format ("vcpus", str(vm.vcpus))
print fmt.format ("memory", vm.memory)
print fmt.format ("maxmem", vm.maxmem)
if vm.template_vm is not None:
print fmt.format ("kernel", "%s (from template)" % vm.kernel)
elif vm.uses_default_kernel:
print fmt.format ("kernel", "%s (default)" % vm.kernel)
else:
print fmt.format ("kernel", vm.kernel)
if vm.uses_default_kernelopts:
print fmt.format ("kernelopts", "%s (default)" % vm.kernelopts)
else:
print fmt.format ("kernelopts", vm.kernelopts)
if hasattr(vm, 'maxmem'):
print fmt.format ("maxmem", vm.maxmem)
if hasattr(vm, 'kernel'):
if vm.template_vm is not None:
print fmt.format ("kernel", "%s (from template)" % vm.kernel)
elif vm.uses_default_kernel:
print fmt.format ("kernel", "%s (default)" % vm.kernel)
else:
print fmt.format ("kernel", vm.kernel)
if hasattr(vm, 'kernelopts'):
if vm.uses_default_kernelopts:
print fmt.format ("kernelopts", "%s (default)" % vm.kernelopts)
else:
print fmt.format ("kernelopts", vm.kernelopts)
if hasattr(vm, 'drive'):
print fmt.format("drive", str(vm.drive))
def set_label(vms, vm, args):
@ -287,6 +297,13 @@ def set_name(vms, vm, args):
vm.set_name(args[0])
return True
def set_drive(vms, vm, args):
if len (args) != 1:
print >> sys.stderr, "Missing new drive content (file/device)!"
return False
vm.drive = args[0]
return True
properties = {
"updateable": set_updateable,
@ -301,6 +318,7 @@ properties = {
"vcpus" : set_vcpus,
"kernelopts": set_kernelopts,
"name": set_name,
"drive": set_drive,
}
@ -309,6 +327,10 @@ def do_set(vms, vm, property, args):
print >> sys.stderr, "ERROR: Wrong property name: '{0}'".format(property)
return False
if not hasattr(vm, property):
print >> sys.stderr, "ERROR: Property '{0}' not available for this VM".format(property)
return False
return properties[property](vms, vm, args)
@ -353,7 +375,8 @@ def main():
print >> sys.stderr, "You must specify the property you wish to set..."
print >> sys.stderr, "Available properties:"
for p in properties.keys():
print >> sys.stderr, "--> '{0}'".format(p)
if hasattr(vm, p):
print >> sys.stderr, "--> '{0}'".format(p)
exit (1)
property = args[1]

View File

@ -37,6 +37,8 @@ def main():
help="Do not start the GUId (ignored)")
parser.add_option ("--console", action="store_true", dest="debug_console", default=False,
help="Attach debugging console to the newly started VM")
parser.add_option ("--drive", dest="drive", default=None,
help="Temporarily attach specified drive as CD/DVD")
parser.add_option ("--dvm", action="store_true", dest="preparing_dvm", default=False,
help="Do actions necessary when preparing DVM image")
@ -55,6 +57,13 @@ def main():
print >> sys.stderr, "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if options.drive:
if hasattr(vm, 'drive'):
vm.drive = options.drive
else:
print >> sys.stderr, "This VM does not support attaching drives"
exit (1)
try:
vm.verify_files()
xid = vm.start(debug_console=options.debug_console, verbose=options.verbose, preparing_dvm=options.preparing_dvm)

View File

@ -151,6 +151,7 @@ cp misc/qubes-vm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
cp misc/qubes-templatevm.directory.template $RPM_BUILD_ROOT/usr/share/qubes/
cp misc/qubes-appmenu-select.desktop $RPM_BUILD_ROOT/usr/share/qubes/
cp misc/vm-template.conf $RPM_BUILD_ROOT/usr/share/qubes/
cp misc/vm-template-hvm.conf $RPM_BUILD_ROOT/usr/share/qubes/
mkdir -p $RPM_BUILD_ROOT/usr/bin
cp ../network/qubes_setup_dnat_to_ns $RPM_BUILD_ROOT/usr/lib/qubes
@ -344,6 +345,7 @@ fi
/usr/share/qubes/qubes-templatevm.directory.template
/usr/share/qubes/qubes-appmenu-select.desktop
/usr/share/qubes/vm-template.conf
/usr/share/qubes/vm-template-hvm.conf
/usr/lib/qubes/qubes_setup_dnat_to_ns
/usr/lib/qubes/qubes_fix_nm_conf.sh
/etc/dhclient.d/qubes_setup_dnat_to_ns.sh

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:
@ -129,8 +171,8 @@ static int server_interface_init(struct libvchan *ctrl, int devno)
ctrl->rd_ring_size = sizeof(ctrl->ring->buf_##dir2)
/**
Run in AppVM (any domain).
Sleeps until the connection is established.
Run in AppVM (any domain).
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);
@ -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).
\returns NULL on failure (e.g. noone listening), handle on success
*/
*/
struct libvchan *libvchan_client_init(int domain, int devno)
{
struct libvchan *ctrl =

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 */