]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.sbin/bhyvectl/bhyvectl.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / usr.sbin / bhyvectl / bhyvectl.c
1 /*-
2  * Copyright (c) 2011 NetApp, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/sysctl.h>
35 #include <sys/errno.h>
36 #include <sys/mman.h>
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <libgen.h>
42 #include <libutil.h>
43 #include <fcntl.h>
44 #include <string.h>
45 #include <getopt.h>
46 #include <assert.h>
47
48 #include <machine/vmm.h>
49 #include <vmmapi.h>
50
51 #include "intel/vmcs.h"
52
53 #define MB      (1UL << 20)
54 #define GB      (1UL << 30)
55
56 #define REQ_ARG         required_argument
57 #define NO_ARG          no_argument
58 #define OPT_ARG         optional_argument
59
60 static const char *progname;
61
62 static void
63 usage(void)
64 {
65
66         (void)fprintf(stderr,
67         "Usage: %s --vm=<vmname>\n"
68         "       [--cpu=<vcpu_number>]\n"
69         "       [--create]\n"
70         "       [--destroy]\n"
71         "       [--get-all]\n"
72         "       [--get-stats]\n"
73         "       [--set-desc-ds]\n"
74         "       [--get-desc-ds]\n"
75         "       [--set-desc-es]\n"
76         "       [--get-desc-es]\n"
77         "       [--set-desc-gs]\n"
78         "       [--get-desc-gs]\n"
79         "       [--set-desc-fs]\n"
80         "       [--get-desc-fs]\n"
81         "       [--set-desc-cs]\n"
82         "       [--get-desc-cs]\n"
83         "       [--set-desc-ss]\n"
84         "       [--get-desc-ss]\n"
85         "       [--set-desc-tr]\n"
86         "       [--get-desc-tr]\n"
87         "       [--set-desc-ldtr]\n"
88         "       [--get-desc-ldtr]\n"
89         "       [--set-desc-gdtr]\n"
90         "       [--get-desc-gdtr]\n"
91         "       [--set-desc-idtr]\n"
92         "       [--get-desc-idtr]\n"
93         "       [--run]\n"
94         "       [--capname=<capname>]\n"
95         "       [--getcap]\n"
96         "       [--setcap=<0|1>]\n"
97         "       [--desc-base=<BASE>]\n"
98         "       [--desc-limit=<LIMIT>]\n"
99         "       [--desc-access=<ACCESS>]\n"
100         "       [--set-cr0=<CR0>]\n"
101         "       [--get-cr0]\n"
102         "       [--set-cr3=<CR3>]\n"
103         "       [--get-cr3]\n"
104         "       [--set-cr4=<CR4>]\n"
105         "       [--get-cr4]\n"
106         "       [--set-dr7=<DR7>]\n"
107         "       [--get-dr7]\n"
108         "       [--set-rsp=<RSP>]\n"
109         "       [--get-rsp]\n"
110         "       [--set-rip=<RIP>]\n"
111         "       [--get-rip]\n"
112         "       [--get-rax]\n"
113         "       [--set-rax=<RAX>]\n"
114         "       [--get-rbx]\n"
115         "       [--get-rcx]\n"
116         "       [--get-rdx]\n"
117         "       [--get-rsi]\n"
118         "       [--get-rdi]\n"
119         "       [--get-rbp]\n"
120         "       [--get-r8]\n"
121         "       [--get-r9]\n"
122         "       [--get-r10]\n"
123         "       [--get-r11]\n"
124         "       [--get-r12]\n"
125         "       [--get-r13]\n"
126         "       [--get-r14]\n"
127         "       [--get-r15]\n"
128         "       [--set-rflags=<RFLAGS>]\n"
129         "       [--get-rflags]\n"
130         "       [--set-cs]\n"
131         "       [--get-cs]\n"
132         "       [--set-ds]\n"
133         "       [--get-ds]\n"
134         "       [--set-es]\n"
135         "       [--get-es]\n"
136         "       [--set-fs]\n"
137         "       [--get-fs]\n"
138         "       [--set-gs]\n"
139         "       [--get-gs]\n"
140         "       [--set-ss]\n"
141         "       [--get-ss]\n"
142         "       [--get-tr]\n"
143         "       [--get-ldtr]\n"
144         "       [--get-vmcs-pinbased-ctls]\n"
145         "       [--get-vmcs-procbased-ctls]\n"
146         "       [--get-vmcs-procbased-ctls2]\n"
147         "       [--get-vmcs-entry-interruption-info]\n"
148         "       [--set-vmcs-entry-interruption-info=<info>]\n"
149         "       [--get-vmcs-eptp]\n"
150         "       [--get-vmcs-guest-physical-address\n"
151         "       [--get-vmcs-guest-linear-address\n"
152         "       [--set-vmcs-exception-bitmap]\n"
153         "       [--get-vmcs-exception-bitmap]\n"
154         "       [--get-vmcs-io-bitmap-address]\n"
155         "       [--get-vmcs-tsc-offset]\n"
156         "       [--get-vmcs-guest-pat]\n"
157         "       [--get-vmcs-host-pat]\n"
158         "       [--get-vmcs-host-cr0]\n"
159         "       [--get-vmcs-host-cr3]\n"
160         "       [--get-vmcs-host-cr4]\n"
161         "       [--get-vmcs-host-rip]\n"
162         "       [--get-vmcs-host-rsp]\n"
163         "       [--get-vmcs-cr0-mask]\n"
164         "       [--get-vmcs-cr0-shadow]\n"
165         "       [--get-vmcs-cr4-mask]\n"
166         "       [--get-vmcs-cr4-shadow]\n"
167         "       [--get-vmcs-cr3-targets]\n"
168         "       [--get-vmcs-apic-access-address]\n"
169         "       [--get-vmcs-virtual-apic-address]\n"
170         "       [--get-vmcs-tpr-threshold]\n"
171         "       [--get-vmcs-msr-bitmap]\n"
172         "       [--get-vmcs-msr-bitmap-address]\n"
173         "       [--get-vmcs-vpid]\n"
174         "       [--get-vmcs-ple-gap]\n"
175         "       [--get-vmcs-ple-window]\n"
176         "       [--get-vmcs-instruction-error]\n"
177         "       [--get-vmcs-exit-ctls]\n"
178         "       [--get-vmcs-entry-ctls]\n"
179         "       [--get-vmcs-guest-sysenter]\n"
180         "       [--get-vmcs-link]\n"
181         "       [--get-vmcs-exit-reason]\n"
182         "       [--get-vmcs-exit-qualification]\n"
183         "       [--get-vmcs-exit-interruption-info]\n"
184         "       [--get-vmcs-exit-interruption-error]\n"
185         "       [--get-vmcs-interruptibility]\n"
186         "       [--set-x2apic-state=<state>]\n"
187         "       [--get-x2apic-state]\n"
188         "       [--unassign-pptdev=<bus/slot/func>]\n"
189         "       [--set-mem=<memory in units of MB>]\n"
190         "       [--get-lowmem]\n"
191         "       [--get-highmem]\n"
192         "       [--get-gpa-pmap]\n",
193         progname);
194         exit(1);
195 }
196
197 static int get_stats, getcap, setcap, capval, get_gpa_pmap;
198 static const char *capname;
199 static int create, destroy, get_lowmem, get_highmem;
200 static uint64_t memsize;
201 static int set_cr0, get_cr0, set_cr3, get_cr3, set_cr4, get_cr4;
202 static int set_efer, get_efer;
203 static int set_dr7, get_dr7;
204 static int set_rsp, get_rsp, set_rip, get_rip, set_rflags, get_rflags;
205 static int set_rax, get_rax;
206 static int get_rbx, get_rcx, get_rdx, get_rsi, get_rdi, get_rbp;
207 static int get_r8, get_r9, get_r10, get_r11, get_r12, get_r13, get_r14, get_r15;
208 static int set_desc_ds, get_desc_ds;
209 static int set_desc_es, get_desc_es;
210 static int set_desc_fs, get_desc_fs;
211 static int set_desc_gs, get_desc_gs;
212 static int set_desc_cs, get_desc_cs;
213 static int set_desc_ss, get_desc_ss;
214 static int set_desc_gdtr, get_desc_gdtr;
215 static int set_desc_idtr, get_desc_idtr;
216 static int set_desc_tr, get_desc_tr;
217 static int set_desc_ldtr, get_desc_ldtr;
218 static int set_cs, set_ds, set_es, set_fs, set_gs, set_ss, set_tr, set_ldtr;
219 static int get_cs, get_ds, get_es, get_fs, get_gs, get_ss, get_tr, get_ldtr;
220 static int set_x2apic_state, get_x2apic_state;
221 enum x2apic_state x2apic_state;
222 static int unassign_pptdev, bus, slot, func;
223 static int run;
224
225 /*
226  * VMCS-specific fields
227  */
228 static int get_pinbased_ctls, get_procbased_ctls, get_procbased_ctls2;
229 static int get_eptp, get_io_bitmap, get_tsc_offset;
230 static int get_vmcs_entry_interruption_info, set_vmcs_entry_interruption_info;
231 static int get_vmcs_interruptibility;
232 uint32_t vmcs_entry_interruption_info;
233 static int get_vmcs_gpa, get_vmcs_gla;
234 static int get_exception_bitmap, set_exception_bitmap, exception_bitmap;
235 static int get_cr0_mask, get_cr0_shadow;
236 static int get_cr4_mask, get_cr4_shadow;
237 static int get_cr3_targets;
238 static int get_apic_access_addr, get_virtual_apic_addr, get_tpr_threshold;
239 static int get_msr_bitmap, get_msr_bitmap_address;
240 static int get_vpid, get_ple_gap, get_ple_window;
241 static int get_inst_err, get_exit_ctls, get_entry_ctls;
242 static int get_host_cr0, get_host_cr3, get_host_cr4;
243 static int get_host_rip, get_host_rsp;
244 static int get_guest_pat, get_host_pat;
245 static int get_guest_sysenter, get_vmcs_link;
246 static int get_vmcs_exit_reason, get_vmcs_exit_qualification;
247 static int get_vmcs_exit_interruption_info, get_vmcs_exit_interruption_error;
248
249 static uint64_t desc_base;
250 static uint32_t desc_limit, desc_access;
251
252 static int get_all;
253
254 static void
255 dump_vm_run_exitcode(struct vm_exit *vmexit, int vcpu)
256 {
257         printf("vm exit[%d]\n", vcpu);
258         printf("\trip\t\t0x%016lx\n", vmexit->rip);
259         printf("\tinst_length\t%d\n", vmexit->inst_length);
260         switch (vmexit->exitcode) {
261         case VM_EXITCODE_INOUT:
262                 printf("\treason\t\tINOUT\n");
263                 printf("\tdirection\t%s\n", vmexit->u.inout.in ? "IN" : "OUT");
264                 printf("\tbytes\t\t%d\n", vmexit->u.inout.bytes);
265                 printf("\tflags\t\t%s%s\n",
266                         vmexit->u.inout.string ? "STRING " : "",
267                         vmexit->u.inout.rep ? "REP " : "");
268                 printf("\tport\t\t0x%04x\n", vmexit->u.inout.port);
269                 printf("\teax\t\t0x%08x\n", vmexit->u.inout.eax);
270                 break;
271         case VM_EXITCODE_VMX:
272                 printf("\treason\t\tVMX\n");
273                 printf("\terror\t\t%d\n", vmexit->u.vmx.error);
274                 printf("\texit_reason\t0x%08x (%u)\n",
275                     vmexit->u.vmx.exit_reason, vmexit->u.vmx.exit_reason);
276                 printf("\tqualification\t0x%016lx\n",
277                         vmexit->u.vmx.exit_qualification);
278                 break;
279         default:
280                 printf("*** unknown vm run exitcode %d\n", vmexit->exitcode);
281                 break;
282         }
283 }
284
285 static int
286 dump_vmcs_msr_bitmap(int vcpu, u_long addr)
287 {
288         int error, fd, byte, bit, readable, writeable;
289         u_int msr;
290         const char *bitmap;
291
292         error = -1;
293         bitmap = MAP_FAILED;
294
295         fd = open("/dev/mem", O_RDONLY, 0);
296         if (fd < 0)
297                 goto done;
298
299         bitmap = mmap(NULL, PAGE_SIZE, PROT_READ, 0, fd, addr);
300         if (bitmap == MAP_FAILED)
301                 goto done;
302
303         for (msr = 0; msr < 0x2000; msr++) {
304                 byte = msr / 8;
305                 bit = msr & 0x7;
306
307                 /* Look at MSRs in the range 0x00000000 to 0x00001FFF */
308                 readable = (bitmap[byte] & (1 << bit)) ? 0 : 1;
309                 writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1;
310                 if (readable || writeable) {
311                         printf("msr 0x%08x[%d]\t\t%c%c\n", msr, vcpu,
312                                 readable ? 'R' : '-',
313                                 writeable ? 'W' : '-');
314                 }
315
316                 /* Look at MSRs in the range 0xC0000000 to 0xC0001FFF */
317                 byte += 1024;
318                 readable = (bitmap[byte] & (1 << bit)) ? 0 : 1;
319                 writeable = (bitmap[2048 + byte] & (1 << bit)) ? 0 : 1;
320                 if (readable || writeable) {
321                         printf("msr 0x%08x[%d]\t\t%c%c\n",
322                                 0xc0000000 + msr, vcpu,
323                                 readable ? 'R' : '-',
324                                 writeable ? 'W' : '-');
325                 }
326         }
327
328         error = 0;
329 done:
330         if (bitmap != MAP_FAILED)
331                 munmap((void *)bitmap, PAGE_SIZE);
332         if (fd >= 0)
333                 close(fd);
334         return (error);
335 }
336
337 static int
338 vm_get_vmcs_field(struct vmctx *ctx, int vcpu, int field, uint64_t *ret_val)
339 {
340
341         return (vm_get_register(ctx, vcpu, VMCS_IDENT(field), ret_val));
342 }
343
344 static int
345 vm_set_vmcs_field(struct vmctx *ctx, int vcpu, int field, uint64_t val)
346 {
347
348         return (vm_set_register(ctx, vcpu, VMCS_IDENT(field), val));
349 }
350
351 enum {
352         VMNAME = 1000,  /* avoid collision with return values from getopt */
353         VCPU,
354         SET_MEM,
355         SET_EFER,
356         SET_CR0,
357         SET_CR3,
358         SET_CR4,
359         SET_DR7,
360         SET_RSP,
361         SET_RIP,
362         SET_RAX,
363         SET_RFLAGS,
364         DESC_BASE,
365         DESC_LIMIT,
366         DESC_ACCESS,
367         SET_CS,
368         SET_DS,
369         SET_ES,
370         SET_FS,
371         SET_GS,
372         SET_SS,
373         SET_TR,
374         SET_LDTR,
375         SET_X2APIC_STATE,
376         SET_VMCS_EXCEPTION_BITMAP,
377         SET_VMCS_ENTRY_INTERRUPTION_INFO,
378         SET_CAP,
379         CAPNAME,
380         UNASSIGN_PPTDEV,
381         GET_GPA_PMAP,
382 };
383
384 int
385 main(int argc, char *argv[])
386 {
387         char *vmname;
388         int error, ch, vcpu, ptenum;
389         vm_paddr_t gpa, gpa_pmap;
390         size_t len;
391         struct vm_exit vmexit;
392         uint64_t ctl, eptp, bm, addr, u64, pteval[4], *pte;
393         struct vmctx *ctx;
394         int wired;
395
396         uint64_t cr0, cr3, cr4, dr7, rsp, rip, rflags, efer, pat;
397         uint64_t rax, rbx, rcx, rdx, rsi, rdi, rbp;
398         uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
399         uint64_t cs, ds, es, fs, gs, ss, tr, ldtr;
400
401         struct option opts[] = {
402                 { "vm",         REQ_ARG,        0,      VMNAME },
403                 { "cpu",        REQ_ARG,        0,      VCPU },
404                 { "set-mem",    REQ_ARG,        0,      SET_MEM },
405                 { "set-efer",   REQ_ARG,        0,      SET_EFER },
406                 { "set-cr0",    REQ_ARG,        0,      SET_CR0 },
407                 { "set-cr3",    REQ_ARG,        0,      SET_CR3 },
408                 { "set-cr4",    REQ_ARG,        0,      SET_CR4 },
409                 { "set-dr7",    REQ_ARG,        0,      SET_DR7 },
410                 { "set-rsp",    REQ_ARG,        0,      SET_RSP },
411                 { "set-rip",    REQ_ARG,        0,      SET_RIP },
412                 { "set-rax",    REQ_ARG,        0,      SET_RAX },
413                 { "set-rflags", REQ_ARG,        0,      SET_RFLAGS },
414                 { "desc-base",  REQ_ARG,        0,      DESC_BASE },
415                 { "desc-limit", REQ_ARG,        0,      DESC_LIMIT },
416                 { "desc-access",REQ_ARG,        0,      DESC_ACCESS },
417                 { "set-cs",     REQ_ARG,        0,      SET_CS },
418                 { "set-ds",     REQ_ARG,        0,      SET_DS },
419                 { "set-es",     REQ_ARG,        0,      SET_ES },
420                 { "set-fs",     REQ_ARG,        0,      SET_FS },
421                 { "set-gs",     REQ_ARG,        0,      SET_GS },
422                 { "set-ss",     REQ_ARG,        0,      SET_SS },
423                 { "set-tr",     REQ_ARG,        0,      SET_TR },
424                 { "set-ldtr",   REQ_ARG,        0,      SET_LDTR },
425                 { "set-x2apic-state",REQ_ARG,   0,      SET_X2APIC_STATE },
426                 { "set-vmcs-exception-bitmap",
427                                 REQ_ARG,        0, SET_VMCS_EXCEPTION_BITMAP },
428                 { "set-vmcs-entry-interruption-info",
429                                 REQ_ARG, 0, SET_VMCS_ENTRY_INTERRUPTION_INFO },
430                 { "capname",    REQ_ARG,        0,      CAPNAME },
431                 { "unassign-pptdev", REQ_ARG,   0,      UNASSIGN_PPTDEV },
432                 { "setcap",     REQ_ARG,        0,      SET_CAP },
433                 { "get-gpa-pmap", REQ_ARG,      0,      GET_GPA_PMAP },
434                 { "getcap",     NO_ARG,         &getcap,        1 },
435                 { "get-stats",  NO_ARG,         &get_stats,     1 },
436                 { "get-desc-ds",NO_ARG,         &get_desc_ds,   1 },
437                 { "set-desc-ds",NO_ARG,         &set_desc_ds,   1 },
438                 { "get-desc-es",NO_ARG,         &get_desc_es,   1 },
439                 { "set-desc-es",NO_ARG,         &set_desc_es,   1 },
440                 { "get-desc-ss",NO_ARG,         &get_desc_ss,   1 },
441                 { "set-desc-ss",NO_ARG,         &set_desc_ss,   1 },
442                 { "get-desc-cs",NO_ARG,         &get_desc_cs,   1 },
443                 { "set-desc-cs",NO_ARG,         &set_desc_cs,   1 },
444                 { "get-desc-fs",NO_ARG,         &get_desc_fs,   1 },
445                 { "set-desc-fs",NO_ARG,         &set_desc_fs,   1 },
446                 { "get-desc-gs",NO_ARG,         &get_desc_gs,   1 },
447                 { "set-desc-gs",NO_ARG,         &set_desc_gs,   1 },
448                 { "get-desc-tr",NO_ARG,         &get_desc_tr,   1 },
449                 { "set-desc-tr",NO_ARG,         &set_desc_tr,   1 },
450                 { "set-desc-ldtr", NO_ARG,      &set_desc_ldtr, 1 },
451                 { "get-desc-ldtr", NO_ARG,      &get_desc_ldtr, 1 },
452                 { "set-desc-gdtr", NO_ARG,      &set_desc_gdtr, 1 },
453                 { "get-desc-gdtr", NO_ARG,      &get_desc_gdtr, 1 },
454                 { "set-desc-idtr", NO_ARG,      &set_desc_idtr, 1 },
455                 { "get-desc-idtr", NO_ARG,      &get_desc_idtr, 1 },
456                 { "get-lowmem", NO_ARG,         &get_lowmem,    1 },
457                 { "get-highmem",NO_ARG,         &get_highmem,   1 },
458                 { "get-efer",   NO_ARG,         &get_efer,      1 },
459                 { "get-cr0",    NO_ARG,         &get_cr0,       1 },
460                 { "get-cr3",    NO_ARG,         &get_cr3,       1 },
461                 { "get-cr4",    NO_ARG,         &get_cr4,       1 },
462                 { "get-dr7",    NO_ARG,         &get_dr7,       1 },
463                 { "get-rsp",    NO_ARG,         &get_rsp,       1 },
464                 { "get-rip",    NO_ARG,         &get_rip,       1 },
465                 { "get-rax",    NO_ARG,         &get_rax,       1 },
466                 { "get-rbx",    NO_ARG,         &get_rbx,       1 },
467                 { "get-rcx",    NO_ARG,         &get_rcx,       1 },
468                 { "get-rdx",    NO_ARG,         &get_rdx,       1 },
469                 { "get-rsi",    NO_ARG,         &get_rsi,       1 },
470                 { "get-rdi",    NO_ARG,         &get_rdi,       1 },
471                 { "get-rbp",    NO_ARG,         &get_rbp,       1 },
472                 { "get-r8",     NO_ARG,         &get_r8,        1 },
473                 { "get-r9",     NO_ARG,         &get_r9,        1 },
474                 { "get-r10",    NO_ARG,         &get_r10,       1 },
475                 { "get-r11",    NO_ARG,         &get_r11,       1 },
476                 { "get-r12",    NO_ARG,         &get_r12,       1 },
477                 { "get-r13",    NO_ARG,         &get_r13,       1 },
478                 { "get-r14",    NO_ARG,         &get_r14,       1 },
479                 { "get-r15",    NO_ARG,         &get_r15,       1 },
480                 { "get-rflags", NO_ARG,         &get_rflags,    1 },
481                 { "get-cs",     NO_ARG,         &get_cs,        1 },
482                 { "get-ds",     NO_ARG,         &get_ds,        1 },
483                 { "get-es",     NO_ARG,         &get_es,        1 },
484                 { "get-fs",     NO_ARG,         &get_fs,        1 },
485                 { "get-gs",     NO_ARG,         &get_gs,        1 },
486                 { "get-ss",     NO_ARG,         &get_ss,        1 },
487                 { "get-tr",     NO_ARG,         &get_tr,        1 },
488                 { "get-ldtr",   NO_ARG,         &get_ldtr,      1 },
489                 { "get-vmcs-pinbased-ctls",
490                                 NO_ARG,         &get_pinbased_ctls, 1 },
491                 { "get-vmcs-procbased-ctls",
492                                 NO_ARG,         &get_procbased_ctls, 1 },
493                 { "get-vmcs-procbased-ctls2",
494                                 NO_ARG,         &get_procbased_ctls2, 1 },
495                 { "get-vmcs-guest-linear-address",
496                                 NO_ARG,         &get_vmcs_gla,  1 },
497                 { "get-vmcs-guest-physical-address",
498                                 NO_ARG,         &get_vmcs_gpa,  1 },
499                 { "get-vmcs-entry-interruption-info",
500                                 NO_ARG, &get_vmcs_entry_interruption_info, 1},
501                 { "get-vmcs-eptp", NO_ARG,      &get_eptp,      1 },
502                 { "get-vmcs-exception-bitmap",
503                                 NO_ARG,         &get_exception_bitmap, 1 },
504                 { "get-vmcs-io-bitmap-address",
505                                 NO_ARG,         &get_io_bitmap, 1 },
506                 { "get-vmcs-tsc-offset", NO_ARG,&get_tsc_offset, 1 },
507                 { "get-vmcs-cr0-mask", NO_ARG,  &get_cr0_mask,  1 },
508                 { "get-vmcs-cr0-shadow", NO_ARG,&get_cr0_shadow, 1 },
509                 { "get-vmcs-cr4-mask", NO_ARG,  &get_cr4_mask,  1 },
510                 { "get-vmcs-cr4-shadow", NO_ARG,&get_cr4_shadow, 1 },
511                 { "get-vmcs-cr3-targets", NO_ARG, &get_cr3_targets, 1},
512                 { "get-vmcs-apic-access-address",
513                                 NO_ARG,         &get_apic_access_addr, 1},
514                 { "get-vmcs-virtual-apic-address",
515                                 NO_ARG,         &get_virtual_apic_addr, 1},
516                 { "get-vmcs-tpr-threshold",
517                                 NO_ARG,         &get_tpr_threshold, 1 },
518                 { "get-vmcs-msr-bitmap",
519                                 NO_ARG,         &get_msr_bitmap, 1 },
520                 { "get-vmcs-msr-bitmap-address",
521                                 NO_ARG,         &get_msr_bitmap_address, 1 },
522                 { "get-vmcs-vpid", NO_ARG,      &get_vpid,      1 },
523                 { "get-vmcs-ple-gap", NO_ARG,   &get_ple_gap,   1 },
524                 { "get-vmcs-ple-window", NO_ARG,&get_ple_window,1 },
525                 { "get-vmcs-instruction-error",
526                                 NO_ARG,         &get_inst_err,  1 },
527                 { "get-vmcs-exit-ctls", NO_ARG, &get_exit_ctls, 1 },
528                 { "get-vmcs-entry-ctls",
529                                         NO_ARG, &get_entry_ctls, 1 },
530                 { "get-vmcs-guest-pat", NO_ARG, &get_guest_pat, 1 },
531                 { "get-vmcs-host-pat",  NO_ARG, &get_host_pat,  1 },
532                 { "get-vmcs-host-cr0",
533                                 NO_ARG,         &get_host_cr0,  1 },
534                 { "get-vmcs-host-cr3",
535                                 NO_ARG,         &get_host_cr3,  1 },
536                 { "get-vmcs-host-cr4",
537                                 NO_ARG,         &get_host_cr4,  1 },
538                 { "get-vmcs-host-rip",
539                                 NO_ARG,         &get_host_rip,  1 },
540                 { "get-vmcs-host-rsp",
541                                 NO_ARG,         &get_host_rsp,  1 },
542                 { "get-vmcs-guest-sysenter",
543                                 NO_ARG,         &get_guest_sysenter, 1 },
544                 { "get-vmcs-link", NO_ARG,      &get_vmcs_link, 1 },
545                 { "get-vmcs-exit-reason",
546                                 NO_ARG,         &get_vmcs_exit_reason, 1 },
547                 { "get-vmcs-exit-qualification",
548                         NO_ARG,         &get_vmcs_exit_qualification, 1 },
549                 { "get-vmcs-exit-interruption-info",
550                                 NO_ARG, &get_vmcs_exit_interruption_info, 1},
551                 { "get-vmcs-exit-interruption-error",
552                                 NO_ARG, &get_vmcs_exit_interruption_error, 1},
553                 { "get-vmcs-interruptibility",
554                                 NO_ARG, &get_vmcs_interruptibility, 1 },
555                 { "get-x2apic-state",NO_ARG,    &get_x2apic_state, 1 },
556                 { "get-all",    NO_ARG,         &get_all,       1 },
557                 { "run",        NO_ARG,         &run,           1 },
558                 { "create",     NO_ARG,         &create,        1 },
559                 { "destroy",    NO_ARG,         &destroy,       1 },
560                 { NULL,         0,              NULL,           0 }
561         };
562
563         vcpu = 0;
564         progname = basename(argv[0]);
565
566         while ((ch = getopt_long(argc, argv, "", opts, NULL)) != -1) {
567                 switch (ch) {
568                 case 0:
569                         break;
570                 case VMNAME:
571                         vmname = optarg;
572                         break;
573                 case VCPU:
574                         vcpu = atoi(optarg);
575                         break;
576                 case SET_MEM:
577                         memsize = atoi(optarg) * MB;
578                         memsize = roundup(memsize, 2 * MB);
579                         break;
580                 case SET_EFER:
581                         efer = strtoul(optarg, NULL, 0);
582                         set_efer = 1;
583                         break;
584                 case SET_CR0:
585                         cr0 = strtoul(optarg, NULL, 0);
586                         set_cr0 = 1;
587                         break;
588                 case SET_CR3:
589                         cr3 = strtoul(optarg, NULL, 0);
590                         set_cr3 = 1;
591                         break;
592                 case SET_CR4:
593                         cr4 = strtoul(optarg, NULL, 0);
594                         set_cr4 = 1;
595                         break;
596                 case SET_DR7:
597                         dr7 = strtoul(optarg, NULL, 0);
598                         set_dr7 = 1;
599                         break;
600                 case SET_RSP:
601                         rsp = strtoul(optarg, NULL, 0);
602                         set_rsp = 1;
603                         break;
604                 case SET_RIP:
605                         rip = strtoul(optarg, NULL, 0);
606                         set_rip = 1;
607                         break;
608                 case SET_RAX:
609                         rax = strtoul(optarg, NULL, 0);
610                         set_rax = 1;
611                         break;
612                 case SET_RFLAGS:
613                         rflags = strtoul(optarg, NULL, 0);
614                         set_rflags = 1;
615                         break;
616                 case DESC_BASE:
617                         desc_base = strtoul(optarg, NULL, 0);
618                         break;
619                 case DESC_LIMIT:
620                         desc_limit = strtoul(optarg, NULL, 0);
621                         break;
622                 case DESC_ACCESS:
623                         desc_access = strtoul(optarg, NULL, 0);
624                         break;
625                 case SET_CS:
626                         cs = strtoul(optarg, NULL, 0);
627                         set_cs = 1;
628                         break;
629                 case SET_DS:
630                         ds = strtoul(optarg, NULL, 0);
631                         set_ds = 1;
632                         break;
633                 case SET_ES:
634                         es = strtoul(optarg, NULL, 0);
635                         set_es = 1;
636                         break;
637                 case SET_FS:
638                         fs = strtoul(optarg, NULL, 0);
639                         set_fs = 1;
640                         break;
641                 case SET_GS:
642                         gs = strtoul(optarg, NULL, 0);
643                         set_gs = 1;
644                         break;
645                 case SET_SS:
646                         ss = strtoul(optarg, NULL, 0);
647                         set_ss = 1;
648                         break;
649                 case SET_TR:
650                         tr = strtoul(optarg, NULL, 0);
651                         set_tr = 1;
652                         break;
653                 case SET_LDTR:
654                         ldtr = strtoul(optarg, NULL, 0);
655                         set_ldtr = 1;
656                         break;
657                 case SET_X2APIC_STATE:
658                         x2apic_state = strtol(optarg, NULL, 0);
659                         set_x2apic_state = 1;
660                         break;
661                 case SET_VMCS_EXCEPTION_BITMAP:
662                         exception_bitmap = strtoul(optarg, NULL, 0);
663                         set_exception_bitmap = 1;
664                         break;
665                 case SET_VMCS_ENTRY_INTERRUPTION_INFO:
666                         vmcs_entry_interruption_info = strtoul(optarg, NULL, 0);
667                         set_vmcs_entry_interruption_info = 1;
668                         break;
669                 case SET_CAP:
670                         capval = strtoul(optarg, NULL, 0);
671                         setcap = 1;
672                         break;
673                 case GET_GPA_PMAP:
674                         gpa_pmap = strtoul(optarg, NULL, 0);
675                         get_gpa_pmap = 1;
676                         break;
677                 case CAPNAME:
678                         capname = optarg;
679                         break;
680                 case UNASSIGN_PPTDEV:
681                         unassign_pptdev = 1;
682                         if (sscanf(optarg, "%d/%d/%d", &bus, &slot, &func) != 3)
683                                 usage();
684                         break;
685                 default:
686                         usage();
687                 }
688         }
689         argc -= optind;
690         argv += optind;
691
692         if (vmname == NULL)
693                 usage();
694
695         error = 0;
696
697         if (!error && create)
698                 error = vm_create(vmname);
699
700         if (!error) {
701                 ctx = vm_open(vmname);
702                 if (ctx == NULL)
703                         error = -1;
704         }
705
706         if (!error && memsize)
707                 error = vm_setup_memory(ctx, memsize, VM_MMAP_NONE);
708
709         if (!error && set_efer)
710                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_EFER, efer);
711
712         if (!error && set_cr0)
713                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR0, cr0);
714
715         if (!error && set_cr3)
716                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR3, cr3);
717
718         if (!error && set_cr4)
719                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CR4, cr4);
720
721         if (!error && set_dr7)
722                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DR7, dr7);
723
724         if (!error && set_rsp)
725                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RSP, rsp);
726
727         if (!error && set_rip)
728                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RIP, rip);
729
730         if (!error && set_rax)
731                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX, rax);
732
733         if (!error && set_rflags) {
734                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RFLAGS,
735                                         rflags);
736         }
737
738         if (!error && set_desc_ds) {
739                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_DS,
740                                     desc_base, desc_limit, desc_access);
741         }
742
743         if (!error && set_desc_es) {
744                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_ES,
745                                     desc_base, desc_limit, desc_access);
746         }
747
748         if (!error && set_desc_ss) {
749                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_SS,
750                                     desc_base, desc_limit, desc_access);
751         }
752
753         if (!error && set_desc_cs) {
754                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_CS,
755                                     desc_base, desc_limit, desc_access);
756         }
757
758         if (!error && set_desc_fs) {
759                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_FS,
760                                     desc_base, desc_limit, desc_access);
761         }
762
763         if (!error && set_desc_gs) {
764                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_GS,
765                                     desc_base, desc_limit, desc_access);
766         }
767
768         if (!error && set_desc_tr) {
769                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_TR,
770                                     desc_base, desc_limit, desc_access);
771         }
772
773         if (!error && set_desc_ldtr) {
774                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_LDTR,
775                                     desc_base, desc_limit, desc_access);
776         }
777
778         if (!error && set_desc_gdtr) {
779                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_GDTR,
780                                     desc_base, desc_limit, 0);
781         }
782
783         if (!error && set_desc_idtr) {
784                 error = vm_set_desc(ctx, vcpu, VM_REG_GUEST_IDTR,
785                                     desc_base, desc_limit, 0);
786         }
787
788         if (!error && set_cs)
789                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_CS, cs);
790
791         if (!error && set_ds)
792                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_DS, ds);
793
794         if (!error && set_es)
795                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_ES, es);
796
797         if (!error && set_fs)
798                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_FS, fs);
799
800         if (!error && set_gs)
801                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_GS, gs);
802
803         if (!error && set_ss)
804                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_SS, ss);
805
806         if (!error && set_tr)
807                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_TR, tr);
808
809         if (!error && set_ldtr)
810                 error = vm_set_register(ctx, vcpu, VM_REG_GUEST_LDTR, ldtr);
811
812         if (!error && set_x2apic_state)
813                 error = vm_set_x2apic_state(ctx, vcpu, x2apic_state);
814
815         if (!error && unassign_pptdev)
816                 error = vm_unassign_pptdev(ctx, bus, slot, func);
817
818         if (!error && set_exception_bitmap) {
819                 error = vm_set_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP,
820                                           exception_bitmap);
821         }
822
823         if (!error && set_vmcs_entry_interruption_info) {
824                 error = vm_set_vmcs_field(ctx, vcpu, VMCS_ENTRY_INTR_INFO,
825                                           vmcs_entry_interruption_info);
826         }
827
828         if (!error && (get_lowmem || get_all)) {
829                 gpa = 0;
830                 error = vm_get_memory_seg(ctx, gpa, &len, &wired);
831                 if (error == 0)
832                         printf("lowmem\t\t0x%016lx/%ld%s\n", gpa, len,
833                             wired ? " wired" : "");
834         }
835
836         if (!error && (get_highmem || get_all)) {
837                 gpa = 4 * GB;
838                 error = vm_get_memory_seg(ctx, gpa, &len, &wired);
839                 if (error == 0)
840                         printf("highmem\t\t0x%016lx/%ld%s\n", gpa, len,
841                             wired ? " wired" : "");
842         }
843
844         if (!error && (get_efer || get_all)) {
845                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_EFER, &efer);
846                 if (error == 0)
847                         printf("efer[%d]\t\t0x%016lx\n", vcpu, efer);
848         }
849
850         if (!error && (get_cr0 || get_all)) {
851                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR0, &cr0);
852                 if (error == 0)
853                         printf("cr0[%d]\t\t0x%016lx\n", vcpu, cr0);
854         }
855
856         if (!error && (get_cr3 || get_all)) {
857                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR3, &cr3);
858                 if (error == 0)
859                         printf("cr3[%d]\t\t0x%016lx\n", vcpu, cr3);
860         }
861
862         if (!error && (get_cr4 || get_all)) {
863                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CR4, &cr4);
864                 if (error == 0)
865                         printf("cr4[%d]\t\t0x%016lx\n", vcpu, cr4);
866         }
867
868         if (!error && (get_dr7 || get_all)) {
869                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DR7, &dr7);
870                 if (error == 0)
871                         printf("dr7[%d]\t\t0x%016lx\n", vcpu, dr7);
872         }
873
874         if (!error && (get_rsp || get_all)) {
875                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSP, &rsp);
876                 if (error == 0)
877                         printf("rsp[%d]\t\t0x%016lx\n", vcpu, rsp);
878         }
879
880         if (!error && (get_rip || get_all)) {
881                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip);
882                 if (error == 0)
883                         printf("rip[%d]\t\t0x%016lx\n", vcpu, rip);
884         }
885
886         if (!error && (get_rax || get_all)) {
887                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RAX, &rax);
888                 if (error == 0)
889                         printf("rax[%d]\t\t0x%016lx\n", vcpu, rax);
890         }
891
892         if (!error && (get_rbx || get_all)) {
893                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBX, &rbx);
894                 if (error == 0)
895                         printf("rbx[%d]\t\t0x%016lx\n", vcpu, rbx);
896         }
897
898         if (!error && (get_rcx || get_all)) {
899                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RCX, &rcx);
900                 if (error == 0)
901                         printf("rcx[%d]\t\t0x%016lx\n", vcpu, rcx);
902         }
903
904         if (!error && (get_rdx || get_all)) {
905                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDX, &rdx);
906                 if (error == 0)
907                         printf("rdx[%d]\t\t0x%016lx\n", vcpu, rdx);
908         }
909
910         if (!error && (get_rsi || get_all)) {
911                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RSI, &rsi);
912                 if (error == 0)
913                         printf("rsi[%d]\t\t0x%016lx\n", vcpu, rsi);
914         }
915
916         if (!error && (get_rdi || get_all)) {
917                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RDI, &rdi);
918                 if (error == 0)
919                         printf("rdi[%d]\t\t0x%016lx\n", vcpu, rdi);
920         }
921
922         if (!error && (get_rbp || get_all)) {
923                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RBP, &rbp);
924                 if (error == 0)
925                         printf("rbp[%d]\t\t0x%016lx\n", vcpu, rbp);
926         }
927
928         if (!error && (get_r8 || get_all)) {
929                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R8, &r8);
930                 if (error == 0)
931                         printf("r8[%d]\t\t0x%016lx\n", vcpu, r8);
932         }
933
934         if (!error && (get_r9 || get_all)) {
935                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R9, &r9);
936                 if (error == 0)
937                         printf("r9[%d]\t\t0x%016lx\n", vcpu, r9);
938         }
939
940         if (!error && (get_r10 || get_all)) {
941                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R10, &r10);
942                 if (error == 0)
943                         printf("r10[%d]\t\t0x%016lx\n", vcpu, r10);
944         }
945
946         if (!error && (get_r11 || get_all)) {
947                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R11, &r11);
948                 if (error == 0)
949                         printf("r11[%d]\t\t0x%016lx\n", vcpu, r11);
950         }
951
952         if (!error && (get_r12 || get_all)) {
953                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R12, &r12);
954                 if (error == 0)
955                         printf("r12[%d]\t\t0x%016lx\n", vcpu, r12);
956         }
957
958         if (!error && (get_r13 || get_all)) {
959                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R13, &r13);
960                 if (error == 0)
961                         printf("r13[%d]\t\t0x%016lx\n", vcpu, r13);
962         }
963
964         if (!error && (get_r14 || get_all)) {
965                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R14, &r14);
966                 if (error == 0)
967                         printf("r14[%d]\t\t0x%016lx\n", vcpu, r14);
968         }
969
970         if (!error && (get_r15 || get_all)) {
971                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_R15, &r15);
972                 if (error == 0)
973                         printf("r15[%d]\t\t0x%016lx\n", vcpu, r15);
974         }
975
976         if (!error && (get_rflags || get_all)) {
977                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RFLAGS,
978                                         &rflags);
979                 if (error == 0)
980                         printf("rflags[%d]\t0x%016lx\n", vcpu, rflags);
981         }
982
983         if (!error && (get_stats || get_all)) {
984                 int i, num_stats;
985                 uint64_t *stats;
986                 struct timeval tv;
987                 const char *desc;
988
989                 stats = vm_get_stats(ctx, vcpu, &tv, &num_stats);
990                 if (stats != NULL) {
991                         printf("vcpu%d\n", vcpu);
992                         for (i = 0; i < num_stats; i++) {
993                                 desc = vm_get_stat_desc(ctx, i);
994                                 printf("%-40s\t%ld\n", desc, stats[i]);
995                         }
996                 }
997         }
998
999         if (!error && (get_desc_ds || get_all)) {
1000                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_DS,
1001                                     &desc_base, &desc_limit, &desc_access);
1002                 if (error == 0) {
1003                         printf("ds desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1004                                vcpu, desc_base, desc_limit, desc_access);       
1005                 }
1006         }
1007
1008         if (!error && (get_desc_es || get_all)) {
1009                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_ES,
1010                                     &desc_base, &desc_limit, &desc_access);
1011                 if (error == 0) {
1012                         printf("es desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1013                                vcpu, desc_base, desc_limit, desc_access);       
1014                 }
1015         }
1016
1017         if (!error && (get_desc_fs || get_all)) {
1018                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_FS,
1019                                     &desc_base, &desc_limit, &desc_access);
1020                 if (error == 0) {
1021                         printf("fs desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1022                                vcpu, desc_base, desc_limit, desc_access);       
1023                 }
1024         }
1025
1026         if (!error && (get_desc_gs || get_all)) {
1027                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GS,
1028                                     &desc_base, &desc_limit, &desc_access);
1029                 if (error == 0) {
1030                         printf("gs desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1031                                vcpu, desc_base, desc_limit, desc_access);       
1032                 }
1033         }
1034
1035         if (!error && (get_desc_ss || get_all)) {
1036                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_SS,
1037                                     &desc_base, &desc_limit, &desc_access);
1038                 if (error == 0) {
1039                         printf("ss desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1040                                vcpu, desc_base, desc_limit, desc_access);       
1041                 }
1042         }
1043
1044         if (!error && (get_desc_cs || get_all)) {
1045                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_CS,
1046                                     &desc_base, &desc_limit, &desc_access);
1047                 if (error == 0) {
1048                         printf("cs desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1049                                vcpu, desc_base, desc_limit, desc_access);       
1050                 }
1051         }
1052
1053         if (!error && (get_desc_tr || get_all)) {
1054                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_TR,
1055                                     &desc_base, &desc_limit, &desc_access);
1056                 if (error == 0) {
1057                         printf("tr desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1058                                vcpu, desc_base, desc_limit, desc_access);       
1059                 }
1060         }
1061
1062         if (!error && (get_desc_ldtr || get_all)) {
1063                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_LDTR,
1064                                     &desc_base, &desc_limit, &desc_access);
1065                 if (error == 0) {
1066                         printf("ldtr desc[%d]\t0x%016lx/0x%08x/0x%08x\n",
1067                                vcpu, desc_base, desc_limit, desc_access);       
1068                 }
1069         }
1070
1071         if (!error && (get_desc_gdtr || get_all)) {
1072                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_GDTR,
1073                                     &desc_base, &desc_limit, &desc_access);
1074                 if (error == 0) {
1075                         printf("gdtr[%d]\t\t0x%016lx/0x%08x\n",
1076                                vcpu, desc_base, desc_limit);    
1077                 }
1078         }
1079
1080         if (!error && (get_desc_idtr || get_all)) {
1081                 error = vm_get_desc(ctx, vcpu, VM_REG_GUEST_IDTR,
1082                                     &desc_base, &desc_limit, &desc_access);
1083                 if (error == 0) {
1084                         printf("idtr[%d]\t\t0x%016lx/0x%08x\n",
1085                                vcpu, desc_base, desc_limit);    
1086                 }
1087         }
1088
1089         if (!error && (get_cs || get_all)) {
1090                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_CS, &cs);
1091                 if (error == 0)
1092                         printf("cs[%d]\t\t0x%04lx\n", vcpu, cs);
1093         }
1094
1095         if (!error && (get_ds || get_all)) {
1096                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_DS, &ds);
1097                 if (error == 0)
1098                         printf("ds[%d]\t\t0x%04lx\n", vcpu, ds);
1099         }
1100
1101         if (!error && (get_es || get_all)) {
1102                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_ES, &es);
1103                 if (error == 0)
1104                         printf("es[%d]\t\t0x%04lx\n", vcpu, es);
1105         }
1106
1107         if (!error && (get_fs || get_all)) {
1108                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_FS, &fs);
1109                 if (error == 0)
1110                         printf("fs[%d]\t\t0x%04lx\n", vcpu, fs);
1111         }
1112
1113         if (!error && (get_gs || get_all)) {
1114                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_GS, &gs);
1115                 if (error == 0)
1116                         printf("gs[%d]\t\t0x%04lx\n", vcpu, gs);
1117         }
1118
1119         if (!error && (get_ss || get_all)) {
1120                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_SS, &ss);
1121                 if (error == 0)
1122                         printf("ss[%d]\t\t0x%04lx\n", vcpu, ss);
1123         }
1124
1125         if (!error && (get_tr || get_all)) {
1126                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_TR, &tr);
1127                 if (error == 0)
1128                         printf("tr[%d]\t\t0x%04lx\n", vcpu, tr);
1129         }
1130
1131         if (!error && (get_ldtr || get_all)) {
1132                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_LDTR, &ldtr);
1133                 if (error == 0)
1134                         printf("ldtr[%d]\t\t0x%04lx\n", vcpu, ldtr);
1135         }
1136
1137         if (!error && (get_x2apic_state || get_all)) {
1138                 error = vm_get_x2apic_state(ctx, vcpu, &x2apic_state);
1139                 if (error == 0)
1140                         printf("x2apic_state[%d]\t%d\n", vcpu, x2apic_state);
1141         }
1142
1143         if (!error && (get_pinbased_ctls || get_all)) {
1144                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_PIN_BASED_CTLS, &ctl);
1145                 if (error == 0)
1146                         printf("pinbased_ctls[%d]\t0x%08lx\n", vcpu, ctl);
1147         }
1148
1149         if (!error && (get_procbased_ctls || get_all)) {
1150                 error = vm_get_vmcs_field(ctx, vcpu,
1151                                           VMCS_PRI_PROC_BASED_CTLS, &ctl);
1152                 if (error == 0)
1153                         printf("procbased_ctls[%d]\t0x%08lx\n", vcpu, ctl);
1154         }
1155
1156         if (!error && (get_procbased_ctls2 || get_all)) {
1157                 error = vm_get_vmcs_field(ctx, vcpu,
1158                                           VMCS_SEC_PROC_BASED_CTLS, &ctl);
1159                 if (error == 0)
1160                         printf("procbased_ctls2[%d]\t0x%08lx\n", vcpu, ctl);
1161         }
1162
1163         if (!error && (get_vmcs_gla || get_all)) {
1164                 error = vm_get_vmcs_field(ctx, vcpu,
1165                                           VMCS_GUEST_LINEAR_ADDRESS, &u64);
1166                 if (error == 0)
1167                         printf("gla[%d]\t\t0x%016lx\n", vcpu, u64);
1168         }
1169
1170         if (!error && (get_vmcs_gpa || get_all)) {
1171                 error = vm_get_vmcs_field(ctx, vcpu,
1172                                           VMCS_GUEST_PHYSICAL_ADDRESS, &u64);
1173                 if (error == 0)
1174                         printf("gpa[%d]\t\t0x%016lx\n", vcpu, u64);
1175         }
1176
1177         if (!error && (get_vmcs_entry_interruption_info || get_all)) {
1178                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_INTR_INFO,&u64);
1179                 if (error == 0) {
1180                         printf("entry_interruption_info[%d]\t0x%08lx\n",
1181                                 vcpu, u64);
1182                 }
1183         }
1184
1185         if (!error && (get_eptp || get_all)) {
1186                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_EPTP, &eptp);
1187                 if (error == 0)
1188                         printf("eptp[%d]\t\t0x%016lx\n", vcpu, eptp);
1189         }
1190
1191         if (!error && (get_exception_bitmap || get_all)) {
1192                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP,
1193                                           &bm);
1194                 if (error == 0)
1195                         printf("exception_bitmap[%d]\t0x%08lx\n", vcpu, bm);
1196         }
1197
1198         if (!error && (get_io_bitmap || get_all)) {
1199                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_A, &bm);
1200                 if (error == 0)
1201                         printf("io_bitmap_a[%d]\t0x%08lx\n", vcpu, bm);
1202                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_IO_BITMAP_B, &bm);
1203                 if (error == 0)
1204                         printf("io_bitmap_b[%d]\t0x%08lx\n", vcpu, bm);
1205         }
1206
1207         if (!error && (get_tsc_offset || get_all)) {
1208                 uint64_t tscoff;
1209                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_TSC_OFFSET, &tscoff);
1210                 if (error == 0)
1211                         printf("tsc_offset[%d]\t0x%016lx\n", vcpu, tscoff);
1212         }
1213
1214         if (!error && (get_cr0_mask || get_all)) {
1215                 uint64_t cr0mask;
1216                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_MASK, &cr0mask);
1217                 if (error == 0)
1218                         printf("cr0_mask[%d]\t\t0x%016lx\n", vcpu, cr0mask);
1219         }
1220
1221         if (!error && (get_cr0_shadow || get_all)) {
1222                 uint64_t cr0shadow;
1223                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR0_SHADOW,
1224                                           &cr0shadow);
1225                 if (error == 0)
1226                         printf("cr0_shadow[%d]\t\t0x%016lx\n", vcpu, cr0shadow);
1227         }
1228
1229         if (!error && (get_cr4_mask || get_all)) {
1230                 uint64_t cr4mask;
1231                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_MASK, &cr4mask);
1232                 if (error == 0)
1233                         printf("cr4_mask[%d]\t\t0x%016lx\n", vcpu, cr4mask);
1234         }
1235
1236         if (!error && (get_cr4_shadow || get_all)) {
1237                 uint64_t cr4shadow;
1238                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR4_SHADOW,
1239                                           &cr4shadow);
1240                 if (error == 0)
1241                         printf("cr4_shadow[%d]\t\t0x%016lx\n", vcpu, cr4shadow);
1242         }
1243         
1244         if (!error && (get_cr3_targets || get_all)) {
1245                 uint64_t target_count, target_addr;
1246                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET_COUNT,
1247                                           &target_count);
1248                 if (error == 0) {
1249                         printf("cr3_target_count[%d]\t0x%08lx\n",
1250                                 vcpu, target_count);
1251                 }
1252
1253                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET0,
1254                                           &target_addr);
1255                 if (error == 0) {
1256                         printf("cr3_target0[%d]\t\t0x%016lx\n",
1257                                 vcpu, target_addr);
1258                 }
1259
1260                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET1,
1261                                           &target_addr);
1262                 if (error == 0) {
1263                         printf("cr3_target1[%d]\t\t0x%016lx\n",
1264                                 vcpu, target_addr);
1265                 }
1266
1267                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET2,
1268                                           &target_addr);
1269                 if (error == 0) {
1270                         printf("cr3_target2[%d]\t\t0x%016lx\n",
1271                                 vcpu, target_addr);
1272                 }
1273
1274                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_CR3_TARGET3,
1275                                           &target_addr);
1276                 if (error == 0) {
1277                         printf("cr3_target3[%d]\t\t0x%016lx\n",
1278                                 vcpu, target_addr);
1279                 }
1280         }
1281
1282         if (!error && (get_apic_access_addr || get_all)) {
1283                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_APIC_ACCESS, &addr);
1284                 if (error == 0)
1285                         printf("apic_access_addr[%d]\t0x%016lx\n", vcpu, addr);
1286         }
1287
1288         if (!error && (get_virtual_apic_addr || get_all)) {
1289                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_VIRTUAL_APIC, &addr);
1290                 if (error == 0)
1291                         printf("virtual_apic_addr[%d]\t0x%016lx\n", vcpu, addr);
1292         }
1293
1294         if (!error && (get_tpr_threshold || get_all)) {
1295                 uint64_t threshold;
1296                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_TPR_THRESHOLD,
1297                                           &threshold);
1298                 if (error == 0)
1299                         printf("tpr_threshold[%d]\t0x%08lx\n", vcpu, threshold);
1300         }
1301
1302         if (!error && (get_msr_bitmap_address || get_all)) {
1303                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_MSR_BITMAP, &addr);
1304                 if (error == 0)
1305                         printf("msr_bitmap[%d]\t\t0x%016lx\n", vcpu, addr);
1306         }
1307
1308         if (!error && (get_msr_bitmap || get_all)) {
1309                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_MSR_BITMAP, &addr);
1310                 if (error == 0)
1311                         error = dump_vmcs_msr_bitmap(vcpu, addr);
1312         }
1313
1314         if (!error && (get_vpid || get_all)) {
1315                 uint64_t vpid;
1316                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_VPID, &vpid);
1317                 if (error == 0)
1318                         printf("vpid[%d]\t\t0x%04lx\n", vcpu, vpid);
1319         }
1320         
1321         if (!error && (get_ple_window || get_all)) {
1322                 uint64_t window;
1323                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_PLE_WINDOW, &window);
1324                 if (error == 0)
1325                         printf("ple_window[%d]\t\t0x%08lx\n", vcpu, window);
1326         }
1327
1328         if (!error && (get_ple_gap || get_all)) {
1329                 uint64_t gap;
1330                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_PLE_GAP, &gap);
1331                 if (error == 0)
1332                         printf("ple_gap[%d]\t\t0x%08lx\n", vcpu, gap);
1333         }
1334
1335         if (!error && (get_inst_err || get_all)) {
1336                 uint64_t insterr;
1337                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_INSTRUCTION_ERROR,
1338                                           &insterr);
1339                 if (error == 0) {
1340                         printf("instruction_error[%d]\t0x%08lx\n",
1341                                 vcpu, insterr);
1342                 }
1343         }
1344
1345         if (!error && (get_exit_ctls || get_all)) {
1346                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_CTLS, &ctl);
1347                 if (error == 0)
1348                         printf("exit_ctls[%d]\t\t0x%08lx\n", vcpu, ctl);
1349         }
1350
1351         if (!error && (get_entry_ctls || get_all)) {
1352                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_ENTRY_CTLS, &ctl);
1353                 if (error == 0)
1354                         printf("entry_ctls[%d]\t\t0x%08lx\n", vcpu, ctl);
1355         }
1356
1357         if (!error && (get_host_pat || get_all)) {
1358                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_IA32_PAT, &pat);
1359                 if (error == 0)
1360                         printf("host_pat[%d]\t\t0x%016lx\n", vcpu, pat);
1361         }
1362
1363         if (!error && (get_guest_pat || get_all)) {
1364                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_GUEST_IA32_PAT, &pat);
1365                 if (error == 0)
1366                         printf("guest_pat[%d]\t\t0x%016lx\n", vcpu, pat);
1367         }
1368
1369         if (!error && (get_host_cr0 || get_all)) {
1370                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR0, &cr0);
1371                 if (error == 0)
1372                         printf("host_cr0[%d]\t\t0x%016lx\n", vcpu, cr0);
1373         }
1374
1375         if (!error && (get_host_cr3 || get_all)) {
1376                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR3, &cr3);
1377                 if (error == 0)
1378                         printf("host_cr3[%d]\t\t0x%016lx\n", vcpu, cr3);
1379         }
1380
1381         if (!error && (get_host_cr4 || get_all)) {
1382                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_CR4, &cr4);
1383                 if (error == 0)
1384                         printf("host_cr4[%d]\t\t0x%016lx\n", vcpu, cr4);
1385         }
1386
1387         if (!error && (get_host_rip || get_all)) {
1388                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RIP, &rip);
1389                 if (error == 0)
1390                         printf("host_rip[%d]\t\t0x%016lx\n", vcpu, rip);
1391         }
1392
1393         if (!error && (get_host_rsp || get_all)) {
1394                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_HOST_RSP, &rsp);
1395                 if (error == 0)
1396                         printf("host_rsp[%d]\t\t0x%016lx\n", vcpu, rsp);
1397         }
1398
1399         if (!error && (get_guest_sysenter || get_all)) {
1400                 error = vm_get_vmcs_field(ctx, vcpu,
1401                                           VMCS_GUEST_IA32_SYSENTER_CS, &cs);
1402                 if (error == 0)
1403                         printf("guest_sysenter_cs[%d]\t0x%08lx\n", vcpu, cs);
1404
1405                 error = vm_get_vmcs_field(ctx, vcpu,
1406                                           VMCS_GUEST_IA32_SYSENTER_ESP, &rsp);
1407                 if (error == 0)
1408                         printf("guest_sysenter_sp[%d]\t0x%016lx\n", vcpu, rsp);
1409                 error = vm_get_vmcs_field(ctx, vcpu,
1410                                           VMCS_GUEST_IA32_SYSENTER_EIP, &rip);
1411                 if (error == 0)
1412                         printf("guest_sysenter_ip[%d]\t0x%016lx\n", vcpu, rip);
1413         }
1414
1415         if (!error && (get_vmcs_link || get_all)) {
1416                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_LINK_POINTER, &addr);
1417                 if (error == 0)
1418                         printf("vmcs_pointer[%d]\t0x%016lx\n", vcpu, addr);
1419         }
1420
1421         if (!error && (get_vmcs_exit_reason || get_all)) {
1422                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_REASON, &u64);
1423                 if (error == 0)
1424                         printf("vmcs_exit_reason[%d]\t0x%016lx\n", vcpu, u64);
1425         }
1426
1427         if (!error && (get_vmcs_exit_qualification || get_all)) {
1428                 error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_QUALIFICATION,
1429                                           &u64);
1430                 if (error == 0)
1431                         printf("vmcs_exit_qualification[%d]\t0x%016lx\n",
1432                                 vcpu, u64);
1433         }
1434
1435         if (!error && (get_vmcs_exit_interruption_info || get_all)) {
1436                 error = vm_get_vmcs_field(ctx, vcpu,
1437                                           VMCS_EXIT_INTERRUPTION_INFO, &u64);
1438                 if (error == 0) {
1439                         printf("vmcs_exit_interruption_info[%d]\t0x%08lx\n",
1440                                 vcpu, u64);
1441                 }
1442         }
1443
1444         if (!error && (get_vmcs_exit_interruption_error || get_all)) {
1445                 error = vm_get_vmcs_field(ctx, vcpu,
1446                                           VMCS_EXIT_INTERRUPTION_ERROR, &u64);
1447                 if (error == 0) {
1448                         printf("vmcs_exit_interruption_error[%d]\t0x%08lx\n",
1449                                 vcpu, u64);
1450                 }
1451         }
1452
1453         if (!error && (get_vmcs_interruptibility || get_all)) {
1454                 error = vm_get_vmcs_field(ctx, vcpu,
1455                                           VMCS_GUEST_INTERRUPTIBILITY, &u64);
1456                 if (error == 0) {
1457                         printf("vmcs_guest_interruptibility[%d]\t0x%08lx\n",
1458                                 vcpu, u64);
1459                 }
1460         }
1461
1462         if (!error && setcap) {
1463                 int captype;
1464                 captype = vm_capability_name2type(capname);
1465                 error = vm_set_capability(ctx, vcpu, captype, capval);
1466                 if (error != 0 && errno == ENOENT)
1467                         printf("Capability \"%s\" is not available\n", capname);
1468         }
1469
1470         if (!error && get_gpa_pmap) {
1471                 error = vm_get_gpa_pmap(ctx, gpa_pmap, pteval, &ptenum);
1472                 if (error == 0) {
1473                         printf("gpa %#lx:", gpa_pmap);
1474                         pte = &pteval[0];
1475                         while (ptenum-- > 0)
1476                                 printf(" %#lx", *pte++);
1477                         printf("\n");
1478                 }
1479         }
1480
1481         if (!error && (getcap || get_all)) {
1482                 int captype, val, getcaptype;
1483
1484                 if (getcap && capname)
1485                         getcaptype = vm_capability_name2type(capname);
1486                 else
1487                         getcaptype = -1;
1488
1489                 for (captype = 0; captype < VM_CAP_MAX; captype++) {
1490                         if (getcaptype >= 0 && captype != getcaptype)
1491                                 continue;
1492                         error = vm_get_capability(ctx, vcpu, captype, &val);
1493                         if (error == 0) {
1494                                 printf("Capability \"%s\" is %s on vcpu %d\n",
1495                                         vm_capability_type2name(captype),
1496                                         val ? "set" : "not set", vcpu);
1497                         } else if (errno == ENOENT) {
1498                                 printf("Capability \"%s\" is not available\n",
1499                                         vm_capability_type2name(captype));
1500                         } else {
1501                                 break;
1502                         }
1503                 }
1504         }
1505
1506         if (!error && run) {
1507                 error = vm_get_register(ctx, vcpu, VM_REG_GUEST_RIP, &rip);
1508                 assert(error == 0);
1509
1510                 error = vm_run(ctx, vcpu, rip, &vmexit);
1511                 if (error == 0)
1512                         dump_vm_run_exitcode(&vmexit, vcpu);
1513                 else
1514                         printf("vm_run error %d\n", error);
1515         }
1516
1517         if (error)
1518                 printf("errno = %d\n", errno);
1519
1520         if (!error && destroy)
1521                 vm_destroy(ctx);
1522
1523         exit(error);
1524 }