# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 4083eb31def03aa7cb98edf4a390e2f94459efe2
# Parent cd228621e1fd4bc0f404b80e6c618ae02d0c1173
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@xxxxxxxxxxxxx>
diff -r cd228621e1fd -r 4083eb31def0
linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Oct 6 14:12:31 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Oct 6 15:07:52 2005
@@ -44,9 +44,9 @@
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/init.h>
-#define XEN_EVTCHN_MASK_OPS
+#include <linux/gfp.h>
#include <asm-xen/evtchn.h>
-#include <linux/gfp.h>
+#include <asm-xen/linux-public/evtchn.h>
struct per_user_data {
/* Notification ring, accessed via /dev/xen/evtchn. */
@@ -78,7 +78,8 @@
u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
if (u->ring_cons == u->ring_prod++) {
wake_up_interruptible(&u->evtchn_wait);
- kill_fasync(&u->evtchn_async_queue, SIGIO,
POLL_IN);
+ kill_fasync(&u->evtchn_async_queue,
+ SIGIO, POLL_IN);
}
} else {
u->ring_overflow = 1;
@@ -208,38 +209,100 @@
static int evtchn_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int rc = 0;
+ int rc;
struct per_user_data *u = file->private_data;
+ evtchn_op_t op = { 0 };
spin_lock_irq(&port_user_lock);
switch (cmd) {
- case EVTCHN_RESET:
+ case IOCTL_EVTCHN_BIND_VIRQ: {
+ struct ioctl_evtchn_bind_virq bind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
+ break;
+
+ op.cmd = EVTCHNOP_bind_virq;
+ op.u.bind_virq.virq = bind.virq;
+ op.u.bind_virq.vcpu = 0;
+ rc = HYPERVISOR_event_channel_op(&op);
+ if (rc != 0)
+ break;
+
+ rc = op.u.bind_virq.port;
+ port_user[rc] = u;
+ unmask_evtchn(rc);
+ break;
+ }
+
+ case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
+ struct ioctl_evtchn_bind_interdomain bind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
+ break;
+
+ op.cmd = EVTCHNOP_bind_interdomain;
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = bind.remote_domain;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = bind.remote_port;
+ rc = HYPERVISOR_event_channel_op(&op);
+ if (rc != 0)
+ break;
+
+ rc = op.u.bind_interdomain.port1;
+ port_user[rc] = u;
+ unmask_evtchn(rc);
+ break;
+ }
+
+ case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
+ struct ioctl_evtchn_bind_unbound_port bind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
+ break;
+
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = bind.remote_domain;
+ rc = HYPERVISOR_event_channel_op(&op);
+ if (rc != 0)
+ break;
+
+ rc = op.u.alloc_unbound.port;
+ port_user[rc] = u;
+ unmask_evtchn(rc);
+ break;
+ }
+
+ case IOCTL_EVTCHN_UNBIND: {
+ struct ioctl_evtchn_unbind unbind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&unbind, (void *)arg, sizeof(unbind)))
+ break;
+
+ if (unbind.port >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[unbind.port] != u) {
+ rc = -ENOTCONN;
+ } else {
+ port_user[unbind.port] = NULL;
+ mask_evtchn(unbind.port);
+ rc = 0;
+ }
+ break;
+ }
+
+ case IOCTL_EVTCHN_RESET: {
/* Initialise the ring to empty. Clear errors. */
u->ring_cons = u->ring_prod = u->ring_overflow = 0;
- break;
-
- case EVTCHN_BIND:
- if (arg >= NR_EVENT_CHANNELS) {
- rc = -EINVAL;
- } else if (port_user[arg] != NULL) {
- rc = -EISCONN;
- } else {
- port_user[arg] = u;
- unmask_evtchn(arg);
- }
- break;
-
- case EVTCHN_UNBIND:
- if (arg >= NR_EVENT_CHANNELS) {
- rc = -EINVAL;
- } else if (port_user[arg] != u) {
- rc = -ENOTCONN;
- } else {
- port_user[arg] = NULL;
- mask_evtchn(arg);
- }
- break;
+ rc = 0;
+ break;
+ }
default:
rc = -ENOSYS;
@@ -295,6 +358,7 @@
{
int i;
struct per_user_data *u = filp->private_data;
+ evtchn_op_t op = { 0 };
spin_lock_irq(&port_user_lock);
@@ -302,11 +366,16 @@
for (i = 0; i < NR_EVENT_CHANNELS; i++)
{
- if (port_user[i] == u)
- {
- port_user[i] = NULL;
- mask_evtchn(i);
- }
+ if (port_user[i] != u)
+ continue;
+
+ port_user[i] = NULL;
+ mask_evtchn(i);
+
+ op.cmd = EVTCHNOP_close;
+ op.u.close.dom = DOMID_SELF;
+ op.u.close.port = i;
+ BUG_ON(HYPERVISOR_event_channel_op(&op));
}
spin_unlock_irq(&port_user_lock);
diff -r cd228621e1fd -r 4083eb31def0
linux-2.6-xen-sparse/include/asm-xen/evtchn.h
--- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Oct 6 14:12:31 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Oct 6 15:07:52 2005
@@ -129,21 +129,6 @@
(void)HYPERVISOR_event_channel_op(&op);
}
-/*
- * CHARACTER-DEVICE DEFINITIONS
- */
-
-/* /dev/xen/evtchn resides at device number major=10, minor=201 */
-#define EVTCHN_MINOR 201
-
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
#endif /* __ASM_EVTCHN_H__ */
/*
diff -r cd228621e1fd -r 4083eb31def0
linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Thu Oct
6 14:12:31 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Thu Oct
6 15:07:52 2005
@@ -3,7 +3,7 @@
*
* Interface to /proc/xen/privcmd.
*
- * Copyright (c) 2003-2004, K A Fraser
+ * Copyright (c) 2003-2005, K A Fraser
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
@@ -27,39 +27,39 @@
* IN THE SOFTWARE.
*/
-#ifndef __PRIVCMD_H__
-#define __PRIVCMD_H__
+#ifndef __LINUX_PUBLIC_PRIVCMD_H__
+#define __LINUX_PUBLIC_PRIVCMD_H__
typedef struct privcmd_hypercall
{
- unsigned long op;
- unsigned long arg[5];
+ unsigned long op;
+ unsigned long arg[5];
} privcmd_hypercall_t;
typedef struct privcmd_mmap_entry {
- unsigned long va;
- unsigned long mfn;
- unsigned long npages;
+ unsigned long va;
+ unsigned long mfn;
+ unsigned long npages;
} privcmd_mmap_entry_t;
typedef struct privcmd_mmap {
- int num;
- domid_t dom; /* target domain */
- privcmd_mmap_entry_t *entry;
+ int num;
+ domid_t dom; /* target domain */
+ privcmd_mmap_entry_t *entry;
} privcmd_mmap_t;
typedef struct privcmd_mmapbatch {
- int num; /* number of pages to populate */
- domid_t dom; /* target domain */
- unsigned long addr; /* virtual address */
- unsigned long *arr; /* array of mfns - top nibble set on err */
+ int num; /* number of pages to populate */
+ domid_t dom; /* target domain */
+ unsigned long addr; /* virtual address */
+ unsigned long *arr; /* array of mfns - top nibble set on err */
} privcmd_mmapbatch_t;
typedef struct privcmd_blkmsg
{
- unsigned long op;
- void *buf;
- int buf_size;
+ unsigned long op;
+ void *buf;
+ int buf_size;
} privcmd_blkmsg_t;
/*
@@ -67,16 +67,26 @@
* @arg: &privcmd_hypercall_t
* Return: Value returned from execution of the specified hypercall.
*/
-#define IOCTL_PRIVCMD_HYPERCALL \
- _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
+#define IOCTL_PRIVCMD_HYPERCALL \
+ _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
-#define IOCTL_PRIVCMD_MMAP \
- _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
-#define IOCTL_PRIVCMD_MMAPBATCH \
- _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
-#define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN \
- _IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
-#define IOCTL_PRIVCMD_INITDOMAIN_STORE \
- _IOC(_IOC_READ, 'P', 5, 0)
+#define IOCTL_PRIVCMD_MMAP \
+ _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
+#define IOCTL_PRIVCMD_MMAPBATCH \
+ _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
+#define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN \
+ _IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
+#define IOCTL_PRIVCMD_INITDOMAIN_STORE \
+ _IOC(_IOC_READ, 'P', 5, 0)
-#endif /* __PRIVCMD_H__ */
+#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r cd228621e1fd -r 4083eb31def0 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Thu Oct 6 14:12:31 2005
+++ b/tools/console/daemon/io.c Thu Oct 6 15:07:52 2005
@@ -1,4 +1,4 @@
-/*\
+/*
* Copyright (C) International Business Machines Corp., 2005
* Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
*
@@ -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 @@
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 @@
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 -r cd228621e1fd -r 4083eb31def0 tools/debugger/pdb/pdb_xen.c
--- a/tools/debugger/pdb/pdb_xen.c Thu Oct 6 14:12:31 2005
+++ b/tools/debugger/pdb/pdb_xen.c Thu Oct 6 15:07:52 2005
@@ -43,11 +43,7 @@
#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 -r cd228621e1fd -r 4083eb31def0 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Thu Oct 6 14:12:31 2005
+++ b/tools/ioemu/target-i386-dm/helper2.c Thu Oct 6 15:07:52 2005
@@ -49,10 +49,13 @@
#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;
@@ -119,7 +122,7 @@
//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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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 -r cd228621e1fd -r 4083eb31def0 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Thu Oct 6 14:12:31 2005
+++ b/tools/ioemu/vl.c Thu Oct 6 15:07:52 2005
@@ -2806,9 +2806,9 @@
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 -r cd228621e1fd -r 4083eb31def0 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Oct 6 14:12:31 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu Oct 6 15:07:52 2005
@@ -435,10 +435,10 @@
u32 dom = DOMID_SELF, remote_dom;
int port = 0;
- static char *kwd_list[] = { "remote_dom", "dom", "port", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
- &remote_dom, &dom, &port) )
+ static char *kwd_list[] = { "remote_dom", "dom", NULL };
+
+ 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 -r cd228621e1fd -r 4083eb31def0 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py Thu Oct 6 14:12:31 2005
+++ b/tools/python/xen/xend/XendCheckpoint.py Thu Oct 6 15:07:52 2005
@@ -126,8 +126,8 @@
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 @@
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 -r cd228621e1fd -r 4083eb31def0 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu Oct 6 14:12:31 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu Oct 6 15:07:52 2005
@@ -31,8 +31,6 @@
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
@@ -785,32 +783,6 @@
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 @@
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 @@
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 @@
guarantee."""
self.release_devices()
- self.closeStoreChannel()
- self.closeConsoleChannel()
if self.image:
try:
@@ -1164,35 +1130,22 @@
@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 @@
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 -r cd228621e1fd -r 4083eb31def0 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu Oct 6 14:12:31 2005
+++ b/tools/python/xen/xend/image.py Thu Oct 6 15:07:52 2005
@@ -25,8 +25,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
return vncconnect
def destroy(self):
- if self.device_channel:
- self.device_channel.close()
import signal
if not self.pid:
return
diff -r cd228621e1fd -r 4083eb31def0 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Thu Oct 6 14:12:31 2005
+++ b/tools/xenstore/xenstored_domain.c Thu Oct 6 15:07:52 2005
@@ -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;
@@ -76,9 +78,6 @@
u8 flags;
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 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->page)
+ 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)
munmap(domain->page, getpagesize());
return 0;
@@ -278,6 +280,9 @@
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 @@
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 @@
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 @@
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;
}
diff -r cd228621e1fd -r 4083eb31def0 xen/common/event_channel.c
--- a/xen/common/event_channel.c Thu Oct 6 14:12:31 2005
+++ b/xen/common/event_channel.c Thu Oct 6 15:07:52 2005
@@ -36,7 +36,13 @@
#define evtchn_from_port(d,p) \
(&(bucket_from_port(d,p))[(p)&(EVTCHNS_PER_BUCKET-1)])
-#define ERROR_EXIT(_errno) do { rc = (_errno); goto out; } while ( 0 )
+#define ERROR_EXIT(_errno) \
+ do { \
+ DPRINTK("EVTCHNOP failure: domain %d, error %d, line %d\n", \
+ current->domain->domain_id, (_errno), __LINE__); \
+ rc = (_errno); \
+ goto out; \
+ } while ( 0 )
static int get_free_port(struct domain *d)
{
diff -r cd228621e1fd -r 4083eb31def0
linux-2.6-xen-sparse/include/asm-xen/linux-public/evtchn.h
--- /dev/null Thu Oct 6 14:12:31 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/evtchn.h Thu Oct
6 15:07:52 2005
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * evtchn.h
+ *
+ * Interface to /dev/xen/evtchn.
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __LINUX_PUBLIC_EVTCHN_H__
+#define __LINUX_PUBLIC_EVTCHN_H__
+
+/* /dev/xen/evtchn resides at device number major=10, minor=201 */
+#define EVTCHN_MINOR 201
+
+/*
+ * Bind a fresh port to VIRQ @virq.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_VIRQ \
+ _IOC(_IOC_NONE, 'E', 0, sizeof(struct ioctl_evtchn_bind_virq))
+struct ioctl_evtchn_bind_virq {
+ unsigned int virq;
+};
+
+/*
+ * Bind a fresh port to remote <@remote_domain, @remote_port>.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_INTERDOMAIN \
+ _IOC(_IOC_NONE, 'E', 1, sizeof(struct ioctl_evtchn_bind_interdomain))
+struct ioctl_evtchn_bind_interdomain {
+ unsigned int remote_domain, remote_port;
+};
+
+/*
+ * Allocate a fresh port for binding to @remote_domain.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \
+ _IOC(_IOC_NONE, 'E', 2, sizeof(struct ioctl_evtchn_bind_unbound_port))
+struct ioctl_evtchn_bind_unbound_port {
+ unsigned int remote_domain;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_UNBIND \
+ _IOC(_IOC_NONE, 'E', 3, sizeof(struct ioctl_evtchn_unbind))
+struct ioctl_evtchn_unbind {
+ unsigned int port;
+};
+
+/* Clear and reinitialise the event buffer. Clear error condition. */
+#define IOCTL_EVTCHN_RESET \
+ _IOC(_IOC_NONE, 'E', 4, 0)
+
+#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r cd228621e1fd -r 4083eb31def0 tools/python/xen/xend/server/channel.py
--- a/tools/python/xen/xend/server/channel.py Thu Oct 6 14:12:31 2005
+++ /dev/null Thu Oct 6 15:07:52 2005
@@ -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@xxxxxx>
-# 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
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|