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