ia64/xen-unstable

view tools/python/xen/lowlevel/xc/xc.c @ 6700:12ff9c954ace

Give each domain some memory below 4GB. This solves the "PGD's must be below 4GB" for the initial page tables. I'm not sure we'll stick with this approach, but this is good enough for the time being.

PAE should be a *lot* more robust on systems that actually have more than 4GB thanks to all the various patches that went in today. I find it astounding that it ever appeared to work at all!

Signed-off-by: ian@xensource.com
author iap10@freefall.cl.cam.ac.uk
date Thu Sep 08 01:07:15 2005 +0000 (2005-09-08)
parents 7d0fb56b4a91
children 5db85ba1c4e0 3bde4219c681 aa0990ef260f
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 list = PyList_New(nr_doms);
225 for ( i = 0 ; i < nr_doms; i++ )
226 {
227 vcpu_list = PyList_New(MAX_VIRT_CPUS);
228 cpumap_list = PyList_New(MAX_VIRT_CPUS);
229 for ( j = 0; j < MAX_VIRT_CPUS; j++ ) {
230 PyList_SetItem( vcpu_list, j,
231 Py_BuildValue("i", info[i].vcpu_to_cpu[j]));
232 PyList_SetItem( cpumap_list, j,
233 Py_BuildValue("i", info[i].cpumap[j]));
234 }
236 info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
237 ",s:l,s:L,s:l,s:i,s:i}",
238 "dom", info[i].domid,
239 "vcpus", info[i].vcpus,
240 "dying", info[i].dying,
241 "crashed", info[i].crashed,
242 "shutdown", info[i].shutdown,
243 "paused", info[i].paused,
244 "blocked", info[i].blocked,
245 "running", info[i].running,
246 "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024),
247 "cpu_time", info[i].cpu_time,
248 "maxmem_kb", info[i].max_memkb,
249 "ssidref", info[i].ssidref,
250 "shutdown_reason", info[i].shutdown_reason);
251 PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list );
252 PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
253 PyList_SetItem( list, i, info_dict);
255 }
257 free(info);
259 return list;
260 }
262 static PyObject *pyxc_linux_build(PyObject *self,
263 PyObject *args,
264 PyObject *kwds)
265 {
266 XcObject *xc = (XcObject *)self;
268 u32 dom;
269 char *image, *ramdisk = NULL, *cmdline = "";
270 int flags = 0, vcpus = 1;
271 int store_evtchn, console_evtchn;
272 unsigned long store_mfn = 0;
273 unsigned long console_mfn = 0;
275 static char *kwd_list[] = { "dom", "store_evtchn",
276 "console_evtchn", "image",
277 /* optional */
278 "ramdisk", "cmdline", "flags",
279 "vcpus", NULL };
281 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssii", kwd_list,
282 &dom, &store_evtchn,
283 &console_evtchn, &image,
284 /* optional */
285 &ramdisk, &cmdline, &flags,
286 &vcpus) )
287 return NULL;
289 if ( xc_linux_build(xc->xc_handle, dom, image,
290 ramdisk, cmdline, flags, vcpus,
291 store_evtchn, &store_mfn,
292 console_evtchn, &console_mfn) != 0 )
293 return PyErr_SetFromErrno(xc_error);
295 return Py_BuildValue("{s:i,s:i}",
296 "store_mfn", store_mfn,
297 "console_mfn", console_mfn);
298 }
300 static PyObject *pyxc_vmx_build(PyObject *self,
301 PyObject *args,
302 PyObject *kwds)
303 {
304 XcObject *xc = (XcObject *)self;
306 u32 dom;
307 char *image, *ramdisk = NULL, *cmdline = "";
308 PyObject *memmap;
309 int control_evtchn, store_evtchn;
310 int flags = 0, vcpus = 1;
311 int numItems, i;
312 int memsize;
313 struct mem_map mem_map;
314 unsigned long store_mfn = 0;
316 static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
317 "memsize", "image", "memmap",
318 "ramdisk", "cmdline", "flags",
319 "vcpus", NULL };
321 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisO!|ssii", kwd_list,
322 &dom, &control_evtchn, &store_evtchn,
323 &memsize,
324 &image, &PyList_Type, &memmap,
325 &ramdisk, &cmdline, &flags, &vcpus) )
326 return NULL;
328 memset(&mem_map, 0, sizeof(mem_map));
329 /* Parse memmap */
331 /* get the number of lines passed to us */
332 numItems = PyList_Size(memmap) - 1; /* removing the line
333 containing "memmap" */
334 mem_map.nr_map = numItems;
336 /* should raise an error here. */
337 if (numItems < 0) return NULL; /* Not a list */
339 /* iterate over items of the list, grabbing ranges and parsing them */
340 for (i = 1; i <= numItems; i++) { // skip over "memmap"
341 PyObject *item, *f1, *f2, *f3, *f4;
342 int numFields;
343 unsigned long lf1, lf2, lf3, lf4;
344 char *sf1, *sf2;
346 /* grab the string object from the next element of the list */
347 item = PyList_GetItem(memmap, i); /* Can't fail */
349 /* get the number of lines passed to us */
350 numFields = PyList_Size(item);
352 if (numFields != 4)
353 return NULL;
355 f1 = PyList_GetItem(item, 0);
356 f2 = PyList_GetItem(item, 1);
357 f3 = PyList_GetItem(item, 2);
358 f4 = PyList_GetItem(item, 3);
360 /* Convert objects to strings/longs */
361 sf1 = PyString_AsString(f1);
362 sf2 = PyString_AsString(f2);
363 lf3 = PyLong_AsLong(f3);
364 lf4 = PyLong_AsLong(f4);
365 if ( sscanf(sf1, "%lx", &lf1) != 1 )
366 return NULL;
367 if ( sscanf(sf2, "%lx", &lf2) != 1 )
368 return NULL;
370 mem_map.map[i-1].addr = lf1;
371 mem_map.map[i-1].size = lf2 - lf1;
372 mem_map.map[i-1].type = lf3;
373 mem_map.map[i-1].caching_attr = lf4;
374 }
376 if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, &mem_map,
377 ramdisk, cmdline, control_evtchn, flags,
378 vcpus, store_evtchn, &store_mfn) != 0 )
379 return PyErr_SetFromErrno(xc_error);
381 return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
382 }
384 static PyObject *pyxc_bvtsched_global_set(PyObject *self,
385 PyObject *args,
386 PyObject *kwds)
387 {
388 XcObject *xc = (XcObject *)self;
390 unsigned long ctx_allow;
392 static char *kwd_list[] = { "ctx_allow", NULL };
394 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
395 return NULL;
397 if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
398 return PyErr_SetFromErrno(xc_error);
400 Py_INCREF(zero);
401 return zero;
402 }
404 static PyObject *pyxc_bvtsched_global_get(PyObject *self,
405 PyObject *args,
406 PyObject *kwds)
407 {
408 XcObject *xc = (XcObject *)self;
410 unsigned long ctx_allow;
412 if ( !PyArg_ParseTuple(args, "") )
413 return NULL;
415 if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
416 return PyErr_SetFromErrno(xc_error);
418 return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
419 }
421 static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
422 PyObject *args,
423 PyObject *kwds)
424 {
425 XcObject *xc = (XcObject *)self;
427 u32 dom;
428 u32 mcuadv;
429 int warpback;
430 s32 warpvalue;
431 long long warpl;
432 long long warpu;
434 static char *kwd_list[] = { "dom", "mcuadv", "warpback", "warpvalue",
435 "warpl", "warpu", NULL };
437 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiiLL", kwd_list,
438 &dom, &mcuadv, &warpback, &warpvalue,
439 &warpl, &warpu) )
440 return NULL;
442 if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
443 warpback, warpvalue, warpl, warpu) != 0 )
444 return PyErr_SetFromErrno(xc_error);
446 Py_INCREF(zero);
447 return zero;
448 }
450 static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
451 PyObject *args,
452 PyObject *kwds)
453 {
454 XcObject *xc = (XcObject *)self;
455 u32 dom;
456 u32 mcuadv;
457 int warpback;
458 s32 warpvalue;
459 long long warpl;
460 long long warpu;
462 static char *kwd_list[] = { "dom", NULL };
464 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
465 return NULL;
467 if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warpback,
468 &warpvalue, &warpl, &warpu) != 0 )
469 return PyErr_SetFromErrno(xc_error);
471 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
472 "domain", dom,
473 "mcuadv", mcuadv,
474 "warpback", warpback,
475 "warpvalue", warpvalue,
476 "warpl", warpl,
477 "warpu", warpu);
478 }
480 static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
481 PyObject *args,
482 PyObject *kwds)
483 {
484 XcObject *xc = (XcObject *)self;
486 u32 dom;
487 int port = 0;
489 static char *kwd_list[] = { "dom", "port", NULL };
491 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
492 &dom, &port) )
493 return NULL;
495 if ( xc_evtchn_alloc_unbound(xc->xc_handle, dom, &port) != 0 )
496 return PyErr_SetFromErrno(xc_error);
498 return PyInt_FromLong(port);
499 }
501 static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
502 PyObject *args,
503 PyObject *kwds)
504 {
505 XcObject *xc = (XcObject *)self;
507 u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
508 int port1 = 0, port2 = 0;
510 static char *kwd_list[] = { "dom1", "dom2", "port1", "port2", NULL };
512 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiii", kwd_list,
513 &dom1, &dom2, &port1, &port2) )
514 return NULL;
516 if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
517 dom2, &port1, &port2) != 0 )
518 return PyErr_SetFromErrno(xc_error);
520 return Py_BuildValue("{s:i,s:i}",
521 "port1", port1,
522 "port2", port2);
523 }
525 static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
526 PyObject *args,
527 PyObject *kwds)
528 {
529 XcObject *xc = (XcObject *)self;
531 int virq, port;
533 static char *kwd_list[] = { "virq", NULL };
535 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
536 return NULL;
538 if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
539 return PyErr_SetFromErrno(xc_error);
541 return PyInt_FromLong(port);
542 }
544 static PyObject *pyxc_evtchn_close(PyObject *self,
545 PyObject *args,
546 PyObject *kwds)
547 {
548 XcObject *xc = (XcObject *)self;
550 u32 dom = DOMID_SELF;
551 int port;
553 static char *kwd_list[] = { "port", "dom", NULL };
555 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
556 &port, &dom) )
557 return NULL;
559 if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
560 return PyErr_SetFromErrno(xc_error);
562 Py_INCREF(zero);
563 return zero;
564 }
566 static PyObject *pyxc_evtchn_send(PyObject *self,
567 PyObject *args,
568 PyObject *kwds)
569 {
570 XcObject *xc = (XcObject *)self;
572 int port;
574 static char *kwd_list[] = { "port", NULL };
576 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
577 return NULL;
579 if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
580 return PyErr_SetFromErrno(xc_error);
582 Py_INCREF(zero);
583 return zero;
584 }
586 static PyObject *pyxc_evtchn_status(PyObject *self,
587 PyObject *args,
588 PyObject *kwds)
589 {
590 XcObject *xc = (XcObject *)self;
591 PyObject *dict;
593 u32 dom = DOMID_SELF;
594 int port, ret;
595 xc_evtchn_status_t status;
597 static char *kwd_list[] = { "port", "dom", NULL };
599 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
600 &port, &dom) )
601 return NULL;
603 ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
604 if ( ret != 0 )
605 return PyErr_SetFromErrno(xc_error);
607 switch ( status.status )
608 {
609 case EVTCHNSTAT_closed:
610 dict = Py_BuildValue("{s:s}",
611 "status", "closed");
612 break;
613 case EVTCHNSTAT_unbound:
614 dict = Py_BuildValue("{s:s}",
615 "status", "unbound");
616 break;
617 case EVTCHNSTAT_interdomain:
618 dict = Py_BuildValue("{s:s,s:i,s:i}",
619 "status", "interdomain",
620 "dom", status.u.interdomain.dom,
621 "port", status.u.interdomain.port);
622 break;
623 case EVTCHNSTAT_pirq:
624 dict = Py_BuildValue("{s:s,s:i}",
625 "status", "pirq",
626 "irq", status.u.pirq);
627 break;
628 case EVTCHNSTAT_virq:
629 dict = Py_BuildValue("{s:s,s:i}",
630 "status", "virq",
631 "irq", status.u.virq);
632 break;
633 default:
634 dict = Py_BuildValue("{}");
635 break;
636 }
638 return dict;
639 }
641 static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
642 PyObject *args,
643 PyObject *kwds)
644 {
645 XcObject *xc = (XcObject *)self;
646 u32 dom;
647 int bus, dev, func, enable, ret;
649 static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
651 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
652 &dom, &bus, &dev, &func, &enable) )
653 return NULL;
655 ret = xc_physdev_pci_access_modify(
656 xc->xc_handle, dom, bus, dev, func, enable);
657 if ( ret != 0 )
658 return PyErr_SetFromErrno(xc_error);
660 Py_INCREF(zero);
661 return zero;
662 }
664 static PyObject *pyxc_readconsolering(PyObject *self,
665 PyObject *args,
666 PyObject *kwds)
667 {
668 XcObject *xc = (XcObject *)self;
670 unsigned int clear = 0;
671 char _str[32768], *str = _str;
672 unsigned int count = 32768;
673 int ret;
675 static char *kwd_list[] = { "clear", NULL };
677 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
678 return NULL;
680 ret = xc_readconsolering(xc->xc_handle, &str, &count, clear);
681 if ( ret < 0 )
682 return PyErr_SetFromErrno(xc_error);
684 return PyString_FromStringAndSize(str, count);
685 }
687 static PyObject *pyxc_physinfo(PyObject *self,
688 PyObject *args,
689 PyObject *kwds)
690 {
691 XcObject *xc = (XcObject *)self;
692 xc_physinfo_t info;
694 if ( !PyArg_ParseTuple(args, "") )
695 return NULL;
697 if ( xc_physinfo(xc->xc_handle, &info) != 0 )
698 return PyErr_SetFromErrno(xc_error);
700 return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:i}",
701 "threads_per_core", info.threads_per_core,
702 "cores_per_socket", info.cores_per_socket,
703 "sockets_per_node", info.sockets_per_node,
704 "nr_nodes", info.nr_nodes,
705 "total_pages", info.total_pages,
706 "free_pages", info.free_pages,
707 "cpu_khz", info.cpu_khz);
708 }
710 static PyObject *pyxc_xeninfo(PyObject *self,
711 PyObject *args,
712 PyObject *kwds)
713 {
714 XcObject *xc = (XcObject *)self;
715 xen_extraversion_t xen_extra;
716 xen_compile_info_t xen_cc;
717 xen_changeset_info_t xen_chgset;
718 long xen_version;
720 xen_version = xc_version(xc->xc_handle, XENVER_version, NULL);
722 if ( xc_version(xc->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
723 return PyErr_SetFromErrno(xc_error);
725 if ( xc_version(xc->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
726 return PyErr_SetFromErrno(xc_error);
728 if ( xc_version(xc->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
729 return PyErr_SetFromErrno(xc_error);
731 return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s}",
732 "xen_major", xen_version >> 16,
733 "xen_minor", (xen_version & 0xffff),
734 "xen_extra", xen_extra,
735 "xen_changeset", xen_chgset,
736 "cc_compiler", xen_cc.compiler,
737 "cc_compile_by", xen_cc.compile_by,
738 "cc_compile_domain", xen_cc.compile_domain,
739 "cc_compile_date", xen_cc.compile_date);
740 }
743 static PyObject *pyxc_sedf_domain_set(PyObject *self,
744 PyObject *args,
745 PyObject *kwds)
746 {
747 XcObject *xc = (XcObject *)self;
748 u32 domid;
749 u64 period, slice, latency;
750 u16 extratime, weight;
751 static char *kwd_list[] = { "dom", "period", "slice",
752 "latency", "extratime", "weight",NULL };
754 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLhh", kwd_list,
755 &domid, &period, &slice,
756 &latency, &extratime, &weight) )
757 return NULL;
758 if ( xc_sedf_domain_set(xc->xc_handle, domid, period,
759 slice, latency, extratime,weight) != 0 )
760 return PyErr_SetFromErrno(xc_error);
762 Py_INCREF(zero);
763 return zero;
764 }
766 static PyObject *pyxc_sedf_domain_get(PyObject *self,
767 PyObject *args,
768 PyObject *kwds)
769 {
770 XcObject *xc = (XcObject *)self;
771 u32 domid;
772 u64 period, slice,latency;
773 u16 weight, extratime;
775 static char *kwd_list[] = { "dom", NULL };
777 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
778 return NULL;
780 if ( xc_sedf_domain_get( xc->xc_handle, domid, &period,
781 &slice,&latency,&extratime,&weight) )
782 return PyErr_SetFromErrno(xc_error);
784 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
785 "domain", domid,
786 "period", period,
787 "slice", slice,
788 "latency", latency,
789 "extratime", extratime);
790 }
792 static PyObject *pyxc_shadow_control(PyObject *self,
793 PyObject *args,
794 PyObject *kwds)
795 {
796 XcObject *xc = (XcObject *)self;
798 u32 dom;
799 int op=0;
801 static char *kwd_list[] = { "dom", "op", NULL };
803 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
804 &dom, &op) )
805 return NULL;
807 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
808 return PyErr_SetFromErrno(xc_error);
810 Py_INCREF(zero);
811 return zero;
812 }
814 static PyObject *pyxc_domain_setmaxmem(PyObject *self,
815 PyObject *args,
816 PyObject *kwds)
817 {
818 XcObject *xc = (XcObject *)self;
820 u32 dom;
821 unsigned long maxmem_kb;
823 static char *kwd_list[] = { "dom", "maxmem_kb", NULL };
825 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
826 &dom, &maxmem_kb) )
827 return NULL;
829 if ( xc_domain_setmaxmem(xc->xc_handle, dom, maxmem_kb) != 0 )
830 return PyErr_SetFromErrno(xc_error);
832 Py_INCREF(zero);
833 return zero;
834 }
836 static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
837 PyObject *args,
838 PyObject *kwds)
839 {
840 XcObject *xc = (XcObject *)self;
842 u32 dom;
843 unsigned long mem_kb;
844 unsigned int extent_order = 0 , address_bits = 0;
846 static char *kwd_list[] = { "dom", "mem_kb", "extent_order", "address_bits", NULL };
848 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii|ii", kwd_list,
849 &dom, &mem_kb, &extent_order, &address_bits) )
850 return NULL;
852 if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom,
853 mem_kb, extent_order, address_bits) )
854 return PyErr_SetFromErrno(xc_error);
856 Py_INCREF(zero);
857 return zero;
858 }
860 static PyObject *pyxc_init_store(PyObject *self, PyObject *args,
861 PyObject *kwds)
862 {
863 XcObject *xc = (XcObject *)self;
865 int remote_port;
867 static char *kwd_list[] = { "remote_port", NULL };
869 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
870 &remote_port) )
871 return NULL;
873 return PyInt_FromLong(xc_init_store(xc->xc_handle, remote_port));
874 }
877 static PyMethodDef pyxc_methods[] = {
878 { "handle",
879 (PyCFunction)pyxc_handle,
880 0, "\n"
881 "Query the xc control interface file descriptor.\n\n"
882 "Returns: [int] file descriptor\n" },
884 { "domain_create",
885 (PyCFunction)pyxc_domain_create,
886 METH_VARARGS | METH_KEYWORDS, "\n"
887 "Create a new domain.\n"
888 " dom [int, 0]: Domain identifier to use (allocated if zero).\n"
889 "Returns: [int] new domain identifier; -1 on error.\n" },
891 { "domain_dumpcore",
892 (PyCFunction)pyxc_domain_dumpcore,
893 METH_VARARGS | METH_KEYWORDS, "\n"
894 "Dump core of a domain.\n"
895 " dom [int]: Identifier of domain to dump core of.\n"
896 " corefile [string]: Name of corefile to be created.\n\n"
897 "Returns: [int] 0 on success; -1 on error.\n" },
899 { "domain_pause",
900 (PyCFunction)pyxc_domain_pause,
901 METH_VARARGS | METH_KEYWORDS, "\n"
902 "Temporarily pause execution of a domain.\n"
903 " dom [int]: Identifier of domain to be paused.\n\n"
904 "Returns: [int] 0 on success; -1 on error.\n" },
906 { "domain_unpause",
907 (PyCFunction)pyxc_domain_unpause,
908 METH_VARARGS | METH_KEYWORDS, "\n"
909 "(Re)start execution of a domain.\n"
910 " dom [int]: Identifier of domain to be unpaused.\n\n"
911 "Returns: [int] 0 on success; -1 on error.\n" },
913 { "domain_destroy",
914 (PyCFunction)pyxc_domain_destroy,
915 METH_VARARGS | METH_KEYWORDS, "\n"
916 "Destroy a domain.\n"
917 " dom [int]: Identifier of domain to be destroyed.\n\n"
918 "Returns: [int] 0 on success; -1 on error.\n" },
920 { "domain_pincpu",
921 (PyCFunction)pyxc_domain_pincpu,
922 METH_VARARGS | METH_KEYWORDS, "\n"
923 "Pin a VCPU to a specified set CPUs.\n"
924 " dom [int]: Identifier of domain to which VCPU belongs.\n"
925 " vcpu [int, 0]: VCPU being pinned.\n"
926 " cpumap [int, -1]: Bitmap of usable CPUs.\n\n"
927 "Returns: [int] 0 on success; -1 on error.\n" },
929 { "domain_setcpuweight",
930 (PyCFunction)pyxc_domain_setcpuweight,
931 METH_VARARGS | METH_KEYWORDS, "\n"
932 "Set cpuweight scheduler parameter for domain.\n"
933 " dom [int]: Identifier of domain to be changed.\n"
934 " cpuweight [float, 1]: VCPU being pinned.\n"
935 "Returns: [int] 0 on success; -1 on error.\n" },
937 { "domain_getinfo",
938 (PyCFunction)pyxc_domain_getinfo,
939 METH_VARARGS | METH_KEYWORDS, "\n"
940 "Get information regarding a set of domains, in increasing id order.\n"
941 " first_dom [int, 0]: First domain to retrieve info about.\n"
942 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
943 " about.\n\n"
944 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
945 " parameter then there was an error, or the end of the\n"
946 " domain-id space was reached.\n"
947 " dom [int]: Identifier of domain to which this info pertains\n"
948 " cpu [int]: CPU to which this domain is bound\n"
949 " vcpus [int]: Number of Virtual CPUS in this domain\n"
950 " dying [int]: Bool - is the domain dying?\n"
951 " crashed [int]: Bool - has the domain crashed?\n"
952 " shutdown [int]: Bool - has the domain shut itself down?\n"
953 " paused [int]: Bool - is the domain paused by control software?\n"
954 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
955 " running [int]: Bool - is the domain currently running?\n"
956 " mem_kb [int]: Memory reservation, in kilobytes\n"
957 " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
958 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
959 " shutdown_reason [int]: Numeric code from guest OS, explaining "
960 "reason why it shut itself down.\n"
961 " vcpu_to_cpu [[int]]: List that maps VCPUS to CPUS\n" },
963 { "linux_build",
964 (PyCFunction)pyxc_linux_build,
965 METH_VARARGS | METH_KEYWORDS, "\n"
966 "Build a new Linux guest OS.\n"
967 " dom [int]: Identifier of domain to build into.\n"
968 " image [str]: Name of kernel image file. May be gzipped.\n"
969 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
970 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
971 " vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
972 "Returns: [int] 0 on success; -1 on error.\n" },
974 { "vmx_build",
975 (PyCFunction)pyxc_vmx_build,
976 METH_VARARGS | METH_KEYWORDS, "\n"
977 "Build a new Linux guest OS.\n"
978 " dom [int]: Identifier of domain to build into.\n"
979 " image [str]: Name of kernel image file. May be gzipped.\n"
980 " memmap [str]: Memory map.\n\n"
981 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
982 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
983 "Returns: [int] 0 on success; -1 on error.\n" },
985 { "bvtsched_global_set",
986 (PyCFunction)pyxc_bvtsched_global_set,
987 METH_VARARGS | METH_KEYWORDS, "\n"
988 "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
989 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
990 "Returns: [int] 0 on success; -1 on error.\n" },
992 { "bvtsched_global_get",
993 (PyCFunction)pyxc_bvtsched_global_get,
994 METH_KEYWORDS, "\n"
995 "Get global tuning parameters for BVT scheduler.\n"
996 "Returns: [dict]:\n"
997 " ctx_allow [int]: context switch allowance\n" },
999 { "bvtsched_domain_set",
1000 (PyCFunction)pyxc_bvtsched_domain_set,
1001 METH_VARARGS | METH_KEYWORDS, "\n"
1002 "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
1003 " dom [int]: Identifier of domain to be tuned.\n"
1004 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
1005 " warpback [int]: Warp ? \n"
1006 " warpvalue [int]: How far to warp domain's EVT on unblock.\n"
1007 " warpl [int]: How long the domain can run warped.\n"
1008 " warpu [int]: How long before the domain can warp again.\n\n"
1009 "Returns: [int] 0 on success; -1 on error.\n" },
1011 { "bvtsched_domain_get",
1012 (PyCFunction)pyxc_bvtsched_domain_get,
1013 METH_KEYWORDS, "\n"
1014 "Get per-domain tuning parameters under the BVT scheduler.\n"
1015 " dom [int]: Identifier of domain to be queried.\n"
1016 "Returns [dict]:\n"
1017 " domain [int]: Domain ID.\n"
1018 " mcuadv [long]: MCU Advance.\n"
1019 " warp [long]: Warp.\n"
1020 " warpu [long]: Unwarp requirement.\n"
1021 " warpl [long]: Warp limit,\n"
1022 },
1024 { "sedf_domain_set",
1025 (PyCFunction)pyxc_sedf_domain_set,
1026 METH_KEYWORDS, "\n"
1027 "Set the scheduling parameters for a domain when running with Atropos.\n"
1028 " dom [int]: domain to set\n"
1029 " period [long]: domain's scheduling period\n"
1030 " slice [long]: domain's slice per period\n"
1031 " latency [long]: domain's wakeup latency hint\n"
1032 " extratime [int]: domain aware of extratime?\n"
1033 "Returns: [int] 0 on success; -1 on error.\n" },
1035 { "sedf_domain_get",
1036 (PyCFunction)pyxc_sedf_domain_get,
1037 METH_KEYWORDS, "\n"
1038 "Get the current scheduling parameters for a domain when running with\n"
1039 "the Atropos scheduler."
1040 " dom [int]: domain to query\n"
1041 "Returns: [dict]\n"
1042 " domain [int]: domain ID\n"
1043 " period [long]: scheduler period\n"
1044 " slice [long]: CPU reservation per period\n"
1045 " latency [long]: domain's wakeup latency hint\n"
1046 " extratime [int]: domain aware of extratime?\n"},
1048 { "evtchn_alloc_unbound",
1049 (PyCFunction)pyxc_evtchn_alloc_unbound,
1050 METH_VARARGS | METH_KEYWORDS, "\n"
1051 "Allocate an unbound local port that will await a remote connection.\n"
1052 " dom [int]: Remote domain to accept connections from.\n\n"
1053 "Returns: [int] Unbound event-channel port.\n" },
1055 { "evtchn_bind_interdomain",
1056 (PyCFunction)pyxc_evtchn_bind_interdomain,
1057 METH_VARARGS | METH_KEYWORDS, "\n"
1058 "Open an event channel between two domains.\n"
1059 " dom1 [int, SELF]: First domain to be connected.\n"
1060 " dom2 [int, SELF]: Second domain to be connected.\n\n"
1061 "Returns: [dict] dictionary is empty on failure.\n"
1062 " port1 [int]: Port-id for endpoint at dom1.\n"
1063 " port2 [int]: Port-id for endpoint at dom2.\n" },
1065 { "evtchn_bind_virq",
1066 (PyCFunction)pyxc_evtchn_bind_virq,
1067 METH_VARARGS | METH_KEYWORDS, "\n"
1068 "Bind an event channel to the specified VIRQ.\n"
1069 " virq [int]: VIRQ to bind.\n\n"
1070 "Returns: [int] Bound event-channel port.\n" },
1072 { "evtchn_close",
1073 (PyCFunction)pyxc_evtchn_close,
1074 METH_VARARGS | METH_KEYWORDS, "\n"
1075 "Close an event channel. If interdomain, sets remote end to 'unbound'.\n"
1076 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1077 " port [int]: Port-id of one endpoint of the channel.\n\n"
1078 "Returns: [int] 0 on success; -1 on error.\n" },
1080 { "evtchn_send",
1081 (PyCFunction)pyxc_evtchn_send,
1082 METH_VARARGS | METH_KEYWORDS, "\n"
1083 "Send an event along a locally-connected event channel.\n"
1084 " port [int]: Port-id of a local channel endpoint.\n\n"
1085 "Returns: [int] 0 on success; -1 on error.\n" },
1087 { "evtchn_status",
1088 (PyCFunction)pyxc_evtchn_status,
1089 METH_VARARGS | METH_KEYWORDS, "\n"
1090 "Query the status of an event channel.\n"
1091 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1092 " port [int]: Port-id of one endpoint of the channel.\n\n"
1093 "Returns: [dict] dictionary is empty on failure.\n"
1094 " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
1095 " or 'virq'.\n"
1096 "The following are returned if 'status' is 'interdomain':\n"
1097 " dom [int]: Dom-id of remote endpoint.\n"
1098 " port [int]: Port-id of remote endpoint.\n"
1099 "The following are returned if 'status' is 'pirq' or 'virq':\n"
1100 " irq [int]: IRQ number.\n" },
1102 { "physdev_pci_access_modify",
1103 (PyCFunction)pyxc_physdev_pci_access_modify,
1104 METH_VARARGS | METH_KEYWORDS, "\n"
1105 "Allow a domain access to a PCI device\n"
1106 " dom [int]: Identifier of domain to be allowed access.\n"
1107 " bus [int]: PCI bus\n"
1108 " dev [int]: PCI slot\n"
1109 " func [int]: PCI function\n"
1110 " enable [int]: Non-zero means enable access; else disable access\n\n"
1111 "Returns: [int] 0 on success; -1 on error.\n" },
1113 { "readconsolering",
1114 (PyCFunction)pyxc_readconsolering,
1115 METH_VARARGS | METH_KEYWORDS, "\n"
1116 "Read Xen's console ring.\n"
1117 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1118 "Returns: [str] string is empty on failure.\n" },
1120 { "physinfo",
1121 (PyCFunction)pyxc_physinfo,
1122 METH_VARARGS, "\n"
1123 "Get information about the physical host machine\n"
1124 "Returns [dict]: information about the hardware"
1125 " [None]: on failure.\n" },
1127 { "xeninfo",
1128 (PyCFunction)pyxc_xeninfo,
1129 METH_VARARGS, "\n"
1130 "Get information about the Xen host\n"
1131 "Returns [dict]: information about Xen"
1132 " [None]: on failure.\n" },
1134 { "shadow_control",
1135 (PyCFunction)pyxc_shadow_control,
1136 METH_VARARGS | METH_KEYWORDS, "\n"
1137 "Set parameter for shadow pagetable interface\n"
1138 " dom [int]: Identifier of domain.\n"
1139 " op [int, 0]: operation\n\n"
1140 "Returns: [int] 0 on success; -1 on error.\n" },
1142 { "domain_setmaxmem",
1143 (PyCFunction)pyxc_domain_setmaxmem,
1144 METH_VARARGS | METH_KEYWORDS, "\n"
1145 "Set a domain's memory limit\n"
1146 " dom [int]: Identifier of domain.\n"
1147 " maxmem_kb [long]: .\n"
1148 "Returns: [int] 0 on success; -1 on error.\n" },
1150 { "domain_memory_increase_reservation",
1151 (PyCFunction)pyxc_domain_memory_increase_reservation,
1152 METH_VARARGS | METH_KEYWORDS, "\n"
1153 "Increase a domain's memory reservation\n"
1154 " dom [int]: Identifier of domain.\n"
1155 " mem_kb [long]: .\n"
1156 "Returns: [int] 0 on success; -1 on error.\n" },
1158 { "init_store",
1159 (PyCFunction)pyxc_init_store,
1160 METH_VARARGS | METH_KEYWORDS, "\n"
1161 "Initialize the store event channel and return the store page mfn.\n"
1162 " remote_port [int]: store event channel port number.\n"
1163 "Returns: [int] mfn on success; <0 on error.\n" },
1165 { NULL, NULL, 0, NULL }
1166 };
1169 /*
1170 * Definitions for the 'Xc' module wrapper.
1171 */
1173 staticforward PyTypeObject PyXcType;
1175 static PyObject *PyXc_new(PyObject *self, PyObject *args)
1177 XcObject *xc;
1179 if ( !PyArg_ParseTuple(args, ":new") )
1180 return NULL;
1182 xc = PyObject_New(XcObject, &PyXcType);
1184 if ( (xc->xc_handle = xc_interface_open()) == -1 )
1186 PyObject_Del((PyObject *)xc);
1187 return PyErr_SetFromErrno(xc_error);
1190 return (PyObject *)xc;
1193 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1195 return Py_FindMethod(pyxc_methods, obj, name);
1198 static void PyXc_dealloc(PyObject *self)
1200 XcObject *xc = (XcObject *)self;
1201 (void)xc_interface_close(xc->xc_handle);
1202 PyObject_Del(self);
1205 static PyTypeObject PyXcType = {
1206 PyObject_HEAD_INIT(&PyType_Type)
1207 0,
1208 "Xc",
1209 sizeof(XcObject),
1210 0,
1211 PyXc_dealloc, /* tp_dealloc */
1212 NULL, /* tp_print */
1213 PyXc_getattr, /* tp_getattr */
1214 NULL, /* tp_setattr */
1215 NULL, /* tp_compare */
1216 NULL, /* tp_repr */
1217 NULL, /* tp_as_number */
1218 NULL, /* tp_as_sequence */
1219 NULL, /* tp_as_mapping */
1220 NULL /* tp_hash */
1221 };
1223 static PyMethodDef PyXc_methods[] = {
1224 { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
1225 { NULL, NULL, 0, NULL }
1226 };
1228 PyMODINIT_FUNC initxc(void)
1230 PyObject *m, *d;
1232 m = Py_InitModule(XENPKG, PyXc_methods);
1234 d = PyModule_GetDict(m);
1235 xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
1236 PyDict_SetItemString(d, "error", xc_error);
1237 PyDict_SetItemString(d, "VIRQ_DOM_EXC", PyInt_FromLong(VIRQ_DOM_EXC));
1239 zero = PyInt_FromLong(0);
1241 /* KAF: This ensures that we get debug output in a timely manner. */
1242 setbuf(stdout, NULL);
1243 setbuf(stderr, NULL);