ia64/xen-unstable

view tools/libxc/xc_domain.c @ 18394:dade7f0bdc8d

hvm: Use main memory for video memory.

When creating an HVM domain, if e.g. another domain is created before
qemu allocates video memory, the extra 8MB memory ballooning is not
available any more, because it got consumed by the other domain.

This fixes it by taking video memory from the main memory:

- make hvmloader use e820_malloc to reserve some of the main memory
and notify ioemu of its address through the Xen platform PCI card.
- add XENMAPSPACE_mfn to the xen_add_to_physmap memory op, to allow
ioemu to move the MFNs between the original position and the PCI
mapping, when LFB acceleration is disabled/enabled
- add a remove_from_physmap memory op, to allow ioemu to unmap it
completely for the case of old guests with acceleration disabled.
- add xc_domain_memory_translate_gpfn_list to libxc to allow ioemu to
get the MFNs of the video memory.
- have xend save the PCI memory space instead of ioemu: if a memory
page is there, the guest can access it like usual memory, so xend
can safely be responsible to save it. The extra benefit is that
live migration will apply the logdirty optimization there too.
- handle old saved images, populating the video memory from ioemu if
really needed.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Aug 27 14:53:39 2008 +0100 (2008-08-27)
parents f40c310dca31
children 3603e95245fa
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 mem_flags,
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 .mem_flags = mem_flags,
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, mem_flags %x\n",
463 domid, nr_extents, extent_order, mem_flags);
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 .mem_flags = 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 mem_flags,
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 .mem_flags = mem_flags,
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_memory_translate_gpfn_list(int xc_handle,
541 uint32_t domid,
542 unsigned long nr_gpfns,
543 xen_pfn_t *gpfn_list,
544 xen_pfn_t *mfn_list)
545 {
546 int err;
547 struct xen_translate_gpfn_list translate_gpfn_list = {
548 .domid = domid,
549 .nr_gpfns = nr_gpfns,
550 };
551 set_xen_guest_handle(translate_gpfn_list.gpfn_list, gpfn_list);
552 set_xen_guest_handle(translate_gpfn_list.mfn_list, mfn_list);
554 err = xc_memory_op(xc_handle, XENMEM_translate_gpfn_list, &translate_gpfn_list);
556 if ( err != 0 )
557 {
558 DPRINTF("Failed translation for dom %d (%ld PFNs)\n",
559 domid, nr_gpfns);
560 errno = -err;
561 err = -1;
562 }
564 return err;
565 }
567 int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
568 {
569 DECLARE_DOMCTL;
570 domctl.cmd = XEN_DOMCTL_max_vcpus;
571 domctl.domain = (domid_t)domid;
572 domctl.u.max_vcpus.max = max;
573 return do_domctl(xc_handle, &domctl);
574 }
576 int xc_domain_sethandle(int xc_handle, uint32_t domid,
577 xen_domain_handle_t handle)
578 {
579 DECLARE_DOMCTL;
580 domctl.cmd = XEN_DOMCTL_setdomainhandle;
581 domctl.domain = (domid_t)domid;
582 memcpy(domctl.u.setdomainhandle.handle, handle,
583 sizeof(xen_domain_handle_t));
584 return do_domctl(xc_handle, &domctl);
585 }
587 int xc_vcpu_getinfo(int xc_handle,
588 uint32_t domid,
589 uint32_t vcpu,
590 xc_vcpuinfo_t *info)
591 {
592 int rc;
593 DECLARE_DOMCTL;
595 domctl.cmd = XEN_DOMCTL_getvcpuinfo;
596 domctl.domain = (domid_t)domid;
597 domctl.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
599 rc = do_domctl(xc_handle, &domctl);
601 memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
603 return rc;
604 }
606 int xc_domain_ioport_permission(int xc_handle,
607 uint32_t domid,
608 uint32_t first_port,
609 uint32_t nr_ports,
610 uint32_t allow_access)
611 {
612 DECLARE_DOMCTL;
614 domctl.cmd = XEN_DOMCTL_ioport_permission;
615 domctl.domain = (domid_t)domid;
616 domctl.u.ioport_permission.first_port = first_port;
617 domctl.u.ioport_permission.nr_ports = nr_ports;
618 domctl.u.ioport_permission.allow_access = allow_access;
620 return do_domctl(xc_handle, &domctl);
621 }
623 int xc_availheap(int xc_handle,
624 int min_width,
625 int max_width,
626 int node,
627 uint64_t *bytes)
628 {
629 DECLARE_SYSCTL;
630 int rc;
632 sysctl.cmd = XEN_SYSCTL_availheap;
633 sysctl.u.availheap.min_bitwidth = min_width;
634 sysctl.u.availheap.max_bitwidth = max_width;
635 sysctl.u.availheap.node = node;
637 rc = xc_sysctl(xc_handle, &sysctl);
639 *bytes = sysctl.u.availheap.avail_bytes;
641 return rc;
642 }
644 int xc_vcpu_setcontext(int xc_handle,
645 uint32_t domid,
646 uint32_t vcpu,
647 vcpu_guest_context_any_t *ctxt)
648 {
649 DECLARE_DOMCTL;
650 int rc;
651 size_t sz = sizeof(vcpu_guest_context_any_t);
653 if (ctxt == NULL)
654 {
655 errno = EINVAL;
656 return -1;
657 }
659 domctl.cmd = XEN_DOMCTL_setvcpucontext;
660 domctl.domain = domid;
661 domctl.u.vcpucontext.vcpu = vcpu;
662 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt->c);
664 if ( (rc = lock_pages(ctxt, sz)) != 0 )
665 return rc;
666 rc = do_domctl(xc_handle, &domctl);
668 unlock_pages(ctxt, sz);
670 return rc;
671 }
673 int xc_domain_irq_permission(int xc_handle,
674 uint32_t domid,
675 uint8_t pirq,
676 uint8_t allow_access)
677 {
678 DECLARE_DOMCTL;
680 domctl.cmd = XEN_DOMCTL_irq_permission;
681 domctl.domain = domid;
682 domctl.u.irq_permission.pirq = pirq;
683 domctl.u.irq_permission.allow_access = allow_access;
685 return do_domctl(xc_handle, &domctl);
686 }
688 int xc_domain_iomem_permission(int xc_handle,
689 uint32_t domid,
690 unsigned long first_mfn,
691 unsigned long nr_mfns,
692 uint8_t allow_access)
693 {
694 DECLARE_DOMCTL;
696 domctl.cmd = XEN_DOMCTL_iomem_permission;
697 domctl.domain = domid;
698 domctl.u.iomem_permission.first_mfn = first_mfn;
699 domctl.u.iomem_permission.nr_mfns = nr_mfns;
700 domctl.u.iomem_permission.allow_access = allow_access;
702 return do_domctl(xc_handle, &domctl);
703 }
705 int xc_domain_send_trigger(int xc_handle,
706 uint32_t domid,
707 uint32_t trigger,
708 uint32_t vcpu)
709 {
710 DECLARE_DOMCTL;
712 domctl.cmd = XEN_DOMCTL_sendtrigger;
713 domctl.domain = domid;
714 domctl.u.sendtrigger.trigger = trigger;
715 domctl.u.sendtrigger.vcpu = vcpu;
717 return do_domctl(xc_handle, &domctl);
718 }
720 int xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value)
721 {
722 DECLARE_HYPERCALL;
723 xen_hvm_param_t arg;
724 int rc;
726 hypercall.op = __HYPERVISOR_hvm_op;
727 hypercall.arg[0] = HVMOP_set_param;
728 hypercall.arg[1] = (unsigned long)&arg;
729 arg.domid = dom;
730 arg.index = param;
731 arg.value = value;
732 if ( lock_pages(&arg, sizeof(arg)) != 0 )
733 return -1;
734 rc = do_xen_hypercall(handle, &hypercall);
735 unlock_pages(&arg, sizeof(arg));
736 return rc;
737 }
739 int xc_get_hvm_param(int handle, domid_t dom, int param, unsigned long *value)
740 {
741 DECLARE_HYPERCALL;
742 xen_hvm_param_t arg;
743 int rc;
745 hypercall.op = __HYPERVISOR_hvm_op;
746 hypercall.arg[0] = HVMOP_get_param;
747 hypercall.arg[1] = (unsigned long)&arg;
748 arg.domid = dom;
749 arg.index = param;
750 if ( lock_pages(&arg, sizeof(arg)) != 0 )
751 return -1;
752 rc = do_xen_hypercall(handle, &hypercall);
753 unlock_pages(&arg, sizeof(arg));
754 *value = arg.value;
755 return rc;
756 }
758 int xc_domain_setdebugging(int xc_handle,
759 uint32_t domid,
760 unsigned int enable)
761 {
762 DECLARE_DOMCTL;
764 domctl.cmd = XEN_DOMCTL_setdebugging;
765 domctl.domain = domid;
766 domctl.u.setdebugging.enable = enable;
767 return do_domctl(xc_handle, &domctl);
768 }
770 int xc_assign_device(
771 int xc_handle,
772 uint32_t domid,
773 uint32_t machine_bdf)
774 {
775 DECLARE_DOMCTL;
777 domctl.cmd = XEN_DOMCTL_assign_device;
778 domctl.domain = domid;
779 domctl.u.assign_device.machine_bdf = machine_bdf;
781 return do_domctl(xc_handle, &domctl);
782 }
784 int xc_get_device_group(
785 int xc_handle,
786 uint32_t domid,
787 uint32_t machine_bdf,
788 uint32_t max_sdevs,
789 uint32_t *num_sdevs,
790 uint32_t *sdev_array)
791 {
792 int rc;
793 DECLARE_DOMCTL;
795 domctl.cmd = XEN_DOMCTL_get_device_group;
796 domctl.domain = (domid_t)domid;
798 domctl.u.get_device_group.machine_bdf = machine_bdf;
799 domctl.u.get_device_group.max_sdevs = max_sdevs;
801 set_xen_guest_handle(domctl.u.get_device_group.sdev_array, sdev_array);
803 if ( lock_pages(sdev_array, max_sdevs * sizeof(*sdev_array)) != 0 )
804 {
805 PERROR("Could not lock memory for xc_get_device_group\n");
806 return -ENOMEM;
807 }
808 rc = do_domctl(xc_handle, &domctl);
809 unlock_pages(sdev_array, max_sdevs * sizeof(*sdev_array));
811 *num_sdevs = domctl.u.get_device_group.num_sdevs;
812 return rc;
813 }
815 int xc_test_assign_device(
816 int xc_handle,
817 uint32_t domid,
818 uint32_t machine_bdf)
819 {
820 DECLARE_DOMCTL;
822 domctl.cmd = XEN_DOMCTL_test_assign_device;
823 domctl.domain = domid;
824 domctl.u.assign_device.machine_bdf = machine_bdf;
826 return do_domctl(xc_handle, &domctl);
827 }
829 int xc_deassign_device(
830 int xc_handle,
831 uint32_t domid,
832 uint32_t machine_bdf)
833 {
834 DECLARE_DOMCTL;
836 domctl.cmd = XEN_DOMCTL_deassign_device;
837 domctl.domain = domid;
838 domctl.u.assign_device.machine_bdf = machine_bdf;
840 return do_domctl(xc_handle, &domctl);
841 }
843 int xc_domain_update_msi_irq(
844 int xc_handle,
845 uint32_t domid,
846 uint32_t gvec,
847 uint32_t pirq,
848 uint32_t gflags)
849 {
850 int rc;
851 xen_domctl_bind_pt_irq_t *bind;
853 DECLARE_DOMCTL;
855 domctl.cmd = XEN_DOMCTL_bind_pt_irq;
856 domctl.domain = (domid_t)domid;
858 bind = &(domctl.u.bind_pt_irq);
859 bind->hvm_domid = domid;
860 bind->irq_type = PT_IRQ_TYPE_MSI;
861 bind->machine_irq = pirq;
862 bind->u.msi.gvec = gvec;
863 bind->u.msi.gflags = gflags;
865 rc = do_domctl(xc_handle, &domctl);
866 return rc;
867 }
869 /* Pass-through: binds machine irq to guests irq */
870 int xc_domain_bind_pt_irq(
871 int xc_handle,
872 uint32_t domid,
873 uint8_t machine_irq,
874 uint8_t irq_type,
875 uint8_t bus,
876 uint8_t device,
877 uint8_t intx,
878 uint8_t isa_irq)
879 {
880 int rc;
881 xen_domctl_bind_pt_irq_t * bind;
882 DECLARE_DOMCTL;
884 domctl.cmd = XEN_DOMCTL_bind_pt_irq;
885 domctl.domain = (domid_t)domid;
887 bind = &(domctl.u.bind_pt_irq);
888 bind->hvm_domid = domid;
889 bind->irq_type = irq_type;
890 bind->machine_irq = machine_irq;
891 if ( irq_type == PT_IRQ_TYPE_PCI )
892 {
893 bind->u.pci.bus = bus;
894 bind->u.pci.device = device;
895 bind->u.pci.intx = intx;
896 }
897 else if ( irq_type == PT_IRQ_TYPE_ISA )
898 bind->u.isa.isa_irq = isa_irq;
900 rc = do_domctl(xc_handle, &domctl);
901 return rc;
902 }
904 int xc_domain_unbind_pt_irq(
905 int xc_handle,
906 uint32_t domid,
907 uint8_t machine_irq,
908 uint8_t irq_type,
909 uint8_t bus,
910 uint8_t device,
911 uint8_t intx,
912 uint8_t isa_irq)
913 {
914 int rc;
915 xen_domctl_bind_pt_irq_t * bind;
916 DECLARE_DOMCTL;
918 domctl.cmd = XEN_DOMCTL_unbind_pt_irq;
919 domctl.domain = (domid_t)domid;
921 bind = &(domctl.u.bind_pt_irq);
922 bind->hvm_domid = domid;
923 bind->irq_type = irq_type;
924 bind->machine_irq = machine_irq;
925 bind->u.pci.bus = bus;
926 bind->u.pci.device = device;
927 bind->u.pci.intx = intx;
928 bind->u.isa.isa_irq = isa_irq;
930 rc = do_domctl(xc_handle, &domctl);
931 return rc;
932 }
934 int xc_domain_bind_pt_pci_irq(
935 int xc_handle,
936 uint32_t domid,
937 uint8_t machine_irq,
938 uint8_t bus,
939 uint8_t device,
940 uint8_t intx)
941 {
943 return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
944 PT_IRQ_TYPE_PCI, bus, device, intx, 0));
945 }
947 int xc_domain_bind_pt_isa_irq(
948 int xc_handle,
949 uint32_t domid,
950 uint8_t machine_irq)
951 {
953 return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq,
954 PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq));
955 }
957 int xc_domain_memory_mapping(
958 int xc_handle,
959 uint32_t domid,
960 unsigned long first_gfn,
961 unsigned long first_mfn,
962 unsigned long nr_mfns,
963 uint32_t add_mapping)
964 {
965 DECLARE_DOMCTL;
967 domctl.cmd = XEN_DOMCTL_memory_mapping;
968 domctl.domain = domid;
969 domctl.u.memory_mapping.first_gfn = first_gfn;
970 domctl.u.memory_mapping.first_mfn = first_mfn;
971 domctl.u.memory_mapping.nr_mfns = nr_mfns;
972 domctl.u.memory_mapping.add_mapping = add_mapping;
974 return do_domctl(xc_handle, &domctl);
975 }
977 int xc_domain_ioport_mapping(
978 int xc_handle,
979 uint32_t domid,
980 uint32_t first_gport,
981 uint32_t first_mport,
982 uint32_t nr_ports,
983 uint32_t add_mapping)
984 {
985 DECLARE_DOMCTL;
987 domctl.cmd = XEN_DOMCTL_ioport_mapping;
988 domctl.domain = domid;
989 domctl.u.ioport_mapping.first_gport = first_gport;
990 domctl.u.ioport_mapping.first_mport = first_mport;
991 domctl.u.ioport_mapping.nr_ports = nr_ports;
992 domctl.u.ioport_mapping.add_mapping = add_mapping;
994 return do_domctl(xc_handle, &domctl);
995 }
997 int xc_domain_set_target(
998 int xc_handle,
999 uint32_t domid,
1000 uint32_t target)
1002 DECLARE_DOMCTL;
1004 domctl.cmd = XEN_DOMCTL_set_target;
1005 domctl.domain = domid;
1006 domctl.u.set_target.target = target;
1008 return do_domctl(xc_handle, &domctl);
1011 int xc_domain_subscribe_for_suspend(
1012 int xc_handle, domid_t dom, evtchn_port_t port)
1014 DECLARE_DOMCTL;
1016 domctl.cmd = XEN_DOMCTL_subscribe;
1017 domctl.domain = dom;
1018 domctl.u.subscribe.port = port;
1020 return do_domctl(xc_handle, &domctl);
1023 int xc_domain_set_machine_address_size(int xc,
1024 uint32_t domid,
1025 unsigned int width)
1027 DECLARE_DOMCTL;
1029 memset(&domctl, 0, sizeof(domctl));
1030 domctl.domain = domid;
1031 domctl.cmd = XEN_DOMCTL_set_machine_address_size;
1032 domctl.u.address_size.size = width;
1034 return do_domctl(xc, &domctl);
1038 int xc_domain_get_machine_address_size(int xc, uint32_t domid)
1040 DECLARE_DOMCTL;
1041 int rc;
1043 memset(&domctl, 0, sizeof(domctl));
1044 domctl.domain = domid;
1045 domctl.cmd = XEN_DOMCTL_get_machine_address_size;
1047 rc = do_domctl(xc, &domctl);
1049 return rc == 0 ? domctl.u.address_size.size : rc;
1052 /*
1053 * Local variables:
1054 * mode: C
1055 * c-set-style: "BSD"
1056 * c-basic-offset: 4
1057 * tab-width: 4
1058 * indent-tabs-mode: nil
1059 * End:
1060 */