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/aa23a59cb2b3
branches:  trunk
changeset: 460436:aa23a59cb2b3
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 1d043fada5ca -r aa23a59cb2b3 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 1d043fada5ca -r aa23a59cb2b3 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 1d043fada5ca -r aa23a59cb2b3 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 1d043fada5ca -r aa23a59cb2b3 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