Module Name:    src
Committed By:   maxv
Date:           Mon Apr  8 18:21:42 UTC 2019

Modified Files:
        src/sys/dev/nvmm: nvmm.c nvmm_internal.h

Log Message:
Use the fd_clone approach, to avoid losing references to the registered
VMs during fork(). We attach an nvmm_owner struct to the fd, reference it
in each VM, and identify the process' VMs by just comparing the pointer.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/nvmm/nvmm.c
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/nvmm/nvmm_internal.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/nvmm/nvmm.c
diff -u src/sys/dev/nvmm/nvmm.c:1.13 src/sys/dev/nvmm/nvmm.c:1.14
--- src/sys/dev/nvmm/nvmm.c:1.13	Sun Apr  7 14:05:15 2019
+++ src/sys/dev/nvmm/nvmm.c	Mon Apr  8 18:21:42 2019
@@ -1,7 +1,7 @@
-/*	$NetBSD: nvmm.c,v 1.13 2019/04/07 14:05:15 maxv Exp $	*/
+/*	$NetBSD: nvmm.c,v 1.14 2019/04/08 18:21:42 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
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.13 2019/04/07 14:05:15 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.14 2019/04/08 18:21:42 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -42,6 +42,8 @@ __KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.1
 #include <sys/module.h>
 #include <sys/proc.h>
 #include <sys/mman.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
 
 #include <uvm/uvm.h>
 #include <uvm/uvm_page.h>
@@ -98,7 +100,8 @@ nvmm_machine_free(struct nvmm_machine *m
 }
 
 static int
-nvmm_machine_get(nvmm_machid_t machid, struct nvmm_machine **ret, bool writer)
+nvmm_machine_get(struct nvmm_owner *owner, nvmm_machid_t machid,
+    struct nvmm_machine **ret, bool writer)
 {
 	struct nvmm_machine *mach;
 	krw_t op = writer ? RW_WRITER : RW_READER;
@@ -113,7 +116,7 @@ nvmm_machine_get(nvmm_machid_t machid, s
 		rw_exit(&mach->lock);
 		return ENOENT;
 	}
-	if (mach->procid != curproc->p_pid) {
+	if (mach->owner != owner) {
 		rw_exit(&mach->lock);
 		return EPERM;
 	}
@@ -194,7 +197,7 @@ nvmm_vcpu_put(struct nvmm_cpu *vcpu)
 /* -------------------------------------------------------------------------- */
 
 static void
-nvmm_kill_machines(pid_t pid)
+nvmm_kill_machines(struct nvmm_owner *owner)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
@@ -205,7 +208,7 @@ nvmm_kill_machines(pid_t pid)
 		mach = &machines[i];
 
 		rw_enter(&mach->lock, RW_WRITER);
