Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Miscellaneous changes in NVMM, to address several inconsiste...
details: https://anonhg.NetBSD.org/src/rev/7aff5e820bdc
branches: trunk
changeset: 1004313:7aff5e820bdc
user: maxv <maxv%NetBSD.org@localhost>
date: Wed Oct 23 07:01:11 2019 +0000
description:
Miscellaneous changes in NVMM, to address several inconsistencies and
issues in the libnvmm API.
- Rename NVMM_CAPABILITY_VERSION to NVMM_KERN_VERSION, and check it in
libnvmm. Introduce NVMM_USER_VERSION, for future use.
- In libnvmm, open "/dev/nvmm" as read-only and with O_CLOEXEC. This is to
avoid sharing the VMs with the children if the process forks. In the
NVMM driver, force O_CLOEXEC on open().
- Rename the following things for consistency:
nvmm_exit* -> nvmm_vcpu_exit*
nvmm_event* -> nvmm_vcpu_event*
NVMM_EXIT_* -> NVMM_VCPU_EXIT_*
NVMM_EVENT_INTERRUPT_HW -> NVMM_VCPU_EVENT_INTR
NVMM_EVENT_EXCEPTION -> NVMM_VCPU_EVENT_EXCP
Delete NVMM_EVENT_INTERRUPT_SW, unused already.
- Slightly reorganize the MI/MD definitions, for internal clarity.
- Split NVMM_VCPU_EXIT_MSR in two: NVMM_VCPU_EXIT_{RD,WR}MSR. Also provide
separate u.rdmsr and u.wrmsr fields. This is more consistent with the
other exit reasons.
- Change the types of several variables:
event.type enum -> u_int
event.vector uint64_t -> uint8_t
exit.u.*msr.msr: uint64_t -> uint32_t
exit.u.io.type: enum -> bool
exit.u.io.seg: int -> int8_t
cap.arch.mxcsr_mask: uint64_t -> uint32_t
cap.arch.conf_cpuid_maxops: uint64_t -> uint32_t
- Delete NVMM_VCPU_EXIT_MWAIT_COND, it is AMD-only and confusing, and we
already intercept 'monitor' so it is never armed.
- Introduce vmx_exit_insn() for NVMM-Intel, similar to svm_exit_insn().
The 'npc' field wasn't getting filled properly during certain VMEXITs.
- Introduce nvmm_vcpu_configure(). Similar to nvmm_machine_configure(),
but as its name indicates, the configuration is per-VCPU and not per-VM.
Migrate and rename NVMM_MACH_CONF_X86_CPUID to NVMM_VCPU_CONF_CPUID.
This becomes per-VCPU, which makes more sense than per-VM.
- Extend the NVMM_VCPU_CONF_CPUID conf to allow triggering VMEXITs on
specific leaves. Until now we could only mask the leaves. An uint32_t
is added in the structure:
uint32_t mask:1;
uint32_t exit:1;
uint32_t rsvd:30;
The two first bits select the desired behavior on the leaf. Specifying
zero on both resets the leaf to the default behavior. The new
NVMM_VCPU_EXIT_CPUID exit reason is added.
diffstat:
lib/libnvmm/libnvmm.c | 32 +++-
lib/libnvmm/libnvmm_x86.c | 16 +-
lib/libnvmm/nvmm.h | 12 +-
sys/dev/nvmm/nvmm.c | 63 +++++-
sys/dev/nvmm/nvmm.h | 52 +----
sys/dev/nvmm/nvmm_internal.h | 15 +-
sys/dev/nvmm/nvmm_ioctl.h | 30 ++-
sys/dev/nvmm/x86/nvmm_x86.h | 144 ++++++++++-----
sys/dev/nvmm/x86/nvmm_x86_svm.c | 365 +++++++++++++++++++++-----------------
sys/dev/nvmm/x86/nvmm_x86_vmx.c | 359 +++++++++++++++++++++----------------
tests/lib/libnvmm/h_io_assist.c | 14 +-
tests/lib/libnvmm/h_mem_assist.c | 12 +-
12 files changed, 654 insertions(+), 460 deletions(-)
diffs (truncated from 2145 to 300 lines):
diff -r c4e872a99edc -r 7aff5e820bdc lib/libnvmm/libnvmm.c
--- a/lib/libnvmm/libnvmm.c Wed Oct 23 05:20:52 2019 +0000
+++ b/lib/libnvmm/libnvmm.c Wed Oct 23 07:01:11 2019 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: libnvmm.c,v 1.14 2019/06/08 07:27:44 maxv Exp $ */
+/* $NetBSD: libnvmm.c,v 1.15 2019/10/23 07:01:11 maxv Exp $ */
/*
- * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -161,7 +161,7 @@
{
if (nvmm_fd != -1)
return 0;
- nvmm_fd = open("/dev/nvmm", O_RDWR);
+ nvmm_fd = open("/dev/nvmm", O_RDONLY | O_CLOEXEC);
if (nvmm_fd == -1)
return -1;
if (nvmm_capability(&__capability) == -1) {
@@ -169,6 +169,13 @@
nvmm_fd = -1;
return -1;
}
+ if (__capability.version != NVMM_KERN_VERSION) {
+ close(nvmm_fd);
+ nvmm_fd = -1;
+ errno = EPROGMISMATCH;
+ return -1;
+ }
+
return 0;
}
@@ -322,6 +329,25 @@
}
int
+nvmm_vcpu_configure(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
+ uint64_t op, void *conf)
+{
+ struct nvmm_ioc_vcpu_configure args;
+ int ret;
+
+ args.machid = mach->machid;
+ args.cpuid = vcpu->cpuid;
+ args.op = op;
+ args.conf = conf;
+
+ ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_CONFIGURE, &args);
+ if (ret == -1)
+ return -1;
+
+ return 0;
+}
+
+int
nvmm_vcpu_setstate(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
uint64_t flags)
{
diff -r c4e872a99edc -r 7aff5e820bdc lib/libnvmm/libnvmm_x86.c
--- a/lib/libnvmm/libnvmm_x86.c Wed Oct 23 05:20:52 2019 +0000
+++ b/lib/libnvmm/libnvmm_x86.c Wed Oct 23 07:01:11 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: libnvmm_x86.c,v 1.35 2019/10/19 19:45:10 maxv Exp $ */
+/* $NetBSD: libnvmm_x86.c,v 1.36 2019/10/23 07:01:11 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -706,7 +706,7 @@
nvmm_assist_io(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
{
struct nvmm_x64_state *state = vcpu->state;
- struct nvmm_exit *exit = vcpu->exit;
+ struct nvmm_vcpu_exit *exit = vcpu->exit;
struct nvmm_io io;
uint64_t cnt = 0; /* GCC */
uint8_t iobuf[8];
@@ -716,13 +716,13 @@
int ret, seg;
bool psld = false;
- if (__predict_false(exit->reason != NVMM_EXIT_IO)) {
+ if (__predict_false(exit->reason != NVMM_VCPU_EXIT_IO)) {
errno = EINVAL;
return -1;
}
io.port = exit->u.io.port;
- io.in = (exit->u.io.type == NVMM_EXIT_IO_IN);
+ io.in = exit->u.io.in;
io.size = exit->u.io.operand_size;
io.data = iobuf;
@@ -3107,7 +3107,7 @@
static int
fetch_instruction(struct nvmm_machine *mach, struct nvmm_x64_state *state,
- struct nvmm_exit *exit)
+ struct nvmm_vcpu_exit *exit)
{
size_t fetchsize;
gvaddr_t gva;
@@ -3170,7 +3170,7 @@
static int
assist_mem_single(struct nvmm_machine *mach, struct nvmm_x64_state *state,
- struct x86_instr *instr, struct nvmm_exit *exit)
+ struct x86_instr *instr, struct nvmm_vcpu_exit *exit)
{
struct nvmm_mem mem;
uint8_t membuf[8];
@@ -3292,12 +3292,12 @@
nvmm_assist_mem(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
{
struct nvmm_x64_state *state = vcpu->state;
- struct nvmm_exit *exit = vcpu->exit;
+ struct nvmm_vcpu_exit *exit = vcpu->exit;
struct x86_instr instr;
uint64_t cnt = 0; /* GCC */
int ret;
- if (__predict_false(exit->reason != NVMM_EXIT_MEMORY)) {
+ if (__predict_false(exit->reason != NVMM_VCPU_EXIT_MEMORY)) {
errno = EINVAL;
return -1;
}
diff -r c4e872a99edc -r 7aff5e820bdc lib/libnvmm/nvmm.h
--- a/lib/libnvmm/nvmm.h Wed Oct 23 05:20:52 2019 +0000
+++ b/lib/libnvmm/nvmm.h Wed Oct 23 07:01:11 2019 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: nvmm.h,v 1.12 2019/06/08 07:27:44 maxv Exp $ */
+/* $NetBSD: nvmm.h,v 1.13 2019/10/23 07:01:11 maxv Exp $ */
/*
- * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -38,6 +38,8 @@
#include <dev/nvmm/nvmm.h>
#include <dev/nvmm/nvmm_ioctl.h>
+#define NVMM_USER_VERSION 1
+
struct nvmm_io {
uint64_t port;
bool in;
@@ -67,8 +69,8 @@
struct nvmm_vcpu {
nvmm_cpuid_t cpuid;
struct nvmm_vcpu_state *state;
- struct nvmm_event *event;
- struct nvmm_exit *exit;
+ struct nvmm_vcpu_event *event;
+ struct nvmm_vcpu_exit *exit;
};
#define NVMM_MACH_CONF_CALLBACKS NVMM_MACH_CONF_LIBNVMM_BEGIN
@@ -88,6 +90,8 @@
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_configure(struct nvmm_machine *, struct nvmm_vcpu *, uint64_t,
+ void *);
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 *);
diff -r c4e872a99edc -r 7aff5e820bdc sys/dev/nvmm/nvmm.c
--- a/sys/dev/nvmm/nvmm.c Wed Oct 23 05:20:52 2019 +0000
+++ b/sys/dev/nvmm/nvmm.c Wed Oct 23 07:01:11 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: nvmm.c,v 1.22 2019/07/06 05:13:10 maxv Exp $ */
+/* $NetBSD: nvmm.c,v 1.23 2019/10/23 07:01:11 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.22 2019/07/06 05:13:10 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.23 2019/10/23 07:01:11 maxv Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -247,7 +247,7 @@
static int
nvmm_capability(struct nvmm_owner *owner, struct nvmm_ioc_capability *args)
{
- args->cap.version = NVMM_CAPABILITY_VERSION;
+ args->cap.version = NVMM_KERN_VERSION;
args->cap.state_size = nvmm_impl->state_size;
args->cap.max_machines = NVMM_MAX_MACHINES;
args->cap.max_vcpus = NVMM_MAX_VCPUS;
@@ -343,11 +343,11 @@
int error;
op = NVMM_MACH_CONF_MD(args->op);
- if (__predict_false(op >= nvmm_impl->conf_max)) {
+ if (__predict_false(op >= nvmm_impl->mach_conf_max)) {
return EINVAL;
}
- allocsz = nvmm_impl->conf_sizes[op];
+ allocsz = nvmm_impl->mach_conf_sizes[op];
data = kmem_alloc(allocsz, KM_SLEEP);
error = nvmm_machine_get(owner, args->machid, &mach, true);
@@ -443,6 +443,51 @@
}
static int
+nvmm_vcpu_configure(struct nvmm_owner *owner,
+ struct nvmm_ioc_vcpu_configure *args)
+{
+ struct nvmm_machine *mach;
+ struct nvmm_cpu *vcpu;
+ size_t allocsz;
+ uint64_t op;
+ void *data;
+ int error;
+
+ op = NVMM_VCPU_CONF_MD(args->op);
+ if (__predict_false(op >= nvmm_impl->vcpu_conf_max))
+ return EINVAL;
+
+ allocsz = nvmm_impl->vcpu_conf_sizes[op];
+ data = kmem_alloc(allocsz, KM_SLEEP);
+
+ error = nvmm_machine_get(owner, args->machid, &mach, false);
+ if (error) {
+ kmem_free(data, allocsz);
+ return error;
+ }
+
+ error = nvmm_vcpu_get(mach, args->cpuid, &vcpu);
+ if (error) {
+ nvmm_machine_put(mach);
+ kmem_free(data, allocsz);
+ return error;
+ }
+
+ error = copyin(args->conf, data, allocsz);
+ if (error) {
+ goto out;
+ }
+
+ error = (*nvmm_impl->vcpu_configure)(vcpu, op, data);
+
+out:
+ nvmm_vcpu_put(vcpu);
+ nvmm_machine_put(mach);
+ kmem_free(data, allocsz);
+ return error;
+}
+
+static int
nvmm_vcpu_setstate(struct nvmm_owner *owner,
struct nvmm_ioc_vcpu_setstate *args)
{
@@ -515,7 +560,7 @@
static int
nvmm_do_vcpu_run(struct nvmm_machine *mach, struct nvmm_cpu *vcpu,
- struct nvmm_exit *exit)
+ struct nvmm_vcpu_exit *exit)
{
struct vmspace *vm = mach->vm;
int ret;
@@ -526,7 +571,7 @@
return ret;
}
- if (__predict_true(exit->reason != NVMM_EXIT_MEMORY)) {
+ if (__predict_true(exit->reason != NVMM_VCPU_EXIT_MEMORY)) {
break;
}
if (exit->u.mem.gpa >= mach->gpa_end) {
@@ -996,6 +1041,8 @@
if (minor(dev) != 0)
return EXDEV;
+ if (!(flags & O_CLOEXEC))
+ return EINVAL;
error = fd_allocfile(&fp, &fd);
if (error)
return error;
@@ -1073,6 +1120,8 @@
return nvmm_vcpu_create(owner, data);
case NVMM_IOC_VCPU_DESTROY:
return nvmm_vcpu_destroy(owner, data);
+ case NVMM_IOC_VCPU_CONFIGURE:
+ return nvmm_vcpu_configure(owner, data);
case NVMM_IOC_VCPU_SETSTATE:
return nvmm_vcpu_setstate(owner, data);
case NVMM_IOC_VCPU_GETSTATE:
Home |
Main Index |
Thread Index |
Old Index