Module Name: src
Committed By: maxv
Date: Wed May 1 09:20:21 UTC 2019
Modified Files:
src/lib/libnvmm: libnvmm.c
src/sys/dev/nvmm: nvmm.c nvmm.h nvmm_internal.h nvmm_ioctl.h
src/sys/dev/nvmm/x86: nvmm_x86.h nvmm_x86_svm.c nvmm_x86_vmx.c
Log Message:
Use the comm page to inject events, rather than ioctls, and commit them in
vcpu_run. This saves a few syscalls and copyins.
For example on Windows 10, moving the mouse from the left to right sides of
the screen generates ~500 events, which now don't result in syscalls.
The error handling is done in vcpu_run and it is less precise, but this
doesn't matter a lot, and will be solved with future NVMM error codes.
To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/lib/libnvmm/libnvmm.c
cvs rdiff -u -r1.19 -r1.20 src/sys/dev/nvmm/nvmm.c
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/nvmm/nvmm.h
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/nvmm/nvmm_internal.h
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/nvmm/nvmm_ioctl.h
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/nvmm/x86/nvmm_x86.h
cvs rdiff -u -r1.44 -r1.45 src/sys/dev/nvmm/x86/nvmm_x86_svm.c
cvs rdiff -u -r1.32 -r1.33 src/sys/dev/nvmm/x86/nvmm_x86_vmx.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.c
diff -u src/lib/libnvmm/libnvmm.c:1.11 src/lib/libnvmm/libnvmm.c:1.12
--- src/lib/libnvmm/libnvmm.c:1.11 Mon Apr 29 17:27:57 2019
+++ src/lib/libnvmm/libnvmm.c Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: libnvmm.c,v 1.11 2019/04/29 17:27:57 maxv Exp $ */
+/* $NetBSD: libnvmm.c,v 1.12 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -362,16 +362,15 @@ int
nvmm_vcpu_inject(struct nvmm_machine *mach, nvmm_cpuid_t cpuid,
struct nvmm_event *event)
{
- struct nvmm_ioc_vcpu_inject args;
- int ret;
-
- args.machid = mach->machid;
- args.cpuid = cpuid;
- memcpy(&args.event, event, sizeof(args.event));
+ struct nvmm_comm_page *comm;
- ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_INJECT, &args);
- if (ret == -1)
+ if (__predict_false(cpuid >= mach->npages)) {
return -1;
+ }
+ comm = mach->pages[cpuid];
+
+ memcpy(&comm->event, event, sizeof(comm->event));
+ comm->event_commit = true;
return 0;
}
Index: src/sys/dev/nvmm/nvmm.c
diff -u src/sys/dev/nvmm/nvmm.c:1.19 src/sys/dev/nvmm/nvmm.c:1.20
--- src/sys/dev/nvmm/nvmm.c:1.19 Sun Apr 28 14:22:13 2019
+++ src/sys/dev/nvmm/nvmm.c Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm.c,v 1.19 2019/04/28 14:22:13 maxv Exp $ */
+/* $NetBSD: nvmm.c,v 1.20 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.19 2019/04/28 14:22:13 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.20 2019/05/01 09:20:21 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -503,7 +503,7 @@ nvmm_vcpu_inject(struct nvmm_owner *owne
if (error)
goto out;
- error = (*nvmm_impl->vcpu_inject)(mach, vcpu, &args->event);
+ error = (*nvmm_impl->vcpu_inject)(vcpu);
nvmm_vcpu_put(vcpu);
out:
Index: src/sys/dev/nvmm/nvmm.h
diff -u src/sys/dev/nvmm/nvmm.h:1.8 src/sys/dev/nvmm/nvmm.h:1.9
--- src/sys/dev/nvmm/nvmm.h:1.8 Sun Apr 28 14:22:13 2019
+++ src/sys/dev/nvmm/nvmm.h Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm.h,v 1.8 2019/04/28 14:22:13 maxv Exp $ */
+/* $NetBSD: nvmm.h,v 1.9 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -94,6 +94,18 @@ struct nvmm_capability {
struct nvmm_cap_md arch;
};
+struct nvmm_comm_page {
+ /* State. */
+ uint64_t state_wanted;
+ uint64_t state_cached;
+ uint64_t state_commit;
+ struct nvmm_vcpu_state state;
+
+ /* Event. */
+ bool event_commit;
+ struct nvmm_event event;
+};
+
/*
* Bits 20:27 -> machid
* Bits 12:19 -> cpuid
Index: src/sys/dev/nvmm/nvmm_internal.h
diff -u src/sys/dev/nvmm/nvmm_internal.h:1.10 src/sys/dev/nvmm/nvmm_internal.h:1.11
--- src/sys/dev/nvmm/nvmm_internal.h:1.10 Sun Apr 28 14:22:13 2019
+++ src/sys/dev/nvmm/nvmm_internal.h Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_internal.h,v 1.10 2019/04/28 14:22:13 maxv Exp $ */
+/* $NetBSD: nvmm_internal.h,v 1.11 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -107,8 +107,7 @@ struct nvmm_impl {
void (*vcpu_destroy)(struct nvmm_machine *, struct nvmm_cpu *);
void (*vcpu_setstate)(struct nvmm_cpu *);
void (*vcpu_getstate)(struct nvmm_cpu *);
- int (*vcpu_inject)(struct nvmm_machine *, struct nvmm_cpu *,
- struct nvmm_event *);
+ int (*vcpu_inject)(struct nvmm_cpu *);
int (*vcpu_run)(struct nvmm_machine *, struct nvmm_cpu *,
struct nvmm_exit *);
};
Index: src/sys/dev/nvmm/nvmm_ioctl.h
diff -u src/sys/dev/nvmm/nvmm_ioctl.h:1.6 src/sys/dev/nvmm/nvmm_ioctl.h:1.7
--- src/sys/dev/nvmm/nvmm_ioctl.h:1.6 Sun Apr 28 14:22:13 2019
+++ src/sys/dev/nvmm/nvmm_ioctl.h Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_ioctl.h,v 1.6 2019/04/28 14:22:13 maxv Exp $ */
+/* $NetBSD: nvmm_ioctl.h,v 1.7 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -75,7 +75,6 @@ struct nvmm_ioc_vcpu_getstate {
struct nvmm_ioc_vcpu_inject {
nvmm_machid_t machid;
nvmm_cpuid_t cpuid;
- struct nvmm_event event;
};
struct nvmm_ioc_vcpu_run {
Index: src/sys/dev/nvmm/x86/nvmm_x86.h
diff -u src/sys/dev/nvmm/x86/nvmm_x86.h:1.13 src/sys/dev/nvmm/x86/nvmm_x86.h:1.14
--- src/sys/dev/nvmm/x86/nvmm_x86.h:1.13 Sun Apr 28 14:22:13 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86.h Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86.h,v 1.13 2019/04/28 14:22:13 maxv Exp $ */
+/* $NetBSD: nvmm_x86.h,v 1.14 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -229,6 +229,8 @@ struct nvmm_x64_state {
struct fxsave fpu;
};
+#define nvmm_vcpu_state nvmm_x64_state
+
#define NVMM_X86_CONF_CPUID 0
#define NVMM_X86_NCONF 1
@@ -248,13 +250,6 @@ struct nvmm_x86_conf_cpuid {
} del;
};
-struct nvmm_comm_page {
- uint64_t state_wanted;
- uint64_t state_cached;
- uint64_t state_commit;
- struct nvmm_x64_state state;
-};
-
#ifdef _KERNEL
struct nvmm_x86_cpuid_mask {
uint32_t eax;
Index: src/sys/dev/nvmm/x86/nvmm_x86_svm.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.44 src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.45
--- src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.44 Mon Apr 29 18:54:25 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86_svm.c Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86_svm.c,v 1.44 2019/04/29 18:54:25 maxv Exp $ */
+/* $NetBSD: nvmm_x86_svm.c,v 1.45 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.44 2019/04/29 18:54:25 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.45 2019/05/01 09:20:21 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -661,46 +661,51 @@ svm_event_has_error(uint64_t vector)
}
static int
-svm_vcpu_inject(struct nvmm_machine *mach, struct nvmm_cpu *vcpu,
- struct nvmm_event *event)
+svm_vcpu_inject(struct nvmm_cpu *vcpu)
{
+ struct nvmm_comm_page *comm = vcpu->comm;
struct svm_cpudata *cpudata = vcpu->cpudata;
struct vmcb *vmcb = cpudata->vmcb;
+ enum nvmm_event_type evtype;
+ uint64_t vector, error;
int type = 0, err = 0;
- if (event->vector >= 256) {
+ evtype = comm->event.type;
+ vector = comm->event.vector;
+ error = comm->event.u.error;
+ __insn_barrier();
+
+ if (__predict_false(vector >= 256)) {
return EINVAL;
}
- switch (event->type) {
+ switch (evtype) {
case NVMM_EVENT_INTERRUPT_HW:
type = SVM_EVENT_TYPE_HW_INT;
- if (event->vector == 2) {
+ if (vector == 2) {
type = SVM_EVENT_TYPE_NMI;
svm_event_waitexit_enable(vcpu, true);
}
err = 0;
break;
- case NVMM_EVENT_INTERRUPT_SW:
- return EINVAL;
case NVMM_EVENT_EXCEPTION:
type = SVM_EVENT_TYPE_EXC;
- if (event->vector == 2 || event->vector >= 32)
+ if (vector == 2 || vector >= 32)
return EINVAL;
- if (event->vector == 3 || event->vector == 0)
+ if (vector == 3 || vector == 0)
return EINVAL;
- err = svm_event_has_error(event->vector);
+ err = svm_event_has_error(vector);
break;
default:
return EINVAL;
}
vmcb->ctrl.eventinj =
- __SHIFTIN(event->vector, VMCB_CTRL_EVENTINJ_VECTOR) |
+ __SHIFTIN(vector, VMCB_CTRL_EVENTINJ_VECTOR) |
__SHIFTIN(type, VMCB_CTRL_EVENTINJ_TYPE) |
__SHIFTIN(err, VMCB_CTRL_EVENTINJ_EV) |
__SHIFTIN(1, VMCB_CTRL_EVENTINJ_V) |
- __SHIFTIN(event->u.error, VMCB_CTRL_EVENTINJ_ERRORCODE);
+ __SHIFTIN(error, VMCB_CTRL_EVENTINJ_ERRORCODE);
cpudata->evt_pending = true;
@@ -708,33 +713,43 @@ svm_vcpu_inject(struct nvmm_machine *mac
}
static void
-svm_inject_ud(struct nvmm_machine *mach, struct nvmm_cpu *vcpu)
+svm_inject_ud(struct nvmm_cpu *vcpu)
{
- struct nvmm_event event;
+ struct nvmm_comm_page *comm = vcpu->comm;
int ret __diagused;
- event.type = NVMM_EVENT_EXCEPTION;
- event.vector = 6;
- event.u.error = 0;
+ comm->event.type = NVMM_EVENT_EXCEPTION;
+ comm->event.vector = 6;
+ comm->event.u.error = 0;
- ret = svm_vcpu_inject(mach, vcpu, &event);
+ ret = svm_vcpu_inject(vcpu);
KASSERT(ret == 0);
}
static void
-svm_inject_gp(struct nvmm_machine *mach, struct nvmm_cpu *vcpu)
+svm_inject_gp(struct nvmm_cpu *vcpu)
{
- struct nvmm_event event;
+ struct nvmm_comm_page *comm = vcpu->comm;
int ret __diagused;
- event.type = NVMM_EVENT_EXCEPTION;
- event.vector = 13;
- event.u.error = 0;
+ comm->event.type = NVMM_EVENT_EXCEPTION;
+ comm->event.vector = 13;
+ comm->event.u.error = 0;
- ret = svm_vcpu_inject(mach, vcpu, &event);
+ ret = svm_vcpu_inject(vcpu);
KASSERT(ret == 0);
}
+static inline int
+svm_vcpu_event_commit(struct nvmm_cpu *vcpu)
+{
+ if (__predict_true(!vcpu->comm->event_commit)) {
+ return 0;
+ }
+ vcpu->comm->event_commit = false;
+ return svm_vcpu_inject(vcpu);
+}
+
static inline void
svm_inkernel_advance(struct vmcb *vmcb)
{
@@ -1018,7 +1033,7 @@ handled:
return true;
error:
- svm_inject_gp(mach, vcpu);
+ svm_inject_gp(vcpu);
return true;
}
@@ -1117,7 +1132,7 @@ svm_exit_xsetbv(struct nvmm_machine *mac
return;
error:
- svm_inject_gp(mach, vcpu);
+ svm_inject_gp(vcpu);
}
static void
@@ -1283,6 +1298,9 @@ svm_vcpu_run(struct nvmm_machine *mach,
uint64_t machgen;
int hcpu, s;
+ if (__predict_false(svm_vcpu_event_commit(vcpu) != 0)) {
+ return EINVAL;
+ }
svm_vcpu_state_commit(vcpu);
comm->state_cached = 0;
@@ -1368,7 +1386,7 @@ svm_vcpu_run(struct nvmm_machine *mach,
case VMCB_EXITCODE_CLGI:
case VMCB_EXITCODE_SKINIT:
case VMCB_EXITCODE_RDTSCP:
- svm_inject_ud(mach, vcpu);
+ svm_inject_ud(vcpu);
exit->reason = NVMM_EXIT_NONE;
break;
case VMCB_EXITCODE_MONITOR:
Index: src/sys/dev/nvmm/x86/nvmm_x86_vmx.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.32 src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.33
--- src/sys/dev/nvmm/x86/nvmm_x86_vmx.c:1.32 Mon Apr 29 18:54:26 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86_vmx.c Wed May 1 09:20:21 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm_x86_vmx.c,v 1.32 2019/04/29 18:54:26 maxv Exp $ */
+/* $NetBSD: nvmm_x86_vmx.c,v 1.33 2019/05/01 09:20:21 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.32 2019/04/29 18:54:26 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_vmx.c,v 1.33 2019/05/01 09:20:21 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -992,49 +992,53 @@ vmx_event_has_error(uint64_t vector)
}
static int
-vmx_vcpu_inject(struct nvmm_machine *mach, struct nvmm_cpu *vcpu,
- struct nvmm_event *event)
+vmx_vcpu_inject(struct nvmm_cpu *vcpu)
{
+ struct nvmm_comm_page *comm = vcpu->comm;
struct vmx_cpudata *cpudata = vcpu->cpudata;
int type = 0, err = 0, ret = EINVAL;
- uint64_t info;
+ enum nvmm_event_type evtype;
+ uint64_t info, vector, error;
+
+ evtype = comm->event.type;
+ vector = comm->event.vector;
+ error = comm->event.u.error;
+ __insn_barrier();
- if (event->vector >= 256) {
+ if (__predict_false(vector >= 256)) {
return EINVAL;
}
vmx_vmcs_enter(vcpu);
- switch (event->type) {
+ switch (evtype) {
case NVMM_EVENT_INTERRUPT_HW:
type = INTR_TYPE_EXT_INT;
- if (event->vector == 2) {
+ if (vector == 2) {
type = INTR_TYPE_NMI;
vmx_event_waitexit_enable(vcpu, true);
}
err = 0;
break;
- case NVMM_EVENT_INTERRUPT_SW:
- goto out;
case NVMM_EVENT_EXCEPTION:
- if (event->vector == 2 || event->vector >= 32)
+ if (vector == 2 || vector >= 32)
goto out;
- if (event->vector == 3 || event->vector == 0)
+ if (vector == 3 || vector == 0)
goto out;
type = INTR_TYPE_HW_EXC;
- err = vmx_event_has_error(event->vector);
+ err = vmx_event_has_error(vector);
break;
default:
goto out;
}
info =
- __SHIFTIN(event->vector, INTR_INFO_VECTOR) |
+ __SHIFTIN(vector, INTR_INFO_VECTOR) |
__SHIFTIN(type, INTR_INFO_TYPE) |
__SHIFTIN(err, INTR_INFO_ERROR) |
__SHIFTIN(1, INTR_INFO_VALID);
vmx_vmwrite(VMCS_ENTRY_INTR_INFO, info);
- vmx_vmwrite(VMCS_ENTRY_EXCEPTION_ERROR, event->u.error);
+ vmx_vmwrite(VMCS_ENTRY_EXCEPTION_ERROR, error);
cpudata->evt_pending = true;
ret = 0;
@@ -1045,33 +1049,43 @@ out:
}
static void
-vmx_inject_ud(struct nvmm_machine *mach, struct nvmm_cpu *vcpu)
+vmx_inject_ud(struct nvmm_cpu *vcpu)
{
- struct nvmm_event event;
+ struct nvmm_comm_page *comm = vcpu->comm;
int ret __diagused;
- event.type = NVMM_EVENT_EXCEPTION;
- event.vector = 6;
- event.u.error = 0;
+ comm->event.type = NVMM_EVENT_EXCEPTION;
+ comm->event.vector = 6;
+ comm->event.u.error = 0;
- ret = vmx_vcpu_inject(mach, vcpu, &event);
+ ret = vmx_vcpu_inject(vcpu);
KASSERT(ret == 0);
}
static void
-vmx_inject_gp(struct nvmm_machine *mach, struct nvmm_cpu *vcpu)
+vmx_inject_gp(struct nvmm_cpu *vcpu)
{
- struct nvmm_event event;
+ struct nvmm_comm_page *comm = vcpu->comm;
int ret __diagused;
- event.type = NVMM_EVENT_EXCEPTION;
- event.vector = 13;
- event.u.error = 0;
+ comm->event.type = NVMM_EVENT_EXCEPTION;
+ comm->event.vector = 13;
+ comm->event.u.error = 0;
- ret = vmx_vcpu_inject(mach, vcpu, &event);
+ ret = vmx_vcpu_inject(vcpu);
KASSERT(ret == 0);
}
+static inline int
+vmx_vcpu_event_commit(struct nvmm_cpu *vcpu)
+{
+ if (__predict_true(!vcpu->comm->event_commit)) {
+ return 0;
+ }
+ vcpu->comm->event_commit = false;
+ return vmx_vcpu_inject(vcpu);
+}
+
static inline void
vmx_inkernel_advance(void)
{
@@ -1430,7 +1444,7 @@ vmx_exit_cr(struct nvmm_machine *mach, s
}
if (ret == -1) {
- vmx_inject_gp(mach, vcpu);
+ vmx_inject_gp(vcpu);
}
exit->reason = NVMM_EXIT_NONE;
@@ -1575,7 +1589,7 @@ handled:
return true;
error:
- vmx_inject_gp(mach, vcpu);
+ vmx_inject_gp(vcpu);
return true;
}
@@ -1642,7 +1656,7 @@ vmx_exit_xsetbv(struct nvmm_machine *mac
return;
error:
- vmx_inject_gp(mach, vcpu);
+ vmx_inject_gp(vcpu);
}
#define VMX_EPT_VIOLATION_READ __BIT(0)
@@ -1873,6 +1887,10 @@ vmx_vcpu_run(struct nvmm_machine *mach,
vmx_vmcs_enter(vcpu);
+ if (__predict_false(vmx_vcpu_event_commit(vcpu) != 0)) {
+ vmx_vmcs_leave(vcpu);
+ return EINVAL;
+ }
vmx_vcpu_state_commit(vcpu);
comm->state_cached = 0;
@@ -1984,7 +2002,7 @@ vmx_vcpu_run(struct nvmm_machine *mach,
case VMCS_EXITCODE_VMWRITE:
case VMCS_EXITCODE_VMXOFF:
case VMCS_EXITCODE_VMXON:
- vmx_inject_ud(mach, vcpu);
+ vmx_inject_ud(vcpu);
exit->reason = NVMM_EXIT_NONE;
break;
case VMCS_EXITCODE_EPT_VIOLATION: