debuggers.hg

view tools/python/xen/lowlevel/xc/xc.c @ 4647:9c88ba91d330

bitkeeper revision 1.1346.1.1 (42670505dNhgnJm5dQD81pCalXMZgw)

manual merge
author iap10@freefall.cl.cam.ac.uk
date Thu Apr 21 01:42:29 2005 +0000 (2005-04-21)
parents 7fc6eac6da3a 3dc193a9786a
children 86285c9c18c1
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"
19 #include "linux_boot_params.h"
21 /* Needed for Python versions earlier than 2.3. */
22 #ifndef PyMODINIT_FUNC
23 #define PyMODINIT_FUNC DL_EXPORT(void)
24 #endif
26 #define XENPKG "xen.lowlevel.xc"
28 static PyObject *xc_error, *zero;
30 typedef struct {
31 PyObject_HEAD;
32 int xc_handle;
33 } XcObject;
35 /*
36 * Definitions for the 'xc' object type.
37 */
39 static PyObject *pyxc_domain_create(PyObject *self,
40 PyObject *args,
41 PyObject *kwds)
42 {
43 XcObject *xc = (XcObject *)self;
45 unsigned int mem_kb = 0;
46 int cpu = -1;
47 float cpu_weight = 1;
48 u32 dom = 0;
49 int ret;
51 static char *kwd_list[] = { "dom", "mem_kb", "cpu", "cpu_weight", NULL };
53 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiif", kwd_list,
54 &dom, &mem_kb, &cpu, &cpu_weight))
55 return NULL;
57 if ( (ret = xc_domain_create(
58 xc->xc_handle, mem_kb, cpu, cpu_weight, &dom)) < 0 )
59 return PyErr_SetFromErrno(xc_error);
61 return PyInt_FromLong(dom);
62 }
64 static PyObject *pyxc_domain_pause(PyObject *self,
65 PyObject *args,
66 PyObject *kwds)
67 {
68 XcObject *xc = (XcObject *)self;
70 u32 dom;
72 static char *kwd_list[] = { "dom", NULL };
74 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
75 return NULL;
77 if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
78 return PyErr_SetFromErrno(xc_error);
80 Py_INCREF(zero);
81 return zero;
82 }
84 static PyObject *pyxc_domain_unpause(PyObject *self,
85 PyObject *args,
86 PyObject *kwds)
87 {
88 XcObject *xc = (XcObject *)self;
90 u32 dom;
92 static char *kwd_list[] = { "dom", NULL };
94 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
95 return NULL;
97 if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
98 return PyErr_SetFromErrno(xc_error);
100 Py_INCREF(zero);
101 return zero;
102 }
104 static PyObject *pyxc_domain_destroy(PyObject *self,
105 PyObject *args,
106 PyObject *kwds)
107 {
108 XcObject *xc = (XcObject *)self;
110 u32 dom;
112 static char *kwd_list[] = { "dom", NULL };
114 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
115 return NULL;
117 if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
118 return PyErr_SetFromErrno(xc_error);
120 Py_INCREF(zero);
121 return zero;
122 }
124 static PyObject *pyxc_domain_pincpu(PyObject *self,
125 PyObject *args,
126 PyObject *kwds)
127 {
128 XcObject *xc = (XcObject *)self;
130 u32 dom;
131 int cpu = -1;
133 static char *kwd_list[] = { "dom", "cpu", NULL };
135 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
136 &dom, &cpu) )
137 return NULL;
139 if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
140 return PyErr_SetFromErrno(xc_error);
142 Py_INCREF(zero);
143 return zero;
144 }
146 static PyObject *pyxc_domain_getinfo(PyObject *self,
147 PyObject *args,
148 PyObject *kwds)
149 {
150 XcObject *xc = (XcObject *)self;
151 PyObject *list;
153 u32 first_dom = 0;
154 int max_doms = 1024, nr_doms, i;
155 xc_dominfo_t *info;
157 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
159 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
160 &first_dom, &max_doms) )
161 return NULL;
163 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
164 return PyErr_NoMemory();
166 nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
168 list = PyList_New(nr_doms);
169 for ( i = 0 ; i < nr_doms; i++ )
170 {
171 PyList_SetItem(
172 list, i,
173 Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
174 ",s:l,s:L,s:l,s:i}",
175 "dom", info[i].domid,
176 "cpu", info[i].cpu,
177 "dying", info[i].dying,
178 "crashed", info[i].crashed,
179 "shutdown", info[i].shutdown,
180 "paused", info[i].paused,
181 "blocked", info[i].blocked,
182 "running", info[i].running,
183 "mem_kb", info[i].nr_pages*4,
184 "cpu_time", info[i].cpu_time,
185 "maxmem_kb", info[i].max_memkb,
186 "shutdown_reason", info[i].shutdown_reason
187 ));
188 }
190 free(info);
192 return list;
193 }
195 static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file)
196 {
197 int rc = -1;
198 int fd = -1;
199 int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
200 int open_mode = 0644;
202 printf("%s>\n", __FUNCTION__);
204 if ( (fd = open(state_file, open_flags, open_mode)) < 0 )
205 {
206 xcio_perror(ctxt, "Could not open file for writing");
207 goto exit;
208 }
210 printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
212 /* Compression rate 1: we want speed over compression.
213 * We're mainly going for those zero pages, after all.
214 */
215 ctxt->io = gzip_stream_fdopen(fd, "wb1");
216 if ( ctxt->io == NULL )
217 {
218 xcio_perror(ctxt, "Could not allocate compression state");
219 goto exit;
220 }
222 printf("%s> xc_linux_save...\n", __FUNCTION__);
224 rc = xc_linux_save(xc->xc_handle, ctxt);
226 exit:
227 if ( ctxt->io != NULL )
228 IOStream_close(ctxt->io);
229 if ( fd >= 0 )
230 close(fd);
231 unlink(state_file);
232 printf("%s> rc=%d\n", __FUNCTION__, rc);
233 return rc;
234 }
236 static PyObject *pyxc_linux_save(PyObject *self,
237 PyObject *args,
238 PyObject *kwds)
239 {
240 XcObject *xc = (XcObject *)self;
242 char *state_file;
243 int progress = 1, debug = 0;
244 PyObject *val = NULL;
245 int rc = -1;
246 XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
248 static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
250 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list,
251 &ioctxt.domain,
252 &state_file,
253 &ioctxt.vmconfig,
254 &progress,
255 &debug) )
256 goto exit;
258 ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
260 if ( progress )
261 ioctxt.flags |= XCFLAGS_VERBOSE;
262 if ( debug )
263 ioctxt.flags |= XCFLAGS_DEBUG;
265 if ( (state_file == NULL) || (state_file[0] == '\0') )
266 goto exit;
268 rc = file_save(xc, &ioctxt, state_file);
269 if ( rc != 0 )
270 {
271 PyErr_SetFromErrno(xc_error);
272 goto exit;
273 }
275 Py_INCREF(zero);
276 val = zero;
278 exit:
279 return val;
280 }
283 static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file)
284 {
285 int rc = -1;
287 ioctxt->io = gzip_stream_fopen(state_file, "rb");
288 if ( ioctxt->io == NULL )
289 {
290 xcio_perror(ioctxt, "Could not open file for reading");
291 return rc;
292 }
294 rc = xc_linux_restore(xc->xc_handle, ioctxt);
296 IOStream_close(ioctxt->io);
298 return rc;
299 }
301 static PyObject *pyxc_linux_restore(PyObject *self,
302 PyObject *args,
303 PyObject *kwds)
304 {
305 XcObject *xc = (XcObject *)self;
306 char *state_file;
307 int progress = 1, debug = 0;
308 PyObject *val = NULL;
309 XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
310 int rc =-1;
312 static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
314 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s|ii", kwd_list,
315 &state_file,
316 &progress,
317 &debug) )
318 goto exit;
320 if ( progress )
321 ioctxt.flags |= XCFLAGS_VERBOSE;
322 if ( debug )
323 ioctxt.flags |= XCFLAGS_DEBUG;
325 if ( (state_file == NULL) || (state_file[0] == '\0') )
326 goto exit;
328 rc = file_restore(xc, &ioctxt, state_file);
329 if ( rc != 0 )
330 {
331 PyErr_SetFromErrno(xc_error);
332 goto exit;
333 }
335 val = Py_BuildValue("{s:i,s:s}",
336 "dom", ioctxt.domain,
337 "vmconfig", ioctxt.vmconfig);
339 exit:
340 return val;
341 }
343 static PyObject *pyxc_linux_build(PyObject *self,
344 PyObject *args,
345 PyObject *kwds)
346 {
347 XcObject *xc = (XcObject *)self;
349 u32 dom;
350 char *image, *ramdisk = NULL, *cmdline = "";
351 int control_evtchn, flags = 0, vcpus = 1;
353 static char *kwd_list[] = { "dom", "control_evtchn",
354 "image", "ramdisk", "cmdline", "flags", "vcpus",
355 NULL };
357 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssii", kwd_list,
358 &dom, &control_evtchn,
359 &image, &ramdisk, &cmdline, &flags, &vcpus) )
360 return NULL;
362 if ( xc_linux_build(xc->xc_handle, dom, image,
363 ramdisk, cmdline, control_evtchn, flags, vcpus) != 0 )
364 return PyErr_SetFromErrno(xc_error);
366 Py_INCREF(zero);
367 return zero;
368 }
370 static PyObject *pyxc_plan9_build(PyObject *self,
371 PyObject *args,
372 PyObject *kwds)
373 {
374 XcObject *xc = (XcObject *)self;
376 u32 dom;
377 char *image, *ramdisk = NULL, *cmdline = "";
378 int control_evtchn, flags = 0;
380 static char *kwd_list[] = { "dom", "control_evtchn",
381 "image", "ramdisk", "cmdline", "flags",
382 NULL };
384 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
385 &dom, &control_evtchn,
386 &image, &ramdisk, &cmdline, &flags) )
387 return NULL;
389 if ( xc_plan9_build(xc->xc_handle, dom, image,
390 cmdline, control_evtchn, flags) != 0 )
391 return PyErr_SetFromErrno(xc_error);
393 Py_INCREF(zero);
394 return zero;
395 }
397 static PyObject *pyxc_vmx_build(PyObject *self,
398 PyObject *args,
399 PyObject *kwds)
400 {
401 XcObject *xc = (XcObject *)self;
403 u32 dom;
404 char *image, *ramdisk = NULL, *cmdline = "";
405 PyObject *memmap;
406 int control_evtchn, flags = 0;
407 int numItems, i;
408 int memsize;
409 struct mem_map mem_map;
411 static char *kwd_list[] = { "dom", "control_evtchn",
412 "memsize",
413 "image", "memmap",
414 "ramdisk", "cmdline", "flags",
415 NULL };
417 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiisO!|ssi", kwd_list,
418 &dom, &control_evtchn,
419 &memsize,
420 &image, &PyList_Type, &memmap,
421 &ramdisk, &cmdline, &flags) )
422 return NULL;
424 memset(&mem_map, 0, sizeof(mem_map));
425 /* Parse memmap */
427 /* get the number of lines passed to us */
428 numItems = PyList_Size(memmap) - 1; /* removing the line
429 containing "memmap" */
430 printf ("numItems: %d\n", numItems);
431 mem_map.nr_map = numItems;
433 /* should raise an error here. */
434 if (numItems < 0) return NULL; /* Not a list */
436 /* iterate over items of the list, grabbing ranges and parsing them */
437 for (i = 1; i <= numItems; i++) { // skip over "memmap"
438 PyObject *item, *f1, *f2, *f3, *f4;
439 int numFields;
440 unsigned long lf1, lf2, lf3, lf4;
441 char *sf1, *sf2;
443 /* grab the string object from the next element of the list */
444 item = PyList_GetItem(memmap, i); /* Can't fail */
446 /* get the number of lines passed to us */
447 numFields = PyList_Size(item);
449 if (numFields != 4)
450 return NULL;
452 f1 = PyList_GetItem(item, 0);
453 f2 = PyList_GetItem(item, 1);
454 f3 = PyList_GetItem(item, 2);
455 f4 = PyList_GetItem(item, 3);
457 /* Convert objects to strings/longs */
458 sf1 = PyString_AsString(f1);
459 sf2 = PyString_AsString(f2);
460 lf3 = PyLong_AsLong(f3);
461 lf4 = PyLong_AsLong(f4);
462 if ( sscanf(sf1, "%lx", &lf1) != 1 )
463 return NULL;
464 if ( sscanf(sf2, "%lx", &lf2) != 1 )
465 return NULL;
467 mem_map.map[i-1].addr = lf1;
468 mem_map.map[i-1].size = lf2 - lf1;
469 mem_map.map[i-1].type = lf3;
470 mem_map.map[i-1].caching_attr = lf4;
471 }
473 if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, &mem_map,
474 ramdisk, cmdline, control_evtchn, flags) != 0 )
475 return PyErr_SetFromErrno(xc_error);
477 Py_INCREF(zero);
478 return zero;
479 }
481 static PyObject *pyxc_bvtsched_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_bvtsched_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_bvtsched_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_bvtsched_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_bvtsched_domain_set(PyObject *self,
519 PyObject *args,
520 PyObject *kwds)
521 {
522 XcObject *xc = (XcObject *)self;
524 u32 dom;
525 u32 mcuadv;
526 int warpback;
527 s32 warpvalue;
528 long long warpl;
529 long long warpu;
531 static char *kwd_list[] = { "dom", "mcuadv", "warpback", "warpvalue",
532 "warpl", "warpu", NULL };
534 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiiLL", kwd_list,
535 &dom, &mcuadv, &warpback, &warpvalue,
536 &warpl, &warpu) )
537 return NULL;
539 if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
540 warpback, warpvalue, warpl, warpu) != 0 )
541 return PyErr_SetFromErrno(xc_error);
543 Py_INCREF(zero);
544 return zero;
545 }
547 static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
548 PyObject *args,
549 PyObject *kwds)
550 {
551 XcObject *xc = (XcObject *)self;
552 u32 dom;
553 u32 mcuadv;
554 int warpback;
555 s32 warpvalue;
556 long long warpl;
557 long long warpu;
559 static char *kwd_list[] = { "dom", NULL };
561 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
562 return NULL;
564 if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warpback,
565 &warpvalue, &warpl, &warpu) != 0 )
566 return PyErr_SetFromErrno(xc_error);
568 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
569 "domain", dom,
570 "mcuadv", mcuadv,
571 "warpback", warpback,
572 "warpvalue", warpvalue,
573 "warpl", warpl,
574 "warpu", warpu);
575 }
577 static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
578 PyObject *args,
579 PyObject *kwds)
580 {
581 XcObject *xc = (XcObject *)self;
583 u32 dom;
584 int port;
586 static char *kwd_list[] = { "dom", NULL };
588 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
589 return NULL;
591 if ( xc_evtchn_alloc_unbound(xc->xc_handle, dom, &port) != 0 )
592 return PyErr_SetFromErrno(xc_error);
594 return PyInt_FromLong(port);
595 }
597 static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
598 PyObject *args,
599 PyObject *kwds)
600 {
601 XcObject *xc = (XcObject *)self;
603 u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
604 int port1 = 0, port2 = 0;
606 static char *kwd_list[] = { "dom1", "dom2", "port1", "port2", NULL };
608 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiii", kwd_list,
609 &dom1, &dom2, &port1, &port2) )
610 return NULL;
612 if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
613 dom2, &port1, &port2) != 0 )
614 return PyErr_SetFromErrno(xc_error);
616 return Py_BuildValue("{s:i,s:i}",
617 "port1", port1,
618 "port2", port2);
619 }
621 static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
622 PyObject *args,
623 PyObject *kwds)
624 {
625 XcObject *xc = (XcObject *)self;
627 int virq, port;
629 static char *kwd_list[] = { "virq", NULL };
631 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
632 return NULL;
634 if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
635 return PyErr_SetFromErrno(xc_error);
637 return PyInt_FromLong(port);
638 }
640 static PyObject *pyxc_evtchn_close(PyObject *self,
641 PyObject *args,
642 PyObject *kwds)
643 {
644 XcObject *xc = (XcObject *)self;
646 u32 dom = DOMID_SELF;
647 int port;
649 static char *kwd_list[] = { "port", "dom", NULL };
651 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
652 &port, &dom) )
653 return NULL;
655 if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
656 return PyErr_SetFromErrno(xc_error);
658 Py_INCREF(zero);
659 return zero;
660 }
662 static PyObject *pyxc_evtchn_send(PyObject *self,
663 PyObject *args,
664 PyObject *kwds)
665 {
666 XcObject *xc = (XcObject *)self;
668 int port;
670 static char *kwd_list[] = { "port", NULL };
672 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
673 return NULL;
675 if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
676 return PyErr_SetFromErrno(xc_error);
678 Py_INCREF(zero);
679 return zero;
680 }
682 static PyObject *pyxc_evtchn_status(PyObject *self,
683 PyObject *args,
684 PyObject *kwds)
685 {
686 XcObject *xc = (XcObject *)self;
687 PyObject *dict;
689 u32 dom = DOMID_SELF;
690 int port, ret;
691 xc_evtchn_status_t status;
693 static char *kwd_list[] = { "port", "dom", NULL };
695 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
696 &port, &dom) )
697 return NULL;
699 ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
700 if ( ret != 0 )
701 return PyErr_SetFromErrno(xc_error);
703 switch ( status.status )
704 {
705 case EVTCHNSTAT_closed:
706 dict = Py_BuildValue("{s:s}",
707 "status", "closed");
708 break;
709 case EVTCHNSTAT_unbound:
710 dict = Py_BuildValue("{s:s}",
711 "status", "unbound");
712 break;
713 case EVTCHNSTAT_interdomain:
714 dict = Py_BuildValue("{s:s,s:i,s:i}",
715 "status", "interdomain",
716 "dom", status.u.interdomain.dom,
717 "port", status.u.interdomain.port);
718 break;
719 case EVTCHNSTAT_pirq:
720 dict = Py_BuildValue("{s:s,s:i}",
721 "status", "pirq",
722 "irq", status.u.pirq);
723 break;
724 case EVTCHNSTAT_virq:
725 dict = Py_BuildValue("{s:s,s:i}",
726 "status", "virq",
727 "irq", status.u.virq);
728 break;
729 default:
730 dict = Py_BuildValue("{}");
731 break;
732 }
734 return dict;
735 }
737 static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
738 PyObject *args,
739 PyObject *kwds)
740 {
741 XcObject *xc = (XcObject *)self;
742 u32 dom;
743 int bus, dev, func, enable, ret;
745 static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
747 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
748 &dom, &bus, &dev, &func, &enable) )
749 return NULL;
751 ret = xc_physdev_pci_access_modify(
752 xc->xc_handle, dom, bus, dev, func, enable);
753 if ( ret != 0 )
754 return PyErr_SetFromErrno(xc_error);
756 Py_INCREF(zero);
757 return zero;
758 }
760 static PyObject *pyxc_readconsolering(PyObject *self,
761 PyObject *args,
762 PyObject *kwds)
763 {
764 XcObject *xc = (XcObject *)self;
766 unsigned int clear = 0;
767 char str[32768];
768 int ret;
770 static char *kwd_list[] = { "clear", NULL };
772 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
773 return NULL;
775 ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
776 if ( ret < 0 )
777 return PyErr_SetFromErrno(xc_error);
779 return PyString_FromStringAndSize(str, ret);
780 }
782 static PyObject *pyxc_physinfo(PyObject *self,
783 PyObject *args,
784 PyObject *kwds)
785 {
786 XcObject *xc = (XcObject *)self;
787 xc_physinfo_t info;
789 if ( !PyArg_ParseTuple(args, "") )
790 return NULL;
792 if ( xc_physinfo(xc->xc_handle, &info) != 0 )
793 return PyErr_SetFromErrno(xc_error);
795 return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
796 "ht_per_core", info.ht_per_core,
797 "cores", info.cores,
798 "total_pages", info.total_pages,
799 "free_pages", info.free_pages,
800 "cpu_khz", info.cpu_khz);
801 }
803 static PyObject *pyxc_sedf_domain_set(PyObject *self,
804 PyObject *args,
805 PyObject *kwds)
806 {
807 XcObject *xc = (XcObject *)self;
808 u32 domid;
809 u64 period, slice, latency;
810 u16 extratime, weight;
811 static char *kwd_list[] = { "dom", "period", "slice", "latency", "extratime", "weight",NULL };
813 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list, &domid,
814 &period, &slice, &latency, &extratime, &weight) )
815 return NULL;
816 if ( xc_sedf_domain_set(xc->xc_handle, domid, period, slice, latency, extratime,weight) != 0 )
817 return PyErr_SetFromErrno(xc_error);
819 Py_INCREF(zero);
820 return zero;
821 }
823 static PyObject *pyxc_sedf_domain_get(PyObject *self,
824 PyObject *args,
825 PyObject *kwds)
826 {
827 XcObject *xc = (XcObject *)self;
828 u32 domid;
829 u64 period, slice,latency;
830 u16 weight, extratime;
832 static char *kwd_list[] = { "dom", NULL };
834 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
835 return NULL;
837 if ( xc_sedf_domain_get( xc->xc_handle, domid, &period,
838 &slice,&latency,&extratime,&weight) )
839 return PyErr_SetFromErrno(xc_error);
841 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
842 "domain", domid,
843 "period", period,
844 "slice", slice,
845 "latency", latency,
846 "extratime", extratime);
847 }
849 static PyObject *pyxc_shadow_control(PyObject *self,
850 PyObject *args,
851 PyObject *kwds)
852 {
853 XcObject *xc = (XcObject *)self;
855 u32 dom;
856 int op=0;
858 static char *kwd_list[] = { "dom", "op", NULL };
860 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
861 &dom, &op) )
862 return NULL;
864 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
865 return PyErr_SetFromErrno(xc_error);
867 Py_INCREF(zero);
868 return zero;
869 }
871 static PyObject *pyxc_domain_setmaxmem(PyObject *self,
872 PyObject *args,
873 PyObject *kwds)
874 {
875 XcObject *xc = (XcObject *)self;
877 u32 dom;
878 unsigned long maxmem_kb;
880 static char *kwd_list[] = { "dom", "maxmem_kb", NULL };
882 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
883 &dom, &maxmem_kb) )
884 return NULL;
886 if ( xc_domain_setmaxmem(xc->xc_handle, dom, maxmem_kb) != 0 )
887 return PyErr_SetFromErrno(xc_error);
889 Py_INCREF(zero);
890 return zero;
891 }
894 static PyMethodDef pyxc_methods[] = {
895 { "domain_create",
896 (PyCFunction)pyxc_domain_create,
897 METH_VARARGS | METH_KEYWORDS, "\n"
898 "Create a new domain.\n"
899 " dom [int, 0]: Domain identifier to use (allocated if zero).\n"
900 " mem_kb [int, 0]: Memory allocation, in kilobytes.\n"
901 "Returns: [int] new domain identifier; -1 on error.\n" },
903 { "domain_pause",
904 (PyCFunction)pyxc_domain_pause,
905 METH_VARARGS | METH_KEYWORDS, "\n"
906 "Temporarily pause execution of a domain.\n"
907 " dom [int]: Identifier of domain to be paused.\n\n"
908 "Returns: [int] 0 on success; -1 on error.\n" },
910 { "domain_unpause",
911 (PyCFunction)pyxc_domain_unpause,
912 METH_VARARGS | METH_KEYWORDS, "\n"
913 "(Re)start execution of a domain.\n"
914 " dom [int]: Identifier of domain to be unpaused.\n\n"
915 "Returns: [int] 0 on success; -1 on error.\n" },
917 { "domain_destroy",
918 (PyCFunction)pyxc_domain_destroy,
919 METH_VARARGS | METH_KEYWORDS, "\n"
920 "Destroy a domain.\n"
921 " dom [int]: Identifier of domain to be destroyed.\n\n"
922 "Returns: [int] 0 on success; -1 on error.\n" },
924 { "domain_pincpu",
925 (PyCFunction)pyxc_domain_pincpu,
926 METH_VARARGS | METH_KEYWORDS, "\n"
927 "Pin a domain to a specified CPU.\n"
928 " dom [int]: Identifier of domain to be pinned.\n"
929 " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
930 "Returns: [int] 0 on success; -1 on error.\n" },
932 { "domain_getinfo",
933 (PyCFunction)pyxc_domain_getinfo,
934 METH_VARARGS | METH_KEYWORDS, "\n"
935 "Get information regarding a set of domains, in increasing id order.\n"
936 " first_dom [int, 0]: First domain to retrieve info about.\n"
937 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
938 " about.\n\n"
939 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
940 " parameter then there was an error, or the end of the\n"
941 " domain-id space was reached.\n"
942 " dom [int]: Identifier of domain to which this info pertains\n"
943 " cpu [int]: CPU to which this domain is bound\n"
944 " dying [int]: Bool - is the domain dying?\n"
945 " crashed [int]: Bool - has the domain crashed?\n"
946 " shutdown [int]: Bool - has the domain shut itself down?\n"
947 " paused [int]: Bool - is the domain paused by control software?\n"
948 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
949 " running [int]: Bool - is the domain currently running?\n"
950 " mem_kb [int]: Memory reservation, in kilobytes\n"
951 " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
952 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
953 " shutdown_reason [int]: Numeric code from guest OS, explaining "
954 "reason why it shut itself down.\n" },
956 { "linux_save",
957 (PyCFunction)pyxc_linux_save,
958 METH_VARARGS | METH_KEYWORDS, "\n"
959 "Save the CPU and memory state of a Linux guest OS.\n"
960 " dom [int]: Identifier of domain to be saved.\n"
961 " state_file [str]: Name of state file. Must not currently exist.\n"
962 " progress [int, 1]: Bool - display a running progress indication?\n\n"
963 "Returns: [int] 0 on success; -1 on error.\n" },
964 { "plan9_build",
965 (PyCFunction)pyxc_plan9_build,
966 METH_VARARGS | METH_KEYWORDS, "\n"
967 "Build a new Plan 9 guest OS.\n"
968 " dom [long]: Identifier of domain to build into.\n"
969 " image [str]: Name of kernel image file. May be gzipped.\n"
970 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
971 "Returns: [int] 0 on success; -1 on error.\n" },
973 { "linux_restore",
974 (PyCFunction)pyxc_linux_restore,
975 METH_VARARGS | METH_KEYWORDS, "\n"
976 "Restore the CPU and memory state of a Linux guest OS.\n"
977 " state_file [str]: Name of state file. Must not currently exist.\n"
978 " progress [int, 1]: Bool - display a running progress indication?\n\n"
979 "Returns: [int] new domain identifier on success; -1 on error.\n" },
981 { "linux_build",
982 (PyCFunction)pyxc_linux_build,
983 METH_VARARGS | METH_KEYWORDS, "\n"
984 "Build a new Linux guest OS.\n"
985 " dom [int]: Identifier of domain to build into.\n"
986 " image [str]: Name of kernel image file. May be gzipped.\n"
987 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
988 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
989 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
990 "Returns: [int] 0 on success; -1 on error.\n" },
992 { "vmx_build",
993 (PyCFunction)pyxc_vmx_build,
994 METH_VARARGS | METH_KEYWORDS, "\n"
995 "Build a new Linux guest OS.\n"
996 " dom [int]: Identifier of domain to build into.\n"
997 " image [str]: Name of kernel image file. May be gzipped.\n"
998 " memmap [str]: Memory map.\n\n"
999 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
1000 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1001 "Returns: [int] 0 on success; -1 on error.\n" },
1003 { "bvtsched_global_set",
1004 (PyCFunction)pyxc_bvtsched_global_set,
1005 METH_VARARGS | METH_KEYWORDS, "\n"
1006 "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
1007 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
1008 "Returns: [int] 0 on success; -1 on error.\n" },
1010 { "bvtsched_global_get",
1011 (PyCFunction)pyxc_bvtsched_global_get,
1012 METH_KEYWORDS, "\n"
1013 "Get global tuning parameters for BVT scheduler.\n"
1014 "Returns: [dict]:\n"
1015 " ctx_allow [int]: context switch allowance\n" },
1017 { "bvtsched_domain_set",
1018 (PyCFunction)pyxc_bvtsched_domain_set,
1019 METH_VARARGS | METH_KEYWORDS, "\n"
1020 "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
1021 " dom [int]: Identifier of domain to be tuned.\n"
1022 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
1023 " warpback [int]: Warp ? \n"
1024 " warpvalue [int]: How far to warp domain's EVT on unblock.\n"
1025 " warpl [int]: How long the domain can run warped.\n"
1026 " warpu [int]: How long before the domain can warp again.\n\n"
1027 "Returns: [int] 0 on success; -1 on error.\n" },
1029 { "bvtsched_domain_get",
1030 (PyCFunction)pyxc_bvtsched_domain_get,
1031 METH_KEYWORDS, "\n"
1032 "Get per-domain tuning parameters under the BVT scheduler.\n"
1033 " dom [int]: Identifier of domain to be queried.\n"
1034 "Returns [dict]:\n"
1035 " domain [int]: Domain ID.\n"
1036 " mcuadv [long]: MCU Advance.\n"
1037 " warp [long]: Warp.\n"
1038 " warpu [long]: Unwarp requirement.\n"
1039 " warpl [long]: Warp limit,\n"
1040 },
1042 { "sedf_domain_set",
1043 (PyCFunction)pyxc_sedf_domain_set,
1044 METH_KEYWORDS, "\n"
1045 "Set the scheduling parameters for a domain when running with Atropos.\n"
1046 " dom [int]: domain to set\n"
1047 " period [long]: domain's scheduling period\n"
1048 " slice [long]: domain's slice per period\n"
1049 " latency [long]: domain's wakeup latency hint\n"
1050 " extratime [int]: domain aware of extratime?\n"
1051 "Returns: [int] 0 on success; -1 on error.\n" },
1053 { "sedf_domain_get",
1054 (PyCFunction)pyxc_sedf_domain_get,
1055 METH_KEYWORDS, "\n"
1056 "Get the current scheduling parameters for a domain when running with\n"
1057 "the Atropos scheduler."
1058 " dom [int]: domain to query\n"
1059 "Returns: [dict]\n"
1060 " domain [int]: domain ID\n"
1061 " period [long]: scheduler period\n"
1062 " slice [long]: CPU reservation per period\n"
1063 " latency [long]: domain's wakeup latency hint\n"
1064 " extratime [int]: domain aware of extratime?\n"},
1066 { "evtchn_alloc_unbound",
1067 (PyCFunction)pyxc_evtchn_alloc_unbound,
1068 METH_VARARGS | METH_KEYWORDS, "\n"
1069 "Allocate an unbound local port that will await a remote connection.\n"
1070 " dom [int]: Remote domain to accept connections from.\n\n"
1071 "Returns: [int] Unbound event-channel port.\n" },
1073 { "evtchn_bind_interdomain",
1074 (PyCFunction)pyxc_evtchn_bind_interdomain,
1075 METH_VARARGS | METH_KEYWORDS, "\n"
1076 "Open an event channel between two domains.\n"
1077 " dom1 [int, SELF]: First domain to be connected.\n"
1078 " dom2 [int, SELF]: Second domain to be connected.\n\n"
1079 "Returns: [dict] dictionary is empty on failure.\n"
1080 " port1 [int]: Port-id for endpoint at dom1.\n"
1081 " port2 [int]: Port-id for endpoint at dom2.\n" },
1083 { "evtchn_bind_virq",
1084 (PyCFunction)pyxc_evtchn_bind_virq,
1085 METH_VARARGS | METH_KEYWORDS, "\n"
1086 "Bind an event channel to the specified VIRQ.\n"
1087 " virq [int]: VIRQ to bind.\n\n"
1088 "Returns: [int] Bound event-channel port.\n" },
1090 { "evtchn_close",
1091 (PyCFunction)pyxc_evtchn_close,
1092 METH_VARARGS | METH_KEYWORDS, "\n"
1093 "Close an event channel. If interdomain, sets remote end to 'unbound'.\n"
1094 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1095 " port [int]: Port-id of one endpoint of the channel.\n\n"
1096 "Returns: [int] 0 on success; -1 on error.\n" },
1098 { "evtchn_send",
1099 (PyCFunction)pyxc_evtchn_send,
1100 METH_VARARGS | METH_KEYWORDS, "\n"
1101 "Send an event along a locally-connected event channel.\n"
1102 " port [int]: Port-id of a local channel endpoint.\n\n"
1103 "Returns: [int] 0 on success; -1 on error.\n" },
1105 { "evtchn_status",
1106 (PyCFunction)pyxc_evtchn_status,
1107 METH_VARARGS | METH_KEYWORDS, "\n"
1108 "Query the status of an event channel.\n"
1109 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1110 " port [int]: Port-id of one endpoint of the channel.\n\n"
1111 "Returns: [dict] dictionary is empty on failure.\n"
1112 " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
1113 " or 'virq'.\n"
1114 "The following are returned if 'status' is 'interdomain':\n"
1115 " dom [int]: Dom-id of remote endpoint.\n"
1116 " port [int]: Port-id of remote endpoint.\n"
1117 "The following are returned if 'status' is 'pirq' or 'virq':\n"
1118 " irq [int]: IRQ number.\n" },
1120 { "physdev_pci_access_modify",
1121 (PyCFunction)pyxc_physdev_pci_access_modify,
1122 METH_VARARGS | METH_KEYWORDS, "\n"
1123 "Allow a domain access to a PCI device\n"
1124 " dom [int]: Identifier of domain to be allowed access.\n"
1125 " bus [int]: PCI bus\n"
1126 " dev [int]: PCI slot\n"
1127 " func [int]: PCI function\n"
1128 " enable [int]: Non-zero means enable access; else disable access\n\n"
1129 "Returns: [int] 0 on success; -1 on error.\n" },
1131 { "readconsolering",
1132 (PyCFunction)pyxc_readconsolering,
1133 METH_VARARGS | METH_KEYWORDS, "\n"
1134 "Read Xen's console ring.\n"
1135 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1136 "Returns: [str] string is empty on failure.\n" },
1138 { "physinfo",
1139 (PyCFunction)pyxc_physinfo,
1140 METH_VARARGS, "\n"
1141 "Get information about the physical host machine\n"
1142 "Returns [dict]: information about the hardware"
1143 " [None]: on failure.\n" },
1145 { "shadow_control",
1146 (PyCFunction)pyxc_shadow_control,
1147 METH_VARARGS | METH_KEYWORDS, "\n"
1148 "Set parameter for shadow pagetable interface\n"
1149 " dom [int]: Identifier of domain.\n"
1150 " op [int, 0]: operation\n\n"
1151 "Returns: [int] 0 on success; -1 on error.\n" },
1153 { "domain_setmaxmem",
1154 (PyCFunction)pyxc_domain_setmaxmem,
1155 METH_VARARGS | METH_KEYWORDS, "\n"
1156 "Set a domain's memory limit\n"
1157 " dom [int]: Identifier of domain.\n"
1158 " maxmem_kb [long]: .\n"
1159 "Returns: [int] 0 on success; -1 on error.\n" },
1161 { NULL, NULL, 0, NULL }
1162 };
1165 /*
1166 * Definitions for the 'Xc' module wrapper.
1167 */
1169 staticforward PyTypeObject PyXcType;
1171 static PyObject *PyXc_new(PyObject *self, PyObject *args)
1173 XcObject *xc;
1175 if ( !PyArg_ParseTuple(args, ":new") )
1176 return NULL;
1178 xc = PyObject_New(XcObject, &PyXcType);
1180 if ( (xc->xc_handle = xc_interface_open()) == -1 )
1182 PyObject_Del((PyObject *)xc);
1183 return PyErr_SetFromErrno(xc_error);
1186 return (PyObject *)xc;
1189 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1191 return Py_FindMethod(pyxc_methods, obj, name);
1194 static void PyXc_dealloc(PyObject *self)
1196 XcObject *xc = (XcObject *)self;
1197 (void)xc_interface_close(xc->xc_handle);
1198 PyObject_Del(self);
1201 static PyTypeObject PyXcType = {
1202 PyObject_HEAD_INIT(&PyType_Type)
1203 0,
1204 "Xc",
1205 sizeof(XcObject),
1206 0,
1207 PyXc_dealloc, /* tp_dealloc */
1208 NULL, /* tp_print */
1209 PyXc_getattr, /* tp_getattr */
1210 NULL, /* tp_setattr */
1211 NULL, /* tp_compare */
1212 NULL, /* tp_repr */
1213 NULL, /* tp_as_number */
1214 NULL, /* tp_as_sequence */
1215 NULL, /* tp_as_mapping */
1216 NULL /* tp_hash */
1217 };
1219 static PyMethodDef PyXc_methods[] = {
1220 { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
1221 { NULL, NULL, 0, NULL }
1222 };
1224 PyMODINIT_FUNC initxc(void)
1226 PyObject *m, *d;
1228 m = Py_InitModule(XENPKG, PyXc_methods);
1230 d = PyModule_GetDict(m);
1231 xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
1232 PyDict_SetItemString(d, "error", xc_error);
1234 zero = PyInt_FromLong(0);
1236 /* KAF: This ensures that we get debug output in a timely manner. */
1237 setbuf(stdout, NULL);
1238 setbuf(stderr, NULL);