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 */