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