direct-io.hg

view tools/xc/py/Xc.c @ 1521:e1ea789b5c8c

bitkeeper revision 1.990.2.3 (40d6e1bdskqDk0KjO_liWAgHndEuiQ)

Fix problem with missing fields in domain_getinfo.
author mjw@wray-m-3.hpl.hp.com
date Mon Jun 21 13:25:17 2004 +0000 (2004-06-21)
parents 50ebf96e89bf
children 5ce5fa6643ed 396e842f2f14
line source
1 /******************************************************************************
2 * Xc.c
3 *
4 * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
5 */
7 #include <Python.h>
8 #include <xc.h>
9 #include <zlib.h>
10 #include <fcntl.h>
11 #include <netinet/in.h>
12 #include <netinet/tcp.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netdb.h>
16 #include <arpa/inet.h>
18 /* Needed for Python versions earlier than 2.3. */
19 #ifndef PyMODINIT_FUNC
20 #define PyMODINIT_FUNC DL_EXPORT(void)
21 #endif
23 static PyObject *xc_error, *zero;
25 typedef struct {
26 PyObject_HEAD;
27 int xc_handle;
28 } XcObject;
30 /*
31 * Definitions for the 'xc' object type.
32 */
34 static PyObject *pyxc_domain_create(PyObject *self,
35 PyObject *args,
36 PyObject *kwds)
37 {
38 XcObject *xc = (XcObject *)self;
40 unsigned int mem_kb = 0;
41 char *name = "(anon)";
42 int cpu = -1;
43 u32 dom;
44 int ret;
46 static char *kwd_list[] = { "mem_kb", "name", "cpu", NULL };
48 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|isi", kwd_list,
49 &mem_kb, &name, &cpu) )
50 return NULL;
52 if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, cpu, &dom)) < 0 )
53 return PyErr_SetFromErrno(xc_error);
55 return PyInt_FromLong(dom);
56 }
58 static PyObject *pyxc_domain_start(PyObject *self,
59 PyObject *args,
60 PyObject *kwds)
61 {
62 XcObject *xc = (XcObject *)self;
64 u32 dom;
66 static char *kwd_list[] = { "dom", NULL };
68 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
69 return NULL;
71 if ( xc_domain_start(xc->xc_handle, dom) != 0 )
72 return PyErr_SetFromErrno(xc_error);
74 Py_INCREF(zero);
75 return zero;
76 }
78 static PyObject *pyxc_domain_stop(PyObject *self,
79 PyObject *args,
80 PyObject *kwds)
81 {
82 XcObject *xc = (XcObject *)self;
84 u32 dom;
86 static char *kwd_list[] = { "dom", NULL };
88 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
89 return NULL;
91 if ( xc_domain_stop(xc->xc_handle, dom) != 0 )
92 return PyErr_SetFromErrno(xc_error);
94 Py_INCREF(zero);
95 return zero;
96 }
98 static PyObject *pyxc_domain_destroy(PyObject *self,
99 PyObject *args,
100 PyObject *kwds)
101 {
102 XcObject *xc = (XcObject *)self;
104 u32 dom;
105 int force = 0;
107 static char *kwd_list[] = { "dom", "force", NULL };
109 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
110 &dom, &force) )
111 return NULL;
113 if ( xc_domain_destroy(xc->xc_handle, dom, force) != 0 )
114 return PyErr_SetFromErrno(xc_error);
116 Py_INCREF(zero);
117 return zero;
118 }
120 static PyObject *pyxc_domain_pincpu(PyObject *self,
121 PyObject *args,
122 PyObject *kwds)
123 {
124 XcObject *xc = (XcObject *)self;
126 u32 dom;
127 int cpu = -1;
129 static char *kwd_list[] = { "dom", "cpu", NULL };
131 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
132 &dom, &cpu) )
133 return NULL;
135 if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
136 return PyErr_SetFromErrno(xc_error);
138 Py_INCREF(zero);
139 return zero;
140 }
142 static PyObject *pyxc_domain_getinfo(PyObject *self,
143 PyObject *args,
144 PyObject *kwds)
145 {
146 XcObject *xc = (XcObject *)self;
147 PyObject *list;
149 u32 first_dom = 0;
150 int max_doms = 1024, nr_doms, i;
151 xc_dominfo_t *info;
153 static char *kwd_list[] = { "first_dom", "max_doms", NULL };
155 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
156 &first_dom, &max_doms) )
157 return NULL;
159 if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
160 return PyErr_NoMemory();
162 nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
164 list = PyList_New(nr_doms);
165 for ( i = 0 ; i < nr_doms; i++ )
166 {
167 PyList_SetItem(
168 list, i,
169 Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:l,s:L,s:s,s:l}",
170 "dom", info[i].domid,
171 "cpu", info[i].cpu,
172 "dying", info[i].dying,
173 "crashed", info[i].crashed,
174 "suspended", info[i].suspended,
175 "stopped", info[i].stopped,
176 "blocked", info[i].blocked,
177 "running", info[i].running,
178 "mem_kb", info[i].nr_pages*4,
179 "cpu_time", info[i].cpu_time,
180 "name", info[i].name,
181 "maxmem_kb", info[i].max_memkb
182 ));
183 }
185 free(info);
187 return list;
188 }
190 static PyObject *pyxc_linux_save(PyObject *self,
191 PyObject *args,
192 PyObject *kwds)
193 {
194 XcObject *xc = (XcObject *)self;
196 u32 dom;
197 char *state_file;
198 int progress = 1, live = -1, debug = 0;
199 unsigned int flags = 0;
201 static char *kwd_list[] = { "dom", "state_file", "progress",
202 "live", "debug", NULL };
204 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list,
205 &dom, &state_file, &progress,
206 &live, &debug) )
207 return NULL;
209 if (progress) flags |= XCFLAGS_VERBOSE;
210 if (live == 1) flags |= XCFLAGS_LIVE;
211 if (debug) flags |= XCFLAGS_DEBUG;
213 if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
214 {
215 #define max_namelen 64
216 char server[max_namelen];
217 char *port_s;
218 int port=777;
219 int sd = -1;
220 struct hostent *h;
221 struct sockaddr_in s;
222 int sockbufsize;
223 int rc = -1;
225 int writerfn(void *fd, const void *buf, size_t count)
226 {
227 int tot = 0, rc;
228 do {
229 rc = write( (int) fd, ((char*)buf)+tot, count-tot );
230 if ( rc < 0 ) { perror("WRITE"); return rc; };
231 tot += rc;
232 }
233 while ( tot < count );
234 return 0;
235 }
237 if (live == -1) flags |= XCFLAGS_LIVE; /* default to live for tcp */
239 strncpy( server, state_file+strlen("tcp://"), max_namelen);
240 server[max_namelen-1]='\0';
241 if ( (port_s = strchr(server,':')) != NULL )
242 {
243 *port_s = '\0';
244 port = atoi(port_s+1);
245 }
247 printf("X server=%s port=%d\n",server,port);
249 h = gethostbyname(server);
250 sd = socket (AF_INET,SOCK_STREAM,0);
251 if ( sd < 0 )
252 goto serr;
253 s.sin_family = AF_INET;
254 bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
255 s.sin_port = htons(port);
256 if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) )
257 goto serr;
259 sockbufsize=128*1024;
260 if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF,
261 &sockbufsize, sizeof sockbufsize) < 0 )
262 goto serr;
264 if ( xc_linux_save(xc->xc_handle, dom, flags,
265 writerfn, (void*)sd) == 0 )
266 {
267 if ( read( sd, &rc, sizeof(int) ) != sizeof(int) )
268 goto serr;
270 if ( rc == 0 )
271 {
272 printf("Migration succesful -- destroy local copy\n");
273 xc_domain_destroy( xc->xc_handle, dom, 1 );
274 close(sd);
275 Py_INCREF(zero);
276 return zero;
277 }
278 else
279 errno = rc;
280 }
282 serr:
283 printf("Migration failed -- restart local copy\n");
284 xc_domain_start( xc->xc_handle, dom );
285 PyErr_SetFromErrno(xc_error);
286 if ( sd >= 0 ) close(sd);
287 return NULL;
288 }
289 else
290 {
291 int fd = -1;
292 gzFile gfd = NULL;
294 int writerfn(void *fd, const void *buf, size_t count)
295 {
296 int rc;
297 while ( ((rc = gzwrite( (gzFile*)fd, (void*)buf, count)) == -1) &&
298 (errno = EINTR) )
299 continue;
300 return ! (rc == count);
301 }
303 if (strncmp(state_file,"file:",strlen("file:")) == 0)
304 state_file += strlen("file:");
306 if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
307 {
308 perror("Could not open file for writing");
309 goto err;
310 }
312 /*
313 * Compression rate 1: we want speed over compression.
314 * We're mainly going for those zero pages, after all.
315 */
317 if ( (gfd = gzdopen(fd, "wb1")) == NULL )
318 {
319 perror("Could not allocate compression state for state file");
320 close(fd);
321 goto err;
322 }
325 if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 )
326 {
327 /* kill domain. We don't want to do this for checkpointing, but
328 if we don't do it here I think people will hurt themselves
329 by accident... */
330 xc_domain_destroy( xc->xc_handle, dom, 1 );
331 gzclose(gfd);
332 close(fd);
334 Py_INCREF(zero);
335 return zero;
336 }
338 err:
339 PyErr_SetFromErrno(xc_error);
340 if ( gfd != NULL )
341 gzclose(gfd);
342 if ( fd >= 0 )
343 close(fd);
344 unlink(state_file);
345 return NULL;
346 }
348 }
350 static PyObject *pyxc_linux_restore(PyObject *self,
351 PyObject *args,
352 PyObject *kwds)
353 {
354 XcObject *xc = (XcObject *)self;
356 char *state_file;
357 int progress = 1;
358 u32 dom;
359 unsigned int flags = 0;
361 static char *kwd_list[] = { "dom", "state_file", "progress", NULL };
363 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|i", kwd_list,
364 &dom, &state_file, &progress) )
365 return NULL;
367 if ( progress )
368 flags |= XCFLAGS_VERBOSE;
370 if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
371 {
372 #define max_namelen 64
373 char server[max_namelen];
374 char *port_s;
375 int port=777;
376 int ld = -1, sd = -1;
377 struct hostent *h;
378 struct sockaddr_in s, d, p;
379 socklen_t dlen, plen;
380 int sockbufsize;
381 int on = 1, rc = -1;
383 int readerfn(void *fd, void *buf, size_t count)
384 {
385 int rc, tot = 0;
386 do {
387 rc = read( (int) fd, ((char*)buf)+tot, count-tot );
388 if ( rc < 0 ) { perror("READ"); return rc; }
389 if ( rc == 0 ) { printf("read: need %d, tot=%d got zero\n",
390 count-tot, tot); return -1; }
391 tot += rc;
392 }
393 while ( tot < count );
394 return 0;
395 }
397 strncpy( server, state_file+strlen("tcp://"), max_namelen);
398 server[max_namelen-1]='\0';
399 if ( (port_s = strchr(server,':')) != NULL )
400 {
401 *port_s = '\0';
402 port = atoi(port_s+1);
403 }
405 printf("X server=%s port=%d\n",server,port);
407 h = gethostbyname(server);
408 ld = socket (AF_INET,SOCK_STREAM,0);
409 if ( ld < 0 ) goto serr;
410 s.sin_family = AF_INET;
411 s.sin_addr.s_addr = htonl(INADDR_ANY);
412 s.sin_port = htons(port);
414 if ( setsockopt(ld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 )
415 goto serr;
417 if ( bind(ld, (struct sockaddr *) &s, sizeof(s)) )
418 goto serr;
420 if ( listen(ld, 1) )
421 goto serr;
423 dlen=sizeof(struct sockaddr);
424 if ( (sd = accept(ld, (struct sockaddr *) &d, &dlen )) < 0 )
425 goto serr;
427 plen = sizeof(p);
428 if ( getpeername(sd, (struct sockaddr_in *) &p,
429 &plen) < 0 )
430 goto serr;
432 printf("Accepted connection from %s\n", inet_ntoa(p.sin_addr));
434 sockbufsize=128*1024;
435 if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
436 sizeof sockbufsize) < 0 )
437 goto serr;
439 rc = xc_linux_restore(xc->xc_handle, dom, flags,
440 readerfn, (void*)sd, &dom);
442 write( sd, &rc, sizeof(int) );
444 if (rc == 0)
445 {
446 close(sd);
447 Py_INCREF(zero);
448 return zero;
449 }
450 errno = rc;
452 serr:
453 PyErr_SetFromErrno(xc_error);
454 if ( ld >= 0 ) close(ld);
455 if ( sd >= 0 ) close(sd);
456 return NULL;
457 }
458 else
459 {
460 int fd = -1;
461 gzFile gfd = NULL;
463 int readerfn(void *fd, void *buf, size_t count)
464 {
465 int rc;
466 while ( ((rc = gzread( (gzFile*)fd, (void*)buf, count)) == -1) &&
467 (errno = EINTR) )
468 continue;
469 return ! (rc == count);
470 }
472 if ( strncmp(state_file,"file:",strlen("file:")) == 0 )
473 state_file += strlen("file:");
475 if ( (fd = open(state_file, O_RDONLY)) == -1 )
476 {
477 perror("Could not open file for writing");
478 goto err;
479 }
481 /*
482 * Compression rate 1: we want speed over compression.
483 * We're mainly going for those zero pages, after all.
484 */
485 if ( (gfd = gzdopen(fd, "rb")) == NULL )
486 {
487 perror("Could not allocate compression state for state file");
488 close(fd);
489 goto err;
490 }
493 if ( xc_linux_restore(xc->xc_handle, dom, flags,
494 readerfn, gfd, &dom) == 0 )
495 {
496 gzclose(gfd);
497 close(fd);
499 Py_INCREF(zero);
500 return zero;
501 }
503 err:
504 PyErr_SetFromErrno(xc_error);
505 if ( gfd != NULL ) gzclose(gfd);
506 if ( fd >= 0 ) close(fd);
507 return NULL;
508 }
510 }
512 static PyObject *pyxc_linux_build(PyObject *self,
513 PyObject *args,
514 PyObject *kwds)
515 {
516 XcObject *xc = (XcObject *)self;
518 u32 dom;
519 char *image, *ramdisk = NULL, *cmdline = "";
520 int control_evtchn, flags = 0;
522 static char *kwd_list[] = { "dom", "control_evtchn",
523 "image", "ramdisk", "cmdline", "flags",
524 NULL };
526 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
527 &dom, &control_evtchn,
528 &image, &ramdisk, &cmdline, &flags) )
529 return NULL;
531 if ( xc_linux_build(xc->xc_handle, dom, image,
532 ramdisk, cmdline, control_evtchn, flags) != 0 )
533 return PyErr_SetFromErrno(xc_error);
535 Py_INCREF(zero);
536 return zero;
537 }
539 static PyObject *pyxc_netbsd_build(PyObject *self,
540 PyObject *args,
541 PyObject *kwds)
542 {
543 XcObject *xc = (XcObject *)self;
545 u32 dom;
546 char *image, *ramdisk = NULL, *cmdline = "";
547 int control_evtchn;
549 static char *kwd_list[] = { "dom", "control_evtchn",
550 "image", "ramdisk", "cmdline", NULL };
552 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list,
553 &dom, &control_evtchn,
554 &image, &ramdisk, &cmdline) )
555 return NULL;
557 if ( xc_netbsd_build(xc->xc_handle, dom, image,
558 cmdline, control_evtchn) != 0 )
559 return PyErr_SetFromErrno(xc_error);
561 Py_INCREF(zero);
562 return zero;
563 }
565 static PyObject *pyxc_bvtsched_global_set(PyObject *self,
566 PyObject *args,
567 PyObject *kwds)
568 {
569 XcObject *xc = (XcObject *)self;
571 unsigned long ctx_allow;
573 static char *kwd_list[] = { "ctx_allow", NULL };
575 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
576 return NULL;
578 if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
579 return PyErr_SetFromErrno(xc_error);
581 Py_INCREF(zero);
582 return zero;
583 }
585 static PyObject *pyxc_bvtsched_global_get(PyObject *self,
586 PyObject *args,
587 PyObject *kwds)
588 {
589 XcObject *xc = (XcObject *)self;
591 unsigned long ctx_allow;
593 if ( !PyArg_ParseTuple(args, "") )
594 return NULL;
596 if ( xc_bvtsched_global_get(xc->xc_handle, &ctx_allow) != 0 )
597 return PyErr_SetFromErrno(xc_error);
599 return Py_BuildValue("s:l", "ctx_allow", ctx_allow);
600 }
602 static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
603 PyObject *args,
604 PyObject *kwds)
605 {
606 XcObject *xc = (XcObject *)self;
608 u32 dom;
609 unsigned long mcuadv, warp, warpl, warpu;
611 static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl",
612 "warpu", NULL };
614 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illll", kwd_list,
615 &dom, &mcuadv, &warp, &warpl, &warpu) )
616 return NULL;
618 if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv,
619 warp, warpl, warpu) != 0 )
620 return PyErr_SetFromErrno(xc_error);
622 Py_INCREF(zero);
623 return zero;
624 }
626 static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
627 PyObject *args,
628 PyObject *kwds)
629 {
630 XcObject *xc = (XcObject *)self;
631 u32 dom;
632 unsigned long mcuadv, warp, warpl, warpu;
634 static char *kwd_list[] = { "dom", NULL };
636 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &dom) )
637 return NULL;
639 if ( xc_bvtsched_domain_get(xc->xc_handle, dom, &mcuadv, &warp,
640 &warpl, &warpu) != 0 )
641 return PyErr_SetFromErrno(xc_error);
643 return Py_BuildValue("{s:i,s:l,s:l,s:l,s:l}",
644 "domain", dom,
645 "mcuadv", mcuadv,
646 "warp", warp,
647 "warpl", warpl,
648 "warpu", warpu);
649 }
651 static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
652 PyObject *args,
653 PyObject *kwds)
654 {
655 XcObject *xc = (XcObject *)self;
657 u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
658 int port1, port2;
660 static char *kwd_list[] = { "dom1", "dom2", NULL };
662 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
663 &dom1, &dom2) )
664 return NULL;
666 if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
667 dom2, &port1, &port2) != 0 )
668 return PyErr_SetFromErrno(xc_error);
670 return Py_BuildValue("{s:i,s:i}",
671 "port1", port1,
672 "port2", port2);
673 }
675 static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
676 PyObject *args,
677 PyObject *kwds)
678 {
679 XcObject *xc = (XcObject *)self;
681 int virq, port;
683 static char *kwd_list[] = { "virq", NULL };
685 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
686 return NULL;
688 if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
689 return PyErr_SetFromErrno(xc_error);
691 return PyInt_FromLong(port);
692 }
694 static PyObject *pyxc_evtchn_close(PyObject *self,
695 PyObject *args,
696 PyObject *kwds)
697 {
698 XcObject *xc = (XcObject *)self;
700 u32 dom = DOMID_SELF;
701 int port;
703 static char *kwd_list[] = { "port", "dom", NULL };
705 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
706 &port, &dom) )
707 return NULL;
709 if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
710 return PyErr_SetFromErrno(xc_error);
712 Py_INCREF(zero);
713 return zero;
714 }
716 static PyObject *pyxc_evtchn_send(PyObject *self,
717 PyObject *args,
718 PyObject *kwds)
719 {
720 XcObject *xc = (XcObject *)self;
722 int port;
724 static char *kwd_list[] = { "port", NULL };
726 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
727 return NULL;
729 if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
730 return PyErr_SetFromErrno(xc_error);
732 Py_INCREF(zero);
733 return zero;
734 }
736 static PyObject *pyxc_evtchn_status(PyObject *self,
737 PyObject *args,
738 PyObject *kwds)
739 {
740 XcObject *xc = (XcObject *)self;
741 PyObject *dict;
743 u32 dom = DOMID_SELF;
744 int port, ret;
745 xc_evtchn_status_t status;
747 static char *kwd_list[] = { "port", "dom", NULL };
749 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
750 &port, &dom) )
751 return NULL;
753 ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
754 if ( ret != 0 )
755 return PyErr_SetFromErrno(xc_error);
757 switch ( status.status )
758 {
759 case EVTCHNSTAT_closed:
760 dict = Py_BuildValue("{s:s}",
761 "status", "closed");
762 break;
763 case EVTCHNSTAT_unbound:
764 dict = Py_BuildValue("{s:s}",
765 "status", "unbound");
766 break;
767 case EVTCHNSTAT_interdomain:
768 dict = Py_BuildValue("{s:s,s:i,s:i}",
769 "status", "interdomain",
770 "dom", status.u.interdomain.dom,
771 "port", status.u.interdomain.port);
772 break;
773 case EVTCHNSTAT_pirq:
774 dict = Py_BuildValue("{s:s,s:i}",
775 "status", "pirq",
776 "irq", status.u.pirq);
777 break;
778 case EVTCHNSTAT_virq:
779 dict = Py_BuildValue("{s:s,s:i}",
780 "status", "virq",
781 "irq", status.u.virq);
782 break;
783 default:
784 dict = Py_BuildValue("{}");
785 break;
786 }
788 return dict;
789 }
791 static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
792 PyObject *args,
793 PyObject *kwds)
794 {
795 XcObject *xc = (XcObject *)self;
796 u32 dom;
797 int bus, dev, func, enable, ret;
799 static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
801 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiii", kwd_list,
802 &dom, &bus, &dev, &func, &enable) )
803 return NULL;
805 ret = xc_physdev_pci_access_modify(
806 xc->xc_handle, dom, bus, dev, func, enable);
807 if ( ret != 0 )
808 return PyErr_SetFromErrno(xc_error);
810 Py_INCREF(zero);
811 return zero;
812 }
814 static PyObject *pyxc_readconsolering(PyObject *self,
815 PyObject *args,
816 PyObject *kwds)
817 {
818 XcObject *xc = (XcObject *)self;
820 unsigned int clear = 0;
821 char str[32768];
822 int ret;
824 static char *kwd_list[] = { "clear", NULL };
826 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
827 return NULL;
829 ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
830 if ( ret < 0 )
831 return PyErr_SetFromErrno(xc_error);
833 return PyString_FromStringAndSize(str, ret);
834 }
836 static PyObject *pyxc_physinfo(PyObject *self,
837 PyObject *args,
838 PyObject *kwds)
839 {
840 XcObject *xc = (XcObject *)self;
841 xc_physinfo_t info;
843 if ( !PyArg_ParseTuple(args, "") )
844 return NULL;
846 if ( xc_physinfo(xc->xc_handle, &info) != 0 )
847 return PyErr_SetFromErrno(xc_error);
849 return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
850 "ht_per_core", info.ht_per_core,
851 "cores", info.cores,
852 "total_pages", info.total_pages,
853 "free_pages", info.free_pages,
854 "cpu_khz", info.cpu_khz);
855 }
857 static PyObject *pyxc_atropos_domain_set(PyObject *self,
858 PyObject *args,
859 PyObject *kwds)
860 {
861 XcObject *xc = (XcObject *)self;
862 u32 domid;
863 u64 period, slice, latency;
864 int xtratime;
866 static char *kwd_list[] = { "dom", "period", "slice", "latency",
867 "xtratime", NULL };
869 if( !PyArg_ParseTupleAndKeywords(args, kwds, "iLLLi", kwd_list, &domid,
870 &period, &slice, &latency, &xtratime) )
871 return NULL;
873 if ( xc_atropos_domain_set(xc->xc_handle, domid, period, slice,
874 latency, xtratime) != 0 )
875 return PyErr_SetFromErrno(xc_error);
877 Py_INCREF(zero);
878 return zero;
879 }
881 static PyObject *pyxc_atropos_domain_get(PyObject *self,
882 PyObject *args,
883 PyObject *kwds)
884 {
885 XcObject *xc = (XcObject *)self;
886 u32 domid;
887 u64 period, slice, latency;
888 int xtratime;
890 static char *kwd_list[] = { "dom", NULL };
892 if( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &domid) )
893 return NULL;
895 if ( xc_atropos_domain_get( xc->xc_handle, domid, &period,
896 &slice, &latency, &xtratime ) )
897 return PyErr_SetFromErrno(xc_error);
899 return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
900 "domain", domid,
901 "period", period,
902 "slice", slice,
903 "latency", latency,
904 "xtratime", xtratime);
905 }
908 static PyObject *pyxc_rrobin_global_set(PyObject *self,
909 PyObject *args,
910 PyObject *kwds)
911 {
912 XcObject *xc = (XcObject *)self;
913 u64 slice;
915 static char *kwd_list[] = { "slice", NULL };
917 if( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &slice) )
918 return NULL;
920 if ( xc_rrobin_global_set(xc->xc_handle, slice) != 0 )
921 return PyErr_SetFromErrno(xc_error);
923 Py_INCREF(zero);
924 return zero;
925 }
927 static PyObject *pyxc_shadow_control(PyObject *self,
928 PyObject *args,
929 PyObject *kwds)
930 {
931 XcObject *xc = (XcObject *)self;
933 u32 dom;
934 int op=0;
936 static char *kwd_list[] = { "dom", "op", NULL };
938 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
939 &dom, &op) )
940 return NULL;
942 if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL, NULL) < 0 )
943 return PyErr_SetFromErrno(xc_error);
945 Py_INCREF(zero);
946 return zero;
947 }
949 static PyObject *pyxc_rrobin_global_get(PyObject *self,
950 PyObject *args,
951 PyObject *kwds)
952 {
953 XcObject *xc = (XcObject *)self;
954 u64 slice;
956 if ( !PyArg_ParseTuple(args, "") )
957 return NULL;
959 if ( xc_rrobin_global_get(xc->xc_handle, &slice) != 0 )
960 return PyErr_SetFromErrno(xc_error);
962 return Py_BuildValue("{s:L}", "slice", slice);
963 }
965 static PyObject *pyxc_domain_setname(PyObject *self,
966 PyObject *args,
967 PyObject *kwds)
968 {
969 XcObject *xc = (XcObject *)self;
970 u32 dom;
971 char *name;
973 static char *kwd_list[] = { "dom", "name", NULL };
975 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list,
976 &dom, &name) )
977 return NULL;
979 if ( xc_domain_setname(xc->xc_handle, dom, name) != 0 )
980 return PyErr_SetFromErrno(xc_error);
982 Py_INCREF(zero);
983 return zero;
984 }
986 static PyObject *pyxc_domain_setmaxmem(PyObject *self,
987 PyObject *args,
988 PyObject *kwds)
989 {
990 XcObject *xc = (XcObject *)self;
992 u32 dom;
993 unsigned long max_memkb;
995 static char *kwd_list[] = { "dom", "max_memkb", NULL };
997 if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
998 &dom, &max_memkb) )
999 return NULL;
1001 if ( xc_domain_setmaxmem(xc->xc_handle, dom, max_memkb) != 0 )
1002 return PyErr_SetFromErrno(xc_error);
1004 Py_INCREF(zero);
1005 return zero;
1009 static PyMethodDef pyxc_methods[] = {
1010 { "domain_create",
1011 (PyCFunction)pyxc_domain_create,
1012 METH_VARARGS | METH_KEYWORDS, "\n"
1013 "Create a new domain.\n"
1014 " mem_kb [int, 65536]: Memory allocation, in kilobytes.\n"
1015 " name [str, '(anon)']: Informative textual name.\n\n"
1016 "Returns: [int] new domain identifier; -1 on error.\n" },
1018 { "domain_start",
1019 (PyCFunction)pyxc_domain_start,
1020 METH_VARARGS | METH_KEYWORDS, "\n"
1021 "Start execution of a domain.\n"
1022 " dom [int]: Identifier of domain to be started.\n\n"
1023 "Returns: [int] 0 on success; -1 on error.\n" },
1025 { "domain_stop",
1026 (PyCFunction)pyxc_domain_stop,
1027 METH_VARARGS | METH_KEYWORDS, "\n"
1028 "Stop execution of a domain.\n"
1029 " dom [int]: Identifier of domain to be stopped.\n\n"
1030 "Returns: [int] 0 on success; -1 on error.\n" },
1032 { "domain_destroy",
1033 (PyCFunction)pyxc_domain_destroy,
1034 METH_VARARGS | METH_KEYWORDS, "\n"
1035 "Destroy a domain.\n"
1036 " dom [int]: Identifier of domain to be destroyed.\n"
1037 " force [int, 0]: Bool - force immediate destruction?\n\n"
1038 "Returns: [int] 0 on success; -1 on error.\n" },
1040 { "domain_pincpu",
1041 (PyCFunction)pyxc_domain_pincpu,
1042 METH_VARARGS | METH_KEYWORDS, "\n"
1043 "Pin a domain to a specified CPU.\n"
1044 " dom [int]: Identifier of domain to be pinned.\n"
1045 " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
1046 "Returns: [int] 0 on success; -1 on error.\n" },
1048 { "domain_getinfo",
1049 (PyCFunction)pyxc_domain_getinfo,
1050 METH_VARARGS | METH_KEYWORDS, "\n"
1051 "Get information regarding a set of domains, in increasing id order.\n"
1052 " first_dom [int, 0]: First domain to retrieve info about.\n"
1053 " max_doms [int, 1024]: Maximum number of domains to retrieve info"
1054 " about.\n\n"
1055 "Returns: [list of dicts] if list length is less than 'max_doms'\n"
1056 " parameter then there was an error, or the end of the\n"
1057 " domain-id space was reached.\n"
1058 " dom [int]: Identifier of domain to which this info pertains\n"
1059 " cpu [int]: CPU to which this domain is bound\n"
1060 " dying [int]: Bool - is the domain dying?\n"
1061 " crashed [int]: Bool - has the domain crashed?\n"
1062 " suspended[int]: Bool - has the domain suspended itself?\n"
1063 " stopped [int]: Bool - is the domain stopped by control software?\n"
1064 " blocked [int]: Bool - is the domain blocked waiting for an event?\n"
1065 " running [int]: Bool - is the domain currently running?\n"
1066 " mem_kb [int]: Memory reservation, in kilobytes\n"
1067 " cpu_time [long]: CPU time consumed, in nanoseconds\n"
1068 " name [str]: Identifying name\n" },
1070 { "linux_save",
1071 (PyCFunction)pyxc_linux_save,
1072 METH_VARARGS | METH_KEYWORDS, "\n"
1073 "Save the CPU and memory state of a Linux guest OS.\n"
1074 " dom [int]: Identifier of domain to be saved.\n"
1075 " state_file [str]: Name of state file. Must not currently exist.\n"
1076 " progress [int, 1]: Bool - display a running progress indication?\n\n"
1077 "Returns: [int] 0 on success; -1 on error.\n" },
1079 { "linux_restore",
1080 (PyCFunction)pyxc_linux_restore,
1081 METH_VARARGS | METH_KEYWORDS, "\n"
1082 "Restore the CPU and memory state of a Linux guest OS.\n"
1083 " state_file [str]: Name of state file. Must not currently exist.\n"
1084 " progress [int, 1]: Bool - display a running progress indication?\n\n"
1085 "Returns: [int] new domain identifier on success; -1 on error.\n" },
1087 { "linux_build",
1088 (PyCFunction)pyxc_linux_build,
1089 METH_VARARGS | METH_KEYWORDS, "\n"
1090 "Build a new Linux guest OS.\n"
1091 " dom [int]: Identifier of domain to build into.\n"
1092 " image [str]: Name of kernel image file. May be gzipped.\n"
1093 " ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
1094 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1095 "Returns: [int] 0 on success; -1 on error.\n" },
1097 { "netbsd_build",
1098 (PyCFunction)pyxc_netbsd_build,
1099 METH_VARARGS | METH_KEYWORDS, "\n"
1100 "Build a new NetBSD guest OS.\n"
1101 " dom [int]: Identifier of domain to build into.\n"
1102 " image [str]: Name of kernel image file. May be gzipped.\n"
1103 " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
1104 "Returns: [int] 0 on success; -1 on error.\n" },
1106 { "bvtsched_global_set",
1107 (PyCFunction)pyxc_bvtsched_global_set,
1108 METH_VARARGS | METH_KEYWORDS, "\n"
1109 "Set global tuning parameters for Borrowed Virtual Time scheduler.\n"
1110 " ctx_allow [int]: Minimal guaranteed quantum.\n\n"
1111 "Returns: [int] 0 on success; -1 on error.\n" },
1113 { "bvtsched_global_get",
1114 (PyCFunction)pyxc_bvtsched_global_get,
1115 METH_KEYWORDS, "\n"
1116 "Get global tuning parameters for BVT scheduler.\n"
1117 "Returns: [dict]:\n"
1118 " ctx_allow [int]: context switch allowance\n" },
1120 { "bvtsched_domain_set",
1121 (PyCFunction)pyxc_bvtsched_domain_set,
1122 METH_VARARGS | METH_KEYWORDS, "\n"
1123 "Set per-domain tuning parameters for Borrowed Virtual Time scheduler.\n"
1124 " dom [int]: Identifier of domain to be tuned.\n"
1125 " mcuadv [int]: Proportional to the inverse of the domain's weight.\n"
1126 " warp [int]: How far to warp domain's EVT on unblock.\n"
1127 " warpl [int]: How long the domain can run warped.\n"
1128 " warpu [int]: How long before the domain can warp again.\n\n"
1129 "Returns: [int] 0 on success; -1 on error.\n" },
1131 { "bvtsched_domain_get",
1132 (PyCFunction)pyxc_bvtsched_domain_get,
1133 METH_KEYWORDS, "\n"
1134 "Get per-domain tuning parameters under the BVT scheduler.\n"
1135 " dom [int]: Identifier of domain to be queried.\n"
1136 "Returns [dict]:\n"
1137 " domain [int]: Domain ID.\n"
1138 " mcuadv [long]: MCU Advance.\n"
1139 " warp [long]: Warp.\n"
1140 " warpu [long]: Unwarp requirement.\n"
1141 " warpl [long]: Warp limit,\n"
1142 },
1144 { "atropos_domain_set",
1145 (PyCFunction)pyxc_atropos_domain_set,
1146 METH_KEYWORDS, "\n"
1147 "Set the scheduling parameters for a domain when running with Atropos.\n"
1148 " dom [int]: domain to set\n"
1149 " period [long]: domain's scheduling period\n"
1150 " slice [long]: domain's slice per period\n"
1151 " latency [long]: wakeup latency hint\n"
1152 " xtratime [int]: boolean\n"
1153 "Returns: [int] 0 on success; -1 on error.\n" },
1155 { "atropos_domain_get",
1156 (PyCFunction)pyxc_atropos_domain_get,
1157 METH_KEYWORDS, "\n"
1158 "Get the current scheduling parameters for a domain when running with\n"
1159 "the Atropos scheduler."
1160 " dom [int]: domain to query\n"
1161 "Returns: [dict]\n"
1162 " domain [int]: domain ID\n"
1163 " period [long]: scheduler period\n"
1164 " slice [long]: CPU reservation per period\n"
1165 " latency [long]: unblocking latency hint\n"
1166 " xtratime [int] : 0 if not using slack time, nonzero otherwise\n" },
1168 { "rrobin_global_set",
1169 (PyCFunction)pyxc_rrobin_global_set,
1170 METH_KEYWORDS, "\n"
1171 "Set Round Robin scheduler slice.\n"
1172 " slice [long]: Round Robin scheduler slice\n"
1173 "Returns: [int] 0 on success, throws an exception on failure\n" },
1175 { "rrobin_global_get",
1176 (PyCFunction)pyxc_rrobin_global_get,
1177 METH_KEYWORDS, "\n"
1178 "Get Round Robin scheduler settings\n"
1179 "Returns [dict]:\n"
1180 " slice [long]: Scheduler time slice.\n" },
1182 { "evtchn_bind_interdomain",
1183 (PyCFunction)pyxc_evtchn_bind_interdomain,
1184 METH_VARARGS | METH_KEYWORDS, "\n"
1185 "Open an event channel between two domains.\n"
1186 " dom1 [int, SELF]: First domain to be connected.\n"
1187 " dom2 [int, SELF]: Second domain to be connected.\n\n"
1188 "Returns: [dict] dictionary is empty on failure.\n"
1189 " port1 [int]: Port-id for endpoint at dom1.\n"
1190 " port2 [int]: Port-id for endpoint at dom2.\n" },
1192 { "evtchn_bind_virq",
1193 (PyCFunction)pyxc_evtchn_bind_virq,
1194 METH_VARARGS | METH_KEYWORDS, "\n"
1195 "Bind an event channel to the specified VIRQ.\n"
1196 " virq [int]: VIRQ to bind.\n\n"
1197 "Returns: [int] Bound event-channel port.\n" },
1199 { "evtchn_close",
1200 (PyCFunction)pyxc_evtchn_close,
1201 METH_VARARGS | METH_KEYWORDS, "\n"
1202 "Close an event channel.\n"
1203 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1204 " port [int]: Port-id of one endpoint of the channel.\n\n"
1205 "Returns: [int] 0 on success; -1 on error.\n" },
1207 { "evtchn_send",
1208 (PyCFunction)pyxc_evtchn_send,
1209 METH_VARARGS | METH_KEYWORDS, "\n"
1210 "Send an event along a locally-connected event channel.\n"
1211 " port [int]: Port-id of a local channel endpoint.\n\n"
1212 "Returns: [int] 0 on success; -1 on error.\n" },
1214 { "evtchn_status",
1215 (PyCFunction)pyxc_evtchn_status,
1216 METH_VARARGS | METH_KEYWORDS, "\n"
1217 "Query the status of an event channel.\n"
1218 " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
1219 " port [int]: Port-id of one endpoint of the channel.\n\n"
1220 "Returns: [dict] dictionary is empty on failure.\n"
1221 " status [str]: 'closed', 'unbound', 'interdomain', 'pirq',"
1222 " or 'virq'.\n"
1223 "The following are returned if 'status' is 'interdomain':\n"
1224 " dom [int]: Dom-id of remote endpoint.\n"
1225 " port [int]: Port-id of remote endpoint.\n"
1226 "The following are returned if 'status' is 'pirq' or 'virq':\n"
1227 " irq [int]: IRQ number.\n" },
1229 { "physdev_pci_access_modify",
1230 (PyCFunction)pyxc_physdev_pci_access_modify,
1231 METH_VARARGS | METH_KEYWORDS, "\n"
1232 "Allow a domain access to a PCI device\n"
1233 " dom [int]: Identifier of domain to be allowed access.\n"
1234 " bus [int]: PCI bus\n"
1235 " dev [int]: PCI slot\n"
1236 " func [int]: PCI function\n"
1237 " enable [int]: Non-zero means enable access; else disable access\n\n"
1238 "Returns: [int] 0 on success; -1 on error.\n" },
1240 { "readconsolering",
1241 (PyCFunction)pyxc_readconsolering,
1242 METH_VARARGS | METH_KEYWORDS, "\n"
1243 "Read Xen's console ring.\n"
1244 " clear [int, 0]: Bool - clear the ring after reading from it?\n\n"
1245 "Returns: [str] string is empty on failure.\n" },
1247 { "physinfo",
1248 (PyCFunction)pyxc_physinfo,
1249 METH_VARARGS, "\n"
1250 "Get information about the physical host machine\n"
1251 "Returns [dict]: information about the hardware"
1252 " [None]: on failure.\n" },
1254 { "shadow_control",
1255 (PyCFunction)pyxc_shadow_control,
1256 METH_VARARGS | METH_KEYWORDS, "\n"
1257 "Set parameter for shadow pagetable interface\n"
1258 " dom [int]: Identifier of domain.\n"
1259 " op [int, 0]: operation\n\n"
1260 "Returns: [int] 0 on success; -1 on error.\n" },
1262 { "domain_setname",
1263 (PyCFunction)pyxc_domain_setname,
1264 METH_VARARGS | METH_KEYWORDS, "\n"
1265 "Set domain informative textual name\n"
1266 " dom [int]: Identifier of domain.\n"
1267 " name [str]: Text string.\n\n"
1268 "Returns: [int] 0 on success; -1 on error.\n" },
1270 { "domain_setmaxmem",
1271 (PyCFunction)pyxc_domain_setname,
1272 METH_VARARGS | METH_KEYWORDS, "\n"
1273 "Set a domain's memory limit\n"
1274 " dom [int]: Identifier of domain.\n"
1275 " max_memkb [long]: .\n"
1276 "Returns: [int] 0 on success; -1 on error.\n" },
1278 { NULL, NULL, 0, NULL }
1279 };
1282 /*
1283 * Definitions for the 'Xc' module wrapper.
1284 */
1286 staticforward PyTypeObject PyXcType;
1288 static PyObject *PyXc_new(PyObject *self, PyObject *args)
1290 XcObject *xc;
1292 if ( !PyArg_ParseTuple(args, ":new") )
1293 return NULL;
1295 xc = PyObject_New(XcObject, &PyXcType);
1297 if ( (xc->xc_handle = xc_interface_open()) == -1 )
1299 PyObject_Del((PyObject *)xc);
1300 return PyErr_SetFromErrno(xc_error);
1303 return (PyObject *)xc;
1306 static PyObject *PyXc_getattr(PyObject *obj, char *name)
1308 return Py_FindMethod(pyxc_methods, obj, name);
1311 static void PyXc_dealloc(PyObject *self)
1313 XcObject *xc = (XcObject *)self;
1314 (void)xc_interface_close(xc->xc_handle);
1315 PyObject_Del(self);
1318 static PyTypeObject PyXcType = {
1319 PyObject_HEAD_INIT(&PyType_Type)
1320 0,
1321 "Xc",
1322 sizeof(XcObject),
1323 0,
1324 PyXc_dealloc, /* tp_dealloc */
1325 NULL, /* tp_print */
1326 PyXc_getattr, /* tp_getattr */
1327 NULL, /* tp_setattr */
1328 NULL, /* tp_compare */
1329 NULL, /* tp_repr */
1330 NULL, /* tp_as_number */
1331 NULL, /* tp_as_sequence */
1332 NULL, /* tp_as_mapping */
1333 NULL /* tp_hash */
1334 };
1336 static PyMethodDef PyXc_methods[] = {
1337 { "new", PyXc_new, METH_VARARGS, "Create a new Xc object." },
1338 { NULL, NULL, 0, NULL }
1339 };
1341 PyMODINIT_FUNC initXc(void)
1343 PyObject *m, *d;
1345 m = Py_InitModule("Xc", PyXc_methods);
1347 d = PyModule_GetDict(m);
1348 xc_error = PyErr_NewException("Xc.error", NULL, NULL);
1349 PyDict_SetItemString(d, "error", xc_error);
1351 zero = PyInt_FromLong(0);