diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-10-06 16:07:52 +0100 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-10-06 16:07:52 +0100 |
commit | c804adf4b64a5755c885b681c32591d2e67aa636 (patch) | |
tree | 618b3e8823bd2cbbba9091988dab2c4ab102cf7c /tools | |
parent | 0c6f366280979dae46309b894d21b2c99fa5e816 (diff) | |
download | xen-c804adf4b64a5755c885b681c32591d2e67aa636.tar.gz xen-c804adf4b64a5755c885b681c32591d2e67aa636.tar.bz2 xen-c804adf4b64a5755c885b681c32591d2e67aa636.zip |
Change how event channels are allocated and used by the control
tools. /dev/xen/evtchn is now used by daemons to connect to
remote domains: the advantage is that the local ports are garbage
collected automatically if the daemon dies. xen no longer
constructs end-to-end event-channel port pairs -- it allocates an
unbound port in new domU and writes that port to xenstore. It is
then picked up by teh appropriate daemon which does interdomain bind
via /dev/xen/evtchn.
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/console/daemon/io.c | 55 | ||||
-rw-r--r-- | tools/debugger/pdb/pdb_xen.c | 6 | ||||
-rw-r--r-- | tools/ioemu/target-i386-dm/helper2.c | 25 | ||||
-rw-r--r-- | tools/ioemu/vl.c | 6 | ||||
-rw-r--r-- | tools/python/xen/lowlevel/xc/xc.c | 6 | ||||
-rw-r--r-- | tools/python/xen/xend/XendCheckpoint.py | 6 | ||||
-rw-r--r-- | tools/python/xen/xend/XendDomainInfo.py | 71 | ||||
-rw-r--r-- | tools/python/xen/xend/image.py | 21 | ||||
-rwxr-xr-x | tools/python/xen/xend/server/channel.py | 76 | ||||
-rw-r--r-- | tools/xenstore/xenstored_domain.c | 36 |
10 files changed, 97 insertions, 211 deletions
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index a841af1c95..dab3177d14 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -1,4 +1,4 @@ -/*\ +/* * Copyright (C) International Business Machines Corp., 2005 * Author(s): Anthony Liguori <aliguori@us.ibm.com> * @@ -16,14 +16,15 @@ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -\*/ + */ #define _GNU_SOURCE #include "utils.h" #include "io.h" -#include "xenctrl.h" -#include "xs.h" +#include <xenctrl.h> +#include <xs.h> +#include <xen/linux/evtchn.h> #include <malloc.h> #include <stdlib.h> @@ -225,16 +226,14 @@ int xs_gather(struct xs_handle *xs, const char *dir, ...) return ret; } -#define EVENTCHN_BIND _IO('E', 2) -#define EVENTCHN_UNBIND _IO('E', 3) - static int domain_create_ring(struct domain *dom) { - int err, local_port, ring_ref; + int err, remote_port, ring_ref, rc; + struct ioctl_evtchn_bind_interdomain bind; err = xs_gather(xs, dom->conspath, "ring-ref", "%u", &ring_ref, - "port", "%i", &local_port, + "port", "%i", &remote_port, NULL); if (err) goto out; @@ -252,26 +251,28 @@ static int domain_create_ring(struct domain *dom) dom->ring_ref = ring_ref; } - if (local_port != dom->local_port) { - dom->local_port = -1; - if (dom->evtchn_fd != -1) - close(dom->evtchn_fd); - /* Opening evtchn independently for each console is a bit - * wastefule, but that's how the code is structured... */ - dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR); - if (dom->evtchn_fd == -1) { - err = errno; - goto out; - } + dom->local_port = -1; + if (dom->evtchn_fd != -1) + close(dom->evtchn_fd); + + /* Opening evtchn independently for each console is a bit + * wasteful, but that's how the code is structured... */ + dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR); + if (dom->evtchn_fd == -1) { + err = errno; + goto out; + } - if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, local_port) == -1) { - err = errno; - close(dom->evtchn_fd); - dom->evtchn_fd = -1; - goto out; - } - dom->local_port = local_port; + bind.remote_domain = dom->domid; + bind.remote_port = remote_port; + rc = ioctl(dom->evtchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind); + if (rc == -1) { + err = errno; + close(dom->evtchn_fd); + dom->evtchn_fd = -1; + goto out; } + dom->local_port = rc; out: return err; diff --git a/tools/debugger/pdb/pdb_xen.c b/tools/debugger/pdb/pdb_xen.c index e89f364f61..b2c994c188 100644 --- a/tools/debugger/pdb/pdb_xen.c +++ b/tools/debugger/pdb/pdb_xen.c @@ -43,11 +43,7 @@ pdb_close (int xc_handle) #include <sys/ioctl.h> - -/* /dev/xen/evtchn ioctls */ -#define EVTCHN_RESET _IO('E', 1) /* clear & reinit buffer */ -#define EVTCHN_BIND _IO('E', 2) /* bind to event channel */ -#define EVTCHN_UNBIND _IO('E', 3) /* unbind from event channel */ +#include <xen/linux/evtchn.h> int xen_evtchn_bind (int evtchn_fd, int idx) diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index a3c22d5f1a..d32ef006ba 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -49,11 +49,14 @@ #include <xenctrl.h> #include <xen/io/ioreq.h> +#include <xen/linux/evtchn.h> #include "cpu.h" #include "exec-all.h" #include "vl.h" +extern int domid; + void *shared_vram; shared_iopage_t *shared_page = NULL; @@ -119,7 +122,7 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) //the evtchn fd for polling int evtchn_fd = -1; //the evtchn port for polling the notification, should be inputed as bochs's parameter -u16 ioreq_port = 0; +u16 ioreq_remote_port, ioreq_local_port; //some functions to handle the io req packet void @@ -156,9 +159,9 @@ ioreq_t* cpu_get_ioreq(void) int rc; u16 buf[2]; rc = read(evtchn_fd, buf, 2); - if (rc == 2 && buf[0] == ioreq_port){//got only one matched 16bit port index + if (rc == 2 && buf[0] == ioreq_local_port){//got only one matched 16bit port index // unmask the wanted port again - write(evtchn_fd, &ioreq_port, 2); + write(evtchn_fd, &ioreq_local_port, 2); //get the io packet from shared memory return __cpu_get_ioreq(); @@ -417,7 +420,6 @@ do_interrupt(CPUState *env, int vector) void destroy_vmx_domain(void) { - extern int domid; extern FILE* logfile; char destroy_cmd[20]; sprintf(destroy_cmd, "xm destroy %d", domid); @@ -485,9 +487,9 @@ int main_loop(void) #endif if (env->send_event) { int ret; - ret = xc_evtchn_send(xc_handle, ioreq_port); + ret = xc_evtchn_send(xc_handle, ioreq_local_port); if (ret == -1) { - fprintf(logfile, "evtchn_send failed on port: %d\n", ioreq_port); + fprintf(logfile, "evtchn_send failed on port: %d\n", ioreq_local_port); } } } @@ -499,7 +501,6 @@ static void qemu_vmx_reset(void *unused) { char cmd[255]; - extern int domid; /* pause domain first, to avoid repeated reboot request*/ xc_domain_pause (xc_handle, domid); @@ -512,6 +513,8 @@ CPUState * cpu_init() { CPUX86State *env; + struct ioctl_evtchn_bind_interdomain bind; + int rc; cpu_exec_init(); qemu_register_reset(qemu_vmx_reset, NULL); @@ -532,12 +535,14 @@ cpu_init() return NULL; } - fprintf(logfile, "listening to port: %d\n", ioreq_port); - /*unmask the wanted port -- bind*/ - if (ioctl(evtchn_fd, ('E'<<8)|2, ioreq_port) == -1) { + bind.remote_domain = domid; + bind.remote_port = ioreq_remote_port; + rc = ioctl(evtchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind); + if (rc == -1) { perror("ioctl"); return NULL; } + ioreq_local_port = rc; return env; } diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 5a4617dbc9..e09153f8b8 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -2806,9 +2806,9 @@ int main(int argc, char **argv) case QEMU_OPTION_p: { - extern short ioreq_port; - ioreq_port = atoi(optarg); - printf("port: %d\n", ioreq_port); + extern short ioreq_remote_port; + ioreq_remote_port = atoi(optarg); + printf("port: %d\n", ioreq_remote_port); } break; case QEMU_OPTION_l: diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 7ff5b40ca9..5074b4b3c6 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -435,10 +435,10 @@ static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self, u32 dom = DOMID_SELF, remote_dom; int port = 0; - static char *kwd_list[] = { "remote_dom", "dom", "port", NULL }; + static char *kwd_list[] = { "remote_dom", "dom", NULL }; - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list, - &remote_dom, &dom, &port) ) + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, + &remote_dom, &dom) ) return NULL; if ( xc_evtchn_alloc_unbound(xc->xc_handle, remote_dom, dom, &port) != 0 ) diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index ab8ba6fb4e..6e6e60156f 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -126,8 +126,8 @@ def restore(xd, fd): raise XendError( "not a valid guest state file: pfn count out of range") - store_evtchn = dominfo.store_channel.port2 - console_evtchn = dominfo.console_channel.port2 + store_evtchn = dominfo.store_channel + console_evtchn = dominfo.console_channel cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd), str(dominfo.getDomid()), str(nr_pfns), @@ -146,7 +146,7 @@ def restore(xd, fd): dominfo.getDomainPath()) IntroduceDomain(dominfo.getDomid(), store_mfn, - dominfo.store_channel.port1, + dominfo.store_channel, dominfo.getDomainPath()) else: m = re.match(r"^(console-mfn) (\d+)$", line) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 19814c6bdc..4cdaa0e54e 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -32,8 +32,6 @@ import errno import xen.lowlevel.xc from xen.util.blkif import blkdev_uname_to_file -from xen.xend.server import channel - from xen.xend import image from xen.xend import scheduler from xen.xend import sxp @@ -785,32 +783,6 @@ class XendDomainInfo: self.domid, self.info['name']) - def closeChannel(self, chan, entry): - """Close the given channel, if set, and remove the given entry in the - store. Nothrow guarantee.""" - - if chan: - chan.close() - try: - self.removeDom(entry) - except: - log.exception('Removing entry %s failed', entry) - - - def closeStoreChannel(self): - """Close the store channel, if any. Nothrow guarantee.""" - - self.closeChannel(self.store_channel, "store/port") - self.store_channel = None - - - def closeConsoleChannel(self): - """Close the console channel, if any. Nothrow guarantee.""" - - self.closeChannel(self.console_channel, "console/port") - self.console_channel = None - - ## public: def setConsoleRef(self, ref): @@ -960,12 +932,8 @@ class XendDomainInfo: sxpr.append(['up_time', str(up_time) ]) sxpr.append(['start_time', str(self.info['start_time']) ]) - if self.store_channel: - sxpr.append(self.store_channel.sxpr()) if self.store_mfn: sxpr.append(['store_mfn', self.store_mfn]) - if self.console_channel: - sxpr.append(['console_channel', self.console_channel.sxpr()]) if self.console_mfn: sxpr.append(['console_mfn', self.console_mfn]) @@ -1073,7 +1041,7 @@ class XendDomainInfo: self.create_channel() self.image.createImage() IntroduceDomain(self.domid, self.store_mfn, - self.store_channel.port1, self.dompath) + self.store_channel, self.dompath) ## public: @@ -1083,8 +1051,6 @@ class XendDomainInfo: guarantee.""" self.release_devices() - self.closeStoreChannel() - self.closeConsoleChannel() if self.image: try: @@ -1164,35 +1130,22 @@ class XendDomainInfo: @param path under which port is stored in db """ - port = 0 if path: try: - port = int(self.readDom(path)) + return int(self.readDom(path)) except: # The port is not yet set, i.e. the channel has not yet been # created. pass - # Stale port information from above causes an Invalid Argument to be - # thrown by the eventChannel call below. To recover, we throw away - # port if it turns out to be bad, and just create a new channel. - # If creating a new channel with two new ports fails, then something - # else is going wrong, so we bail. - while True: - try: - ret = channel.eventChannel(0, self.domid, port1 = port, - port2 = 0) - break - except: - log.exception("Exception in eventChannel(0, %d, %d, %d)", - self.domid, port, 0) - if port == 0: - raise - else: - port = 0 - log.error("Recovering from above exception.") - self.storeDom(path, ret.port1) - return ret + try: + port = xc.evtchn_alloc_unbound(dom=self.domid, remote_dom=0) + except: + log.exception("Exception in alloc_unbound(%d)", self.domid) + raise + + self.storeDom(path, port) + return port def create_channel(self): """Create the channels to the domain. @@ -1419,11 +1372,11 @@ class XendDomainInfo: def initStoreConnection(self): - ref = xc.init_store(self.store_channel.port2) + ref = xc.init_store(self.store_channel) if ref and ref >= 0: self.setStoreRef(ref) try: - IntroduceDomain(self.domid, ref, self.store_channel.port1, + IntroduceDomain(self.domid, ref, self.store_channel, self.dompath) except RuntimeError, ex: if ex.args[0] == errno.EISCONN: diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 0e71568c1d..9ad3d29f00 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -25,8 +25,6 @@ from xen.xend import sxp from xen.xend.XendError import VmError from xen.xend.XendLogging import log -from xen.xend.server import channel - xc = xen.lowlevel.xc.new() @@ -168,11 +166,11 @@ class LinuxImageHandler(ImageHandler): def buildDomain(self): if self.vm.store_channel: - store_evtchn = self.vm.store_channel.port2 + store_evtchn = self.vm.store_channel else: store_evtchn = 0 if self.vm.console_channel: - console_evtchn = self.vm.console_channel.port2 + console_evtchn = self.vm.console_channel else: console_evtchn = 0 @@ -228,16 +226,17 @@ class VmxImageHandler(ImageHandler): def buildDomain(self): # Create an event channel - self.device_channel = channel.eventChannel(0, self.vm.getDomid()) - log.info("VMX device model port: %d", self.device_channel.port2) + self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(), + remote_dom=0) + log.info("VMX device model port: %d", self.device_channel) if self.vm.store_channel: - store_evtchn = self.vm.store_channel.port2 + store_evtchn = self.vm.store_channel else: store_evtchn = 0 log.debug("dom = %d", self.vm.getDomid()) log.debug("image = %s", self.kernel) - log.debug("control_evtchn = %d", self.device_channel.port2) + log.debug("control_evtchn = %d", self.device_channel) log.debug("store_evtchn = %d", store_evtchn) log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024) log.debug("flags = %d", self.flags) @@ -245,7 +244,7 @@ class VmxImageHandler(ImageHandler): ret = xc.vmx_build(dom = self.vm.getDomid(), image = self.kernel, - control_evtchn = self.device_channel.port2, + control_evtchn = self.device_channel, store_evtchn = store_evtchn, memsize = self.vm.getMemoryTarget() / 1024, flags = self.flags, @@ -334,7 +333,7 @@ class VmxImageHandler(ImageHandler): if len(vnc): args = args + vnc args = args + ([ "-d", "%d" % self.vm.getDomid(), - "-p", "%d" % self.device_channel.port1, + "-p", "%d" % self.device_channel, "-m", "%s" % (self.vm.getMemoryTarget() / 1024)]) args = args + self.dmargs env = dict(os.environ) @@ -358,8 +357,6 @@ class VmxImageHandler(ImageHandler): return vncconnect def destroy(self): - if self.device_channel: - self.device_channel.close() import signal if not self.pid: return diff --git a/tools/python/xen/xend/server/channel.py b/tools/python/xen/xend/server/channel.py deleted file mode 100755 index 095a14786a..0000000000 --- a/tools/python/xen/xend/server/channel.py +++ /dev/null @@ -1,76 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com> -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -import xen.lowlevel.xc - -from xen.xend.XendLogging import log - - -xc = xen.lowlevel.xc.new() - - -class EventChannel: - """An event channel between domains. - """ - - def __init__(self, dom1, dom2, port1, port2): - self.dom1 = dom1 - self.dom2 = dom2 - self.port1 = port1 - self.port2 = port2 - - - def close(self): - """Close the event channel. Nothrow guarantee. - """ - def evtchn_close(dom, port): - try: - xc.evtchn_close(dom=dom, port=port) - except Exception: - log.exception("Exception closing event channel %d, %d.", dom, - port) - - evtchn_close(self.dom1, self.port1) - evtchn_close(self.dom2, self.port2) - - - def sxpr(self): - return ['event-channel', - ['dom1', self.dom1 ], - ['port1', self.port1 ], - ['dom2', self.dom2 ], - ['port2', self.port2 ] - ] - - - def __repr__(self): - return ("<EventChannel dom1:%d:%d dom2:%d:%d>" - % (self.dom1, self.port1, self.dom2, self.port2)) - - -def eventChannel(dom1, dom2, port1 = 0, port2 = 0): - """Create an event channel between domains. - - @return EventChannel (None on error) - """ - v = xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2, - port1=port1, port2=port2) - if v and v.get('port1'): - return EventChannel(dom1, dom2, v['port1'], v['port2']) - else: - return None diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index 9ac1b28eef..69ace083d9 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -36,6 +36,8 @@ #include "xenstored_watch.h" #include "xenstored_test.h" +#include <xen/linux/evtchn.h> + static int *xc_handle; static int eventchn_fd; static int virq_port; @@ -77,9 +79,6 @@ struct ringbuf_head char buf[0]; } __attribute__((packed)); -#define EVENTCHN_BIND _IO('E', 2) -#define EVENTCHN_UNBIND _IO('E', 3) - /* FIXME: Mark connection as broken (close it?) when this happens. */ static bool check_buffer(const struct ringbuf_head *h) { @@ -207,14 +206,17 @@ static int readchn(struct connection *conn, void *data, unsigned int len) static int destroy_domain(void *_domain) { struct domain *domain = _domain; + struct ioctl_evtchn_unbind unbind; list_del(&domain->list); - if (domain->port && - (ioctl(eventchn_fd, EVENTCHN_UNBIND, domain->port) != 0)) - eprintf("> Unbinding port %i failed!\n", domain->port); + if (domain->port) { + unbind.port = domain->port; + if (ioctl(eventchn_fd, IOCTL_EVTCHN_UNBIND, &unbind) == -1) + eprintf("> Unbinding port %i failed!\n", domain->port); + } - if(domain->page) + if (domain->page) munmap(domain->page, getpagesize()); return 0; @@ -278,6 +280,9 @@ static struct domain *new_domain(void *context, domid_t domid, const char *path) { struct domain *domain; + struct ioctl_evtchn_bind_interdomain bind; + int rc; + domain = talloc(context, struct domain); domain->port = 0; domain->shutdown = 0; @@ -298,10 +303,13 @@ static struct domain *new_domain(void *context, domid_t domid, domain->output = domain->page + getpagesize()/2; /* Tell kernel we're interested in this event. */ - if (ioctl(eventchn_fd, EVENTCHN_BIND, port) != 0) + bind.remote_domain = domid; + bind.remote_port = port; + rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind); + if (rc == -1) return NULL; - domain->port = port; + domain->port = rc; domain->conn = new_connection(writechn, readchn); domain->conn->domain = domain; return domain; @@ -445,6 +453,8 @@ void restore_existing_connections(void) int domain_init(void) { struct stat st; + struct ioctl_evtchn_bind_virq bind; + int rc; /* The size of the ringbuffer: half a page minus head structure. */ ringbuf_datasize = getpagesize() / 2 - sizeof(struct ringbuf_head); @@ -482,11 +492,11 @@ int domain_init(void) if (eventchn_fd < 0) barf_perror("Failed to open evtchn device"); - if (xc_evtchn_bind_virq(*xc_handle, VIRQ_DOM_EXC, &virq_port)) - barf_perror("Failed to bind to domain exception virq"); - - if (ioctl(eventchn_fd, EVENTCHN_BIND, virq_port) != 0) + bind.virq = VIRQ_DOM_EXC; + rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_VIRQ, &bind); + if (rc == -1) barf_perror("Failed to bind to domain exception virq port"); + virq_port = rc; return eventchn_fd; } |