-		if (!mach->present || mach->procid != pid) {
+		if (!mach->present || mach->owner != owner) {
 			rw_exit(&mach->lock);
 			continue;
 		}
@@ -237,7 +240,7 @@ nvmm_kill_machines(pid_t pid)
 /* -------------------------------------------------------------------------- */
 
 static int
-nvmm_capability(struct nvmm_ioc_capability *args)
+nvmm_capability(struct nvmm_owner *owner, struct nvmm_ioc_capability *args)
 {
 	args->cap.version = NVMM_CAPABILITY_VERSION;
 	args->cap.state_size = nvmm_impl->state_size;
@@ -251,7 +254,8 @@ nvmm_capability(struct nvmm_ioc_capabili
 }
 
 static int
-nvmm_machine_create(struct nvmm_ioc_machine_create *args)
+nvmm_machine_create(struct nvmm_owner *owner,
+    struct nvmm_ioc_machine_create *args)
 {
 	struct nvmm_machine *mach;
 	int error;
@@ -261,7 +265,7 @@ nvmm_machine_create(struct nvmm_ioc_mach
 		return error;
 
 	/* Curproc owns the machine. */
-	mach->procid = curproc->p_pid;
+	mach->owner = owner;
 
 	/* Zero out the host mappings. */
 	memset(&mach->hmap, 0, sizeof(mach->hmap));
@@ -280,14 +284,15 @@ nvmm_machine_create(struct nvmm_ioc_mach
 }
 
 static int
-nvmm_machine_destroy(struct nvmm_ioc_machine_destroy *args)
+nvmm_machine_destroy(struct nvmm_owner *owner,
+    struct nvmm_ioc_machine_destroy *args)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
 	int error;
 	size_t i;
 
-	error = nvmm_machine_get(args->machid, &mach, true);
+	error = nvmm_machine_get(owner, args->machid, &mach, true);
 	if (error)
 		return error;
 
@@ -320,7 +325,8 @@ nvmm_machine_destroy(struct nvmm_ioc_mac
 }
 
 static int
-nvmm_machine_configure(struct nvmm_ioc_machine_configure *args)
+nvmm_machine_configure(struct nvmm_owner *owner,
+    struct nvmm_ioc_machine_configure *args)
 {
 	struct nvmm_machine *mach;
 	size_t allocsz;
@@ -334,7 +340,7 @@ nvmm_machine_configure(struct nvmm_ioc_m
 	allocsz = nvmm_impl->conf_sizes[args->op];
 	data = kmem_alloc(allocsz, KM_SLEEP);
 
-	error = nvmm_machine_get(args->machid, &mach, true);
+	error = nvmm_machine_get(owner, args->machid, &mach, true);
 	if (error) {
 		kmem_free(data, allocsz);
 		return error;
@@ -354,13 +360,13 @@ out:
 }
 
 static int
-nvmm_vcpu_create(struct nvmm_ioc_vcpu_create *args)
+nvmm_vcpu_create(struct nvmm_owner *owner, struct nvmm_ioc_vcpu_create *args)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -383,13 +389,13 @@ out:
 }
 
 static int
-nvmm_vcpu_destroy(struct nvmm_ioc_vcpu_destroy *args)
+nvmm_vcpu_destroy(struct nvmm_owner *owner, struct nvmm_ioc_vcpu_destroy *args)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -407,13 +413,14 @@ out:
 }
 
 static int
-nvmm_vcpu_setstate(struct nvmm_ioc_vcpu_setstate *args)
+nvmm_vcpu_setstate(struct nvmm_owner *owner,
+    struct nvmm_ioc_vcpu_setstate *args)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -436,13 +443,14 @@ out:
 }
 
 static int
-nvmm_vcpu_getstate(struct nvmm_ioc_vcpu_getstate *args)
+nvmm_vcpu_getstate(struct nvmm_owner *owner,
+    struct nvmm_ioc_vcpu_getstate *args)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -460,13 +468,13 @@ out:
 }
 
 static int
-nvmm_vcpu_inject(struct nvmm_ioc_vcpu_inject *args)
+nvmm_vcpu_inject(struct nvmm_owner *owner, struct nvmm_ioc_vcpu_inject *args)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -504,13 +512,13 @@ nvmm_do_vcpu_run(struct nvmm_machine *ma
 }
 
 static int
-nvmm_vcpu_run(struct nvmm_ioc_vcpu_run *args)
+nvmm_vcpu_run(struct nvmm_owner *owner, struct nvmm_ioc_vcpu_run *args)
 {
 	struct nvmm_machine *mach;
 	struct nvmm_cpu *vcpu;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -636,7 +644,7 @@ nvmm_hmapping_free(struct nvmm_machine *
 }
 
 static int
-nvmm_hva_map(struct nvmm_ioc_hva_map *args)
+nvmm_hva_map(struct nvmm_owner *owner, struct nvmm_ioc_hva_map *args)
 {
 	struct vmspace *vmspace = curproc->p_vmspace;
 	struct nvmm_machine *mach;
@@ -644,7 +652,7 @@ nvmm_hva_map(struct nvmm_ioc_hva_map *ar
 	vaddr_t uva;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, true);
+	error = nvmm_machine_get(owner, args->machid, &mach, true);
 	if (error)
 		return error;
 
@@ -680,12 +688,12 @@ out:
 }
 
 static int
-nvmm_hva_unmap(struct nvmm_ioc_hva_unmap *args)
+nvmm_hva_unmap(struct nvmm_owner *owner, struct nvmm_ioc_hva_unmap *args)
 {
 	struct nvmm_machine *mach;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, true);
+	error = nvmm_machine_get(owner, args->machid, &mach, true);
 	if (error)
 		return error;
 
@@ -698,7 +706,7 @@ nvmm_hva_unmap(struct nvmm_ioc_hva_unmap
 /* -------------------------------------------------------------------------- */
 
 static int
-nvmm_gpa_map(struct nvmm_ioc_gpa_map *args)
+nvmm_gpa_map(struct nvmm_owner *owner, struct nvmm_ioc_gpa_map *args)
 {
 	struct nvmm_machine *mach;
 	struct uvm_object *uobj;
@@ -706,7 +714,7 @@ nvmm_gpa_map(struct nvmm_ioc_gpa_map *ar
 	size_t off;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -768,13 +776,13 @@ out:
 }
 
 static int
-nvmm_gpa_unmap(struct nvmm_ioc_gpa_unmap *args)
+nvmm_gpa_unmap(struct nvmm_owner *owner, struct nvmm_ioc_gpa_unmap *args)
 {
 	struct nvmm_machine *mach;
 	gpaddr_t gpa;
 	int error;
 
-	error = nvmm_machine_get(args->machid, &mach, false);
+	error = nvmm_machine_get(owner, args->machid, &mach, false);
 	if (error)
 		return error;
 
@@ -855,79 +863,113 @@ nvmm_fini(void)
 
 /* -------------------------------------------------------------------------- */
 
+static dev_type_open(nvmm_open);
+
+const struct cdevsw nvmm_cdevsw = {
+	.d_open = nvmm_open,
+	.d_close = noclose,
+	.d_read = noread,
+	.d_write = nowrite,
+	.d_ioctl = noioctl,
+	.d_stop = nostop,
+	.d_tty = notty,
+	.d_poll = nopoll,
+	.d_mmap = nommap,
+	.d_kqfilter = nokqfilter,
+	.d_discard = nodiscard,
+	.d_flag = D_OTHER | D_MPSAFE
+};
+
+static int nvmm_ioctl(file_t *, u_long, void *);
+static int nvmm_close(file_t *);
+
+const struct fileops nvmm_fileops = {
+	.fo_read = fbadop_read,
+	.fo_write = fbadop_write,
+	.fo_ioctl = nvmm_ioctl,
+	.fo_fcntl = fnullop_fcntl,
+	.fo_poll = fnullop_poll,
+	.fo_stat = fbadop_stat,
+	.fo_close = nvmm_close,
+	.fo_kqfilter = fnullop_kqfilter,
+	.fo_restart = fnullop_restart,
+	.fo_mmap = NULL,
+};
+
 static int
 nvmm_open(dev_t dev, int flags, int type, struct lwp *l)
 {
-	if (minor(dev) != 0) {
+	struct nvmm_owner *owner;
+	struct file *fp;
+	int error, fd;
+
+	if (minor(dev) != 0)
 		return EXDEV;
-	}
+	error = fd_allocfile(&fp, &fd);
+	if (error)
+		return error;
 
-	return 0;
+	owner = kmem_alloc(sizeof(*owner), KM_SLEEP);
+	owner->pid = l->l_proc->p_pid;
+
+	return fd_clone(fp, fd, flags, &nvmm_fileops, owner);
 }
 
 static int
-nvmm_close(dev_t dev, int flags, int type, struct lwp *l)
+nvmm_close(file_t *fp)
 {
-	KASSERT(minor(dev) == 0);
+	struct nvmm_owner *owner = fp->f_data;
 
-	nvmm_kill_machines(l->l_proc->p_pid);
+	KASSERT(owner != NULL);
+	nvmm_kill_machines(owner);
+	kmem_free(owner, sizeof(*owner));
+	fp->f_data = NULL;
 
-	return 0;
+   	return 0;
 }
 
 static int
-nvmm_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
+nvmm_ioctl(file_t *fp, u_long cmd, void *data)
 {
-	KASSERT(minor(dev) == 0);
+	struct nvmm_owner *owner = fp->f_data;
+
+	KASSERT(owner != NULL);
 
 	switch (cmd) {
 	case NVMM_IOC_CAPABILITY:
-		return nvmm_capability(data);
+		return nvmm_capability(owner, data);
 	case NVMM_IOC_MACHINE_CREATE:
-		return nvmm_machine_create(data);
+		return nvmm_machine_create(owner, data);
 	case NVMM_IOC_MACHINE_DESTROY:
-		return nvmm_machine_destroy(data);
+		return nvmm_machine_destroy(owner, data);
 	case NVMM_IOC_MACHINE_CONFIGURE:
-		return nvmm_machine_configure(data);
+		return nvmm_machine_configure(owner, data);
 	case NVMM_IOC_VCPU_CREATE:
-		return nvmm_vcpu_create(data);
+		return nvmm_vcpu_create(owner, data);
 	case NVMM_IOC_VCPU_DESTROY:
-		return nvmm_vcpu_destroy(data);
+		return nvmm_vcpu_destroy(owner, data);
 	case NVMM_IOC_VCPU_SETSTATE:
-		return nvmm_vcpu_setstate(data);
+		return nvmm_vcpu_setstate(owner, data);
 	case NVMM_IOC_VCPU_GETSTATE:
-		return nvmm_vcpu_getstate(data);
+		return nvmm_vcpu_getstate(owner, data);
 	case NVMM_IOC_VCPU_INJECT:
-		return nvmm_vcpu_inject(data);
+		return nvmm_vcpu_inject(owner, data);
 	case NVMM_IOC_VCPU_RUN:
-		return nvmm_vcpu_run(data);
+		return nvmm_vcpu_run(owner, data);
 	case NVMM_IOC_GPA_MAP:
-		return nvmm_gpa_map(data);
+		return nvmm_gpa_map(owner, data);
 	case NVMM_IOC_GPA_UNMAP:
-		return nvmm_gpa_unmap(data);
+		return nvmm_gpa_unmap(owner, data);
 	case NVMM_IOC_HVA_MAP:
-		return nvmm_hva_map(data);
+		return nvmm_hva_map(owner, data);
 	case NVMM_IOC_HVA_UNMAP:
-		return nvmm_hva_unmap(data);
+		return nvmm_hva_unmap(owner, data);
 	default:
 		return EINVAL;
 	}
 }
 
-const struct cdevsw nvmm_cdevsw = {
-	.d_open = nvmm_open,
-	.d_close = nvmm_close,
-	.d_read = noread,
-	.d_write = nowrite,
-	.d_ioctl = nvmm_ioctl,
-	.d_stop = nostop,
-	.d_tty = notty,
-	.d_poll = nopoll,
-	.d_mmap = nommap,
-	.d_kqfilter = nokqfilter,
-	.d_discard = nodiscard,
-	.d_flag = D_OTHER | D_MPSAFE
-};
+/* -------------------------------------------------------------------------- */
 
 void
 nvmmattach(int nunits)

Index: src/sys/dev/nvmm/nvmm_internal.h
diff -u src/sys/dev/nvmm/nvmm_internal.h:1.7 src/sys/dev/nvmm/nvmm_internal.h:1.8
--- src/sys/dev/nvmm/nvmm_internal.h:1.7	Thu Mar  7 15:22:21 2019
+++ src/sys/dev/nvmm/nvmm_internal.h	Mon Apr  8 18:21:42 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: nvmm_internal.h,v 1.7 2019/03/07 15:22:21 maxv Exp $	*/
+/*	$NetBSD: nvmm_internal.h,v 1.8 2019/04/08 18:21:42 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -37,6 +37,10 @@
 #define NVMM_MAX_HMAPPINGS	32
 #define NVMM_MAX_RAM		(128ULL * (1 << 30))
 
+struct nvmm_owner {
+	pid_t pid;
+};
+
 struct nvmm_cpu {
 	/* Shared. */
 	bool present;
@@ -63,7 +67,7 @@ struct nvmm_hmapping {
 struct nvmm_machine {
 	bool present;
 	nvmm_machid_t machid;
-	pid_t procid;
+	struct nvmm_owner *owner;
 	krwlock_t lock;
 
 	/* Kernel */

Reply via email to