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