debuggers.hg

view tools/python/xen/lowlevel/xc/xc.c @ 3611:3dc193a9786a

bitkeeper revision 1.1159.170.102 (41fa2751heRkQ76AYa9Oe-6cOyJuLw)

Enhanced SEDF scheduler
author sd386@font.cl.cam.ac.uk
date Fri Jan 28 11:51:45 2005 +0000 (2005-01-28)
parents f8e1f285e41f
children 9c88ba91d330
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 <xc.h>
9 #include <zlib.h>
10 #include <fcntl.h>
11 #include <netinet/in.h>
12 #include <netinet/tcp.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netdb.h>
16 #include <arpa/inet.h>
17 #include "xc_private.h"
18 #include "gzip_stream.h"
20 /* Needed for Python versions earlier than 2.3. */
21 #ifndef PyMODINIT_FUNC
22 #define PyMODINIT_FUNC DL_EXPORT(void)
23 #endif
25 #define XENPKG "xen.lowlevel.xc"
27 static PyObject *xc_error, *zero;
29 typedef struct {
30 PyObject_HEAD;
31 int xc_handle;
32 } XcObject;
34 /*
35 * Definitions for the 'xc' object type.
36 */
38 static PyObject *pyxc_domain_create(PyObject *self,
39 PyObject *args,
40 PyObject *kwds)
41 {
42 XcObject *xc = (XcObject *)self;
44 unsigned int mem_kb = 0;
45 int cpu = -1;
46 float cpu_weight = 1;
47 u32 dom = 0;
48 int ret;
50 static char *kwd_list[] = { "dom", "mem_kb", "cpu", "cpu_weight", NULL };
52 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiif", kwd_list,
53 &dom, &mem_kb, &cpu, &cpu_weight))
54 return NULL;
56 if ( (ret = xc_domain_create(
57 xc->xc_handle, mem_kb, cpu, cpu_weight, &dom)) < 0 )
58 return PyErr_SetFromErrno(xc_error);
60 return PyInt_FromLong(dom);
61 }
63 static PyObject *pyxc_domain_pause(PyObject *self,
64 PyObject *args,
65 PyObject *kwds)
66 {
67 XcObject *xc = (XcObject *)self;
69 u32 dom;
71 static char *kwd_list[] = { "dom", NULL };
73 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
74 return NULL;
76 if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
77 return PyErr_SetFromErrno(xc_error);
79 Py_INCREF(zero);
80 return zero;
81 }
83 static PyObject *pyxc_domain_unpause(PyObject *self,
84 PyObject *args,
85 PyObject *kwds)
86 {
87 XcObject *xc = (XcObject *)self;
89 u32 dom;
91 static char *kwd_list[] = { "dom", NULL };
93 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
94 return NULL;
96 if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
97 return PyErr_SetFromErrno(xc_error);
99 Py_INCREF(zero);
100 return zero;
101 }
103 static PyObject *pyxc_domain_destroy(PyObject *self,
104 PyObject *args,
105 PyObject *kwds)
106 {
107 XcObject *xc = (XcObject *)self;
109 u32 dom;
111 static char *kwd_list[] = { "dom", NULL };
113 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
114 return NULL;
116 if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
117 return PyErr_SetFromErrno(xc_error);
119 Py_INCREF(zero);
120 return zero;
121 }
123 static PyObject *pyxc_domain_pincpu(PyObject *self,
124 PyObject *args,
125 PyObject *kwds)
126 {
127 XcObject *xc = (XcObject *)self;
129 u32 dom;
130 int cpu = -1;
132 static char *kwd_list[] = { "dom", "cpu", NULL };
134 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
135 &dom, &cpu) )
136 return NULL;
138 if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
139 return PyErr_SetFromErrno(xc_error);
141 Py_INCREF(zero);
142 return zero;
143 }
145 static PyObject *pyxc_domain_getinfo(PyObject *self,
146 PyObject *args,
147 PyObject *kwds)
148 {
149 XcObject *xc = (XcObject *)self;
150 PyObject *list;
152 u32 first_dom = 0;
153 int max_doms = 1024, nr_doms, i;
154 xc_dominfo_t *info;
156 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
158 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
159 &first_dom, &max_doms) )
160 return NULL;
162 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
163 return PyErr_NoMemory();
165 nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
167 list = PyList_New(nr_doms);
168 for ( i = 0 ; i < nr_doms; i++ )
169 {
170 PyList_SetItem(
171 list, i,
172 Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
173 ",s:l,s:L,s:l,s:i}",
174 "dom", info[i].domid,
175 "cpu", info[i].cpu,
176 "dying", info[i].dying,
177 "crashed", info[i].crashed,
178 "shutdown", info[i].shutdown,
179 "paused", info[i].paused,
180 "blocked", info[i].blocked,
181 "running", info[i].running,
182 "mem_kb", info[i].nr_pages*4,
183 "cpu_time", info[i].cpu_time,
184 "maxmem_kb", info[i].max_memkb,
185 "shutdown_reason", info[i].shutdown_reason
186 ));
187 }
189 free(info);
191 return list;
192 }
194 static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file)
195 {
196 int rc = -1;
197 int fd = -1;
198 int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
199 int open_mode = 0644;
201 printf("%s>\n", __FUNCTION__);
203 if ( (fd = open(state_file, open_flags, open_mode)) < 0 )
204 {
205 xcio_perror(ctxt, "Could not open file for writing");
206 goto exit;
207 }
209 printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
211 /* Compression rate 1: we want speed over compression.
212 * We're mainly going for those zero pages, after all.
213 */
214 ctxt->io = gzip_stream_fdopen(fd, "wb1");
215 if ( ctxt->io == NULL )
216 {
217 xcio_perror(ctxt, "Could not allocate compression state");
218 goto exit;
219 }
221 printf("%s> xc_linux_save...\n", __FUNCTION__);
223 rc = xc_linux_save(xc->xc_handle, ctxt);
225 exit:
226 if ( ctxt->io != NULL )
227 IOStream_close(ctxt->io);
228 if ( fd >= 0 )
229 close(fd);
230 unlink(state_file);
231 printf("%s> rc=%d\n", __FUNCTION__, rc);
232 return rc;
233 }
235 static PyObject *pyxc_linux_save(PyObject *self,
236 PyObject *args,
237 PyObject *kwds)
238 {
239 XcObject *xc = (XcObject *)self;
241 char *state_file;
242 int progress = 1, debug = 0;
243 PyObject *val = NULL;
244 int rc = -1;
245 XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
247 static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
249 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list,
250 &ioctxt.domain,
251 &state_file,
252 &ioctxt.vmconfig,
253 &progress,
254 &debug) )
255 goto exit;
257 ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
259 if ( progress )
260 ioctxt.flags |= XCFLAGS_VERBOSE;
261 if ( debug )
262 ioctxt.flags |= XCFLAGS_DEBUG;
264 if ( (state_file == NULL) || (state_file[0] == '\0') )
265 goto exit;
267 rc = file_save(xc, &ioctxt, state_file);
268 if ( rc != 0 )
269 {
270 PyErr_SetFromErrno(xc_error);
271 goto exit;
272 }
274 Py_INCREF(zero);
275 val = zero;
277 exit:
278 return val;
279 }
282 static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file)
283 {
284 int rc = -1;
286 ioctxt->io = gzip_stream_fopen(state_file, "rb");
287 if ( ioctxt->io == NULL )
288 {
289 xcio_perror(ioctxt, "Could not open file for reading");
290 return rc;
291 }
293 rc = xc_linux_restore(xc->xc_handle, ioctxt);
295 IOStream_close(ioctxt->io);
297 return rc;
298 }
300 static PyObject *pyxc_linux_restore(PyObject *self,
301 PyObject *args,
302 PyObject *kwds)
303 {
304 XcObject *xc = (XcObject *)self;
305 char *state_file;
306 int progress = 1, debug = 0;
307 PyObject *val = NULL;
308 XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
309 int rc =-1;
311 static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
313 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s|ii", kwd_list,
314 &state_file,
315 &progress,
316 &debug) )
317 goto exit;
319 if ( progress )
320 ioctxt.flags |= XCFLAGS_VERBOSE;
321 if ( debug )
322 ioctxt.flags |= XCFLAGS_DEBUG;
324 if ( (state_file == NULL) || (state_file[0] == '\0') )
325 goto exit;
327 rc = file_restore(xc, &ioctxt, state_file);
328 if ( rc != 0 )
329 {
330 PyErr_SetFromErrno(xc_error);
331 goto exit;
332 }
334 val = Py_BuildValue("{s:i,s:s}",
335 "dom", ioctxt.domain,
336 "vmconfig", ioctxt.vmconfig);
338 exit:
339 return val;
340 }
342 static PyObject *pyxc_linux_build(PyObject *self,
343 PyObject *args,
344 PyObject *kwds)
345 {
346 XcObject *xc = (XcObject *)self;
348 u32 dom;
349 char *image, *ramdisk = NULL, *cmdline = "";
350 int control_evtchn, flags = 0;
352 static char *kwd_list[] = { "dom", "control_evtchn",
353 "image", "ramdisk", "cmdline", "flags",
354 NULL };
356 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
357 &dom, &control_evtchn,
358 &image, &ramdisk, &cmdline, &flags) )
359 return NULL;
361 if ( xc_linux_build(xc->xc_handle, dom, image,
362 ramdisk, cmdline, control_evtchn, flags) != 0 )
363 return PyErr_SetFromErrno(xc_error);
365 Py_INCREF(zero);
366 return zero;
367 }
369 static PyObject *pyxc_plan9_build(PyObject *self,
370 PyObject *args,
371 PyObject *kwds)
372 {
373 XcObject *xc = (XcObject *)self;
375 u32 dom;
376 char *image, *ramdisk = NULL, *cmdline = "";
377 int control_evtchn, flags = 0;
379 static char *kwd_list[] = { "dom", "control_evtchn",
380 "image", "ramdisk", "cmdline", "flags",
381 NULL };
383 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
384 &dom, &control_evtchn,
385 &image, &ramdisk, &cmdline, &flags) )
386 return NULL;
388 if ( xc_plan9_build(xc->xc_handle, dom, image,
389 cmdline, control_evtchn, flags) != 0 )
390 return PyErr_SetFromErrno(xc_error);
392 Py_INCREF(zero);
393 return zero;
394 }
396 static PyObject *pyxc_bvtsched_global_set(PyObject *self,
397 PyObject *args,
398 PyObject *kwds)
399 {
400 XcObject *xc = (XcObject *)self;
402 unsigned long ctx_allow;
404 static char *kwd_list[] = { "ctx_allow", NULL };
406 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
407 return NULL;
409 if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
410 return PyErr_SetFromErrno(xc_error);
412 Py_INCREF(zero);
413 return zero;
414 }
416 static PyObject *pyxc_bvtsched_global_get(PyObject *self,
417 PyObject *args,
418 PyObject *kwds)
419 {
420 XcObject *xc = (XcObject *)self;
422 unsigned long ctx_allow;
424 if ( !PyArg_ParseTuple(args, "") )
425 return NULL;
427 if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
428 return PyErr_SetFromErrno(xc_error);
430 return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
431 }
433 static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
434 PyObject *args,
435 PyObject *kwds)
436 {
437 XcObject *xc = (XcObject *)self;
439 u32 dom;
440 u32 mcuadv;
441 int warpback;
442 s32 warpvalue;
443 long long warpl;
444 long long warpu;
446 static char *kwd_list[] = { "dom", "mcuadv", "warpback", "warpvalue",
447 "warpl", "warpu", NULL };
449 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiiLL", kwd_list,
450 &dom, &mcuadv, &warpback, &warpvalue,
451 &warpl, &warpu) )
452 return NULL;
454 if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
455 warpback, warpvalue, warpl, warpu) != 0 )
456 return PyErr_SetFromErrno(xc_error);
458 Py_INCREF(zero);
459 return zero;
460 }
462 static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
463 PyObject *args,
464 PyObject *kwds)
465 {
466 XcObject *xc = (XcObject *)self;
467 u32 dom;
468 u32 mcuadv;
469 int warpback;
470 s32 warpvalue;
471 long long warpl;
472 long long warpu;
474 static char *kwd_list[] = { "dom", NULL };
476 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
477 return NULL;
479 if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warpback,
480 &warpvalue, &warpl, &warpu) != 0 )
481 return PyErr_SetFromErrno(xc_error);
483 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
484 "domain", dom,
485 "mcuadv", mcuadv,
486 "warpback", warpback,
487 "warpvalue", warpvalue,
488 "warpl", warpl,
489 "warpu", warpu);
490 }
492 static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
493 PyObject *args,
494 PyObject *kwds)
495 {
496 XcObject *xc = (XcObject *)self;
498 u32 dom;
499 int port;
501 static char *kwd_list[] = { "dom", NULL };
503 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
504 return NULL;
506 if ( xc_evtchn_alloc_unbound(xc->xc_handle, dom, &port) != 0 )
507 return PyErr_SetFromErrno(xc_error);
509 return PyInt_FromLong(port);
510 }
512 static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
513 PyObject *args,
514 PyObject *kwds)
515 {
516 XcObject *xc = (XcObject *)self;
518 u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
519 int port1 = 0, port2 = 0;
521 static char *kwd_list[] = { "dom1", "dom2", "port1", "port2", NULL };
523 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiii", kwd_list,
524 &dom1, &dom2, &port1, &port2) )
525 return NULL;
527 if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
528 dom2, &port1, &port2) != 0 )
529 return PyErr_SetFromErrno(xc_error);
531 return Py_BuildValue("{s:i,s:i}",
532 "port1", port1,
533 "port2", port2);
534 }
536 static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
537 PyObject *args,
538 PyObject *kwds)
539 {
540 XcObject *xc = (XcObject *)self;
542 int virq, port;
544 static char *kwd_list[] = { "virq", NULL };
546 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
547 return NULL;
549 if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
550 return PyErr_SetFromErrno(xc_error);
552 return PyInt_FromLong(port);
553 }
555 static PyObject *pyxc_evtchn_close(PyObject *self,
556 PyObject *args,
557 PyObject *kwds)
558 {
559 XcObject *xc = (XcObject *)self;
561 u32 dom = DOMID_SELF;
562 int port;
564 static char *kwd_list[] = { "port", "dom", NULL };
566 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
567 &port, &dom) )
568 return NULL;
570 if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
571 return PyErr_SetFromErrno(xc_error);
573 Py_INCREF(zero);
574 return zero;
575 }
577 static PyObject *pyxc_evtchn_send(PyObject *self,
578 PyObject *args,
579 PyObject *kwds)
580 {
581 XcObject *xc = (XcObject *)self;
583 int port;
585 static char *kwd_list[] = { "port", NULL };
587 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
588 return NULL;
590 if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
591 return PyErr_SetFromErrno(xc_error);
593 Py_INCREF(zero);
594 return zero;
595 }
597 static PyObject *pyxc_evtchn_status(PyObject *self,
598 PyObject *args,
599 PyObject *kwds)
600 {
601 XcObject *xc = (XcObject *)self;
602 PyObject *dict;
604 u32 dom = DOMID_SELF;
605 int port, ret;
606 xc_evtchn_status_t status;
608 static char *kwd_list[] = { "port", "dom", NULL };
610 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
611 &port, &dom) )
612 return NULL;
614 ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
615 if ( ret != 0 )
616 return PyErr_SetFromErrno(xc_error);
618 switch ( status.status )
619 {
620 case EVTCHNSTAT_closed:
621 dict = Py_BuildValue("{s:s}",
622 "status", "closed");
623 break;
624 case EVTCHNSTAT_unbound:
625 dict = Py_BuildValue("{s:s}",
626 "status", "unbound");
627 break;
628 case EVTCHNSTAT_interdomain:
629 dict = Py_BuildValue("{s:s,s:i,s:i}",
630 "status", "interdomain",
631 "dom", status.u.interdomain.dom,
632 "port", status.u.interdomain.port);
633 break;
634 case EVTCHNSTAT_pirq:
635 dict = Py_BuildValue("{s:s,s:i}",
636 "status", "pirq",
637 "irq", status.u.pirq);
638 break;
639 case EVTCHNSTAT_virq:
640 dict = Py_BuildValue("{s:s,s:i}",
641 "status", "virq",
642 "irq", status.u.virq);
643 break;
644 default:
645 dict = Py_BuildValue("{}");
646 break;
647 }
649 return dict;
650 }
652 static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
653 PyObject *args,
654 PyObject *kwds)
655 {
656 XcObject *xc = (XcObject *)self;
657 u32 dom;
658 int bus, dev, func, enable, ret;
660 static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
662 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
663 &dom, &bus, &dev, &func, &enable) )
664 return NULL;
666 ret = xc_physdev_pci_access_modify(
667 xc->xc_handle, dom, bus, dev, func, enable);
668 if ( ret != 0 )
669 return PyErr_SetFromErrno(xc_error);
671 Py_INCREF(zero);
672 return zero;
673 }
675 static PyObject *pyxc_readconsolering(PyObject *self,
676 PyObject *args,
677 PyObject *kwds)
678 {
679 XcObject *xc = (XcObject *)self;
681 unsigned int clear = 0;
682 char str[32768];
683 int ret;
685 static char *kwd_list[] = { "clear", NULL };
687 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
688 return NULL;
690 ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
691 if ( ret < 0 )
692 return PyErr_SetFromErrno(xc_error);
694 return PyString_FromStringAndSize(str, ret);
695 }
697 static PyObject *pyxc_physinfo(PyObject *self,
698 PyObject *args,
699 PyObject *kwds)
700 {
701 XcObject *xc = (XcObject *)self;
702 xc_physinfo_t info;
704 if ( !PyArg_ParseTuple(args, "") )
705 return NULL;
707 if ( xc_physinfo(xc->xc_handle, &info) != 0 )
708 return PyErr_SetFromErrno(xc_error);
710 return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
711 "ht_per_core", info.ht_per_core,
712 "cores", info.cores,
713 "total_pages", info.total_pages,
714 "free_pages", info.free_pages,
715 "cpu_khz", info.cpu_khz);
716 }
718 static PyObject *pyxc_atropos_domain_set(PyObject *self,
719 PyObject *args,
720 PyObject *kwds)
721 {
722 XcObject *xc = (XcObject *)self;
723 u32 domid;
724 u64 period, slice, latency;
725 int xtratime;
727 static char *kwd_list[] = { "dom", "period", "slice", "latency",
728 "xtratime", NULL };
730 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
731 &period, &slice, &latency, &xtratime) )
732 return NULL;
734 if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
735 latency, xtratime) != 0 )
736 return PyErr_SetFromErrno(xc_error);
738 Py_INCREF(zero);
739 return zero;
740 }
742 static PyObject *pyxc_atropos_domain_get(PyObject *self,
743 PyObject *args,
744 PyObject *kwds)
745 {
746 XcObject *xc = (XcObject *)self;
747 u32 domid;
748 u64 period, slice, latency;
749 int xtratime;
751 static char *kwd_list[] = { "dom", NULL };
753 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
754 return NULL;
756 if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
757 &slice, &latency, &xtratime ) )
758 return PyErr_SetFromErrno(xc_error);
760 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
761 "domain", domid,
762 "period", period,
763 "slice", slice,
764 "latency", latency,
765 "xtratime", xtratime);
766 }
769 static PyObject *pyxc_rrobin_global_set(PyObject *self,
770 PyObject *args,
771 PyObject *kwds)
772 {
773 XcObject *xc = (XcObject *)self;
774 u64 slice;
776 static char *kwd_list[] = { "slice", NULL };
778 if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
779 return NULL;
781 if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
782 return PyErr_SetFromErrno(xc_error);
784 Py_INCREF(zero);
785 return zero;
786 }
788 static PyObject *pyxc_sedf_domain_set(PyObject *self,
789 PyObject *args,
790 PyObject *kwds)
791 {
792 XcObject *xc = (XcObject *)self;
793 u32 domid;
794 u64 period, slice, latency;
795 u16 extratime, weight;
796 static char *kwd_list[] = { "dom", "period", "slice", "latency", "extratime", "weight",NULL };
798 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list, &domid,
799 &period, &slice, &latency, &extratime, &weight) )
800 return NULL;
801 if ( xc_sedf_domain_set(xc->xc_handle, domid, period, slice, latency, extratime,weight) != 0 )
802 return PyErr_SetFromErrno(xc_error);
804 Py_INCREF(zero);
805 return zero;
806 }
808 static PyObject *pyxc_sedf_domain_get(PyObject *self,
809 PyObject *args,
810 PyObject *kwds)
811 {
812 XcObject *xc = (XcObject *)self;
813 u32 domid;
814 u64 period, slice,latency;
815 u16 weight, extratime;
817 static char *kwd_list[] = { "dom", NULL };
819 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
820 return NULL;
822 if ( xc_sedf_domain_get( xc->xc_handle, domid, &period,
823 &slice,&latency,&extratime,&weight) )
824 return PyErr_SetFromErrno(xc_error);
826 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
827 "domain", domid,
828 "period", period,
829 "slice", slice,
830 "latency", latency,
831 "extratime", extratime);
832 }
834 static PyObject *pyxc_shadow_control(PyObject *self,
835 PyObject *args,
836 PyObject *kwds)
837 {
838 XcObject *xc = (XcObject *)self;
840 u32 dom;
841 int op=0;
843 static char *kwd_list[] = { "dom", "op", NULL };
845 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
846 &dom, &op) )
847 return NULL;
849 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
850 return PyErr_SetFromErrno(xc_error);
852 Py_INCREF(zero);
853 return zero;
854 }
856 static PyObject *pyxc_rrobin_global_get(PyObject *self,
857 PyObject *args,
858 PyObject *kwds)
859 {
860 XcObject *xc = (XcObject *)self;
861 u64 slice;
863 if ( !PyArg_ParseTuple(args, "") )
864 return NULL;
866 if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
867 return PyErr_SetFromErrno(xc_error);
869 return Py_BuildValue("{s:L}", "slice", slice);
870 }
872 static PyObject *pyxc_domain_setmaxmem(PyObject *self,
873 PyObject *args,
874 PyObject *kwds)
875 {
876 XcObject *xc = (XcObject *)self;
878 u32 dom;
879 unsigned long maxmem_kb;
881 static char *kwd_list[] = { "dom", "maxmem_kb", NULL };
883 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
884 &dom, &maxmem_kb) )
885 return NULL;
887 if ( xc_domain_setmaxmem(xc->xc_handle, dom, maxmem_kb) != 0 )
888 return PyErr_SetFromErrno(xc_error);
890 Py_INCREF(zero);
891 return zero;
892 }
895 static PyMethodDef pyxc_methods[] = {
896 { "domain_create",
897 (PyCFunction)pyxc_domain_create,
898 METH_VARARGS | METH_KEYWORDS, "\n"
899 "Create a new domain.\n"
900 " dom [int, 0]: Domain identifier to use (allocated if zero).\n"
901 " mem_kb [int, 0]: Memory allocation, in kilobytes.\n"
902 "Returns: [int] new domain identifier; -1 on error.\n" },
904 { "domain_pause",
905 (PyCFunction)pyxc_domain_pause,
906 METH_VARARGS | METH_KEYWORDS, "\n"
907 "Temporarily pause execution of a domain.\n"
908 " dom [int]: Identifier of domain to be paused.\n\n"
909 "Returns: [int] 0 on success; -1 on error.\n" },
911 { "domain_unpause",
912 (PyCFunction)pyxc_domain_unpause,
913 METH_VARARGS | METH_KEYWORDS, "\n"
914 "(Re)start execution of a domain.\n"
915 " dom [int]: Identifier of domain to be unpaused.\n\n"
916 "Returns: [int] 0 on success; -1 on error.\n" },
918 { "domain_destroy",
919 (PyCFunction)pyxc_domain_destroy,
920 METH_VARARGS | METH_KEYWORDS, "\n"
921 "Destroy a domain.\n"
922 " dom [int]: Identifier of domain to be destroyed.\n\n"
923 "Returns: [int] 0 on success; -1 on error.\n" },
925 { "domain_pincpu",
926 (PyCFunction)pyxc_domain_pincpu,
927 METH_VARARGS | METH_KEYWORDS, "\n"
928 "Pin a domain to a specified CPU.\n"
929 " dom [int]: Identifier of domain to be pinned.\n"
930 " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
931 "Returns: [int] 0 on success; -1 on error.\n" },
933 { "domain_getinfo",
934 (PyCFunction)pyxc_domain_getinfo,
935 METH_VARARGS | METH_KEYWORDS, "\n"
936 "Get information regarding a set of domains, in increasing id order.\n"
937 " first_dom [int, 0]: First domain to retrieve info about.\n"
938 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
939 " about.\n\n"
940 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
941 " parameter then there was an error, or the end of the\n"
942 " domain-id space was reached.\n"
943 " dom [int]: Identifier of domain to which this info pertains\n"
944 " cpu [int]: CPU to which this domain is bound\n"
945 " dying [int]: Bool - is the domain dying?\n"
946 " crashed [int]: Bool - has the domain crashed?\n"
947 " shutdown [int]: Bool - has the domain shut itself down?\n"
948 " paused [int]: Bool - is the domain paused by control software?\n"
949 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
950 " running [int]: Bool - is the domain currently running?\n"
951 " mem_kb [int]: Memory reservation, in kilobytes\n"
952 " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
953 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
954 " shutdown_reason [int]: Numeric code from guest OS, explaining "
955 "reason why it shut itself down.\n" },
957 { "linux_save",
958 (PyCFunction)pyxc_linux_save,
959 METH_VARARGS | METH_KEYWORDS, "\n"
960 "Save the CPU and memory state of a Linux guest OS.\n"
961 " dom [int]: Identifier of domain to be saved.\n"
962 " state_file [str]: Name of state file. Must not currently exist.\n"
963 " progress [int, 1]: Bool - display a running progress indication?\n\n"
964 "Returns: [int] 0 on success; -1 on error.\n" },
965 { "plan9_build",
966 (PyCFunction)pyxc_plan9_build,
967 METH_VARARGS | METH_KEYWORDS, "\n"
968 "Build a new Plan 9 guest OS.\n"
969 " dom [long]: Identifier of domain to build into.\n"
970 " image [str]: Name of kernel image file. May be gzipped.\n"
971 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
972 "Returns: [int] 0 on success; -1 on error.\n" },
974 { "linux_restore",
975 (PyCFunction)pyxc_linux_restore,
976 METH_VARARGS | METH_KEYWORDS, "\n"
977 "Restore the CPU and memory state of a Linux guest OS.\n"
978 " state_file [str]: Name of state file. Must not currently exist.\n"
979 " progress [int, 1]: Bool - display a running progress indication?\n\n"
980 "Returns: [int] new domain identifier on success; -1 on error.\n" },
982 { "linux_build",
983 (PyCFunction)pyxc_linux_build,
984 METH_VARARGS | METH_KEYWORDS, "\n"
985 "Build a new Linux guest OS.\n"
986 " dom [int]: Identifier of domain to build into.\n"
987 " image [str]: Name of kernel image file. May be gzipped.\n"
988 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
989 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
990 "Returns: [int] 0 on success; -1 on error.\n" },
992 { "bvtsched_global_set",
993 (PyCFunction)pyxc_bvtsched_global_set,
994 METH_VARARGS | METH_KEYWORDS, "\n"
995 "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
996 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
997 "Returns: [int] 0 on success; -1 on error.\n" },
999 { "bvtsched_global_get",
1000 (PyCFunction)pyxc_bvtsched_global_get,
1001 METH_KEYWORDS, "\n"
1002 "Get global tuning parameters for BVT scheduler.\n"
1003 "Returns: [dict]:\n"
1004 " ctx_allow [int]: context switch allowance\n" },
1006 { "bvtsched_domain_set",
1007 (PyCFunction)pyxc_bvtsched_domain_set,
1008 METH_VARARGS | METH_KEYWORDS, "\n"
1009 "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
1010 " dom [int]: Identifier of domain to be tuned.\n"
1011 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
1012 " warpback [int]: Warp ? \n"
1013 " warpvalue [int]: How far to warp domain's EVT on unblock.\n"
1014 " warpl [int]: How long the domain can run warped.\n"
1015 " warpu [int]: How long before the domain can warp again.\n\n"
1016 "Returns: [int] 0 on success; -1 on error.\n" },
1018 { "bvtsched_domain_get",
1019 (PyCFunction)pyxc_bvtsched_domain_get,
1020 METH_KEYWORDS, "\n"
1021 "Get per-domain tuning parameters under the BVT scheduler.\n"
1022 " dom [int]: Identifier of domain to be queried.\n"
1023 "Returns [dict]:\n"
1024 " domain [int]: Domain ID.\n"
1025 " mcuadv [long]: MCU Advance.\n"
1026 " warp [long]: Warp.\n"
1027 " warpu [long]: Unwarp requirement.\n"
1028 " warpl [long]: Warp limit,\n"
1029 },
1031 { "atropos_domain_set",
1032 (PyCFunction)pyxc_atropos_domain_set,
1033 METH_KEYWORDS, "\n"
1034 "Set the scheduling parameters for a domain when running with Atropos.\n"
1035 " dom [int]: domain to set\n"
1036 " period [long]: domain's scheduling period\n"
1037 " slice [long]: domain's slice per period\n"
1038 " latency [long]: wakeup latency hint\n"
1039 " xtratime [int]: boolean\n"
1040 "Returns: [int] 0 on success; -1 on error.\n" },
1042 { "atropos_domain_get",
1043 (PyCFunction)pyxc_atropos_domain_get,
1044 METH_KEYWORDS, "\n"
1045 "Get the current scheduling parameters for a domain when running with\n"
1046 "the Atropos scheduler."
1047 " dom [int]: domain to query\n"
1048 "Returns: [dict]\n"
1049 " domain [int]: domain ID\n"
1050 " period [long]: scheduler period\n"
1051 " slice [long]: CPU reservation per period\n"
1052 " latency [long]: unblocking latency hint\n"
1053 " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
1055 { "rrobin_global_set",
1056 (PyCFunction)pyxc_rrobin_global_set,
1057 METH_KEYWORDS, "\n"
1058 "Set Round Robin scheduler slice.\n"
1059 " slice [long]: Round Robin scheduler slice\n"
1060 "Returns: [int] 0 on success, throws an exception on failure\n" },
1062 { "rrobin_global_get",
1063 (PyCFunction)pyxc_rrobin_global_get,
1064 METH_KEYWORDS, "\n"
1065 "Get Round Robin scheduler settings\n"
1066 "Returns [dict]:\n"
1067 " slice [long]: Scheduler time slice.\n" },
1069 { "sedf_domain_set",
1070 (PyCFunction)pyxc_sedf_domain_set,
1071 METH_KEYWORDS, "\n"
1072 "Set the scheduling parameters for a domain when running with Atropos.\n"
1073 " dom [int]: domain to set\n"
1074 " period [long]: domain's scheduling period\n"
1075 " slice [long]: domain's slice per period\n"
1076 " latency [long]: domain's wakeup latency hint\n"
1077 " extratime [int]: domain aware of extratime?\n"
1078 "Returns: [int] 0 on success; -1 on error.\n" },
1080 { "sedf_domain_get",
1081 (PyCFunction)pyxc_sedf_domain_get,
1082 METH_KEYWORDS, "\n"
1083 "Get the current scheduling parameters for a domain when running with\n"
1084 "the Atropos scheduler."
1085 " dom [int]: domain to query\n"
1086 "Returns: [dict]\n"
1087 " domain [int]: domain ID\n"
1088 " period [long]: scheduler period\n"
1089 " slice [long]: CPU reservation per period\n"
1090 " latency [long]: domain's wakeup latency hint\n"
1091 " extratime [int]: domain aware of extratime?\n"},
1093 { "evtchn_alloc_unbound",
1094 (PyCFunction)pyxc_evtchn_alloc_unbound,
1095 METH_VARARGS | METH_KEYWORDS, "\n"
1096 "Allocate an unbound local port that will await a remote connection.\n"
1097 " dom [int]: Remote domain to accept connections from.\n\n"
1098 "Returns: [int] Unbound event-channel port.\n" },
1100 { "evtchn_bind_interdomain",
1101 (PyCFunction)pyxc_evtchn_bind_interdomain,
1102 METH_VARARGS | METH_KEYWORDS, "\n"
1103 "Open an event channel between two domains.\n"
1104 " dom1 [int, SELF]: First domain to be connected.\n"
1105 " dom2 [int, SELF]: Second domain to be connected.\n\n"
1106 "Returns: [dict] dictionary is empty on failure.\n"
1107 " port1 [int]: Port-id for endpoint at dom1.\n"
1108 " port2 [int]: Port-id for endpoint at dom2.\n" },
1110 { "evtchn_bind_virq",
1111 (PyCFunction)pyxc_evtchn_bind_virq,
1112 METH_VARARGS | METH_KEYWORDS, "\n"
1113 "Bind an event channel to the specified VIRQ.\n"
1114 " virq [int]: VIRQ to bind.\n\n"
1115 "Returns: [int] Bound event-channel port.\n" },
1117 { "evtchn_close",
1118 (PyCFunction)pyxc_evtchn_close,
1119 METH_VARARGS | METH_KEYWORDS, "\n"
1120 "Close an event channel. If interdomain, sets remote end to 'unbound'.\n"
1121 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1122 " port [int]: Port-id of one endpoint of the channel.\n\n"
1123 "Returns: [int] 0 on success; -1 on error.\n" },
1125 { "evtchn_send",
1126 (PyCFunction)pyxc_evtchn_send,
1127 METH_VARARGS | METH_KEYWORDS, "\n"
1128 "Send an event along a locally-connected event channel.\n"
1129 " port [int]: Port-id of a local channel endpoint.\n\n"
1130 "Returns: [int] 0 on success; -1 on error.\n" },
1132 { "evtchn_status",
1133 (PyCFunction)pyxc_evtchn_status,
1134 METH_VARARGS | METH_KEYWORDS, "\n"
1135 "Query the status of an event channel.\n"
1136 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1137 " port [int]: Port-id of one endpoint of the channel.\n\n"
1138 "Returns: [dict] dictionary is empty on failure.\n"
1139 " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
1140 " or 'virq'.\n"
1141 "The following are returned if 'status' is 'interdomain':\n"
1142 " dom [int]: Dom-id of remote endpoint.\n"
1143 " port [int]: Port-id of remote endpoint.\n"
1144 "The following are returned if 'status' is 'pirq' or 'virq':\n"
1145 " irq [int]: IRQ number.\n" },
1147 { "physdev_pci_access_modify",
1148 (PyCFunction)pyxc_physdev_pci_access_modify,
1149 METH_VARARGS | METH_KEYWORDS, "\n"
1150 "Allow a domain access to a PCI device\n"
1151 " dom [int]: Identifier of domain to be allowed access.\n"
1152 " bus [int]: PCI bus\n"
1153 " dev [int]: PCI slot\n"
1154 " func [int]: PCI function\n"
1155 " enable [int]: Non-zero means enable access; else disable access\n\n"
1156 "Returns: [int] 0 on success; -1 on error.\n" },
1158 { "readconsolering",
1159 (PyCFunction)pyxc_readconsolering,
1160 METH_VARARGS | METH_KEYWORDS, "\n"
1161 "Read Xen's console ring.\n"
1162 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1163 "Returns: [str] string is empty on failure.\n" },
1165 { "physinfo",
1166 (PyCFunction)pyxc_physinfo,
1167 METH_VARARGS, "\n"
1168 "Get information about the physical host machine\n"
1169 "Returns [dict]: information about the hardware"
1170 " [None]: on failure.\n" },
1172 { "shadow_control",
1173 (PyCFunction)pyxc_shadow_control,
1174 METH_VARARGS | METH_KEYWORDS, "\n"
1175 "Set parameter for shadow pagetable interface\n"
1176 " dom [int]: Identifier of domain.\n"
1177 " op [int, 0]: operation\n\n"
1178 "Returns: [int] 0 on success; -1 on error.\n" },
1180 { "domain_setmaxmem",
1181 (PyCFunction)pyxc_domain_setmaxmem,
1182 METH_VARARGS | METH_KEYWORDS, "\n"
1183 "Set a domain's memory limit\n"
1184 " dom [int]: Identifier of domain.\n"
1185 " maxmem_kb [long]: .\n"
1186 "Returns: [int] 0 on success; -1 on error.\n" },
1188 { NULL, NULL, 0, NULL }
1189 };
1192 /*
1193 * Definitions for the 'Xc' module wrapper.
1194 */
1196 staticforward PyTypeObject PyXcType;
1198 static PyObject *PyXc_new(PyObject *self, PyObject *args)
1200 XcObject *xc;
1202 if ( !PyArg_ParseTuple(args, ":new") )
1203 return NULL;
1205 xc = PyObject_New(XcObject, &PyXcType);
1207 if ( (xc->xc_handle = xc_interface_open()) == -1 )
1209 PyObject_Del((PyObject *)xc);
1210 return PyErr_SetFromErrno(xc_error);
1213 return (PyObject *)xc;
1216 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1218 return Py_FindMethod(pyxc_methods, obj, name);
1221 static void PyXc_dealloc(PyObject *self)
1223 XcObject *xc = (XcObject *)self;
1224 (void)xc_interface_close(xc->xc_handle);
1225 PyObject_Del(self);
1228 static PyTypeObject PyXcType = {
1229 PyObject_HEAD_INIT(&PyType_Type)
1230 0,
1231 "Xc",
1232 sizeof(XcObject),
1233 0,
1234 PyXc_dealloc, /* tp_dealloc */
1235 NULL, /* tp_print */
1236 PyXc_getattr, /* tp_getattr */
1237 NULL, /* tp_setattr */
1238 NULL, /* tp_compare */
1239 NULL, /* tp_repr */
1240 NULL, /* tp_as_number */
1241 NULL, /* tp_as_sequence */
1242 NULL, /* tp_as_mapping */
1243 NULL /* tp_hash */
1244 };
1246 static PyMethodDef PyXc_methods[] = {
1247 { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
1248 { NULL, NULL, 0, NULL }
1249 };
1251 PyMODINIT_FUNC initxc(void)
1253 PyObject *m, *d;
1255 m = Py_InitModule(XENPKG, PyXc_methods);
1257 d = PyModule_GetDict(m);
1258 xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
1259 PyDict_SetItemString(d, "error", xc_error);
1261 zero = PyInt_FromLong(0);
1263 /* KAF: This ensures that we get debug output in a timely manner. */
1264 setbuf(stdout, NULL);
1265 setbuf(stderr, NULL);