diff options
Diffstat (limited to 'tools/python/xen/ext/xc/xc.c')
-rw-r--r-- | tools/python/xen/ext/xc/xc.c | 1160 |
1 files changed, 1160 insertions, 0 deletions
diff --git a/tools/python/xen/ext/xc/xc.c b/tools/python/xen/ext/xc/xc.c new file mode 100644 index 0000000000..2eb70cf2a0 --- /dev/null +++ b/tools/python/xen/ext/xc/xc.c @@ -0,0 +1,1160 @@ +/****************************************************************************** + * Xc.c + * + * Copyright (c) 2003-2004, K A Fraser (University of Cambridge) + */ + +#include <Python.h> +#include <xc.h> +#include <zlib.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +#include <arpa/inet.h> +#include "xc_private.h" +#include "gzip_stream.h" + +/* Needed for Python versions earlier than 2.3. */ +#ifndef PyMODINIT_FUNC +#define PyMODINIT_FUNC DL_EXPORT(void) +#endif + +#define XENPKG "xen.ext.xc" + +static PyObject *xc_error, *zero; + +typedef struct { + PyObject_HEAD; + int xc_handle; +} XcObject; + +/* + * Definitions for the 'xc' object type. + */ + +static PyObject *pyxc_domain_create(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + unsigned int mem_kb = 0; + char *name = "(anon)"; + int cpu = -1; + u32 dom; + int ret; + + static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list, + &mem_kb, &name, &cpu) ) + return NULL; + + if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 ) + return PyErr_SetFromErrno(xc_error); + + return PyInt_FromLong(dom); +} + +static PyObject *pyxc_domain_pause(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + + static char *kwd_list[] = { "dom", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) ) + return NULL; + + if ( xc_domain_pause(xc->xc_handle, dom) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_domain_unpause(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + + static char *kwd_list[] = { "dom", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) ) + return NULL; + + if ( xc_domain_unpause(xc->xc_handle, dom) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_domain_destroy(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + + static char *kwd_list[] = { "dom", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) ) + return NULL; + + if ( xc_domain_destroy(xc->xc_handle, dom) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_domain_pincpu(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + int cpu = -1; + + static char *kwd_list[] = { "dom", "cpu", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, + &dom, &cpu) ) + return NULL; + + if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_domain_getinfo(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + PyObject *list; + + u32 first_dom = 0; + int max_doms = 1024, nr_doms, i; + xc_dominfo_t *info; + + static char *kwd_list[] = { "first_dom", "max_doms", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, + &first_dom, &max_doms) ) + return NULL; + + if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL ) + return PyErr_NoMemory(); + + nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info); + + list = PyList_New(nr_doms); + for ( i = 0 ; i < nr_doms; i++ ) + { + PyList_SetItem( + list, i, + Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i" + ",s:l,s:L,s:s,s:l,s:i}", + "dom", info[i].domid, + "cpu", info[i].cpu, + "dying", info[i].dying, + "crashed", info[i].crashed, + "shutdown", info[i].shutdown, + "paused", info[i].paused, + "blocked", info[i].blocked, + "running", info[i].running, + "mem_kb", info[i].nr_pages*4, + "cpu_time", info[i].cpu_time, + "name", info[i].name, + "maxmem_kb", info[i].max_memkb, + "shutdown_reason", info[i].shutdown_reason + )); + } + + free(info); + + return list; +} + +static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file){ + int rc = -1; + int fd = -1; + int open_flags = (O_CREAT | O_EXCL | O_WRONLY); + int open_mode = 0644; + + printf("%s>\n", __FUNCTION__); + fd = open(state_file, open_flags, open_mode); + if(fd < 0){ + xcio_perror(ctxt, "Could not open file for writing"); + goto exit; + } + /* Compression rate 1: we want speed over compression. + * We're mainly going for those zero pages, after all. + */ + printf("%s>gzip_stream_fdopen... \n", __FUNCTION__); + ctxt->io = gzip_stream_fdopen(fd, "wb1"); + if(!ctxt->io){ + xcio_perror(ctxt, "Could not allocate compression state"); + goto exit; + } + printf("%s> xc_linux_save...\n", __FUNCTION__); + rc = xc_linux_save(xc->xc_handle, ctxt); + exit: + if(ctxt->io) IOStream_close(ctxt->io); + if(fd >= 0) close(fd); + unlink(state_file); + printf("%s> rc=%d\n", __FUNCTION__, rc); + return rc; +} + +static PyObject *pyxc_linux_save(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + char *state_file; + int progress = 1, debug = 0; + unsigned int flags = 0; + PyObject *val = NULL; + int rc = -1; + XcIOContext ioctxt = { .info = iostdout, .err = iostderr }; + + static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, + &ioctxt.domain, + &state_file, + &ioctxt.vmconfig, + &progress, + &debug)){ + goto exit; + } + ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0); + if (progress) ioctxt.flags |= XCFLAGS_VERBOSE; + if (debug) ioctxt.flags |= XCFLAGS_DEBUG; + if(!state_file || state_file[0] == '\0') goto exit; + rc = file_save(xc, &ioctxt, state_file); + if(rc){ + PyErr_SetFromErrno(xc_error); + goto exit; + } + //xc_domain_destroy(xc->xc_handle, dom); + Py_INCREF(zero); + val = zero; + exit: + return val; +} + + +static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file){ + int rc = -1; + + ioctxt->io = gzip_stream_fopen(state_file, "rb"); + if (!ioctxt->io) { + xcio_perror(ioctxt, "Could not open file for reading"); + goto exit; + } + + rc = xc_linux_restore(xc->xc_handle, ioctxt); + exit: + if(ioctxt->io) IOStream_close(ioctxt->io); + return rc; +} + +static PyObject *pyxc_linux_restore(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + char *state_file; + int progress = 1, debug = 0; + u32 dom; + PyObject *val = NULL; + XcIOContext ioctxt = { .info = iostdout, .err = iostderr }; + int rc =-1; + + static char *kwd_list[] = { "state_file", "progress", "debug", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list, + &ioctxt.domain, + &state_file, + &progress, + &debug)){ + goto exit; + } + if (progress) ioctxt.flags |= XCFLAGS_VERBOSE; + if (debug) ioctxt.flags |= XCFLAGS_DEBUG; + + if(!state_file || state_file[0] == '\0') goto exit; + rc = file_restore(xc, &ioctxt, state_file); + if(rc){ + PyErr_SetFromErrno(xc_error); + goto exit; + } + val = Py_BuildValue("{s:i,s:s}", + "dom", ioctxt.domain, + "vmconfig", ioctxt.vmconfig); + //? free(ioctxt.vmconfig); + exit: + return val; +} + +static PyObject *pyxc_linux_build(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + char *image, *ramdisk = NULL, *cmdline = ""; + int control_evtchn, flags = 0; + + static char *kwd_list[] = { "dom", "control_evtchn", + "image", "ramdisk", "cmdline", "flags", + NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, + &dom, &control_evtchn, + &image, &ramdisk, &cmdline, &flags) ) + return NULL; + + if ( xc_linux_build(xc->xc_handle, dom, image, + ramdisk, cmdline, control_evtchn, flags) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_netbsd_build(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + char *image, *ramdisk = NULL, *cmdline = ""; + int control_evtchn; + + static char *kwd_list[] = { "dom", "control_evtchn", + "image", "ramdisk", "cmdline", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, + &dom, &control_evtchn, + &image, &ramdisk, &cmdline) ) + return NULL; + + if ( xc_netbsd_build(xc->xc_handle, dom, image, + cmdline, control_evtchn) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_bvtsched_global_set(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + unsigned long ctx_allow; + + static char *kwd_list[] = { "ctx_allow", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) ) + return NULL; + + if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_bvtsched_global_get(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + unsigned long ctx_allow; + + if ( !PyArg_ParseTuple(args, "") ) + return NULL; + + if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 ) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("s:l", "ctx_allow", ctx_allow); +} + +static PyObject *pyxc_bvtsched_domain_set(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + unsigned long mcuadv, warp, warpl, warpu; + + static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl", + "warpu", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list, + &dom, &mcuadv, &warp, &warpl, &warpu) ) + return NULL; + + if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv, + warp, warpl, warpu) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_bvtsched_domain_get(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + u32 dom; + unsigned long mcuadv, warp, warpl, warpu; + + static char *kwd_list[] = { "dom", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) ) + return NULL; + + if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp, + &warpl, &warpu) != 0 ) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}", + "domain", dom, + "mcuadv", mcuadv, + "warp", warp, + "warpl", warpl, + "warpu", warpu); +} + +static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF; + int port1, port2; + + static char *kwd_list[] = { "dom1", "dom2", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list, + &dom1, &dom2) ) + return NULL; + + if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1, + dom2, &port1, &port2) != 0 ) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("{s:i,s:i}", + "port1", port1, + "port2", port2); +} + +static PyObject *pyxc_evtchn_bind_virq(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + int virq, port; + + static char *kwd_list[] = { "virq", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) ) + return NULL; + + if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 ) + return PyErr_SetFromErrno(xc_error); + + return PyInt_FromLong(port); +} + +static PyObject *pyxc_evtchn_close(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom = DOMID_SELF; + int port; + + static char *kwd_list[] = { "port", "dom", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, + &port, &dom) ) + return NULL; + + if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_evtchn_send(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + int port; + + static char *kwd_list[] = { "port", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) ) + return NULL; + + if ( xc_evtchn_send(xc->xc_handle, port) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_evtchn_status(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + PyObject *dict; + + u32 dom = DOMID_SELF; + int port, ret; + xc_evtchn_status_t status; + + static char *kwd_list[] = { "port", "dom", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, + &port, &dom) ) + return NULL; + + ret = xc_evtchn_status(xc->xc_handle, dom, port, &status); + if ( ret != 0 ) + return PyErr_SetFromErrno(xc_error); + + switch ( status.status ) + { + case EVTCHNSTAT_closed: + dict = Py_BuildValue("{s:s}", + "status", "closed"); + break; + case EVTCHNSTAT_unbound: + dict = Py_BuildValue("{s:s}", + "status", "unbound"); + break; + case EVTCHNSTAT_interdomain: + dict = Py_BuildValue("{s:s,s:i,s:i}", + "status", "interdomain", + "dom", status.u.interdomain.dom, + "port", status.u.interdomain.port); + break; + case EVTCHNSTAT_pirq: + dict = Py_BuildValue("{s:s,s:i}", + "status", "pirq", + "irq", status.u.pirq); + break; + case EVTCHNSTAT_virq: + dict = Py_BuildValue("{s:s,s:i}", + "status", "virq", + "irq", status.u.virq); + break; + default: + dict = Py_BuildValue("{}"); + break; + } + + return dict; +} + +static PyObject *pyxc_physdev_pci_access_modify(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + u32 dom; + int bus, dev, func, enable, ret; + + static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list, + &dom, &bus, &dev, &func, &enable) ) + return NULL; + + ret = xc_physdev_pci_access_modify( + xc->xc_handle, dom, bus, dev, func, enable); + if ( ret != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_readconsolering(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + unsigned int clear = 0; + char str[32768]; + int ret; + + static char *kwd_list[] = { "clear", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) ) + return NULL; + + ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear); + if ( ret < 0 ) + return PyErr_SetFromErrno(xc_error); + + return PyString_FromStringAndSize(str, ret); +} + +static PyObject *pyxc_physinfo(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + xc_physinfo_t info; + + if ( !PyArg_ParseTuple(args, "") ) + return NULL; + + if ( xc_physinfo(xc->xc_handle, &info) != 0 ) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}", + "ht_per_core", info.ht_per_core, + "cores", info.cores, + "total_pages", info.total_pages, + "free_pages", info.free_pages, + "cpu_khz", info.cpu_khz); +} + +static PyObject *pyxc_atropos_domain_set(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + u32 domid; + u64 period, slice, latency; + int xtratime; + + static char *kwd_list[] = { "dom", "period", "slice", "latency", + "xtratime", NULL }; + + if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid, + &period, &slice, &latency, &xtratime) ) + return NULL; + + if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice, + latency, xtratime) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_atropos_domain_get(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + u32 domid; + u64 period, slice, latency; + int xtratime; + + static char *kwd_list[] = { "dom", NULL }; + + if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) ) + return NULL; + + if ( xc_atropos_domain_get( xc->xc_handle, domid, &period, + &slice, &latency, &xtratime ) ) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}", + "domain", domid, + "period", period, + "slice", slice, + "latency", latency, + "xtratime", xtratime); +} + + +static PyObject *pyxc_rrobin_global_set(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + u64 slice; + + static char *kwd_list[] = { "slice", NULL }; + + if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) ) + return NULL; + + if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_shadow_control(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + int op=0; + + static char *kwd_list[] = { "dom", "op", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, + &dom, &op) ) + return NULL; + + if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_rrobin_global_get(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + u64 slice; + + if ( !PyArg_ParseTuple(args, "") ) + return NULL; + + if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 ) + return PyErr_SetFromErrno(xc_error); + + return Py_BuildValue("{s:L}", "slice", slice); +} + +static PyObject *pyxc_domain_setname(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + u32 dom; + char *name; + + static char *kwd_list[] = { "dom", "name", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list, + &dom, &name) ) + return NULL; + + if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_domain_setmaxmem(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom; + unsigned long max_memkb; + + static char *kwd_list[] = { "dom", "max_memkb", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, + &dom, &max_memkb) ) + return NULL; + + if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + + +static PyMethodDef pyxc_methods[] = { + { "domain_create", + (PyCFunction)pyxc_domain_create, + METH_VARARGS | METH_KEYWORDS, "\n" + "Create a new domain.\n" + " mem_kb [int, 0]: Memory allocation, in kilobytes.\n" + " name [str, '(anon)']: Informative textual name.\n\n" + "Returns: [int] new domain identifier; -1 on error.\n" }, + + { "domain_pause", + (PyCFunction)pyxc_domain_pause, + METH_VARARGS | METH_KEYWORDS, "\n" + "Temporarily pause execution of a domain.\n" + " dom [int]: Identifier of domain to be paused.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_unpause", + (PyCFunction)pyxc_domain_unpause, + METH_VARARGS | METH_KEYWORDS, "\n" + "(Re)start execution of a domain.\n" + " dom [int]: Identifier of domain to be unpaused.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_destroy", + (PyCFunction)pyxc_domain_destroy, + METH_VARARGS | METH_KEYWORDS, "\n" + "Destroy a domain.\n" + " dom [int]: Identifier of domain to be destroyed.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_pincpu", + (PyCFunction)pyxc_domain_pincpu, + METH_VARARGS | METH_KEYWORDS, "\n" + "Pin a domain to a specified CPU.\n" + " dom [int]: Identifier of domain to be pinned.\n" + " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_getinfo", + (PyCFunction)pyxc_domain_getinfo, + METH_VARARGS | METH_KEYWORDS, "\n" + "Get information regarding a set of domains, in increasing id order.\n" + " first_dom [int, 0]: First domain to retrieve info about.\n" + " max_doms [int, 1024]: Maximum number of domains to retrieve info" + " about.\n\n" + "Returns: [list of dicts] if list length is less than 'max_doms'\n" + " parameter then there was an error, or the end of the\n" + " domain-id space was reached.\n" + " dom [int]: Identifier of domain to which this info pertains\n" + " cpu [int]: CPU to which this domain is bound\n" + " dying [int]: Bool - is the domain dying?\n" + " crashed [int]: Bool - has the domain crashed?\n" + " shutdown [int]: Bool - has the domain shut itself down?\n" + " paused [int]: Bool - is the domain paused by control software?\n" + " blocked [int]: Bool - is the domain blocked waiting for an event?\n" + " running [int]: Bool - is the domain currently running?\n" + " mem_kb [int]: Memory reservation, in kilobytes\n" + " cpu_time [long]: CPU time consumed, in nanoseconds\n" + " name [str]: Identifying name\n" + " shutdown_reason [int]: Numeric code from guest OS, explaining " + "reason why it shut itself down.\n" }, + + { "linux_save", + (PyCFunction)pyxc_linux_save, + METH_VARARGS | METH_KEYWORDS, "\n" + "Save the CPU and memory state of a Linux guest OS.\n" + " dom [int]: Identifier of domain to be saved.\n" + " state_file [str]: Name of state file. Must not currently exist.\n" + " progress [int, 1]: Bool - display a running progress indication?\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "linux_restore", + (PyCFunction)pyxc_linux_restore, + METH_VARARGS | METH_KEYWORDS, "\n" + "Restore the CPU and memory state of a Linux guest OS.\n" + " state_file [str]: Name of state file. Must not currently exist.\n" + " progress [int, 1]: Bool - display a running progress indication?\n\n" + "Returns: [int] new domain identifier on success; -1 on error.\n" }, + + { "linux_build", + (PyCFunction)pyxc_linux_build, + METH_VARARGS | METH_KEYWORDS, "\n" + "Build a new Linux guest OS.\n" + " dom [int]: Identifier of domain to build into.\n" + " image [str]: Name of kernel image file. May be gzipped.\n" + " ramdisk [str, n/a]: Name of ramdisk file, if any.\n" + " cmdline [str, n/a]: Kernel parameters, if any.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "netbsd_build", + (PyCFunction)pyxc_netbsd_build, + METH_VARARGS | METH_KEYWORDS, "\n" + "Build a new NetBSD guest OS.\n" + " dom [int]: Identifier of domain to build into.\n" + " image [str]: Name of kernel image file. May be gzipped.\n" + " cmdline [str, n/a]: Kernel parameters, if any.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "bvtsched_global_set", + (PyCFunction)pyxc_bvtsched_global_set, + METH_VARARGS | METH_KEYWORDS, "\n" + "Set global tuning parameters for Borrowed Virtual Time scheduler.\n" + " ctx_allow [int]: Minimal guaranteed quantum.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "bvtsched_global_get", + (PyCFunction)pyxc_bvtsched_global_get, + METH_KEYWORDS, "\n" + "Get global tuning parameters for BVT scheduler.\n" + "Returns: [dict]:\n" + " ctx_allow [int]: context switch allowance\n" }, + + { "bvtsched_domain_set", + (PyCFunction)pyxc_bvtsched_domain_set, + METH_VARARGS | METH_KEYWORDS, "\n" + "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n" + " dom [int]: Identifier of domain to be tuned.\n" + " mcuadv [int]: Proportional to the inverse of the domain's weight.\n" + " warp [int]: How far to warp domain's EVT on unblock.\n" + " warpl [int]: How long the domain can run warped.\n" + " warpu [int]: How long before the domain can warp again.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "bvtsched_domain_get", + (PyCFunction)pyxc_bvtsched_domain_get, + METH_KEYWORDS, "\n" + "Get per-domain tuning parameters under the BVT scheduler.\n" + " dom [int]: Identifier of domain to be queried.\n" + "Returns [dict]:\n" + " domain [int]: Domain ID.\n" + " mcuadv [long]: MCU Advance.\n" + " warp [long]: Warp.\n" + " warpu [long]: Unwarp requirement.\n" + " warpl [long]: Warp limit,\n" + }, + + { "atropos_domain_set", + (PyCFunction)pyxc_atropos_domain_set, + METH_KEYWORDS, "\n" + "Set the scheduling parameters for a domain when running with Atropos.\n" + " dom [int]: domain to set\n" + " period [long]: domain's scheduling period\n" + " slice [long]: domain's slice per period\n" + " latency [long]: wakeup latency hint\n" + " xtratime [int]: boolean\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "atropos_domain_get", + (PyCFunction)pyxc_atropos_domain_get, + METH_KEYWORDS, "\n" + "Get the current scheduling parameters for a domain when running with\n" + "the Atropos scheduler." + " dom [int]: domain to query\n" + "Returns: [dict]\n" + " domain [int]: domain ID\n" + " period [long]: scheduler period\n" + " slice [long]: CPU reservation per period\n" + " latency [long]: unblocking latency hint\n" + " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" }, + + { "rrobin_global_set", + (PyCFunction)pyxc_rrobin_global_set, + METH_KEYWORDS, "\n" + "Set Round Robin scheduler slice.\n" + " slice [long]: Round Robin scheduler slice\n" + "Returns: [int] 0 on success, throws an exception on failure\n" }, + + { "rrobin_global_get", + (PyCFunction)pyxc_rrobin_global_get, + METH_KEYWORDS, "\n" + "Get Round Robin scheduler settings\n" + "Returns [dict]:\n" + " slice [long]: Scheduler time slice.\n" }, + + { "evtchn_bind_interdomain", + (PyCFunction)pyxc_evtchn_bind_interdomain, + METH_VARARGS | METH_KEYWORDS, "\n" + "Open an event channel between two domains.\n" + " dom1 [int, SELF]: First domain to be connected.\n" + " dom2 [int, SELF]: Second domain to be connected.\n\n" + "Returns: [dict] dictionary is empty on failure.\n" + " port1 [int]: Port-id for endpoint at dom1.\n" + " port2 [int]: Port-id for endpoint at dom2.\n" }, + + { "evtchn_bind_virq", + (PyCFunction)pyxc_evtchn_bind_virq, + METH_VARARGS | METH_KEYWORDS, "\n" + "Bind an event channel to the specified VIRQ.\n" + " virq [int]: VIRQ to bind.\n\n" + "Returns: [int] Bound event-channel port.\n" }, + + { "evtchn_close", + (PyCFunction)pyxc_evtchn_close, + METH_VARARGS | METH_KEYWORDS, "\n" + "Close an event channel.\n" + " dom [int, SELF]: Dom-id of one endpoint of the channel.\n" + " port [int]: Port-id of one endpoint of the channel.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "evtchn_send", + (PyCFunction)pyxc_evtchn_send, + METH_VARARGS | METH_KEYWORDS, "\n" + "Send an event along a locally-connected event channel.\n" + " port [int]: Port-id of a local channel endpoint.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "evtchn_status", + (PyCFunction)pyxc_evtchn_status, + METH_VARARGS | METH_KEYWORDS, "\n" + "Query the status of an event channel.\n" + " dom [int, SELF]: Dom-id of one endpoint of the channel.\n" + " port [int]: Port-id of one endpoint of the channel.\n\n" + "Returns: [dict] dictionary is empty on failure.\n" + " status [str]: 'closed', 'unbound', 'interdomain', 'pirq'," + " or 'virq'.\n" + "The following are returned if 'status' is 'interdomain':\n" + " dom [int]: Dom-id of remote endpoint.\n" + " port [int]: Port-id of remote endpoint.\n" + "The following are returned if 'status' is 'pirq' or 'virq':\n" + " irq [int]: IRQ number.\n" }, + + { "physdev_pci_access_modify", + (PyCFunction)pyxc_physdev_pci_access_modify, + METH_VARARGS | METH_KEYWORDS, "\n" + "Allow a domain access to a PCI device\n" + " dom [int]: Identifier of domain to be allowed access.\n" + " bus [int]: PCI bus\n" + " dev [int]: PCI slot\n" + " func [int]: PCI function\n" + " enable [int]: Non-zero means enable access; else disable access\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "readconsolering", + (PyCFunction)pyxc_readconsolering, + METH_VARARGS | METH_KEYWORDS, "\n" + "Read Xen's console ring.\n" + " clear [int, 0]: Bool - clear the ring after reading from it?\n\n" + "Returns: [str] string is empty on failure.\n" }, + + { "physinfo", + (PyCFunction)pyxc_physinfo, + METH_VARARGS, "\n" + "Get information about the physical host machine\n" + "Returns [dict]: information about the hardware" + " [None]: on failure.\n" }, + + { "shadow_control", + (PyCFunction)pyxc_shadow_control, + METH_VARARGS | METH_KEYWORDS, "\n" + "Set parameter for shadow pagetable interface\n" + " dom [int]: Identifier of domain.\n" + " op [int, 0]: operation\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_setname", + (PyCFunction)pyxc_domain_setname, + METH_VARARGS | METH_KEYWORDS, "\n" + "Set domain informative textual name\n" + " dom [int]: Identifier of domain.\n" + " name [str]: Text string.\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_setmaxmem", + (PyCFunction)pyxc_domain_setname, + METH_VARARGS | METH_KEYWORDS, "\n" + "Set a domain's memory limit\n" + " dom [int]: Identifier of domain.\n" + " max_memkb [long]: .\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { NULL, NULL, 0, NULL } +}; + + +/* + * Definitions for the 'Xc' module wrapper. + */ + +staticforward PyTypeObject PyXcType; + +static PyObject *PyXc_new(PyObject *self, PyObject *args) +{ + XcObject *xc; + + if ( !PyArg_ParseTuple(args, ":new") ) + return NULL; + + xc = PyObject_New(XcObject, &PyXcType); + + if ( (xc->xc_handle = xc_interface_open()) == -1 ) + { + PyObject_Del((PyObject *)xc); + return PyErr_SetFromErrno(xc_error); + } + + return (PyObject *)xc; +} + +static PyObject *PyXc_getattr(PyObject *obj, char *name) +{ + return Py_FindMethod(pyxc_methods, obj, name); +} + +static void PyXc_dealloc(PyObject *self) +{ + XcObject *xc = (XcObject *)self; + (void)xc_interface_close(xc->xc_handle); + PyObject_Del(self); +} + +static PyTypeObject PyXcType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "Xc", + sizeof(XcObject), + 0, + PyXc_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + PyXc_getattr, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + NULL /* tp_hash */ +}; + +static PyMethodDef PyXc_methods[] = { + { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." }, + { NULL, NULL, 0, NULL } +}; + +PyMODINIT_FUNC initxc(void) +{ + PyObject *m, *d; + + m = Py_InitModule(XENPKG, PyXc_methods); + + d = PyModule_GetDict(m); + xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL); + PyDict_SetItemString(d, "error", xc_error); + + zero = PyInt_FromLong(0); +} |