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