Module Name: src Committed By: maxv Date: Sat Jun 8 07:27:44 UTC 2019
Modified Files: src/lib/libnvmm: libnvmm.3 libnvmm.c libnvmm_x86.c nvmm.h src/tests/lib/libnvmm: h_io_assist.c h_mem_assist.c Log Message: Change the NVMM API to reduce data movements. Sent to tech-kern@. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/lib/libnvmm/libnvmm.3 cvs rdiff -u -r1.13 -r1.14 src/lib/libnvmm/libnvmm.c cvs rdiff -u -r1.30 -r1.31 src/lib/libnvmm/libnvmm_x86.c cvs rdiff -u -r1.11 -r1.12 src/lib/libnvmm/nvmm.h cvs rdiff -u -r1.7 -r1.8 src/tests/lib/libnvmm/h_io_assist.c cvs rdiff -u -r1.10 -r1.11 src/tests/lib/libnvmm/h_mem_assist.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libnvmm/libnvmm.3 diff -u src/lib/libnvmm/libnvmm.3:1.18 src/lib/libnvmm/libnvmm.3:1.19 --- src/lib/libnvmm/libnvmm.3:1.18 Sat May 11 07:44:00 2019 +++ src/lib/libnvmm/libnvmm.3 Sat Jun 8 07:27:44 2019 @@ -1,4 +1,4 @@ -.\" $NetBSD: libnvmm.3,v 1.18 2019/05/11 07:44:00 maxv Exp $ +.\" $NetBSD: libnvmm.3,v 1.19 2019/06/08 07:27:44 maxv Exp $ .\" .\" Copyright (c) 2018, 2019 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd May 11, 2019 +.Dd May 30, 2019 .Dt LIBNVMM 3 .Os .Sh NAME @@ -47,21 +47,20 @@ .Fn nvmm_machine_configure "struct nvmm_machine *mach" "uint64_t op" \ "void *conf" .Ft int -.Fn nvmm_vcpu_create "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" +.Fn nvmm_vcpu_create "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ + "struct nvmm_vcpu *vcpu" .Ft int -.Fn nvmm_vcpu_destroy "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" +.Fn nvmm_vcpu_destroy "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" .Ft int -.Fn nvmm_vcpu_getstate "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ - "void *state" "uint64_t flags" +.Fn nvmm_vcpu_getstate "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" \ + "uint64_t flags" .Ft int -.Fn nvmm_vcpu_setstate "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ - "void *state" "uint64_t flags" +.Fn nvmm_vcpu_setstate "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" \ + "uint64_t flags" .Ft int -.Fn nvmm_vcpu_inject "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ - "struct nvmm_event *event" +.Fn nvmm_vcpu_inject "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" .Ft int -.Fn nvmm_vcpu_run "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ - "struct nvmm_exit *exit" +.Fn nvmm_vcpu_run "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" .Ft int .Fn nvmm_hva_map "struct nvmm_machine *mach" "uintptr_t hva" "size_t size" .Ft int @@ -73,17 +72,15 @@ .Fn nvmm_gpa_unmap "struct nvmm_machine *mach" "uintptr_t hva" "gpaddr_t gpa" \ "size_t size" .Ft int -.Fn nvmm_gva_to_gpa "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ +.Fn nvmm_gva_to_gpa "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" \ "gvaddr_t gva" "gpaddr_t *gpa" "nvmm_prot_t *prot" .Ft int .Fn nvmm_gpa_to_hva "struct nvmm_machine *mach" "gpaddr_t gpa" \ "uintptr_t *hva" "nvmm_prot_t *prot" .Ft int -.Fn nvmm_assist_io "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ - "struct nvmm_exit *exit" +.Fn nvmm_assist_io "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" .Ft int -.Fn nvmm_assist_mem "struct nvmm_machine *mach" "nvmm_cpuid_t cpuid" \ - "struct nvmm_exit *exit" +.Fn nvmm_assist_mem "struct nvmm_machine *mach" "struct nvmm_vcpu *vcpu" .Sh DESCRIPTION .Nm provides a library for emulator software to handle hardware-accelerated virtual @@ -95,6 +92,8 @@ Emulator software should not attempt to should use the API provided by .Nm to manage virtual machines. +A virtual CPU is described by a public structure, +.Cd nvmm_vcpu . .Pp .Fn nvmm_capability gets the capabilities of NVMM. @@ -124,61 +123,61 @@ describes the value of the parameter. creates a virtual CPU in the machine .Fa mach , giving it the CPU id -.Fa cpuid . +.Fa cpuid , +and initializes +.Fa vcpu . .Pp .Fn nvmm_vcpu_destroy destroys the virtual CPU identified by -.Fa cpuid +.Fa vcpu in the machine .Fa mach . .Pp .Fn nvmm_vcpu_getstate gets the state of the virtual CPU identified by -.Fa cpuid +.Fa vcpu in the machine .Fa mach . -The -.Fa state -argument is the address of a state area, and .Fa flags is the bitmap of the components that are to be retrieved. +The components are located in +.Fa vcpu->state . See .Sx VCPU State Area below for details. .Pp .Fn nvmm_vcpu_setstate sets the state of the virtual CPU identified by -.Fa cpuid +.Fa vcpu in the machine .Fa mach . -The -.Fa state -argument is the address of a state area, and .Fa flags is the bitmap of the components that are to be set. +The components are located in +.Fa vcpu->state . See .Sx VCPU State Area below for details. .Pp .Fn nvmm_vcpu_inject injects into the CPU identified by -.Fa cpuid +.Fa vcpu of the machine .Fa mach an event described by -.Fa event . +.Fa vcpu->event . See .Sx Event Injection below for details. .Pp .Fn nvmm_vcpu_run runs the CPU identified by -.Fa cpuid +.Fa vcpu in the machine .Fa mach , until a VM exit is triggered. The -.Fa exit +.Fa vcpu->exit structure is filled to indicate the exit reason, and the associated parameters if any. .Pp @@ -220,7 +219,7 @@ from the machine .Pp .Fn nvmm_gva_to_gpa translates, on the CPU -.Fa cpuid +.Fa vcpu from the machine .Fa mach , the guest virtual address given in @@ -246,9 +245,9 @@ must be page-aligned. .Pp .Fn nvmm_assist_io emulates the I/O operation described in -.Fa exit +.Fa vcpu->exit on CPU -.Fa cpuid +.Fa vcpu from machine .Fa mach . See @@ -257,9 +256,9 @@ below for details. .Pp .Fn nvmm_assist_mem emulates the Mem operation described in -.Fa exit +.Fa vcpu->exit on CPU -.Fa cpuid +.Fa vcpu from machine .Fa mach . See @@ -364,6 +363,7 @@ struct nvmm_x64_state { struct nvmm_x64_state_intr intr; struct fxsave fpu; }; +#define nvmm_vcpu_state nvmm_x64_state .Ed .Pp Refer to functional examples to see precisely how to use this structure. @@ -379,6 +379,46 @@ During VM exits, a partial VCPU state ar see .Sx Exit Reasons below for details. +.Ss VCPU Programming Model +A VCPU is described by a public structure, +.Cd nvmm_vcpu : +.Bd -literal +struct nvmm_vcpu { + nvmm_cpuid_t cpuid; + struct nvmm_vcpu_state *state; + struct nvmm_event *event; + struct nvmm_exit *exit; +}; +.Ed +.Pp +This structure is used both publicly by emulator software and internally by +.Nm . +Emulator software should not modify the pointers of this structure, because +they are initialized to special values by +.Nm . +.Pp +A call to +.Fn nvmm_vcpu_getstate +will fetch the relevant parts of the VCPU state and put them in +.Fa vcpu->state . +A call to +.Fn nvmm_vcpu_setstate +will install in the VCPU the relevant parts of +.Fa vcpu->state . +A call to +.Fn nvmm_vcpu_inject +will inject in the VCPU the event in +.Fa vcpu->event . +A call to +.Fn nvmm_vcpu_run +will fill +.Fa vcpu->exit +with the VCPU exit information. +.Pp +If emulator software uses several threads, a VCPU should be associated with +only one thread, and only this thread should perform VCPU modifications. +Emulator software should not modify the state of a VCPU with several +different threads. .Ss Exit Reasons The .Cd nvmm_exit Index: src/lib/libnvmm/libnvmm.c diff -u src/lib/libnvmm/libnvmm.c:1.13 src/lib/libnvmm/libnvmm.c:1.14 --- src/lib/libnvmm/libnvmm.c:1.13 Sat May 11 07:31:57 2019 +++ src/lib/libnvmm/libnvmm.c Sat Jun 8 07:27:44 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: libnvmm.c,v 1.13 2019/05/11 07:31:57 maxv Exp $ */ +/* $NetBSD: libnvmm.c,v 1.14 2019/06/08 07:27:44 maxv Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -224,7 +224,6 @@ nvmm_machine_create(struct nvmm_machine memset(mach, 0, sizeof(*mach)); mach->machid = args.machid; mach->pages = pages; - mach->npages = __capability.max_vcpus; mach->areas = areas; return 0; @@ -272,7 +271,8 @@ nvmm_machine_configure(struct nvmm_machi } int -nvmm_vcpu_create(struct nvmm_machine *mach, nvmm_cpuid_t cpuid) +nvmm_vcpu_create(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, + struct nvmm_vcpu *vcpu) { struct nvmm_ioc_vcpu_create args; struct nvmm_comm_page *comm; @@ -292,41 +292,42 @@ nvmm_vcpu_create(struct nvmm_machine *ma mach->pages[cpuid] = comm; + vcpu->cpuid = cpuid; + vcpu->state = &comm->state; + vcpu->event = &comm->event; + vcpu->exit = malloc(sizeof(*vcpu->exit)); + return 0; } int -nvmm_vcpu_destroy(struct nvmm_machine *mach, nvmm_cpuid_t cpuid) +nvmm_vcpu_destroy(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { struct nvmm_ioc_vcpu_destroy args; struct nvmm_comm_page *comm; int ret; args.machid = mach->machid; - args.cpuid = cpuid; + args.cpuid = vcpu->cpuid; ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_DESTROY, &args); if (ret == -1) return -1; - comm = mach->pages[cpuid]; + comm = mach->pages[vcpu->cpuid]; munmap(comm, PAGE_SIZE); + free(vcpu->exit); return 0; } int -nvmm_vcpu_setstate(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, - void *state, uint64_t flags) +nvmm_vcpu_setstate(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu, + uint64_t flags) { struct nvmm_comm_page *comm; - if (__predict_false(cpuid >= mach->npages)) { - return -1; - } - comm = mach->pages[cpuid]; - - nvmm_arch_copystate(&comm->state, state, flags); + comm = mach->pages[vcpu->cpuid]; comm->state_commit |= flags; comm->state_cached |= flags; @@ -334,68 +335,57 @@ nvmm_vcpu_setstate(struct nvmm_machine * } int -nvmm_vcpu_getstate(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, - void *state, uint64_t flags) +nvmm_vcpu_getstate(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu, + uint64_t flags) { struct nvmm_ioc_vcpu_getstate args; struct nvmm_comm_page *comm; int ret; - if (__predict_false(cpuid >= mach->npages)) { - return -1; - } - comm = mach->pages[cpuid]; + comm = mach->pages[vcpu->cpuid]; if (__predict_true((flags & ~comm->state_cached) == 0)) { - goto out; + return 0; } comm->state_wanted = flags & ~comm->state_cached; args.machid = mach->machid; - args.cpuid = cpuid; + args.cpuid = vcpu->cpuid; ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_GETSTATE, &args); if (ret == -1) return -1; -out: - nvmm_arch_copystate(state, &comm->state, flags); return 0; } int -nvmm_vcpu_inject(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, - struct nvmm_event *event) +nvmm_vcpu_inject(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { struct nvmm_comm_page *comm; - if (__predict_false(cpuid >= mach->npages)) { - return -1; - } - comm = mach->pages[cpuid]; - - memcpy(&comm->event, event, sizeof(comm->event)); + comm = mach->pages[vcpu->cpuid]; comm->event_commit = true; return 0; } int -nvmm_vcpu_run(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, - struct nvmm_exit *exit) +nvmm_vcpu_run(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { struct nvmm_ioc_vcpu_run args; int ret; args.machid = mach->machid; - args.cpuid = cpuid; + args.cpuid = vcpu->cpuid; memset(&args.exit, 0, sizeof(args.exit)); ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_RUN, &args); if (ret == -1) return -1; - memcpy(exit, &args.exit, sizeof(args.exit)); + /* No comm support yet, just copy. */ + memcpy(vcpu->exit, &args.exit, sizeof(args.exit)); return 0; } Index: src/lib/libnvmm/libnvmm_x86.c diff -u src/lib/libnvmm/libnvmm_x86.c:1.30 src/lib/libnvmm/libnvmm_x86.c:1.31 --- src/lib/libnvmm/libnvmm_x86.c:1.30 Sat May 11 07:31:57 2019 +++ src/lib/libnvmm/libnvmm_x86.c Sat Jun 8 07:27:44 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: libnvmm_x86.c,v 1.30 2019/05/11 07:31:57 maxv Exp $ */ +/* $NetBSD: libnvmm_x86.c,v 1.31 2019/06/08 07:27:44 maxv Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -50,44 +50,13 @@ /* -------------------------------------------------------------------------- */ -static void -nvmm_arch_copystate(void *_dst, void *_src, uint64_t flags) -{ - struct nvmm_x64_state *src = _src; - struct nvmm_x64_state *dst = _dst; - - if (flags & NVMM_X64_STATE_GPRS) { - memcpy(dst->gprs, src->gprs, sizeof(dst->gprs)); - } - if (flags & NVMM_X64_STATE_SEGS) { - memcpy(dst->segs, src->segs, sizeof(dst->segs)); - } - if (flags & NVMM_X64_STATE_CRS) { - memcpy(dst->crs, src->crs, sizeof(dst->crs)); - } - if (flags & NVMM_X64_STATE_DRS) { - memcpy(dst->drs, src->drs, sizeof(dst->drs)); - } - if (flags & NVMM_X64_STATE_MSRS) { - memcpy(dst->msrs, src->msrs, sizeof(dst->msrs)); - } - if (flags & NVMM_X64_STATE_INTR) { - memcpy(&dst->intr, &src->intr, sizeof(dst->intr)); - } - if (flags & NVMM_X64_STATE_FPU) { - memcpy(&dst->fpu, &src->fpu, sizeof(dst->fpu)); - } -} - -/* -------------------------------------------------------------------------- */ - /* * Undocumented debugging function. Helpful. */ int -nvmm_vcpu_dump(struct nvmm_machine *mach, nvmm_cpuid_t cpuid) +nvmm_vcpu_dump(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { - struct nvmm_x64_state state; + struct nvmm_x64_state *state = vcpu->state; uint16_t *attr; size_t i; int ret; @@ -96,31 +65,31 @@ nvmm_vcpu_dump(struct nvmm_machine *mach "ES", "CS", "SS", "DS", "FS", "GS", "GDT", "IDT", "LDT", "TR" }; - ret = nvmm_vcpu_getstate(mach, cpuid, &state, NVMM_X64_STATE_ALL); + ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_ALL); if (ret == -1) return -1; - printf("+ VCPU id=%d\n", (int)cpuid); - printf("| -> RIP=%"PRIx64"\n", state.gprs[NVMM_X64_GPR_RIP]); - printf("| -> RSP=%"PRIx64"\n", state.gprs[NVMM_X64_GPR_RSP]); - printf("| -> RAX=%"PRIx64"\n", state.gprs[NVMM_X64_GPR_RAX]); - printf("| -> RBX=%"PRIx64"\n", state.gprs[NVMM_X64_GPR_RBX]); - printf("| -> RCX=%"PRIx64"\n", state.gprs[NVMM_X64_GPR_RCX]); - printf("| -> RFLAGS=%p\n", (void *)state.gprs[NVMM_X64_GPR_RFLAGS]); + printf("+ VCPU id=%d\n", (int)vcpu->cpuid); + printf("| -> RIP=%"PRIx64"\n", state->gprs[NVMM_X64_GPR_RIP]); + printf("| -> RSP=%"PRIx64"\n", state->gprs[NVMM_X64_GPR_RSP]); + printf("| -> RAX=%"PRIx64"\n", state->gprs[NVMM_X64_GPR_RAX]); + printf("| -> RBX=%"PRIx64"\n", state->gprs[NVMM_X64_GPR_RBX]); + printf("| -> RCX=%"PRIx64"\n", state->gprs[NVMM_X64_GPR_RCX]); + printf("| -> RFLAGS=%p\n", (void *)state->gprs[NVMM_X64_GPR_RFLAGS]); for (i = 0; i < NVMM_X64_NSEG; i++) { - attr = (uint16_t *)&state.segs[i].attrib; + attr = (uint16_t *)&state->segs[i].attrib; printf("| -> %s: sel=0x%x base=%"PRIx64", limit=%x, attrib=%x\n", segnames[i], - state.segs[i].selector, - state.segs[i].base, - state.segs[i].limit, + state->segs[i].selector, + state->segs[i].base, + state->segs[i].limit, *attr); } - printf("| -> MSR_EFER=%"PRIx64"\n", state.msrs[NVMM_X64_MSR_EFER]); - printf("| -> CR0=%"PRIx64"\n", state.crs[NVMM_X64_CR_CR0]); - printf("| -> CR3=%"PRIx64"\n", state.crs[NVMM_X64_CR_CR3]); - printf("| -> CR4=%"PRIx64"\n", state.crs[NVMM_X64_CR_CR4]); - printf("| -> CR8=%"PRIx64"\n", state.crs[NVMM_X64_CR_CR8]); + printf("| -> MSR_EFER=%"PRIx64"\n", state->msrs[NVMM_X64_MSR_EFER]); + printf("| -> CR0=%"PRIx64"\n", state->crs[NVMM_X64_CR_CR0]); + printf("| -> CR3=%"PRIx64"\n", state->crs[NVMM_X64_CR_CR3]); + printf("| -> CR4=%"PRIx64"\n", state->crs[NVMM_X64_CR_CR4]); + printf("| -> CR8=%"PRIx64"\n", state->crs[NVMM_X64_CR_CR8]); return 0; } @@ -456,18 +425,18 @@ x86_gva_to_gpa(struct nvmm_machine *mach } int -nvmm_gva_to_gpa(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, +nvmm_gva_to_gpa(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu, gvaddr_t gva, gpaddr_t *gpa, nvmm_prot_t *prot) { - struct nvmm_x64_state state; + struct nvmm_x64_state *state = vcpu->state; int ret; - ret = nvmm_vcpu_getstate(mach, cpuid, &state, + ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_CRS | NVMM_X64_STATE_MSRS); if (ret == -1) return -1; - return x86_gva_to_gpa(mach, &state, gva, gpa, prot); + return x86_gva_to_gpa(mach, state, gva, gpa, prot); } /* -------------------------------------------------------------------------- */ @@ -720,10 +689,10 @@ assist_io_batch(struct nvmm_machine *mac } int -nvmm_assist_io(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, - struct nvmm_exit *exit) +nvmm_assist_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { - struct nvmm_x64_state state; + struct nvmm_x64_state *state = vcpu->state; + struct nvmm_exit *exit = vcpu->exit; struct nvmm_io io; uint64_t cnt = 0; /* GCC */ uint8_t iobuf[8]; @@ -743,21 +712,21 @@ nvmm_assist_io(struct nvmm_machine *mach io.size = exit->u.io.operand_size; io.data = iobuf; - ret = nvmm_vcpu_getstate(mach, cpuid, &state, + ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS | NVMM_X64_STATE_SEGS | NVMM_X64_STATE_CRS | NVMM_X64_STATE_MSRS); if (ret == -1) return -1; if (exit->u.io.rep) { - cnt = rep_get_cnt(&state, exit->u.io.address_size); + cnt = rep_get_cnt(state, exit->u.io.address_size); if (__predict_false(cnt == 0)) { - state.gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc; + state->gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc; goto out; } } - if (__predict_false(state.gprs[NVMM_X64_GPR_RFLAGS] & PSL_D)) { + if (__predict_false(state->gprs[NVMM_X64_GPR_RFLAGS] & PSL_D)) { psld = true; } @@ -771,7 +740,7 @@ nvmm_assist_io(struct nvmm_machine *mach reg = NVMM_X64_GPR_RSI; } - gva = state.gprs[reg]; + gva = state->gprs[reg]; gva &= size_to_mask(exit->u.io.address_size); if (exit->u.io.seg != -1) { @@ -780,25 +749,25 @@ nvmm_assist_io(struct nvmm_machine *mach if (io.in) { seg = NVMM_X64_SEG_ES; } else { - seg = fetch_segment(mach, &state); + seg = fetch_segment(mach, state); if (seg == -1) return -1; } } - if (__predict_true(is_long_mode(&state))) { + if (__predict_true(is_long_mode(state))) { if (seg == NVMM_X64_SEG_GS || seg == NVMM_X64_SEG_FS) { - segment_apply(&state.segs[seg], &gva); + segment_apply(&state->segs[seg], &gva); } } else { - ret = segment_check(&state.segs[seg], gva, io.size); + ret = segment_check(&state->segs[seg], gva, io.size); if (ret == -1) return -1; - segment_apply(&state.segs[seg], &gva); + segment_apply(&state->segs[seg], &gva); } if (exit->u.io.rep && !psld) { - iocnt = assist_io_batch(mach, &state, &io, gva, cnt); + iocnt = assist_io_batch(mach, state, &io, gva, cnt); if (iocnt == -1) return -1; goto done; @@ -807,9 +776,9 @@ nvmm_assist_io(struct nvmm_machine *mach if (!io.in) { if (!exit->u.io.str) { - memcpy(io.data, &state.gprs[NVMM_X64_GPR_RAX], io.size); + memcpy(io.data, &state->gprs[NVMM_X64_GPR_RAX], io.size); } else { - ret = read_guest_memory(mach, &state, gva, io.data, + ret = read_guest_memory(mach, state, gva, io.data, io.size); if (ret == -1) return -1; @@ -820,13 +789,13 @@ nvmm_assist_io(struct nvmm_machine *mach if (io.in) { if (!exit->u.io.str) { - memcpy(&state.gprs[NVMM_X64_GPR_RAX], io.data, io.size); + memcpy(&state->gprs[NVMM_X64_GPR_RAX], io.data, io.size); if (io.size == 4) { /* Zero-extend to 64 bits. */ - state.gprs[NVMM_X64_GPR_RAX] &= size_to_mask(4); + state->gprs[NVMM_X64_GPR_RAX] &= size_to_mask(4); } } else { - ret = write_guest_memory(mach, &state, gva, io.data, + ret = write_guest_memory(mach, state, gva, io.data, io.size); if (ret == -1) return -1; @@ -836,24 +805,24 @@ nvmm_assist_io(struct nvmm_machine *mach done: if (exit->u.io.str) { if (__predict_false(psld)) { - state.gprs[reg] -= iocnt * io.size; + state->gprs[reg] -= iocnt * io.size; } else { - state.gprs[reg] += iocnt * io.size; + state->gprs[reg] += iocnt * io.size; } } if (exit->u.io.rep) { cnt -= iocnt; - rep_set_cnt(&state, exit->u.io.address_size, cnt); + rep_set_cnt(state, exit->u.io.address_size, cnt); if (cnt == 0) { - state.gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc; + state->gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc; } } else { - state.gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc; + state->gprs[NVMM_X64_GPR_RIP] = exit->u.io.npc; } out: - ret = nvmm_vcpu_setstate(mach, cpuid, &state, NVMM_X64_STATE_GPRS); + ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS); if (ret == -1) return -1; @@ -3141,10 +3110,10 @@ assist_mem_single(struct nvmm_machine *m } int -nvmm_assist_mem(struct nvmm_machine *mach, nvmm_cpuid_t cpuid, - struct nvmm_exit *exit) +nvmm_assist_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { - struct nvmm_x64_state state; + struct nvmm_x64_state *state = vcpu->state; + struct nvmm_exit *exit = vcpu->exit; struct x86_instr instr; uint64_t cnt = 0; /* GCC */ int ret; @@ -3154,7 +3123,7 @@ nvmm_assist_mem(struct nvmm_machine *mac return -1; } - ret = nvmm_vcpu_getstate(mach, cpuid, &state, + ret = nvmm_vcpu_getstate(mach, vcpu, NVMM_X64_STATE_GPRS | NVMM_X64_STATE_SEGS | NVMM_X64_STATE_CRS | NVMM_X64_STATE_MSRS); if (ret == -1) @@ -3165,30 +3134,30 @@ nvmm_assist_mem(struct nvmm_machine *mac * The instruction was not fetched from the kernel. Fetch * it ourselves. */ - ret = fetch_instruction(mach, &state, exit); + ret = fetch_instruction(mach, state, exit); if (ret == -1) return -1; } ret = x86_decode(exit->u.mem.inst_bytes, exit->u.mem.inst_len, - &instr, &state); + &instr, state); if (ret == -1) { errno = ENODEV; return -1; } if (instr.legpref.rep || instr.legpref.repn) { - cnt = rep_get_cnt(&state, instr.address_size); + cnt = rep_get_cnt(state, instr.address_size); if (__predict_false(cnt == 0)) { - state.gprs[NVMM_X64_GPR_RIP] += instr.len; + state->gprs[NVMM_X64_GPR_RIP] += instr.len; goto out; } } if (instr.opcode->movs) { - ret = assist_mem_double(mach, &state, &instr); + ret = assist_mem_double(mach, state, &instr); } else { - ret = assist_mem_single(mach, &state, &instr, exit); + ret = assist_mem_single(mach, state, &instr, exit); } if (ret == -1) { errno = ENODEV; @@ -3197,20 +3166,20 @@ nvmm_assist_mem(struct nvmm_machine *mac if (instr.legpref.rep || instr.legpref.repn) { cnt -= 1; - rep_set_cnt(&state, instr.address_size, cnt); + rep_set_cnt(state, instr.address_size, cnt); if (cnt == 0) { - state.gprs[NVMM_X64_GPR_RIP] += instr.len; + state->gprs[NVMM_X64_GPR_RIP] += instr.len; } else if (__predict_false(instr.legpref.repn)) { - if (state.gprs[NVMM_X64_GPR_RFLAGS] & PSL_Z) { - state.gprs[NVMM_X64_GPR_RIP] += instr.len; + if (state->gprs[NVMM_X64_GPR_RFLAGS] & PSL_Z) { + state->gprs[NVMM_X64_GPR_RIP] += instr.len; } } } else { - state.gprs[NVMM_X64_GPR_RIP] += instr.len; + state->gprs[NVMM_X64_GPR_RIP] += instr.len; } out: - ret = nvmm_vcpu_setstate(mach, cpuid, &state, NVMM_X64_STATE_GPRS); + ret = nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_GPRS); if (ret == -1) return -1; Index: src/lib/libnvmm/nvmm.h diff -u src/lib/libnvmm/nvmm.h:1.11 src/lib/libnvmm/nvmm.h:1.12 --- src/lib/libnvmm/nvmm.h:1.11 Sat May 11 07:31:57 2019 +++ src/lib/libnvmm/nvmm.h Sat Jun 8 07:27:44 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: nvmm.h,v 1.11 2019/05/11 07:31:57 maxv Exp $ */ +/* $NetBSD: nvmm.h,v 1.12 2019/06/08 07:27:44 maxv Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -60,11 +60,17 @@ struct nvmm_callbacks { struct nvmm_machine { nvmm_machid_t machid; struct nvmm_comm_page **pages; - size_t npages; void *areas; /* opaque */ struct nvmm_callbacks cbs; }; +struct nvmm_vcpu { + nvmm_cpuid_t cpuid; + struct nvmm_vcpu_state *state; + struct nvmm_event *event; + struct nvmm_exit *exit; +}; + #define NVMM_MACH_CONF_CALLBACKS NVMM_MACH_CONF_LIBNVMM_BEGIN #define NVMM_PROT_READ 0x01 @@ -80,28 +86,28 @@ int nvmm_machine_create(struct nvmm_mach int nvmm_machine_destroy(struct nvmm_machine *); int nvmm_machine_configure(struct nvmm_machine *, uint64_t, void *); -int nvmm_vcpu_create(struct nvmm_machine *, nvmm_cpuid_t); -int nvmm_vcpu_destroy(struct nvmm_machine *, nvmm_cpuid_t); -int nvmm_vcpu_setstate(struct nvmm_machine *, nvmm_cpuid_t, void *, uint64_t); -int nvmm_vcpu_getstate(struct nvmm_machine *, nvmm_cpuid_t, void *, uint64_t); -int nvmm_vcpu_inject(struct nvmm_machine *, nvmm_cpuid_t, struct nvmm_event *); -int nvmm_vcpu_run(struct nvmm_machine *, nvmm_cpuid_t, struct nvmm_exit *); +int nvmm_vcpu_create(struct nvmm_machine *, nvmm_cpuid_t, struct nvmm_vcpu *); +int nvmm_vcpu_destroy(struct nvmm_machine *, struct nvmm_vcpu *); +int nvmm_vcpu_setstate(struct nvmm_machine *, struct nvmm_vcpu *, uint64_t); +int nvmm_vcpu_getstate(struct nvmm_machine *, struct nvmm_vcpu *, uint64_t); +int nvmm_vcpu_inject(struct nvmm_machine *, struct nvmm_vcpu *); +int nvmm_vcpu_run(struct nvmm_machine *, struct nvmm_vcpu *); int nvmm_gpa_map(struct nvmm_machine *, uintptr_t, gpaddr_t, size_t, int); int nvmm_gpa_unmap(struct nvmm_machine *, uintptr_t, gpaddr_t, size_t); int nvmm_hva_map(struct nvmm_machine *, uintptr_t, size_t); int nvmm_hva_unmap(struct nvmm_machine *, uintptr_t, size_t); -int nvmm_gva_to_gpa(struct nvmm_machine *, nvmm_cpuid_t, gvaddr_t, gpaddr_t *, +int nvmm_gva_to_gpa(struct nvmm_machine *, struct nvmm_vcpu *, gvaddr_t, gpaddr_t *, nvmm_prot_t *); int nvmm_gpa_to_hva(struct nvmm_machine *, gpaddr_t, uintptr_t *, nvmm_prot_t *); -int nvmm_assist_io(struct nvmm_machine *, nvmm_cpuid_t, struct nvmm_exit *); -int nvmm_assist_mem(struct nvmm_machine *, nvmm_cpuid_t, struct nvmm_exit *); +int nvmm_assist_io(struct nvmm_machine *, struct nvmm_vcpu *); +int nvmm_assist_mem(struct nvmm_machine *, struct nvmm_vcpu *); int nvmm_ctl(int, void *, size_t); -int nvmm_vcpu_dump(struct nvmm_machine *, nvmm_cpuid_t); +int nvmm_vcpu_dump(struct nvmm_machine *, struct nvmm_vcpu *); #endif /* _LIBNVMM_H_ */ Index: src/tests/lib/libnvmm/h_io_assist.c diff -u src/tests/lib/libnvmm/h_io_assist.c:1.7 src/tests/lib/libnvmm/h_io_assist.c:1.8 --- src/tests/lib/libnvmm/h_io_assist.c:1.7 Sat May 11 07:31:57 2019 +++ src/tests/lib/libnvmm/h_io_assist.c Sat Jun 8 07:27:44 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: h_io_assist.c,v 1.7 2019/05/11 07:31:57 maxv Exp $ */ +/* $NetBSD: h_io_assist.c,v 1.8 2019/06/08 07:27:44 maxv Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -71,33 +71,33 @@ init_seg(struct nvmm_x64_state_seg *seg, } static void -reset_machine(struct nvmm_machine *mach) +reset_machine(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { - struct nvmm_x64_state state; + struct nvmm_x64_state *state = vcpu->state; - memset(&state, 0, sizeof(state)); + memset(state, 0, sizeof(*state)); /* Default. */ - state.gprs[NVMM_X64_GPR_RFLAGS] = PSL_MBO; - init_seg(&state.segs[NVMM_X64_SEG_CS], SDT_MEMERA, GSEL(GCODE_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_SS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_DS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_ES], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_FS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_GS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + state->gprs[NVMM_X64_GPR_RFLAGS] = PSL_MBO; + init_seg(&state->segs[NVMM_X64_SEG_CS], SDT_MEMERA, GSEL(GCODE_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_SS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_DS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_ES], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_FS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_GS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); /* Blank. */ - init_seg(&state.segs[NVMM_X64_SEG_GDT], 0, 0); - init_seg(&state.segs[NVMM_X64_SEG_IDT], 0, 0); - init_seg(&state.segs[NVMM_X64_SEG_LDT], SDT_SYSLDT, 0); - init_seg(&state.segs[NVMM_X64_SEG_TR], SDT_SYS386BSY, 0); + init_seg(&state->segs[NVMM_X64_SEG_GDT], 0, 0); + init_seg(&state->segs[NVMM_X64_SEG_IDT], 0, 0); + init_seg(&state->segs[NVMM_X64_SEG_LDT], SDT_SYSLDT, 0); + init_seg(&state->segs[NVMM_X64_SEG_TR], SDT_SYS386BSY, 0); /* Protected mode enabled. */ - state.crs[NVMM_X64_CR_CR0] = CR0_PG|CR0_PE|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM; + state->crs[NVMM_X64_CR_CR0] = CR0_PG|CR0_PE|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM; /* 64bit mode enabled. */ - state.crs[NVMM_X64_CR_CR4] = CR4_PAE; - state.msrs[NVMM_X64_MSR_EFER] = EFER_LME | EFER_SCE | EFER_LMA; + state->crs[NVMM_X64_CR_CR4] = CR4_PAE; + state->msrs[NVMM_X64_MSR_EFER] = EFER_LME | EFER_SCE | EFER_LMA; /* Stolen from x86/pmap.c */ #define PATENTRY(n, type) (type << ((n) * 8)) @@ -107,18 +107,18 @@ reset_machine(struct nvmm_machine *mach) #define PAT_WP 0x5ULL #define PAT_WB 0x6ULL #define PAT_UCMINUS 0x7ULL - state.msrs[NVMM_X64_MSR_PAT] = + state->msrs[NVMM_X64_MSR_PAT] = PATENTRY(0, PAT_WB) | PATENTRY(1, PAT_WT) | PATENTRY(2, PAT_UCMINUS) | PATENTRY(3, PAT_UC) | PATENTRY(4, PAT_WB) | PATENTRY(5, PAT_WT) | PATENTRY(6, PAT_UCMINUS) | PATENTRY(7, PAT_UC); /* Page tables. */ - state.crs[NVMM_X64_CR_CR3] = 0x3000; + state->crs[NVMM_X64_CR_CR3] = 0x3000; - state.gprs[NVMM_X64_GPR_RIP] = 0x2000; + state->gprs[NVMM_X64_GPR_RIP] = 0x2000; - if (nvmm_vcpu_setstate(mach, 0, &state, NVMM_X64_STATE_ALL) == -1) + if (nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1) err(errno, "nvmm_vcpu_setstate"); } @@ -227,11 +227,11 @@ io_callback(struct nvmm_io *io) } static int -handle_io(struct nvmm_machine *mach, struct nvmm_exit *exit) +handle_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { int ret; - ret = nvmm_assist_io(mach, 0, exit); + ret = nvmm_assist_io(mach, vcpu); if (ret == -1) { err(errno, "nvmm_assist_io"); } @@ -240,15 +240,15 @@ handle_io(struct nvmm_machine *mach, str } static void -run_machine(struct nvmm_machine *mach) +run_machine(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { - struct nvmm_exit exit; + struct nvmm_exit *exit = vcpu->exit; while (1) { - if (nvmm_vcpu_run(mach, 0, &exit) == -1) + if (nvmm_vcpu_run(mach, vcpu) == -1) err(errno, "nvmm_vcpu_run"); - switch (exit.reason) { + switch (exit->reason) { case NVMM_EXIT_NONE: break; @@ -257,7 +257,7 @@ run_machine(struct nvmm_machine *mach) return; case NVMM_EXIT_IO: - handle_io(mach, &exit); + handle_io(mach, vcpu); break; case NVMM_EXIT_SHUTDOWN: @@ -282,14 +282,15 @@ struct test { }; static void -run_test(struct nvmm_machine *mach, const struct test *test) +run_test(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu, + const struct test *test) { size_t size; char *res; size = (size_t)test->code_end - (size_t)test->code_begin; - reset_machine(mach); + reset_machine(mach, vcpu); iobuf_off = 0; memset(iobuf, 0, IO_SIZE); @@ -302,7 +303,7 @@ run_test(struct nvmm_machine *mach, cons strcpy(databuf, test->wanted); } - run_machine(mach); + run_machine(mach, vcpu); if (test->in) { res = databuf; @@ -369,17 +370,18 @@ static struct nvmm_callbacks callbacks = int main(int argc, char *argv[]) { struct nvmm_machine mach; + struct nvmm_vcpu vcpu; size_t i; if (nvmm_machine_create(&mach) == -1) err(errno, "nvmm_machine_create"); - if (nvmm_vcpu_create(&mach, 0) == -1) + if (nvmm_vcpu_create(&mach, 0, &vcpu) == -1) err(errno, "nvmm_vcpu_create"); nvmm_machine_configure(&mach, NVMM_MACH_CONF_CALLBACKS, &callbacks); map_pages(&mach); for (i = 0; tests[i].name != NULL; i++) { - run_test(&mach, &tests[i]); + run_test(&mach, &vcpu, &tests[i]); } return 0; Index: src/tests/lib/libnvmm/h_mem_assist.c diff -u src/tests/lib/libnvmm/h_mem_assist.c:1.10 src/tests/lib/libnvmm/h_mem_assist.c:1.11 --- src/tests/lib/libnvmm/h_mem_assist.c:1.10 Sat May 11 07:31:57 2019 +++ src/tests/lib/libnvmm/h_mem_assist.c Sat Jun 8 07:27:44 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: h_mem_assist.c,v 1.10 2019/05/11 07:31:57 maxv Exp $ */ +/* $NetBSD: h_mem_assist.c,v 1.11 2019/06/08 07:27:44 maxv Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -68,33 +68,33 @@ init_seg(struct nvmm_x64_state_seg *seg, } static void -reset_machine(struct nvmm_machine *mach) +reset_machine(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { - struct nvmm_x64_state state; + struct nvmm_x64_state *state = vcpu->state; - memset(&state, 0, sizeof(state)); + memset(state, 0, sizeof(*state)); /* Default. */ - state.gprs[NVMM_X64_GPR_RFLAGS] = PSL_MBO; - init_seg(&state.segs[NVMM_X64_SEG_CS], SDT_MEMERA, GSEL(GCODE_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_SS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_DS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_ES], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_FS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); - init_seg(&state.segs[NVMM_X64_SEG_GS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + state->gprs[NVMM_X64_GPR_RFLAGS] = PSL_MBO; + init_seg(&state->segs[NVMM_X64_SEG_CS], SDT_MEMERA, GSEL(GCODE_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_SS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_DS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_ES], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_FS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); + init_seg(&state->segs[NVMM_X64_SEG_GS], SDT_MEMRWA, GSEL(GDATA_SEL, SEL_KPL)); /* Blank. */ - init_seg(&state.segs[NVMM_X64_SEG_GDT], 0, 0); - init_seg(&state.segs[NVMM_X64_SEG_IDT], 0, 0); - init_seg(&state.segs[NVMM_X64_SEG_LDT], SDT_SYSLDT, 0); - init_seg(&state.segs[NVMM_X64_SEG_TR], SDT_SYS386BSY, 0); + init_seg(&state->segs[NVMM_X64_SEG_GDT], 0, 0); + init_seg(&state->segs[NVMM_X64_SEG_IDT], 0, 0); + init_seg(&state->segs[NVMM_X64_SEG_LDT], SDT_SYSLDT, 0); + init_seg(&state->segs[NVMM_X64_SEG_TR], SDT_SYS386BSY, 0); /* Protected mode enabled. */ - state.crs[NVMM_X64_CR_CR0] = CR0_PG|CR0_PE|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM; + state->crs[NVMM_X64_CR_CR0] = CR0_PG|CR0_PE|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM; /* 64bit mode enabled. */ - state.crs[NVMM_X64_CR_CR4] = CR4_PAE; - state.msrs[NVMM_X64_MSR_EFER] = EFER_LME | EFER_SCE | EFER_LMA; + state->crs[NVMM_X64_CR_CR4] = CR4_PAE; + state->msrs[NVMM_X64_MSR_EFER] = EFER_LME | EFER_SCE | EFER_LMA; /* Stolen from x86/pmap.c */ #define PATENTRY(n, type) (type << ((n) * 8)) @@ -104,18 +104,18 @@ reset_machine(struct nvmm_machine *mach) #define PAT_WP 0x5ULL #define PAT_WB 0x6ULL #define PAT_UCMINUS 0x7ULL - state.msrs[NVMM_X64_MSR_PAT] = + state->msrs[NVMM_X64_MSR_PAT] = PATENTRY(0, PAT_WB) | PATENTRY(1, PAT_WT) | PATENTRY(2, PAT_UCMINUS) | PATENTRY(3, PAT_UC) | PATENTRY(4, PAT_WB) | PATENTRY(5, PAT_WT) | PATENTRY(6, PAT_UCMINUS) | PATENTRY(7, PAT_UC); /* Page tables. */ - state.crs[NVMM_X64_CR_CR3] = 0x3000; + state->crs[NVMM_X64_CR_CR3] = 0x3000; - state.gprs[NVMM_X64_GPR_RIP] = 0x2000; + state->gprs[NVMM_X64_GPR_RIP] = 0x2000; - if (nvmm_vcpu_setstate(mach, 0, &state, NVMM_X64_STATE_ALL) == -1) + if (nvmm_vcpu_setstate(mach, vcpu, NVMM_X64_STATE_ALL) == -1) err(errno, "nvmm_vcpu_setstate"); } @@ -216,11 +216,11 @@ mem_callback(struct nvmm_mem *mem) } static int -handle_memory(struct nvmm_machine *mach, struct nvmm_exit *exit) +handle_memory(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { int ret; - ret = nvmm_assist_mem(mach, 0, exit); + ret = nvmm_assist_mem(mach, vcpu); if (ret == -1) { err(errno, "nvmm_assist_mem"); } @@ -229,15 +229,15 @@ handle_memory(struct nvmm_machine *mach, } static void -run_machine(struct nvmm_machine *mach) +run_machine(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu) { - struct nvmm_exit exit; + struct nvmm_exit *exit = vcpu->exit; while (1) { - if (nvmm_vcpu_run(mach, 0, &exit) == -1) + if (nvmm_vcpu_run(mach, vcpu) == -1) err(errno, "nvmm_vcpu_run"); - switch (exit.reason) { + switch (exit->reason) { case NVMM_EXIT_NONE: break; @@ -246,7 +246,7 @@ run_machine(struct nvmm_machine *mach) return; case NVMM_EXIT_MEMORY: - handle_memory(mach, &exit); + handle_memory(mach, vcpu); break; case NVMM_EXIT_SHUTDOWN: @@ -270,19 +270,20 @@ struct test { }; static void -run_test(struct nvmm_machine *mach, const struct test *test) +run_test(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu, + const struct test *test) { uint64_t *res; size_t size; size = (size_t)test->code_end - (size_t)test->code_begin; - reset_machine(mach); + reset_machine(mach, vcpu); memset(mmiobuf, 0, PAGE_SIZE); memcpy(instbuf, test->code_begin, size); - run_machine(mach); + run_machine(mach, vcpu); res = (uint64_t *)mmiobuf; if (*res == test->wanted) { @@ -344,17 +345,18 @@ static struct nvmm_callbacks callbacks = int main(int argc, char *argv[]) { struct nvmm_machine mach; + struct nvmm_vcpu vcpu; size_t i; if (nvmm_machine_create(&mach) == -1) err(errno, "nvmm_machine_create"); - if (nvmm_vcpu_create(&mach, 0) == -1) + if (nvmm_vcpu_create(&mach, 0, &vcpu) == -1) err(errno, "nvmm_vcpu_create"); nvmm_machine_configure(&mach, NVMM_MACH_CONF_CALLBACKS, &callbacks); map_pages(&mach); for (i = 0; tests[i].name != NULL; i++) { - run_test(&mach, &tests[i]); + run_test(&mach, &vcpu, &tests[i]); } return 0;