direct-io.hg

view tools/libxc/xc_domain.c @ 12803:df5fa63490f4

[XEN] Implement XENMEM_set_memory_map, which specifies memory map to
be returned by XENMEM_memory_map. Hook this into the domain builder.

Based on a patch by Glauber de Oliveira Costa <gcosta@redhat.com>

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Dec 08 11:30:30 2006 +0000 (2006-12-08)
parents 2ae4e4e89d6d
children 44668189f354
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;
100 domctl.cmd = XEN_DOMCTL_setvcpuaffinity;
101 domctl.domain = (domid_t)domid;
102 domctl.u.vcpuaffinity.vcpu = vcpu;
104 set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap,
105 (uint8_t *)&cpumap);
106 domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
108 if ( lock_pages(&cpumap, sizeof(cpumap)) != 0 )
109 {
110 PERROR("Could not lock memory for Xen hypercall");
111 goto out;
112 }
114 ret = do_domctl(xc_handle, &domctl);
116 unlock_pages(&cpumap, sizeof(cpumap));
118 out:
119 return ret;
120 }
123 int xc_vcpu_getaffinity(int xc_handle,
124 uint32_t domid,
125 int vcpu,
126 uint64_t *cpumap)
127 {
128 DECLARE_DOMCTL;
129 int ret = -1;
131 domctl.cmd = XEN_DOMCTL_getvcpuaffinity;
132 domctl.domain = (domid_t)domid;
133 domctl.u.vcpuaffinity.vcpu = vcpu;
135 set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap,
136 (uint8_t *)cpumap);
137 domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(*cpumap) * 8;
139 if ( lock_pages(cpumap, sizeof(*cpumap)) != 0 )
140 {
141 PERROR("Could not lock memory for Xen hypercall");
142 goto out;
143 }
145 ret = do_domctl(xc_handle, &domctl);
147 unlock_pages(cpumap, sizeof(*cpumap));
149 out:
150 return ret;
151 }
154 int xc_domain_getinfo(int xc_handle,
155 uint32_t first_domid,
156 unsigned int max_doms,
157 xc_dominfo_t *info)
158 {
159 unsigned int nr_doms;
160 uint32_t next_domid = first_domid;
161 DECLARE_DOMCTL;
162 int rc = 0;
164 memset(info, 0, max_doms*sizeof(xc_dominfo_t));
166 for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
167 {
168 domctl.cmd = XEN_DOMCTL_getdomaininfo;
169 domctl.domain = (domid_t)next_domid;
170 if ( (rc = do_domctl(xc_handle, &domctl)) < 0 )
171 break;
172 info->domid = (uint16_t)domctl.domain;
174 info->dying = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_dying);
175 info->shutdown = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_shutdown);
176 info->paused = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_paused);
177 info->blocked = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
178 info->running = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
179 info->hvm = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
181 info->shutdown_reason =
182 (domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
183 XEN_DOMINF_shutdownmask;
185 if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
186 {
187 info->shutdown = 0;
188 info->crashed = 1;
189 }
191 info->ssidref = domctl.u.getdomaininfo.ssidref;
192 info->nr_pages = domctl.u.getdomaininfo.tot_pages;
193 info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10);
194 info->shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
195 info->cpu_time = domctl.u.getdomaininfo.cpu_time;
196 info->nr_online_vcpus = domctl.u.getdomaininfo.nr_online_vcpus;
197 info->max_vcpu_id = domctl.u.getdomaininfo.max_vcpu_id;
199 memcpy(info->handle, domctl.u.getdomaininfo.handle,
200 sizeof(xen_domain_handle_t));
202 next_domid = (uint16_t)domctl.domain + 1;
203 info++;
204 }
206 if ( nr_doms == 0 )
207 return rc;
209 return nr_doms;
210 }
212 int xc_domain_getinfolist(int xc_handle,
213 uint32_t first_domain,
214 unsigned int max_domains,
215 xc_domaininfo_t *info)
216 {
217 int ret = 0;
218 DECLARE_SYSCTL;
220 if ( lock_pages(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
221 return -1;
223 sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
224 sysctl.u.getdomaininfolist.first_domain = first_domain;
225 sysctl.u.getdomaininfolist.max_domains = max_domains;
226 set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);
228 if ( xc_sysctl(xc_handle, &sysctl) < 0 )
229 ret = -1;
230 else
231 ret = sysctl.u.getdomaininfolist.num_domains;
233 unlock_pages(info, max_domains*sizeof(xc_domaininfo_t));
235 return ret;
236 }
238 int xc_vcpu_getcontext(int xc_handle,
239 uint32_t domid,
240 uint32_t vcpu,
241 vcpu_guest_context_t *ctxt)
242 {
243 int rc;
244 DECLARE_DOMCTL;
246 domctl.cmd = XEN_DOMCTL_getvcpucontext;
247 domctl.domain = (domid_t)domid;
248 domctl.u.vcpucontext.vcpu = (uint16_t)vcpu;
249 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
251 if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 )
252 return rc;
254 rc = do_domctl(xc_handle, &domctl);
256 unlock_pages(ctxt, sizeof(*ctxt));
258 return rc;
259 }
262 int xc_shadow_control(int xc_handle,
263 uint32_t domid,
264 unsigned int sop,
265 unsigned long *dirty_bitmap,
266 unsigned long pages,
267 unsigned long *mb,
268 uint32_t mode,
269 xc_shadow_op_stats_t *stats)
270 {
271 int rc;
272 DECLARE_DOMCTL;
273 domctl.cmd = XEN_DOMCTL_shadow_op;
274 domctl.domain = (domid_t)domid;
275 domctl.u.shadow_op.op = sop;
276 domctl.u.shadow_op.pages = pages;
277 domctl.u.shadow_op.mb = mb ? *mb : 0;
278 domctl.u.shadow_op.mode = mode;
279 set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap, dirty_bitmap);
281 rc = do_domctl(xc_handle, &domctl);
283 if ( stats )
284 memcpy(stats, &domctl.u.shadow_op.stats,
285 sizeof(xc_shadow_op_stats_t));
287 if ( mb )
288 *mb = domctl.u.shadow_op.mb;
290 return (rc == 0) ? domctl.u.shadow_op.pages : rc;
291 }
293 int xc_domain_setcpuweight(int xc_handle,
294 uint32_t domid,
295 float weight)
296 {
297 int sched_id;
298 int ret;
300 /* Figure out which scheduler is currently used: */
301 if ( (ret = xc_sched_id(xc_handle, &sched_id)) != 0 )
302 return ret;
304 /* No-op. */
305 return 0;
306 }
308 int xc_domain_setmaxmem(int xc_handle,
309 uint32_t domid,
310 unsigned int max_memkb)
311 {
312 DECLARE_DOMCTL;
313 domctl.cmd = XEN_DOMCTL_max_mem;
314 domctl.domain = (domid_t)domid;
315 domctl.u.max_mem.max_memkb = max_memkb;
316 return do_domctl(xc_handle, &domctl);
317 }
319 #if defined(__i386__) || defined(__x86_64__)
320 #include <xen/hvm/e820.h>
321 int xc_domain_set_memmap_limit(int xc_handle,
322 uint32_t domid,
323 unsigned long map_limitkb)
324 {
325 int rc;
327 struct xen_foreign_memory_map fmap = {
328 .domid = domid,
329 .map = { .nr_entries = 1 }
330 };
332 struct e820entry e820 = {
333 .addr = 0,
334 .size = (uint64_t)map_limitkb << 10,
335 .type = E820_RAM
336 };
338 set_xen_guest_handle(fmap.map.buffer, &e820);
340 if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) )
341 {
342 PERROR("Could not lock memory for Xen hypercall");
343 rc = -1;
344 goto out;
345 }
347 rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap);
349 out:
350 unlock_pages(&fmap, sizeof(fmap));
351 unlock_pages(&e820, sizeof(e820));
352 return rc;
353 }
354 #else
355 int xc_domain_set_memmap_limit(int xc_handle,
356 uint32_t domid,
357 unsigned long map_limitkb)
358 {
359 PERROR("Function not implemented");
360 errno = ENOSYS;
361 return -1;
362 }
363 #endif
365 int xc_domain_set_time_offset(int xc_handle,
366 uint32_t domid,
367 int32_t time_offset_seconds)
368 {
369 DECLARE_DOMCTL;
370 domctl.cmd = XEN_DOMCTL_settimeoffset;
371 domctl.domain = (domid_t)domid;
372 domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
373 return do_domctl(xc_handle, &domctl);
374 }
376 int xc_domain_memory_increase_reservation(int xc_handle,
377 uint32_t domid,
378 unsigned long nr_extents,
379 unsigned int extent_order,
380 unsigned int address_bits,
381 xen_pfn_t *extent_start)
382 {
383 int err;
384 struct xen_memory_reservation reservation = {
385 .nr_extents = nr_extents,
386 .extent_order = extent_order,
387 .address_bits = address_bits,
388 .domid = domid
389 };
391 /* may be NULL */
392 set_xen_guest_handle(reservation.extent_start, extent_start);
394 err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
395 if ( err == nr_extents )
396 return 0;
398 if ( err >= 0 )
399 {
400 DPRINTF("Failed allocation for dom %d: "
401 "%ld extents of order %d, addr_bits %d\n",
402 domid, nr_extents, extent_order, address_bits);
403 errno = ENOMEM;
404 err = -1;
405 }
407 return err;
408 }
410 int xc_domain_memory_decrease_reservation(int xc_handle,
411 uint32_t domid,
412 unsigned long nr_extents,
413 unsigned int extent_order,
414 xen_pfn_t *extent_start)
415 {
416 int err;
417 struct xen_memory_reservation reservation = {
418 .nr_extents = nr_extents,
419 .extent_order = extent_order,
420 .address_bits = 0,
421 .domid = domid
422 };
424 set_xen_guest_handle(reservation.extent_start, extent_start);
426 if ( extent_start == NULL )
427 {
428 DPRINTF("decrease_reservation extent_start is NULL!\n");
429 errno = EINVAL;
430 return -1;
431 }
433 err = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation);
434 if ( err == nr_extents )
435 return 0;
437 if ( err >= 0 )
438 {
439 DPRINTF("Failed deallocation for dom %d: %ld extents of order %d\n",
440 domid, nr_extents, extent_order);
441 errno = EINVAL;
442 err = -1;
443 }
445 return err;
446 }
448 int xc_domain_memory_populate_physmap(int xc_handle,
449 uint32_t domid,
450 unsigned long nr_extents,
451 unsigned int extent_order,
452 unsigned int address_bits,
453 xen_pfn_t *extent_start)
454 {
455 int err;
456 struct xen_memory_reservation reservation = {
457 .nr_extents = nr_extents,
458 .extent_order = extent_order,
459 .address_bits = address_bits,
460 .domid = domid
461 };
462 set_xen_guest_handle(reservation.extent_start, extent_start);
464 err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
465 if ( err == nr_extents )
466 return 0;
468 if ( err >= 0 )
469 {
470 DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
471 domid, nr_extents, extent_order);
472 errno = EBUSY;
473 err = -1;
474 }
476 return err;
477 }
479 int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
480 {
481 DECLARE_DOMCTL;
482 domctl.cmd = XEN_DOMCTL_max_vcpus;
483 domctl.domain = (domid_t)domid;
484 domctl.u.max_vcpus.max = max;
485 return do_domctl(xc_handle, &domctl);
486 }
488 int xc_domain_sethandle(int xc_handle, uint32_t domid,
489 xen_domain_handle_t handle)
490 {
491 DECLARE_DOMCTL;
492 domctl.cmd = XEN_DOMCTL_setdomainhandle;
493 domctl.domain = (domid_t)domid;
494 memcpy(domctl.u.setdomainhandle.handle, handle,
495 sizeof(xen_domain_handle_t));
496 return do_domctl(xc_handle, &domctl);
497 }
499 int xc_vcpu_getinfo(int xc_handle,
500 uint32_t domid,
501 uint32_t vcpu,
502 xc_vcpuinfo_t *info)
503 {
504 int rc;
505 DECLARE_DOMCTL;
507 domctl.cmd = XEN_DOMCTL_getvcpuinfo;
508 domctl.domain = (domid_t)domid;
509 domctl.u.getvcpuinfo.vcpu = (uint16_t)vcpu;
511 rc = do_domctl(xc_handle, &domctl);
513 memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
515 return rc;
516 }
518 int xc_domain_ioport_permission(int xc_handle,
519 uint32_t domid,
520 uint32_t first_port,
521 uint32_t nr_ports,
522 uint32_t allow_access)
523 {
524 DECLARE_DOMCTL;
526 domctl.cmd = XEN_DOMCTL_ioport_permission;
527 domctl.domain = (domid_t)domid;
528 domctl.u.ioport_permission.first_port = first_port;
529 domctl.u.ioport_permission.nr_ports = nr_ports;
530 domctl.u.ioport_permission.allow_access = allow_access;
532 return do_domctl(xc_handle, &domctl);
533 }
535 int xc_vcpu_setcontext(int xc_handle,
536 uint32_t domid,
537 uint32_t vcpu,
538 vcpu_guest_context_t *ctxt)
539 {
540 DECLARE_DOMCTL;
541 int rc;
543 domctl.cmd = XEN_DOMCTL_setvcpucontext;
544 domctl.domain = domid;
545 domctl.u.vcpucontext.vcpu = vcpu;
546 set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
548 if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 )
549 return rc;
551 rc = do_domctl(xc_handle, &domctl);
553 unlock_pages(ctxt, sizeof(*ctxt));
555 return rc;
557 }
559 int xc_domain_irq_permission(int xc_handle,
560 uint32_t domid,
561 uint8_t pirq,
562 uint8_t allow_access)
563 {
564 DECLARE_DOMCTL;
566 domctl.cmd = XEN_DOMCTL_irq_permission;
567 domctl.domain = domid;
568 domctl.u.irq_permission.pirq = pirq;
569 domctl.u.irq_permission.allow_access = allow_access;
571 return do_domctl(xc_handle, &domctl);
572 }
574 int xc_domain_iomem_permission(int xc_handle,
575 uint32_t domid,
576 unsigned long first_mfn,
577 unsigned long nr_mfns,
578 uint8_t allow_access)
579 {
580 DECLARE_DOMCTL;
582 domctl.cmd = XEN_DOMCTL_iomem_permission;
583 domctl.domain = domid;
584 domctl.u.iomem_permission.first_mfn = first_mfn;
585 domctl.u.iomem_permission.nr_mfns = nr_mfns;
586 domctl.u.iomem_permission.allow_access = allow_access;
588 return do_domctl(xc_handle, &domctl);
589 }
591 /*
592 * Local variables:
593 * mode: C
594 * c-set-style: "BSD"
595 * c-basic-offset: 4
596 * tab-width: 4
597 * indent-tabs-mode: nil
598 * End:
599 */