1 /*
2 * Copyright 2009-2017 Citrix Ltd and other contributors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; version 2.1 only. with the special
7 * exception on linking described in file LICENSE.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 */
14
15 #include <string.h>
16
17 #include <libxl.h>
18 #include <xen-tools/common-macros.h>
19
20 #include "xl.h"
21
22 const struct cmd_spec cmd_table[] = {
23 { "create",
24 &main_create, 1, 1,
25 "Create a domain from config file <filename>",
26 "<ConfigFile> [options] [vars]",
27 "-c Connect to the console after the domain is created.\n"
28 "-d Enable debug messages.\n"
29 "-e Do not wait in the background for the death of the domain.\n"
30 "-F Run in foreground until death of the domain.\n"
31 "-f FILE, --defconfig=FILE\n Use the given configuration file.\n"
32 "-h Print this help.\n"
33 "-n, --dryrun Dry run - prints the resulting configuration\n"
34 " (deprecated in favour of global -N option).\n"
35 "-p Leave the domain paused after it is created.\n"
36 "-q, --quiet Quiet.\n"
37 "-V, --vncviewer Connect to the VNC display after the domain is created.\n"
38 "-A, --vncviewer-autopass\n"
39 " Pass VNC password to viewer via stdin.\n"
40 "--ignore-global-affinity-masks Ignore global masks in xl.conf."
41 },
42 { "config-update",
43 &main_config_update, 1, 1,
44 "Update a running domain's saved configuration, used when rebuilding "
45 "the domain after reboot.\n"
46 "WARNING: xl now has better capability to manage domain configuration, "
47 "avoid using this command when possible",
48 "<Domain> <ConfigFile> [options] [vars]",
49 "-h Print this help.\n"
50 "-f FILE, --defconfig=FILE\n Use the given configuration file.\n"
51 "-d Enable debug messages.\n"
52 },
53 { "list",
54 &main_list, 0, 0,
55 "List information about all/some domains",
56 "[options] [Domain]\n",
57 "-l, --long Output all VM details\n"
58 "-v, --verbose Prints out UUIDs and security context\n"
59 "-Z, --context Prints out security context\n"
60 "-c, --cpupool Prints the cpupool the domain is in\n"
61 "-n, --numa Prints out NUMA node affinity"
62 },
63 { "destroy",
64 &main_destroy, 0, 1,
65 "Terminate a domain immediately",
66 "[options] <Domain>\n",
67 "-f Permit destroying domain 0, which will only succeed\n"
68 " when run from disaggregated toolstack domain with a\n"
69 " hardware domain distinct from domain 0."
70 },
71 { "shutdown",
72 &main_shutdown, 0, 1,
73 "Issue a shutdown signal to a domain",
74 "[options] <-a|Domain>",
75 "-a, --all Shutdown all guest domains.\n"
76 "-h Print this help.\n"
77 "-F Fallback to ACPI power event for HVM guests with\n"
78 " no PV drivers.\n"
79 "-w, --wait Wait for guest(s) to shutdown.\n"
80 },
81 { "reboot",
82 &main_reboot, 0, 1,
83 "Issue a reboot signal to a domain",
84 "[options] <-a|Domain>",
85 "-a, --all Shutdown all guest domains.\n"
86 "-h Print this help.\n"
87 "-F Fallback to ACPI reset event for HVM guests with\n"
88 " no PV drivers.\n"
89 "-w, --wait Wait for guest(s) to reboot.\n"
90 },
91 { "pci-attach",
92 &main_pciattach, 0, 1,
93 "Insert a new pass-through pci device",
94 "<Domain> <PCI_SPEC_STRING>",
95 },
96 { "pci-detach",
97 &main_pcidetach, 0, 1,
98 "Remove a domain's pass-through pci device",
99 "<Domain> <PCI_SPEC_STRING>",
100 },
101 { "pci-list",
102 &main_pcilist, 0, 0,
103 "List pass-through pci devices for a domain",
104 "<Domain>",
105 },
106 { "pci-assignable-add",
107 &main_pciassignable_add, 0, 1,
108 "Make a device assignable for pci-passthru",
109 "[options] <BDF>",
110 "-n NAME, --name=NAME Name the assignable device.\n"
111 "-h Print this help.\n"
112 },
113 { "pci-assignable-remove",
114 &main_pciassignable_remove, 0, 1,
115 "Remove a device from being assignable",
116 "[options] <BDF>|NAME",
117 "-h Print this help.\n"
118 "-r Attempt to re-assign the device to the\n"
119 " original driver."
120 },
121 { "pci-assignable-list",
122 &main_pciassignable_list, 0, 0,
123 "List all the assignable pci devices",
124 "[options]",
125 "-h Print this help.\n"
126 "-n, --show-names Display assignable device names where\n"
127 " supplied.\n"
128 },
129 { "pause",
130 &main_pause, 0, 1,
131 "Pause execution of a domain",
132 "<Domain>",
133 },
134 { "unpause",
135 &main_unpause, 0, 1,
136 "Unpause a paused domain",
137 "<Domain>",
138 },
139 { "console",
140 &main_console, 0, 0,
141 "Attach to domain's console",
142 "[options] <Domain>\n"
143 "-t <type> console type, pv , serial or vuart\n"
144 "-n <number> console number\n"
145 "-e <escape> escape character"
146 },
147 { "vncviewer",
148 &main_vncviewer, 0, 0,
149 "Attach to domain's VNC server.",
150 "[options] <Domain>\n"
151 "--autopass Pass VNC password to viewer via stdin and\n"
152 " -autopass\n"
153 "--vncviewer-autopass (consistency alias for --autopass)"
154 },
155 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
156 { "save",
157 &main_save, 0, 1,
158 "Save a domain state to restore later",
159 "[options] <Domain> <CheckpointFile> [<ConfigFile>]",
160 "-h Print this help.\n"
161 "-c Leave domain running after creating the snapshot.\n"
162 "-p Leave domain paused after creating the snapshot.\n"
163 "-D Store the domain id in the configuration."
164 },
165 { "migrate",
166 &main_migrate, 0, 1,
167 "Migrate a domain to another host",
168 "[options] <Domain> <host>",
169 "-h Print this help.\n"
170 "-C <config> Send <config> instead of config file from creation.\n"
171 "-s <sshcommand> Use <sshcommand> instead of ssh. String will be passed\n"
172 " to sh. If empty, run <host> instead of ssh <host> xl\n"
173 " migrate-receive [-d -e]\n"
174 "-e Do not wait in the background (on <host>) for the death\n"
175 " of the domain.\n"
176 "--debug Print huge (!) amount of debug during the migration process.\n"
177 "-p Do not unpause domain after migrating it.\n"
178 "-D Preserve the domain id"
179 },
180 { "restore",
181 &main_restore, 0, 1,
182 "Restore a domain from a saved state",
183 "[options] [<ConfigFile>] <CheckpointFile>",
184 "-h Print this help.\n"
185 "-p Do not unpause domain after restoring it.\n"
186 "-e Do not wait in the background for the death of the domain.\n"
187 "-d Enable debug messages.\n"
188 "-V, --vncviewer Connect to the VNC display after the domain is created.\n"
189 "-A, --vncviewer-autopass Pass VNC password to viewer via stdin."
190 },
191 { "migrate-receive",
192 &main_migrate_receive, 0, 1,
193 "Restore a domain from a saved state",
194 "- for internal use only",
195 },
196 { "suspend",
197 &main_suspend, 0, 1,
198 "Suspend a domain to RAM",
199 "<Domain>",
200 },
201 { "resume",
202 &main_resume, 0, 1,
203 "Resume a domain from RAM",
204 "<Domain>",
205 },
206 #endif
207 { "dump-core",
208 &main_dump_core, 0, 1,
209 "Core dump a domain",
210 "<Domain> <filename>"
211 },
212 { "cd-insert",
213 &main_cd_insert, 1, 1,
214 "Insert a cdrom into a guest's cd drive",
215 "<Domain> <VirtualDevice> <path>",
216 },
217 { "cd-eject",
218 &main_cd_eject, 1, 1,
219 "Eject a cdrom from a guest's cd drive",
220 "<Domain> <VirtualDevice>",
221 },
222 { "mem-max",
223 &main_memmax, 0, 1,
224 "Set the maximum amount reservation for a domain",
225 "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
226 },
227 { "mem-set",
228 &main_memset, 0, 1,
229 "Set the current memory usage for a domain",
230 "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
231 },
232 { "button-press",
233 &main_button_press, 0, 1,
234 "Indicate an ACPI button press to the domain",
235 "<Domain> <Button>",
236 "<Button> may be 'power' or 'sleep'."
237 },
238 { "vcpu-list",
239 &main_vcpulist, 0, 0,
240 "List the VCPUs for all/some domains",
241 "[Domain, ...]",
242 },
243 { "vcpu-pin",
244 &main_vcpupin, 1, 1,
245 "Set which CPUs a VCPU can use",
246 "[option] <Domain> <VCPU|all> <Hard affinity|-|all> <Soft affinity|-|all>",
247 "-f, --force undo an override pinning done by the kernel\n"
248 "--ignore-global-affinity-masks Ignore global masks in xl.conf",
249 },
250 { "vcpu-set",
251 &main_vcpuset, 0, 1,
252 "Set the number of active VCPUs allowed for the domain",
253 "[option] <Domain> <vCPUs>",
254 "-i, --ignore-host Don't limit the vCPU based on the host CPU count",
255 },
256 { "vm-list",
257 &main_vm_list, 0, 0,
258 "List guest domains, excluding dom0, stubdoms, etc.",
259 "",
260 },
261 { "info",
262 &main_info, 0, 0,
263 "Get information about Xen host",
264 "-n, --numa List host NUMA topology information",
265 },
266 { "sharing",
267 &main_sharing, 0, 0,
268 "Get information about page sharing",
269 "[Domain]",
270 },
271 { "sched-credit",
272 &main_sched_credit, 0, 1,
273 "Get/set credit scheduler parameters",
274 "[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]] [-s [-t TSLICE] [-r RATELIMIT]] [-p CPUPOOL]",
275 "-d DOMAIN, --domain=DOMAIN Domain to modify\n"
276 "-w WEIGHT, --weight=WEIGHT Weight (int)\n"
277 "-c CAP, --cap=CAP Cap (int)\n"
278 "-s --schedparam Query / modify scheduler parameters\n"
279 "-t TSLICE, --tslice_ms=TSLICE Set the timeslice, in milliseconds\n"
280 "-r RLIMIT, --ratelimit_us=RLIMIT Set the scheduling rate limit, in microseconds\n"
281 "-m DLY, --migration_delay_us=DLY Set the migration delay, in microseconds\n"
282 "-p CPUPOOL, --cpupool=CPUPOOL Restrict output to CPUPOOL"
283 },
284 { "sched-credit2",
285 &main_sched_credit2, 0, 1,
286 "Get/set credit2 scheduler parameters",
287 "[-d <Domain> [-w[=WEIGHT]]] [-p CPUPOOL]",
288 "-d DOMAIN, --domain=DOMAIN Domain to modify\n"
289 "-w WEIGHT, --weight=WEIGHT Weight (int)\n"
290 "-c CAP, --cap=CAP Cap (int)\n"
291 "-s --schedparam Query / modify scheduler parameters\n"
292 "-r RLIMIT, --ratelimit_us=RLIMIT Set the scheduling rate limit, in microseconds\n"
293 "-p CPUPOOL, --cpupool=CPUPOOL Restrict output to CPUPOOL"
294 },
295 { "sched-rtds",
296 &main_sched_rtds, 0, 1,
297 "Get/set rtds scheduler parameters",
298 "[-d <Domain> [-v[=VCPUID/all]] [-p[=PERIOD]] [-b[=BUDGET]] [-e[=Extratime]]]",
299 "-d DOMAIN, --domain=DOMAIN Domain to modify\n"
300 "-v VCPUID/all, --vcpuid=VCPUID/all VCPU to modify or output;\n"
301 " Using '-v all' to modify/output all vcpus\n"
302 "-p PERIOD, --period=PERIOD Period (us)\n"
303 "-b BUDGET, --budget=BUDGET Budget (us)\n"
304 "-e Extratime, --extratime=Extratime Extratime (1=yes, 0=no)\n"
305 },
306 { "domid",
307 &main_domid, 0, 0,
308 "Convert a domain name to domain id",
309 "<DomainName>",
310 },
311 { "domname",
312 &main_domname, 0, 0,
313 "Convert a domain id to domain name",
314 "<DomainId>",
315 },
316 { "rename",
317 &main_rename, 0, 1,
318 "Rename a domain",
319 "<Domain> <NewDomainName>",
320 },
321 { "trigger",
322 &main_trigger, 0, 1,
323 "Send a trigger to a domain",
324 "<Domain> <nmi|reset|init|power|sleep|s3resume> [<VCPU>]",
325 },
326 { "sysrq",
327 &main_sysrq, 0, 1,
328 "Send a sysrq to a domain",
329 "<Domain> <letter>",
330 },
331 { "debug-keys",
332 &main_debug_keys, 0, 1,
333 "Send debug keys to Xen",
334 "<Keys>",
335 },
336 { "set-parameters",
337 &main_set_parameters, 0, 1,
338 "Set hypervisor parameters",
339 "<Params>",
340 },
341 { "dmesg",
342 &main_dmesg, 0, 0,
343 "Read and/or clear dmesg buffer",
344 "[-c]",
345 " -c Clear dmesg buffer as well as printing it",
346 },
347 { "top",
348 &main_top, 0, 0,
349 "Monitor a host and the domains in real time",
350 "",
351 },
352 { "network-attach",
353 &main_networkattach, 1, 1,
354 "Create a new virtual network device",
355 "<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] "
356 "[ip=<ip>] [script=<script>] [backend=<BackDomain>] [vifname=<name>] "
357 "[rate=<rate>] [model=<model>] [accel=<accel>] [mtu=<mtu>]",
358 },
359 { "network-list",
360 &main_networklist, 0, 0,
361 "List virtual network interfaces for a domain",
362 "<Domain(s)>",
363 },
364 { "network-detach",
365 &main_networkdetach, 0, 1,
366 "Destroy a domain's virtual network device",
367 "<Domain> <DevId|mac>",
368 },
369 { "channel-list",
370 &main_channellist, 0, 0,
371 "List virtual channel devices for a domain",
372 "<Domain(s)>",
373 },
374 { "block-attach",
375 &main_blockattach, 1, 1,
376 "Create a new virtual block device",
377 "<Domain> <disk-spec-component(s)>...",
378 },
379 { "block-list",
380 &main_blocklist, 0, 0,
381 "List virtual block devices for a domain",
382 "<Domain(s)>",
383 },
384 { "block-detach",
385 &main_blockdetach, 0, 1,
386 "Destroy a domain's virtual block device",
387 "[option] <Domain> <DevId>",
388 "-f, --force do not wait for the domain to release the device"
389 },
390 { "vtpm-attach",
391 &main_vtpmattach, 1, 1,
392 "Create a new virtual TPM device",
393 "<Domain> [uuid=<uuid>] [backend=<BackDomain>]",
394 },
395 { "vtpm-list",
396 &main_vtpmlist, 0, 0,
397 "List virtual TPM devices for a domain",
398 "<Domain(s)>",
399 },
400 { "vtpm-detach",
401 &main_vtpmdetach, 0, 1,
402 "Destroy a domain's virtual TPM device",
403 "<Domain> <DevId|uuid>",
404 },
405 { "vkb-attach",
406 &main_vkbattach, 1, 1,
407 "Create a new virtual keyboard device",
408 "<Domain> <vkb-spec-component(s)>...",
409 },
410 { "vkb-list",
411 &main_vkblist, 0, 0,
412 "List virtual keyboard devices for a domain",
413 "<Domain(s)>",
414 },
415 { "vkb-detach",
416 &main_vkbdetach, 0, 1,
417 "Destroy a domain's virtual keyboard device",
418 "<Domain> <DevId>",
419 },
420 { "vdispl-attach",
421 &main_vdisplattach, 1, 1,
422 "Create a new virtual display device",
423 "<Domain> [backend=<BackDomain>] [be-alloc=<BackAlloc>] [connectors='<Connectors>']",
424 " BackAlloc - set to 1 to if backend allocates display buffers\n"
425 " Connectors - list of connector's description in ID:WxH format,\n"
426 " where: ID - unique connector ID, W - connector width,\n"
427 " H - connector height: connectors='id0:800x600;id1:1024x768'\n"
428 },
429 { "vdispl-list",
430 &main_vdispllist, 0, 0,
431 "List virtual display devices for a domain",
432 "<Domain(s)>",
433 },
434 { "vdispl-detach",
435 &main_vdispldetach, 0, 1,
436 "Destroy a domain's virtual display device",
437 "<Domain> <DevId>",
438 },
439 { "vsnd-attach",
440 &main_vsndattach, 1, 1,
441 "Create a new virtual sound device",
442 "<Domain> <vsnd-spec-component(s)>...",
443 },
444 { "vsnd-list",
445 &main_vsndlist, 0, 0,
446 "List virtual sound devices for a domain",
447 "<Domain(s)>",
448 },
449 { "vsnd-detach",
450 &main_vsnddetach, 0, 1,
451 "Destroy a domain's virtual sound device",
452 "<Domain> <DevId>",
453 },
454 { "uptime",
455 &main_uptime, 0, 0,
456 "Print uptime for all/some domains",
457 "[-s] [Domain]",
458 },
459 { "claims",
460 &main_claims, 0, 0,
461 "List outstanding claim information about all domains",
462 "",
463 "",
464 },
465 { "cpupool-create",
466 &main_cpupoolcreate, 1, 1,
467 "Create a new CPU pool",
468 "[options] [<ConfigFile>] [Variable=value ...]",
469 "-h, --help Print this help.\n"
470 "-f FILE, --defconfig=FILE Use the given configuration file.\n"
471 "-n, --dryrun Dry run - prints the resulting configuration.\n"
472 " (deprecated in favour of global -N option).\n"
473 "\nSee the xlcpupool.cfg(5) manpage for more information.",
474
475 },
476 { "cpupool-list",
477 &main_cpupoollist, 0, 0,
478 "List CPU pools on host",
479 "[-c|--cpus] [<CPU Pool>]",
480 "-c, --cpus Output list of CPUs used by a pool"
481 },
482 { "cpupool-destroy",
483 &main_cpupooldestroy, 0, 1,
484 "Deactivates a CPU pool",
485 "<CPU Pool>",
486 },
487 { "cpupool-rename",
488 &main_cpupoolrename, 0, 1,
489 "Renames a CPU pool",
490 "<CPU Pool> <new name>",
491 },
492 { "cpupool-cpu-add",
493 &main_cpupoolcpuadd, 0, 1,
494 "Adds a CPU to a CPU pool",
495 "<CPU Pool> <CPU nr>|node:<node nr>",
496 },
497 { "cpupool-cpu-remove",
498 &main_cpupoolcpuremove, 0, 1,
499 "Removes a CPU from a CPU pool",
500 "<CPU Pool> <CPU nr>|node:<node nr>",
501 },
502 { "cpupool-migrate",
503 &main_cpupoolmigrate, 0, 1,
504 "Moves a domain into a CPU pool",
505 "<Domain> <CPU Pool>",
506 },
507 { "cpupool-numa-split",
508 &main_cpupoolnumasplit, 0, 1,
509 "Splits up the machine into one CPU pool per NUMA node",
510 "",
511 },
512 { "getenforce",
513 &main_getenforce, 0, 0,
514 "Returns the current enforcing mode of the Flask Xen security module",
515 "",
516 },
517 { "setenforce",
518 &main_setenforce, 0, 1,
519 "Sets the current enforcing mode of the Flask Xen security module",
520 "<1|0|Enforcing|Permissive>",
521 },
522 { "loadpolicy",
523 &main_loadpolicy, 0, 1,
524 "Loads a new policy into the Flask Xen security module",
525 "<policy file>",
526 },
527 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
528 { "remus",
529 &main_remus, 0, 1,
530 "Enable Remus HA for domain",
531 "[options] <Domain> [<host>]",
532 "-i MS Checkpoint domain memory every MS milliseconds (def. 200ms).\n"
533 "-u Disable memory checkpoint compression.\n"
534 "-s <sshcommand> Use <sshcommand> instead of ssh. String will be passed\n"
535 " to sh. If empty, run <host> instead of \n"
536 " ssh <host> xl migrate-receive -r [-e]\n"
537 "-e Do not wait in the background (on <host>) for the death\n"
538 " of the domain.\n"
539 "-N <netbufscript> Use netbufscript to setup network buffering instead of the\n"
540 " default script (" XEN_SCRIPT_DIR "/remus-netbuf-setup).\n"
541 "-F Enable unsafe configurations [-b|-n|-d flags]. Use this option\n"
542 " with caution as failover may not work as intended.\n"
543 "-b Replicate memory checkpoints to /dev/null (blackhole).\n"
544 " Works only in unsafe mode.\n"
545 "-n Disable network output buffering. Works only in unsafe mode.\n"
546 "-d Disable disk replication. Works only in unsafe mode.\n"
547 "-c Enable COLO HA. It is conflict with -i and -b, and memory\n"
548 " checkpoint must be disabled.\n"
549 "-p Use COLO userspace proxy."
550 },
551 #endif
552 { "devd",
553 &main_devd, 0, 1,
554 "Daemon that listens for devices and launches backends",
555 "[options]",
556 "-F Run in the foreground.\n"
557 "-p, --pidfile [FILE] Write PID to pidfile when daemonizing.",
558 },
559 #if defined(__i386__) || defined(__x86_64__)
560 { "psr-hwinfo",
561 &main_psr_hwinfo, 0, 1,
562 "Show hardware information for Platform Shared Resource",
563 "[options]",
564 "-m, --cmt Show Cache Monitoring Technology (CMT) hardware info\n"
565 "-a, --cat Show Cache Allocation Technology (CAT) hardware info\n"
566 "-b, --mba Show Memory Bandwidth Allocation (MBA) hardware info\n"
567 },
568 { "psr-cmt-attach",
569 &main_psr_cmt_attach, 0, 1,
570 "Attach Cache Monitoring Technology service to a domain",
571 "<Domain>",
572 },
573 { "psr-cmt-detach",
574 &main_psr_cmt_detach, 0, 1,
575 "Detach Cache Monitoring Technology service from a domain",
576 "<Domain>",
577 },
578 { "psr-cmt-show",
579 &main_psr_cmt_show, 0, 1,
580 "Show Cache Monitoring Technology information",
581 "<PSR-CMT-Type> <Domain>",
582 "Available monitor types:\n"
583 "\"cache-occupancy\": Show L3 cache occupancy(KB)\n"
584 "\"total-mem-bandwidth\": Show total memory bandwidth(KB/s)\n"
585 "\"local-mem-bandwidth\": Show local memory bandwidth(KB/s)\n",
586 },
587 { "psr-cat-set",
588 &main_psr_cat_cbm_set, 0, 1,
589 "Set cache capacity bitmasks(CBM) for a domain",
590 "[options] <Domain> <CBM>",
591 "-s <socket> Specify the socket to process, otherwise all sockets are processed\n"
592 "-l <level> Specify the cache level to process, otherwise L3 cache is processed\n"
593 "-c Set code CBM if CDP is supported\n"
594 "-d Set data CBM if CDP is supported\n"
595 },
596 { "psr-cat-show",
597 &main_psr_cat_show, 0, 1,
598 "Show Cache Allocation Technology information",
599 "[options] <Domain>",
600 "-l <level> Specify the cache level to process, otherwise L3 cache is processed\n"
601 },
602 { "psr-mba-set",
603 &main_psr_mba_set, 0, 1,
604 "Set throttling value (THRTL) for a domain",
605 "[options] <Domain> <THRTL>",
606 "-s <socket> Specify the socket to process, otherwise all sockets are processed\n"
607 },
608 { "psr-mba-show",
609 &main_psr_mba_show, 0, 1,
610 "Show Memory Bandwidth Allocation information",
611 "<Domain>",
612 },
613 #endif
614 { "usbctrl-attach",
615 &main_usbctrl_attach, 0, 1,
616 "Create a virtual USB controller for a domain",
617 "<Domain> [type=pv] [version=<version>] [ports=<number>]",
618 },
619 { "usbctrl-detach",
620 &main_usbctrl_detach, 0, 1,
621 "Remove the virtual USB controller specified by <DevId> for a domain",
622 "<Domain> <DevId>",
623 },
624 { "usbdev-attach",
625 &main_usbdev_attach, 0, 1,
626 "Attach a USB device to a domain",
627 "<Domain> hostbus=<busnum> hostaddr=<devnum> [controller=<DevId> [port=<port>]]",
628 },
629 { "usbdev-detach",
630 &main_usbdev_detach, 0, 1,
631 "Detach a USB device from a domain",
632 "<Domain> <controller> <port>",
633 },
634 { "usb-list",
635 &main_usblist, 0, 0,
636 "List information about all USB controllers and devices for a domain",
637 "<Domain>",
638 },
639 { "qemu-monitor-command",
640 &main_qemu_monitor_command, 0, 1,
641 "Issue a qemu monitor command to the device model of a domain",
642 "<Domain> <Command>",
643 },
644 #ifdef LIBXL_HAVE_DT_OVERLAY
645 { "dt-overlay",
646 &main_dt_overlay, 0, 1,
647 "Add/Remove a device tree overlay to Xen device tree, attach/detach the device to a domain",
648 "<operation=add|remove> <.dtbo> OR <operation=attach> <.dtbo> <Domain>",
649 "-h print this help\n"
650 },
651 #endif
652 };
653
654 const int cmdtable_len = ARRAY_SIZE(cmd_table);
655
656 /* Look up a command in the table, allowing unambiguous truncation */
cmdtable_lookup(const char * s)657 const struct cmd_spec *cmdtable_lookup(const char *s)
658 {
659 const struct cmd_spec *cmd = NULL;
660 size_t len;
661 int i, count = 0;
662
663 if (!s)
664 return NULL;
665 len = strlen(s);
666 for (i = 0; i < cmdtable_len; i++) {
667 if (!strncmp(s, cmd_table[i].cmd_name, len)) {
668 cmd = &cmd_table[i];
669 /* Take an exact match, even if it also prefixes another command */
670 if (len == strlen(cmd->cmd_name))
671 return cmd;
672 count++;
673 }
674 }
675 return (count == 1) ? cmd : NULL;
676 }
677
678 /*
679 * Local variables:
680 * mode: C
681 * c-basic-offset: 4
682 * indent-tabs-mode: nil
683 * End:
684 */
685