ia64/xen-unstable

view tools/python/xen/lowlevel/xc/xc.c @ 1772:384558e64811

bitkeeper revision 1.1078 (40f3fba76Iz0xWiPyLNc6VMjsLY3Dw)

Fix the arg spec for save.
author mjw@wray-m-3.hpl.hp.com
date Tue Jul 13 15:11:35 2004 +0000 (2004-07-13)
parents 083178f6cdfa
children de62fd103f99 dae98734f12e
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 char *name = "(anon)";
46 int cpu = -1;
47 u32 dom;
48 int ret;
50 static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
52 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list,
53 &mem_kb, &name, &cpu) )
54 return NULL;
56 if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
57 return PyErr_SetFromErrno(xc_error);
59 return PyInt_FromLong(dom);
60 }
62 static PyObject *pyxc_domain_pause(PyObject *self,
63 PyObject *args,
64 PyObject *kwds)
65 {
66 XcObject *xc = (XcObject *)self;
68 u32 dom;
70 static char *kwd_list[] = { "dom", NULL };
72 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
73 return NULL;
75 if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
76 return PyErr_SetFromErrno(xc_error);
78 Py_INCREF(zero);
79 return zero;
80 }
82 static PyObject *pyxc_domain_unpause(PyObject *self,
83 PyObject *args,
84 PyObject *kwds)
85 {
86 XcObject *xc = (XcObject *)self;
88 u32 dom;
90 static char *kwd_list[] = { "dom", NULL };
92 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
93 return NULL;
95 if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
96 return PyErr_SetFromErrno(xc_error);
98 Py_INCREF(zero);
99 return zero;
100 }
102 static PyObject *pyxc_domain_destroy(PyObject *self,
103 PyObject *args,
104 PyObject *kwds)
105 {
106 XcObject *xc = (XcObject *)self;
108 u32 dom;
110 static char *kwd_list[] = { "dom", NULL };
112 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
113 return NULL;
115 if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
116 return PyErr_SetFromErrno(xc_error);
118 Py_INCREF(zero);
119 return zero;
120 }
122 static PyObject *pyxc_domain_pincpu(PyObject *self,
123 PyObject *args,
124 PyObject *kwds)
125 {
126 XcObject *xc = (XcObject *)self;
128 u32 dom;
129 int cpu = -1;
131 static char *kwd_list[] = { "dom", "cpu", NULL };
133 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
134 &dom, &cpu) )
135 return NULL;
137 if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
138 return PyErr_SetFromErrno(xc_error);
140 Py_INCREF(zero);
141 return zero;
142 }
144 static PyObject *pyxc_domain_getinfo(PyObject *self,
145 PyObject *args,
146 PyObject *kwds)
147 {
148 XcObject *xc = (XcObject *)self;
149 PyObject *list;
151 u32 first_dom = 0;
152 int max_doms = 1024, nr_doms, i;
153 xc_dominfo_t *info;
155 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
157 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
158 &first_dom, &max_doms) )
159 return NULL;
161 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
162 return PyErr_NoMemory();
164 nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
166 list = PyList_New(nr_doms);
167 for ( i = 0 ; i < nr_doms; i++ )
168 {
169 PyList_SetItem(
170 list, i,
171 Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
172 ",s:l,s:L,s:s,s:l,s:i}",
173 "dom", info[i].domid,
174 "cpu", info[i].cpu,
175 "dying", info[i].dying,
176 "crashed", info[i].crashed,
177 "shutdown", info[i].shutdown,
178 "paused", info[i].paused,
179 "blocked", info[i].blocked,
180 "running", info[i].running,
181 "mem_kb", info[i].nr_pages*4,
182 "cpu_time", info[i].cpu_time,
183 "name", info[i].name,
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_netbsd_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;
379 static char *kwd_list[] = { "dom", "control_evtchn",
380 "image", "ramdisk", "cmdline", NULL };
382 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
383 &dom, &control_evtchn,
384 &image, &ramdisk, &cmdline) )
385 return NULL;
387 if ( xc_netbsd_build(xc->xc_handle, dom, image,
388 cmdline, control_evtchn) != 0 )
389 return PyErr_SetFromErrno(xc_error);
391 Py_INCREF(zero);
392 return zero;
393 }
395 static PyObject *pyxc_bvtsched_global_set(PyObject *self,
396 PyObject *args,
397 PyObject *kwds)
398 {
399 XcObject *xc = (XcObject *)self;
401 unsigned long ctx_allow;
403 static char *kwd_list[] = { "ctx_allow", NULL };
405 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
406 return NULL;
408 if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
409 return PyErr_SetFromErrno(xc_error);
411 Py_INCREF(zero);
412 return zero;
413 }
415 static PyObject *pyxc_bvtsched_global_get(PyObject *self,
416 PyObject *args,
417 PyObject *kwds)
418 {
419 XcObject *xc = (XcObject *)self;
421 unsigned long ctx_allow;
423 if ( !PyArg_ParseTuple(args, "") )
424 return NULL;
426 if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
427 return PyErr_SetFromErrno(xc_error);
429 return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
430 }
432 static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
433 PyObject *args,
434 PyObject *kwds)
435 {
436 XcObject *xc = (XcObject *)self;
438 u32 dom;
439 unsigned long mcuadv, warp, warpl, warpu;
441 static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
442 "warpu", NULL };
444 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
445 &dom, &mcuadv, &warp, &warpl, &warpu) )
446 return NULL;
448 if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
449 warp, warpl, warpu) != 0 )
450 return PyErr_SetFromErrno(xc_error);
452 Py_INCREF(zero);
453 return zero;
454 }
456 static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
457 PyObject *args,
458 PyObject *kwds)
459 {
460 XcObject *xc = (XcObject *)self;
461 u32 dom;
462 unsigned long mcuadv, warp, warpl, warpu;
464 static char *kwd_list[] = { "dom", NULL };
466 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
467 return NULL;
469 if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
470 &warpl, &warpu) != 0 )
471 return PyErr_SetFromErrno(xc_error);
473 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
474 "domain", dom,
475 "mcuadv", mcuadv,
476 "warp", warp,
477 "warpl", warpl,
478 "warpu", warpu);
479 }
481 static PyObject *pyxc_fbvtsched_global_set(PyObject *self,
482 PyObject *args,
483 PyObject *kwds)
484 {
485 XcObject *xc = (XcObject *)self;
487 unsigned long ctx_allow;
489 static char *kwd_list[] = { "ctx_allow", NULL };
491 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
492 return NULL;
494 if ( xc_fbvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
495 return PyErr_SetFromErrno(xc_error);
497 Py_INCREF(zero);
498 return zero;
499 }
501 static PyObject *pyxc_fbvtsched_global_get(PyObject *self,
502 PyObject *args,
503 PyObject *kwds)
504 {
505 XcObject *xc = (XcObject *)self;
507 unsigned long ctx_allow;
509 if ( !PyArg_ParseTuple(args, "") )
510 return NULL;
512 if ( xc_fbvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
513 return PyErr_SetFromErrno(xc_error);
515 return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
516 }
518 static PyObject *pyxc_fbvtsched_domain_set(PyObject *self,
519 PyObject *args,
520 PyObject *kwds)
521 {
522 XcObject *xc = (XcObject *)self;
524 u32 dom;
525 unsigned long mcuadv, warp, warpl, warpu;
527 static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
528 "warpu", NULL };
530 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
531 &dom, &mcuadv, &warp, &warpl, &warpu) )
532 return NULL;
534 if ( xc_fbvtsched_domain_set(xc->xc_handle, dom, mcuadv,
535 warp, warpl, warpu) != 0 )
536 return PyErr_SetFromErrno(xc_error);
538 Py_INCREF(zero);
539 return zero;
540 }
542 static PyObject *pyxc_fbvtsched_domain_get(PyObject *self,
543 PyObject *args,
544 PyObject *kwds)
545 {
546 XcObject *xc = (XcObject *)self;
547 u32 dom;
548 unsigned long mcuadv, warp, warpl, warpu;
550 static char *kwd_list[] = { "dom", NULL };
552 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
553 return NULL;
555 if ( xc_fbvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
556 &warpl, &warpu) != 0 )
557 return PyErr_SetFromErrno(xc_error);
559 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
560 "domain", dom,
561 "mcuadv", mcuadv,
562 "warp", warp,
563 "warpl", warpl,
564 "warpu", warpu);
565 }
567 static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
568 PyObject *args,
569 PyObject *kwds)
570 {
571 XcObject *xc = (XcObject *)self;
573 u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
574 int port1, port2;
576 static char *kwd_list[] = { "dom1", "dom2", NULL };
578 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
579 &dom1, &dom2) )
580 return NULL;
582 if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
583 dom2, &port1, &port2) != 0 )
584 return PyErr_SetFromErrno(xc_error);
586 return Py_BuildValue("{s:i,s:i}",
587 "port1", port1,
588 "port2", port2);
589 }
591 static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
592 PyObject *args,
593 PyObject *kwds)
594 {
595 XcObject *xc = (XcObject *)self;
597 int virq, port;
599 static char *kwd_list[] = { "virq", NULL };
601 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
602 return NULL;
604 if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
605 return PyErr_SetFromErrno(xc_error);
607 return PyInt_FromLong(port);
608 }
610 static PyObject *pyxc_evtchn_close(PyObject *self,
611 PyObject *args,
612 PyObject *kwds)
613 {
614 XcObject *xc = (XcObject *)self;
616 u32 dom = DOMID_SELF;
617 int port;
619 static char *kwd_list[] = { "port", "dom", NULL };
621 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
622 &port, &dom) )
623 return NULL;
625 if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
626 return PyErr_SetFromErrno(xc_error);
628 Py_INCREF(zero);
629 return zero;
630 }
632 static PyObject *pyxc_evtchn_send(PyObject *self,
633 PyObject *args,
634 PyObject *kwds)
635 {
636 XcObject *xc = (XcObject *)self;
638 int port;
640 static char *kwd_list[] = { "port", NULL };
642 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
643 return NULL;
645 if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
646 return PyErr_SetFromErrno(xc_error);
648 Py_INCREF(zero);
649 return zero;
650 }
652 static PyObject *pyxc_evtchn_status(PyObject *self,
653 PyObject *args,
654 PyObject *kwds)
655 {
656 XcObject *xc = (XcObject *)self;
657 PyObject *dict;
659 u32 dom = DOMID_SELF;
660 int port, ret;
661 xc_evtchn_status_t status;
663 static char *kwd_list[] = { "port", "dom", NULL };
665 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
666 &port, &dom) )
667 return NULL;
669 ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
670 if ( ret != 0 )
671 return PyErr_SetFromErrno(xc_error);
673 switch ( status.status )
674 {
675 case EVTCHNSTAT_closed:
676 dict = Py_BuildValue("{s:s}",
677 "status", "closed");
678 break;
679 case EVTCHNSTAT_unbound:
680 dict = Py_BuildValue("{s:s}",
681 "status", "unbound");
682 break;
683 case EVTCHNSTAT_interdomain:
684 dict = Py_BuildValue("{s:s,s:i,s:i}",
685 "status", "interdomain",
686 "dom", status.u.interdomain.dom,
687 "port", status.u.interdomain.port);
688 break;
689 case EVTCHNSTAT_pirq:
690 dict = Py_BuildValue("{s:s,s:i}",
691 "status", "pirq",
692 "irq", status.u.pirq);
693 break;
694 case EVTCHNSTAT_virq:
695 dict = Py_BuildValue("{s:s,s:i}",
696 "status", "virq",
697 "irq", status.u.virq);
698 break;
699 default:
700 dict = Py_BuildValue("{}");
701 break;
702 }
704 return dict;
705 }
707 static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
708 PyObject *args,
709 PyObject *kwds)
710 {
711 XcObject *xc = (XcObject *)self;
712 u32 dom;
713 int bus, dev, func, enable, ret;
715 static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
717 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
718 &dom, &bus, &dev, &func, &enable) )
719 return NULL;
721 ret = xc_physdev_pci_access_modify(
722 xc->xc_handle, dom, bus, dev, func, enable);
723 if ( ret != 0 )
724 return PyErr_SetFromErrno(xc_error);
726 Py_INCREF(zero);
727 return zero;
728 }
730 static PyObject *pyxc_readconsolering(PyObject *self,
731 PyObject *args,
732 PyObject *kwds)
733 {
734 XcObject *xc = (XcObject *)self;
736 unsigned int clear = 0;
737 char str[32768];
738 int ret;
740 static char *kwd_list[] = { "clear", NULL };
742 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
743 return NULL;
745 ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
746 if ( ret < 0 )
747 return PyErr_SetFromErrno(xc_error);
749 return PyString_FromStringAndSize(str, ret);
750 }
752 static PyObject *pyxc_physinfo(PyObject *self,
753 PyObject *args,
754 PyObject *kwds)
755 {
756 XcObject *xc = (XcObject *)self;
757 xc_physinfo_t info;
759 if ( !PyArg_ParseTuple(args, "") )
760 return NULL;
762 if ( xc_physinfo(xc->xc_handle, &info) != 0 )
763 return PyErr_SetFromErrno(xc_error);
765 return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
766 "ht_per_core", info.ht_per_core,
767 "cores", info.cores,
768 "total_pages", info.total_pages,
769 "free_pages", info.free_pages,
770 "cpu_khz", info.cpu_khz);
771 }
773 static PyObject *pyxc_atropos_domain_set(PyObject *self,
774 PyObject *args,
775 PyObject *kwds)
776 {
777 XcObject *xc = (XcObject *)self;
778 u32 domid;
779 u64 period, slice, latency;
780 int xtratime;
782 static char *kwd_list[] = { "dom", "period", "slice", "latency",
783 "xtratime", NULL };
785 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
786 &period, &slice, &latency, &xtratime) )
787 return NULL;
789 if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
790 latency, xtratime) != 0 )
791 return PyErr_SetFromErrno(xc_error);
793 Py_INCREF(zero);
794 return zero;
795 }
797 static PyObject *pyxc_atropos_domain_get(PyObject *self,
798 PyObject *args,
799 PyObject *kwds)
800 {
801 XcObject *xc = (XcObject *)self;
802 u32 domid;
803 u64 period, slice, latency;
804 int xtratime;
806 static char *kwd_list[] = { "dom", NULL };
808 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
809 return NULL;
811 if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
812 &slice, &latency, &xtratime ) )
813 return PyErr_SetFromErrno(xc_error);
815 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
816 "domain", domid,
817 "period", period,
818 "slice", slice,
819 "latency", latency,
820 "xtratime", xtratime);
821 }
824 static PyObject *pyxc_rrobin_global_set(PyObject *self,
825 PyObject *args,
826 PyObject *kwds)
827 {
828 XcObject *xc = (XcObject *)self;
829 u64 slice;
831 static char *kwd_list[] = { "slice", NULL };
833 if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
834 return NULL;
836 if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
837 return PyErr_SetFromErrno(xc_error);
839 Py_INCREF(zero);
840 return zero;
841 }
843 static PyObject *pyxc_shadow_control(PyObject *self,
844 PyObject *args,
845 PyObject *kwds)
846 {
847 XcObject *xc = (XcObject *)self;
849 u32 dom;
850 int op=0;
852 static char *kwd_list[] = { "dom", "op", NULL };
854 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
855 &dom, &op) )
856 return NULL;
858 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
859 return PyErr_SetFromErrno(xc_error);
861 Py_INCREF(zero);
862 return zero;
863 }
865 static PyObject *pyxc_rrobin_global_get(PyObject *self,
866 PyObject *args,
867 PyObject *kwds)
868 {
869 XcObject *xc = (XcObject *)self;
870 u64 slice;
872 if ( !PyArg_ParseTuple(args, "") )
873 return NULL;
875 if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
876 return PyErr_SetFromErrno(xc_error);
878 return Py_BuildValue("{s:L}", "slice", slice);
879 }
881 static PyObject *pyxc_domain_setname(PyObject *self,
882 PyObject *args,
883 PyObject *kwds)
884 {
885 XcObject *xc = (XcObject *)self;
886 u32 dom;
887 char *name;
889 static char *kwd_list[] = { "dom", "name", NULL };
891 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list,
892 &dom, &name) )
893 return NULL;
895 if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
896 return PyErr_SetFromErrno(xc_error);
898 Py_INCREF(zero);
899 return zero;
900 }
902 static PyObject *pyxc_domain_setmaxmem(PyObject *self,
903 PyObject *args,
904 PyObject *kwds)
905 {
906 XcObject *xc = (XcObject *)self;
908 u32 dom;
909 unsigned long max_memkb;
911 static char *kwd_list[] = { "dom", "max_memkb", NULL };
913 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
914 &dom, &max_memkb) )
915 return NULL;
917 if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
918 return PyErr_SetFromErrno(xc_error);
920 Py_INCREF(zero);
921 return zero;
922 }
925 static PyMethodDef pyxc_methods[] = {
926 { "domain_create",
927 (PyCFunction)pyxc_domain_create,
928 METH_VARARGS | METH_KEYWORDS, "\n"
929 "Create a new domain.\n"
930 " mem_kb [int, 0]: Memory allocation, in kilobytes.\n"
931 " name [str, '(anon)']: Informative textual name.\n\n"
932 "Returns: [int] new domain identifier; -1 on error.\n" },
934 { "domain_pause",
935 (PyCFunction)pyxc_domain_pause,
936 METH_VARARGS | METH_KEYWORDS, "\n"
937 "Temporarily pause execution of a domain.\n"
938 " dom [int]: Identifier of domain to be paused.\n\n"
939 "Returns: [int] 0 on success; -1 on error.\n" },
941 { "domain_unpause",
942 (PyCFunction)pyxc_domain_unpause,
943 METH_VARARGS | METH_KEYWORDS, "\n"
944 "(Re)start execution of a domain.\n"
945 " dom [int]: Identifier of domain to be unpaused.\n\n"
946 "Returns: [int] 0 on success; -1 on error.\n" },
948 { "domain_destroy",
949 (PyCFunction)pyxc_domain_destroy,
950 METH_VARARGS | METH_KEYWORDS, "\n"
951 "Destroy a domain.\n"
952 " dom [int]: Identifier of domain to be destroyed.\n\n"
953 "Returns: [int] 0 on success; -1 on error.\n" },
955 { "domain_pincpu",
956 (PyCFunction)pyxc_domain_pincpu,
957 METH_VARARGS | METH_KEYWORDS, "\n"
958 "Pin a domain to a specified CPU.\n"
959 " dom [int]: Identifier of domain to be pinned.\n"
960 " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
961 "Returns: [int] 0 on success; -1 on error.\n" },
963 { "domain_getinfo",
964 (PyCFunction)pyxc_domain_getinfo,
965 METH_VARARGS | METH_KEYWORDS, "\n"
966 "Get information regarding a set of domains, in increasing id order.\n"
967 " first_dom [int, 0]: First domain to retrieve info about.\n"
968 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
969 " about.\n\n"
970 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
971 " parameter then there was an error, or the end of the\n"
972 " domain-id space was reached.\n"
973 " dom [int]: Identifier of domain to which this info pertains\n"
974 " cpu [int]: CPU to which this domain is bound\n"
975 " dying [int]: Bool - is the domain dying?\n"
976 " crashed [int]: Bool - has the domain crashed?\n"
977 " shutdown [int]: Bool - has the domain shut itself down?\n"
978 " paused [int]: Bool - is the domain paused by control software?\n"
979 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
980 " running [int]: Bool - is the domain currently running?\n"
981 " mem_kb [int]: Memory reservation, in kilobytes\n"
982 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
983 " name [str]: Identifying name\n"
984 " shutdown_reason [int]: Numeric code from guest OS, explaining "
985 "reason why it shut itself down.\n" },
987 { "linux_save",
988 (PyCFunction)pyxc_linux_save,
989 METH_VARARGS | METH_KEYWORDS, "\n"
990 "Save the CPU and memory state of a Linux guest OS.\n"
991 " dom [int]: Identifier of domain to be saved.\n"
992 " state_file [str]: Name of state file. Must not currently exist.\n"
993 " progress [int, 1]: Bool - display a running progress indication?\n\n"
994 "Returns: [int] 0 on success; -1 on error.\n" },
996 { "linux_restore",
997 (PyCFunction)pyxc_linux_restore,
998 METH_VARARGS | METH_KEYWORDS, "\n"
999 "Restore the CPU and memory state of a Linux guest OS.\n"
1000 " state_file [str]: Name of state file. Must not currently exist.\n"
1001 " progress [int, 1]: Bool - display a running progress indication?\n\n"
1002 "Returns: [int] new domain identifier on success; -1 on error.\n" },
1004 { "linux_build",
1005 (PyCFunction)pyxc_linux_build,
1006 METH_VARARGS | METH_KEYWORDS, "\n"
1007 "Build a new Linux guest OS.\n"
1008 " dom [int]: Identifier of domain to build into.\n"
1009 " image [str]: Name of kernel image file. May be gzipped.\n"
1010 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
1011 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1012 "Returns: [int] 0 on success; -1 on error.\n" },
1014 { "netbsd_build",
1015 (PyCFunction)pyxc_netbsd_build,
1016 METH_VARARGS | METH_KEYWORDS, "\n"
1017 "Build a new NetBSD guest OS.\n"
1018 " dom [int]: Identifier of domain to build into.\n"
1019 " image [str]: Name of kernel image file. May be gzipped.\n"
1020 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1021 "Returns: [int] 0 on success; -1 on error.\n" },
1023 { "bvtsched_global_set",
1024 (PyCFunction)pyxc_bvtsched_global_set,
1025 METH_VARARGS | METH_KEYWORDS, "\n"
1026 "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
1027 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
1028 "Returns: [int] 0 on success; -1 on error.\n" },
1030 { "bvtsched_global_get",
1031 (PyCFunction)pyxc_bvtsched_global_get,
1032 METH_KEYWORDS, "\n"
1033 "Get global tuning parameters for BVT scheduler.\n"
1034 "Returns: [dict]:\n"
1035 " ctx_allow [int]: context switch allowance\n" },
1037 { "bvtsched_domain_set",
1038 (PyCFunction)pyxc_bvtsched_domain_set,
1039 METH_VARARGS | METH_KEYWORDS, "\n"
1040 "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
1041 " dom [int]: Identifier of domain to be tuned.\n"
1042 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
1043 " warp [int]: How far to warp domain's EVT on unblock.\n"
1044 " warpl [int]: How long the domain can run warped.\n"
1045 " warpu [int]: How long before the domain can warp again.\n\n"
1046 "Returns: [int] 0 on success; -1 on error.\n" },
1048 { "bvtsched_domain_get",
1049 (PyCFunction)pyxc_bvtsched_domain_get,
1050 METH_KEYWORDS, "\n"
1051 "Get per-domain tuning parameters under the BVT scheduler.\n"
1052 " dom [int]: Identifier of domain to be queried.\n"
1053 "Returns [dict]:\n"
1054 " domain [int]: Domain ID.\n"
1055 " mcuadv [long]: MCU Advance.\n"
1056 " warp [long]: Warp.\n"
1057 " warpu [long]: Unwarp requirement.\n"
1058 " warpl [long]: Warp limit,\n"
1059 },
1061 { "fbvtsched_global_set",
1062 (PyCFunction)pyxc_fbvtsched_global_set,
1063 METH_VARARGS | METH_KEYWORDS, "\n"
1064 "Set global tuning parameters for Fair Borrowed Virtual Time scheduler.\n"
1065 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
1066 "Returns: [int] 0 on success; -1 on error.\n" },
1068 { "fbvtsched_global_get",
1069 (PyCFunction)pyxc_fbvtsched_global_get,
1070 METH_KEYWORDS, "\n"
1071 "Get global tuning parameters for FBVT scheduler.\n"
1072 "Returns: [dict]:\n"
1073 " ctx_allow [int]: context switch allowance\n" },
1075 { "fbvtsched_domain_set",
1076 (PyCFunction)pyxc_fbvtsched_domain_set,
1077 METH_VARARGS | METH_KEYWORDS, "\n"
1078 "Set per-domain tuning parameters for Fair Borrowed Virtual Time scheduler.\n"
1079 " dom [int]: Identifier of domain to be tuned.\n"
1080 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
1081 " warp [int]: How far to warp domain's EVT on unblock.\n"
1082 " warpl [int]: How long the domain can run warped.\n"
1083 " warpu [int]: How long before the domain can warp again.\n\n"
1084 "Returns: [int] 0 on success; -1 on error.\n" },
1086 { "fbvtsched_domain_get",
1087 (PyCFunction)pyxc_fbvtsched_domain_get,
1088 METH_KEYWORDS, "\n"
1089 "Get per-domain tuning parameters under the FBVT scheduler.\n"
1090 " dom [int]: Identifier of domain to be queried.\n"
1091 "Returns [dict]:\n"
1092 " domain [int]: Domain ID.\n"
1093 " mcuadv [long]: MCU Advance.\n"
1094 " warp [long]: Warp.\n"
1095 " warpu [long]: Unwarp requirement.\n"
1096 " warpl [long]: Warp limit,\n"
1097 },
1099 { "atropos_domain_set",
1100 (PyCFunction)pyxc_atropos_domain_set,
1101 METH_KEYWORDS, "\n"
1102 "Set the scheduling parameters for a domain when running with Atropos.\n"
1103 " dom [int]: domain to set\n"
1104 " period [long]: domain's scheduling period\n"
1105 " slice [long]: domain's slice per period\n"
1106 " latency [long]: wakeup latency hint\n"
1107 " xtratime [int]: boolean\n"
1108 "Returns: [int] 0 on success; -1 on error.\n" },
1110 { "atropos_domain_get",
1111 (PyCFunction)pyxc_atropos_domain_get,
1112 METH_KEYWORDS, "\n"
1113 "Get the current scheduling parameters for a domain when running with\n"
1114 "the Atropos scheduler."
1115 " dom [int]: domain to query\n"
1116 "Returns: [dict]\n"
1117 " domain [int]: domain ID\n"
1118 " period [long]: scheduler period\n"
1119 " slice [long]: CPU reservation per period\n"
1120 " latency [long]: unblocking latency hint\n"
1121 " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
1123 { "rrobin_global_set",
1124 (PyCFunction)pyxc_rrobin_global_set,
1125 METH_KEYWORDS, "\n"
1126 "Set Round Robin scheduler slice.\n"
1127 " slice [long]: Round Robin scheduler slice\n"
1128 "Returns: [int] 0 on success, throws an exception on failure\n" },
1130 { "rrobin_global_get",
1131 (PyCFunction)pyxc_rrobin_global_get,
1132 METH_KEYWORDS, "\n"
1133 "Get Round Robin scheduler settings\n"
1134 "Returns [dict]:\n"
1135 " slice [long]: Scheduler time slice.\n" },
1137 { "evtchn_bind_interdomain",
1138 (PyCFunction)pyxc_evtchn_bind_interdomain,
1139 METH_VARARGS | METH_KEYWORDS, "\n"
1140 "Open an event channel between two domains.\n"
1141 " dom1 [int, SELF]: First domain to be connected.\n"
1142 " dom2 [int, SELF]: Second domain to be connected.\n\n"
1143 "Returns: [dict] dictionary is empty on failure.\n"
1144 " port1 [int]: Port-id for endpoint at dom1.\n"
1145 " port2 [int]: Port-id for endpoint at dom2.\n" },
1147 { "evtchn_bind_virq",
1148 (PyCFunction)pyxc_evtchn_bind_virq,
1149 METH_VARARGS | METH_KEYWORDS, "\n"
1150 "Bind an event channel to the specified VIRQ.\n"
1151 " virq [int]: VIRQ to bind.\n\n"
1152 "Returns: [int] Bound event-channel port.\n" },
1154 { "evtchn_close",
1155 (PyCFunction)pyxc_evtchn_close,
1156 METH_VARARGS | METH_KEYWORDS, "\n"
1157 "Close an event channel.\n"
1158 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1159 " port [int]: Port-id of one endpoint of the channel.\n\n"
1160 "Returns: [int] 0 on success; -1 on error.\n" },
1162 { "evtchn_send",
1163 (PyCFunction)pyxc_evtchn_send,
1164 METH_VARARGS | METH_KEYWORDS, "\n"
1165 "Send an event along a locally-connected event channel.\n"
1166 " port [int]: Port-id of a local channel endpoint.\n\n"
1167 "Returns: [int] 0 on success; -1 on error.\n" },
1169 { "evtchn_status",
1170 (PyCFunction)pyxc_evtchn_status,
1171 METH_VARARGS | METH_KEYWORDS, "\n"
1172 "Query the status of an event channel.\n"
1173 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1174 " port [int]: Port-id of one endpoint of the channel.\n\n"
1175 "Returns: [dict] dictionary is empty on failure.\n"
1176 " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
1177 " or 'virq'.\n"
1178 "The following are returned if 'status' is 'interdomain':\n"
1179 " dom [int]: Dom-id of remote endpoint.\n"
1180 " port [int]: Port-id of remote endpoint.\n"
1181 "The following are returned if 'status' is 'pirq' or 'virq':\n"
1182 " irq [int]: IRQ number.\n" },
1184 { "physdev_pci_access_modify",
1185 (PyCFunction)pyxc_physdev_pci_access_modify,
1186 METH_VARARGS | METH_KEYWORDS, "\n"
1187 "Allow a domain access to a PCI device\n"
1188 " dom [int]: Identifier of domain to be allowed access.\n"
1189 " bus [int]: PCI bus\n"
1190 " dev [int]: PCI slot\n"
1191 " func [int]: PCI function\n"
1192 " enable [int]: Non-zero means enable access; else disable access\n\n"
1193 "Returns: [int] 0 on success; -1 on error.\n" },
1195 { "readconsolering",
1196 (PyCFunction)pyxc_readconsolering,
1197 METH_VARARGS | METH_KEYWORDS, "\n"
1198 "Read Xen's console ring.\n"
1199 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1200 "Returns: [str] string is empty on failure.\n" },
1202 { "physinfo",
1203 (PyCFunction)pyxc_physinfo,
1204 METH_VARARGS, "\n"
1205 "Get information about the physical host machine\n"
1206 "Returns [dict]: information about the hardware"
1207 " [None]: on failure.\n" },
1209 { "shadow_control",
1210 (PyCFunction)pyxc_shadow_control,
1211 METH_VARARGS | METH_KEYWORDS, "\n"
1212 "Set parameter for shadow pagetable interface\n"
1213 " dom [int]: Identifier of domain.\n"
1214 " op [int, 0]: operation\n\n"
1215 "Returns: [int] 0 on success; -1 on error.\n" },
1217 { "domain_setname",
1218 (PyCFunction)pyxc_domain_setname,
1219 METH_VARARGS | METH_KEYWORDS, "\n"
1220 "Set domain informative textual name\n"
1221 " dom [int]: Identifier of domain.\n"
1222 " name [str]: Text string.\n\n"
1223 "Returns: [int] 0 on success; -1 on error.\n" },
1225 { "domain_setmaxmem",
1226 (PyCFunction)pyxc_domain_setmaxmem,
1227 METH_VARARGS | METH_KEYWORDS, "\n"
1228 "Set a domain's memory limit\n"
1229 " dom [int]: Identifier of domain.\n"
1230 " max_memkb [long]: .\n"
1231 "Returns: [int] 0 on success; -1 on error.\n" },
1233 { NULL, NULL, 0, NULL }
1234 };
1237 /*
1238 * Definitions for the 'Xc' module wrapper.
1239 */
1241 staticforward PyTypeObject PyXcType;
1243 static PyObject *PyXc_new(PyObject *self, PyObject *args)
1245 XcObject *xc;
1247 if ( !PyArg_ParseTuple(args, ":new") )
1248 return NULL;
1250 xc = PyObject_New(XcObject, &PyXcType);
1252 if ( (xc->xc_handle = xc_interface_open()) == -1 )
1254 PyObject_Del((PyObject *)xc);
1255 return PyErr_SetFromErrno(xc_error);
1258 return (PyObject *)xc;
1261 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1263 return Py_FindMethod(pyxc_methods, obj, name);
1266 static void PyXc_dealloc(PyObject *self)
1268 XcObject *xc = (XcObject *)self;
1269 (void)xc_interface_close(xc->xc_handle);
1270 PyObject_Del(self);
1273 static PyTypeObject PyXcType = {
1274 PyObject_HEAD_INIT(&PyType_Type)
1275 0,
1276 "Xc",
1277 sizeof(XcObject),
1278 0,
1279 PyXc_dealloc, /* tp_dealloc */
1280 NULL, /* tp_print */
1281 PyXc_getattr, /* tp_getattr */
1282 NULL, /* tp_setattr */
1283 NULL, /* tp_compare */
1284 NULL, /* tp_repr */
1285 NULL, /* tp_as_number */
1286 NULL, /* tp_as_sequence */
1287 NULL, /* tp_as_mapping */
1288 NULL /* tp_hash */
1289 };
1291 static PyMethodDef PyXc_methods[] = {
1292 { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
1293 { NULL, NULL, 0, NULL }
1294 };
1296 PyMODINIT_FUNC initxc(void)
1298 PyObject *m, *d;
1300 m = Py_InitModule(XENPKG, PyXc_methods);
1302 d = PyModule_GetDict(m);
1303 xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
1304 PyDict_SetItemString(d, "error", xc_error);
1306 zero = PyInt_FromLong(0);