direct-io.hg

view tools/libxc/xc_domain.c @ 13525:9f27746eff43

[LIBXC] Refactor xc_domain_resume() into its own source file.

The idea is that this file is where we will have two implementations
of 'suspend cancellation': one which the guest is aware of (and is
faster) and the other which does more work to avoid requiring guest
modifications.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Jan 19 18:32:28 2007 +0000 (2007-01-19)
parents 0bf0672528cf
children 30af6cfdb05c
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, dirty_bitmap);
328 rc = do_domctl(xc_handle, &domctl);
330 if ( stats )
331 memcpy(stats, &domctl.u.shadow_op.stats,
332 sizeof(xc_shadow_op_stats_t));
334 if ( mb )
335 *mb = domctl.u.shadow_op.mb;
337 return (rc == 0) ? domctl.u.shadow_op.pages : rc;
338 }
340 int xc_domain_setcpuweight(int xc_handle,
341 uint32_t domid,
342 float weight)
343 {
344 int sched_id;
345 int ret;
347 /* Figure out which scheduler is currently used: */
348 if ( (ret = xc_sched_id(xc_handle, &sched_id)) != 0 )
349 return ret;
351 /* No-op. */
352 return 0;
353 }
355 int xc_domain_setmaxmem(int xc_handle,
356 uint32_t domid,
357 unsigned int max_memkb)
358 {
359 DECLARE_DOMCTL;
360 domctl.cmd = XEN_DOMCTL_max_mem;
361 domctl.domain = (domid_t)domid;
362 domctl.u.max_mem.max_memkb = max_memkb;
363 return do_domctl(xc_handle, &domctl);
364 }
366 #if defined(__i386__) || defined(__x86_64__)
367 #include <xen/hvm/e820.h>
368 int xc_domain_set_memmap_limit(int xc_handle,
369 uint32_t domid,
370 unsigned long map_limitkb)
371 {
372 int rc;
374 struct xen_foreign_memory_map fmap = {
375 .domid = domid,
376 .map = { .nr_entries = 1 }
377 };
379 struct e820entry e820 = {
380 .addr = 0,
381 .size = (uint64_t)map_limitkb << 10,
382 .type = E820_RAM
383 };
385 set_xen_guest_handle(fmap.map.buffer, &e820);
387 if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) )
388 {
389 PERROR("Could not lock memory for Xen hypercall");
390 rc = -1;
391 goto out;
392 }
394 rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap);
396 out:
397 unlock_pages(&fmap, sizeof(fmap));
398 unlock_pages(&e820, sizeof(e820));
399 return rc;
400 }
401 #else
402 int xc_domain_set_memmap_limit(int xc_handle,
403 uint32_t domid,
404 unsigned long map_limitkb)
405 {
406 PERROR("Function not implemented");
407 errno = ENOSYS;
408 return -1;
409 }
410 #endif
412 int xc_domain_set_time_offset(int xc_handle,
413 uint32_t domid,
414 int32_t time_offset_seconds)
415 {
416 DECLARE_DOMCTL;
417 domctl.cmd = XEN_DOMCTL_settimeoffset;
418 domctl.domain = (domid_t)domid;
419 domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
420 return do_domctl(xc_handle, &domctl);
421 }
423 int xc_domain_memory_increase_reservation(int xc_handle,
424 uint32_t domid,
425 unsigned long nr_extents,
426 unsigned int extent_order,
427 unsigned int address_bits,
428 xen_pfn_t *extent_start)
429 {
430 int err;
431 struct xen_memory_reservation reservation = {
432 .nr_extents = nr_extents,
433 .extent_order = extent_order,
434 .address_bits = address_bits,
435 .domid = domid
436 };
438 /* may be NULL */
439 set_xen_guest_handle(reservation.extent_start, extent_start);
441 err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
442 if ( err == nr_extents )
443 return 0;
445 if ( err >= 0 )
446 {
447 DPRINTF("Failed allocation for dom %d: "
448 "%ld extents of order %d, addr_bits %d\n",
449 domid, nr_extents, extent_order, address_bits);
450 errno = ENOMEM;
451 err = -1;
452 }
454 return err;
455 }
457 int xc_domain_memory_decrease_reservation(int xc_handle,
458 uint32_t domid,
459 unsigned long nr_extents,
460 unsigned int extent_order,
461 xen_pfn_t *extent_start)
462 {
463 int err;
464 struct xen_memory_reservation reservation = {
465 .nr_extents = nr_extents,
466 .extent_order = extent_order,
467 .address_bits = 0,
468 .domid = domid
469 };
471 set_xen_guest_handle(reservation.extent_start, extent_start);
473 if ( extent_start == NULL )
474 {
475 DPRINTF("decrease_reservation extent_start is NULL!\n");
476 errno = EINVAL;
477 return -1;
478 }
480 err = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation);
481 if ( err == nr_extents )
482 return 0;
484 if ( err >= 0 )
485 {
486 DPRINTF("Failed deallocation for dom %d: %ld extents of order %d\n",
487 domid, nr_extents, extent_order);
488 errno = EINVAL;
489 err = -1;
490 }
492 return err;
493 }
495 int xc_domain_memory_populate_physmap(int xc_handle,
496 uint32_t domid,
497 unsigned long nr_extents,
498 unsigned int extent_order,
499 unsigned int address_bits,
500 xen_pfn_t *extent_start)
501 {
502 int err;
503 struct xen_memory_reservation reservation = {
504 .nr_extents = nr_extents,
505 .extent_order = extent_order,
506 .address_bits = address_bits,
507 .domid = domid
508 };
509 set_xen_guest_handle(reservation.extent_start, extent_start);
511 err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
512 if ( err == nr_extents )
513 return 0;
515 if ( err >= 0 )
516 {
517 DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
518 domid, nr_extents, extent_order);
519 errno = EBUSY;
520 err = -1;
521 }
523 return err;
524 }
526 int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
527 {
528 DECLARE_DOMCTL;
529 domctl.cmd = XEN_DOMCTL_max_vcpus;
530 domctl.domain = (domid_t)domid;
531 domctl.u.max_vcpus.max = max;
532 return do_domctl(xc_handle, &domctl);
533 }
535 int xc_domain_sethandle(int xc_handle, uint32_t domid,
536 xen_domain_handle_t handle)
537 {
538 DECLARE_DOMCTL;
539 domctl.cmd = XEN_DOMCTL_setdomainhandle;
540 domctl.domain = (domid_t)domid;
541 memcpy(domctl.u.setdomainhandle.handle, handle,
542 sizeof(xen_domain_handle_t));
543 return do_domctl(xc_handle, &domctl);
544 }
546 int xc_vcpu_getinfo(int xc_handle,
547 uint32_t domid,
548 uint32_t vcpu,
549 xc_vcpuinfo_t *info)
550 {
551 int rc;
552 DECLARE_DOMCTL;
554 domctl.cmd = XEN_DOMCTL_getvcpuinfo;
555 domctl.domain = (domid_t)domid;
556 domctl.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
558 rc = do_domctl(xc_handle, &domctl);
560 memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
562 return rc;
563 }
565 int xc_domain_ioport_permission(int xc_handle,
566 uint32_t domid,
567 uint32_t first_port,
568 uint32_t nr_ports,
569 uint32_t allow_access)
570 {
571 DECLARE_DOMCTL;
573 domctl.cmd = XEN_DOMCTL_ioport_permission;
574 domctl.domain = (domid_t)domid;
575 domctl.u.ioport_permission.first_port = first_port;
576 domctl.u.ioport_permission.nr_ports = nr_ports;
577 domctl.u.ioport_permission.allow_access = allow_access;
579 return do_domctl(xc_handle, &domctl);
580 }
582 int xc_vcpu_setcontext(int xc_handle,
583 uint32_t domid,
584 uint32_t vcpu,
585 vcpu_guest_context_t *ctxt)
586 {
587 DECLARE_DOMCTL;
588 int rc;
590 domctl.cmd = XEN_DOMCTL_setvcpucontext;
591 domctl.domain = domid;
592 domctl.u.vcpucontext.vcpu = vcpu;
593 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
595 if ( (ctxt != NULL) && ((rc = lock_pages(ctxt, sizeof(*ctxt))) != 0) )
596 return rc;
598 rc = do_domctl(xc_handle, &domctl);
600 if ( ctxt != NULL )
601 unlock_pages(ctxt, sizeof(*ctxt));
603 return rc;
604 }
606 int xc_domain_irq_permission(int xc_handle,
607 uint32_t domid,
608 uint8_t pirq,
609 uint8_t allow_access)
610 {
611 DECLARE_DOMCTL;
613 domctl.cmd = XEN_DOMCTL_irq_permission;
614 domctl.domain = domid;
615 domctl.u.irq_permission.pirq = pirq;
616 domctl.u.irq_permission.allow_access = allow_access;
618 return do_domctl(xc_handle, &domctl);
619 }
621 int xc_domain_iomem_permission(int xc_handle,
622 uint32_t domid,
623 unsigned long first_mfn,
624 unsigned long nr_mfns,
625 uint8_t allow_access)
626 {
627 DECLARE_DOMCTL;
629 domctl.cmd = XEN_DOMCTL_iomem_permission;
630 domctl.domain = domid;
631 domctl.u.iomem_permission.first_mfn = first_mfn;
632 domctl.u.iomem_permission.nr_mfns = nr_mfns;
633 domctl.u.iomem_permission.allow_access = allow_access;
635 return do_domctl(xc_handle, &domctl);
636 }
638 /*
639 * Local variables:
640 * mode: C
641 * c-set-style: "BSD"
642 * c-basic-offset: 4
643 * tab-width: 4
644 * indent-tabs-mode: nil
645 * End:
646 */