ia64/xen-unstable

view tools/libxc/xc_domain.c @ 13608:30af6cfdb05c

Make domctl/sysctl interfaces 32-/64-bit invariant.
This kills off a fair amount of unpleasant CONFIG_COMPAT shimming and
avoids needing to keep the compat paths in sync as these interfaces
continue to develop.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Jan 24 16:33:19 2007 +0000 (2007-01-24)
parents 9f27746eff43
children 5e66c05c67ad
line source
1 /******************************************************************************
2 * xc_domain.c
3 *
4 * API for manipulating and obtaining information on domains.
5 *
6 * Copyright (c) 2003, K A Fraser.
7 */
9 #include "xc_private.h"
10 #include <xen/memory.h>
12 int xc_domain_create(int xc_handle,
13 uint32_t ssidref,
14 xen_domain_handle_t handle,
15 uint32_t flags,
16 uint32_t *pdomid)
17 {
18 int err;
19 DECLARE_DOMCTL;
21 domctl.cmd = XEN_DOMCTL_createdomain;
22 domctl.domain = (domid_t)*pdomid;
23 domctl.u.createdomain.ssidref = ssidref;
24 domctl.u.createdomain.flags = flags;
25 memcpy(domctl.u.createdomain.handle, handle, sizeof(xen_domain_handle_t));
26 if ( (err = do_domctl(xc_handle, &domctl)) != 0 )
27 return err;
29 *pdomid = (uint16_t)domctl.domain;
30 return 0;
31 }
34 int xc_domain_pause(int xc_handle,
35 uint32_t domid)
36 {
37 DECLARE_DOMCTL;
38 domctl.cmd = XEN_DOMCTL_pausedomain;
39 domctl.domain = (domid_t)domid;
40 return do_domctl(xc_handle, &domctl);
41 }
44 int xc_domain_unpause(int xc_handle,
45 uint32_t domid)
46 {
47 DECLARE_DOMCTL;
48 domctl.cmd = XEN_DOMCTL_unpausedomain;
49 domctl.domain = (domid_t)domid;
50 return do_domctl(xc_handle, &domctl);
51 }
54 int xc_domain_destroy(int xc_handle,
55 uint32_t domid)
56 {
57 DECLARE_DOMCTL;
58 domctl.cmd = XEN_DOMCTL_destroydomain;
59 domctl.domain = (domid_t)domid;
60 return do_domctl(xc_handle, &domctl);
61 }
63 int xc_domain_shutdown(int xc_handle,
64 uint32_t domid,
65 int reason)
66 {
67 int ret = -1;
68 sched_remote_shutdown_t arg;
69 DECLARE_HYPERCALL;
71 hypercall.op = __HYPERVISOR_sched_op;
72 hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown;
73 hypercall.arg[1] = (unsigned long)&arg;
74 arg.domain_id = domid;
75 arg.reason = reason;
77 if ( lock_pages(&arg, sizeof(arg)) != 0 )
78 {
79 PERROR("Could not lock memory for Xen hypercall");
80 goto out1;
81 }
83 ret = do_xen_hypercall(xc_handle, &hypercall);
85 unlock_pages(&arg, sizeof(arg));
87 out1:
88 return ret;
89 }
92 int xc_vcpu_setaffinity(int xc_handle,
93 uint32_t domid,
94 int vcpu,
95 uint64_t cpumap)
96 {
97 DECLARE_DOMCTL;
98 int ret = -1;
99 uint8_t local[sizeof (cpumap)];
101 domctl.cmd = XEN_DOMCTL_setvcpuaffinity;
102 domctl.domain = (domid_t)domid;
103 domctl.u.vcpuaffinity.vcpu = vcpu;
105 bitmap_64_to_byte(local, &cpumap, sizeof (cpumap));
107 set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
109 domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
111 if ( lock_pages(local, sizeof(local)) != 0 )
112 {
113 PERROR("Could not lock memory for Xen hypercall");
114 goto out;
115 }
117 ret = do_domctl(xc_handle, &domctl);
119 unlock_pages(local, sizeof(local));
121 out:
122 return ret;
123 }
126 int xc_vcpu_getaffinity(int xc_handle,
127 uint32_t domid,
128 int vcpu,
129 uint64_t *cpumap)
130 {
131 DECLARE_DOMCTL;
132 int ret = -1;
133 uint8_t local[sizeof (cpumap)];
135 domctl.cmd = XEN_DOMCTL_getvcpuaffinity;
136 domctl.domain = (domid_t)domid;
137 domctl.u.vcpuaffinity.vcpu = vcpu;
139 set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
140 domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
142 if ( lock_pages(local, sizeof(local)) != 0 )
143 {
144 PERROR("Could not lock memory for Xen hypercall");
145 goto out;
146 }
148 ret = do_domctl(xc_handle, &domctl);
150 unlock_pages(local, sizeof (local));
151 bitmap_byte_to_64(cpumap, local, sizeof (local));
152 out:
153 return ret;
154 }
157 int xc_domain_getinfo(int xc_handle,
158 uint32_t first_domid,
159 unsigned int max_doms,
160 xc_dominfo_t *info)
161 {
162 unsigned int nr_doms;
163 uint32_t next_domid = first_domid;
164 DECLARE_DOMCTL;
165 int rc = 0;
167 memset(info, 0, max_doms*sizeof(xc_dominfo_t));
169 for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
170 {
171 domctl.cmd = XEN_DOMCTL_getdomaininfo;
172 domctl.domain = (domid_t)next_domid;
173 if ( (rc = do_domctl(xc_handle, &domctl)) < 0 )
174 break;
175 info->domid = (uint16_t)domctl.domain;
177 info->dying = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_dying);
178 info->shutdown = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_shutdown);
179 info->paused = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_paused);
180 info->blocked = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
181 info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
182 info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
184 info->shutdown_reason =
185 (domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
186 XEN_DOMINF_shutdownmask;
188 if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
189 {
190 info->shutdown = 0;
191 info->crashed = 1;
192 }
194 info->ssidref = domctl.u.getdomaininfo.ssidref;
195 info->nr_pages = domctl.u.getdomaininfo.tot_pages;
196 info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10);
197 info->shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
198 info->cpu_time = domctl.u.getdomaininfo.cpu_time;
199 info->nr_online_vcpus = domctl.u.getdomaininfo.nr_online_vcpus;
200 info->max_vcpu_id = domctl.u.getdomaininfo.max_vcpu_id;
202 memcpy(info->handle, domctl.u.getdomaininfo.handle,
203 sizeof(xen_domain_handle_t));
205 next_domid = (uint16_t)domctl.domain + 1;
206 info++;
207 }
209 if ( nr_doms == 0 )
210 return rc;
212 return nr_doms;
213 }
215 int xc_domain_getinfolist(int xc_handle,
216 uint32_t first_domain,
217 unsigned int max_domains,
218 xc_domaininfo_t *info)
219 {
220 int ret = 0;
221 DECLARE_SYSCTL;
223 if ( lock_pages(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
224 return -1;
226 sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
227 sysctl.u.getdomaininfolist.first_domain = first_domain;
228 sysctl.u.getdomaininfolist.max_domains = max_domains;
229 set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);
231 if ( xc_sysctl(xc_handle, &sysctl) < 0 )
232 ret = -1;
233 else
234 ret = sysctl.u.getdomaininfolist.num_domains;
236 unlock_pages(info, max_domains*sizeof(xc_domaininfo_t));
238 return ret;
239 }
241 /* get info from hvm guest for save */
242 int xc_domain_hvm_getcontext(int xc_handle,
243 uint32_t domid,
244 hvm_domain_context_t *hvm_ctxt)
245 {
246 int rc;
247 DECLARE_DOMCTL;
249 domctl.cmd = XEN_DOMCTL_gethvmcontext;
250 domctl.domain = (domid_t)domid;
251 set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
253 if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
254 return rc;
256 rc = do_domctl(xc_handle, &domctl);
258 safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
260 return rc;
261 }
263 /* set info to hvm guest for restore */
264 int xc_domain_hvm_setcontext(int xc_handle,
265 uint32_t domid,
266 hvm_domain_context_t *hvm_ctxt)
267 {
268 int rc;
269 DECLARE_DOMCTL;
271 domctl.cmd = XEN_DOMCTL_sethvmcontext;
272 domctl.domain = domid;
273 set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt);
275 if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 )
276 return rc;
278 rc = do_domctl(xc_handle, &domctl);
280 safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt));
282 return rc;
283 }
285 int xc_vcpu_getcontext(int xc_handle,
286 uint32_t domid,
287 uint32_t vcpu,
288 vcpu_guest_context_t *ctxt)
289 {
290 int rc;
291 DECLARE_DOMCTL;
293 domctl.cmd = XEN_DOMCTL_getvcpucontext;
294 domctl.domain = (domid_t)domid;
295 domctl.u.vcpucontext.vcpu = (uint16_t)vcpu;
296 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
298 if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 )
299 return rc;
301 rc = do_domctl(xc_handle, &domctl);
303 unlock_pages(ctxt, sizeof(*ctxt));
305 return rc;
306 }
309 int xc_shadow_control(int xc_handle,
310 uint32_t domid,
311 unsigned int sop,
312 unsigned long *dirty_bitmap,
313 unsigned long pages,
314 unsigned long *mb,
315 uint32_t mode,
316 xc_shadow_op_stats_t *stats)
317 {
318 int rc;
319 DECLARE_DOMCTL;
320 domctl.cmd = XEN_DOMCTL_shadow_op;
321 domctl.domain = (domid_t)domid;
322 domctl.u.shadow_op.op = sop;
323 domctl.u.shadow_op.pages = pages;
324 domctl.u.shadow_op.mb = mb ? *mb : 0;
325 domctl.u.shadow_op.mode = mode;
326 set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap,
327 (uint8_t *)dirty_bitmap);
329 rc = do_domctl(xc_handle, &domctl);
331 if ( stats )
332 memcpy(stats, &domctl.u.shadow_op.stats,
333 sizeof(xc_shadow_op_stats_t));
335 if ( mb )
336 *mb = domctl.u.shadow_op.mb;
338 return (rc == 0) ? domctl.u.shadow_op.pages : rc;
339 }
341 int xc_domain_setcpuweight(int xc_handle,
342 uint32_t domid,
343 float weight)
344 {
345 int sched_id;
346 int ret;
348 /* Figure out which scheduler is currently used: */
349 if ( (ret = xc_sched_id(xc_handle, &sched_id)) != 0 )
350 return ret;
352 /* No-op. */
353 return 0;
354 }
356 int xc_domain_setmaxmem(int xc_handle,
357 uint32_t domid,
358 unsigned int max_memkb)
359 {
360 DECLARE_DOMCTL;
361 domctl.cmd = XEN_DOMCTL_max_mem;
362 domctl.domain = (domid_t)domid;
363 domctl.u.max_mem.max_memkb = max_memkb;
364 return do_domctl(xc_handle, &domctl);
365 }
367 #if defined(__i386__) || defined(__x86_64__)
368 #include <xen/hvm/e820.h>
369 int xc_domain_set_memmap_limit(int xc_handle,
370 uint32_t domid,
371 unsigned long map_limitkb)
372 {
373 int rc;
375 struct xen_foreign_memory_map fmap = {
376 .domid = domid,
377 .map = { .nr_entries = 1 }
378 };
380 struct e820entry e820 = {
381 .addr = 0,
382 .size = (uint64_t)map_limitkb << 10,
383 .type = E820_RAM
384 };
386 set_xen_guest_handle(fmap.map.buffer, &e820);
388 if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) )
389 {
390 PERROR("Could not lock memory for Xen hypercall");
391 rc = -1;
392 goto out;
393 }
395 rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap);
397 out:
398 unlock_pages(&fmap, sizeof(fmap));
399 unlock_pages(&e820, sizeof(e820));
400 return rc;
401 }
402 #else
403 int xc_domain_set_memmap_limit(int xc_handle,
404 uint32_t domid,
405 unsigned long map_limitkb)
406 {
407 PERROR("Function not implemented");
408 errno = ENOSYS;
409 return -1;
410 }
411 #endif
413 int xc_domain_set_time_offset(int xc_handle,
414 uint32_t domid,
415 int32_t time_offset_seconds)
416 {
417 DECLARE_DOMCTL;
418 domctl.cmd = XEN_DOMCTL_settimeoffset;
419 domctl.domain = (domid_t)domid;
420 domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
421 return do_domctl(xc_handle, &domctl);
422 }
424 int xc_domain_memory_increase_reservation(int xc_handle,
425 uint32_t domid,
426 unsigned long nr_extents,
427 unsigned int extent_order,
428 unsigned int address_bits,
429 xen_pfn_t *extent_start)
430 {
431 int err;
432 struct xen_memory_reservation reservation = {
433 .nr_extents = nr_extents,
434 .extent_order = extent_order,
435 .address_bits = address_bits,
436 .domid = domid
437 };
439 /* may be NULL */
440 set_xen_guest_handle(reservation.extent_start, extent_start);
442 err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
443 if ( err == nr_extents )
444 return 0;
446 if ( err >= 0 )
447 {
448 DPRINTF("Failed allocation for dom %d: "
449 "%ld extents of order %d, addr_bits %d\n",
450 domid, nr_extents, extent_order, address_bits);
451 errno = ENOMEM;
452 err = -1;
453 }
455 return err;
456 }
458 int xc_domain_memory_decrease_reservation(int xc_handle,
459 uint32_t domid,
460 unsigned long nr_extents,
461 unsigned int extent_order,
462 xen_pfn_t *extent_start)
463 {
464 int err;
465 struct xen_memory_reservation reservation = {
466 .nr_extents = nr_extents,
467 .extent_order = extent_order,
468 .address_bits = 0,
469 .domid = domid
470 };
472 set_xen_guest_handle(reservation.extent_start, extent_start);
474 if ( extent_start == NULL )
475 {
476 DPRINTF("decrease_reservation extent_start is NULL!\n");
477 errno = EINVAL;
478 return -1;
479 }
481 err = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation);
482 if ( err == nr_extents )
483 return 0;
485 if ( err >= 0 )
486 {
487 DPRINTF("Failed deallocation for dom %d: %ld extents of order %d\n",
488 domid, nr_extents, extent_order);
489 errno = EINVAL;
490 err = -1;
491 }
493 return err;
494 }
496 int xc_domain_memory_populate_physmap(int xc_handle,
497 uint32_t domid,
498 unsigned long nr_extents,
499 unsigned int extent_order,
500 unsigned int address_bits,
501 xen_pfn_t *extent_start)
502 {
503 int err;
504 struct xen_memory_reservation reservation = {
505 .nr_extents = nr_extents,
506 .extent_order = extent_order,
507 .address_bits = address_bits,
508 .domid = domid
509 };
510 set_xen_guest_handle(reservation.extent_start, extent_start);
512 err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
513 if ( err == nr_extents )
514 return 0;
516 if ( err >= 0 )
517 {
518 DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
519 domid, nr_extents, extent_order);
520 errno = EBUSY;
521 err = -1;
522 }
524 return err;
525 }
527 int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
528 {
529 DECLARE_DOMCTL;
530 domctl.cmd = XEN_DOMCTL_max_vcpus;
531 domctl.domain = (domid_t)domid;
532 domctl.u.max_vcpus.max = max;
533 return do_domctl(xc_handle, &domctl);
534 }
536 int xc_domain_sethandle(int xc_handle, uint32_t domid,
537 xen_domain_handle_t handle)
538 {
539 DECLARE_DOMCTL;
540 domctl.cmd = XEN_DOMCTL_setdomainhandle;
541 domctl.domain = (domid_t)domid;
542 memcpy(domctl.u.setdomainhandle.handle, handle,
543 sizeof(xen_domain_handle_t));
544 return do_domctl(xc_handle, &domctl);
545 }
547 int xc_vcpu_getinfo(int xc_handle,
548 uint32_t domid,
549 uint32_t vcpu,
550 xc_vcpuinfo_t *info)
551 {
552 int rc;
553 DECLARE_DOMCTL;
555 domctl.cmd = XEN_DOMCTL_getvcpuinfo;
556 domctl.domain = (domid_t)domid;
557 domctl.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
559 rc = do_domctl(xc_handle, &domctl);
561 memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
563 return rc;
564 }
566 int xc_domain_ioport_permission(int xc_handle,
567 uint32_t domid,
568 uint32_t first_port,
569 uint32_t nr_ports,
570 uint32_t allow_access)
571 {
572 DECLARE_DOMCTL;
574 domctl.cmd = XEN_DOMCTL_ioport_permission;
575 domctl.domain = (domid_t)domid;
576 domctl.u.ioport_permission.first_port = first_port;
577 domctl.u.ioport_permission.nr_ports = nr_ports;
578 domctl.u.ioport_permission.allow_access = allow_access;
580 return do_domctl(xc_handle, &domctl);
581 }
583 int xc_vcpu_setcontext(int xc_handle,
584 uint32_t domid,
585 uint32_t vcpu,
586 vcpu_guest_context_t *ctxt)
587 {
588 DECLARE_DOMCTL;
589 int rc;
591 domctl.cmd = XEN_DOMCTL_setvcpucontext;
592 domctl.domain = domid;
593 domctl.u.vcpucontext.vcpu = vcpu;
594 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
596 if ( (ctxt != NULL) && ((rc = lock_pages(ctxt, sizeof(*ctxt))) != 0) )
597 return rc;
599 rc = do_domctl(xc_handle, &domctl);
601 if ( ctxt != NULL )
602 unlock_pages(ctxt, sizeof(*ctxt));
604 return rc;
605 }
607 int xc_domain_irq_permission(int xc_handle,
608 uint32_t domid,
609 uint8_t pirq,
610 uint8_t allow_access)
611 {
612 DECLARE_DOMCTL;
614 domctl.cmd = XEN_DOMCTL_irq_permission;
615 domctl.domain = domid;
616 domctl.u.irq_permission.pirq = pirq;
617 domctl.u.irq_permission.allow_access = allow_access;
619 return do_domctl(xc_handle, &domctl);
620 }
622 int xc_domain_iomem_permission(int xc_handle,
623 uint32_t domid,
624 unsigned long first_mfn,
625 unsigned long nr_mfns,
626 uint8_t allow_access)
627 {
628 DECLARE_DOMCTL;
630 domctl.cmd = XEN_DOMCTL_iomem_permission;
631 domctl.domain = domid;
632 domctl.u.iomem_permission.first_mfn = first_mfn;
633 domctl.u.iomem_permission.nr_mfns = nr_mfns;
634 domctl.u.iomem_permission.allow_access = allow_access;
636 return do_domctl(xc_handle, &domctl);
637 }
639 /*
640 * Local variables:
641 * mode: C
642 * c-set-style: "BSD"
643 * c-basic-offset: 4
644 * tab-width: 4
645 * indent-tabs-mode: nil
646 * End:
647 */