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