ia64/xen-unstable

view tools/python/xen/lowlevel/xc/xc.c @ 12705:b7095209e31a

[LIBXC] Fix Solaris build: Use XC_PAGE_SIZE not PAGE_SIZE.
Signed-off-by: John Levon <john.levon@sun.com>
author kfraser@localhost.localdomain
date Thu Nov 30 17:36:03 2006 +0000 (2006-11-30)
parents 9d6bc06919e0
children ba7fca36fbd0 2dd4569e0640
line source
1 /******************************************************************************
2 * Xc.c
3 *
4 * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
5 */
7 #include <Python.h>
8 #include <xenctrl.h>
9 #include <xenguest.h>
10 #include <zlib.h>
11 #include <fcntl.h>
12 #include <netinet/in.h>
13 #include <netinet/tcp.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <sys/mman.h>
17 #include <netdb.h>
18 #include <arpa/inet.h>
20 #include "xenctrl.h"
21 #include <xen/hvm/hvm_info_table.h>
22 #include <xen/hvm/params.h>
24 /* Needed for Python versions earlier than 2.3. */
25 #ifndef PyMODINIT_FUNC
26 #define PyMODINIT_FUNC DL_EXPORT(void)
27 #endif
29 #define PKG "xen.lowlevel.xc"
30 #define CLS "xc"
32 static PyObject *xc_error, *zero;
34 typedef struct {
35 PyObject_HEAD;
36 int xc_handle;
37 } XcObject;
40 static PyObject *dom_op(XcObject *self, PyObject *args,
41 int (*fn)(int, uint32_t));
44 static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args)
45 {
46 uint32_t dom;
47 char *corefile;
49 if (!PyArg_ParseTuple(args, "is", &dom, &corefile))
50 return NULL;
52 if ( (corefile == NULL) || (corefile[0] == '\0') )
53 return NULL;
55 if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0)
56 return PyErr_SetFromErrno(xc_error);
58 Py_INCREF(zero);
59 return zero;
60 }
62 static PyObject *pyxc_handle(XcObject *self)
63 {
64 return PyInt_FromLong(self->xc_handle);
65 }
67 static PyObject *pyxc_domain_create(XcObject *self,
68 PyObject *args,
69 PyObject *kwds)
70 {
71 uint32_t dom = 0, ssidref = 0, flags = 0;
72 int ret, i, hvm = 0;
73 PyObject *pyhandle = NULL;
74 xen_domain_handle_t handle = {
75 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
76 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef };
78 static char *kwd_list[] = { "domid", "ssidref", "handle", "hvm", NULL };
80 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiOi", kwd_list,
81 &dom, &ssidref, &pyhandle, &hvm))
82 return NULL;
84 if ( pyhandle != NULL )
85 {
86 if ( !PyList_Check(pyhandle) ||
87 (PyList_Size(pyhandle) != sizeof(xen_domain_handle_t)) )
88 goto out_exception;
90 for ( i = 0; i < sizeof(xen_domain_handle_t); i++ )
91 {
92 PyObject *p = PyList_GetItem(pyhandle, i);
93 if ( !PyInt_Check(p) )
94 goto out_exception;
95 handle[i] = (uint8_t)PyInt_AsLong(p);
96 }
97 }
99 if ( hvm )
100 flags |= XEN_DOMCTL_CDF_hvm_guest;
102 if ( (ret = xc_domain_create(self->xc_handle, ssidref,
103 handle, flags, &dom)) < 0 )
104 return PyErr_SetFromErrno(xc_error);
106 return PyInt_FromLong(dom);
108 out_exception:
109 errno = EINVAL;
110 PyErr_SetFromErrno(xc_error);
111 return NULL;
112 }
114 static PyObject *pyxc_domain_max_vcpus(XcObject *self, PyObject *args)
115 {
116 uint32_t dom, max;
118 if (!PyArg_ParseTuple(args, "ii", &dom, &max))
119 return NULL;
121 if (xc_domain_max_vcpus(self->xc_handle, dom, max) != 0)
122 return PyErr_SetFromErrno(xc_error);
124 Py_INCREF(zero);
125 return zero;
126 }
128 static PyObject *pyxc_domain_pause(XcObject *self, PyObject *args)
129 {
130 return dom_op(self, args, xc_domain_pause);
131 }
133 static PyObject *pyxc_domain_unpause(XcObject *self, PyObject *args)
134 {
135 return dom_op(self, args, xc_domain_unpause);
136 }
138 static PyObject *pyxc_domain_destroy(XcObject *self, PyObject *args)
139 {
140 return dom_op(self, args, xc_domain_destroy);
141 }
144 static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
145 PyObject *args,
146 PyObject *kwds)
147 {
148 uint32_t dom;
149 int vcpu = 0, i;
150 uint64_t cpumap = ~0ULL;
151 PyObject *cpulist = NULL;
153 static char *kwd_list[] = { "domid", "vcpu", "cpumap", NULL };
155 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|iO", kwd_list,
156 &dom, &vcpu, &cpulist) )
157 return NULL;
159 if ( (cpulist != NULL) && PyList_Check(cpulist) )
160 {
161 cpumap = 0ULL;
162 for ( i = 0; i < PyList_Size(cpulist); i++ )
163 cpumap |= (uint64_t)1 << PyInt_AsLong(PyList_GetItem(cpulist, i));
164 }
166 if ( xc_vcpu_setaffinity(self->xc_handle, dom, vcpu, cpumap) != 0 )
167 return PyErr_SetFromErrno(xc_error);
169 Py_INCREF(zero);
170 return zero;
171 }
173 static PyObject *pyxc_domain_setcpuweight(XcObject *self,
174 PyObject *args,
175 PyObject *kwds)
176 {
177 uint32_t dom;
178 float cpuweight = 1;
180 static char *kwd_list[] = { "domid", "cpuweight", NULL };
182 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|f", kwd_list,
183 &dom, &cpuweight) )
184 return NULL;
186 if ( xc_domain_setcpuweight(self->xc_handle, dom, cpuweight) != 0 )
187 return PyErr_SetFromErrno(xc_error);
189 Py_INCREF(zero);
190 return zero;
191 }
193 static PyObject *pyxc_domain_sethandle(XcObject *self, PyObject *args)
194 {
195 int i;
196 uint32_t dom;
197 PyObject *pyhandle;
198 xen_domain_handle_t handle;
200 if (!PyArg_ParseTuple(args, "iO", &dom, &pyhandle))
201 return NULL;
203 if ( !PyList_Check(pyhandle) ||
204 (PyList_Size(pyhandle) != sizeof(xen_domain_handle_t)) )
205 {
206 goto out_exception;
207 }
209 for ( i = 0; i < sizeof(xen_domain_handle_t); i++ )
210 {
211 PyObject *p = PyList_GetItem(pyhandle, i);
212 if ( !PyInt_Check(p) )
213 goto out_exception;
214 handle[i] = (uint8_t)PyInt_AsLong(p);
215 }
217 if (xc_domain_sethandle(self->xc_handle, dom, handle) < 0)
218 return PyErr_SetFromErrno(xc_error);
220 Py_INCREF(zero);
221 return zero;
223 out_exception:
224 errno = EINVAL;
225 PyErr_SetFromErrno(xc_error);
226 return NULL;
227 }
230 static PyObject *pyxc_domain_getinfo(XcObject *self,
231 PyObject *args,
232 PyObject *kwds)
233 {
234 PyObject *list, *info_dict;
236 uint32_t first_dom = 0;
237 int max_doms = 1024, nr_doms, i, j;
238 xc_dominfo_t *info;
240 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
242 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
243 &first_dom, &max_doms) )
244 return NULL;
246 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
247 return PyErr_NoMemory();
249 nr_doms = xc_domain_getinfo(self->xc_handle, first_dom, max_doms, info);
251 if (nr_doms < 0)
252 {
253 free(info);
254 return PyErr_SetFromErrno(xc_error);
255 }
257 list = PyList_New(nr_doms);
258 for ( i = 0 ; i < nr_doms; i++ )
259 {
260 PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t));
261 for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
262 PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j]));
263 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
264 ",s:l,s:L,s:l,s:i,s:i}",
265 "domid", info[i].domid,
266 "online_vcpus", info[i].nr_online_vcpus,
267 "max_vcpu_id", info[i].max_vcpu_id,
268 "hvm", info[i].hvm,
269 "dying", info[i].dying,
270 "crashed", info[i].crashed,
271 "shutdown", info[i].shutdown,
272 "paused", info[i].paused,
273 "blocked", info[i].blocked,
274 "running", info[i].running,
275 "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
276 "cpu_time", info[i].cpu_time,
277 "maxmem_kb", info[i].max_memkb,
278 "ssidref", info[i].ssidref,
279 "shutdown_reason", info[i].shutdown_reason);
280 PyDict_SetItemString(info_dict, "handle", pyhandle);
281 Py_DECREF(pyhandle);
282 PyList_SetItem(list, i, info_dict);
283 }
285 free(info);
287 return list;
288 }
290 static PyObject *pyxc_vcpu_getinfo(XcObject *self,
291 PyObject *args,
292 PyObject *kwds)
293 {
294 PyObject *info_dict, *cpulist;
296 uint32_t dom, vcpu = 0;
297 xc_vcpuinfo_t info;
298 int rc, i;
299 uint64_t cpumap;
301 static char *kwd_list[] = { "domid", "vcpu", NULL };
303 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
304 &dom, &vcpu) )
305 return NULL;
307 rc = xc_vcpu_getinfo(self->xc_handle, dom, vcpu, &info);
308 if ( rc < 0 )
309 return PyErr_SetFromErrno(xc_error);
310 rc = xc_vcpu_getaffinity(self->xc_handle, dom, vcpu, &cpumap);
311 if ( rc < 0 )
312 return PyErr_SetFromErrno(xc_error);
314 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:L,s:i}",
315 "online", info.online,
316 "blocked", info.blocked,
317 "running", info.running,
318 "cpu_time", info.cpu_time,
319 "cpu", info.cpu);
321 cpulist = PyList_New(0);
322 for ( i = 0; cpumap != 0; i++ )
323 {
324 if ( cpumap & 1 )
325 PyList_Append(cpulist, PyInt_FromLong(i));
326 cpumap >>= 1;
327 }
328 PyDict_SetItemString(info_dict, "cpumap", cpulist);
329 Py_DECREF(cpulist);
330 return info_dict;
331 }
333 static PyObject *pyxc_linux_build(XcObject *self,
334 PyObject *args,
335 PyObject *kwds)
336 {
337 uint32_t dom;
338 char *image, *ramdisk = NULL, *cmdline = "", *features = NULL;
339 int flags = 0;
340 int store_evtchn, console_evtchn;
341 unsigned int mem_mb;
342 unsigned long store_mfn = 0;
343 unsigned long console_mfn = 0;
345 static char *kwd_list[] = { "domid", "store_evtchn", "memsize",
346 "console_evtchn", "image",
347 /* optional */
348 "ramdisk", "cmdline", "flags",
349 "features", NULL };
351 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiis|ssis", kwd_list,
352 &dom, &store_evtchn, &mem_mb,
353 &console_evtchn, &image,
354 /* optional */
355 &ramdisk, &cmdline, &flags,
356 &features) )
357 return NULL;
359 if ( xc_linux_build(self->xc_handle, dom, mem_mb, image,
360 ramdisk, cmdline, features, flags,
361 store_evtchn, &store_mfn,
362 console_evtchn, &console_mfn) != 0 ) {
363 if (!errno)
364 errno = EINVAL;
365 return PyErr_SetFromErrno(xc_error);
366 }
367 return Py_BuildValue("{s:i,s:i}",
368 "store_mfn", store_mfn,
369 "console_mfn", console_mfn);
370 }
372 static PyObject *pyxc_hvm_build(XcObject *self,
373 PyObject *args,
374 PyObject *kwds)
375 {
376 uint32_t dom;
377 struct hvm_info_table *va_hvm;
378 uint8_t *va_map, sum;
379 char *image;
380 int i, store_evtchn, memsize, vcpus = 1, pae = 0, acpi = 0, apic = 1;
381 unsigned long store_mfn;
383 static char *kwd_list[] = { "domid", "store_evtchn",
384 "memsize", "image", "vcpus", "pae", "acpi",
385 "apic", NULL };
386 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|iiii", kwd_list,
387 &dom, &store_evtchn, &memsize,
388 &image, &vcpus, &pae, &acpi, &apic) )
389 return NULL;
391 if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
392 return PyErr_SetFromErrno(xc_error);
394 /* Set up the HVM info table. */
395 va_map = xc_map_foreign_range(self->xc_handle, dom, XC_PAGE_SIZE,
396 PROT_READ | PROT_WRITE,
397 HVM_INFO_PFN);
398 if ( va_map == NULL )
399 return PyErr_SetFromErrno(xc_error);
400 va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
401 memset(va_hvm, 0, sizeof(*va_hvm));
402 strncpy(va_hvm->signature, "HVM INFO", 8);
403 va_hvm->length = sizeof(struct hvm_info_table);
404 va_hvm->acpi_enabled = acpi;
405 va_hvm->apic_mode = apic;
406 va_hvm->nr_vcpus = vcpus;
407 for ( i = 0, sum = 0; i < va_hvm->length; i++ )
408 sum += ((uint8_t *)va_hvm)[i];
409 va_hvm->checksum = -sum;
410 munmap(va_map, XC_PAGE_SIZE);
412 xc_get_hvm_param(self->xc_handle, dom, HVM_PARAM_STORE_PFN, &store_mfn);
413 xc_set_hvm_param(self->xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
414 xc_set_hvm_param(self->xc_handle, dom, HVM_PARAM_STORE_EVTCHN,
415 store_evtchn);
417 return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
418 }
420 static PyObject *pyxc_evtchn_alloc_unbound(XcObject *self,
421 PyObject *args,
422 PyObject *kwds)
423 {
424 uint32_t dom, remote_dom;
425 int port;
427 static char *kwd_list[] = { "domid", "remote_dom", NULL };
429 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
430 &dom, &remote_dom) )
431 return NULL;
433 if ( (port = xc_evtchn_alloc_unbound(self->xc_handle, dom, remote_dom)) < 0 )
434 return PyErr_SetFromErrno(xc_error);
436 return PyInt_FromLong(port);
437 }
439 static PyObject *pyxc_physdev_pci_access_modify(XcObject *self,
440 PyObject *args,
441 PyObject *kwds)
442 {
443 uint32_t dom;
444 int bus, dev, func, enable, ret;
446 static char *kwd_list[] = { "domid", "bus", "dev", "func", "enable", NULL };
448 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
449 &dom, &bus, &dev, &func, &enable) )
450 return NULL;
452 ret = xc_physdev_pci_access_modify(
453 self->xc_handle, dom, bus, dev, func, enable);
454 if ( ret != 0 )
455 return PyErr_SetFromErrno(xc_error);
457 Py_INCREF(zero);
458 return zero;
459 }
461 static PyObject *pyxc_readconsolering(XcObject *self,
462 PyObject *args,
463 PyObject *kwds)
464 {
465 unsigned int clear = 0;
466 char _str[32768], *str = _str;
467 unsigned int count = 32768;
468 int ret;
470 static char *kwd_list[] = { "clear", NULL };
472 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
473 return NULL;
475 ret = xc_readconsolering(self->xc_handle, &str, &count, clear);
476 if ( ret < 0 )
477 return PyErr_SetFromErrno(xc_error);
479 return PyString_FromStringAndSize(str, count);
480 }
483 static unsigned long pages_to_kib(unsigned long pages)
484 {
485 return pages * (XC_PAGE_SIZE / 1024);
486 }
489 static PyObject *pyxc_pages_to_kib(XcObject *self, PyObject *args)
490 {
491 unsigned long pages;
493 if (!PyArg_ParseTuple(args, "l", &pages))
494 return NULL;
496 return PyLong_FromUnsignedLong(pages_to_kib(pages));
497 }
500 static PyObject *pyxc_physinfo(XcObject *self)
501 {
502 xc_physinfo_t info;
503 char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
504 int i;
506 if ( xc_physinfo(self->xc_handle, &info) != 0 )
507 return PyErr_SetFromErrno(xc_error);
509 *q=0;
510 for(i=0;i<sizeof(info.hw_cap)/4;i++)
511 {
512 p+=sprintf(p,"%08x:",info.hw_cap[i]);
513 if(info.hw_cap[i])
514 q=p;
515 }
516 if(q>cpu_cap)
517 *(q-1)=0;
519 return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
520 "threads_per_core", info.threads_per_core,
521 "cores_per_socket", info.cores_per_socket,
522 "sockets_per_node", info.sockets_per_node,
523 "nr_nodes", info.nr_nodes,
524 "total_memory", pages_to_kib(info.total_pages),
525 "free_memory", pages_to_kib(info.free_pages),
526 "scrub_memory", pages_to_kib(info.scrub_pages),
527 "cpu_khz", info.cpu_khz,
528 "hw_caps", cpu_cap);
529 }
531 static PyObject *pyxc_xeninfo(XcObject *self)
532 {
533 xen_extraversion_t xen_extra;
534 xen_compile_info_t xen_cc;
535 xen_changeset_info_t xen_chgset;
536 xen_capabilities_info_t xen_caps;
537 xen_platform_parameters_t p_parms;
538 long xen_version;
539 long xen_pagesize;
540 char str[128];
542 xen_version = xc_version(self->xc_handle, XENVER_version, NULL);
544 if ( xc_version(self->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
545 return PyErr_SetFromErrno(xc_error);
547 if ( xc_version(self->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
548 return PyErr_SetFromErrno(xc_error);
550 if ( xc_version(self->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
551 return PyErr_SetFromErrno(xc_error);
553 if ( xc_version(self->xc_handle, XENVER_capabilities, &xen_caps) != 0 )
554 return PyErr_SetFromErrno(xc_error);
556 if ( xc_version(self->xc_handle, XENVER_platform_parameters, &p_parms) != 0 )
557 return PyErr_SetFromErrno(xc_error);
559 sprintf(str, "virt_start=0x%lx", p_parms.virt_start);
561 xen_pagesize = xc_version(self->xc_handle, XENVER_pagesize, NULL);
562 if (xen_pagesize < 0 )
563 return PyErr_SetFromErrno(xc_error);
565 return Py_BuildValue("{s:i,s:i,s:s,s:s,s:i,s:s,s:s,s:s,s:s,s:s,s:s}",
566 "xen_major", xen_version >> 16,
567 "xen_minor", (xen_version & 0xffff),
568 "xen_extra", xen_extra,
569 "xen_caps", xen_caps,
570 "xen_pagesize", xen_pagesize,
571 "platform_params", str,
572 "xen_changeset", xen_chgset,
573 "cc_compiler", xen_cc.compiler,
574 "cc_compile_by", xen_cc.compile_by,
575 "cc_compile_domain", xen_cc.compile_domain,
576 "cc_compile_date", xen_cc.compile_date);
577 }
580 static PyObject *pyxc_sedf_domain_set(XcObject *self,
581 PyObject *args,
582 PyObject *kwds)
583 {
584 uint32_t domid;
585 uint64_t period, slice, latency;
586 uint16_t extratime, weight;
587 static char *kwd_list[] = { "domid", "period", "slice",
588 "latency", "extratime", "weight",NULL };
590 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list,
591 &domid, &period, &slice,
592 &latency, &extratime, &weight) )
593 return NULL;
594 if ( xc_sedf_domain_set(self->xc_handle, domid, period,
595 slice, latency, extratime,weight) != 0 )
596 return PyErr_SetFromErrno(xc_error);
598 Py_INCREF(zero);
599 return zero;
600 }
602 static PyObject *pyxc_sedf_domain_get(XcObject *self, PyObject *args)
603 {
604 uint32_t domid;
605 uint64_t period, slice,latency;
606 uint16_t weight, extratime;
608 if(!PyArg_ParseTuple(args, "i", &domid))
609 return NULL;
611 if (xc_sedf_domain_get(self->xc_handle, domid, &period,
612 &slice,&latency,&extratime,&weight))
613 return PyErr_SetFromErrno(xc_error);
615 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i,s:i}",
616 "domid", domid,
617 "period", period,
618 "slice", slice,
619 "latency", latency,
620 "extratime", extratime,
621 "weight", weight);
622 }
624 static PyObject *pyxc_shadow_control(PyObject *self,
625 PyObject *args,
626 PyObject *kwds)
627 {
628 XcObject *xc = (XcObject *)self;
630 uint32_t dom;
631 int op=0;
633 static char *kwd_list[] = { "dom", "op", NULL };
635 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
636 &dom, &op) )
637 return NULL;
639 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL, 0, NULL)
640 < 0 )
641 return PyErr_SetFromErrno(xc_error);
643 Py_INCREF(zero);
644 return zero;
645 }
647 static PyObject *pyxc_shadow_mem_control(PyObject *self,
648 PyObject *args,
649 PyObject *kwds)
650 {
651 XcObject *xc = (XcObject *)self;
652 int op;
653 uint32_t dom;
654 int mbarg = -1;
655 unsigned long mb;
657 static char *kwd_list[] = { "dom", "mb", NULL };
659 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
660 &dom, &mbarg) )
661 return NULL;
663 if ( mbarg < 0 )
664 op = XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION;
665 else
666 {
667 mb = mbarg;
668 op = XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION;
669 }
670 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, &mb, 0, NULL) < 0 )
671 return PyErr_SetFromErrno(xc_error);
673 mbarg = mb;
674 return Py_BuildValue("i", mbarg);
675 }
677 static PyObject *pyxc_sched_id_get(XcObject *self) {
679 int sched_id;
680 if (xc_sched_id(self->xc_handle, &sched_id) != 0)
681 return PyErr_SetFromErrno(xc_error);
683 return Py_BuildValue("i", sched_id);
684 }
686 static PyObject *pyxc_sched_credit_domain_set(XcObject *self,
687 PyObject *args,
688 PyObject *kwds)
689 {
690 uint32_t domid;
691 uint16_t weight;
692 uint16_t cap;
693 static char *kwd_list[] = { "domid", "weight", "cap", NULL };
694 static char kwd_type[] = "I|HH";
695 struct xen_domctl_sched_credit sdom;
697 weight = 0;
698 cap = (uint16_t)~0U;
699 if( !PyArg_ParseTupleAndKeywords(args, kwds, kwd_type, kwd_list,
700 &domid, &weight, &cap) )
701 return NULL;
703 sdom.weight = weight;
704 sdom.cap = cap;
706 if ( xc_sched_credit_domain_set(self->xc_handle, domid, &sdom) != 0 )
707 return PyErr_SetFromErrno(xc_error);
709 Py_INCREF(zero);
710 return zero;
711 }
713 static PyObject *pyxc_sched_credit_domain_get(XcObject *self, PyObject *args)
714 {
715 uint32_t domid;
716 struct xen_domctl_sched_credit sdom;
718 if( !PyArg_ParseTuple(args, "I", &domid) )
719 return NULL;
721 if ( xc_sched_credit_domain_get(self->xc_handle, domid, &sdom) != 0 )
722 return PyErr_SetFromErrno(xc_error);
724 return Py_BuildValue("{s:H,s:H}",
725 "weight", sdom.weight,
726 "cap", sdom.cap);
727 }
729 static PyObject *pyxc_domain_setmaxmem(XcObject *self, PyObject *args)
730 {
731 uint32_t dom;
732 unsigned int maxmem_kb;
734 if (!PyArg_ParseTuple(args, "ii", &dom, &maxmem_kb))
735 return NULL;
737 if (xc_domain_setmaxmem(self->xc_handle, dom, maxmem_kb) != 0)
738 return PyErr_SetFromErrno(xc_error);
740 Py_INCREF(zero);
741 return zero;
742 }
744 static PyObject *pyxc_domain_memory_increase_reservation(XcObject *self,
745 PyObject *args,
746 PyObject *kwds)
747 {
748 uint32_t dom;
749 unsigned long mem_kb;
750 unsigned int extent_order = 0 , address_bits = 0;
751 unsigned long nr_extents;
753 static char *kwd_list[] = { "domid", "mem_kb", "extent_order", "address_bits", NULL };
755 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list,
756 &dom, &mem_kb, &extent_order, &address_bits) )
757 return NULL;
759 /* round down to nearest power of 2. Assume callers using extent_order>0
760 know what they are doing */
761 nr_extents = (mem_kb / (XC_PAGE_SIZE/1024)) >> extent_order;
762 if ( xc_domain_memory_increase_reservation(self->xc_handle, dom,
763 nr_extents, extent_order,
764 address_bits, NULL) )
765 return PyErr_SetFromErrno(xc_error);
767 Py_INCREF(zero);
768 return zero;
769 }
771 static PyObject *pyxc_domain_ioport_permission(XcObject *self,
772 PyObject *args,
773 PyObject *kwds)
774 {
775 uint32_t dom;
776 int first_port, nr_ports, allow_access, ret;
778 static char *kwd_list[] = { "domid", "first_port", "nr_ports", "allow_access", NULL };
780 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiii", kwd_list,
781 &dom, &first_port, &nr_ports, &allow_access) )
782 return NULL;
784 ret = xc_domain_ioport_permission(
785 self->xc_handle, dom, first_port, nr_ports, allow_access);
786 if ( ret != 0 )
787 return PyErr_SetFromErrno(xc_error);
789 Py_INCREF(zero);
790 return zero;
791 }
793 static PyObject *pyxc_domain_irq_permission(PyObject *self,
794 PyObject *args,
795 PyObject *kwds)
796 {
797 XcObject *xc = (XcObject *)self;
798 uint32_t dom;
799 int pirq, allow_access, ret;
801 static char *kwd_list[] = { "domid", "pirq", "allow_access", NULL };
803 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list,
804 &dom, &pirq, &allow_access) )
805 return NULL;
807 ret = xc_domain_irq_permission(
808 xc->xc_handle, dom, pirq, allow_access);
809 if ( ret != 0 )
810 return PyErr_SetFromErrno(xc_error);
812 Py_INCREF(zero);
813 return zero;
814 }
816 static PyObject *pyxc_domain_iomem_permission(PyObject *self,
817 PyObject *args,
818 PyObject *kwds)
819 {
820 XcObject *xc = (XcObject *)self;
821 uint32_t dom;
822 unsigned long first_pfn, nr_pfns, allow_access, ret;
824 static char *kwd_list[] = { "domid", "first_pfn", "nr_pfns", "allow_access", NULL };
826 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list,
827 &dom, &first_pfn, &nr_pfns, &allow_access) )
828 return NULL;
830 ret = xc_domain_iomem_permission(
831 xc->xc_handle, dom, first_pfn, nr_pfns, allow_access);
832 if ( ret != 0 )
833 return PyErr_SetFromErrno(xc_error);
835 Py_INCREF(zero);
836 return zero;
837 }
839 static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args)
840 {
841 uint32_t dom;
842 int32_t time_offset_seconds;
843 time_t calendar_time;
844 struct tm local_time;
845 struct tm utc_time;
847 if (!PyArg_ParseTuple(args, "i", &dom))
848 return NULL;
850 calendar_time = time(NULL);
851 localtime_r(&calendar_time, &local_time);
852 gmtime_r(&calendar_time, &utc_time);
853 /* set up to get calendar time based on utc_time, with local dst setting */
854 utc_time.tm_isdst = local_time.tm_isdst;
855 time_offset_seconds = (int32_t)difftime(calendar_time, mktime(&utc_time));
857 if (xc_domain_set_time_offset(self->xc_handle, dom, time_offset_seconds) != 0)
858 return NULL;
860 Py_INCREF(zero);
861 return zero;
862 }
864 static PyObject *dom_op(XcObject *self, PyObject *args,
865 int (*fn)(int, uint32_t))
866 {
867 uint32_t dom;
869 if (!PyArg_ParseTuple(args, "i", &dom))
870 return NULL;
872 if (fn(self->xc_handle, dom) != 0)
873 return PyErr_SetFromErrno(xc_error);
875 Py_INCREF(zero);
876 return zero;
877 }
880 static PyMethodDef pyxc_methods[] = {
881 { "handle",
882 (PyCFunction)pyxc_handle,
883 METH_NOARGS, "\n"
884 "Query the xc control interface file descriptor.\n\n"
885 "Returns: [int] file descriptor\n" },
887 { "domain_create",
888 (PyCFunction)pyxc_domain_create,
889 METH_VARARGS | METH_KEYWORDS, "\n"
890 "Create a new domain.\n"
891 " dom [int, 0]: Domain identifier to use (allocated if zero).\n"
892 "Returns: [int] new domain identifier; -1 on error.\n" },
894 { "domain_max_vcpus",
895 (PyCFunction)pyxc_domain_max_vcpus,
896 METH_VARARGS, "\n"
897 "Set the maximum number of VCPUs a domain may create.\n"
898 " dom [int, 0]: Domain identifier to use.\n"
899 " max [int, 0]: New maximum number of VCPUs in domain.\n"
900 "Returns: [int] 0 on success; -1 on error.\n" },
902 { "domain_dumpcore",
903 (PyCFunction)pyxc_domain_dumpcore,
904 METH_VARARGS, "\n"
905 "Dump core of a domain.\n"
906 " dom [int]: Identifier of domain to dump core of.\n"
907 " corefile [string]: Name of corefile to be created.\n\n"
908 "Returns: [int] 0 on success; -1 on error.\n" },
910 { "domain_pause",
911 (PyCFunction)pyxc_domain_pause,
912 METH_VARARGS, "\n"
913 "Temporarily pause execution of a domain.\n"
914 " dom [int]: Identifier of domain to be paused.\n\n"
915 "Returns: [int] 0 on success; -1 on error.\n" },
917 { "domain_unpause",
918 (PyCFunction)pyxc_domain_unpause,
919 METH_VARARGS, "\n"
920 "(Re)start execution of a domain.\n"
921 " dom [int]: Identifier of domain to be unpaused.\n\n"
922 "Returns: [int] 0 on success; -1 on error.\n" },
924 { "domain_destroy",
925 (PyCFunction)pyxc_domain_destroy,
926 METH_VARARGS, "\n"
927 "Destroy a domain.\n"
928 " dom [int]: Identifier of domain to be destroyed.\n\n"
929 "Returns: [int] 0 on success; -1 on error.\n" },
931 { "vcpu_setaffinity",
932 (PyCFunction)pyxc_vcpu_setaffinity,
933 METH_VARARGS | METH_KEYWORDS, "\n"
934 "Pin a VCPU to a specified set CPUs.\n"
935 " dom [int]: Identifier of domain to which VCPU belongs.\n"
936 " vcpu [int, 0]: VCPU being pinned.\n"
937 " cpumap [list, []]: list of usable CPUs.\n\n"
938 "Returns: [int] 0 on success; -1 on error.\n" },
940 { "domain_setcpuweight",
941 (PyCFunction)pyxc_domain_setcpuweight,
942 METH_VARARGS | METH_KEYWORDS, "\n"
943 "Set cpuweight scheduler parameter for domain.\n"
944 " dom [int]: Identifier of domain to be changed.\n"
945 " cpuweight [float, 1]: VCPU being pinned.\n"
946 "Returns: [int] 0 on success; -1 on error.\n" },
948 { "domain_sethandle",
949 (PyCFunction)pyxc_domain_sethandle,
950 METH_VARARGS, "\n"
951 "Set domain's opaque handle.\n"
952 " dom [int]: Identifier of domain.\n"
953 " handle [list of 16 ints]: New opaque handle.\n"
954 "Returns: [int] 0 on success; -1 on error.\n" },
956 { "domain_getinfo",
957 (PyCFunction)pyxc_domain_getinfo,
958 METH_VARARGS | METH_KEYWORDS, "\n"
959 "Get information regarding a set of domains, in increasing id order.\n"
960 " first_dom [int, 0]: First domain to retrieve info about.\n"
961 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
962 " about.\n\n"
963 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
964 " parameter then there was an error, or the end of the\n"
965 " domain-id space was reached.\n"
966 " dom [int]: Identifier of domain to which this info pertains\n"
967 " cpu [int]: CPU to which this domain is bound\n"
968 " vcpus [int]: Number of Virtual CPUS in this domain\n"
969 " dying [int]: Bool - is the domain dying?\n"
970 " crashed [int]: Bool - has the domain crashed?\n"
971 " shutdown [int]: Bool - has the domain shut itself down?\n"
972 " paused [int]: Bool - is the domain paused by control software?\n"
973 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
974 " running [int]: Bool - is the domain currently running?\n"
975 " mem_kb [int]: Memory reservation, in kilobytes\n"
976 " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
977 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
978 " shutdown_reason [int]: Numeric code from guest OS, explaining "
979 "reason why it shut itself down.\n" },
981 { "vcpu_getinfo",
982 (PyCFunction)pyxc_vcpu_getinfo,
983 METH_VARARGS | METH_KEYWORDS, "\n"
984 "Get information regarding a VCPU.\n"
985 " dom [int]: Domain to retrieve info about.\n"
986 " vcpu [int, 0]: VCPU to retrieve info about.\n\n"
987 "Returns: [dict]\n"
988 " online [int]: Bool - Is this VCPU currently online?\n"
989 " blocked [int]: Bool - Is this VCPU blocked waiting for an event?\n"
990 " running [int]: Bool - Is this VCPU currently running on a CPU?\n"
991 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
992 " cpumap [int]: Bitmap of CPUs this VCPU can run on\n"
993 " cpu [int]: CPU that this VCPU is currently bound to\n" },
995 { "linux_build",
996 (PyCFunction)pyxc_linux_build,
997 METH_VARARGS | METH_KEYWORDS, "\n"
998 "Build a new Linux guest OS.\n"
999 " dom [int]: Identifier of domain to build into.\n"
1000 " image [str]: Name of kernel image file. May be gzipped.\n"
1001 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
1002 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1003 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
1004 "Returns: [int] 0 on success; -1 on error.\n" },
1006 { "hvm_build",
1007 (PyCFunction)pyxc_hvm_build,
1008 METH_VARARGS | METH_KEYWORDS, "\n"
1009 "Build a new HVM guest OS.\n"
1010 " dom [int]: Identifier of domain to build into.\n"
1011 " image [str]: Name of HVM loader image file.\n"
1012 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
1013 "Returns: [int] 0 on success; -1 on error.\n" },
1015 { "sched_id_get",
1016 (PyCFunction)pyxc_sched_id_get,
1017 METH_NOARGS, "\n"
1018 "Get the current scheduler type in use.\n"
1019 "Returns: [int] sched_id.\n" },
1021 { "sedf_domain_set",
1022 (PyCFunction)pyxc_sedf_domain_set,
1023 METH_KEYWORDS, "\n"
1024 "Set the scheduling parameters for a domain when running with Atropos.\n"
1025 " dom [int]: domain to set\n"
1026 " period [long]: domain's scheduling period\n"
1027 " slice [long]: domain's slice per period\n"
1028 " latency [long]: domain's wakeup latency hint\n"
1029 " extratime [int]: domain aware of extratime?\n"
1030 "Returns: [int] 0 on success; -1 on error.\n" },
1032 { "sedf_domain_get",
1033 (PyCFunction)pyxc_sedf_domain_get,
1034 METH_VARARGS, "\n"
1035 "Get the current scheduling parameters for a domain when running with\n"
1036 "the Atropos scheduler."
1037 " dom [int]: domain to query\n"
1038 "Returns: [dict]\n"
1039 " domain [int]: domain ID\n"
1040 " period [long]: scheduler period\n"
1041 " slice [long]: CPU reservation per period\n"
1042 " latency [long]: domain's wakeup latency hint\n"
1043 " extratime [int]: domain aware of extratime?\n"},
1045 { "sched_credit_domain_set",
1046 (PyCFunction)pyxc_sched_credit_domain_set,
1047 METH_KEYWORDS, "\n"
1048 "Set the scheduling parameters for a domain when running with the\n"
1049 "SMP credit scheduler.\n"
1050 " domid [int]: domain id to set\n"
1051 " weight [short]: domain's scheduling weight\n"
1052 "Returns: [int] 0 on success; -1 on error.\n" },
1054 { "sched_credit_domain_get",
1055 (PyCFunction)pyxc_sched_credit_domain_get,
1056 METH_VARARGS, "\n"
1057 "Get the scheduling parameters for a domain when running with the\n"
1058 "SMP credit scheduler.\n"
1059 " domid [int]: domain id to get\n"
1060 "Returns: [dict]\n"
1061 " weight [short]: domain's scheduling weight\n"},
1063 { "evtchn_alloc_unbound",
1064 (PyCFunction)pyxc_evtchn_alloc_unbound,
1065 METH_VARARGS | METH_KEYWORDS, "\n"
1066 "Allocate an unbound port that will await a remote connection.\n"
1067 " dom [int]: Domain whose port space to allocate from.\n"
1068 " remote_dom [int]: Remote domain to accept connections from.\n\n"
1069 "Returns: [int] Unbound event-channel port.\n" },
1071 { "physdev_pci_access_modify",
1072 (PyCFunction)pyxc_physdev_pci_access_modify,
1073 METH_VARARGS | METH_KEYWORDS, "\n"
1074 "Allow a domain access to a PCI device\n"
1075 " dom [int]: Identifier of domain to be allowed access.\n"
1076 " bus [int]: PCI bus\n"
1077 " dev [int]: PCI slot\n"
1078 " func [int]: PCI function\n"
1079 " enable [int]: Non-zero means enable access; else disable access\n\n"
1080 "Returns: [int] 0 on success; -1 on error.\n" },
1082 { "readconsolering",
1083 (PyCFunction)pyxc_readconsolering,
1084 METH_VARARGS | METH_KEYWORDS, "\n"
1085 "Read Xen's console ring.\n"
1086 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1087 "Returns: [str] string is empty on failure.\n" },
1089 { "physinfo",
1090 (PyCFunction)pyxc_physinfo,
1091 METH_NOARGS, "\n"
1092 "Get information about the physical host machine\n"
1093 "Returns [dict]: information about the hardware"
1094 " [None]: on failure.\n" },
1096 { "xeninfo",
1097 (PyCFunction)pyxc_xeninfo,
1098 METH_NOARGS, "\n"
1099 "Get information about the Xen host\n"
1100 "Returns [dict]: information about Xen"
1101 " [None]: on failure.\n" },
1103 { "shadow_control",
1104 (PyCFunction)pyxc_shadow_control,
1105 METH_VARARGS | METH_KEYWORDS, "\n"
1106 "Set parameter for shadow pagetable interface\n"
1107 " dom [int]: Identifier of domain.\n"
1108 " op [int, 0]: operation\n\n"
1109 "Returns: [int] 0 on success; -1 on error.\n" },
1111 { "shadow_mem_control",
1112 (PyCFunction)pyxc_shadow_mem_control,
1113 METH_VARARGS | METH_KEYWORDS, "\n"
1114 "Set or read shadow pagetable memory use\n"
1115 " dom [int]: Identifier of domain.\n"
1116 " mb [int, -1]: MB of shadow memory this domain should have.\n\n"
1117 "Returns: [int] MB of shadow memory in use by this domain.\n" },
1119 { "domain_setmaxmem",
1120 (PyCFunction)pyxc_domain_setmaxmem,
1121 METH_VARARGS, "\n"
1122 "Set a domain's memory limit\n"
1123 " dom [int]: Identifier of domain.\n"
1124 " maxmem_kb [int]: .\n"
1125 "Returns: [int] 0 on success; -1 on error.\n" },
1127 { "domain_memory_increase_reservation",
1128 (PyCFunction)pyxc_domain_memory_increase_reservation,
1129 METH_VARARGS | METH_KEYWORDS, "\n"
1130 "Increase a domain's memory reservation\n"
1131 " dom [int]: Identifier of domain.\n"
1132 " mem_kb [long]: .\n"
1133 "Returns: [int] 0 on success; -1 on error.\n" },
1135 { "domain_ioport_permission",
1136 (PyCFunction)pyxc_domain_ioport_permission,
1137 METH_VARARGS | METH_KEYWORDS, "\n"
1138 "Allow a domain access to a range of IO ports\n"
1139 " dom [int]: Identifier of domain to be allowed access.\n"
1140 " first_port [int]: First IO port\n"
1141 " nr_ports [int]: Number of IO ports\n"
1142 " allow_access [int]: Non-zero means enable access; else disable access\n\n"
1143 "Returns: [int] 0 on success; -1 on error.\n" },
1145 { "domain_irq_permission",
1146 (PyCFunction)pyxc_domain_irq_permission,
1147 METH_VARARGS | METH_KEYWORDS, "\n"
1148 "Allow a domain access to a physical IRQ\n"
1149 " dom [int]: Identifier of domain to be allowed access.\n"
1150 " pirq [int]: The Physical IRQ\n"
1151 " allow_access [int]: Non-zero means enable access; else disable access\n\n"
1152 "Returns: [int] 0 on success; -1 on error.\n" },
1154 { "domain_iomem_permission",
1155 (PyCFunction)pyxc_domain_iomem_permission,
1156 METH_VARARGS | METH_KEYWORDS, "\n"
1157 "Allow a domain access to a range of IO memory pages\n"
1158 " dom [int]: Identifier of domain to be allowed access.\n"
1159 " first_pfn [long]: First page of I/O Memory\n"
1160 " nr_pfns [long]: Number of pages of I/O Memory (>0)\n"
1161 " allow_access [int]: Non-zero means enable access; else disable access\n\n"
1162 "Returns: [int] 0 on success; -1 on error.\n" },
1164 { "pages_to_kib",
1165 (PyCFunction)pyxc_pages_to_kib,
1166 METH_VARARGS, "\n"
1167 "Returns: [int]: The size in KiB of memory spanning the given number "
1168 "of pages.\n" },
1170 { "domain_set_time_offset",
1171 (PyCFunction)pyxc_domain_set_time_offset,
1172 METH_VARARGS, "\n"
1173 "Set a domain's time offset to Dom0's localtime\n"
1174 " dom [int]: Domain whose time offset is being set.\n"
1175 "Returns: [int] 0 on success; -1 on error.\n" },
1177 { NULL, NULL, 0, NULL }
1178 };
1181 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1183 return Py_FindMethod(pyxc_methods, obj, name);
1186 static PyObject *PyXc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1188 XcObject *self = (XcObject *)type->tp_alloc(type, 0);
1190 if (self == NULL)
1191 return NULL;
1193 self->xc_handle = -1;
1195 return (PyObject *)self;
1198 static int
1199 PyXc_init(XcObject *self, PyObject *args, PyObject *kwds)
1201 if ((self->xc_handle = xc_interface_open()) == -1) {
1202 PyErr_SetFromErrno(xc_error);
1203 return -1;
1206 return 0;
1209 static void PyXc_dealloc(XcObject *self)
1211 if (self->xc_handle != -1) {
1212 xc_interface_close(self->xc_handle);
1213 self->xc_handle = -1;
1216 self->ob_type->tp_free((PyObject *)self);
1219 static PyTypeObject PyXcType = {
1220 PyObject_HEAD_INIT(NULL)
1221 0,
1222 PKG "." CLS,
1223 sizeof(XcObject),
1224 0,
1225 (destructor)PyXc_dealloc, /* tp_dealloc */
1226 NULL, /* tp_print */
1227 PyXc_getattr, /* tp_getattr */
1228 NULL, /* tp_setattr */
1229 NULL, /* tp_compare */
1230 NULL, /* tp_repr */
1231 NULL, /* tp_as_number */
1232 NULL, /* tp_as_sequence */
1233 NULL, /* tp_as_mapping */
1234 NULL, /* tp_hash */
1235 NULL, /* tp_call */
1236 NULL, /* tp_str */
1237 NULL, /* tp_getattro */
1238 NULL, /* tp_setattro */
1239 NULL, /* tp_as_buffer */
1240 Py_TPFLAGS_DEFAULT, /* tp_flags */
1241 "Xen client connections", /* tp_doc */
1242 NULL, /* tp_traverse */
1243 NULL, /* tp_clear */
1244 NULL, /* tp_richcompare */
1245 0, /* tp_weaklistoffset */
1246 NULL, /* tp_iter */
1247 NULL, /* tp_iternext */
1248 pyxc_methods, /* tp_methods */
1249 NULL, /* tp_members */
1250 NULL, /* tp_getset */
1251 NULL, /* tp_base */
1252 NULL, /* tp_dict */
1253 NULL, /* tp_descr_get */
1254 NULL, /* tp_descr_set */
1255 0, /* tp_dictoffset */
1256 (initproc)PyXc_init, /* tp_init */
1257 NULL, /* tp_alloc */
1258 PyXc_new, /* tp_new */
1259 };
1261 static PyMethodDef xc_methods[] = { { NULL } };
1263 PyMODINIT_FUNC initxc(void)
1265 PyObject *m;
1267 if (PyType_Ready(&PyXcType) < 0)
1268 return;
1270 m = Py_InitModule(PKG, xc_methods);
1272 if (m == NULL)
1273 return;
1275 xc_error = PyErr_NewException(PKG ".Error", PyExc_RuntimeError, NULL);
1276 zero = PyInt_FromLong(0);
1278 /* KAF: This ensures that we get debug output in a timely manner. */
1279 setbuf(stdout, NULL);
1280 setbuf(stderr, NULL);
1282 Py_INCREF(&PyXcType);
1283 PyModule_AddObject(m, CLS, (PyObject *)&PyXcType);
1285 Py_INCREF(xc_error);
1286 PyModule_AddObject(m, "Error", xc_error);
1288 /* Expose some libxc constants to Python */
1289 PyModule_AddIntConstant(m, "XEN_SCHEDULER_SEDF", XEN_SCHEDULER_SEDF);
1290 PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT);
1295 /*
1296 * Local variables:
1297 * c-indent-level: 4
1298 * c-basic-offset: 4
1299 * End:
1300 */