ia64/xen-unstable

view tools/python/xen/lowlevel/xc/xc.c @ 6880:fb72c78604c6

The dom destroy path is doing a dom_get on a non-existent domain to
ensure it is non-existent. This changes throws an explicit exception
when xc_domain_getinfo returns an error, instead of triggering an
internal python error. It then handles the exception in dom_get by
returning None, which callers already expect to mean failure.

Signed-off-by: Robert Read <robert@xensource.com>
author shand@ubuntu.eng.hq.xensource.com
date Wed Sep 14 14:36:29 2005 -0800 (2005-09-14)
parents 813c37b68376
children 3233e7ecfa9f
line source
1 /******************************************************************************
2 * Xc.c
3 *
4 * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
5 */
7 #include <Python.h>
8 #include <xenctrl.h>
9 #include <xenguest.h>
10 #include <zlib.h>
11 #include <fcntl.h>
12 #include <netinet/in.h>
13 #include <netinet/tcp.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <netdb.h>
17 #include <arpa/inet.h>
19 #include "xc_private.h"
20 #include "linux_boot_params.h"
22 /* Needed for Python versions earlier than 2.3. */
23 #ifndef PyMODINIT_FUNC
24 #define PyMODINIT_FUNC DL_EXPORT(void)
25 #endif
27 #define XENPKG "xen.lowlevel.xc"
29 static PyObject *xc_error, *zero;
31 typedef struct {
32 PyObject_HEAD;
33 int xc_handle;
34 } XcObject;
36 /*
37 * Definitions for the 'xc' object type.
38 */
40 static PyObject *pyxc_domain_dumpcore(PyObject *self,
41 PyObject *args,
42 PyObject *kwds)
43 {
44 XcObject *xc = (XcObject *)self;
46 u32 dom;
47 char *corefile;
49 static char *kwd_list[] = { "dom", "corefile", NULL };
51 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list,
52 &dom, &corefile) )
53 goto exit;
55 if ( (corefile == NULL) || (corefile[0] == '\0') )
56 goto exit;
58 if ( xc_domain_dumpcore(xc->xc_handle, dom, corefile) != 0 )
59 return PyErr_SetFromErrno(xc_error);
61 Py_INCREF(zero);
62 return zero;
64 exit:
65 return NULL;
66 }
68 static PyObject *pyxc_handle(PyObject *self)
69 {
70 XcObject *xc = (XcObject *)self;
72 return PyInt_FromLong(xc->xc_handle);
73 }
75 static PyObject *pyxc_domain_create(PyObject *self,
76 PyObject *args,
77 PyObject *kwds)
78 {
79 XcObject *xc = (XcObject *)self;
81 u32 dom = 0;
82 int ret;
83 u32 ssidref = 0x0;
85 static char *kwd_list[] = { "dom", "ssidref", NULL };
87 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
88 &dom, &ssidref))
89 return NULL;
91 if ( (ret = xc_domain_create(xc->xc_handle, ssidref, &dom)) < 0 )
92 return PyErr_SetFromErrno(xc_error);
94 return PyInt_FromLong(dom);
95 }
97 static PyObject *pyxc_domain_pause(PyObject *self,
98 PyObject *args,
99 PyObject *kwds)
100 {
101 XcObject *xc = (XcObject *)self;
103 u32 dom;
105 static char *kwd_list[] = { "dom", NULL };
107 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
108 return NULL;
110 if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
111 return PyErr_SetFromErrno(xc_error);
113 Py_INCREF(zero);
114 return zero;
115 }
117 static PyObject *pyxc_domain_unpause(PyObject *self,
118 PyObject *args,
119 PyObject *kwds)
120 {
121 XcObject *xc = (XcObject *)self;
123 u32 dom;
125 static char *kwd_list[] = { "dom", NULL };
127 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
128 return NULL;
130 if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
131 return PyErr_SetFromErrno(xc_error);
133 Py_INCREF(zero);
134 return zero;
135 }
137 static PyObject *pyxc_domain_destroy(PyObject *self,
138 PyObject *args,
139 PyObject *kwds)
140 {
141 XcObject *xc = (XcObject *)self;
143 u32 dom;
145 static char *kwd_list[] = { "dom", NULL };
147 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
148 return NULL;
150 if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
151 return PyErr_SetFromErrno(xc_error);
153 Py_INCREF(zero);
154 return zero;
155 }
157 static PyObject *pyxc_domain_pincpu(PyObject *self,
158 PyObject *args,
159 PyObject *kwds)
160 {
161 XcObject *xc = (XcObject *)self;
163 u32 dom;
164 int vcpu = 0;
165 cpumap_t cpumap = 0xFFFFFFFF;
167 static char *kwd_list[] = { "dom", "vcpu", "cpumap", NULL };
169 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
170 &dom, &vcpu, &cpumap) )
171 return NULL;
173 if ( xc_domain_pincpu(xc->xc_handle, dom, vcpu, &cpumap) != 0 )
174 return PyErr_SetFromErrno(xc_error);
176 Py_INCREF(zero);
177 return zero;
178 }
180 static PyObject *pyxc_domain_setcpuweight(PyObject *self,
181 PyObject *args,
182 PyObject *kwds)
183 {
184 XcObject *xc = (XcObject *)self;
186 u32 dom;
187 float cpuweight = 1;
189 static char *kwd_list[] = { "dom", "cpuweight", NULL };
191 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|f", kwd_list,
192 &dom, &cpuweight) )
193 return NULL;
195 if ( xc_domain_setcpuweight(xc->xc_handle, dom, cpuweight) != 0 )
196 return PyErr_SetFromErrno(xc_error);
198 Py_INCREF(zero);
199 return zero;
200 }
202 static PyObject *pyxc_domain_getinfo(PyObject *self,
203 PyObject *args,
204 PyObject *kwds)
205 {
206 XcObject *xc = (XcObject *)self;
207 PyObject *list, *vcpu_list, *cpumap_list, *info_dict;
209 u32 first_dom = 0;
210 int max_doms = 1024, nr_doms, i, j;
211 xc_dominfo_t *info;
213 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
215 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
216 &first_dom, &max_doms) )
217 return NULL;
219 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
220 return PyErr_NoMemory();
222 nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
224 if (nr_doms < 0)
225 return PyErr_SetFromErrno(xc_error);
227 list = PyList_New(nr_doms);
228 for ( i = 0 ; i < nr_doms; i++ )
229 {
230 vcpu_list = PyList_New(MAX_VIRT_CPUS);
231 cpumap_list = PyList_New(MAX_VIRT_CPUS);
232 for ( j = 0; j < MAX_VIRT_CPUS; j++ ) {
233 PyList_SetItem( vcpu_list, j,
234 Py_BuildValue("i", info[i].vcpu_to_cpu[j]));
235 PyList_SetItem( cpumap_list, j,
236 Py_BuildValue("i", info[i].cpumap[j]));
237 }
239 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
240 ",s:l,s:L,s:l,s:i,s:i}",
241 "dom", info[i].domid,
242 "vcpus", info[i].vcpus,
243 "dying", info[i].dying,
244 "crashed", info[i].crashed,
245 "shutdown", info[i].shutdown,
246 "paused", info[i].paused,
247 "blocked", info[i].blocked,
248 "running", info[i].running,
249 "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
250 "cpu_time", info[i].cpu_time,
251 "maxmem_kb", info[i].max_memkb,
252 "ssidref", info[i].ssidref,
253 "shutdown_reason", info[i].shutdown_reason);
254 PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list );
255 PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
256 PyList_SetItem( list, i, info_dict);
258 }
260 free(info);
262 return list;
263 }
265 static PyObject *pyxc_linux_build(PyObject *self,
266 PyObject *args,
267 PyObject *kwds)
268 {
269 XcObject *xc = (XcObject *)self;
271 u32 dom;
272 char *image, *ramdisk = NULL, *cmdline = "";
273 int flags = 0, vcpus = 1;
274 int store_evtchn, console_evtchn;
275 unsigned long store_mfn = 0;
276 unsigned long console_mfn = 0;
278 static char *kwd_list[] = { "dom", "store_evtchn",
279 "console_evtchn", "image",
280 /* optional */
281 "ramdisk", "cmdline", "flags",
282 "vcpus", NULL };
284 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssii", kwd_list,
285 &dom, &store_evtchn,
286 &console_evtchn, &image,
287 /* optional */
288 &ramdisk, &cmdline, &flags,
289 &vcpus) )
290 return NULL;
292 if ( xc_linux_build(xc->xc_handle, dom, image,
293 ramdisk, cmdline, flags, vcpus,
294 store_evtchn, &store_mfn,
295 console_evtchn, &console_mfn) != 0 )
296 return PyErr_SetFromErrno(xc_error);
298 return Py_BuildValue("{s:i,s:i}",
299 "store_mfn", store_mfn,
300 "console_mfn", console_mfn);
301 }
303 static PyObject *pyxc_vmx_build(PyObject *self,
304 PyObject *args,
305 PyObject *kwds)
306 {
307 XcObject *xc = (XcObject *)self;
309 u32 dom;
310 char *image, *ramdisk = NULL, *cmdline = "";
311 PyObject *memmap;
312 int control_evtchn, store_evtchn;
313 int flags = 0, vcpus = 1;
314 int numItems, i;
315 int memsize;
316 struct mem_map mem_map;
317 unsigned long store_mfn = 0;
319 static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
320 "memsize", "image", "memmap",
321 "ramdisk", "cmdline", "flags",
322 "vcpus", NULL };
324 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisO!|ssii", kwd_list,
325 &dom, &control_evtchn, &store_evtchn,
326 &memsize,
327 &image, &PyList_Type, &memmap,
328 &ramdisk, &cmdline, &flags, &vcpus) )
329 return NULL;
331 memset(&mem_map, 0, sizeof(mem_map));
332 /* Parse memmap */
334 /* get the number of lines passed to us */
335 numItems = PyList_Size(memmap) - 1; /* removing the line
336 containing "memmap" */
337 mem_map.nr_map = numItems;
339 /* should raise an error here. */
340 if (numItems < 0) return NULL; /* Not a list */
342 /* iterate over items of the list, grabbing ranges and parsing them */
343 for (i = 1; i <= numItems; i++) { // skip over "memmap"
344 PyObject *item, *f1, *f2, *f3, *f4;
345 int numFields;
346 unsigned long lf1, lf2, lf3, lf4;
347 char *sf1, *sf2;
349 /* grab the string object from the next element of the list */
350 item = PyList_GetItem(memmap, i); /* Can't fail */
352 /* get the number of lines passed to us */
353 numFields = PyList_Size(item);
355 if (numFields != 4)
356 return NULL;
358 f1 = PyList_GetItem(item, 0);
359 f2 = PyList_GetItem(item, 1);
360 f3 = PyList_GetItem(item, 2);
361 f4 = PyList_GetItem(item, 3);
363 /* Convert objects to strings/longs */
364 sf1 = PyString_AsString(f1);
365 sf2 = PyString_AsString(f2);
366 lf3 = PyLong_AsLong(f3);
367 lf4 = PyLong_AsLong(f4);
368 if ( sscanf(sf1, "%lx", &lf1) != 1 )
369 return NULL;
370 if ( sscanf(sf2, "%lx", &lf2) != 1 )
371 return NULL;
373 mem_map.map[i-1].addr = lf1;
374 mem_map.map[i-1].size = lf2 - lf1;
375 mem_map.map[i-1].type = lf3;
376 mem_map.map[i-1].caching_attr = lf4;
377 }
379 if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, &mem_map,
380 ramdisk, cmdline, control_evtchn, flags,
381 vcpus, store_evtchn, &store_mfn) != 0 )
382 return PyErr_SetFromErrno(xc_error);
384 return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
385 }
387 static PyObject *pyxc_bvtsched_global_set(PyObject *self,
388 PyObject *args,
389 PyObject *kwds)
390 {
391 XcObject *xc = (XcObject *)self;
393 unsigned long ctx_allow;
395 static char *kwd_list[] = { "ctx_allow", NULL };
397 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
398 return NULL;
400 if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
401 return PyErr_SetFromErrno(xc_error);
403 Py_INCREF(zero);
404 return zero;
405 }
407 static PyObject *pyxc_bvtsched_global_get(PyObject *self,
408 PyObject *args,
409 PyObject *kwds)
410 {
411 XcObject *xc = (XcObject *)self;
413 unsigned long ctx_allow;
415 if ( !PyArg_ParseTuple(args, "") )
416 return NULL;
418 if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
419 return PyErr_SetFromErrno(xc_error);
421 return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
422 }
424 static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
425 PyObject *args,
426 PyObject *kwds)
427 {
428 XcObject *xc = (XcObject *)self;
430 u32 dom;
431 u32 mcuadv;
432 int warpback;
433 s32 warpvalue;
434 long long warpl;
435 long long warpu;
437 static char *kwd_list[] = { "dom", "mcuadv", "warpback", "warpvalue",
438 "warpl", "warpu", NULL };
440 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiiLL", kwd_list,
441 &dom, &mcuadv, &warpback, &warpvalue,
442 &warpl, &warpu) )
443 return NULL;
445 if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
446 warpback, warpvalue, warpl, warpu) != 0 )
447 return PyErr_SetFromErrno(xc_error);
449 Py_INCREF(zero);
450 return zero;
451 }
453 static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
454 PyObject *args,
455 PyObject *kwds)
456 {
457 XcObject *xc = (XcObject *)self;
458 u32 dom;
459 u32 mcuadv;
460 int warpback;
461 s32 warpvalue;
462 long long warpl;
463 long long warpu;
465 static char *kwd_list[] = { "dom", NULL };
467 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
468 return NULL;
470 if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warpback,
471 &warpvalue, &warpl, &warpu) != 0 )
472 return PyErr_SetFromErrno(xc_error);
474 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
475 "domain", dom,
476 "mcuadv", mcuadv,
477 "warpback", warpback,
478 "warpvalue", warpvalue,
479 "warpl", warpl,
480 "warpu", warpu);
481 }
483 static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
484 PyObject *args,
485 PyObject *kwds)
486 {
487 XcObject *xc = (XcObject *)self;
489 u32 dom;
490 int port = 0;
492 static char *kwd_list[] = { "dom", "port", NULL };
494 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
495 &dom, &port) )
496 return NULL;
498 if ( xc_evtchn_alloc_unbound(xc->xc_handle, dom, &port) != 0 )
499 return PyErr_SetFromErrno(xc_error);
501 return PyInt_FromLong(port);
502 }
504 static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
505 PyObject *args,
506 PyObject *kwds)
507 {
508 XcObject *xc = (XcObject *)self;
510 u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
511 int port1 = 0, port2 = 0;
513 static char *kwd_list[] = { "dom1", "dom2", "port1", "port2", NULL };
515 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiii", kwd_list,
516 &dom1, &dom2, &port1, &port2) )
517 return NULL;
519 if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
520 dom2, &port1, &port2) != 0 )
521 return PyErr_SetFromErrno(xc_error);
523 return Py_BuildValue("{s:i,s:i}",
524 "port1", port1,
525 "port2", port2);
526 }
528 static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
529 PyObject *args,
530 PyObject *kwds)
531 {
532 XcObject *xc = (XcObject *)self;
534 int virq, port;
536 static char *kwd_list[] = { "virq", NULL };
538 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
539 return NULL;
541 if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
542 return PyErr_SetFromErrno(xc_error);
544 return PyInt_FromLong(port);
545 }
547 static PyObject *pyxc_evtchn_close(PyObject *self,
548 PyObject *args,
549 PyObject *kwds)
550 {
551 XcObject *xc = (XcObject *)self;
553 u32 dom = DOMID_SELF;
554 int port;
556 static char *kwd_list[] = { "port", "dom", NULL };
558 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
559 &port, &dom) )
560 return NULL;
562 if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
563 return PyErr_SetFromErrno(xc_error);
565 Py_INCREF(zero);
566 return zero;
567 }
569 static PyObject *pyxc_evtchn_send(PyObject *self,
570 PyObject *args,
571 PyObject *kwds)
572 {
573 XcObject *xc = (XcObject *)self;
575 int port;
577 static char *kwd_list[] = { "port", NULL };
579 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
580 return NULL;
582 if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
583 return PyErr_SetFromErrno(xc_error);
585 Py_INCREF(zero);
586 return zero;
587 }
589 static PyObject *pyxc_evtchn_status(PyObject *self,
590 PyObject *args,
591 PyObject *kwds)
592 {
593 XcObject *xc = (XcObject *)self;
594 PyObject *dict;
596 u32 dom = DOMID_SELF;
597 int port, ret;
598 xc_evtchn_status_t status;
600 static char *kwd_list[] = { "port", "dom", NULL };
602 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
603 &port, &dom) )
604 return NULL;
606 ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
607 if ( ret != 0 )
608 return PyErr_SetFromErrno(xc_error);
610 switch ( status.status )
611 {
612 case EVTCHNSTAT_closed:
613 dict = Py_BuildValue("{s:s}",
614 "status", "closed");
615 break;
616 case EVTCHNSTAT_unbound:
617 dict = Py_BuildValue("{s:s}",
618 "status", "unbound");
619 break;
620 case EVTCHNSTAT_interdomain:
621 dict = Py_BuildValue("{s:s,s:i,s:i}",
622 "status", "interdomain",
623 "dom", status.u.interdomain.dom,
624 "port", status.u.interdomain.port);
625 break;
626 case EVTCHNSTAT_pirq:
627 dict = Py_BuildValue("{s:s,s:i}",
628 "status", "pirq",
629 "irq", status.u.pirq);
630 break;
631 case EVTCHNSTAT_virq:
632 dict = Py_BuildValue("{s:s,s:i}",
633 "status", "virq",
634 "irq", status.u.virq);
635 break;
636 default:
637 dict = Py_BuildValue("{}");
638 break;
639 }
641 return dict;
642 }
644 static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
645 PyObject *args,
646 PyObject *kwds)
647 {
648 XcObject *xc = (XcObject *)self;
649 u32 dom;
650 int bus, dev, func, enable, ret;
652 static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
654 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
655 &dom, &bus, &dev, &func, &enable) )
656 return NULL;
658 ret = xc_physdev_pci_access_modify(
659 xc->xc_handle, dom, bus, dev, func, enable);
660 if ( ret != 0 )
661 return PyErr_SetFromErrno(xc_error);
663 Py_INCREF(zero);
664 return zero;
665 }
667 static PyObject *pyxc_readconsolering(PyObject *self,
668 PyObject *args,
669 PyObject *kwds)
670 {
671 XcObject *xc = (XcObject *)self;
673 unsigned int clear = 0;
674 char _str[32768], *str = _str;
675 unsigned int count = 32768;
676 int ret;
678 static char *kwd_list[] = { "clear", NULL };
680 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
681 return NULL;
683 ret = xc_readconsolering(xc->xc_handle, &str, &count, clear);
684 if ( ret < 0 )
685 return PyErr_SetFromErrno(xc_error);
687 return PyString_FromStringAndSize(str, count);
688 }
690 static PyObject *pyxc_physinfo(PyObject *self,
691 PyObject *args,
692 PyObject *kwds)
693 {
694 XcObject *xc = (XcObject *)self;
695 xc_physinfo_t info;
696 char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
697 int i;
699 if ( !PyArg_ParseTuple(args, "") )
700 return NULL;
702 if ( xc_physinfo(xc->xc_handle, &info) != 0 )
703 return PyErr_SetFromErrno(xc_error);
705 *q=0;
706 for(i=0;i<sizeof(info.hw_cap)/4;i++)
707 {
708 p+=sprintf(p,"%08x:",info.hw_cap[i]);
709 if(info.hw_cap[i])
710 q=p;
711 }
712 if(q>cpu_cap)
713 *(q-1)=0;
715 return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i,s:s}",
716 "threads_per_core", info.threads_per_core,
717 "cores_per_socket", info.cores_per_socket,
718 "sockets_per_node", info.sockets_per_node,
719 "nr_nodes", info.nr_nodes,
720 "total_pages", info.total_pages,
721 "free_pages", info.free_pages,
722 "cpu_khz", info.cpu_khz,
723 "hw_caps", cpu_cap);
724 }
726 static PyObject *pyxc_xeninfo(PyObject *self,
727 PyObject *args,
728 PyObject *kwds)
729 {
730 XcObject *xc = (XcObject *)self;
731 xen_extraversion_t xen_extra;
732 xen_compile_info_t xen_cc;
733 xen_changeset_info_t xen_chgset;
734 xen_capabilities_info_t xen_caps;
735 xen_parameters_info_t xen_parms;
736 long xen_version;
737 char str[128];
739 xen_version = xc_version(xc->xc_handle, XENVER_version, NULL);
741 if ( xc_version(xc->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
742 return PyErr_SetFromErrno(xc_error);
744 if ( xc_version(xc->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
745 return PyErr_SetFromErrno(xc_error);
747 if ( xc_version(xc->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
748 return PyErr_SetFromErrno(xc_error);
750 if ( xc_version(xc->xc_handle, XENVER_capabilities, &xen_caps) != 0 )
751 return PyErr_SetFromErrno(xc_error);
753 if ( xc_version(xc->xc_handle, XENVER_parameters, &xen_parms) != 0 )
754 return PyErr_SetFromErrno(xc_error);
756 sprintf(str,"virt_start=0x%lx",xen_parms.virt_start);
758 return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
759 "xen_major", xen_version >> 16,
760 "xen_minor", (xen_version & 0xffff),
761 "xen_extra", xen_extra,
762 "xen_caps", xen_caps,
763 "xen_params", str,
764 "xen_changeset", xen_chgset,
765 "cc_compiler", xen_cc.compiler,
766 "cc_compile_by", xen_cc.compile_by,
767 "cc_compile_domain", xen_cc.compile_domain,
768 "cc_compile_date", xen_cc.compile_date);
769 }
772 static PyObject *pyxc_sedf_domain_set(PyObject *self,
773 PyObject *args,
774 PyObject *kwds)
775 {
776 XcObject *xc = (XcObject *)self;
777 u32 domid;
778 u64 period, slice, latency;
779 u16 extratime, weight;
780 static char *kwd_list[] = { "dom", "period", "slice",
781 "latency", "extratime", "weight",NULL };
783 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list,
784 &domid, &period, &slice,
785 &latency, &extratime, &weight) )
786 return NULL;
787 if ( xc_sedf_domain_set(xc->xc_handle, domid, period,
788 slice, latency, extratime,weight) != 0 )
789 return PyErr_SetFromErrno(xc_error);
791 Py_INCREF(zero);
792 return zero;
793 }
795 static PyObject *pyxc_sedf_domain_get(PyObject *self,
796 PyObject *args,
797 PyObject *kwds)
798 {
799 XcObject *xc = (XcObject *)self;
800 u32 domid;
801 u64 period, slice,latency;
802 u16 weight, extratime;
804 static char *kwd_list[] = { "dom", NULL };
806 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
807 return NULL;
809 if ( xc_sedf_domain_get( xc->xc_handle, domid, &period,
810 &slice,&latency,&extratime,&weight) )
811 return PyErr_SetFromErrno(xc_error);
813 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
814 "domain", domid,
815 "period", period,
816 "slice", slice,
817 "latency", latency,
818 "extratime", extratime);
819 }
821 static PyObject *pyxc_shadow_control(PyObject *self,
822 PyObject *args,
823 PyObject *kwds)
824 {
825 XcObject *xc = (XcObject *)self;
827 u32 dom;
828 int op=0;
830 static char *kwd_list[] = { "dom", "op", NULL };
832 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
833 &dom, &op) )
834 return NULL;
836 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
837 return PyErr_SetFromErrno(xc_error);
839 Py_INCREF(zero);
840 return zero;
841 }
843 static PyObject *pyxc_domain_setmaxmem(PyObject *self,
844 PyObject *args,
845 PyObject *kwds)
846 {
847 XcObject *xc = (XcObject *)self;
849 u32 dom;
850 unsigned long maxmem_kb;
852 static char *kwd_list[] = { "dom", "maxmem_kb", NULL };
854 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
855 &dom, &maxmem_kb) )
856 return NULL;
858 if ( xc_domain_setmaxmem(xc->xc_handle, dom, maxmem_kb) != 0 )
859 return PyErr_SetFromErrno(xc_error);
861 Py_INCREF(zero);
862 return zero;
863 }
865 static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
866 PyObject *args,
867 PyObject *kwds)
868 {
869 XcObject *xc = (XcObject *)self;
871 u32 dom;
872 unsigned long mem_kb;
873 unsigned int extent_order = 0 , address_bits = 0;
874 unsigned long nr_extents;
876 static char *kwd_list[] = { "dom", "mem_kb", "extent_order", "address_bits", NULL };
878 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list,
879 &dom, &mem_kb, &extent_order, &address_bits) )
880 return NULL;
882 /* round down to nearest power of 2. Assume callers using extent_order>0
883 know what they are doing */
884 nr_extents = (mem_kb / (XC_PAGE_SIZE/1024)) >> extent_order;
885 if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom,
886 nr_extents, extent_order,
887 address_bits, NULL) )
888 return PyErr_SetFromErrno(xc_error);
890 Py_INCREF(zero);
891 return zero;
892 }
894 static PyObject *pyxc_init_store(PyObject *self, PyObject *args,
895 PyObject *kwds)
896 {
897 XcObject *xc = (XcObject *)self;
899 int remote_port;
901 static char *kwd_list[] = { "remote_port", NULL };
903 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
904 &remote_port) )
905 return NULL;
907 return PyInt_FromLong(xc_init_store(xc->xc_handle, remote_port));
908 }
911 static PyMethodDef pyxc_methods[] = {
912 { "handle",
913 (PyCFunction)pyxc_handle,
914 0, "\n"
915 "Query the xc control interface file descriptor.\n\n"
916 "Returns: [int] file descriptor\n" },
918 { "domain_create",
919 (PyCFunction)pyxc_domain_create,
920 METH_VARARGS | METH_KEYWORDS, "\n"
921 "Create a new domain.\n"
922 " dom [int, 0]: Domain identifier to use (allocated if zero).\n"
923 "Returns: [int] new domain identifier; -1 on error.\n" },
925 { "domain_dumpcore",
926 (PyCFunction)pyxc_domain_dumpcore,
927 METH_VARARGS | METH_KEYWORDS, "\n"
928 "Dump core of a domain.\n"
929 " dom [int]: Identifier of domain to dump core of.\n"
930 " corefile [string]: Name of corefile to be created.\n\n"
931 "Returns: [int] 0 on success; -1 on error.\n" },
933 { "domain_pause",
934 (PyCFunction)pyxc_domain_pause,
935 METH_VARARGS | METH_KEYWORDS, "\n"
936 "Temporarily pause execution of a domain.\n"
937 " dom [int]: Identifier of domain to be paused.\n\n"
938 "Returns: [int] 0 on success; -1 on error.\n" },
940 { "domain_unpause",
941 (PyCFunction)pyxc_domain_unpause,
942 METH_VARARGS | METH_KEYWORDS, "\n"
943 "(Re)start execution of a domain.\n"
944 " dom [int]: Identifier of domain to be unpaused.\n\n"
945 "Returns: [int] 0 on success; -1 on error.\n" },
947 { "domain_destroy",
948 (PyCFunction)pyxc_domain_destroy,
949 METH_VARARGS | METH_KEYWORDS, "\n"
950 "Destroy a domain.\n"
951 " dom [int]: Identifier of domain to be destroyed.\n\n"
952 "Returns: [int] 0 on success; -1 on error.\n" },
954 { "domain_pincpu",
955 (PyCFunction)pyxc_domain_pincpu,
956 METH_VARARGS | METH_KEYWORDS, "\n"
957 "Pin a VCPU to a specified set CPUs.\n"
958 " dom [int]: Identifier of domain to which VCPU belongs.\n"
959 " vcpu [int, 0]: VCPU being pinned.\n"
960 " cpumap [int, -1]: Bitmap of usable CPUs.\n\n"
961 "Returns: [int] 0 on success; -1 on error.\n" },
963 { "domain_setcpuweight",
964 (PyCFunction)pyxc_domain_setcpuweight,
965 METH_VARARGS | METH_KEYWORDS, "\n"
966 "Set cpuweight scheduler parameter for domain.\n"
967 " dom [int]: Identifier of domain to be changed.\n"
968 " cpuweight [float, 1]: VCPU being pinned.\n"
969 "Returns: [int] 0 on success; -1 on error.\n" },
971 { "domain_getinfo",
972 (PyCFunction)pyxc_domain_getinfo,
973 METH_VARARGS | METH_KEYWORDS, "\n"
974 "Get information regarding a set of domains, in increasing id order.\n"
975 " first_dom [int, 0]: First domain to retrieve info about.\n"
976 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
977 " about.\n\n"
978 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
979 " parameter then there was an error, or the end of the\n"
980 " domain-id space was reached.\n"
981 " dom [int]: Identifier of domain to which this info pertains\n"
982 " cpu [int]: CPU to which this domain is bound\n"
983 " vcpus [int]: Number of Virtual CPUS in this domain\n"
984 " dying [int]: Bool - is the domain dying?\n"
985 " crashed [int]: Bool - has the domain crashed?\n"
986 " shutdown [int]: Bool - has the domain shut itself down?\n"
987 " paused [int]: Bool - is the domain paused by control software?\n"
988 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
989 " running [int]: Bool - is the domain currently running?\n"
990 " mem_kb [int]: Memory reservation, in kilobytes\n"
991 " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
992 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
993 " shutdown_reason [int]: Numeric code from guest OS, explaining "
994 "reason why it shut itself down.\n"
995 " vcpu_to_cpu [[int]]: List that maps VCPUS to CPUS\n" },
997 { "linux_build",
998 (PyCFunction)pyxc_linux_build,
999 METH_VARARGS | METH_KEYWORDS, "\n"
1000 "Build a new Linux guest OS.\n"
1001 " dom [int]: Identifier of domain to build into.\n"
1002 " image [str]: Name of kernel image file. May be gzipped.\n"
1003 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
1004 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1005 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
1006 "Returns: [int] 0 on success; -1 on error.\n" },
1008 { "vmx_build",
1009 (PyCFunction)pyxc_vmx_build,
1010 METH_VARARGS | METH_KEYWORDS, "\n"
1011 "Build a new Linux guest OS.\n"
1012 " dom [int]: Identifier of domain to build into.\n"
1013 " image [str]: Name of kernel image file. May be gzipped.\n"
1014 " memmap [str]: Memory map.\n\n"
1015 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
1016 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1017 "Returns: [int] 0 on success; -1 on error.\n" },
1019 { "bvtsched_global_set",
1020 (PyCFunction)pyxc_bvtsched_global_set,
1021 METH_VARARGS | METH_KEYWORDS, "\n"
1022 "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
1023 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
1024 "Returns: [int] 0 on success; -1 on error.\n" },
1026 { "bvtsched_global_get",
1027 (PyCFunction)pyxc_bvtsched_global_get,
1028 METH_KEYWORDS, "\n"
1029 "Get global tuning parameters for BVT scheduler.\n"
1030 "Returns: [dict]:\n"
1031 " ctx_allow [int]: context switch allowance\n" },
1033 { "bvtsched_domain_set",
1034 (PyCFunction)pyxc_bvtsched_domain_set,
1035 METH_VARARGS | METH_KEYWORDS, "\n"
1036 "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
1037 " dom [int]: Identifier of domain to be tuned.\n"
1038 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
1039 " warpback [int]: Warp ? \n"
1040 " warpvalue [int]: How far to warp domain's EVT on unblock.\n"
1041 " warpl [int]: How long the domain can run warped.\n"
1042 " warpu [int]: How long before the domain can warp again.\n\n"
1043 "Returns: [int] 0 on success; -1 on error.\n" },
1045 { "bvtsched_domain_get",
1046 (PyCFunction)pyxc_bvtsched_domain_get,
1047 METH_KEYWORDS, "\n"
1048 "Get per-domain tuning parameters under the BVT scheduler.\n"
1049 " dom [int]: Identifier of domain to be queried.\n"
1050 "Returns [dict]:\n"
1051 " domain [int]: Domain ID.\n"
1052 " mcuadv [long]: MCU Advance.\n"
1053 " warp [long]: Warp.\n"
1054 " warpu [long]: Unwarp requirement.\n"
1055 " warpl [long]: Warp limit,\n"
1056 },
1058 { "sedf_domain_set",
1059 (PyCFunction)pyxc_sedf_domain_set,
1060 METH_KEYWORDS, "\n"
1061 "Set the scheduling parameters for a domain when running with Atropos.\n"
1062 " dom [int]: domain to set\n"
1063 " period [long]: domain's scheduling period\n"
1064 " slice [long]: domain's slice per period\n"
1065 " latency [long]: domain's wakeup latency hint\n"
1066 " extratime [int]: domain aware of extratime?\n"
1067 "Returns: [int] 0 on success; -1 on error.\n" },
1069 { "sedf_domain_get",
1070 (PyCFunction)pyxc_sedf_domain_get,
1071 METH_KEYWORDS, "\n"
1072 "Get the current scheduling parameters for a domain when running with\n"
1073 "the Atropos scheduler."
1074 " dom [int]: domain to query\n"
1075 "Returns: [dict]\n"
1076 " domain [int]: domain ID\n"
1077 " period [long]: scheduler period\n"
1078 " slice [long]: CPU reservation per period\n"
1079 " latency [long]: domain's wakeup latency hint\n"
1080 " extratime [int]: domain aware of extratime?\n"},
1082 { "evtchn_alloc_unbound",
1083 (PyCFunction)pyxc_evtchn_alloc_unbound,
1084 METH_VARARGS | METH_KEYWORDS, "\n"
1085 "Allocate an unbound local port that will await a remote connection.\n"
1086 " dom [int]: Remote domain to accept connections from.\n\n"
1087 "Returns: [int] Unbound event-channel port.\n" },
1089 { "evtchn_bind_interdomain",
1090 (PyCFunction)pyxc_evtchn_bind_interdomain,
1091 METH_VARARGS | METH_KEYWORDS, "\n"
1092 "Open an event channel between two domains.\n"
1093 " dom1 [int, SELF]: First domain to be connected.\n"
1094 " dom2 [int, SELF]: Second domain to be connected.\n\n"
1095 "Returns: [dict] dictionary is empty on failure.\n"
1096 " port1 [int]: Port-id for endpoint at dom1.\n"
1097 " port2 [int]: Port-id for endpoint at dom2.\n" },
1099 { "evtchn_bind_virq",
1100 (PyCFunction)pyxc_evtchn_bind_virq,
1101 METH_VARARGS | METH_KEYWORDS, "\n"
1102 "Bind an event channel to the specified VIRQ.\n"
1103 " virq [int]: VIRQ to bind.\n\n"
1104 "Returns: [int] Bound event-channel port.\n" },
1106 { "evtchn_close",
1107 (PyCFunction)pyxc_evtchn_close,
1108 METH_VARARGS | METH_KEYWORDS, "\n"
1109 "Close an event channel. If interdomain, sets remote end to 'unbound'.\n"
1110 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1111 " port [int]: Port-id of one endpoint of the channel.\n\n"
1112 "Returns: [int] 0 on success; -1 on error.\n" },
1114 { "evtchn_send",
1115 (PyCFunction)pyxc_evtchn_send,
1116 METH_VARARGS | METH_KEYWORDS, "\n"
1117 "Send an event along a locally-connected event channel.\n"
1118 " port [int]: Port-id of a local channel endpoint.\n\n"
1119 "Returns: [int] 0 on success; -1 on error.\n" },
1121 { "evtchn_status",
1122 (PyCFunction)pyxc_evtchn_status,
1123 METH_VARARGS | METH_KEYWORDS, "\n"
1124 "Query the status of an event channel.\n"
1125 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1126 " port [int]: Port-id of one endpoint of the channel.\n\n"
1127 "Returns: [dict] dictionary is empty on failure.\n"
1128 " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
1129 " or 'virq'.\n"
1130 "The following are returned if 'status' is 'interdomain':\n"
1131 " dom [int]: Dom-id of remote endpoint.\n"
1132 " port [int]: Port-id of remote endpoint.\n"
1133 "The following are returned if 'status' is 'pirq' or 'virq':\n"
1134 " irq [int]: IRQ number.\n" },
1136 { "physdev_pci_access_modify",
1137 (PyCFunction)pyxc_physdev_pci_access_modify,
1138 METH_VARARGS | METH_KEYWORDS, "\n"
1139 "Allow a domain access to a PCI device\n"
1140 " dom [int]: Identifier of domain to be allowed access.\n"
1141 " bus [int]: PCI bus\n"
1142 " dev [int]: PCI slot\n"
1143 " func [int]: PCI function\n"
1144 " enable [int]: Non-zero means enable access; else disable access\n\n"
1145 "Returns: [int] 0 on success; -1 on error.\n" },
1147 { "readconsolering",
1148 (PyCFunction)pyxc_readconsolering,
1149 METH_VARARGS | METH_KEYWORDS, "\n"
1150 "Read Xen's console ring.\n"
1151 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1152 "Returns: [str] string is empty on failure.\n" },
1154 { "physinfo",
1155 (PyCFunction)pyxc_physinfo,
1156 METH_VARARGS, "\n"
1157 "Get information about the physical host machine\n"
1158 "Returns [dict]: information about the hardware"
1159 " [None]: on failure.\n" },
1161 { "xeninfo",
1162 (PyCFunction)pyxc_xeninfo,
1163 METH_VARARGS, "\n"
1164 "Get information about the Xen host\n"
1165 "Returns [dict]: information about Xen"
1166 " [None]: on failure.\n" },
1168 { "shadow_control",
1169 (PyCFunction)pyxc_shadow_control,
1170 METH_VARARGS | METH_KEYWORDS, "\n"
1171 "Set parameter for shadow pagetable interface\n"
1172 " dom [int]: Identifier of domain.\n"
1173 " op [int, 0]: operation\n\n"
1174 "Returns: [int] 0 on success; -1 on error.\n" },
1176 { "domain_setmaxmem",
1177 (PyCFunction)pyxc_domain_setmaxmem,
1178 METH_VARARGS | METH_KEYWORDS, "\n"
1179 "Set a domain's memory limit\n"
1180 " dom [int]: Identifier of domain.\n"
1181 " maxmem_kb [long]: .\n"
1182 "Returns: [int] 0 on success; -1 on error.\n" },
1184 { "domain_memory_increase_reservation",
1185 (PyCFunction)pyxc_domain_memory_increase_reservation,
1186 METH_VARARGS | METH_KEYWORDS, "\n"
1187 "Increase a domain's memory reservation\n"
1188 " dom [int]: Identifier of domain.\n"
1189 " mem_kb [long]: .\n"
1190 "Returns: [int] 0 on success; -1 on error.\n" },
1192 { "init_store",
1193 (PyCFunction)pyxc_init_store,
1194 METH_VARARGS | METH_KEYWORDS, "\n"
1195 "Initialize the store event channel and return the store page mfn.\n"
1196 " remote_port [int]: store event channel port number.\n"
1197 "Returns: [int] mfn on success; <0 on error.\n" },
1199 { NULL, NULL, 0, NULL }
1200 };
1203 /*
1204 * Definitions for the 'Xc' module wrapper.
1205 */
1207 staticforward PyTypeObject PyXcType;
1209 static PyObject *PyXc_new(PyObject *self, PyObject *args)
1211 XcObject *xc;
1213 if ( !PyArg_ParseTuple(args, ":new") )
1214 return NULL;
1216 xc = PyObject_New(XcObject, &PyXcType);
1218 if ( (xc->xc_handle = xc_interface_open()) == -1 )
1220 PyObject_Del((PyObject *)xc);
1221 return PyErr_SetFromErrno(xc_error);
1224 return (PyObject *)xc;
1227 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1229 return Py_FindMethod(pyxc_methods, obj, name);
1232 static void PyXc_dealloc(PyObject *self)
1234 XcObject *xc = (XcObject *)self;
1235 (void)xc_interface_close(xc->xc_handle);
1236 PyObject_Del(self);
1239 static PyTypeObject PyXcType = {
1240 PyObject_HEAD_INIT(&PyType_Type)
1241 0,
1242 "Xc",
1243 sizeof(XcObject),
1244 0,
1245 PyXc_dealloc, /* tp_dealloc */
1246 NULL, /* tp_print */
1247 PyXc_getattr, /* tp_getattr */
1248 NULL, /* tp_setattr */
1249 NULL, /* tp_compare */
1250 NULL, /* tp_repr */
1251 NULL, /* tp_as_number */
1252 NULL, /* tp_as_sequence */
1253 NULL, /* tp_as_mapping */
1254 NULL /* tp_hash */
1255 };
1257 static PyMethodDef PyXc_methods[] = {
1258 { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
1259 { NULL, NULL, 0, NULL }
1260 };
1262 PyMODINIT_FUNC initxc(void)
1264 PyObject *m, *d;
1266 m = Py_InitModule(XENPKG, PyXc_methods);
1268 d = PyModule_GetDict(m);
1269 xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
1270 PyDict_SetItemString(d, "error", xc_error);
1271 PyDict_SetItemString(d, "VIRQ_DOM_EXC", PyInt_FromLong(VIRQ_DOM_EXC));
1273 zero = PyInt_FromLong(0);
1275 /* KAF: This ensures that we get debug output in a timely manner. */
1276 setbuf(stdout, NULL);
1277 setbuf(stderr, NULL);