1 /******************************************************************************
2  * xc_domain.c
3  *
4  * API for manipulating and obtaining information on domains.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation;
9  * version 2.1 of the License.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Copyright (c) 2003, K A Fraser.
20  */
21 
22 #include "xc_private.h"
23 #include "xc_core.h"
24 #include "xg_private.h"
25 #include "xg_save_restore.h"
26 #include <xen/memory.h>
27 #include <xen/hvm/hvm_op.h>
28 
xc_domain_create(xc_interface * xch,uint32_t * pdomid,struct xen_domctl_createdomain * config)29 int xc_domain_create(xc_interface *xch, uint32_t *pdomid,
30                      struct xen_domctl_createdomain *config)
31 {
32     int err;
33     DECLARE_DOMCTL;
34 
35     domctl.cmd = XEN_DOMCTL_createdomain;
36     domctl.domain = *pdomid;
37     domctl.u.createdomain = *config;
38 
39     if ( (err = do_domctl(xch, &domctl)) != 0 )
40         return err;
41 
42     *pdomid = (uint16_t)domctl.domain;
43     *config = domctl.u.createdomain;
44 
45     return 0;
46 }
47 
xc_domain_cacheflush(xc_interface * xch,uint32_t domid,xen_pfn_t start_pfn,xen_pfn_t nr_pfns)48 int xc_domain_cacheflush(xc_interface *xch, uint32_t domid,
49                          xen_pfn_t start_pfn, xen_pfn_t nr_pfns)
50 {
51 #if defined (__i386__) || defined (__x86_64__)
52     /*
53      * The x86 architecture provides cache coherency guarantees which prevent
54      * the need for this hypercall.  Avoid the overhead of making a hypercall
55      * just for Xen to return -ENOSYS.  It is safe to ignore this call on x86
56      * so we just return 0.
57      */
58     return 0;
59 #else
60     DECLARE_DOMCTL;
61     domctl.cmd = XEN_DOMCTL_cacheflush;
62     domctl.domain = domid;
63     domctl.u.cacheflush.start_pfn = start_pfn;
64     domctl.u.cacheflush.nr_pfns = nr_pfns;
65     return do_domctl(xch, &domctl);
66 #endif
67 }
68 
xc_domain_pause(xc_interface * xch,uint32_t domid)69 int xc_domain_pause(xc_interface *xch,
70                     uint32_t domid)
71 {
72     DECLARE_DOMCTL;
73     domctl.cmd = XEN_DOMCTL_pausedomain;
74     domctl.domain = domid;
75     return do_domctl(xch, &domctl);
76 }
77 
78 
xc_domain_unpause(xc_interface * xch,uint32_t domid)79 int xc_domain_unpause(xc_interface *xch,
80                       uint32_t domid)
81 {
82     DECLARE_DOMCTL;
83     domctl.cmd = XEN_DOMCTL_unpausedomain;
84     domctl.domain = domid;
85     return do_domctl(xch, &domctl);
86 }
87 
88 
xc_domain_destroy(xc_interface * xch,uint32_t domid)89 int xc_domain_destroy(xc_interface *xch,
90                       uint32_t domid)
91 {
92     DECLARE_DOMCTL;
93     domctl.cmd = XEN_DOMCTL_destroydomain;
94     domctl.domain = domid;
95     return do_domctl(xch, &domctl);
96 }
97 
xc_domain_shutdown(xc_interface * xch,uint32_t domid,int reason)98 int xc_domain_shutdown(xc_interface *xch,
99                        uint32_t domid,
100                        int reason)
101 {
102     int ret = -1;
103     DECLARE_HYPERCALL_BUFFER(sched_remote_shutdown_t, arg);
104 
105     arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
106     if ( arg == NULL )
107     {
108         PERROR("Could not allocate memory for xc_domain_shutdown hypercall");
109         goto out1;
110     }
111 
112     arg->domain_id = domid;
113     arg->reason = reason;
114     ret = xencall2(xch->xcall, __HYPERVISOR_sched_op,
115                    SCHEDOP_remote_shutdown,
116                    HYPERCALL_BUFFER_AS_ARG(arg));
117 
118     xc_hypercall_buffer_free(xch, arg);
119 
120  out1:
121     return ret;
122 }
123 
124 
xc_domain_node_setaffinity(xc_interface * xch,uint32_t domid,xc_nodemap_t nodemap)125 int xc_domain_node_setaffinity(xc_interface *xch,
126                                uint32_t domid,
127                                xc_nodemap_t nodemap)
128 {
129     DECLARE_DOMCTL;
130     DECLARE_HYPERCALL_BUFFER(uint8_t, local);
131     int ret = -1;
132     int nodesize;
133 
134     nodesize = xc_get_nodemap_size(xch);
135     if (nodesize <= 0)
136     {
137         PERROR("Could not get number of nodes");
138         goto out;
139     }
140 
141     local = xc_hypercall_buffer_alloc(xch, local, nodesize);
142     if ( local == NULL )
143     {
144         PERROR("Could not allocate memory for setnodeaffinity domctl hypercall");
145         goto out;
146     }
147 
148     domctl.cmd = XEN_DOMCTL_setnodeaffinity;
149     domctl.domain = domid;
150 
151     memcpy(local, nodemap, nodesize);
152     set_xen_guest_handle(domctl.u.nodeaffinity.nodemap.bitmap, local);
153     domctl.u.nodeaffinity.nodemap.nr_bits = nodesize * 8;
154 
155     ret = do_domctl(xch, &domctl);
156 
157     xc_hypercall_buffer_free(xch, local);
158 
159  out:
160     return ret;
161 }
162 
xc_domain_node_getaffinity(xc_interface * xch,uint32_t domid,xc_nodemap_t nodemap)163 int xc_domain_node_getaffinity(xc_interface *xch,
164                                uint32_t domid,
165                                xc_nodemap_t nodemap)
166 {
167     DECLARE_DOMCTL;
168     DECLARE_HYPERCALL_BUFFER(uint8_t, local);
169     int ret = -1;
170     int nodesize;
171 
172     nodesize = xc_get_nodemap_size(xch);
173     if (nodesize <= 0)
174     {
175         PERROR("Could not get number of nodes");
176         goto out;
177     }
178 
179     local = xc_hypercall_buffer_alloc(xch, local, nodesize);
180     if ( local == NULL )
181     {
182         PERROR("Could not allocate memory for getnodeaffinity domctl hypercall");
183         goto out;
184     }
185 
186     domctl.cmd = XEN_DOMCTL_getnodeaffinity;
187     domctl.domain = domid;
188 
189     set_xen_guest_handle(domctl.u.nodeaffinity.nodemap.bitmap, local);
190     domctl.u.nodeaffinity.nodemap.nr_bits = nodesize * 8;
191 
192     ret = do_domctl(xch, &domctl);
193 
194     memcpy(nodemap, local, nodesize);
195 
196     xc_hypercall_buffer_free(xch, local);
197 
198  out:
199     return ret;
200 }
201 
xc_vcpu_setaffinity(xc_interface * xch,uint32_t domid,int vcpu,xc_cpumap_t cpumap_hard_inout,xc_cpumap_t cpumap_soft_inout,uint32_t flags)202 int xc_vcpu_setaffinity(xc_interface *xch,
203                         uint32_t domid,
204                         int vcpu,
205                         xc_cpumap_t cpumap_hard_inout,
206                         xc_cpumap_t cpumap_soft_inout,
207                         uint32_t flags)
208 {
209     DECLARE_DOMCTL;
210     DECLARE_HYPERCALL_BOUNCE(cpumap_hard_inout, 0,
211                              XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
212     DECLARE_HYPERCALL_BOUNCE(cpumap_soft_inout, 0,
213                              XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
214     int ret = -1;
215     int cpusize;
216 
217     cpusize = xc_get_cpumap_size(xch);
218     if (cpusize <= 0)
219     {
220         PERROR("Could not get number of cpus");
221         return -1;
222     }
223 
224     HYPERCALL_BOUNCE_SET_SIZE(cpumap_hard_inout, cpusize);
225     HYPERCALL_BOUNCE_SET_SIZE(cpumap_soft_inout, cpusize);
226 
227     if ( xc_hypercall_bounce_pre(xch, cpumap_hard_inout) ||
228          xc_hypercall_bounce_pre(xch, cpumap_soft_inout) )
229     {
230         PERROR("Could not allocate hcall buffers for DOMCTL_setvcpuaffinity");
231         goto out;
232     }
233 
234     domctl.cmd = XEN_DOMCTL_setvcpuaffinity;
235     domctl.domain = domid;
236     domctl.u.vcpuaffinity.vcpu = vcpu;
237     domctl.u.vcpuaffinity.flags = flags;
238 
239     set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_hard.bitmap,
240                          cpumap_hard_inout);
241     domctl.u.vcpuaffinity.cpumap_hard.nr_bits = cpusize * 8;
242     set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_soft.bitmap,
243                          cpumap_soft_inout);
244     domctl.u.vcpuaffinity.cpumap_soft.nr_bits = cpusize * 8;
245 
246     ret = do_domctl(xch, &domctl);
247 
248  out:
249     xc_hypercall_bounce_post(xch, cpumap_hard_inout);
250     xc_hypercall_bounce_post(xch, cpumap_soft_inout);
251 
252     return ret;
253 }
254 
255 
xc_vcpu_getaffinity(xc_interface * xch,uint32_t domid,int vcpu,xc_cpumap_t cpumap_hard,xc_cpumap_t cpumap_soft,uint32_t flags)256 int xc_vcpu_getaffinity(xc_interface *xch,
257                         uint32_t domid,
258                         int vcpu,
259                         xc_cpumap_t cpumap_hard,
260                         xc_cpumap_t cpumap_soft,
261                         uint32_t flags)
262 {
263     DECLARE_DOMCTL;
264     DECLARE_HYPERCALL_BOUNCE(cpumap_hard, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
265     DECLARE_HYPERCALL_BOUNCE(cpumap_soft, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
266     int ret = -1;
267     int cpusize;
268 
269     cpusize = xc_get_cpumap_size(xch);
270     if (cpusize <= 0)
271     {
272         PERROR("Could not get number of cpus");
273         return -1;
274     }
275 
276     HYPERCALL_BOUNCE_SET_SIZE(cpumap_hard, cpusize);
277     HYPERCALL_BOUNCE_SET_SIZE(cpumap_soft, cpusize);
278 
279     if ( xc_hypercall_bounce_pre(xch, cpumap_hard) ||
280          xc_hypercall_bounce_pre(xch, cpumap_soft) )
281     {
282         PERROR("Could not allocate hcall buffers for DOMCTL_getvcpuaffinity");
283         goto out;
284     }
285 
286     domctl.cmd = XEN_DOMCTL_getvcpuaffinity;
287     domctl.domain = domid;
288     domctl.u.vcpuaffinity.vcpu = vcpu;
289     domctl.u.vcpuaffinity.flags = flags;
290 
291     set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_hard.bitmap,
292                          cpumap_hard);
293     domctl.u.vcpuaffinity.cpumap_hard.nr_bits = cpusize * 8;
294     set_xen_guest_handle(domctl.u.vcpuaffinity.cpumap_soft.bitmap,
295                          cpumap_soft);
296     domctl.u.vcpuaffinity.cpumap_soft.nr_bits = cpusize * 8;
297 
298     ret = do_domctl(xch, &domctl);
299 
300  out:
301     xc_hypercall_bounce_post(xch, cpumap_hard);
302     xc_hypercall_bounce_post(xch, cpumap_soft);
303 
304     return ret;
305 }
306 
xc_domain_get_guest_width(xc_interface * xch,uint32_t domid,unsigned int * guest_width)307 int xc_domain_get_guest_width(xc_interface *xch, uint32_t domid,
308                               unsigned int *guest_width)
309 {
310     DECLARE_DOMCTL;
311 
312     memset(&domctl, 0, sizeof(domctl));
313     domctl.domain = domid;
314     domctl.cmd = XEN_DOMCTL_get_address_size;
315 
316     if ( do_domctl(xch, &domctl) != 0 )
317         return 1;
318 
319     /* We want the result in bytes */
320     *guest_width = domctl.u.address_size.size / 8;
321     return 0;
322 }
323 
xc_dom_vuart_init(xc_interface * xch,uint32_t type,uint32_t domid,uint32_t console_domid,xen_pfn_t gfn,evtchn_port_t * evtchn)324 int xc_dom_vuart_init(xc_interface *xch,
325                       uint32_t type,
326                       uint32_t domid,
327                       uint32_t console_domid,
328                       xen_pfn_t gfn,
329                       evtchn_port_t *evtchn)
330 {
331     DECLARE_DOMCTL;
332     int rc = 0;
333 
334     memset(&domctl, 0, sizeof(domctl));
335 
336     domctl.cmd = XEN_DOMCTL_vuart_op;
337     domctl.domain = domid;
338     domctl.u.vuart_op.cmd = XEN_DOMCTL_VUART_OP_INIT;
339     domctl.u.vuart_op.type = type;
340     domctl.u.vuart_op.console_domid = console_domid;
341     domctl.u.vuart_op.gfn = gfn;
342 
343     if ( (rc = do_domctl(xch, &domctl)) < 0 )
344         return rc;
345 
346     *evtchn = domctl.u.vuart_op.evtchn;
347 
348     return rc;
349 }
350 
xc_domain_getinfo(xc_interface * xch,uint32_t first_domid,unsigned int max_doms,xc_dominfo_t * info)351 int xc_domain_getinfo(xc_interface *xch,
352                       uint32_t first_domid,
353                       unsigned int max_doms,
354                       xc_dominfo_t *info)
355 {
356     unsigned int nr_doms;
357     uint32_t next_domid = first_domid;
358     DECLARE_DOMCTL;
359     int rc = 0;
360 
361     memset(info, 0, max_doms*sizeof(xc_dominfo_t));
362 
363     for ( nr_doms = 0; nr_doms < max_doms; nr_doms++ )
364     {
365         domctl.cmd = XEN_DOMCTL_getdomaininfo;
366         domctl.domain = next_domid;
367         if ( (rc = do_domctl(xch, &domctl)) < 0 )
368             break;
369         info->domid      = domctl.domain;
370 
371         info->dying    = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_dying);
372         info->shutdown = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_shutdown);
373         info->paused   = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_paused);
374         info->blocked  = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_blocked);
375         info->running  = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_running);
376         info->hvm      = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hvm_guest);
377         info->debugged = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_debugged);
378         info->xenstore = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_xs_domain);
379         info->hap      = !!(domctl.u.getdomaininfo.flags&XEN_DOMINF_hap);
380 
381         info->shutdown_reason =
382             (domctl.u.getdomaininfo.flags>>XEN_DOMINF_shutdownshift) &
383             XEN_DOMINF_shutdownmask;
384 
385         if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
386         {
387             info->shutdown = 0;
388             info->crashed  = 1;
389         }
390 
391         info->ssidref  = domctl.u.getdomaininfo.ssidref;
392         info->nr_pages = domctl.u.getdomaininfo.tot_pages;
393         info->nr_outstanding_pages = domctl.u.getdomaininfo.outstanding_pages;
394         info->nr_shared_pages = domctl.u.getdomaininfo.shr_pages;
395         info->nr_paged_pages = domctl.u.getdomaininfo.paged_pages;
396         info->max_memkb = domctl.u.getdomaininfo.max_pages << (PAGE_SHIFT-10);
397         info->shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
398         info->cpu_time = domctl.u.getdomaininfo.cpu_time;
399         info->nr_online_vcpus = domctl.u.getdomaininfo.nr_online_vcpus;
400         info->max_vcpu_id = domctl.u.getdomaininfo.max_vcpu_id;
401         info->cpupool = domctl.u.getdomaininfo.cpupool;
402         info->arch_config = domctl.u.getdomaininfo.arch_config;
403 
404         memcpy(info->handle, domctl.u.getdomaininfo.handle,
405                sizeof(xen_domain_handle_t));
406 
407         next_domid = (uint16_t)domctl.domain + 1;
408         info++;
409     }
410 
411     if ( nr_doms == 0 )
412         return rc;
413 
414     return nr_doms;
415 }
416 
xc_domain_getinfolist(xc_interface * xch,uint32_t first_domain,unsigned int max_domains,xc_domaininfo_t * info)417 int xc_domain_getinfolist(xc_interface *xch,
418                           uint32_t first_domain,
419                           unsigned int max_domains,
420                           xc_domaininfo_t *info)
421 {
422     int ret = 0;
423     DECLARE_SYSCTL;
424     DECLARE_HYPERCALL_BOUNCE(info, max_domains*sizeof(*info), XC_HYPERCALL_BUFFER_BOUNCE_OUT);
425 
426     if ( xc_hypercall_bounce_pre(xch, info) )
427         return -1;
428 
429     sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
430     sysctl.u.getdomaininfolist.first_domain = first_domain;
431     sysctl.u.getdomaininfolist.max_domains  = max_domains;
432     set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);
433 
434     if ( xc_sysctl(xch, &sysctl) < 0 )
435         ret = -1;
436     else
437         ret = sysctl.u.getdomaininfolist.num_domains;
438 
439     xc_hypercall_bounce_post(xch, info);
440 
441     return ret;
442 }
443 
444 /* set broken page p2m */
xc_set_broken_page_p2m(xc_interface * xch,uint32_t domid,unsigned long pfn)445 int xc_set_broken_page_p2m(xc_interface *xch,
446                            uint32_t domid,
447                            unsigned long pfn)
448 {
449     int ret;
450     DECLARE_DOMCTL;
451 
452     domctl.cmd = XEN_DOMCTL_set_broken_page_p2m;
453     domctl.domain = domid;
454     domctl.u.set_broken_page_p2m.pfn = pfn;
455     ret = do_domctl(xch, &domctl);
456 
457     return ret ? -1 : 0;
458 }
459 
460 /* get info from hvm guest for save */
xc_domain_hvm_getcontext(xc_interface * xch,uint32_t domid,uint8_t * ctxt_buf,uint32_t size)461 int xc_domain_hvm_getcontext(xc_interface *xch,
462                              uint32_t domid,
463                              uint8_t *ctxt_buf,
464                              uint32_t size)
465 {
466     int ret;
467     DECLARE_DOMCTL;
468     DECLARE_HYPERCALL_BOUNCE(ctxt_buf, size, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
469 
470     if ( xc_hypercall_bounce_pre(xch, ctxt_buf) )
471         return -1;
472 
473     domctl.cmd = XEN_DOMCTL_gethvmcontext;
474     domctl.domain = domid;
475     domctl.u.hvmcontext.size = size;
476     set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
477 
478     ret = do_domctl(xch, &domctl);
479 
480     xc_hypercall_bounce_post(xch, ctxt_buf);
481 
482     return (ret < 0 ? -1 : domctl.u.hvmcontext.size);
483 }
484 
485 /* Get just one element of the HVM guest context.
486  * size must be >= HVM_SAVE_LENGTH(type) */
xc_domain_hvm_getcontext_partial(xc_interface * xch,uint32_t domid,uint16_t typecode,uint16_t instance,void * ctxt_buf,uint32_t size)487 int xc_domain_hvm_getcontext_partial(xc_interface *xch,
488                                      uint32_t domid,
489                                      uint16_t typecode,
490                                      uint16_t instance,
491                                      void *ctxt_buf,
492                                      uint32_t size)
493 {
494     int ret;
495     DECLARE_DOMCTL;
496     DECLARE_HYPERCALL_BOUNCE(ctxt_buf, size, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
497 
498     if ( !ctxt_buf || xc_hypercall_bounce_pre(xch, ctxt_buf) )
499         return -1;
500 
501     domctl.cmd = XEN_DOMCTL_gethvmcontext_partial;
502     domctl.domain = domid;
503     domctl.u.hvmcontext_partial.type = typecode;
504     domctl.u.hvmcontext_partial.instance = instance;
505     domctl.u.hvmcontext_partial.bufsz = size;
506     set_xen_guest_handle(domctl.u.hvmcontext_partial.buffer, ctxt_buf);
507 
508     ret = do_domctl(xch, &domctl);
509 
510     xc_hypercall_bounce_post(xch, ctxt_buf);
511 
512     return ret ? -1 : 0;
513 }
514 
515 /* set info to hvm guest for restore */
xc_domain_hvm_setcontext(xc_interface * xch,uint32_t domid,uint8_t * ctxt_buf,uint32_t size)516 int xc_domain_hvm_setcontext(xc_interface *xch,
517                              uint32_t domid,
518                              uint8_t *ctxt_buf,
519                              uint32_t size)
520 {
521     int ret;
522     DECLARE_DOMCTL;
523     DECLARE_HYPERCALL_BOUNCE(ctxt_buf, size, XC_HYPERCALL_BUFFER_BOUNCE_IN);
524 
525     if ( xc_hypercall_bounce_pre(xch, ctxt_buf) )
526         return -1;
527 
528     domctl.cmd = XEN_DOMCTL_sethvmcontext;
529     domctl.domain = domid;
530     domctl.u.hvmcontext.size = size;
531     set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf);
532 
533     ret = do_domctl(xch, &domctl);
534 
535     xc_hypercall_bounce_post(xch, ctxt_buf);
536 
537     return ret;
538 }
539 
xc_vcpu_getcontext(xc_interface * xch,uint32_t domid,uint32_t vcpu,vcpu_guest_context_any_t * ctxt)540 int xc_vcpu_getcontext(xc_interface *xch,
541                        uint32_t domid,
542                        uint32_t vcpu,
543                        vcpu_guest_context_any_t *ctxt)
544 {
545     int rc;
546     DECLARE_DOMCTL;
547     DECLARE_HYPERCALL_BOUNCE(ctxt, sizeof(vcpu_guest_context_any_t), XC_HYPERCALL_BUFFER_BOUNCE_OUT);
548 
549     if ( xc_hypercall_bounce_pre(xch, ctxt) )
550         return -1;
551 
552     domctl.cmd = XEN_DOMCTL_getvcpucontext;
553     domctl.domain = domid;
554     domctl.u.vcpucontext.vcpu   = (uint16_t)vcpu;
555     set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
556 
557     rc = do_domctl(xch, &domctl);
558 
559     xc_hypercall_bounce_post(xch, ctxt);
560 
561     return rc;
562 }
563 
xc_vcpu_get_extstate(xc_interface * xch,uint32_t domid,uint32_t vcpu,xc_vcpu_extstate_t * extstate)564 int xc_vcpu_get_extstate(xc_interface *xch,
565                          uint32_t domid,
566                          uint32_t vcpu,
567                          xc_vcpu_extstate_t *extstate)
568 {
569     int rc = -ENODEV;
570 #if defined (__i386__) || defined(__x86_64__)
571     DECLARE_DOMCTL;
572     DECLARE_HYPERCALL_BUFFER(void, buffer);
573     bool get_state;
574 
575     if ( !extstate )
576         return -EINVAL;
577 
578     domctl.cmd = XEN_DOMCTL_getvcpuextstate;
579     domctl.domain = domid;
580     domctl.u.vcpuextstate.vcpu = (uint16_t)vcpu;
581     domctl.u.vcpuextstate.xfeature_mask = extstate->xfeature_mask;
582     domctl.u.vcpuextstate.size = extstate->size;
583 
584     get_state = (extstate->size != 0);
585 
586     if ( get_state )
587     {
588         buffer = xc_hypercall_buffer_alloc(xch, buffer, extstate->size);
589 
590         if ( !buffer )
591         {
592             PERROR("Unable to allocate memory for vcpu%u's xsave context",
593                    vcpu);
594             rc = -ENOMEM;
595             goto out;
596         }
597 
598         set_xen_guest_handle(domctl.u.vcpuextstate.buffer, buffer);
599     }
600 
601     rc = do_domctl(xch, &domctl);
602 
603     if ( rc )
604         goto out;
605 
606     /* A query for the size of buffer to use. */
607     if ( !extstate->size && !extstate->xfeature_mask )
608     {
609         extstate->xfeature_mask = domctl.u.vcpuextstate.xfeature_mask;
610         extstate->size = domctl.u.vcpuextstate.size;
611         goto out;
612     }
613 
614     if ( get_state )
615         memcpy(extstate->buffer, buffer, extstate->size);
616 
617 out:
618     if ( get_state )
619         xc_hypercall_buffer_free(xch, buffer);
620 #endif
621 
622     return rc;
623 }
624 
xc_watchdog(xc_interface * xch,uint32_t id,uint32_t timeout)625 int xc_watchdog(xc_interface *xch,
626                 uint32_t id,
627                 uint32_t timeout)
628 {
629     int ret = -1;
630     DECLARE_HYPERCALL_BUFFER(sched_watchdog_t, arg);
631 
632     arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
633     if ( arg == NULL )
634     {
635         PERROR("Could not allocate memory for xc_watchdog hypercall");
636         goto out1;
637     }
638 
639     arg->id = id;
640     arg->timeout = timeout;
641 
642     ret = xencall2(xch->xcall, __HYPERVISOR_sched_op,
643                    SCHEDOP_watchdog,
644                    HYPERCALL_BUFFER_AS_ARG(arg));
645 
646     xc_hypercall_buffer_free(xch, arg);
647 
648  out1:
649     return ret;
650 }
651 
652 
xc_shadow_control(xc_interface * xch,uint32_t domid,unsigned int sop,xc_hypercall_buffer_t * dirty_bitmap,unsigned long pages,unsigned long * mb,uint32_t mode,xc_shadow_op_stats_t * stats)653 int xc_shadow_control(xc_interface *xch,
654                       uint32_t domid,
655                       unsigned int sop,
656                       xc_hypercall_buffer_t *dirty_bitmap,
657                       unsigned long pages,
658                       unsigned long *mb,
659                       uint32_t mode,
660                       xc_shadow_op_stats_t *stats)
661 {
662     int rc;
663     DECLARE_DOMCTL;
664     DECLARE_HYPERCALL_BUFFER_ARGUMENT(dirty_bitmap);
665 
666     memset(&domctl, 0, sizeof(domctl));
667 
668     domctl.cmd = XEN_DOMCTL_shadow_op;
669     domctl.domain = domid;
670     domctl.u.shadow_op.op     = sop;
671     domctl.u.shadow_op.pages  = pages;
672     domctl.u.shadow_op.mb     = mb ? *mb : 0;
673     domctl.u.shadow_op.mode   = mode;
674     if (dirty_bitmap != NULL)
675         set_xen_guest_handle(domctl.u.shadow_op.dirty_bitmap,
676                                 dirty_bitmap);
677 
678     rc = do_domctl(xch, &domctl);
679 
680     if ( stats )
681         memcpy(stats, &domctl.u.shadow_op.stats,
682                sizeof(xc_shadow_op_stats_t));
683 
684     if ( mb )
685         *mb = domctl.u.shadow_op.mb;
686 
687     return (rc == 0) ? domctl.u.shadow_op.pages : rc;
688 }
689 
xc_domain_setmaxmem(xc_interface * xch,uint32_t domid,uint64_t max_memkb)690 int xc_domain_setmaxmem(xc_interface *xch,
691                         uint32_t domid,
692                         uint64_t max_memkb)
693 {
694     DECLARE_DOMCTL;
695     domctl.cmd = XEN_DOMCTL_max_mem;
696     domctl.domain = domid;
697     domctl.u.max_mem.max_memkb = max_memkb;
698     return do_domctl(xch, &domctl);
699 }
700 
701 #if defined(__i386__) || defined(__x86_64__)
xc_domain_set_memory_map(xc_interface * xch,uint32_t domid,struct e820entry entries[],uint32_t nr_entries)702 int xc_domain_set_memory_map(xc_interface *xch,
703                                uint32_t domid,
704                                struct e820entry entries[],
705                                uint32_t nr_entries)
706 {
707     int rc;
708     struct xen_foreign_memory_map fmap = {
709         .domid = domid,
710         .map = { .nr_entries = nr_entries }
711     };
712     DECLARE_HYPERCALL_BOUNCE(entries, nr_entries * sizeof(struct e820entry),
713                              XC_HYPERCALL_BUFFER_BOUNCE_IN);
714 
715     if ( !entries || xc_hypercall_bounce_pre(xch, entries) )
716         return -1;
717 
718     set_xen_guest_handle(fmap.map.buffer, entries);
719 
720     rc = do_memory_op(xch, XENMEM_set_memory_map, &fmap, sizeof(fmap));
721 
722     xc_hypercall_bounce_post(xch, entries);
723 
724     return rc;
725 }
726 
xc_get_machine_memory_map(xc_interface * xch,struct e820entry entries[],uint32_t max_entries)727 int xc_get_machine_memory_map(xc_interface *xch,
728                               struct e820entry entries[],
729                               uint32_t max_entries)
730 {
731     int rc;
732     struct xen_memory_map memmap = {
733         .nr_entries = max_entries
734     };
735     DECLARE_HYPERCALL_BOUNCE(entries, sizeof(struct e820entry) * max_entries,
736                              XC_HYPERCALL_BUFFER_BOUNCE_OUT);
737 
738     if ( !entries || xc_hypercall_bounce_pre(xch, entries) || max_entries <= 1)
739         return -1;
740 
741 
742     set_xen_guest_handle(memmap.buffer, entries);
743 
744     rc = do_memory_op(xch, XENMEM_machine_memory_map, &memmap, sizeof(memmap));
745 
746     xc_hypercall_bounce_post(xch, entries);
747 
748     return rc ? rc : memmap.nr_entries;
749 }
xc_domain_set_memmap_limit(xc_interface * xch,uint32_t domid,unsigned long map_limitkb)750 int xc_domain_set_memmap_limit(xc_interface *xch,
751                                uint32_t domid,
752                                unsigned long map_limitkb)
753 {
754     struct e820entry e820;
755 
756     e820.addr = 0;
757     e820.size = (uint64_t)map_limitkb << 10;
758     e820.type = E820_RAM;
759 
760     return xc_domain_set_memory_map(xch, domid, &e820, 1);
761 }
762 #else
xc_domain_set_memmap_limit(xc_interface * xch,uint32_t domid,unsigned long map_limitkb)763 int xc_domain_set_memmap_limit(xc_interface *xch,
764                                uint32_t domid,
765                                unsigned long map_limitkb)
766 {
767     PERROR("Function not implemented");
768     errno = ENOSYS;
769     return -1;
770 }
771 #endif
772 
xc_reserved_device_memory_map(xc_interface * xch,uint32_t flags,uint16_t seg,uint8_t bus,uint8_t devfn,struct xen_reserved_device_memory entries[],uint32_t * max_entries)773 int xc_reserved_device_memory_map(xc_interface *xch,
774                                   uint32_t flags,
775                                   uint16_t seg,
776                                   uint8_t bus,
777                                   uint8_t devfn,
778                                   struct xen_reserved_device_memory entries[],
779                                   uint32_t *max_entries)
780 {
781     int rc;
782     struct xen_reserved_device_memory_map xrdmmap = {
783         .flags = flags,
784         .dev.pci.seg = seg,
785         .dev.pci.bus = bus,
786         .dev.pci.devfn = devfn,
787         .nr_entries = *max_entries
788     };
789     DECLARE_HYPERCALL_BOUNCE(entries,
790                              sizeof(struct xen_reserved_device_memory) *
791                              *max_entries, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
792 
793     if ( xc_hypercall_bounce_pre(xch, entries) )
794         return -1;
795 
796     set_xen_guest_handle(xrdmmap.buffer, entries);
797 
798     rc = do_memory_op(xch, XENMEM_reserved_device_memory_map,
799                       &xrdmmap, sizeof(xrdmmap));
800 
801     xc_hypercall_bounce_post(xch, entries);
802 
803     *max_entries = xrdmmap.nr_entries;
804 
805     return rc;
806 }
807 
xc_domain_set_time_offset(xc_interface * xch,uint32_t domid,int32_t time_offset_seconds)808 int xc_domain_set_time_offset(xc_interface *xch,
809                               uint32_t domid,
810                               int32_t time_offset_seconds)
811 {
812     DECLARE_DOMCTL;
813     domctl.cmd = XEN_DOMCTL_settimeoffset;
814     domctl.domain = domid;
815     domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
816     return do_domctl(xch, &domctl);
817 }
818 
xc_domain_disable_migrate(xc_interface * xch,uint32_t domid)819 int xc_domain_disable_migrate(xc_interface *xch, uint32_t domid)
820 {
821     DECLARE_DOMCTL;
822     domctl.cmd = XEN_DOMCTL_disable_migrate;
823     domctl.domain = domid;
824     domctl.u.disable_migrate.disable = 1;
825     return do_domctl(xch, &domctl);
826 }
827 
xc_domain_set_tsc_info(xc_interface * xch,uint32_t domid,uint32_t tsc_mode,uint64_t elapsed_nsec,uint32_t gtsc_khz,uint32_t incarnation)828 int xc_domain_set_tsc_info(xc_interface *xch,
829                            uint32_t domid,
830                            uint32_t tsc_mode,
831                            uint64_t elapsed_nsec,
832                            uint32_t gtsc_khz,
833                            uint32_t incarnation)
834 {
835     DECLARE_DOMCTL;
836     domctl.cmd = XEN_DOMCTL_settscinfo;
837     domctl.domain = domid;
838     domctl.u.tsc_info.tsc_mode = tsc_mode;
839     domctl.u.tsc_info.elapsed_nsec = elapsed_nsec;
840     domctl.u.tsc_info.gtsc_khz = gtsc_khz;
841     domctl.u.tsc_info.incarnation = incarnation;
842     return do_domctl(xch, &domctl);
843 }
844 
xc_domain_get_tsc_info(xc_interface * xch,uint32_t domid,uint32_t * tsc_mode,uint64_t * elapsed_nsec,uint32_t * gtsc_khz,uint32_t * incarnation)845 int xc_domain_get_tsc_info(xc_interface *xch,
846                            uint32_t domid,
847                            uint32_t *tsc_mode,
848                            uint64_t *elapsed_nsec,
849                            uint32_t *gtsc_khz,
850                            uint32_t *incarnation)
851 {
852     int rc;
853     DECLARE_DOMCTL;
854 
855     domctl.cmd = XEN_DOMCTL_gettscinfo;
856     domctl.domain = domid;
857     rc = do_domctl(xch, &domctl);
858     if ( rc == 0 )
859     {
860         *tsc_mode = domctl.u.tsc_info.tsc_mode;
861         *elapsed_nsec = domctl.u.tsc_info.elapsed_nsec;
862         *gtsc_khz = domctl.u.tsc_info.gtsc_khz;
863         *incarnation = domctl.u.tsc_info.incarnation;
864     }
865     return rc;
866 }
867 
868 
xc_domain_maximum_gpfn(xc_interface * xch,uint32_t domid,xen_pfn_t * gpfns)869 int xc_domain_maximum_gpfn(xc_interface *xch, uint32_t domid, xen_pfn_t *gpfns)
870 {
871     long rc = do_memory_op(xch, XENMEM_maximum_gpfn, &domid, sizeof(domid));
872 
873     if ( rc >= 0 )
874     {
875         *gpfns = rc;
876         rc = 0;
877     }
878     return rc;
879 }
880 
xc_domain_nr_gpfns(xc_interface * xch,uint32_t domid,xen_pfn_t * gpfns)881 int xc_domain_nr_gpfns(xc_interface *xch, uint32_t domid, xen_pfn_t *gpfns)
882 {
883     int rc = xc_domain_maximum_gpfn(xch, domid, gpfns);
884 
885     if ( rc >= 0 )
886         *gpfns += 1;
887 
888     return rc;
889 }
890 
xc_domain_increase_reservation(xc_interface * xch,uint32_t domid,unsigned long nr_extents,unsigned int extent_order,unsigned int mem_flags,xen_pfn_t * extent_start)891 int xc_domain_increase_reservation(xc_interface *xch,
892                                    uint32_t domid,
893                                    unsigned long nr_extents,
894                                    unsigned int extent_order,
895                                    unsigned int mem_flags,
896                                    xen_pfn_t *extent_start)
897 {
898     int err;
899     DECLARE_HYPERCALL_BOUNCE(extent_start, nr_extents * sizeof(*extent_start), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
900     struct xen_memory_reservation reservation = {
901         .nr_extents   = nr_extents,
902         .extent_order = extent_order,
903         .mem_flags    = mem_flags,
904         .domid        = domid
905     };
906 
907     /* may be NULL */
908     if ( xc_hypercall_bounce_pre(xch, extent_start) )
909     {
910         PERROR("Could not bounce memory for XENMEM_increase_reservation hypercall");
911         return -1;
912     }
913 
914     set_xen_guest_handle(reservation.extent_start, extent_start);
915 
916     err = do_memory_op(xch, XENMEM_increase_reservation, &reservation, sizeof(reservation));
917 
918     xc_hypercall_bounce_post(xch, extent_start);
919 
920     return err;
921 }
922 
xc_domain_increase_reservation_exact(xc_interface * xch,uint32_t domid,unsigned long nr_extents,unsigned int extent_order,unsigned int mem_flags,xen_pfn_t * extent_start)923 int xc_domain_increase_reservation_exact(xc_interface *xch,
924                                          uint32_t domid,
925                                          unsigned long nr_extents,
926                                          unsigned int extent_order,
927                                          unsigned int mem_flags,
928                                          xen_pfn_t *extent_start)
929 {
930     int err;
931 
932     err = xc_domain_increase_reservation(xch, domid, nr_extents,
933                                          extent_order, mem_flags, extent_start);
934 
935     if ( err == nr_extents )
936         return 0;
937 
938     if ( err >= 0 )
939     {
940         DPRINTF("Failed allocation for dom %d: "
941                 "%ld extents of order %d, mem_flags %x\n",
942                 domid, nr_extents, extent_order, mem_flags);
943         errno = ENOMEM;
944         err = -1;
945     }
946 
947     return err;
948 }
949 
xc_domain_decrease_reservation(xc_interface * xch,uint32_t domid,unsigned long nr_extents,unsigned int extent_order,xen_pfn_t * extent_start)950 int xc_domain_decrease_reservation(xc_interface *xch,
951                                    uint32_t domid,
952                                    unsigned long nr_extents,
953                                    unsigned int extent_order,
954                                    xen_pfn_t *extent_start)
955 {
956     int err;
957     DECLARE_HYPERCALL_BOUNCE(extent_start, nr_extents * sizeof(*extent_start), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
958     struct xen_memory_reservation reservation = {
959         .nr_extents   = nr_extents,
960         .extent_order = extent_order,
961         .mem_flags    = 0,
962         .domid        = domid
963     };
964 
965     if ( extent_start == NULL )
966     {
967         DPRINTF("decrease_reservation extent_start is NULL!\n");
968         errno = EINVAL;
969         return -1;
970     }
971 
972     if ( xc_hypercall_bounce_pre(xch, extent_start) )
973     {
974         PERROR("Could not bounce memory for XENMEM_decrease_reservation hypercall");
975         return -1;
976     }
977     set_xen_guest_handle(reservation.extent_start, extent_start);
978 
979     err = do_memory_op(xch, XENMEM_decrease_reservation, &reservation, sizeof(reservation));
980 
981     xc_hypercall_bounce_post(xch, extent_start);
982 
983     return err;
984 }
985 
xc_domain_decrease_reservation_exact(xc_interface * xch,uint32_t domid,unsigned long nr_extents,unsigned int extent_order,xen_pfn_t * extent_start)986 int xc_domain_decrease_reservation_exact(xc_interface *xch,
987                                          uint32_t domid,
988                                          unsigned long nr_extents,
989                                          unsigned int extent_order,
990                                          xen_pfn_t *extent_start)
991 {
992     int err;
993 
994     err = xc_domain_decrease_reservation(xch, domid, nr_extents,
995                                          extent_order, extent_start);
996 
997     if ( err == nr_extents )
998         return 0;
999 
1000     if ( err >= 0 )
1001     {
1002         DPRINTF("Failed deallocation for dom %d: %ld extents of order %d\n",
1003                 domid, nr_extents, extent_order);
1004         errno = EINVAL;
1005         err = -1;
1006     }
1007 
1008     return err;
1009 }
1010 
xc_domain_add_to_physmap(xc_interface * xch,uint32_t domid,unsigned int space,unsigned long idx,xen_pfn_t gpfn)1011 int xc_domain_add_to_physmap(xc_interface *xch,
1012                              uint32_t domid,
1013                              unsigned int space,
1014                              unsigned long idx,
1015                              xen_pfn_t gpfn)
1016 {
1017     struct xen_add_to_physmap xatp = {
1018         .domid = domid,
1019         .space = space,
1020         .idx = idx,
1021         .gpfn = gpfn,
1022     };
1023     return do_memory_op(xch, XENMEM_add_to_physmap, &xatp, sizeof(xatp));
1024 }
1025 
xc_domain_add_to_physmap_batch(xc_interface * xch,uint32_t domid,uint32_t foreign_domid,unsigned int space,unsigned int size,xen_ulong_t * idxs,xen_pfn_t * gpfns,int * errs)1026 int xc_domain_add_to_physmap_batch(xc_interface *xch,
1027                                    uint32_t domid,
1028                                    uint32_t foreign_domid,
1029                                    unsigned int space,
1030                                    unsigned int size,
1031                                    xen_ulong_t *idxs,
1032                                    xen_pfn_t *gpfns,
1033                                    int *errs)
1034 {
1035     int rc;
1036     DECLARE_HYPERCALL_BOUNCE(idxs, size * sizeof(*idxs), XC_HYPERCALL_BUFFER_BOUNCE_IN);
1037     DECLARE_HYPERCALL_BOUNCE(gpfns, size * sizeof(*gpfns), XC_HYPERCALL_BUFFER_BOUNCE_IN);
1038     DECLARE_HYPERCALL_BOUNCE(errs, size * sizeof(*errs), XC_HYPERCALL_BUFFER_BOUNCE_OUT);
1039 
1040     struct xen_add_to_physmap_batch xatp_batch = {
1041         .domid = domid,
1042         .space = space,
1043         .size = size,
1044         .u = { .foreign_domid = foreign_domid }
1045     };
1046 
1047     if ( xc_hypercall_bounce_pre(xch, idxs)  ||
1048          xc_hypercall_bounce_pre(xch, gpfns) ||
1049          xc_hypercall_bounce_pre(xch, errs)  )
1050     {
1051         PERROR("Could not bounce memory for XENMEM_add_to_physmap_batch");
1052         rc = -1;
1053         goto out;
1054     }
1055 
1056     set_xen_guest_handle(xatp_batch.idxs, idxs);
1057     set_xen_guest_handle(xatp_batch.gpfns, gpfns);
1058     set_xen_guest_handle(xatp_batch.errs, errs);
1059 
1060     rc = do_memory_op(xch, XENMEM_add_to_physmap_batch,
1061                       &xatp_batch, sizeof(xatp_batch));
1062 
1063 out:
1064     xc_hypercall_bounce_post(xch, idxs);
1065     xc_hypercall_bounce_post(xch, gpfns);
1066     xc_hypercall_bounce_post(xch, errs);
1067 
1068     return rc;
1069 }
1070 
xc_domain_remove_from_physmap(xc_interface * xch,uint32_t domid,xen_pfn_t gpfn)1071 int xc_domain_remove_from_physmap(xc_interface *xch,
1072                                   uint32_t domid,
1073                                   xen_pfn_t gpfn)
1074 {
1075     struct xen_remove_from_physmap xrfp = {
1076         .domid = domid,
1077         .gpfn = gpfn,
1078     };
1079     return do_memory_op(xch, XENMEM_remove_from_physmap, &xrfp, sizeof(xrfp));
1080 }
1081 
xc_domain_claim_pages(xc_interface * xch,uint32_t domid,unsigned long nr_pages)1082 int xc_domain_claim_pages(xc_interface *xch,
1083                                uint32_t domid,
1084                                unsigned long nr_pages)
1085 {
1086     int err;
1087     struct xen_memory_reservation reservation = {
1088         .nr_extents   = nr_pages,
1089         .extent_order = 0,
1090         .mem_flags    = 0, /* no flags */
1091         .domid        = domid
1092     };
1093 
1094     set_xen_guest_handle(reservation.extent_start, HYPERCALL_BUFFER_NULL);
1095 
1096     err = do_memory_op(xch, XENMEM_claim_pages, &reservation, sizeof(reservation));
1097     /* Ignore it if the hypervisor does not support the call. */
1098     if (err == -1 && errno == ENOSYS)
1099         err = errno = 0;
1100     return err;
1101 }
1102 
xc_domain_populate_physmap(xc_interface * xch,uint32_t domid,unsigned long nr_extents,unsigned int extent_order,unsigned int mem_flags,xen_pfn_t * extent_start)1103 int xc_domain_populate_physmap(xc_interface *xch,
1104                                uint32_t domid,
1105                                unsigned long nr_extents,
1106                                unsigned int extent_order,
1107                                unsigned int mem_flags,
1108                                xen_pfn_t *extent_start)
1109 {
1110     int err;
1111     DECLARE_HYPERCALL_BOUNCE(extent_start, nr_extents * sizeof(*extent_start), XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
1112     struct xen_memory_reservation reservation = {
1113         .nr_extents   = nr_extents,
1114         .extent_order = extent_order,
1115         .mem_flags    = mem_flags,
1116         .domid        = domid
1117     };
1118 
1119     if ( xc_hypercall_bounce_pre(xch, extent_start) )
1120     {
1121         PERROR("Could not bounce memory for XENMEM_populate_physmap hypercall");
1122         return -1;
1123     }
1124     set_xen_guest_handle(reservation.extent_start, extent_start);
1125 
1126     err = do_memory_op(xch, XENMEM_populate_physmap, &reservation, sizeof(reservation));
1127 
1128     xc_hypercall_bounce_post(xch, extent_start);
1129     return err;
1130 }
1131 
xc_domain_populate_physmap_exact(xc_interface * xch,uint32_t domid,unsigned long nr_extents,unsigned int extent_order,unsigned int mem_flags,xen_pfn_t * extent_start)1132 int xc_domain_populate_physmap_exact(xc_interface *xch,
1133                                      uint32_t domid,
1134                                      unsigned long nr_extents,
1135                                      unsigned int extent_order,
1136                                      unsigned int mem_flags,
1137                                      xen_pfn_t *extent_start)
1138 {
1139     int err;
1140 
1141     err = xc_domain_populate_physmap(xch, domid, nr_extents,
1142                                      extent_order, mem_flags, extent_start);
1143     if ( err == nr_extents )
1144         return 0;
1145 
1146     if ( err >= 0 )
1147     {
1148         DPRINTF("Failed allocation for dom %d: %ld extents of order %d\n",
1149                 domid, nr_extents, extent_order);
1150         errno = EBUSY;
1151         err = -1;
1152     }
1153 
1154     return err;
1155 }
1156 
xc_domain_memory_exchange_pages(xc_interface * xch,uint32_t domid,unsigned long nr_in_extents,unsigned int in_order,xen_pfn_t * in_extents,unsigned long nr_out_extents,unsigned int out_order,xen_pfn_t * out_extents)1157 int xc_domain_memory_exchange_pages(xc_interface *xch,
1158                                     uint32_t domid,
1159                                     unsigned long nr_in_extents,
1160                                     unsigned int in_order,
1161                                     xen_pfn_t *in_extents,
1162                                     unsigned long nr_out_extents,
1163                                     unsigned int out_order,
1164                                     xen_pfn_t *out_extents)
1165 {
1166     int rc = -1;
1167     DECLARE_HYPERCALL_BOUNCE(in_extents, nr_in_extents*sizeof(*in_extents), XC_HYPERCALL_BUFFER_BOUNCE_IN);
1168     DECLARE_HYPERCALL_BOUNCE(out_extents, nr_out_extents*sizeof(*out_extents), XC_HYPERCALL_BUFFER_BOUNCE_OUT);
1169     struct xen_memory_exchange exchange = {
1170         .in = {
1171             .nr_extents   = nr_in_extents,
1172             .extent_order = in_order,
1173             .domid        = domid
1174         },
1175         .out = {
1176             .nr_extents   = nr_out_extents,
1177             .extent_order = out_order,
1178             .domid        = domid
1179         }
1180     };
1181 
1182     if ( xc_hypercall_bounce_pre(xch, in_extents) ||
1183          xc_hypercall_bounce_pre(xch, out_extents))
1184         goto out;
1185 
1186     set_xen_guest_handle(exchange.in.extent_start, in_extents);
1187     set_xen_guest_handle(exchange.out.extent_start, out_extents);
1188 
1189     rc = do_memory_op(xch, XENMEM_exchange, &exchange, sizeof(exchange));
1190 
1191 out:
1192     xc_hypercall_bounce_post(xch, in_extents);
1193     xc_hypercall_bounce_post(xch, out_extents);
1194 
1195     return rc;
1196 }
1197 
1198 /* Currently only implemented on x86. This cannot be handled in the
1199  * caller, e.g. by looking for errno==ENOSYS because of the broken
1200  * error reporting style. Once this is fixed then this condition can
1201  * be removed.
1202  */
1203 #if defined(__i386__)||defined(__x86_64__)
xc_domain_pod_target(xc_interface * xch,int op,uint32_t domid,uint64_t target_pages,uint64_t * tot_pages,uint64_t * pod_cache_pages,uint64_t * pod_entries)1204 static int xc_domain_pod_target(xc_interface *xch,
1205                                 int op,
1206                                 uint32_t domid,
1207                                 uint64_t target_pages,
1208                                 uint64_t *tot_pages,
1209                                 uint64_t *pod_cache_pages,
1210                                 uint64_t *pod_entries)
1211 {
1212     int err;
1213 
1214     struct xen_pod_target pod_target = {
1215         .domid = domid,
1216         .target_pages = target_pages
1217     };
1218 
1219     err = do_memory_op(xch, op, &pod_target, sizeof(pod_target));
1220 
1221     if ( err < 0 )
1222     {
1223         DPRINTF("Failed %s_pod_target dom %d\n",
1224                 (op==XENMEM_set_pod_target)?"set":"get",
1225                 domid);
1226         errno = -err;
1227         err = -1;
1228     }
1229     else
1230         err = 0;
1231 
1232     if ( tot_pages )
1233         *tot_pages = pod_target.tot_pages;
1234     if ( pod_cache_pages )
1235         *pod_cache_pages = pod_target.pod_cache_pages;
1236     if ( pod_entries )
1237         *pod_entries = pod_target.pod_entries;
1238 
1239     return err;
1240 }
1241 
1242 
xc_domain_set_pod_target(xc_interface * xch,uint32_t domid,uint64_t target_pages,uint64_t * tot_pages,uint64_t * pod_cache_pages,uint64_t * pod_entries)1243 int xc_domain_set_pod_target(xc_interface *xch,
1244                              uint32_t domid,
1245                              uint64_t target_pages,
1246                              uint64_t *tot_pages,
1247                              uint64_t *pod_cache_pages,
1248                              uint64_t *pod_entries)
1249 {
1250     return xc_domain_pod_target(xch,
1251                                 XENMEM_set_pod_target,
1252                                 domid,
1253                                 target_pages,
1254                                 tot_pages,
1255                                 pod_cache_pages,
1256                                 pod_entries);
1257 }
1258 
xc_domain_get_pod_target(xc_interface * xch,uint32_t domid,uint64_t * tot_pages,uint64_t * pod_cache_pages,uint64_t * pod_entries)1259 int xc_domain_get_pod_target(xc_interface *xch,
1260                              uint32_t domid,
1261                              uint64_t *tot_pages,
1262                              uint64_t *pod_cache_pages,
1263                              uint64_t *pod_entries)
1264 {
1265     return xc_domain_pod_target(xch,
1266                                 XENMEM_get_pod_target,
1267                                 domid,
1268                                 -1,
1269                                 tot_pages,
1270                                 pod_cache_pages,
1271                                 pod_entries);
1272 }
1273 #else
xc_domain_set_pod_target(xc_interface * xch,uint32_t domid,uint64_t target_pages,uint64_t * tot_pages,uint64_t * pod_cache_pages,uint64_t * pod_entries)1274 int xc_domain_set_pod_target(xc_interface *xch,
1275                              uint32_t domid,
1276                              uint64_t target_pages,
1277                              uint64_t *tot_pages,
1278                              uint64_t *pod_cache_pages,
1279                              uint64_t *pod_entries)
1280 {
1281     return 0;
1282 }
xc_domain_get_pod_target(xc_interface * xch,uint32_t domid,uint64_t * tot_pages,uint64_t * pod_cache_pages,uint64_t * pod_entries)1283 int xc_domain_get_pod_target(xc_interface *xch,
1284                              uint32_t domid,
1285                              uint64_t *tot_pages,
1286                              uint64_t *pod_cache_pages,
1287                              uint64_t *pod_entries)
1288 {
1289     /* On x86 (above) xc_domain_pod_target will incorrectly return -1
1290      * with errno==-1 on error. Do the same for least surprise. */
1291     errno = -1;
1292     return -1;
1293 }
1294 #endif
1295 
xc_domain_max_vcpus(xc_interface * xch,uint32_t domid,unsigned int max)1296 int xc_domain_max_vcpus(xc_interface *xch, uint32_t domid, unsigned int max)
1297 {
1298     DECLARE_DOMCTL;
1299     domctl.cmd = XEN_DOMCTL_max_vcpus;
1300     domctl.domain = domid;
1301     domctl.u.max_vcpus.max    = max;
1302     return do_domctl(xch, &domctl);
1303 }
1304 
xc_domain_sethandle(xc_interface * xch,uint32_t domid,xen_domain_handle_t handle)1305 int xc_domain_sethandle(xc_interface *xch, uint32_t domid,
1306                         xen_domain_handle_t handle)
1307 {
1308     DECLARE_DOMCTL;
1309     domctl.cmd = XEN_DOMCTL_setdomainhandle;
1310     domctl.domain = domid;
1311     memcpy(domctl.u.setdomainhandle.handle, handle,
1312            sizeof(xen_domain_handle_t));
1313     return do_domctl(xch, &domctl);
1314 }
1315 
xc_vcpu_getinfo(xc_interface * xch,uint32_t domid,uint32_t vcpu,xc_vcpuinfo_t * info)1316 int xc_vcpu_getinfo(xc_interface *xch,
1317                     uint32_t domid,
1318                     uint32_t vcpu,
1319                     xc_vcpuinfo_t *info)
1320 {
1321     int rc;
1322     DECLARE_DOMCTL;
1323 
1324     domctl.cmd = XEN_DOMCTL_getvcpuinfo;
1325     domctl.domain = domid;
1326     domctl.u.getvcpuinfo.vcpu   = (uint16_t)vcpu;
1327 
1328     rc = do_domctl(xch, &domctl);
1329 
1330     memcpy(info, &domctl.u.getvcpuinfo, sizeof(*info));
1331 
1332     return rc;
1333 }
1334 
xc_domain_ioport_permission(xc_interface * xch,uint32_t domid,uint32_t first_port,uint32_t nr_ports,uint32_t allow_access)1335 int xc_domain_ioport_permission(xc_interface *xch,
1336                                 uint32_t domid,
1337                                 uint32_t first_port,
1338                                 uint32_t nr_ports,
1339                                 uint32_t allow_access)
1340 {
1341     DECLARE_DOMCTL;
1342 
1343     domctl.cmd = XEN_DOMCTL_ioport_permission;
1344     domctl.domain = domid;
1345     domctl.u.ioport_permission.first_port = first_port;
1346     domctl.u.ioport_permission.nr_ports = nr_ports;
1347     domctl.u.ioport_permission.allow_access = allow_access;
1348 
1349     return do_domctl(xch, &domctl);
1350 }
1351 
xc_availheap(xc_interface * xch,int min_width,int max_width,int node,uint64_t * bytes)1352 int xc_availheap(xc_interface *xch,
1353                  int min_width,
1354                  int max_width,
1355                  int node,
1356                  uint64_t *bytes)
1357 {
1358     DECLARE_SYSCTL;
1359     int rc;
1360 
1361     sysctl.cmd = XEN_SYSCTL_availheap;
1362     sysctl.u.availheap.min_bitwidth = min_width;
1363     sysctl.u.availheap.max_bitwidth = max_width;
1364     sysctl.u.availheap.node = node;
1365 
1366     rc = xc_sysctl(xch, &sysctl);
1367 
1368     *bytes = sysctl.u.availheap.avail_bytes;
1369 
1370     return rc;
1371 }
1372 
xc_vcpu_setcontext(xc_interface * xch,uint32_t domid,uint32_t vcpu,vcpu_guest_context_any_t * ctxt)1373 int xc_vcpu_setcontext(xc_interface *xch,
1374                        uint32_t domid,
1375                        uint32_t vcpu,
1376                        vcpu_guest_context_any_t *ctxt)
1377 {
1378     DECLARE_DOMCTL;
1379     DECLARE_HYPERCALL_BOUNCE(ctxt, sizeof(vcpu_guest_context_any_t), XC_HYPERCALL_BUFFER_BOUNCE_IN);
1380     int rc;
1381 
1382     if ( xc_hypercall_bounce_pre(xch, ctxt) )
1383         return -1;
1384 
1385     domctl.cmd = XEN_DOMCTL_setvcpucontext;
1386     domctl.domain = domid;
1387     domctl.u.vcpucontext.vcpu = vcpu;
1388     set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
1389 
1390     rc = do_domctl(xch, &domctl);
1391 
1392     xc_hypercall_bounce_post(xch, ctxt);
1393 
1394     return rc;
1395 }
1396 
xc_domain_irq_permission(xc_interface * xch,uint32_t domid,uint8_t pirq,uint8_t allow_access)1397 int xc_domain_irq_permission(xc_interface *xch,
1398                              uint32_t domid,
1399                              uint8_t pirq,
1400                              uint8_t allow_access)
1401 {
1402     DECLARE_DOMCTL;
1403 
1404     domctl.cmd = XEN_DOMCTL_irq_permission;
1405     domctl.domain = domid;
1406     domctl.u.irq_permission.pirq = pirq;
1407     domctl.u.irq_permission.allow_access = allow_access;
1408 
1409     return do_domctl(xch, &domctl);
1410 }
1411 
xc_domain_iomem_permission(xc_interface * xch,uint32_t domid,unsigned long first_mfn,unsigned long nr_mfns,uint8_t allow_access)1412 int xc_domain_iomem_permission(xc_interface *xch,
1413                                uint32_t domid,
1414                                unsigned long first_mfn,
1415                                unsigned long nr_mfns,
1416                                uint8_t allow_access)
1417 {
1418     DECLARE_DOMCTL;
1419 
1420     domctl.cmd = XEN_DOMCTL_iomem_permission;
1421     domctl.domain = domid;
1422     domctl.u.iomem_permission.first_mfn = first_mfn;
1423     domctl.u.iomem_permission.nr_mfns = nr_mfns;
1424     domctl.u.iomem_permission.allow_access = allow_access;
1425 
1426     return do_domctl(xch, &domctl);
1427 }
1428 
xc_domain_send_trigger(xc_interface * xch,uint32_t domid,uint32_t trigger,uint32_t vcpu)1429 int xc_domain_send_trigger(xc_interface *xch,
1430                            uint32_t domid,
1431                            uint32_t trigger,
1432                            uint32_t vcpu)
1433 {
1434     DECLARE_DOMCTL;
1435 
1436     domctl.cmd = XEN_DOMCTL_sendtrigger;
1437     domctl.domain = domid;
1438     domctl.u.sendtrigger.trigger = trigger;
1439     domctl.u.sendtrigger.vcpu = vcpu;
1440 
1441     return do_domctl(xch, &domctl);
1442 }
1443 
xc_hvm_param_set(xc_interface * handle,uint32_t dom,uint32_t param,uint64_t value)1444 int xc_hvm_param_set(xc_interface *handle, uint32_t dom, uint32_t param, uint64_t value)
1445 {
1446     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
1447     int rc;
1448 
1449     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
1450     if ( arg == NULL )
1451         return -1;
1452 
1453     arg->domid = dom;
1454     arg->index = param;
1455     arg->value = value;
1456     rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op,
1457                   HVMOP_set_param,
1458                   HYPERCALL_BUFFER_AS_ARG(arg));
1459     xc_hypercall_buffer_free(handle, arg);
1460     return rc;
1461 }
1462 
xc_hvm_param_get(xc_interface * handle,uint32_t dom,uint32_t param,uint64_t * value)1463 int xc_hvm_param_get(xc_interface *handle, uint32_t dom, uint32_t param, uint64_t *value)
1464 {
1465     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
1466     int rc;
1467 
1468     arg = xc_hypercall_buffer_alloc(handle, arg, sizeof(*arg));
1469     if ( arg == NULL )
1470         return -1;
1471 
1472     arg->domid = dom;
1473     arg->index = param;
1474     rc = xencall2(handle->xcall, __HYPERVISOR_hvm_op,
1475                   HVMOP_get_param,
1476                   HYPERCALL_BUFFER_AS_ARG(arg));
1477     *value = arg->value;
1478     xc_hypercall_buffer_free(handle, arg);
1479     return rc;
1480 }
1481 
xc_set_hvm_param(xc_interface * handle,uint32_t dom,int param,unsigned long value)1482 int xc_set_hvm_param(xc_interface *handle, uint32_t dom, int param, unsigned long value)
1483 {
1484     return xc_hvm_param_set(handle, dom, param, value);
1485 }
1486 
xc_get_hvm_param(xc_interface * handle,uint32_t dom,int param,unsigned long * value)1487 int xc_get_hvm_param(xc_interface *handle, uint32_t dom, int param, unsigned long *value)
1488 {
1489     uint64_t v;
1490     int ret;
1491 
1492     ret = xc_hvm_param_get(handle, dom, param, &v);
1493     if (ret < 0)
1494         return ret;
1495     *value = v;
1496     return 0;
1497 }
1498 
xc_domain_setdebugging(xc_interface * xch,uint32_t domid,unsigned int enable)1499 int xc_domain_setdebugging(xc_interface *xch,
1500                            uint32_t domid,
1501                            unsigned int enable)
1502 {
1503     DECLARE_DOMCTL;
1504 
1505     domctl.cmd = XEN_DOMCTL_setdebugging;
1506     domctl.domain = domid;
1507     domctl.u.setdebugging.enable = enable;
1508     return do_domctl(xch, &domctl);
1509 }
1510 
xc_assign_device(xc_interface * xch,uint32_t domid,uint32_t machine_sbdf,uint32_t flags)1511 int xc_assign_device(
1512     xc_interface *xch,
1513     uint32_t domid,
1514     uint32_t machine_sbdf,
1515     uint32_t flags)
1516 {
1517     DECLARE_DOMCTL;
1518 
1519     domctl.cmd = XEN_DOMCTL_assign_device;
1520     domctl.domain = domid;
1521     domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI;
1522     domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf;
1523     domctl.u.assign_device.flags = flags;
1524 
1525     return do_domctl(xch, &domctl);
1526 }
1527 
xc_get_device_group(xc_interface * xch,uint32_t domid,uint32_t machine_sbdf,uint32_t max_sdevs,uint32_t * num_sdevs,uint32_t * sdev_array)1528 int xc_get_device_group(
1529     xc_interface *xch,
1530     uint32_t domid,
1531     uint32_t machine_sbdf,
1532     uint32_t max_sdevs,
1533     uint32_t *num_sdevs,
1534     uint32_t *sdev_array)
1535 {
1536     int rc;
1537     DECLARE_DOMCTL;
1538     DECLARE_HYPERCALL_BOUNCE(sdev_array, max_sdevs * sizeof(*sdev_array), XC_HYPERCALL_BUFFER_BOUNCE_IN);
1539 
1540     if ( xc_hypercall_bounce_pre(xch, sdev_array) )
1541     {
1542         PERROR("Could not bounce buffer for xc_get_device_group");
1543         return -1;
1544     }
1545 
1546     domctl.cmd = XEN_DOMCTL_get_device_group;
1547     domctl.domain = domid;
1548 
1549     domctl.u.get_device_group.machine_sbdf = machine_sbdf;
1550     domctl.u.get_device_group.max_sdevs = max_sdevs;
1551 
1552     set_xen_guest_handle(domctl.u.get_device_group.sdev_array, sdev_array);
1553 
1554     rc = do_domctl(xch, &domctl);
1555 
1556     *num_sdevs = domctl.u.get_device_group.num_sdevs;
1557 
1558     xc_hypercall_bounce_post(xch, sdev_array);
1559 
1560     return rc;
1561 }
1562 
xc_test_assign_device(xc_interface * xch,uint32_t domid,uint32_t machine_sbdf)1563 int xc_test_assign_device(
1564     xc_interface *xch,
1565     uint32_t domid,
1566     uint32_t machine_sbdf)
1567 {
1568     DECLARE_DOMCTL;
1569 
1570     domctl.cmd = XEN_DOMCTL_test_assign_device;
1571     domctl.domain = domid;
1572     domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI;
1573     domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf;
1574     domctl.u.assign_device.flags = 0;
1575 
1576     return do_domctl(xch, &domctl);
1577 }
1578 
xc_deassign_device(xc_interface * xch,uint32_t domid,uint32_t machine_sbdf)1579 int xc_deassign_device(
1580     xc_interface *xch,
1581     uint32_t domid,
1582     uint32_t machine_sbdf)
1583 {
1584     DECLARE_DOMCTL;
1585 
1586     domctl.cmd = XEN_DOMCTL_deassign_device;
1587     domctl.domain = domid;
1588     domctl.u.assign_device.dev = XEN_DOMCTL_DEV_PCI;
1589     domctl.u.assign_device.u.pci.machine_sbdf = machine_sbdf;
1590     domctl.u.assign_device.flags = 0;
1591 
1592     return do_domctl(xch, &domctl);
1593 }
1594 
xc_assign_dt_device(xc_interface * xch,uint32_t domid,char * path)1595 int xc_assign_dt_device(
1596     xc_interface *xch,
1597     uint32_t domid,
1598     char *path)
1599 {
1600     int rc;
1601     size_t size = strlen(path);
1602     DECLARE_DOMCTL;
1603     DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN);
1604 
1605     if ( xc_hypercall_bounce_pre(xch, path) )
1606         return -1;
1607 
1608     domctl.cmd = XEN_DOMCTL_assign_device;
1609     domctl.domain = domid;
1610 
1611     domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT;
1612     domctl.u.assign_device.u.dt.size = size;
1613     /*
1614      * DT doesn't own any RDM so actually DT has nothing to do
1615      * for any flag and here just fix that as 0.
1616      */
1617     domctl.u.assign_device.flags = 0;
1618     set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path);
1619 
1620     rc = do_domctl(xch, &domctl);
1621 
1622     xc_hypercall_bounce_post(xch, path);
1623 
1624     return rc;
1625 }
1626 
xc_test_assign_dt_device(xc_interface * xch,uint32_t domid,char * path)1627 int xc_test_assign_dt_device(
1628     xc_interface *xch,
1629     uint32_t domid,
1630     char *path)
1631 {
1632     int rc;
1633     size_t size = strlen(path);
1634     DECLARE_DOMCTL;
1635     DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN);
1636 
1637     if ( xc_hypercall_bounce_pre(xch, path) )
1638         return -1;
1639 
1640     domctl.cmd = XEN_DOMCTL_test_assign_device;
1641     domctl.domain = domid;
1642 
1643     domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT;
1644     domctl.u.assign_device.u.dt.size = size;
1645     set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path);
1646     domctl.u.assign_device.flags = 0;
1647 
1648     rc = do_domctl(xch, &domctl);
1649 
1650     xc_hypercall_bounce_post(xch, path);
1651 
1652     return rc;
1653 }
1654 
xc_deassign_dt_device(xc_interface * xch,uint32_t domid,char * path)1655 int xc_deassign_dt_device(
1656     xc_interface *xch,
1657     uint32_t domid,
1658     char *path)
1659 {
1660     int rc;
1661     size_t size = strlen(path);
1662     DECLARE_DOMCTL;
1663     DECLARE_HYPERCALL_BOUNCE(path, size, XC_HYPERCALL_BUFFER_BOUNCE_IN);
1664 
1665     if ( xc_hypercall_bounce_pre(xch, path) )
1666         return -1;
1667 
1668     domctl.cmd = XEN_DOMCTL_deassign_device;
1669     domctl.domain = domid;
1670 
1671     domctl.u.assign_device.dev = XEN_DOMCTL_DEV_DT;
1672     domctl.u.assign_device.u.dt.size = size;
1673     set_xen_guest_handle(domctl.u.assign_device.u.dt.path, path);
1674     domctl.u.assign_device.flags = 0;
1675 
1676     rc = do_domctl(xch, &domctl);
1677 
1678     xc_hypercall_bounce_post(xch, path);
1679 
1680     return rc;
1681 }
1682 
1683 
1684 
1685 
xc_domain_update_msi_irq(xc_interface * xch,uint32_t domid,uint32_t gvec,uint32_t pirq,uint32_t gflags,uint64_t gtable)1686 int xc_domain_update_msi_irq(
1687     xc_interface *xch,
1688     uint32_t domid,
1689     uint32_t gvec,
1690     uint32_t pirq,
1691     uint32_t gflags,
1692     uint64_t gtable)
1693 {
1694     int rc;
1695     struct xen_domctl_bind_pt_irq *bind;
1696     DECLARE_DOMCTL;
1697 
1698     domctl.cmd = XEN_DOMCTL_bind_pt_irq;
1699     domctl.domain = domid;
1700 
1701     bind = &(domctl.u.bind_pt_irq);
1702     bind->irq_type = PT_IRQ_TYPE_MSI;
1703     bind->machine_irq = pirq;
1704     bind->u.msi.gvec = gvec;
1705     bind->u.msi.gflags = gflags;
1706     bind->u.msi.gtable = gtable;
1707 
1708     rc = do_domctl(xch, &domctl);
1709     return rc;
1710 }
1711 
xc_domain_unbind_msi_irq(xc_interface * xch,uint32_t domid,uint32_t gvec,uint32_t pirq,uint32_t gflags)1712 int xc_domain_unbind_msi_irq(
1713     xc_interface *xch,
1714     uint32_t domid,
1715     uint32_t gvec,
1716     uint32_t pirq,
1717     uint32_t gflags)
1718 {
1719     int rc;
1720     struct xen_domctl_bind_pt_irq *bind;
1721     DECLARE_DOMCTL;
1722 
1723     domctl.cmd = XEN_DOMCTL_unbind_pt_irq;
1724     domctl.domain = domid;
1725 
1726     bind = &(domctl.u.bind_pt_irq);
1727     bind->irq_type = PT_IRQ_TYPE_MSI;
1728     bind->machine_irq = pirq;
1729     bind->u.msi.gvec = gvec;
1730     bind->u.msi.gflags = gflags;
1731 
1732     rc = do_domctl(xch, &domctl);
1733     return rc;
1734 }
1735 
1736 /* Pass-through: binds machine irq to guests irq */
xc_domain_bind_pt_irq_int(xc_interface * xch,uint32_t domid,uint32_t machine_irq,uint8_t irq_type,uint8_t bus,uint8_t device,uint8_t intx,uint8_t isa_irq,uint16_t spi)1737 static int xc_domain_bind_pt_irq_int(
1738     xc_interface *xch,
1739     uint32_t domid,
1740     uint32_t machine_irq,
1741     uint8_t irq_type,
1742     uint8_t bus,
1743     uint8_t device,
1744     uint8_t intx,
1745     uint8_t isa_irq,
1746     uint16_t spi)
1747 {
1748     int rc;
1749     struct xen_domctl_bind_pt_irq *bind;
1750     DECLARE_DOMCTL;
1751 
1752     domctl.cmd = XEN_DOMCTL_bind_pt_irq;
1753     domctl.domain = domid;
1754 
1755     bind = &(domctl.u.bind_pt_irq);
1756     bind->irq_type = irq_type;
1757     bind->machine_irq = machine_irq;
1758     switch ( irq_type )
1759     {
1760     case PT_IRQ_TYPE_PCI:
1761     case PT_IRQ_TYPE_MSI_TRANSLATE:
1762         bind->u.pci.bus = bus;
1763         bind->u.pci.device = device;
1764         bind->u.pci.intx = intx;
1765         break;
1766     case PT_IRQ_TYPE_ISA:
1767         bind->u.isa.isa_irq = isa_irq;
1768         break;
1769     case PT_IRQ_TYPE_SPI:
1770         bind->u.spi.spi = spi;
1771         break;
1772     default:
1773         errno = EINVAL;
1774         return -1;
1775     }
1776 
1777     rc = do_domctl(xch, &domctl);
1778     return rc;
1779 }
1780 
xc_domain_bind_pt_irq(xc_interface * xch,uint32_t domid,uint8_t machine_irq,uint8_t irq_type,uint8_t bus,uint8_t device,uint8_t intx,uint8_t isa_irq)1781 int xc_domain_bind_pt_irq(
1782     xc_interface *xch,
1783     uint32_t domid,
1784     uint8_t machine_irq,
1785     uint8_t irq_type,
1786     uint8_t bus,
1787     uint8_t device,
1788     uint8_t intx,
1789     uint8_t isa_irq)
1790 {
1791     return xc_domain_bind_pt_irq_int(xch, domid, machine_irq, irq_type,
1792                                      bus, device, intx, isa_irq, 0);
1793 }
1794 
xc_domain_unbind_pt_irq_int(xc_interface * xch,uint32_t domid,uint32_t machine_irq,uint8_t irq_type,uint8_t bus,uint8_t device,uint8_t intx,uint8_t isa_irq,uint8_t spi)1795 static int xc_domain_unbind_pt_irq_int(
1796     xc_interface *xch,
1797     uint32_t domid,
1798     uint32_t machine_irq,
1799     uint8_t irq_type,
1800     uint8_t bus,
1801     uint8_t device,
1802     uint8_t intx,
1803     uint8_t isa_irq,
1804     uint8_t spi)
1805 {
1806     int rc;
1807     struct xen_domctl_bind_pt_irq *bind;
1808     DECLARE_DOMCTL;
1809 
1810     domctl.cmd = XEN_DOMCTL_unbind_pt_irq;
1811     domctl.domain = domid;
1812 
1813     bind = &(domctl.u.bind_pt_irq);
1814     bind->irq_type = irq_type;
1815     bind->machine_irq = machine_irq;
1816     switch ( irq_type )
1817     {
1818     case PT_IRQ_TYPE_PCI:
1819     case PT_IRQ_TYPE_MSI_TRANSLATE:
1820         bind->u.pci.bus = bus;
1821         bind->u.pci.device = device;
1822         bind->u.pci.intx = intx;
1823         break;
1824     case PT_IRQ_TYPE_ISA:
1825         bind->u.isa.isa_irq = isa_irq;
1826         break;
1827     case PT_IRQ_TYPE_SPI:
1828         bind->u.spi.spi = spi;
1829         break;
1830     default:
1831         errno = EINVAL;
1832         return -1;
1833     }
1834 
1835     rc = do_domctl(xch, &domctl);
1836     return rc;
1837 }
1838 
xc_domain_unbind_pt_irq(xc_interface * xch,uint32_t domid,uint8_t machine_irq,uint8_t irq_type,uint8_t bus,uint8_t device,uint8_t intx,uint8_t isa_irq)1839 int xc_domain_unbind_pt_irq(
1840     xc_interface *xch,
1841     uint32_t domid,
1842     uint8_t machine_irq,
1843     uint8_t irq_type,
1844     uint8_t bus,
1845     uint8_t device,
1846     uint8_t intx,
1847     uint8_t isa_irq)
1848 {
1849     return xc_domain_unbind_pt_irq_int(xch, domid, machine_irq, irq_type,
1850                                        bus, device, intx, isa_irq, 0);
1851 }
1852 
xc_domain_bind_pt_pci_irq(xc_interface * xch,uint32_t domid,uint8_t machine_irq,uint8_t bus,uint8_t device,uint8_t intx)1853 int xc_domain_bind_pt_pci_irq(
1854     xc_interface *xch,
1855     uint32_t domid,
1856     uint8_t machine_irq,
1857     uint8_t bus,
1858     uint8_t device,
1859     uint8_t intx)
1860 {
1861 
1862     return (xc_domain_bind_pt_irq(xch, domid, machine_irq,
1863                                   PT_IRQ_TYPE_PCI, bus, device, intx, 0));
1864 }
1865 
xc_domain_bind_pt_isa_irq(xc_interface * xch,uint32_t domid,uint8_t machine_irq)1866 int xc_domain_bind_pt_isa_irq(
1867     xc_interface *xch,
1868     uint32_t domid,
1869     uint8_t machine_irq)
1870 {
1871 
1872     return (xc_domain_bind_pt_irq(xch, domid, machine_irq,
1873                                   PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq));
1874 }
1875 
xc_domain_bind_pt_spi_irq(xc_interface * xch,uint32_t domid,uint16_t vspi,uint16_t spi)1876 int xc_domain_bind_pt_spi_irq(
1877     xc_interface *xch,
1878     uint32_t domid,
1879     uint16_t vspi,
1880     uint16_t spi)
1881 {
1882     return (xc_domain_bind_pt_irq_int(xch, domid, vspi,
1883                                       PT_IRQ_TYPE_SPI, 0, 0, 0, 0, spi));
1884 }
1885 
xc_domain_unbind_pt_spi_irq(xc_interface * xch,uint32_t domid,uint16_t vspi,uint16_t spi)1886 int xc_domain_unbind_pt_spi_irq(xc_interface *xch,
1887                                 uint32_t domid,
1888                                 uint16_t vspi,
1889                                 uint16_t spi)
1890 {
1891     return (xc_domain_unbind_pt_irq_int(xch, domid, vspi,
1892                                         PT_IRQ_TYPE_SPI, 0, 0, 0, 0, spi));
1893 }
1894 
xc_unmap_domain_meminfo(xc_interface * xch,struct xc_domain_meminfo * minfo)1895 int xc_unmap_domain_meminfo(xc_interface *xch, struct xc_domain_meminfo *minfo)
1896 {
1897     struct domain_info_context _di = { .guest_width = minfo->guest_width,
1898                                        .p2m_size = minfo->p2m_size};
1899     struct domain_info_context *dinfo = &_di;
1900 
1901     free(minfo->pfn_type);
1902     if ( minfo->p2m_table )
1903         munmap(minfo->p2m_table, P2M_FL_ENTRIES * PAGE_SIZE);
1904     minfo->p2m_table = NULL;
1905 
1906     return 0;
1907 }
1908 
xc_map_domain_meminfo(xc_interface * xch,uint32_t domid,struct xc_domain_meminfo * minfo)1909 int xc_map_domain_meminfo(xc_interface *xch, uint32_t domid,
1910                           struct xc_domain_meminfo *minfo)
1911 {
1912     struct domain_info_context _di;
1913     struct domain_info_context *dinfo = &_di;
1914 
1915     xc_dominfo_t info;
1916     shared_info_any_t *live_shinfo;
1917     xen_capabilities_info_t xen_caps = "";
1918     int i;
1919 
1920     /* Only be initialized once */
1921     if ( minfo->pfn_type || minfo->p2m_table )
1922     {
1923         errno = EINVAL;
1924         return -1;
1925     }
1926 
1927     if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 )
1928     {
1929         PERROR("Could not get domain info");
1930         return -1;
1931     }
1932 
1933     if ( xc_domain_get_guest_width(xch, domid, &minfo->guest_width) )
1934     {
1935         PERROR("Could not get domain address size");
1936         return -1;
1937     }
1938     _di.guest_width = minfo->guest_width;
1939 
1940     /* Get page table levels (see get_platform_info() in xg_save_restore.h */
1941     if ( xc_version(xch, XENVER_capabilities, &xen_caps) )
1942     {
1943         PERROR("Could not get Xen capabilities (for page table levels)");
1944         return -1;
1945     }
1946     if ( strstr(xen_caps, "xen-3.0-x86_64") )
1947         /* Depends on whether it's a compat 32-on-64 guest */
1948         minfo->pt_levels = ( (minfo->guest_width == 8) ? 4 : 3 );
1949     else if ( strstr(xen_caps, "xen-3.0-x86_32p") )
1950         minfo->pt_levels = 3;
1951     else if ( strstr(xen_caps, "xen-3.0-x86_32") )
1952         minfo->pt_levels = 2;
1953     else
1954     {
1955         errno = EFAULT;
1956         return -1;
1957     }
1958 
1959     /* We need the shared info page for mapping the P2M */
1960     live_shinfo = xc_map_foreign_range(xch, domid, PAGE_SIZE, PROT_READ,
1961                                        info.shared_info_frame);
1962     if ( !live_shinfo )
1963     {
1964         PERROR("Could not map the shared info frame (MFN 0x%lx)",
1965                info.shared_info_frame);
1966         return -1;
1967     }
1968 
1969     if ( xc_core_arch_map_p2m_writable(xch, minfo->guest_width, &info,
1970                                        live_shinfo, &minfo->p2m_table,
1971                                        &minfo->p2m_size) )
1972     {
1973         PERROR("Could not map the P2M table");
1974         munmap(live_shinfo, PAGE_SIZE);
1975         return -1;
1976     }
1977     munmap(live_shinfo, PAGE_SIZE);
1978     _di.p2m_size = minfo->p2m_size;
1979 
1980     /* Make space and prepare for getting the PFN types */
1981     minfo->pfn_type = calloc(sizeof(*minfo->pfn_type), minfo->p2m_size);
1982     if ( !minfo->pfn_type )
1983     {
1984         PERROR("Could not allocate memory for the PFN types");
1985         goto failed;
1986     }
1987     for ( i = 0; i < minfo->p2m_size; i++ )
1988         minfo->pfn_type[i] = xc_pfn_to_mfn(i, minfo->p2m_table,
1989                                            minfo->guest_width);
1990 
1991     /* Retrieve PFN types in batches */
1992     for ( i = 0; i < minfo->p2m_size ; i+=1024 )
1993     {
1994         int count = ((minfo->p2m_size - i ) > 1024 ) ?
1995                         1024: (minfo->p2m_size - i);
1996 
1997         if ( xc_get_pfn_type_batch(xch, domid, count, minfo->pfn_type + i) )
1998         {
1999             PERROR("Could not get %d-eth batch of PFN types", (i+1)/1024);
2000             goto failed;
2001         }
2002     }
2003 
2004     return 0;
2005 
2006 failed:
2007     if ( minfo->pfn_type )
2008     {
2009         free(minfo->pfn_type);
2010         minfo->pfn_type = NULL;
2011     }
2012     if ( minfo->p2m_table )
2013     {
2014         munmap(minfo->p2m_table, P2M_FL_ENTRIES * PAGE_SIZE);
2015         minfo->p2m_table = NULL;
2016     }
2017 
2018     return -1;
2019 }
2020 
xc_domain_memory_mapping(xc_interface * xch,uint32_t domid,unsigned long first_gfn,unsigned long first_mfn,unsigned long nr_mfns,uint32_t add_mapping)2021 int xc_domain_memory_mapping(
2022     xc_interface *xch,
2023     uint32_t domid,
2024     unsigned long first_gfn,
2025     unsigned long first_mfn,
2026     unsigned long nr_mfns,
2027     uint32_t add_mapping)
2028 {
2029     DECLARE_DOMCTL;
2030     xc_dominfo_t info;
2031     int ret = 0, rc;
2032     unsigned long done = 0, nr, max_batch_sz;
2033 
2034     if ( xc_domain_getinfo(xch, domid, 1, &info) != 1 ||
2035          info.domid != domid )
2036     {
2037         PERROR("Could not get info for domain");
2038         return -EINVAL;
2039     }
2040     if ( !xc_core_arch_auto_translated_physmap(&info) )
2041         return 0;
2042 
2043     if ( !nr_mfns )
2044         return 0;
2045 
2046     domctl.cmd = XEN_DOMCTL_memory_mapping;
2047     domctl.domain = domid;
2048     domctl.u.memory_mapping.add_mapping = add_mapping;
2049     max_batch_sz = nr_mfns;
2050     do
2051     {
2052         nr = min_t(unsigned long, nr_mfns - done, max_batch_sz);
2053         domctl.u.memory_mapping.nr_mfns = nr;
2054         domctl.u.memory_mapping.first_gfn = first_gfn + done;
2055         domctl.u.memory_mapping.first_mfn = first_mfn + done;
2056         rc = do_domctl(xch, &domctl);
2057         if ( rc < 0 && errno == E2BIG )
2058         {
2059             if ( max_batch_sz <= 1 )
2060                 break;
2061             max_batch_sz >>= 1;
2062             continue;
2063         }
2064         if ( rc > 0 )
2065         {
2066             done += rc;
2067             continue;
2068         }
2069         /* Save the first error... */
2070         if ( !ret )
2071             ret = rc;
2072         /* .. and ignore the rest of them when removing. */
2073         if ( rc && add_mapping != DPCI_REMOVE_MAPPING )
2074             break;
2075 
2076         done += nr;
2077     } while ( done < nr_mfns );
2078 
2079     /*
2080      * Undo what we have done unless unmapping, by unmapping the entire region.
2081      * Errors here are ignored.
2082      */
2083     if ( ret && add_mapping != DPCI_REMOVE_MAPPING )
2084         xc_domain_memory_mapping(xch, domid, first_gfn, first_mfn, nr_mfns,
2085                                  DPCI_REMOVE_MAPPING);
2086 
2087     /* We might get E2BIG so many times that we never advance. */
2088     if ( !done && !ret )
2089         ret = -1;
2090 
2091     return ret;
2092 }
2093 
xc_domain_ioport_mapping(xc_interface * xch,uint32_t domid,uint32_t first_gport,uint32_t first_mport,uint32_t nr_ports,uint32_t add_mapping)2094 int xc_domain_ioport_mapping(
2095     xc_interface *xch,
2096     uint32_t domid,
2097     uint32_t first_gport,
2098     uint32_t first_mport,
2099     uint32_t nr_ports,
2100     uint32_t add_mapping)
2101 {
2102     DECLARE_DOMCTL;
2103 
2104     domctl.cmd = XEN_DOMCTL_ioport_mapping;
2105     domctl.domain = domid;
2106     domctl.u.ioport_mapping.first_gport = first_gport;
2107     domctl.u.ioport_mapping.first_mport = first_mport;
2108     domctl.u.ioport_mapping.nr_ports = nr_ports;
2109     domctl.u.ioport_mapping.add_mapping = add_mapping;
2110 
2111     return do_domctl(xch, &domctl);
2112 }
2113 
xc_domain_set_target(xc_interface * xch,uint32_t domid,uint32_t target)2114 int xc_domain_set_target(
2115     xc_interface *xch,
2116     uint32_t domid,
2117     uint32_t target)
2118 {
2119     DECLARE_DOMCTL;
2120 
2121     domctl.cmd = XEN_DOMCTL_set_target;
2122     domctl.domain = domid;
2123     domctl.u.set_target.target = target;
2124 
2125     return do_domctl(xch, &domctl);
2126 }
2127 
xc_domain_subscribe_for_suspend(xc_interface * xch,uint32_t dom,evtchn_port_t port)2128 int xc_domain_subscribe_for_suspend(
2129     xc_interface *xch, uint32_t dom, evtchn_port_t port)
2130 {
2131     DECLARE_DOMCTL;
2132 
2133     domctl.cmd = XEN_DOMCTL_subscribe;
2134     domctl.domain = dom;
2135     domctl.u.subscribe.port = port;
2136 
2137     return do_domctl(xch, &domctl);
2138 }
2139 
xc_domain_debug_control(xc_interface * xc,uint32_t domid,uint32_t sop,uint32_t vcpu)2140 int xc_domain_debug_control(xc_interface *xc, uint32_t domid, uint32_t sop, uint32_t vcpu)
2141 {
2142     DECLARE_DOMCTL;
2143 
2144     memset(&domctl, 0, sizeof(domctl));
2145     domctl.domain = domid;
2146     domctl.cmd = XEN_DOMCTL_debug_op;
2147     domctl.u.debug_op.op     = sop;
2148     domctl.u.debug_op.vcpu   = vcpu;
2149 
2150     return do_domctl(xc, &domctl);
2151 }
2152 
xc_domain_p2m_audit(xc_interface * xch,uint32_t domid,uint64_t * orphans,uint64_t * m2p_bad,uint64_t * p2m_bad)2153 int xc_domain_p2m_audit(xc_interface *xch,
2154                         uint32_t domid,
2155                         uint64_t *orphans,
2156                         uint64_t *m2p_bad,
2157                         uint64_t *p2m_bad)
2158 {
2159     DECLARE_DOMCTL;
2160     int rc;
2161 
2162     domctl.cmd = XEN_DOMCTL_audit_p2m;
2163     domctl.domain = domid;
2164     rc = do_domctl(xch, &domctl);
2165 
2166     *orphans = domctl.u.audit_p2m.orphans;
2167     *m2p_bad = domctl.u.audit_p2m.m2p_bad;
2168     *p2m_bad = domctl.u.audit_p2m.p2m_bad;
2169 
2170     return rc;
2171 }
2172 
xc_domain_set_access_required(xc_interface * xch,uint32_t domid,unsigned int required)2173 int xc_domain_set_access_required(xc_interface *xch,
2174                                   uint32_t domid,
2175                                   unsigned int required)
2176 {
2177     DECLARE_DOMCTL;
2178 
2179     domctl.cmd = XEN_DOMCTL_set_access_required;
2180     domctl.domain = domid;
2181     domctl.u.access_required.access_required = required;
2182     return do_domctl(xch, &domctl);
2183 }
2184 
xc_domain_set_virq_handler(xc_interface * xch,uint32_t domid,int virq)2185 int xc_domain_set_virq_handler(xc_interface *xch, uint32_t domid, int virq)
2186 {
2187     DECLARE_DOMCTL;
2188 
2189     domctl.cmd = XEN_DOMCTL_set_virq_handler;
2190     domctl.domain = domid;
2191     domctl.u.set_virq_handler.virq = virq;
2192     return do_domctl(xch, &domctl);
2193 }
2194 
2195 /* Plumbing Xen with vNUMA topology */
xc_domain_setvnuma(xc_interface * xch,uint32_t domid,uint32_t nr_vnodes,uint32_t nr_vmemranges,uint32_t nr_vcpus,xen_vmemrange_t * vmemrange,unsigned int * vdistance,unsigned int * vcpu_to_vnode,unsigned int * vnode_to_pnode)2196 int xc_domain_setvnuma(xc_interface *xch,
2197                        uint32_t domid,
2198                        uint32_t nr_vnodes,
2199                        uint32_t nr_vmemranges,
2200                        uint32_t nr_vcpus,
2201                        xen_vmemrange_t *vmemrange,
2202                        unsigned int *vdistance,
2203                        unsigned int *vcpu_to_vnode,
2204                        unsigned int *vnode_to_pnode)
2205 {
2206     int rc;
2207     DECLARE_DOMCTL;
2208     DECLARE_HYPERCALL_BOUNCE(vmemrange, sizeof(*vmemrange) * nr_vmemranges,
2209                              XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
2210     DECLARE_HYPERCALL_BOUNCE(vdistance, sizeof(*vdistance) *
2211                              nr_vnodes * nr_vnodes,
2212                              XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
2213     DECLARE_HYPERCALL_BOUNCE(vcpu_to_vnode, sizeof(*vcpu_to_vnode) * nr_vcpus,
2214                              XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
2215     DECLARE_HYPERCALL_BOUNCE(vnode_to_pnode, sizeof(*vnode_to_pnode) *
2216                              nr_vnodes,
2217                              XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
2218     errno = EINVAL;
2219 
2220     if ( nr_vnodes == 0 || nr_vmemranges == 0 || nr_vcpus == 0 )
2221         return -1;
2222 
2223     if ( !vdistance || !vcpu_to_vnode || !vmemrange || !vnode_to_pnode )
2224     {
2225         PERROR("%s: Cant set vnuma without initializing topology", __func__);
2226         return -1;
2227     }
2228 
2229     if ( xc_hypercall_bounce_pre(xch, vmemrange)      ||
2230          xc_hypercall_bounce_pre(xch, vdistance)      ||
2231          xc_hypercall_bounce_pre(xch, vcpu_to_vnode)  ||
2232          xc_hypercall_bounce_pre(xch, vnode_to_pnode) )
2233     {
2234         rc = -1;
2235         goto vnumaset_fail;
2236 
2237     }
2238 
2239     set_xen_guest_handle(domctl.u.vnuma.vmemrange, vmemrange);
2240     set_xen_guest_handle(domctl.u.vnuma.vdistance, vdistance);
2241     set_xen_guest_handle(domctl.u.vnuma.vcpu_to_vnode, vcpu_to_vnode);
2242     set_xen_guest_handle(domctl.u.vnuma.vnode_to_pnode, vnode_to_pnode);
2243 
2244     domctl.cmd = XEN_DOMCTL_setvnumainfo;
2245     domctl.domain = domid;
2246     domctl.u.vnuma.nr_vnodes = nr_vnodes;
2247     domctl.u.vnuma.nr_vmemranges = nr_vmemranges;
2248     domctl.u.vnuma.nr_vcpus = nr_vcpus;
2249     domctl.u.vnuma.pad = 0;
2250 
2251     rc = do_domctl(xch, &domctl);
2252 
2253  vnumaset_fail:
2254     xc_hypercall_bounce_post(xch, vmemrange);
2255     xc_hypercall_bounce_post(xch, vdistance);
2256     xc_hypercall_bounce_post(xch, vcpu_to_vnode);
2257     xc_hypercall_bounce_post(xch, vnode_to_pnode);
2258 
2259     return rc;
2260 }
2261 
xc_domain_getvnuma(xc_interface * xch,uint32_t domid,uint32_t * nr_vnodes,uint32_t * nr_vmemranges,uint32_t * nr_vcpus,xen_vmemrange_t * vmemrange,unsigned int * vdistance,unsigned int * vcpu_to_vnode)2262 int xc_domain_getvnuma(xc_interface *xch,
2263                        uint32_t domid,
2264                        uint32_t *nr_vnodes,
2265                        uint32_t *nr_vmemranges,
2266                        uint32_t *nr_vcpus,
2267                        xen_vmemrange_t *vmemrange,
2268                        unsigned int *vdistance,
2269                        unsigned int *vcpu_to_vnode)
2270 {
2271     int rc;
2272     DECLARE_HYPERCALL_BOUNCE(vmemrange, sizeof(*vmemrange) * *nr_vmemranges,
2273                              XC_HYPERCALL_BUFFER_BOUNCE_OUT);
2274     DECLARE_HYPERCALL_BOUNCE(vdistance, sizeof(*vdistance) *
2275                              *nr_vnodes * *nr_vnodes,
2276                              XC_HYPERCALL_BUFFER_BOUNCE_OUT);
2277     DECLARE_HYPERCALL_BOUNCE(vcpu_to_vnode, sizeof(*vcpu_to_vnode) * *nr_vcpus,
2278                              XC_HYPERCALL_BUFFER_BOUNCE_OUT);
2279 
2280     struct xen_vnuma_topology_info vnuma_topo;
2281 
2282     if ( xc_hypercall_bounce_pre(xch, vmemrange)      ||
2283          xc_hypercall_bounce_pre(xch, vdistance)      ||
2284          xc_hypercall_bounce_pre(xch, vcpu_to_vnode) )
2285     {
2286         rc = -1;
2287         errno = ENOMEM;
2288         goto vnumaget_fail;
2289     }
2290 
2291     set_xen_guest_handle(vnuma_topo.vmemrange.h, vmemrange);
2292     set_xen_guest_handle(vnuma_topo.vdistance.h, vdistance);
2293     set_xen_guest_handle(vnuma_topo.vcpu_to_vnode.h, vcpu_to_vnode);
2294 
2295     vnuma_topo.nr_vnodes = *nr_vnodes;
2296     vnuma_topo.nr_vcpus = *nr_vcpus;
2297     vnuma_topo.nr_vmemranges = *nr_vmemranges;
2298     vnuma_topo.domid = domid;
2299     vnuma_topo.pad = 0;
2300 
2301     rc = do_memory_op(xch, XENMEM_get_vnumainfo, &vnuma_topo,
2302                       sizeof(vnuma_topo));
2303 
2304     *nr_vnodes = vnuma_topo.nr_vnodes;
2305     *nr_vcpus = vnuma_topo.nr_vcpus;
2306     *nr_vmemranges = vnuma_topo.nr_vmemranges;
2307 
2308  vnumaget_fail:
2309     xc_hypercall_bounce_post(xch, vmemrange);
2310     xc_hypercall_bounce_post(xch, vdistance);
2311     xc_hypercall_bounce_post(xch, vcpu_to_vnode);
2312 
2313     return rc;
2314 }
2315 
xc_domain_soft_reset(xc_interface * xch,uint32_t domid)2316 int xc_domain_soft_reset(xc_interface *xch,
2317                          uint32_t domid)
2318 {
2319     DECLARE_DOMCTL;
2320     domctl.cmd = XEN_DOMCTL_soft_reset;
2321     domctl.domain = domid;
2322     return do_domctl(xch, &domctl);
2323 }
2324 /*
2325  * Local variables:
2326  * mode: C
2327  * c-file-style: "BSD"
2328  * c-basic-offset: 4
2329  * tab-width: 4
2330  * indent-tabs-mode: nil
2331  * End:
2332  */
2333