ia64/xen-unstable

view tools/python/xen/lowlevel/xc/xc.c @ 7245:4083eb31def0

Change how event channels are allocated and used by the control
tools. /dev/xen/evtchn is now used by daemons to connect to
remote domains: the advantage is that the local ports are garbage
collected automatically if the daemon dies. xen no longer
constructs end-to-end event-channel port pairs -- it allocates an
unbound port in new domU and writes that port to xenstore. It is
then picked up by teh appropriate daemon which does interdomain bind
via /dev/xen/evtchn.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Oct 06 16:07:52 2005 +0100 (2005-10-06)
parents c3d9b7013b14
children 76a7a7aa27e4
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"
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_dumpcore(PyObject *self,
40 PyObject *args,
41 PyObject *kwds)
42 {
43 XcObject *xc = (XcObject *)self;
45 u32 dom;
46 char *corefile;
48 static char *kwd_list[] = { "dom", "corefile", NULL };
50 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list,
51 &dom, &corefile) )
52 goto exit;
54 if ( (corefile == NULL) || (corefile[0] == '\0') )
55 goto exit;
57 if ( xc_domain_dumpcore(xc->xc_handle, dom, corefile) != 0 )
58 return PyErr_SetFromErrno(xc_error);
60 Py_INCREF(zero);
61 return zero;
63 exit:
64 return NULL;
65 }
67 static PyObject *pyxc_handle(PyObject *self)
68 {
69 XcObject *xc = (XcObject *)self;
71 return PyInt_FromLong(xc->xc_handle);
72 }
74 static PyObject *pyxc_domain_create(PyObject *self,
75 PyObject *args,
76 PyObject *kwds)
77 {
78 XcObject *xc = (XcObject *)self;
80 u32 dom = 0;
81 int ret;
82 u32 ssidref = 0x0;
84 static char *kwd_list[] = { "dom", "ssidref", NULL };
86 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
87 &dom, &ssidref))
88 return NULL;
90 if ( (ret = xc_domain_create(xc->xc_handle, ssidref, &dom)) < 0 )
91 return PyErr_SetFromErrno(xc_error);
93 return PyInt_FromLong(dom);
94 }
96 static PyObject *pyxc_domain_pause(PyObject *self,
97 PyObject *args,
98 PyObject *kwds)
99 {
100 XcObject *xc = (XcObject *)self;
102 u32 dom;
104 static char *kwd_list[] = { "dom", NULL };
106 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
107 return NULL;
109 if ( xc_domain_pause(xc->xc_handle, dom) != 0 )
110 return PyErr_SetFromErrno(xc_error);
112 Py_INCREF(zero);
113 return zero;
114 }
116 static PyObject *pyxc_domain_unpause(PyObject *self,
117 PyObject *args,
118 PyObject *kwds)
119 {
120 XcObject *xc = (XcObject *)self;
122 u32 dom;
124 static char *kwd_list[] = { "dom", NULL };
126 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
127 return NULL;
129 if ( xc_domain_unpause(xc->xc_handle, dom) != 0 )
130 return PyErr_SetFromErrno(xc_error);
132 Py_INCREF(zero);
133 return zero;
134 }
136 static PyObject *pyxc_domain_destroy(PyObject *self,
137 PyObject *args,
138 PyObject *kwds)
139 {
140 XcObject *xc = (XcObject *)self;
142 u32 dom;
144 static char *kwd_list[] = { "dom", NULL };
146 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
147 return NULL;
149 if ( xc_domain_destroy(xc->xc_handle, dom) != 0 )
150 return PyErr_SetFromErrno(xc_error);
152 Py_INCREF(zero);
153 return zero;
154 }
156 static PyObject *pyxc_domain_pincpu(PyObject *self,
157 PyObject *args,
158 PyObject *kwds)
159 {
160 XcObject *xc = (XcObject *)self;
162 u32 dom;
163 int vcpu = 0;
164 cpumap_t cpumap = 0xFFFFFFFF;
166 static char *kwd_list[] = { "dom", "vcpu", "cpumap", NULL };
168 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
169 &dom, &vcpu, &cpumap) )
170 return NULL;
172 if ( xc_domain_pincpu(xc->xc_handle, dom, vcpu, &cpumap) != 0 )
173 return PyErr_SetFromErrno(xc_error);
175 Py_INCREF(zero);
176 return zero;
177 }
179 static PyObject *pyxc_domain_setcpuweight(PyObject *self,
180 PyObject *args,
181 PyObject *kwds)
182 {
183 XcObject *xc = (XcObject *)self;
185 u32 dom;
186 float cpuweight = 1;
188 static char *kwd_list[] = { "dom", "cpuweight", NULL };
190 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|f", kwd_list,
191 &dom, &cpuweight) )
192 return NULL;
194 if ( xc_domain_setcpuweight(xc->xc_handle, dom, cpuweight) != 0 )
195 return PyErr_SetFromErrno(xc_error);
197 Py_INCREF(zero);
198 return zero;
199 }
201 static PyObject *pyxc_domain_getinfo(PyObject *self,
202 PyObject *args,
203 PyObject *kwds)
204 {
205 XcObject *xc = (XcObject *)self;
206 PyObject *list, *vcpu_list, *cpumap_list, *info_dict;
208 u32 first_dom = 0;
209 int max_doms = 1024, nr_doms, i, j;
210 xc_dominfo_t *info;
212 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
214 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
215 &first_dom, &max_doms) )
216 return NULL;
218 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
219 return PyErr_NoMemory();
221 nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
223 if (nr_doms < 0)
224 {
225 free(info);
226 return PyErr_SetFromErrno(xc_error);
227 }
229 list = PyList_New(nr_doms);
230 for ( i = 0 ; i < nr_doms; i++ )
231 {
232 vcpu_list = PyList_New(MAX_VIRT_CPUS);
233 cpumap_list = PyList_New(MAX_VIRT_CPUS);
234 for ( j = 0; j < MAX_VIRT_CPUS; j++ ) {
235 PyList_SetItem( vcpu_list, j,
236 Py_BuildValue("i", info[i].vcpu_to_cpu[j]));
237 PyList_SetItem( cpumap_list, j,
238 Py_BuildValue("i", info[i].cpumap[j]));
239 }
241 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
242 ",s:l,s:L,s:l,s:i,s:i}",
243 "dom", info[i].domid,
244 "vcpus", info[i].vcpus,
245 "dying", info[i].dying,
246 "crashed", info[i].crashed,
247 "shutdown", info[i].shutdown,
248 "paused", info[i].paused,
249 "blocked", info[i].blocked,
250 "running", info[i].running,
251 "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
252 "cpu_time", info[i].cpu_time,
253 "maxmem_kb", info[i].max_memkb,
254 "ssidref", info[i].ssidref,
255 "shutdown_reason", info[i].shutdown_reason);
256 PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list );
257 PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
258 PyList_SetItem( list, i, info_dict);
260 }
262 free(info);
264 return list;
265 }
267 static PyObject *pyxc_linux_build(PyObject *self,
268 PyObject *args,
269 PyObject *kwds)
270 {
271 XcObject *xc = (XcObject *)self;
273 u32 dom;
274 char *image, *ramdisk = NULL, *cmdline = "";
275 int flags = 0, vcpus = 1;
276 int store_evtchn, console_evtchn;
277 unsigned long store_mfn = 0;
278 unsigned long console_mfn = 0;
280 static char *kwd_list[] = { "dom", "store_evtchn",
281 "console_evtchn", "image",
282 /* optional */
283 "ramdisk", "cmdline", "flags",
284 "vcpus", NULL };
286 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssii", kwd_list,
287 &dom, &store_evtchn,
288 &console_evtchn, &image,
289 /* optional */
290 &ramdisk, &cmdline, &flags,
291 &vcpus) )
292 return NULL;
294 if ( xc_linux_build(xc->xc_handle, dom, image,
295 ramdisk, cmdline, flags, vcpus,
296 store_evtchn, &store_mfn,
297 console_evtchn, &console_mfn) != 0 )
298 return PyErr_SetFromErrno(xc_error);
300 return Py_BuildValue("{s:i,s:i}",
301 "store_mfn", store_mfn,
302 "console_mfn", console_mfn);
303 }
305 static PyObject *pyxc_vmx_build(PyObject *self,
306 PyObject *args,
307 PyObject *kwds)
308 {
309 XcObject *xc = (XcObject *)self;
311 u32 dom;
312 char *image;
313 int control_evtchn, store_evtchn;
314 int flags = 0, vcpus = 1;
315 int memsize;
316 unsigned long store_mfn = 0;
318 static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
319 "memsize", "image", "flags", "vcpus", NULL };
321 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
322 &dom, &control_evtchn, &store_evtchn,
323 &memsize, &image, &flags, &vcpus) )
324 return NULL;
326 if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn,
327 flags, vcpus, store_evtchn, &store_mfn) != 0 )
328 return PyErr_SetFromErrno(xc_error);
330 return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
331 }
333 static PyObject *pyxc_bvtsched_global_set(PyObject *self,
334 PyObject *args,
335 PyObject *kwds)
336 {
337 XcObject *xc = (XcObject *)self;
339 unsigned long ctx_allow;
341 static char *kwd_list[] = { "ctx_allow", NULL };
343 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
344 return NULL;
346 if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
347 return PyErr_SetFromErrno(xc_error);
349 Py_INCREF(zero);
350 return zero;
351 }
353 static PyObject *pyxc_bvtsched_global_get(PyObject *self,
354 PyObject *args,
355 PyObject *kwds)
356 {
357 XcObject *xc = (XcObject *)self;
359 unsigned long ctx_allow;
361 if ( !PyArg_ParseTuple(args, "") )
362 return NULL;
364 if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
365 return PyErr_SetFromErrno(xc_error);
367 return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
368 }
370 static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
371 PyObject *args,
372 PyObject *kwds)
373 {
374 XcObject *xc = (XcObject *)self;
376 u32 dom;
377 u32 mcuadv;
378 int warpback;
379 s32 warpvalue;
380 long long warpl;
381 long long warpu;
383 static char *kwd_list[] = { "dom", "mcuadv", "warpback", "warpvalue",
384 "warpl", "warpu", NULL };
386 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiiLL", kwd_list,
387 &dom, &mcuadv, &warpback, &warpvalue,
388 &warpl, &warpu) )
389 return NULL;
391 if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
392 warpback, warpvalue, warpl, warpu) != 0 )
393 return PyErr_SetFromErrno(xc_error);
395 Py_INCREF(zero);
396 return zero;
397 }
399 static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
400 PyObject *args,
401 PyObject *kwds)
402 {
403 XcObject *xc = (XcObject *)self;
404 u32 dom;
405 u32 mcuadv;
406 int warpback;
407 s32 warpvalue;
408 long long warpl;
409 long long warpu;
411 static char *kwd_list[] = { "dom", NULL };
413 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
414 return NULL;
416 if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warpback,
417 &warpvalue, &warpl, &warpu) != 0 )
418 return PyErr_SetFromErrno(xc_error);
420 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
421 "domain", dom,
422 "mcuadv", mcuadv,
423 "warpback", warpback,
424 "warpvalue", warpvalue,
425 "warpl", warpl,
426 "warpu", warpu);
427 }
429 static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
430 PyObject *args,
431 PyObject *kwds)
432 {
433 XcObject *xc = (XcObject *)self;
435 u32 dom = DOMID_SELF, remote_dom;
436 int port = 0;
438 static char *kwd_list[] = { "remote_dom", "dom", NULL };
440 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
441 &remote_dom, &dom) )
442 return NULL;
444 if ( xc_evtchn_alloc_unbound(xc->xc_handle, remote_dom, dom, &port) != 0 )
445 return PyErr_SetFromErrno(xc_error);
447 return PyInt_FromLong(port);
448 }
450 static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
451 PyObject *args,
452 PyObject *kwds)
453 {
454 XcObject *xc = (XcObject *)self;
456 u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
457 int port1 = 0, port2 = 0;
459 static char *kwd_list[] = { "dom1", "dom2", "port1", "port2", NULL };
461 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiii", kwd_list,
462 &dom1, &dom2, &port1, &port2) )
463 return NULL;
465 if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
466 dom2, &port1, &port2) != 0 )
467 return PyErr_SetFromErrno(xc_error);
469 return Py_BuildValue("{s:i,s:i}",
470 "port1", port1,
471 "port2", port2);
472 }
474 static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
475 PyObject *args,
476 PyObject *kwds)
477 {
478 XcObject *xc = (XcObject *)self;
480 int virq, port;
482 static char *kwd_list[] = { "virq", NULL };
484 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
485 return NULL;
487 if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
488 return PyErr_SetFromErrno(xc_error);
490 return PyInt_FromLong(port);
491 }
493 static PyObject *pyxc_evtchn_close(PyObject *self,
494 PyObject *args,
495 PyObject *kwds)
496 {
497 XcObject *xc = (XcObject *)self;
499 u32 dom = DOMID_SELF;
500 int port;
502 static char *kwd_list[] = { "port", "dom", NULL };
504 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
505 &port, &dom) )
506 return NULL;
508 if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
509 return PyErr_SetFromErrno(xc_error);
511 Py_INCREF(zero);
512 return zero;
513 }
515 static PyObject *pyxc_evtchn_send(PyObject *self,
516 PyObject *args,
517 PyObject *kwds)
518 {
519 XcObject *xc = (XcObject *)self;
521 int port;
523 static char *kwd_list[] = { "port", NULL };
525 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
526 return NULL;
528 if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
529 return PyErr_SetFromErrno(xc_error);
531 Py_INCREF(zero);
532 return zero;
533 }
535 static PyObject *pyxc_evtchn_status(PyObject *self,
536 PyObject *args,
537 PyObject *kwds)
538 {
539 XcObject *xc = (XcObject *)self;
540 PyObject *dict;
542 u32 dom = DOMID_SELF;
543 int port, ret;
544 xc_evtchn_status_t status;
546 static char *kwd_list[] = { "port", "dom", NULL };
548 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
549 &port, &dom) )
550 return NULL;
552 ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
553 if ( ret != 0 )
554 return PyErr_SetFromErrno(xc_error);
556 switch ( status.status )
557 {
558 case EVTCHNSTAT_closed:
559 dict = Py_BuildValue("{s:s}",
560 "status", "closed");
561 break;
562 case EVTCHNSTAT_unbound:
563 dict = Py_BuildValue("{s:s}",
564 "status", "unbound");
565 break;
566 case EVTCHNSTAT_interdomain:
567 dict = Py_BuildValue("{s:s,s:i,s:i}",
568 "status", "interdomain",
569 "dom", status.u.interdomain.dom,
570 "port", status.u.interdomain.port);
571 break;
572 case EVTCHNSTAT_pirq:
573 dict = Py_BuildValue("{s:s,s:i}",
574 "status", "pirq",
575 "irq", status.u.pirq);
576 break;
577 case EVTCHNSTAT_virq:
578 dict = Py_BuildValue("{s:s,s:i}",
579 "status", "virq",
580 "irq", status.u.virq);
581 break;
582 default:
583 dict = Py_BuildValue("{}");
584 break;
585 }
587 return dict;
588 }
590 static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
591 PyObject *args,
592 PyObject *kwds)
593 {
594 XcObject *xc = (XcObject *)self;
595 u32 dom;
596 int bus, dev, func, enable, ret;
598 static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
600 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
601 &dom, &bus, &dev, &func, &enable) )
602 return NULL;
604 ret = xc_physdev_pci_access_modify(
605 xc->xc_handle, dom, bus, dev, func, enable);
606 if ( ret != 0 )
607 return PyErr_SetFromErrno(xc_error);
609 Py_INCREF(zero);
610 return zero;
611 }
613 static PyObject *pyxc_readconsolering(PyObject *self,
614 PyObject *args,
615 PyObject *kwds)
616 {
617 XcObject *xc = (XcObject *)self;
619 unsigned int clear = 0;
620 char _str[32768], *str = _str;
621 unsigned int count = 32768;
622 int ret;
624 static char *kwd_list[] = { "clear", NULL };
626 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
627 return NULL;
629 ret = xc_readconsolering(xc->xc_handle, &str, &count, clear);
630 if ( ret < 0 )
631 return PyErr_SetFromErrno(xc_error);
633 return PyString_FromStringAndSize(str, count);
634 }
636 static PyObject *pyxc_physinfo(PyObject *self,
637 PyObject *args,
638 PyObject *kwds)
639 {
640 XcObject *xc = (XcObject *)self;
641 xc_physinfo_t info;
642 char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
643 int i;
645 if ( !PyArg_ParseTuple(args, "") )
646 return NULL;
648 if ( xc_physinfo(xc->xc_handle, &info) != 0 )
649 return PyErr_SetFromErrno(xc_error);
651 *q=0;
652 for(i=0;i<sizeof(info.hw_cap)/4;i++)
653 {
654 p+=sprintf(p,"%08x:",info.hw_cap[i]);
655 if(info.hw_cap[i])
656 q=p;
657 }
658 if(q>cpu_cap)
659 *(q-1)=0;
661 return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i,s:s}",
662 "threads_per_core", info.threads_per_core,
663 "cores_per_socket", info.cores_per_socket,
664 "sockets_per_node", info.sockets_per_node,
665 "nr_nodes", info.nr_nodes,
666 "total_pages", info.total_pages,
667 "free_pages", info.free_pages,
668 "cpu_khz", info.cpu_khz,
669 "hw_caps", cpu_cap);
670 }
672 static PyObject *pyxc_xeninfo(PyObject *self,
673 PyObject *args,
674 PyObject *kwds)
675 {
676 XcObject *xc = (XcObject *)self;
677 xen_extraversion_t xen_extra;
678 xen_compile_info_t xen_cc;
679 xen_changeset_info_t xen_chgset;
680 xen_capabilities_info_t xen_caps;
681 xen_parameters_info_t xen_parms;
682 long xen_version;
683 char str[128];
685 xen_version = xc_version(xc->xc_handle, XENVER_version, NULL);
687 if ( xc_version(xc->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
688 return PyErr_SetFromErrno(xc_error);
690 if ( xc_version(xc->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
691 return PyErr_SetFromErrno(xc_error);
693 if ( xc_version(xc->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
694 return PyErr_SetFromErrno(xc_error);
696 if ( xc_version(xc->xc_handle, XENVER_capabilities, &xen_caps) != 0 )
697 return PyErr_SetFromErrno(xc_error);
699 if ( xc_version(xc->xc_handle, XENVER_parameters, &xen_parms) != 0 )
700 return PyErr_SetFromErrno(xc_error);
702 sprintf(str,"virt_start=0x%lx",xen_parms.virt_start);
704 return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s,s:s,s:s}",
705 "xen_major", xen_version >> 16,
706 "xen_minor", (xen_version & 0xffff),
707 "xen_extra", xen_extra,
708 "xen_caps", xen_caps,
709 "xen_params", str,
710 "xen_changeset", xen_chgset,
711 "cc_compiler", xen_cc.compiler,
712 "cc_compile_by", xen_cc.compile_by,
713 "cc_compile_domain", xen_cc.compile_domain,
714 "cc_compile_date", xen_cc.compile_date);
715 }
718 static PyObject *pyxc_sedf_domain_set(PyObject *self,
719 PyObject *args,
720 PyObject *kwds)
721 {
722 XcObject *xc = (XcObject *)self;
723 u32 domid;
724 u64 period, slice, latency;
725 u16 extratime, weight;
726 static char *kwd_list[] = { "dom", "period", "slice",
727 "latency", "extratime", "weight",NULL };
729 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list,
730 &domid, &period, &slice,
731 &latency, &extratime, &weight) )
732 return NULL;
733 if ( xc_sedf_domain_set(xc->xc_handle, domid, period,
734 slice, latency, extratime,weight) != 0 )
735 return PyErr_SetFromErrno(xc_error);
737 Py_INCREF(zero);
738 return zero;
739 }
741 static PyObject *pyxc_sedf_domain_get(PyObject *self,
742 PyObject *args,
743 PyObject *kwds)
744 {
745 XcObject *xc = (XcObject *)self;
746 u32 domid;
747 u64 period, slice,latency;
748 u16 weight, extratime;
750 static char *kwd_list[] = { "dom", NULL };
752 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
753 return NULL;
755 if ( xc_sedf_domain_get( xc->xc_handle, domid, &period,
756 &slice,&latency,&extratime,&weight) )
757 return PyErr_SetFromErrno(xc_error);
759 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
760 "domain", domid,
761 "period", period,
762 "slice", slice,
763 "latency", latency,
764 "extratime", extratime);
765 }
767 static PyObject *pyxc_shadow_control(PyObject *self,
768 PyObject *args,
769 PyObject *kwds)
770 {
771 XcObject *xc = (XcObject *)self;
773 u32 dom;
774 int op=0;
776 static char *kwd_list[] = { "dom", "op", NULL };
778 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
779 &dom, &op) )
780 return NULL;
782 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
783 return PyErr_SetFromErrno(xc_error);
785 Py_INCREF(zero);
786 return zero;
787 }
789 static PyObject *pyxc_domain_setmaxmem(PyObject *self,
790 PyObject *args,
791 PyObject *kwds)
792 {
793 XcObject *xc = (XcObject *)self;
795 u32 dom;
796 unsigned int maxmem_kb;
798 static char *kwd_list[] = { "dom", "maxmem_kb", NULL };
800 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
801 &dom, &maxmem_kb) )
802 return NULL;
804 if ( xc_domain_setmaxmem(xc->xc_handle, dom, maxmem_kb) != 0 )
805 return PyErr_SetFromErrno(xc_error);
807 Py_INCREF(zero);
808 return zero;
809 }
811 static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
812 PyObject *args,
813 PyObject *kwds)
814 {
815 XcObject *xc = (XcObject *)self;
817 u32 dom;
818 unsigned long mem_kb;
819 unsigned int extent_order = 0 , address_bits = 0;
820 unsigned long nr_extents;
822 static char *kwd_list[] = { "dom", "mem_kb", "extent_order", "address_bits", NULL };
824 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list,
825 &dom, &mem_kb, &extent_order, &address_bits) )
826 return NULL;
828 /* round down to nearest power of 2. Assume callers using extent_order>0
829 know what they are doing */
830 nr_extents = (mem_kb / (XC_PAGE_SIZE/1024)) >> extent_order;
831 if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom,
832 nr_extents, extent_order,
833 address_bits, NULL) )
834 return PyErr_SetFromErrno(xc_error);
836 Py_INCREF(zero);
837 return zero;
838 }
840 static PyObject *pyxc_init_store(PyObject *self, PyObject *args,
841 PyObject *kwds)
842 {
843 XcObject *xc = (XcObject *)self;
845 int remote_port;
847 static char *kwd_list[] = { "remote_port", NULL };
849 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
850 &remote_port) )
851 return NULL;
853 return PyInt_FromLong(xc_init_store(xc->xc_handle, remote_port));
854 }
857 static PyMethodDef pyxc_methods[] = {
858 { "handle",
859 (PyCFunction)pyxc_handle,
860 0, "\n"
861 "Query the xc control interface file descriptor.\n\n"
862 "Returns: [int] file descriptor\n" },
864 { "domain_create",
865 (PyCFunction)pyxc_domain_create,
866 METH_VARARGS | METH_KEYWORDS, "\n"
867 "Create a new domain.\n"
868 " dom [int, 0]: Domain identifier to use (allocated if zero).\n"
869 "Returns: [int] new domain identifier; -1 on error.\n" },
871 { "domain_dumpcore",
872 (PyCFunction)pyxc_domain_dumpcore,
873 METH_VARARGS | METH_KEYWORDS, "\n"
874 "Dump core of a domain.\n"
875 " dom [int]: Identifier of domain to dump core of.\n"
876 " corefile [string]: Name of corefile to be created.\n\n"
877 "Returns: [int] 0 on success; -1 on error.\n" },
879 { "domain_pause",
880 (PyCFunction)pyxc_domain_pause,
881 METH_VARARGS | METH_KEYWORDS, "\n"
882 "Temporarily pause execution of a domain.\n"
883 " dom [int]: Identifier of domain to be paused.\n\n"
884 "Returns: [int] 0 on success; -1 on error.\n" },
886 { "domain_unpause",
887 (PyCFunction)pyxc_domain_unpause,
888 METH_VARARGS | METH_KEYWORDS, "\n"
889 "(Re)start execution of a domain.\n"
890 " dom [int]: Identifier of domain to be unpaused.\n\n"
891 "Returns: [int] 0 on success; -1 on error.\n" },
893 { "domain_destroy",
894 (PyCFunction)pyxc_domain_destroy,
895 METH_VARARGS | METH_KEYWORDS, "\n"
896 "Destroy a domain.\n"
897 " dom [int]: Identifier of domain to be destroyed.\n\n"
898 "Returns: [int] 0 on success; -1 on error.\n" },
900 { "domain_pincpu",
901 (PyCFunction)pyxc_domain_pincpu,
902 METH_VARARGS | METH_KEYWORDS, "\n"
903 "Pin a VCPU to a specified set CPUs.\n"
904 " dom [int]: Identifier of domain to which VCPU belongs.\n"
905 " vcpu [int, 0]: VCPU being pinned.\n"
906 " cpumap [int, -1]: Bitmap of usable CPUs.\n\n"
907 "Returns: [int] 0 on success; -1 on error.\n" },
909 { "domain_setcpuweight",
910 (PyCFunction)pyxc_domain_setcpuweight,
911 METH_VARARGS | METH_KEYWORDS, "\n"
912 "Set cpuweight scheduler parameter for domain.\n"
913 " dom [int]: Identifier of domain to be changed.\n"
914 " cpuweight [float, 1]: VCPU being pinned.\n"
915 "Returns: [int] 0 on success; -1 on error.\n" },
917 { "domain_getinfo",
918 (PyCFunction)pyxc_domain_getinfo,
919 METH_VARARGS | METH_KEYWORDS, "\n"
920 "Get information regarding a set of domains, in increasing id order.\n"
921 " first_dom [int, 0]: First domain to retrieve info about.\n"
922 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
923 " about.\n\n"
924 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
925 " parameter then there was an error, or the end of the\n"
926 " domain-id space was reached.\n"
927 " dom [int]: Identifier of domain to which this info pertains\n"
928 " cpu [int]: CPU to which this domain is bound\n"
929 " vcpus [int]: Number of Virtual CPUS in this domain\n"
930 " dying [int]: Bool - is the domain dying?\n"
931 " crashed [int]: Bool - has the domain crashed?\n"
932 " shutdown [int]: Bool - has the domain shut itself down?\n"
933 " paused [int]: Bool - is the domain paused by control software?\n"
934 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
935 " running [int]: Bool - is the domain currently running?\n"
936 " mem_kb [int]: Memory reservation, in kilobytes\n"
937 " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
938 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
939 " shutdown_reason [int]: Numeric code from guest OS, explaining "
940 "reason why it shut itself down.\n"
941 " vcpu_to_cpu [[int]]: List that maps VCPUS to CPUS\n" },
943 { "linux_build",
944 (PyCFunction)pyxc_linux_build,
945 METH_VARARGS | METH_KEYWORDS, "\n"
946 "Build a new Linux guest OS.\n"
947 " dom [int]: Identifier of domain to build into.\n"
948 " image [str]: Name of kernel image file. May be gzipped.\n"
949 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
950 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
951 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
952 "Returns: [int] 0 on success; -1 on error.\n" },
954 { "vmx_build",
955 (PyCFunction)pyxc_vmx_build,
956 METH_VARARGS | METH_KEYWORDS, "\n"
957 "Build a new Linux guest OS.\n"
958 " dom [int]: Identifier of domain to build into.\n"
959 " image [str]: Name of kernel image file. May be gzipped.\n"
960 " memmap [str]: Memory map.\n\n"
961 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
962 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
963 "Returns: [int] 0 on success; -1 on error.\n" },
965 { "bvtsched_global_set",
966 (PyCFunction)pyxc_bvtsched_global_set,
967 METH_VARARGS | METH_KEYWORDS, "\n"
968 "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
969 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
970 "Returns: [int] 0 on success; -1 on error.\n" },
972 { "bvtsched_global_get",
973 (PyCFunction)pyxc_bvtsched_global_get,
974 METH_KEYWORDS, "\n"
975 "Get global tuning parameters for BVT scheduler.\n"
976 "Returns: [dict]:\n"
977 " ctx_allow [int]: context switch allowance\n" },
979 { "bvtsched_domain_set",
980 (PyCFunction)pyxc_bvtsched_domain_set,
981 METH_VARARGS | METH_KEYWORDS, "\n"
982 "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
983 " dom [int]: Identifier of domain to be tuned.\n"
984 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
985 " warpback [int]: Warp ? \n"
986 " warpvalue [int]: How far to warp domain's EVT on unblock.\n"
987 " warpl [int]: How long the domain can run warped.\n"
988 " warpu [int]: How long before the domain can warp again.\n\n"
989 "Returns: [int] 0 on success; -1 on error.\n" },
991 { "bvtsched_domain_get",
992 (PyCFunction)pyxc_bvtsched_domain_get,
993 METH_KEYWORDS, "\n"
994 "Get per-domain tuning parameters under the BVT scheduler.\n"
995 " dom [int]: Identifier of domain to be queried.\n"
996 "Returns [dict]:\n"
997 " domain [int]: Domain ID.\n"
998 " mcuadv [long]: MCU Advance.\n"
999 " warp [long]: Warp.\n"
1000 " warpu [long]: Unwarp requirement.\n"
1001 " warpl [long]: Warp limit,\n"
1002 },
1004 { "sedf_domain_set",
1005 (PyCFunction)pyxc_sedf_domain_set,
1006 METH_KEYWORDS, "\n"
1007 "Set the scheduling parameters for a domain when running with Atropos.\n"
1008 " dom [int]: domain to set\n"
1009 " period [long]: domain's scheduling period\n"
1010 " slice [long]: domain's slice per period\n"
1011 " latency [long]: domain's wakeup latency hint\n"
1012 " extratime [int]: domain aware of extratime?\n"
1013 "Returns: [int] 0 on success; -1 on error.\n" },
1015 { "sedf_domain_get",
1016 (PyCFunction)pyxc_sedf_domain_get,
1017 METH_KEYWORDS, "\n"
1018 "Get the current scheduling parameters for a domain when running with\n"
1019 "the Atropos scheduler."
1020 " dom [int]: domain to query\n"
1021 "Returns: [dict]\n"
1022 " domain [int]: domain ID\n"
1023 " period [long]: scheduler period\n"
1024 " slice [long]: CPU reservation per period\n"
1025 " latency [long]: domain's wakeup latency hint\n"
1026 " extratime [int]: domain aware of extratime?\n"},
1028 { "evtchn_alloc_unbound",
1029 (PyCFunction)pyxc_evtchn_alloc_unbound,
1030 METH_VARARGS | METH_KEYWORDS, "\n"
1031 "Allocate an unbound local port that will await a remote connection.\n"
1032 " dom [int]: Remote domain to accept connections from.\n\n"
1033 "Returns: [int] Unbound event-channel port.\n" },
1035 { "evtchn_bind_interdomain",
1036 (PyCFunction)pyxc_evtchn_bind_interdomain,
1037 METH_VARARGS | METH_KEYWORDS, "\n"
1038 "Open an event channel between two domains.\n"
1039 " dom1 [int, SELF]: First domain to be connected.\n"
1040 " dom2 [int, SELF]: Second domain to be connected.\n\n"
1041 "Returns: [dict] dictionary is empty on failure.\n"
1042 " port1 [int]: Port-id for endpoint at dom1.\n"
1043 " port2 [int]: Port-id for endpoint at dom2.\n" },
1045 { "evtchn_bind_virq",
1046 (PyCFunction)pyxc_evtchn_bind_virq,
1047 METH_VARARGS | METH_KEYWORDS, "\n"
1048 "Bind an event channel to the specified VIRQ.\n"
1049 " virq [int]: VIRQ to bind.\n\n"
1050 "Returns: [int] Bound event-channel port.\n" },
1052 { "evtchn_close",
1053 (PyCFunction)pyxc_evtchn_close,
1054 METH_VARARGS | METH_KEYWORDS, "\n"
1055 "Close an event channel. If interdomain, sets remote end to 'unbound'.\n"
1056 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1057 " port [int]: Port-id of one endpoint of the channel.\n\n"
1058 "Returns: [int] 0 on success; -1 on error.\n" },
1060 { "evtchn_send",
1061 (PyCFunction)pyxc_evtchn_send,
1062 METH_VARARGS | METH_KEYWORDS, "\n"
1063 "Send an event along a locally-connected event channel.\n"
1064 " port [int]: Port-id of a local channel endpoint.\n\n"
1065 "Returns: [int] 0 on success; -1 on error.\n" },
1067 { "evtchn_status",
1068 (PyCFunction)pyxc_evtchn_status,
1069 METH_VARARGS | METH_KEYWORDS, "\n"
1070 "Query the status of an event channel.\n"
1071 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1072 " port [int]: Port-id of one endpoint of the channel.\n\n"
1073 "Returns: [dict] dictionary is empty on failure.\n"
1074 " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
1075 " or 'virq'.\n"
1076 "The following are returned if 'status' is 'interdomain':\n"
1077 " dom [int]: Dom-id of remote endpoint.\n"
1078 " port [int]: Port-id of remote endpoint.\n"
1079 "The following are returned if 'status' is 'pirq' or 'virq':\n"
1080 " irq [int]: IRQ number.\n" },
1082 { "physdev_pci_access_modify",
1083 (PyCFunction)pyxc_physdev_pci_access_modify,
1084 METH_VARARGS | METH_KEYWORDS, "\n"
1085 "Allow a domain access to a PCI device\n"
1086 " dom [int]: Identifier of domain to be allowed access.\n"
1087 " bus [int]: PCI bus\n"
1088 " dev [int]: PCI slot\n"
1089 " func [int]: PCI function\n"
1090 " enable [int]: Non-zero means enable access; else disable access\n\n"
1091 "Returns: [int] 0 on success; -1 on error.\n" },
1093 { "readconsolering",
1094 (PyCFunction)pyxc_readconsolering,
1095 METH_VARARGS | METH_KEYWORDS, "\n"
1096 "Read Xen's console ring.\n"
1097 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1098 "Returns: [str] string is empty on failure.\n" },
1100 { "physinfo",
1101 (PyCFunction)pyxc_physinfo,
1102 METH_VARARGS, "\n"
1103 "Get information about the physical host machine\n"
1104 "Returns [dict]: information about the hardware"
1105 " [None]: on failure.\n" },
1107 { "xeninfo",
1108 (PyCFunction)pyxc_xeninfo,
1109 METH_VARARGS, "\n"
1110 "Get information about the Xen host\n"
1111 "Returns [dict]: information about Xen"
1112 " [None]: on failure.\n" },
1114 { "shadow_control",
1115 (PyCFunction)pyxc_shadow_control,
1116 METH_VARARGS | METH_KEYWORDS, "\n"
1117 "Set parameter for shadow pagetable interface\n"
1118 " dom [int]: Identifier of domain.\n"
1119 " op [int, 0]: operation\n\n"
1120 "Returns: [int] 0 on success; -1 on error.\n" },
1122 { "domain_setmaxmem",
1123 (PyCFunction)pyxc_domain_setmaxmem,
1124 METH_VARARGS | METH_KEYWORDS, "\n"
1125 "Set a domain's memory limit\n"
1126 " dom [int]: Identifier of domain.\n"
1127 " maxmem_kb [int]: .\n"
1128 "Returns: [int] 0 on success; -1 on error.\n" },
1130 { "domain_memory_increase_reservation",
1131 (PyCFunction)pyxc_domain_memory_increase_reservation,
1132 METH_VARARGS | METH_KEYWORDS, "\n"
1133 "Increase a domain's memory reservation\n"
1134 " dom [int]: Identifier of domain.\n"
1135 " mem_kb [long]: .\n"
1136 "Returns: [int] 0 on success; -1 on error.\n" },
1138 { "init_store",
1139 (PyCFunction)pyxc_init_store,
1140 METH_VARARGS | METH_KEYWORDS, "\n"
1141 "Initialize the store event channel and return the store page mfn.\n"
1142 " remote_port [int]: store event channel port number.\n"
1143 "Returns: [int] mfn on success; <0 on error.\n" },
1145 { NULL, NULL, 0, NULL }
1146 };
1149 /*
1150 * Definitions for the 'Xc' module wrapper.
1151 */
1153 staticforward PyTypeObject PyXcType;
1155 static PyObject *PyXc_new(PyObject *self, PyObject *args)
1157 XcObject *xc;
1159 if ( !PyArg_ParseTuple(args, ":new") )
1160 return NULL;
1162 xc = PyObject_New(XcObject, &PyXcType);
1164 if ( (xc->xc_handle = xc_interface_open()) == -1 )
1166 PyObject_Del((PyObject *)xc);
1167 return PyErr_SetFromErrno(xc_error);
1170 return (PyObject *)xc;
1173 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1175 return Py_FindMethod(pyxc_methods, obj, name);
1178 static void PyXc_dealloc(PyObject *self)
1180 XcObject *xc = (XcObject *)self;
1181 (void)xc_interface_close(xc->xc_handle);
1182 PyObject_Del(self);
1185 static PyTypeObject PyXcType = {
1186 PyObject_HEAD_INIT(&PyType_Type)
1187 0,
1188 "Xc",
1189 sizeof(XcObject),
1190 0,
1191 PyXc_dealloc, /* tp_dealloc */
1192 NULL, /* tp_print */
1193 PyXc_getattr, /* tp_getattr */
1194 NULL, /* tp_setattr */
1195 NULL, /* tp_compare */
1196 NULL, /* tp_repr */
1197 NULL, /* tp_as_number */
1198 NULL, /* tp_as_sequence */
1199 NULL, /* tp_as_mapping */
1200 NULL /* tp_hash */
1201 };
1203 static PyMethodDef PyXc_methods[] = {
1204 { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
1205 { NULL, NULL, 0, NULL }
1206 };
1208 PyMODINIT_FUNC initxc(void)
1210 PyObject *m, *d;
1212 m = Py_InitModule(XENPKG, PyXc_methods);
1214 d = PyModule_GetDict(m);
1215 xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
1216 PyDict_SetItemString(d, "error", xc_error);
1217 PyDict_SetItemString(d, "VIRQ_DOM_EXC", PyInt_FromLong(VIRQ_DOM_EXC));
1219 zero = PyInt_FromLong(0);
1221 /* KAF: This ensures that we get debug output in a timely manner. */
1222 setbuf(stdout, NULL);
1223 setbuf(stderr, NULL);