ia64/xen-unstable

view tools/libxc/xc_domain.c @ 17965:14fd83fe71c3

Add facility to get notification of domain suspend by event channel.
This event channel will be notified when the domain transitions to the
suspended state, which can be much faster than raising VIRQ_DOM_EXC
and waiting for the notification to be propagated via xenstore.

No attempt is made here to prevent multiple subscribers (last one
wins), or to detect that the subscriber has gone away. Userspace tools
should take care.

Signed-off-by: Brendan Cully <brendan@cs.ubc.ca>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jul 04 12:00:24 2008 +0100 (2008-07-04)
parents d3a87899985d
children 6c2fe520e32d
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 "xg_save_restore.h"
11 #include <xen/memory.h>
12 #include <xen/hvm/hvm_op.h>
14 int xc_domain_create(int xc_handle,
15 uint32_t ssidref,
16 xen_domain_handle_t handle,
17 uint32_t flags,
18 uint32_t *pdomid)
19 {
20 int err;
21 DECLARE_DOMCTL;
23 domctl.cmd = XEN_DOMCTL_createdomain;
24 domctl.domain = (domid_t)*pdomid;
25 domctl.u.createdomain.ssidref = ssidref;
26 domctl.u.createdomain.flags = flags;
27 memcpy(domctl.u.createdomain.handle, handle, sizeof(xen_domain_handle_t));
28 if ( (err = do_domctl(xc_handle, &domctl)) != 0 )
29 return err;
31 *pdomid = (uint16_t)domctl.domain;
32 return 0;
33 }
36 int xc_domain_pause(int xc_handle,
37 uint32_t domid)
38 {
39 DECLARE_DOMCTL;
40 domctl.cmd = XEN_DOMCTL_pausedomain;
41 domctl.domain = (domid_t)domid;
42 return do_domctl(xc_handle, &domctl);
43 }
46 int xc_domain_unpause(int xc_handle,
47 uint32_t domid)
48 {
49 DECLARE_DOMCTL;
50 domctl.cmd = XEN_DOMCTL_unpausedomain;
51 domctl.domain = (domid_t)domid;
52 return do_domctl(xc_handle, &domctl);
53 }
56 int xc_domain_destroy(int xc_handle,
57 uint32_t domid)
58 {
59 int ret;
60 DECLARE_DOMCTL;
61 domctl.cmd = XEN_DOMCTL_destroydomain;
62 domctl.domain = (domid_t)domid;
63 do {
64 ret = do_domctl(xc_handle, &domctl);
65 } while ( ret && (errno == EAGAIN) );
66 return ret;
67 }
69 int xc_domain_shutdown(int xc_handle,
70 uint32_t domid,
71 int reason)
72 {
73 int ret = -1;
74 sched_remote_shutdown_t arg;
75 DECLARE_HYPERCALL;
77 hypercall.op = __HYPERVISOR_sched_op;
78 hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown;
79 hypercall.arg[1] = (unsigned long)&arg;
80 arg.domain_id = domid;
81 arg.reason = reason;
83 if ( lock_pages(&arg, sizeof(arg)) != 0 )
84 {
85 PERROR("Could not lock memory for Xen hypercall");
86 goto out1;
87 }
89 ret = do_xen_hypercall(xc_handle, &hypercall);
91 unlock_pages(&arg, sizeof(arg));
93 out1:
94 return ret;
95 }
98 int xc_vcpu_setaffinity(int xc_handle,
99 uint32_t domid,
100 int vcpu,
101 uint64_t cpumap)
102 {
103 DECLARE_DOMCTL;
104 int ret = -1;
105 uint8_t local[sizeof (cpumap)];
107 domctl.cmd = XEN_DOMCTL_setvcpuaffinity;
108 domctl.domain = (domid_t)domid;
109 domctl.u.vcpuaffinity.vcpu = vcpu;
111 bitmap_64_to_byte(local, &cpumap, sizeof(cpumap) * 8);
113 set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
115 domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
117 if ( lock_pages(local, sizeof(local)) != 0 )
118 {
119 PERROR("Could not lock memory for Xen hypercall");
120 goto out;
121 }
123 ret = do_domctl(xc_handle, &domctl);
125 unlock_pages(local, sizeof(local));
127 out:
128 return ret;
129 }
132 int xc_vcpu_getaffinity(int xc_handle,
133 uint32_t domid,
134 int vcpu,
135 uint64_t *cpumap)
136 {
137 DECLARE_DOMCTL;
138 int ret = -1;
139 uint8_t local[sizeof (cpumap)];
141 domctl.cmd = XEN_DOMCTL_getvcpuaffinity;
142 domctl.domain = (domid_t)domid;
143 domctl.u.vcpuaffinity.vcpu = vcpu;
145 set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
146 domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
148 if ( lock_pages(local, sizeof(local)) != 0 )
149 {
150 PERROR("Could not lock memory for Xen hypercall");
151 goto out;
152 }
154 ret = do_domctl(xc_handle, &domctl);
156 unlock_pages(local, sizeof (local));
157 bitmap_byte_to_64(cpumap, local, sizeof(local) * 8);
158 out:
159 return ret;
160 }
163 int xc_domain_getinfo(int xc_handle,
164 uint32_t first_domid,
165 unsigned int max_doms,
166 xc_dominfo_t *info)
167 {
168 unsigned int nr_doms;
169 uint32_t next_domid = first_domid;
170 DECLARE_DOMCTL;
171 int rc = 0;
173 memset(info, 0, max_doms*sizeof(xc_dominfo_t));
175 for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
176 {
177 domctl.cmd = XEN_DOMCTL_getdomaininfo;
178 domctl.domain = (domid_t)next_domid;
179 if ( (rc = do_domctl(xc_handle, &domctl)) < 0 )
180 break;
181 info->domid = (uint16_t)domctl.domain;
183 info->dying = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_dying);
184 info->shutdown = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_shutdown);
185 info->paused = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_paused);
186 info->blocked = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
187 info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
188 info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
189 info->debugged = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_debugged);
191 info->shutdown_reason =
192 (domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
193 XEN_DOMINF_shutdownmask;
195 if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
196 {
197 info->shutdown = 0;
198 info->crashed = 1;
199 }
201 info->ssidref = domctl.u.getdomaininfo.ssidref;
202 info->nr_pages = domctl.u.getdomaininfo.tot_pages;
203 info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10);
204 info->shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
205 info->cpu_time = domctl.u.getdomaininfo.cpu_time;
206 info->nr_online_vcpus = domctl.u.getdomaininfo.nr_online_vcpus;
207 info->max_vcpu_id = domctl.u.getdomaininfo.max_vcpu_id;
209 memcpy(info->handle, domctl.u.getdomaininfo.handle,
210 sizeof(xen_domain_handle_t));
212 next_domid = (uint16_t)domctl.domain + 1;
213 info++;
214 }
216 if ( nr_doms == 0 )
217 return rc;
219 return nr_doms;
220 }
222 int xc_domain_getinfolist(int xc_handle,
223 uint32_t first_domain,
224 unsigned int max_domains,
225 xc_domaininfo_t *info)
226 {
227 int ret = 0;
228 DECLARE_SYSCTL;
230 if ( lock_pages(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
231 return -1;
233 sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
234 sysctl.u.getdomaininfolist.first_domain = first_domain;
235 sysctl.u.getdomaininfolist.max_domains = max_domains;
236 set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);
238 if ( xc_sysctl(xc_handle, &sysctl) < 0 )
239 ret = -1;
240 else
241 ret = sysctl.u.getdomaininfolist.num_domains;
243 unlock_pages(info, max_domains*sizeof(xc_domaininfo_t));
245 return ret;
246 }
248 /* get info from hvm guest for save */
249 int xc_domain_hvm_getcontext(int xc_handle,
250 uint32_t domid,
251 uint8_t *ctxt_buf,
252 uint32_t size)
253 {
254 int ret;
255 DECLARE_DOMCTL;
257 domctl.cmd = XEN_DOMCTL_gethvmcontext;
258 domctl.domain = (domid_t)domid;
259 domctl.u.hvmcontext.size = size;
260 set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
262 if ( ctxt_buf )
263 if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
264 return ret;
266 ret = do_domctl(xc_handle, &domctl);
268 if ( ctxt_buf )
269 unlock_pages(ctxt_buf, size);
271 return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
272 }
274 /* set info to hvm guest for restore */
275 int xc_domain_hvm_setcontext(int xc_handle,
276 uint32_t domid,
277 uint8_t *ctxt_buf,
278 uint32_t size)
279 {
280 int ret;
281 DECLARE_DOMCTL;
283 domctl.cmd = XEN_DOMCTL_sethvmcontext;
284 domctl.domain = domid;
285 domctl.u.hvmcontext.size = size;
286 set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
288 if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
289 return ret;
291 ret = do_domctl(xc_handle, &domctl);
293 unlock_pages(ctxt_buf, size);
295 return ret;
296 }
298 int xc_vcpu_getcontext(int xc_handle,
299 uint32_t domid,
300 uint32_t vcpu,
301 vcpu_guest_context_any_t *ctxt)
302 {
303 int rc;
304 DECLARE_DOMCTL;
305 size_t sz = sizeof(vcpu_guest_context_any_t);
307 domctl.cmd = XEN_DOMCTL_getvcpucontext;
308 domctl.domain = (domid_t)domid;
309 domctl.u.vcpucontext.vcpu = (uint16_t)vcpu;
310 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt->c);
313 if ( (rc = lock_pages(ctxt, sz)) != 0 )
314 return rc;
315 rc = do_domctl(xc_handle, &domctl);
316 unlock_pages(ctxt, sz);
318 return rc;
319 }
322 int xc_shadow_control(int xc_handle,
323 uint32_t domid,
324 unsigned int sop,
325 unsigned long *dirty_bitmap,
326 unsigned long pages,
327 unsigned long *mb,
328 uint32_t mode,
329 xc_shadow_op_stats_t *stats)
330 {
331 int rc;
332 DECLARE_DOMCTL;
333 domctl.cmd = XEN_DOMCTL_shadow_op;
334 domctl.domain = (domid_t)domid;
335 domctl.u.shadow_op.op = sop;
336 domctl.u.shadow_op.pages = pages;
337 domctl.u.shadow_op.mb = mb ? *mb : 0;
338 domctl.u.shadow_op.mode = mode;
339 set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap,
340 (uint8_t *)dirty_bitmap);
342 rc = do_domctl(xc_handle, &domctl);
344 if ( stats )
345 memcpy(stats, &domctl.u.shadow_op.stats,
346 sizeof(xc_shadow_op_stats_t));
348 if ( mb )
349 *mb = domctl.u.shadow_op.mb;
351 return (rc == 0) ? domctl.u.shadow_op.pages : rc;
352 }
354 int xc_domain_setmaxmem(int xc_handle,
355 uint32_t domid,
356 unsigned int max_memkb)
357 {
358 DECLARE_DOMCTL;
359 domctl.cmd = XEN_DOMCTL_max_mem;
360 domctl.domain = (domid_t)domid;
361 domctl.u.max_mem.max_memkb = max_memkb;
362 return do_domctl(xc_handle, &domctl);
363 }
365 int xc_domain_pin_memory_cacheattr(int xc_handle,
366 uint32_t domid,
367 uint64_t start,
368 uint64_t end,
369 uint32_t type)
370 {
371 DECLARE_DOMCTL;
372 domctl.cmd = XEN_DOMCTL_pin_mem_cacheattr;
373 domctl.domain = (domid_t)domid;
374 domctl.u.pin_mem_cacheattr.start = start;
375 domctl.u.pin_mem_cacheattr.end = end;
376 domctl.u.pin_mem_cacheattr.type = type;
377 return do_domctl(xc_handle, &domctl);
378 }
380 #if defined(__i386__) || defined(__x86_64__)
381 #include "xc_e820.h"
382 int xc_domain_set_memmap_limit(int xc_handle,
383 uint32_t domid,
384 unsigned long map_limitkb)
385 {
386 int rc;
388 struct xen_foreign_memory_map fmap = {
389 .domid = domid,
390 .map = { .nr_entries = 1 }
391 };
393 struct e820entry e820 = {
394 .addr = 0,
395 .size = (uint64_t)map_limitkb << 10,
396 .type = E820_RAM
397 };
399 set_xen_guest_handle(fmap.map.buffer, &e820);
401 if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) )
402 {
403 PERROR("Could not lock memory for Xen hypercall");
404 rc = -1;
405 goto out;
406 }
408 rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap);
410 out:
411 unlock_pages(&fmap, sizeof(fmap));
412 unlock_pages(&e820, sizeof(e820));
413 return rc;
414 }
415 #else
416 int xc_domain_set_memmap_limit(int xc_handle,
417 uint32_t domid,
418 unsigned long map_limitkb)
419 {
420 PERROR("Function not implemented");
421 errno = ENOSYS;
422 return -1;
423 }
424 #endif
426 int xc_domain_set_time_offset(int xc_handle,
427 uint32_t domid,
428 int32_t time_offset_seconds)
429 {
430 DECLARE_DOMCTL;
431 domctl.cmd = XEN_DOMCTL_settimeoffset;
432 domctl.domain = (domid_t)domid;
433 domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
434 return do_domctl(xc_handle, &domctl);
435 }
437 int xc_domain_memory_increase_reservation(int xc_handle,
438 uint32_t domid,
439 unsigned long nr_extents,
440 unsigned int extent_order,
441 unsigned int address_bits,
442 xen_pfn_t *extent_start)
443 {
444 int err;
445 struct xen_memory_reservation reservation = {
446 .nr_extents = nr_extents,
447 .extent_order = extent_order,
448 .address_bits = address_bits,
449 .domid = domid
450 };
452 /* may be NULL */
453 set_xen_guest_handle(reservation.extent_start, extent_start);
455 err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
456 if ( err == nr_extents )
457 return 0;
459 if ( err >= 0 )
460 {
461 DPRINTF("Failed allocation for dom %d: "
462 "%ld extents of order %d, addr_bits %d\n",
463 domid, nr_extents, extent_order, address_bits);
464 errno = ENOMEM;
465 err = -1;
466 }
468 return err;
469 }
471 int xc_domain_memory_decrease_reservation(int xc_handle,
472 uint32_t domid,
473 unsigned long nr_extents,
474 unsigned int extent_order,
475 xen_pfn_t *extent_start)
476 {
477 int err;
478 struct xen_memory_reservation reservation = {
479 .nr_extents = nr_extents,
480 .extent_order = extent_order,
481 .address_bits = 0,
482 .domid = domid
483 };
485 set_xen_guest_handle(reservation.extent_start, extent_start);
487 if ( extent_start == NULL )
488 {
489 DPRINTF("decrease_reservation extent_start is NULL!\n");
490 errno = EINVAL;
491 return -1;
492 }
494 err = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation);
495 if ( err == nr_extents )
496 return 0;
498 if ( err >= 0 )
499 {
500 DPRINTF("Failed deallocation for dom %d: %ld extents of order %d\n",
501 domid, nr_extents, extent_order);
502 errno = EINVAL;
503 err = -1;
504 }
506 return err;
507 }
509 int xc_domain_memory_populate_physmap(int xc_handle,
510 uint32_t domid,
511 unsigned long nr_extents,
512 unsigned int extent_order,
513 unsigned int address_bits,
514 xen_pfn_t *extent_start)
515 {
516 int err;
517 struct xen_memory_reservation reservation = {
518 .nr_extents = nr_extents,
519 .extent_order = extent_order,
520 .address_bits = address_bits,
521 .domid = domid
522 };
523 set_xen_guest_handle(reservation.extent_start, extent_start);
525 err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
526 if ( err == nr_extents )
527 return 0;
529 if ( err >= 0 )
530 {
531 DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
532 domid, nr_extents, extent_order);
533 errno = EBUSY;
534 err = -1;
535 }
537 return err;
538 }
540 int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
541 {
542 DECLARE_DOMCTL;
543 domctl.cmd = XEN_DOMCTL_max_vcpus;
544 domctl.domain = (domid_t)domid;
545 domctl.u.max_vcpus.max = max;
546 return do_domctl(xc_handle, &domctl);
547 }
549 int xc_domain_sethandle(int xc_handle, uint32_t domid,
550 xen_domain_handle_t handle)
551 {
552 DECLARE_DOMCTL;
553 domctl.cmd = XEN_DOMCTL_setdomainhandle;
554 domctl.domain = (domid_t)domid;
555 memcpy(domctl.u.setdomainhandle.handle, handle,
556 sizeof(xen_domain_handle_t));
557 return do_domctl(xc_handle, &domctl);
558 }
560 int xc_vcpu_getinfo(int xc_handle,
561 uint32_t domid,
562 uint32_t vcpu,
563 xc_vcpuinfo_t *info)
564 {
565 int rc;
566 DECLARE_DOMCTL;
568 domctl.cmd = XEN_DOMCTL_getvcpuinfo;
569 domctl.domain = (domid_t)domid;
570 domctl.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
572 rc = do_domctl(xc_handle, &domctl);
574 memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
576 return rc;
577 }
579 int xc_domain_ioport_permission(int xc_handle,
580 uint32_t domid,
581 uint32_t first_port,
582 uint32_t nr_ports,
583 uint32_t allow_access)
584 {
585 DECLARE_DOMCTL;
587 domctl.cmd = XEN_DOMCTL_ioport_permission;
588 domctl.domain = (domid_t)domid;
589 domctl.u.ioport_permission.first_port = first_port;
590 domctl.u.ioport_permission.nr_ports = nr_ports;
591 domctl.u.ioport_permission.allow_access = allow_access;
593 return do_domctl(xc_handle, &domctl);
594 }
596 int xc_availheap(int xc_handle,
597 int min_width,
598 int max_width,
599 int node,
600 uint64_t *bytes)
601 {
602 DECLARE_SYSCTL;
603 int rc;
605 sysctl.cmd = XEN_SYSCTL_availheap;
606 sysctl.u.availheap.min_bitwidth = min_width;
607 sysctl.u.availheap.max_bitwidth = max_width;
608 sysctl.u.availheap.node = node;
610 rc = xc_sysctl(xc_handle, &sysctl);
612 *bytes = sysctl.u.availheap.avail_bytes;
614 return rc;
615 }
617 int xc_vcpu_setcontext(int xc_handle,
618 uint32_t domid,
619 uint32_t vcpu,
620 vcpu_guest_context_any_t *ctxt)
621 {
622 DECLARE_DOMCTL;
623 int rc;
624 size_t sz = sizeof(vcpu_guest_context_any_t);
626 if (ctxt == NULL)
627 {
628 errno = EINVAL;
629 return -1;
630 }
632 domctl.cmd = XEN_DOMCTL_setvcpucontext;
633 domctl.domain = domid;
634 domctl.u.vcpucontext.vcpu = vcpu;
635 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt->c);
637 if ( (rc = lock_pages(ctxt, sz)) != 0 )
638 return rc;
639 rc = do_domctl(xc_handle, &domctl);
641 unlock_pages(ctxt, sz);
643 return rc;
644 }
646 int xc_domain_irq_permission(int xc_handle,
647 uint32_t domid,
648 uint8_t pirq,
649 uint8_t allow_access)
650 {
651 DECLARE_DOMCTL;
653 domctl.cmd = XEN_DOMCTL_irq_permission;
654 domctl.domain = domid;
655 domctl.u.irq_permission.pirq = pirq;
656 domctl.u.irq_permission.allow_access = allow_access;
658 return do_domctl(xc_handle, &domctl);
659 }
661 int xc_domain_iomem_permission(int xc_handle,
662 uint32_t domid,
663 unsigned long first_mfn,
664 unsigned long nr_mfns,
665 uint8_t allow_access)
666 {
667 DECLARE_DOMCTL;
669 domctl.cmd = XEN_DOMCTL_iomem_permission;
670 domctl.domain = domid;
671 domctl.u.iomem_permission.first_mfn = first_mfn;
672 domctl.u.iomem_permission.nr_mfns = nr_mfns;
673 domctl.u.iomem_permission.allow_access = allow_access;
675 return do_domctl(xc_handle, &domctl);
676 }
678 int xc_domain_send_trigger(int xc_handle,
679 uint32_t domid,
680 uint32_t trigger,
681 uint32_t vcpu)
682 {
683 DECLARE_DOMCTL;
685 domctl.cmd = XEN_DOMCTL_sendtrigger;
686 domctl.domain = domid;
687 domctl.u.sendtrigger.trigger = trigger;
688 domctl.u.sendtrigger.vcpu = vcpu;
690 return do_domctl(xc_handle, &domctl);
691 }
693 int xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value)
694 {
695 DECLARE_HYPERCALL;
696 xen_hvm_param_t arg;
697 int rc;
699 hypercall.op = __HYPERVISOR_hvm_op;
700 hypercall.arg[0] = HVMOP_set_param;
701 hypercall.arg[1] = (unsigned long)&arg;
702 arg.domid = dom;
703 arg.index = param;
704 arg.value = value;
705 if ( lock_pages(&arg, sizeof(arg)) != 0 )
706 return -1;
707 rc = do_xen_hypercall(handle, &hypercall);
708 unlock_pages(&arg, sizeof(arg));
709 return rc;
710 }
712 int xc_get_hvm_param(int handle, domid_t dom, int param, unsigned long *value)
713 {
714 DECLARE_HYPERCALL;
715 xen_hvm_param_t arg;
716 int rc;
718 hypercall.op = __HYPERVISOR_hvm_op;
719 hypercall.arg[0] = HVMOP_get_param;
720 hypercall.arg[1] = (unsigned long)&arg;
721 arg.domid = dom;
722 arg.index = param;
723 if ( lock_pages(&arg, sizeof(arg)) != 0 )
724 return -1;
725 rc = do_xen_hypercall(handle, &hypercall);
726 unlock_pages(&arg, sizeof(arg));
727 *value = arg.value;
728 return rc;
729 }
731 int xc_domain_setdebugging(int xc_handle,
732 uint32_t domid,
733 unsigned int enable)
734 {
735 DECLARE_DOMCTL;
737 domctl.cmd = XEN_DOMCTL_setdebugging;
738 domctl.domain = domid;
739 domctl.u.setdebugging.enable = enable;
740 return do_domctl(xc_handle, &domctl);
741 }
743 int xc_assign_device(
744 int xc_handle,
745 uint32_t domid,
746 uint32_t machine_bdf)
747 {
748 DECLARE_DOMCTL;
750 domctl.cmd = XEN_DOMCTL_assign_device;
751 domctl.domain = domid;
752 domctl.u.assign_device.machine_bdf = machine_bdf;
754 return do_domctl(xc_handle, &domctl);
755 }
757 int xc_get_device_group(
758 int xc_handle,
759 uint32_t domid,
760 uint32_t machine_bdf,
761 uint32_t max_sdevs,
762 uint32_t *num_sdevs,
763 uint32_t *sdev_array)
764 {
765 int rc;
766 DECLARE_DOMCTL;
768 domctl.cmd = XEN_DOMCTL_get_device_group;
769 domctl.domain = (domid_t)domid;
771 domctl.u.get_device_group.machine_bdf = machine_bdf;
772 domctl.u.get_device_group.max_sdevs = max_sdevs;
774 set_xen_guest_handle(domctl.u.get_device_group.sdev_array, sdev_array);
776 if ( lock_pages(sdev_array, max_sdevs * sizeof(*sdev_array)) != 0 )
777 {
778 PERROR("Could not lock memory for xc_get_device_group\n");
779 return -ENOMEM;
780 }
781 rc = do_domctl(xc_handle, &domctl);
782 unlock_pages(sdev_array, max_sdevs * sizeof(*sdev_array));
784 *num_sdevs = domctl.u.get_device_group.num_sdevs;
785 return rc;
786 }
788 int xc_test_assign_device(
789 int xc_handle,
790 uint32_t domid,
791 uint32_t machine_bdf)
792 {
793 DECLARE_DOMCTL;
795 domctl.cmd = XEN_DOMCTL_test_assign_device;
796 domctl.domain = domid;
797 domctl.u.assign_device.machine_bdf = machine_bdf;
799 return do_domctl(xc_handle, &domctl);
800 }
802 int xc_deassign_device(
803 int xc_handle,
804 uint32_t domid,
805 uint32_t machine_bdf)
806 {
807 DECLARE_DOMCTL;
809 domctl.cmd = XEN_DOMCTL_deassign_device;
810 domctl.domain = domid;
811 domctl.u.assign_device.machine_bdf = machine_bdf;
813 return do_domctl(xc_handle, &domctl);
814 }
816 int xc_domain_update_msi_irq(
817 int xc_handle,
818 uint32_t domid,
819 uint32_t gvec,
820 uint32_t pirq,
821 uint32_t gflags)
822 {
823 int rc;
824 xen_domctl_bind_pt_irq_t *bind;
826 DECLARE_DOMCTL;
828 domctl.cmd = XEN_DOMCTL_bind_pt_irq;
829 domctl.domain = (domid_t)domid;
831 bind = &(domctl.u.bind_pt_irq);
832 bind->hvm_domid = domid;
833 bind->irq_type = PT_IRQ_TYPE_MSI;
834 bind->machine_irq = pirq;
835 bind->u.msi.gvec = gvec;
836 bind->u.msi.gflags = gflags;
838 rc = do_domctl(xc_handle, &domctl);
839 return rc;
840 }
842 /* Pass-through: binds machine irq to guests irq */
843 int xc_domain_bind_pt_irq(
844 int xc_handle,
845 uint32_t domid,
846 uint8_t machine_irq,
847 uint8_t irq_type,
848 uint8_t bus,
849 uint8_t device,
850 uint8_t intx,
851 uint8_t isa_irq)
852 {
853 int rc;
854 xen_domctl_bind_pt_irq_t * bind;
855 DECLARE_DOMCTL;
857 domctl.cmd = XEN_DOMCTL_bind_pt_irq;
858 domctl.domain = (domid_t)domid;
860 bind = &(domctl.u.bind_pt_irq);
861 bind->hvm_domid = domid;
862 bind->irq_type = irq_type;
863 bind->machine_irq = machine_irq;
864 if ( irq_type == PT_IRQ_TYPE_PCI )
865 {
866 bind->u.pci.bus = bus;
867 bind->u.pci.device = device;
868 bind->u.pci.intx = intx;
869 }
870 else if ( irq_type == PT_IRQ_TYPE_ISA )
871 bind->u.isa.isa_irq = isa_irq;
873 rc = do_domctl(xc_handle, &domctl);
874 return rc;
875 }
877 int xc_domain_unbind_pt_irq(
878 int xc_handle,
879 uint32_t domid,
880 uint8_t machine_irq,
881 uint8_t irq_type,
882 uint8_t bus,
883 uint8_t device,
884 uint8_t intx,
885 uint8_t isa_irq)
886 {
887 int rc;
888 xen_domctl_bind_pt_irq_t * bind;
889 DECLARE_DOMCTL;
891 domctl.cmd = XEN_DOMCTL_unbind_pt_irq;
892 domctl.domain = (domid_t)domid;
894 bind = &(domctl.u.bind_pt_irq);
895 bind->hvm_domid = domid;
896 bind->irq_type = irq_type;
897 bind->machine_irq = machine_irq;
898 bind->u.pci.bus = bus;
899 bind->u.pci.device = device;
900 bind->u.pci.intx = intx;
901 bind->u.isa.isa_irq = isa_irq;
903 rc = do_domctl(xc_handle, &domctl);
904 return rc;
905 }
907 int xc_domain_bind_pt_pci_irq(
908 int xc_handle,
909 uint32_t domid,
910 uint8_t machine_irq,
911 uint8_t bus,
912 uint8_t device,
913 uint8_t intx)
914 {
916 return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
917 PT_IRQ_TYPE_PCI, bus, device, intx, 0));
918 }
920 int xc_domain_bind_pt_isa_irq(
921 int xc_handle,
922 uint32_t domid,
923 uint8_t machine_irq)
924 {
926 return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
927 PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq));
928 }
930 int xc_domain_memory_mapping(
931 int xc_handle,
932 uint32_t domid,
933 unsigned long first_gfn,
934 unsigned long first_mfn,
935 unsigned long nr_mfns,
936 uint32_t add_mapping)
937 {
938 DECLARE_DOMCTL;
940 domctl.cmd = XEN_DOMCTL_memory_mapping;
941 domctl.domain = domid;
942 domctl.u.memory_mapping.first_gfn = first_gfn;
943 domctl.u.memory_mapping.first_mfn = first_mfn;
944 domctl.u.memory_mapping.nr_mfns = nr_mfns;
945 domctl.u.memory_mapping.add_mapping = add_mapping;
947 return do_domctl(xc_handle, &domctl);
948 }
950 int xc_domain_ioport_mapping(
951 int xc_handle,
952 uint32_t domid,
953 uint32_t first_gport,
954 uint32_t first_mport,
955 uint32_t nr_ports,
956 uint32_t add_mapping)
957 {
958 DECLARE_DOMCTL;
960 domctl.cmd = XEN_DOMCTL_ioport_mapping;
961 domctl.domain = domid;
962 domctl.u.ioport_mapping.first_gport = first_gport;
963 domctl.u.ioport_mapping.first_mport = first_mport;
964 domctl.u.ioport_mapping.nr_ports = nr_ports;
965 domctl.u.ioport_mapping.add_mapping = add_mapping;
967 return do_domctl(xc_handle, &domctl);
968 }
970 int xc_domain_set_target(
971 int xc_handle,
972 uint32_t domid,
973 uint32_t target)
974 {
975 DECLARE_DOMCTL;
977 domctl.cmd = XEN_DOMCTL_set_target;
978 domctl.domain = domid;
979 domctl.u.set_target.target = target;
981 return do_domctl(xc_handle, &domctl);
982 }
984 int xc_dom_subscribe(int xc_handle, domid_t dom, evtchn_port_t port)
985 {
986 DECLARE_DOMCTL;
988 domctl.cmd = XEN_DOMCTL_subscribe;
989 domctl.domain = dom;
990 domctl.u.subscribe.port = port;
992 return do_domctl(xc_handle, &domctl);
993 }
995 /*
996 * Local variables:
997 * mode: C
998 * c-set-style: "BSD"
999 * c-basic-offset: 4
1000 * tab-width: 4
1001 * indent-tabs-mode: nil
1002 * End:
1003 */