source: trunk/packages/xen-3.1/xen-3.1/tools/libxc/xc_domain.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 19.0 KB
RevLine 
[34]1/******************************************************************************
2 * xc_domain.c
3 *
4 * API for manipulating and obtaining information on domains.
5 *
6 * Copyright (c) 2003, K A Fraser.
7 */
8
9#include "xc_private.h"
10#include <xen/memory.h>
11#include <xen/hvm/hvm_op.h>
12
13int xc_domain_create(int xc_handle,
14                     uint32_t ssidref,
15                     xen_domain_handle_t handle,
16                     uint32_t flags,
17                     uint32_t *pdomid)
18{
19    int err;
20    DECLARE_DOMCTL;
21
22    domctl.cmd = XEN_DOMCTL_createdomain;
23    domctl.domain = (domid_t)*pdomid;
24    domctl.u.createdomain.ssidref = ssidref;
25    domctl.u.createdomain.flags   = flags;
26    memcpy(domctl.u.createdomain.handle, handle, sizeof(xen_domain_handle_t));
27    if ( (err = do_domctl(xc_handle, &domctl)) != 0 )
28        return err;
29
30    *pdomid = (uint16_t)domctl.domain;
31    return 0;
32}
33
34
35int xc_domain_pause(int xc_handle,
36                    uint32_t domid)
37{
38    DECLARE_DOMCTL;
39    domctl.cmd = XEN_DOMCTL_pausedomain;
40    domctl.domain = (domid_t)domid;
41    return do_domctl(xc_handle, &domctl);
42}
43
44
45int xc_domain_unpause(int xc_handle,
46                      uint32_t domid)
47{
48    DECLARE_DOMCTL;
49    domctl.cmd = XEN_DOMCTL_unpausedomain;
50    domctl.domain = (domid_t)domid;
51    return do_domctl(xc_handle, &domctl);
52}
53
54
55int xc_domain_destroy(int xc_handle,
56                      uint32_t domid)
57{
58    DECLARE_DOMCTL;
59    domctl.cmd = XEN_DOMCTL_destroydomain;
60    domctl.domain = (domid_t)domid;
61    return do_domctl(xc_handle, &domctl);
62}
63
64int xc_domain_shutdown(int xc_handle,
65                       uint32_t domid,
66                       int reason)
67{
68    int ret = -1;
69    sched_remote_shutdown_t arg;
70    DECLARE_HYPERCALL;
71
72    hypercall.op     = __HYPERVISOR_sched_op;
73    hypercall.arg[0] = (unsigned long)SCHEDOP_remote_shutdown;
74    hypercall.arg[1] = (unsigned long)&arg;
75    arg.domain_id = domid;
76    arg.reason = reason;
77
78    if ( lock_pages(&arg, sizeof(arg)) != 0 )
79    {
80        PERROR("Could not lock memory for Xen hypercall");
81        goto out1;
82    }
83
84    ret = do_xen_hypercall(xc_handle, &hypercall);
85
86    unlock_pages(&arg, sizeof(arg));
87
88 out1:
89    return ret;
90}
91
92
93int xc_vcpu_setaffinity(int xc_handle,
94                        uint32_t domid,
95                        int vcpu,
96                        uint64_t cpumap)
97{
98    DECLARE_DOMCTL;
99    int ret = -1;
100    uint8_t local[sizeof (cpumap)];
101
102    domctl.cmd = XEN_DOMCTL_setvcpuaffinity;
103    domctl.domain = (domid_t)domid;
104    domctl.u.vcpuaffinity.vcpu    = vcpu;
105
106    bitmap_64_to_byte(local, &cpumap, sizeof(cpumap) * 8);
107
108    set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
109
110    domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
111   
112    if ( lock_pages(local, sizeof(local)) != 0 )
113    {
114        PERROR("Could not lock memory for Xen hypercall");
115        goto out;
116    }
117
118    ret = do_domctl(xc_handle, &domctl);
119
120    unlock_pages(local, sizeof(local));
121
122 out:
123    return ret;
124}
125
126
127int xc_vcpu_getaffinity(int xc_handle,
128                        uint32_t domid,
129                        int vcpu,
130                        uint64_t *cpumap)
131{
132    DECLARE_DOMCTL;
133    int ret = -1;
134    uint8_t local[sizeof (cpumap)];
135
136    domctl.cmd = XEN_DOMCTL_getvcpuaffinity;
137    domctl.domain = (domid_t)domid;
138    domctl.u.vcpuaffinity.vcpu = vcpu;
139
140    set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap.bitmap, local);
141    domctl.u.vcpuaffinity.cpumap.nr_cpus = sizeof(cpumap) * 8;
142   
143    if ( lock_pages(local, sizeof(local)) != 0 )
144    {
145        PERROR("Could not lock memory for Xen hypercall");
146        goto out;
147    }
148
149    ret = do_domctl(xc_handle, &domctl);
150
151    unlock_pages(local, sizeof (local));
152    bitmap_byte_to_64(cpumap, local, sizeof(local) * 8);
153 out:
154    return ret;
155}
156
157
158int xc_domain_getinfo(int xc_handle,
159                      uint32_t first_domid,
160                      unsigned int max_doms,
161                      xc_dominfo_t *info)
162{
163    unsigned int nr_doms;
164    uint32_t next_domid = first_domid;
165    DECLARE_DOMCTL;
166    int rc = 0;
167
168    memset(info, 0, max_doms*sizeof(xc_dominfo_t));
169
170    for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
171    {
172        domctl.cmd = XEN_DOMCTL_getdomaininfo;
173        domctl.domain = (domid_t)next_domid;
174        if ( (rc = do_domctl(xc_handle, &domctl)) < 0 )
175            break;
176        info->domid      = (uint16_t)domctl.domain;
177
178        info->dying    = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_dying);
179        info->shutdown = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_shutdown);
180        info->paused   = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_paused);
181        info->blocked  = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
182        info->running  = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
183        info->hvm      = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
184
185        info->shutdown_reason =
186            (domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
187            XEN_DOMINF_shutdownmask;
188
189        if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
190        {
191            info->shutdown = 0;
192            info->crashed  = 1;
193        }
194
195        info->ssidref  = domctl.u.getdomaininfo.ssidref;
196        info->nr_pages = domctl.u.getdomaininfo.tot_pages;
197        info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10);
198        info->shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
199        info->cpu_time = domctl.u.getdomaininfo.cpu_time;
200        info->nr_online_vcpus = domctl.u.getdomaininfo.nr_online_vcpus;
201        info->max_vcpu_id = domctl.u.getdomaininfo.max_vcpu_id;
202
203        memcpy(info->handle, domctl.u.getdomaininfo.handle,
204               sizeof(xen_domain_handle_t));
205
206        next_domid = (uint16_t)domctl.domain + 1;
207        info++;
208    }
209
210    if ( nr_doms == 0 )
211        return rc;
212
213    return nr_doms;
214}
215
216int xc_domain_getinfolist(int xc_handle,
217                          uint32_t first_domain,
218                          unsigned int max_domains,
219                          xc_domaininfo_t *info)
220{
221    int ret = 0;
222    DECLARE_SYSCTL;
223
224    if ( lock_pages(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
225        return -1;
226
227    sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
228    sysctl.u.getdomaininfolist.first_domain = first_domain;
229    sysctl.u.getdomaininfolist.max_domains  = max_domains;
230    set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);
231
232    if ( xc_sysctl(xc_handle, &sysctl) < 0 )
233        ret = -1;
234    else
235        ret = sysctl.u.getdomaininfolist.num_domains;
236
237    unlock_pages(info, max_domains*sizeof(xc_domaininfo_t));
238
239    return ret;
240}
241
242/* get info from hvm guest for save */
243int xc_domain_hvm_getcontext(int xc_handle,
244                             uint32_t domid,
245                             uint8_t *ctxt_buf,
246                             uint32_t size)
247{
248    int ret;
249    DECLARE_DOMCTL;
250
251    domctl.cmd = XEN_DOMCTL_gethvmcontext;
252    domctl.domain = (domid_t)domid;
253    domctl.u.hvmcontext.size = size;
254    set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
255
256    if ( ctxt_buf ) 
257        if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
258            return ret;
259
260    ret = do_domctl(xc_handle, &domctl);
261
262    if ( ctxt_buf ) 
263        unlock_pages(ctxt_buf, size);
264
265    return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
266}
267
268/* set info to hvm guest for restore */
269int xc_domain_hvm_setcontext(int xc_handle,
270                             uint32_t domid,
271                             uint8_t *ctxt_buf,
272                             uint32_t size)
273{
274    int ret;
275    DECLARE_DOMCTL;
276
277    domctl.cmd = XEN_DOMCTL_sethvmcontext;
278    domctl.domain = domid;
279    domctl.u.hvmcontext.size = size;
280    set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
281
282    if ( (ret = lock_pages(ctxt_buf, size)) != 0 )
283        return ret;
284
285    ret = do_domctl(xc_handle, &domctl);
286
287    unlock_pages(ctxt_buf, size);
288
289    return ret;
290}
291
292int xc_vcpu_getcontext(int xc_handle,
293                       uint32_t domid,
294                       uint32_t vcpu,
295                       vcpu_guest_context_t *ctxt)
296{
297    int rc;
298    DECLARE_DOMCTL;
299
300    domctl.cmd = XEN_DOMCTL_getvcpucontext;
301    domctl.domain = (domid_t)domid;
302    domctl.u.vcpucontext.vcpu   = (uint16_t)vcpu;
303    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
304
305    if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 )
306        return rc;
307
308    rc = do_domctl(xc_handle, &domctl);
309
310    unlock_pages(ctxt, sizeof(*ctxt));
311
312    return rc;
313}
314
315
316int xc_shadow_control(int xc_handle,
317                      uint32_t domid,
318                      unsigned int sop,
319                      unsigned long *dirty_bitmap,
320                      unsigned long pages,
321                      unsigned long *mb,
322                      uint32_t mode,
323                      xc_shadow_op_stats_t *stats)
324{
325    int rc;
326    DECLARE_DOMCTL;
327    domctl.cmd = XEN_DOMCTL_shadow_op;
328    domctl.domain = (domid_t)domid;
329    domctl.u.shadow_op.op     = sop;
330    domctl.u.shadow_op.pages  = pages;
331    domctl.u.shadow_op.mb     = mb ? *mb : 0;
332    domctl.u.shadow_op.mode   = mode;
333    set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap,
334                         (uint8_t *)dirty_bitmap);
335
336    rc = do_domctl(xc_handle, &domctl);
337
338    if ( stats )
339        memcpy(stats, &domctl.u.shadow_op.stats,
340               sizeof(xc_shadow_op_stats_t));
341   
342    if ( mb ) 
343        *mb = domctl.u.shadow_op.mb;
344
345    return (rc == 0) ? domctl.u.shadow_op.pages : rc;
346}
347
348int xc_domain_setcpuweight(int xc_handle,
349                           uint32_t domid,
350                           float weight)
351{
352    int sched_id;
353    int ret;
354
355    /* Figure out which scheduler is currently used: */
356    if ( (ret = xc_sched_id(xc_handle, &sched_id)) != 0 )
357        return ret;
358
359    /* No-op. */
360    return 0;
361}
362
363int xc_domain_setmaxmem(int xc_handle,
364                        uint32_t domid,
365                        unsigned int max_memkb)
366{
367    DECLARE_DOMCTL;
368    domctl.cmd = XEN_DOMCTL_max_mem;
369    domctl.domain = (domid_t)domid;
370    domctl.u.max_mem.max_memkb = max_memkb;
371    return do_domctl(xc_handle, &domctl);
372}
373
374#if defined(__i386__) || defined(__x86_64__)
375#include <xen/hvm/e820.h>
376int xc_domain_set_memmap_limit(int xc_handle,
377                               uint32_t domid,
378                               unsigned long map_limitkb)
379{
380    int rc;
381
382    struct xen_foreign_memory_map fmap = {
383        .domid = domid,
384        .map = { .nr_entries = 1 }
385    };
386
387    struct e820entry e820 = {
388        .addr = 0,
389        .size = (uint64_t)map_limitkb << 10,
390        .type = E820_RAM
391    };
392
393    set_xen_guest_handle(fmap.map.buffer, &e820);
394
395    if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) )
396    {
397        PERROR("Could not lock memory for Xen hypercall");
398        rc = -1;
399        goto out;
400    }
401
402    rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap);
403
404 out:
405    unlock_pages(&fmap, sizeof(fmap));
406    unlock_pages(&e820, sizeof(e820));
407    return rc;
408}
409#else
410int xc_domain_set_memmap_limit(int xc_handle,
411                               uint32_t domid,
412                               unsigned long map_limitkb)
413{
414    PERROR("Function not implemented");
415    errno = ENOSYS;
416    return -1;
417}
418#endif
419
420int xc_domain_set_time_offset(int xc_handle,
421                              uint32_t domid,
422                              int32_t time_offset_seconds)
423{
424    DECLARE_DOMCTL;
425    domctl.cmd = XEN_DOMCTL_settimeoffset;
426    domctl.domain = (domid_t)domid;
427    domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
428    return do_domctl(xc_handle, &domctl);
429}
430
431int xc_domain_memory_increase_reservation(int xc_handle,
432                                          uint32_t domid,
433                                          unsigned long nr_extents,
434                                          unsigned int extent_order,
435                                          unsigned int address_bits,
436                                          xen_pfn_t *extent_start)
437{
438    int err;
439    struct xen_memory_reservation reservation = {
440        .nr_extents   = nr_extents,
441        .extent_order = extent_order,
442        .address_bits = address_bits,
443        .domid        = domid
444    };
445
446    /* may be NULL */
447    set_xen_guest_handle(reservation.extent_start, extent_start);
448
449    err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
450    if ( err == nr_extents )
451        return 0;
452
453    if ( err >= 0 )
454    {
455        DPRINTF("Failed allocation for dom %d: "
456                "%ld extents of order %d, addr_bits %d\n",
457                domid, nr_extents, extent_order, address_bits);
458        errno = ENOMEM;
459        err = -1;
460    }
461
462    return err;
463}
464
465int xc_domain_memory_decrease_reservation(int xc_handle,
466                                          uint32_t domid,
467                                          unsigned long nr_extents,
468                                          unsigned int extent_order,
469                                          xen_pfn_t *extent_start)
470{
471    int err;
472    struct xen_memory_reservation reservation = {
473        .nr_extents   = nr_extents,
474        .extent_order = extent_order,
475        .address_bits = 0,
476        .domid        = domid
477    };
478
479    set_xen_guest_handle(reservation.extent_start, extent_start);
480
481    if ( extent_start == NULL )
482    {
483        DPRINTF("decrease_reservation extent_start is NULL!\n");
484        errno = EINVAL;
485        return -1;
486    }
487
488    err = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation);
489    if ( err == nr_extents )
490        return 0;
491
492    if ( err >= 0 )
493    {
494        DPRINTF("Failed deallocation for dom %d: %ld extents of order %d\n",
495                domid, nr_extents, extent_order);
496        errno = EINVAL;
497        err = -1;
498    }
499
500    return err;
501}
502
503int xc_domain_memory_populate_physmap(int xc_handle,
504                                          uint32_t domid,
505                                          unsigned long nr_extents,
506                                          unsigned int extent_order,
507                                          unsigned int address_bits,
508                                          xen_pfn_t *extent_start)
509{
510    int err;
511    struct xen_memory_reservation reservation = {
512        .nr_extents   = nr_extents,
513        .extent_order = extent_order,
514        .address_bits = address_bits,
515        .domid        = domid
516    };
517    set_xen_guest_handle(reservation.extent_start, extent_start);
518
519    err = xc_memory_op(xc_handle, XENMEM_populate_physmap, &reservation);
520    if ( err == nr_extents )
521        return 0;
522
523    if ( err >= 0 )
524    {
525        DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
526                domid, nr_extents, extent_order);
527        errno = EBUSY;
528        err = -1;
529    }
530
531    return err;
532}
533
534int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
535{
536    DECLARE_DOMCTL;
537    domctl.cmd = XEN_DOMCTL_max_vcpus;
538    domctl.domain = (domid_t)domid;
539    domctl.u.max_vcpus.max    = max;
540    return do_domctl(xc_handle, &domctl);
541}
542
543int xc_domain_sethandle(int xc_handle, uint32_t domid,
544                        xen_domain_handle_t handle)
545{
546    DECLARE_DOMCTL;
547    domctl.cmd = XEN_DOMCTL_setdomainhandle;
548    domctl.domain = (domid_t)domid;
549    memcpy(domctl.u.setdomainhandle.handle, handle,
550           sizeof(xen_domain_handle_t));
551    return do_domctl(xc_handle, &domctl);
552}
553
554int xc_vcpu_getinfo(int xc_handle,
555                    uint32_t domid,
556                    uint32_t vcpu,
557                    xc_vcpuinfo_t *info)
558{
559    int rc;
560    DECLARE_DOMCTL;
561
562    domctl.cmd = XEN_DOMCTL_getvcpuinfo;
563    domctl.domain = (domid_t)domid;
564    domctl.u.getvcpuinfo.vcpu   = (uint16_t)vcpu;
565
566    rc = do_domctl(xc_handle, &domctl);
567
568    memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
569
570    return rc;
571}
572
573int xc_domain_ioport_permission(int xc_handle,
574                                uint32_t domid,
575                                uint32_t first_port,
576                                uint32_t nr_ports,
577                                uint32_t allow_access)
578{
579    DECLARE_DOMCTL;
580
581    domctl.cmd = XEN_DOMCTL_ioport_permission;
582    domctl.domain = (domid_t)domid;
583    domctl.u.ioport_permission.first_port = first_port;
584    domctl.u.ioport_permission.nr_ports = nr_ports;
585    domctl.u.ioport_permission.allow_access = allow_access;
586
587    return do_domctl(xc_handle, &domctl);
588}
589
590int xc_vcpu_setcontext(int xc_handle,
591                       uint32_t domid,
592                       uint32_t vcpu,
593                       vcpu_guest_context_t *ctxt)
594{
595    DECLARE_DOMCTL;
596    int rc;
597
598    domctl.cmd = XEN_DOMCTL_setvcpucontext;
599    domctl.domain = domid;
600    domctl.u.vcpucontext.vcpu = vcpu;
601    set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
602
603    if ( (ctxt != NULL) && ((rc = lock_pages(ctxt, sizeof(*ctxt))) != 0) )
604        return rc;
605
606    rc = do_domctl(xc_handle, &domctl);
607
608    if ( ctxt != NULL )
609        unlock_pages(ctxt, sizeof(*ctxt));
610
611    return rc;
612}
613
614int xc_domain_irq_permission(int xc_handle,
615                             uint32_t domid,
616                             uint8_t pirq,
617                             uint8_t allow_access)
618{
619    DECLARE_DOMCTL;
620
621    domctl.cmd = XEN_DOMCTL_irq_permission;
622    domctl.domain = domid;
623    domctl.u.irq_permission.pirq = pirq;
624    domctl.u.irq_permission.allow_access = allow_access;
625
626    return do_domctl(xc_handle, &domctl);
627}
628
629int xc_domain_iomem_permission(int xc_handle,
630                               uint32_t domid,
631                               unsigned long first_mfn,
632                               unsigned long nr_mfns,
633                               uint8_t allow_access)
634{
635    DECLARE_DOMCTL;
636
637    domctl.cmd = XEN_DOMCTL_iomem_permission;
638    domctl.domain = domid;
639    domctl.u.iomem_permission.first_mfn = first_mfn;
640    domctl.u.iomem_permission.nr_mfns = nr_mfns;
641    domctl.u.iomem_permission.allow_access = allow_access;
642
643    return do_domctl(xc_handle, &domctl);
644}
645
646int xc_domain_send_trigger(int xc_handle,
647                           uint32_t domid,
648                           uint32_t trigger,
649                           uint32_t vcpu)
650{
651    DECLARE_DOMCTL;
652
653    domctl.cmd = XEN_DOMCTL_sendtrigger;
654    domctl.domain = domid;
655    domctl.u.sendtrigger.trigger = trigger;
656    domctl.u.sendtrigger.vcpu = vcpu;
657
658    return do_domctl(xc_handle, &domctl);
659}
660
661int xc_set_hvm_param(int handle, domid_t dom, int param, unsigned long value)
662{
663    DECLARE_HYPERCALL;
664    xen_hvm_param_t arg;
665    int rc;
666
667    hypercall.op     = __HYPERVISOR_hvm_op;
668    hypercall.arg[0] = HVMOP_set_param;
669    hypercall.arg[1] = (unsigned long)&arg;
670    arg.domid = dom;
671    arg.index = param;
672    arg.value = value;
673    if ( lock_pages(&arg, sizeof(arg)) != 0 )
674        return -1;
675    rc = do_xen_hypercall(handle, &hypercall);
676    unlock_pages(&arg, sizeof(arg));
677    return rc;
678}
679
680int xc_get_hvm_param(int handle, domid_t dom, int param, unsigned long *value)
681{
682    DECLARE_HYPERCALL;
683    xen_hvm_param_t arg;
684    int rc;
685
686    hypercall.op     = __HYPERVISOR_hvm_op;
687    hypercall.arg[0] = HVMOP_get_param;
688    hypercall.arg[1] = (unsigned long)&arg;
689    arg.domid = dom;
690    arg.index = param;
691    if ( lock_pages(&arg, sizeof(arg)) != 0 )
692        return -1;
693    rc = do_xen_hypercall(handle, &hypercall);
694    unlock_pages(&arg, sizeof(arg));
695    *value = arg.value;
696    return rc;
697}
698
699/*
700 * Local variables:
701 * mode: C
702 * c-set-style: "BSD"
703 * c-basic-offset: 4
704 * tab-width: 4
705 * indent-tabs-mode: nil
706 * End:
707 */
Note: See TracBrowser for help on using the repository browser.