18368e25fSAaron LI /*
2e84206a6SAaron LI * Copyright (c) 2018-2021 Maxime Villard, m00nbsd.net
38368e25fSAaron LI * All rights reserved.
48368e25fSAaron LI *
5e84206a6SAaron LI * This code is part of the NVMM hypervisor.
68368e25fSAaron LI *
78368e25fSAaron LI * Redistribution and use in source and binary forms, with or without
88368e25fSAaron LI * modification, are permitted provided that the following conditions
98368e25fSAaron LI * are met:
108368e25fSAaron LI * 1. Redistributions of source code must retain the above copyright
118368e25fSAaron LI * notice, this list of conditions and the following disclaimer.
128368e25fSAaron LI * 2. Redistributions in binary form must reproduce the above copyright
138368e25fSAaron LI * notice, this list of conditions and the following disclaimer in the
148368e25fSAaron LI * documentation and/or other materials provided with the distribution.
158368e25fSAaron LI *
16e84206a6SAaron LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17e84206a6SAaron LI * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18e84206a6SAaron LI * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19e84206a6SAaron LI * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20e84206a6SAaron LI * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21e84206a6SAaron LI * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22e84206a6SAaron LI * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23e84206a6SAaron LI * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24e84206a6SAaron LI * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25e84206a6SAaron LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26e84206a6SAaron LI * SUCH DAMAGE.
278368e25fSAaron LI */
288368e25fSAaron LI
29*db3748d6SAaron LI #include <sys/types.h>
30*db3748d6SAaron LI #include <sys/mman.h>
31*db3748d6SAaron LI
32f2252fffSAaron LI #include <assert.h>
33*db3748d6SAaron LI #include <err.h>
34*db3748d6SAaron LI #include <pthread.h>
35*db3748d6SAaron LI #include <stdbool.h>
36*db3748d6SAaron LI #include <stdint.h>
378368e25fSAaron LI #include <stdio.h>
388368e25fSAaron LI #include <stdlib.h>
398368e25fSAaron LI #include <unistd.h>
408368e25fSAaron LI
418368e25fSAaron LI #include "common.h"
428368e25fSAaron LI
43*db3748d6SAaron LI #undef MSR_APICBASE
44*db3748d6SAaron LI #define MSR_APICBASE 0x01b
45*db3748d6SAaron LI #undef APICBASE_BSP
46*db3748d6SAaron LI #define APICBASE_BSP 0x00000100 /* bootstrap processor */
47*db3748d6SAaron LI #undef APICBASE_EN
48*db3748d6SAaron LI #define APICBASE_EN 0x00000800 /* software enable */
494dec84dcSAaron LI
508368e25fSAaron LI /* -------------------------------------------------------------------------- */
518368e25fSAaron LI
528368e25fSAaron LI uintptr_t
toyvirt_mem_add(struct nvmm_machine * mach,gpaddr_t gpa,size_t size)538368e25fSAaron LI toyvirt_mem_add(struct nvmm_machine *mach, gpaddr_t gpa, size_t size)
548368e25fSAaron LI {
558368e25fSAaron LI uintptr_t hva;
568368e25fSAaron LI void *buf;
578368e25fSAaron LI
58f2252fffSAaron LI assert(size > 0);
59f2252fffSAaron LI
60f2252fffSAaron LI buf = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
618368e25fSAaron LI if (buf == MAP_FAILED)
628368e25fSAaron LI err(EXIT_FAILURE, "mmap");
638368e25fSAaron LI
648368e25fSAaron LI hva = (uintptr_t)buf;
658368e25fSAaron LI if (nvmm_hva_map(mach, hva, size) == -1)
668368e25fSAaron LI err(EXIT_FAILURE, "nvmm_hva_map");
678368e25fSAaron LI if (nvmm_gpa_map(mach, hva, gpa, size, PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
688368e25fSAaron LI err(EXIT_FAILURE, "nvmm_gpa_map");
698368e25fSAaron LI
708368e25fSAaron LI return hva;
718368e25fSAaron LI }
728368e25fSAaron LI
738368e25fSAaron LI /* -------------------------------------------------------------------------- */
748368e25fSAaron LI
758368e25fSAaron LI static bool can_take_int = false;
768368e25fSAaron LI static bool can_take_nmi = false;
778368e25fSAaron LI static bool has_int_pending = false;
788368e25fSAaron LI static bool has_nmi_pending = false;
792efd87c6SAaron LI static struct nvmm_vcpu_event pending_int;
802efd87c6SAaron LI static struct nvmm_vcpu_event pending_nmi;
818368e25fSAaron LI
828368e25fSAaron LI static void
toyvirt_event_inject(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu,struct nvmm_vcpu_event * event)838368e25fSAaron LI toyvirt_event_inject(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
842efd87c6SAaron LI struct nvmm_vcpu_event *event)
858368e25fSAaron LI {
868368e25fSAaron LI memcpy(vcpu->event, event, sizeof(*event));
878368e25fSAaron LI
888368e25fSAaron LI /* INT. */
898368e25fSAaron LI if (event->vector != 2) {
908368e25fSAaron LI if (can_take_int) {
918368e25fSAaron LI if (nvmm_vcpu_inject(mach, vcpu) == -1)
928368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_inject");
938368e25fSAaron LI has_int_pending = false;
948368e25fSAaron LI } else {
958368e25fSAaron LI memcpy(&pending_int, event, sizeof(pending_int));
968368e25fSAaron LI has_int_pending = true;
978368e25fSAaron LI }
988368e25fSAaron LI }
998368e25fSAaron LI
1008368e25fSAaron LI /* NMI. */
1018368e25fSAaron LI if (event->vector == 2) {
1028368e25fSAaron LI if (can_take_nmi) {
1038368e25fSAaron LI if (nvmm_vcpu_inject(mach, vcpu) == -1)
1048368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_inject");
1058368e25fSAaron LI has_nmi_pending = false;
1068368e25fSAaron LI } else {
1078368e25fSAaron LI memcpy(&pending_nmi, event, sizeof(pending_nmi));
1088368e25fSAaron LI has_nmi_pending = true;
1098368e25fSAaron LI }
1108368e25fSAaron LI }
1118368e25fSAaron LI }
1128368e25fSAaron LI
1138368e25fSAaron LI static void
toyvirt_event_reinject(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)1148368e25fSAaron LI toyvirt_event_reinject(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
1158368e25fSAaron LI {
1162efd87c6SAaron LI struct nvmm_vcpu_exit *exit = vcpu->exit;
1178368e25fSAaron LI
1182efd87c6SAaron LI if (exit->reason == NVMM_VCPU_EXIT_INT_READY) {
1198368e25fSAaron LI if (!has_int_pending)
1208368e25fSAaron LI errx(EXIT_FAILURE, "no INT pending!");
1218368e25fSAaron LI toyvirt_event_inject(mach, vcpu, &pending_int);
1228368e25fSAaron LI } else {
1238368e25fSAaron LI if (!has_nmi_pending)
1248368e25fSAaron LI errx(EXIT_FAILURE, "no NMI pending!");
1258368e25fSAaron LI toyvirt_event_inject(mach, vcpu, &pending_nmi);
1268368e25fSAaron LI }
1278368e25fSAaron LI }
1288368e25fSAaron LI
1298368e25fSAaron LI /* -------------------------------------------------------------------------- */
1308368e25fSAaron LI
131e84206a6SAaron LI static void
toycpu_io_callback(struct nvmm_io * io)132e84206a6SAaron LI toycpu_io_callback(struct nvmm_io *io)
133e84206a6SAaron LI {
134e84206a6SAaron LI /* Hand over to toydev. */
135e84206a6SAaron LI toydev_io(io->port, io->in, io->data, io->size);
136e84206a6SAaron LI }
1378368e25fSAaron LI
1388368e25fSAaron LI static void
toyvirt_mem_callback(struct nvmm_mem * mem)139e84206a6SAaron LI toyvirt_mem_callback(struct nvmm_mem *mem)
140e84206a6SAaron LI {
141e84206a6SAaron LI /* Hand over to toydev. */
142e84206a6SAaron LI toydev_mmio(mem->gpa, mem->write, mem->data, mem->size);
143e84206a6SAaron LI }
144e84206a6SAaron LI
145e84206a6SAaron LI static struct nvmm_assist_callbacks callbacks = {
146e84206a6SAaron LI .io = toycpu_io_callback,
147e84206a6SAaron LI .mem = toyvirt_mem_callback
148e84206a6SAaron LI };
149e84206a6SAaron LI
150e84206a6SAaron LI /* -------------------------------------------------------------------------- */
151e84206a6SAaron LI
152e84206a6SAaron LI static void
toyvirt_vcpu_configure(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)153e84206a6SAaron LI toyvirt_vcpu_configure(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
1548368e25fSAaron LI {
1552efd87c6SAaron LI struct nvmm_vcpu_conf_cpuid cpuid;
156e84206a6SAaron LI int ret;
1578368e25fSAaron LI
158e84206a6SAaron LI /*
159e84206a6SAaron LI * Register the assist callbacks.
160e84206a6SAaron LI */
161e84206a6SAaron LI ret = nvmm_vcpu_configure(mach, vcpu, NVMM_VCPU_CONF_CALLBACKS,
162e84206a6SAaron LI &callbacks);
163e84206a6SAaron LI if (ret == -1)
164e84206a6SAaron LI err(EXIT_FAILURE, "nvmm_vcpu_configure");
165e84206a6SAaron LI
166e84206a6SAaron LI /*
167e84206a6SAaron LI * Hide the No-Execute bit. No particular reason, just to demonstrate.
168e84206a6SAaron LI */
1698368e25fSAaron LI memset(&cpuid, 0, sizeof(cpuid));
1702efd87c6SAaron LI cpuid.mask = 1;
1718368e25fSAaron LI cpuid.leaf = 0x80000001;
172e84206a6SAaron LI cpuid.u.mask.del.edx = CPUID_8_01_EDX_XD;
173e84206a6SAaron LI ret = nvmm_vcpu_configure(mach, vcpu, NVMM_VCPU_CONF_CPUID, &cpuid);
174e84206a6SAaron LI if (ret == -1)
175e84206a6SAaron LI err(EXIT_FAILURE, "nvmm_vcpu_configure");
1768368e25fSAaron LI }
1778368e25fSAaron LI
1788368e25fSAaron LI static void
toyvirt_init_seg(struct nvmm_x64_state_seg * seg,int type,int sel,int limit)1798368e25fSAaron LI toyvirt_init_seg(struct nvmm_x64_state_seg *seg, int type, int sel, int limit)
1808368e25fSAaron LI {
1818368e25fSAaron LI seg->selector = sel;
1828368e25fSAaron LI seg->attrib.type = type;
1838368e25fSAaron LI seg->attrib.s = (type & 0b10000) != 0;
1848368e25fSAaron LI seg->attrib.dpl = 0;
1858368e25fSAaron LI seg->attrib.p = 1;
1868368e25fSAaron LI seg->attrib.avl = 1;
1878368e25fSAaron LI seg->attrib.l = 0;
1888368e25fSAaron LI seg->attrib.def = 1;
1898368e25fSAaron LI seg->attrib.g = 1;
1908368e25fSAaron LI seg->limit = limit;
1918368e25fSAaron LI seg->base = 0x00000000;
1928368e25fSAaron LI }
1938368e25fSAaron LI
1948368e25fSAaron LI static void
toyvirt_init(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu,const char * path)1958368e25fSAaron LI toyvirt_init(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
1968368e25fSAaron LI const char *path)
1978368e25fSAaron LI {
1988368e25fSAaron LI struct nvmm_vcpu_state *state = vcpu->state;
1998368e25fSAaron LI uint64_t rip;
2008368e25fSAaron LI
2018368e25fSAaron LI if (nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1)
2028368e25fSAaron LI errx(EXIT_FAILURE, "nvmm_vcpu_getstate");
2038368e25fSAaron LI
2048368e25fSAaron LI /* Default. */
205e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_CS],
206e84206a6SAaron LI 27 /* memory execute read accessed */, 0, 0xFFFFFFFF);
207e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_SS],
208e84206a6SAaron LI 19 /* memory read write accessed */, 0, 0xFFFFFFFF);
209e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_DS],
210e84206a6SAaron LI 19 /* memory read write accessed */, 0, 0xFFFFFFFF);
211e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_ES],
212e84206a6SAaron LI 19 /* memory read write accessed */, 0, 0xFFFFFFFF);
213e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_FS],
214e84206a6SAaron LI 19 /* memory read write accessed */, 0, 0xFFFFFFFF);
215e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_GS],
216e84206a6SAaron LI 19 /* memory read write accessed */, 0, 0xFFFFFFFF);
2178368e25fSAaron LI
2188368e25fSAaron LI /* Blank. */
2198368e25fSAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_GDT], 0, 0, 0x0000FFFF);
2208368e25fSAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_IDT], 0, 0, 0x0000FFFF);
221e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_LDT], 2, 0, 0xFFFFFFFF);
222e84206a6SAaron LI toyvirt_init_seg(&state->segs[NVMM_X64_SEG_TR], 11, 0, 0xFFFFFFFF);
2238368e25fSAaron LI
2248368e25fSAaron LI /* Protected mode enabled. */
2258368e25fSAaron LI state->crs[NVMM_X64_CR_CR0] = CR0_PE | CR0_ET | CR0_NW | CR0_CD;
2268368e25fSAaron LI
2278368e25fSAaron LI /* Map the VM. */
2288368e25fSAaron LI if (elf_map(mach, path, &rip) != 0)
2298368e25fSAaron LI errx(EXIT_FAILURE, "unable to map the vm");
2308368e25fSAaron LI
2318368e25fSAaron LI state->gprs[NVMM_X64_GPR_RIP] = rip; /* jump here */
2328368e25fSAaron LI
2338368e25fSAaron LI if (nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1)
2348368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_setstate");
2358368e25fSAaron LI }
2368368e25fSAaron LI
2378368e25fSAaron LI /* -------------------------------------------------------------------------- */
2388368e25fSAaron LI
2398368e25fSAaron LI static uint8_t toyvirt_prio = 0;
2408368e25fSAaron LI
2418368e25fSAaron LI static struct {
2428368e25fSAaron LI struct nvmm_machine *mach;
2438368e25fSAaron LI struct nvmm_vcpu *vcpu;
2448368e25fSAaron LI } toyvirt;
2458368e25fSAaron LI
2468368e25fSAaron LI /*
2478368e25fSAaron LI * Create mess in the VCPU. Inject random events at regular intervals.
2488368e25fSAaron LI */
2498368e25fSAaron LI static void *
toyvirt_mess(void * arg __unused)250ce7051aeSAaron LI toyvirt_mess(void *arg __unused)
2518368e25fSAaron LI {
2528368e25fSAaron LI struct nvmm_machine *mach = toyvirt.mach;
2538368e25fSAaron LI struct nvmm_vcpu *vcpu = toyvirt.vcpu;
2542efd87c6SAaron LI struct nvmm_vcpu_event event;
2558368e25fSAaron LI
2568368e25fSAaron LI while (1) {
2578368e25fSAaron LI sleep(3);
2588368e25fSAaron LI
2598368e25fSAaron LI /* Inject a #GP */
260ce659a16SAaron LI printf("[+] Inject #GP event\n");
2612efd87c6SAaron LI event.type = NVMM_VCPU_EVENT_EXCP;
2628368e25fSAaron LI event.vector = 13;
2632efd87c6SAaron LI event.u.excp.error = 0;
2648368e25fSAaron LI toyvirt_event_inject(mach, vcpu, &event);
2658368e25fSAaron LI
2668368e25fSAaron LI sleep(3);
2678368e25fSAaron LI
2688368e25fSAaron LI /* Inject an #NMI */
269ce659a16SAaron LI printf("[+] Inject #NMI event\n");
2702efd87c6SAaron LI event.type = NVMM_VCPU_EVENT_INTR;
2718368e25fSAaron LI event.vector = 2;
2728368e25fSAaron LI toyvirt_event_inject(mach, vcpu, &event);
2738368e25fSAaron LI
2748368e25fSAaron LI sleep(3);
2758368e25fSAaron LI
2768368e25fSAaron LI /* Inject an interrupt */
2778368e25fSAaron LI if (15 > toyvirt_prio) {
278ce659a16SAaron LI printf("[+] Inject hardware interrupt event\n");
2792efd87c6SAaron LI event.type = NVMM_VCPU_EVENT_INTR;
2808368e25fSAaron LI event.vector = 200;
2818368e25fSAaron LI toyvirt_event_inject(mach, vcpu, &event);
2828368e25fSAaron LI }
2838368e25fSAaron LI }
2848368e25fSAaron LI
2858368e25fSAaron LI pthread_exit(NULL);
2868368e25fSAaron LI }
2878368e25fSAaron LI
2888368e25fSAaron LI /* -------------------------------------------------------------------------- */
2898368e25fSAaron LI
2908368e25fSAaron LI /*
2918368e25fSAaron LI * Support one MSR: MSR_APICBASE.
2928368e25fSAaron LI */
2938368e25fSAaron LI static int
toycpu_rdmsr(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)294e84206a6SAaron LI toycpu_rdmsr(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
2958368e25fSAaron LI {
2968368e25fSAaron LI struct nvmm_vcpu_state *state = vcpu->state;
2972efd87c6SAaron LI struct nvmm_vcpu_exit *exit = vcpu->exit;
2988368e25fSAaron LI uint64_t val;
2998368e25fSAaron LI
3002efd87c6SAaron LI if (exit->u.rdmsr.msr != MSR_APICBASE) {
3012efd87c6SAaron LI printf("Unknown MSR!\n");
3028368e25fSAaron LI return -1;
3038368e25fSAaron LI }
3048368e25fSAaron LI
3058368e25fSAaron LI if (nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS) == -1)
3068368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_getstate");
3078368e25fSAaron LI
3088368e25fSAaron LI val = APICBASE_BSP | APICBASE_EN | 0xfee00000;
3098368e25fSAaron LI
3108368e25fSAaron LI state->gprs[NVMM_X64_GPR_RAX] = (val & 0xFFFFFFFF);
3118368e25fSAaron LI state->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
3122efd87c6SAaron LI state->gprs[NVMM_X64_GPR_RIP] = exit->u.rdmsr.npc;
3138368e25fSAaron LI
3148368e25fSAaron LI if (nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS) == -1)
3158368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_setstate");
3168368e25fSAaron LI
3178368e25fSAaron LI return 0;
3188368e25fSAaron LI }
3198368e25fSAaron LI
3208368e25fSAaron LI static void
toyvirt_invalid(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)3218368e25fSAaron LI toyvirt_invalid(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
3228368e25fSAaron LI {
3238368e25fSAaron LI struct nvmm_vcpu_state *state = vcpu->state;
3248368e25fSAaron LI
3258368e25fSAaron LI if (nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS) == -1)
3268368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_getstate");
3278368e25fSAaron LI
3288368e25fSAaron LI printf("[!] Invalid exit: rip=%p\n",
3298368e25fSAaron LI (void *)state->gprs[NVMM_X64_GPR_RIP]);
3308368e25fSAaron LI }
3318368e25fSAaron LI
3328368e25fSAaron LI static void
toyvirt_run(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)3338368e25fSAaron LI toyvirt_run(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
3348368e25fSAaron LI {
3352efd87c6SAaron LI struct nvmm_vcpu_exit *exit = vcpu->exit;
3368368e25fSAaron LI pthread_t thid;
3378368e25fSAaron LI int ret;
3388368e25fSAaron LI
3398368e25fSAaron LI toyvirt.mach = mach;
3408368e25fSAaron LI toyvirt.vcpu = vcpu;
3418368e25fSAaron LI pthread_create(&thid, NULL, toyvirt_mess, NULL);
3428368e25fSAaron LI
3438368e25fSAaron LI while (1) {
3448368e25fSAaron LI if (nvmm_vcpu_run(mach, vcpu) == -1)
3458368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_run");
3468368e25fSAaron LI
3472efd87c6SAaron LI toyvirt_prio = exit->exitstate.cr8;
3482efd87c6SAaron LI can_take_int = !exit->exitstate.int_window_exiting;
3492efd87c6SAaron LI can_take_nmi = !exit->exitstate.nmi_window_exiting;
3508368e25fSAaron LI
3518368e25fSAaron LI switch (exit->reason) {
3522efd87c6SAaron LI case NVMM_VCPU_EXIT_NONE:
3538368e25fSAaron LI /*
3548368e25fSAaron LI * A VMEXIT caused by whatever internal reason, that
3558368e25fSAaron LI * we shouldn't take care of. Keep rolling.
3568368e25fSAaron LI */
3578368e25fSAaron LI continue;
3588368e25fSAaron LI
3592efd87c6SAaron LI case NVMM_VCPU_EXIT_IO:
3608368e25fSAaron LI ret = nvmm_assist_io(mach, vcpu);
3618368e25fSAaron LI if (ret == -1)
3628368e25fSAaron LI err(EXIT_FAILURE, "nvmm_assist_io");
3638368e25fSAaron LI continue;
3648368e25fSAaron LI
3652efd87c6SAaron LI case NVMM_VCPU_EXIT_RDMSR:
366e84206a6SAaron LI toycpu_rdmsr(mach, vcpu);
3678368e25fSAaron LI continue;
3688368e25fSAaron LI
3692efd87c6SAaron LI case NVMM_VCPU_EXIT_MEMORY:
3708368e25fSAaron LI ret = nvmm_assist_mem(mach, vcpu);
3718368e25fSAaron LI if (ret == -1)
3728368e25fSAaron LI err(EXIT_FAILURE, "nvmm_assist_mem");
3738368e25fSAaron LI continue;
3748368e25fSAaron LI
3752efd87c6SAaron LI case NVMM_VCPU_EXIT_INT_READY:
3762efd87c6SAaron LI case NVMM_VCPU_EXIT_NMI_READY:
377ce659a16SAaron LI printf("[+] Machine ready to INT/NMI\n");
3788368e25fSAaron LI toyvirt_event_reinject(mach, vcpu);
3798368e25fSAaron LI return;
3808368e25fSAaron LI
3812efd87c6SAaron LI case NVMM_VCPU_EXIT_SHUTDOWN:
3828368e25fSAaron LI /* Stop the VM here. */
3838368e25fSAaron LI printf("[+] Machine received shutdown\n");
3848368e25fSAaron LI return;
3858368e25fSAaron LI
3862efd87c6SAaron LI case NVMM_VCPU_EXIT_INVALID:
3878368e25fSAaron LI default:
3888368e25fSAaron LI toyvirt_invalid(mach, vcpu);
3898368e25fSAaron LI return;
3908368e25fSAaron LI }
3918368e25fSAaron LI }
3928368e25fSAaron LI }
3938368e25fSAaron LI
main(int argc,char * argv[])3948368e25fSAaron LI int main(int argc, char *argv[])
3958368e25fSAaron LI {
3968368e25fSAaron LI struct nvmm_machine mach;
3978368e25fSAaron LI struct nvmm_vcpu vcpu;
3988368e25fSAaron LI
3998368e25fSAaron LI if (argc != 2)
4008368e25fSAaron LI errx(EXIT_FAILURE, "usage: %s file-path", argv[0]);
4018368e25fSAaron LI
4022efd87c6SAaron LI if (nvmm_init() == -1)
4032efd87c6SAaron LI err(EXIT_FAILURE, "nvmm_init");
4042efd87c6SAaron LI printf("[+] NVMM initialization succeeded\n");
4058368e25fSAaron LI
4068368e25fSAaron LI if (nvmm_machine_create(&mach) == -1)
4078368e25fSAaron LI err(EXIT_FAILURE, "nvmm_machine_create");
4088368e25fSAaron LI printf("[+] Machine creation succeeded\n");
4098368e25fSAaron LI
4108368e25fSAaron LI if (nvmm_vcpu_create(&mach, 120, &vcpu) == -1)
4118368e25fSAaron LI err(EXIT_FAILURE, "nvmm_vcpu_create");
4128368e25fSAaron LI printf("[+] VCPU creation succeeded\n");
4138368e25fSAaron LI
414e84206a6SAaron LI toyvirt_vcpu_configure(&mach, &vcpu);
415e84206a6SAaron LI printf("[+] VCPU configuration succeeded\n");
4168368e25fSAaron LI
4178368e25fSAaron LI toyvirt_init(&mach, &vcpu, argv[1]);
4188368e25fSAaron LI printf("[+] State set\n");
4198368e25fSAaron LI
4208368e25fSAaron LI toyvirt_run(&mach, &vcpu);
4218368e25fSAaron LI printf("[+] Machine execution successful\n");
4228368e25fSAaron LI
4238368e25fSAaron LI if (nvmm_machine_destroy(&mach) == -1)
4248368e25fSAaron LI err(EXIT_FAILURE, "nvmm_machine_destroy");
4258368e25fSAaron LI
4268368e25fSAaron LI printf("[+] Machine destroyed\n");
4278368e25fSAaron LI
4288368e25fSAaron LI return 0;
4298368e25fSAaron LI }
430