aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_evtchn.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxc/xc_evtchn.c')
-rw-r--r--tools/libxc/xc_evtchn.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/tools/libxc/xc_evtchn.c b/tools/libxc/xc_evtchn.c
new file mode 100644
index 0000000000..624f5b1c15
--- /dev/null
+++ b/tools/libxc/xc_evtchn.c
@@ -0,0 +1,131 @@
+/******************************************************************************
+ * xc_evtchn.c
+ *
+ * API for manipulating and accessing inter-domain event channels.
+ *
+ * Copyright (c) 2004, K A Fraser.
+ */
+
+#include "xc_private.h"
+
+
+static int do_evtchn_op(int xc_handle, evtchn_op_t *op)
+{
+ int ret = -1;
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_event_channel_op;
+ hypercall.arg[0] = (unsigned long)op;
+
+ if ( mlock(op, sizeof(*op)) != 0 )
+ {
+ PERROR("Could not lock memory for Xen hypercall");
+ goto out1;
+ }
+
+ if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+ goto out2;
+
+ out2: (void)munlock(op, sizeof(*op));
+ out1: return ret;
+}
+
+
+int xc_evtchn_bind_interdomain(int xc_handle,
+ u32 dom1,
+ u32 dom2,
+ int *port1,
+ int *port2)
+{
+ evtchn_op_t op;
+ int rc;
+
+ op.cmd = EVTCHNOP_bind_interdomain;
+ op.u.bind_interdomain.dom1 = (domid_t)dom1;
+ op.u.bind_interdomain.dom2 = (domid_t)dom2;
+
+ if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
+ {
+ if ( port1 != NULL )
+ *port1 = op.u.bind_interdomain.port1;
+ if ( port2 != NULL )
+ *port2 = op.u.bind_interdomain.port2;
+ }
+
+ return rc;
+}
+
+
+int xc_evtchn_bind_virq(int xc_handle,
+ int virq,
+ int *port)
+{
+ evtchn_op_t op;
+ int rc;
+
+ op.cmd = EVTCHNOP_bind_virq;
+ op.u.bind_virq.virq = (u32)virq;
+
+ if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
+ {
+ if ( port != NULL )
+ *port = op.u.bind_virq.port;
+ }
+
+ return rc;
+}
+
+
+int xc_evtchn_close(int xc_handle,
+ u32 dom,
+ int port)
+{
+ evtchn_op_t op;
+ op.cmd = EVTCHNOP_close;
+ op.u.close.dom = (domid_t)dom;
+ op.u.close.port = port;
+ return do_evtchn_op(xc_handle, &op);
+}
+
+
+int xc_evtchn_send(int xc_handle,
+ int local_port)
+{
+ evtchn_op_t op;
+ op.cmd = EVTCHNOP_send;
+ op.u.send.local_port = local_port;
+ return do_evtchn_op(xc_handle, &op);
+}
+
+
+int xc_evtchn_status(int xc_handle,
+ u32 dom,
+ int port,
+ xc_evtchn_status_t *status)
+{
+ evtchn_op_t op;
+ int rc;
+
+ op.cmd = EVTCHNOP_status;
+ op.u.status.dom = (domid_t)dom;
+ op.u.status.port = port;
+
+ if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
+ {
+ switch ( status->status = op.u.status.status )
+ {
+ case EVTCHNSTAT_interdomain:
+ status->u.interdomain.dom = (u32)op.u.status.u.interdomain.dom;
+ status->u.interdomain.port = op.u.status.u.interdomain.port;
+ break;
+ case EVTCHNSTAT_pirq:
+ status->u.pirq = op.u.status.u.pirq;
+ break;
+ case EVTCHNSTAT_virq:
+ status->u.virq = op.u.status.u.virq;
+ break;
+ }
+ }
+
+ return rc;
+}