From nobody Wed Dec 17 14:08:56 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4dWbJ84D76z6LB0t for ; Wed, 17 Dec 2025 14:08:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4dWbJ81x5yz3Jby for ; Wed, 17 Dec 2025 14:08:56 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1765980536; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=/7FTsmdHhJ87bxka7oME8i3x45a174MSjrYXh4ZHcfs=; b=pv6IBzONvQggiJ5EosMBvSf7BYMuZ/e6DYujCat2IS6qDgvna34puWJeu7728lGWaUaQhh M0MRDEcrZMu0UkVbPUrMKE+OmX3hUFLXmv547YIAA9Mv9zT5b3YbtDrGWEOpqNtABjYGDX rcc4IernuvWTf86z2Ex8Nb39evjkHN2Uv+wxm5o0jJwISP2UA7/7p2ALUrPyIVTmIBr++y /C2mpWXO4NY2y9R9NnDV4U2CIIDu03aCnBtmemRfGsTcIDBpVj626/1aiNcxh0CpGVxY81 1R+qLv82RxGdsFL5RU8/uRxAgR7xRaIkR4SoljPuN+dhxv56tFOejOp3KXN26A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1765980536; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=/7FTsmdHhJ87bxka7oME8i3x45a174MSjrYXh4ZHcfs=; b=vApmTG1SQaBxYX/1GvwgHZt9ruqatj04C6ATm3q23FfRdMtehlMAGrHlfv1rFiAAfwgvXL H6s7cPTW+paAXplAxbKpr2xrS5NmHg9SyZ2BSQqrYDhcyMT4HrQ/RCLrMQjswtF/vx3xR/ btrxiuKq/XS45emLEEmn7l0F66tCkDHWGrQ9V9r8zSlUjyVBxQBLczMcznVc966WkKhMQL Dkh5wsfxy85LBjV6ihzbYo45Ij01jXrMo0CkXL73hD22IVNxwVw47oR3bfgA2ptXUNvXfO 0c0lvwXv2nqugx/chCRNC9adZvpFyNdncXzlKia0vA88kdxBLniYjl1Jv8KV/Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1765980536; a=rsa-sha256; cv=none; b=EJ9EFbYvptw5uk/L/LuDqP+Snuf+LiWK0NOOSKp6bnAcONYPMr3UAT5XkYirXrbvQFVvsC kJ+niZ/w8RJa/UVjfikLK6ktuZkO5soDStLCiC/N73hcy8rA82tMFzEQKG1Nks/ovqOfAG DFnTvextiaqQHh6UTMAuaG7MszIhzo15Sw2jJ3gBP/730280trIZB/menhCtEU5CylCoK2 aR2dHu/JyDkNqGf76yiFiNt5rZQSZyNQlh5yzecuORGQ+p8LyB4M8I4cgQiYFS3dCQcyKC 2VBmf7vm3f9sHJb9rIjDBEK3+MoiMdalh8q4sQH1zDJ7dNtYyzOgzJWzPmaZNw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4dWbJ81TFBzvbj for ; Wed, 17 Dec 2025 14:08:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 38803 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 17 Dec 2025 14:08:56 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Bojan Novk=?utf-8?Q?ovi=C4=87?= Subject: git: bd16bac27e7e - main - vmm: Add ability to destroy VMs on close List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bnovkov X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: bd16bac27e7e0d31bccf88feca95cd98f0ef0fd4 Auto-Submitted: auto-generated Date: Wed, 17 Dec 2025 14:08:56 +0000 Message-Id: <6942b978.38803.12597991@gitrepo.freebsd.org> The branch main has been updated by bnovkov: URL: https://cgit.FreeBSD.org/src/commit/?id=bd16bac27e7e0d31bccf88feca95cd98f0ef0fd4 commit bd16bac27e7e0d31bccf88feca95cd98f0ef0fd4 Author: Bojan Novković AuthorDate: 2025-11-06 14:26:27 +0000 Commit: Bojan Novković CommitDate: 2025-12-17 14:08:32 +0000 vmm: Add ability to destroy VMs on close This change adds the ability to tie a virtual machine's lifecycle to a /dev/vmmctl file descriptor. A user can request `vmmctl` to destroy a virtual machine on close using the `VMMCTL_CREATE_DESTROY_ON_CLOSE` flag when creating the virtual machine. `vmmctl` tracks such virtual machines in per-descriptor lists. Differential Revision: https://reviews.freebsd.org/D53729 Reviewed by: markj Sponsored by: The FreeBSD Foundation Sponsored by: Klara, Inc. MFC after: 3 months --- lib/libvmmapi/vmmapi.c | 8 ++++-- lib/libvmmapi/vmmapi.h | 1 + sys/dev/vmm/vmm_dev.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++--- sys/dev/vmm/vmm_dev.h | 6 +++- 4 files changed, 85 insertions(+), 8 deletions(-) diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index 77f0f8f5c581..ede46dce73b3 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -100,11 +100,13 @@ vm_ctl_open(void) } static int -vm_ctl_create(const char *name, int ctlfd) +vm_ctl_create(const char *name, int flags, int ctlfd) { struct vmmctl_vm_create vmc; memset(&vmc, 0, sizeof(vmc)); + if ((flags & VMMAPI_OPEN_CREATE_DESTROY_ON_CLOSE) != 0) + vmc.flags |= VMMCTL_CREATE_DESTROY_ON_CLOSE; if (strlcpy(vmc.name, name, sizeof(vmc.name)) >= sizeof(vmc.name)) { errno = ENAMETOOLONG; return (-1); @@ -121,7 +123,7 @@ vm_create(const char *name) if (fd < 0) return (-1); - error = vm_ctl_create(name, fd); + error = vm_ctl_create(name, 0, fd); if (error != 0) { error = errno; (void)close(fd); @@ -162,7 +164,7 @@ vm_openf(const char *name, int flags) vm->fd = vm_device_open(vm->name); if (vm->fd < 0 && errno == ENOENT) { if (flags & VMMAPI_OPEN_CREATE) { - if (vm_ctl_create(vm->name, vm->ctlfd) != 0) + if (vm_ctl_create(vm->name, flags, vm->ctlfd) != 0) goto err; vm->fd = vm_device_open(vm->name); created = true; diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index b637c45d1eff..5d3495a128d9 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -115,6 +115,7 @@ int vm_create(const char *name); struct vmctx *vm_open(const char *name); #define VMMAPI_OPEN_CREATE 0x01 /* create if the VM does not exist */ #define VMMAPI_OPEN_REINIT 0x02 /* reinitialize the VM if it exists */ +#define VMMAPI_OPEN_CREATE_DESTROY_ON_CLOSE 0x04 /* Destroy the VM when closing vmm_ctl */ struct vmctx *vm_openf(const char *name, int flags); void vm_close(struct vmctx *ctx); void vm_destroy(struct vmctx *ctx); diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c index 3a86a8f966ef..840e810a39fb 100644 --- a/sys/dev/vmm/vmm_dev.c +++ b/sys/dev/vmm/vmm_dev.c @@ -77,10 +77,15 @@ struct vmmdev_softc { struct cdev *cdev; struct ucred *ucred; SLIST_ENTRY(vmmdev_softc) link; + LIST_ENTRY(vmmdev_softc) priv_link; SLIST_HEAD(, devmem_softc) devmem; int flags; }; +struct vmmctl_priv { + LIST_HEAD(, vmmdev_softc) softcs; +}; + static bool vmm_initialized = false; static SLIST_HEAD(, vmmdev_softc) head; @@ -103,6 +108,7 @@ SYSCTL_UINT(_hw_vmm, OID_AUTO, maxvmms, CTLFLAG_RWTUN, static void devmem_destroy(void *arg); static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *devmem); +static void vmmdev_destroy(struct vmmdev_softc *sc); static int vmm_priv_check(struct ucred *ucred) @@ -909,7 +915,10 @@ vmmdev_destroy(struct vmmdev_softc *sc) sx_xlock(&vmmdev_mtx); SLIST_REMOVE(&head, sc, vmmdev_softc, link); + if ((sc->flags & VMMCTL_CREATE_DESTROY_ON_CLOSE) != 0) + LIST_REMOVE(sc, priv_link); sx_xunlock(&vmmdev_mtx); + wakeup(sc); free(sc, M_VMMDEV); } @@ -934,7 +943,7 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred) sc->cdev = NULL; sx_xunlock(&vmmdev_mtx); - vm_suspend(sc->vm, VM_SUSPEND_DESTROY); + (void)vm_suspend(sc->vm, VM_SUSPEND_DESTROY); destroy_dev(cdev); vmmdev_destroy(sc); @@ -987,17 +996,24 @@ vmmdev_alloc(struct vm *vm, struct ucred *cred) } static int -vmmdev_create(const char *name, struct ucred *cred) +vmmdev_create(const char *name, uint32_t flags, struct ucred *cred) { struct make_dev_args mda; struct cdev *cdev; struct vmmdev_softc *sc; + struct vmmctl_priv *priv; struct vm *vm; int error; if (name == NULL || strlen(name) > VM_MAX_NAMELEN) return (EINVAL); + if ((flags & ~VMMCTL_FLAGS_MASK) != 0) + return (EINVAL); + error = devfs_get_cdevpriv((void **)&priv); + if (error) + return (error); + sx_xlock(&vmmdev_mtx); sc = vmmdev_lookup(name, cred); if (sc != NULL) { @@ -1012,6 +1028,9 @@ vmmdev_create(const char *name, struct ucred *cred) } sc = vmmdev_alloc(vm, cred); SLIST_INSERT_HEAD(&head, sc, link); + sc->flags = flags; + if ((flags & VMMCTL_CREATE_DESTROY_ON_CLOSE) != 0) + LIST_INSERT_HEAD(&priv->softcs, sc, priv_link); make_dev_args_init(&mda); mda.mda_devsw = &vmmdevsw; @@ -1055,7 +1074,7 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS) buf = malloc(buflen, M_VMMDEV, M_WAITOK | M_ZERO); error = sysctl_handle_string(oidp, buf, buflen, req); if (error == 0 && req->newptr != NULL) - error = vmmdev_create(buf, req->td->td_ucred); + error = vmmdev_create(buf, 0, req->td->td_ucred); free(buf, M_VMMDEV); return (error); } @@ -1064,10 +1083,53 @@ SYSCTL_PROC(_hw_vmm, OID_AUTO, create, NULL, 0, sysctl_vmm_create, "A", "Create a vmm(4) instance (legacy interface)"); +static void +vmmctl_dtor(void *arg) +{ + struct cdev *sc_cdev; + struct vmmdev_softc *sc; + struct vmmctl_priv *priv = arg; + + /* + * Scan the softc list for any VMs associated with + * the current descriptor and destroy them. + */ + sx_xlock(&vmmdev_mtx); + while (!LIST_EMPTY(&priv->softcs)) { + sc = LIST_FIRST(&priv->softcs); + sc_cdev = sc->cdev; + if (sc_cdev != NULL) { + sc->cdev = NULL; + } else { + /* + * Another thread has already + * started the removal process. + * Sleep until 'vmmdev_destroy' notifies us + * that the removal has finished. + */ + sx_sleep(sc, &vmmdev_mtx, 0, "vmmctl_dtor", 0); + continue; + } + /* + * Temporarily drop the lock to allow vmmdev_destroy to run. + */ + sx_xunlock(&vmmdev_mtx); + (void)vm_suspend(sc->vm, VM_SUSPEND_DESTROY); + destroy_dev(sc_cdev); + /* vmmdev_destroy will unlink the 'priv_link' entry. */ + vmmdev_destroy(sc); + sx_xlock(&vmmdev_mtx); + } + sx_xunlock(&vmmdev_mtx); + + free(priv, M_VMMDEV); +} + static int vmmctl_open(struct cdev *cdev, int flags, int fmt, struct thread *td) { int error; + struct vmmctl_priv *priv; error = vmm_priv_check(td->td_ucred); if (error != 0) @@ -1076,6 +1138,14 @@ vmmctl_open(struct cdev *cdev, int flags, int fmt, struct thread *td) if ((flags & FWRITE) == 0) return (EPERM); + priv = malloc(sizeof(*priv), M_VMMDEV, M_WAITOK | M_ZERO); + LIST_INIT(&priv->softcs); + error = devfs_set_cdevpriv(priv, vmmctl_dtor); + if (error != 0) { + free(priv, M_VMMDEV); + return (error); + } + return (0); } @@ -1098,7 +1168,7 @@ vmmctl_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, } } - error = vmmdev_create(vmc->name, td->td_ucred); + error = vmmdev_create(vmc->name, vmc->flags, td->td_ucred); break; } case VMMCTL_VM_DESTROY: { diff --git a/sys/dev/vmm/vmm_dev.h b/sys/dev/vmm/vmm_dev.h index f14176c8afad..f8f637fda687 100644 --- a/sys/dev/vmm/vmm_dev.h +++ b/sys/dev/vmm/vmm_dev.h @@ -70,9 +70,13 @@ extern u_int vm_maxcpu; #endif /* _KERNEL */ +#define VMMCTL_CREATE_DESTROY_ON_CLOSE 0x1 +#define VMMCTL_FLAGS_MASK (VMMCTL_CREATE_DESTROY_ON_CLOSE) + struct vmmctl_vm_create { char name[VM_MAX_NAMELEN + 1]; - int reserved[16]; + uint32_t flags; + int reserved[15]; }; struct vmmctl_vm_destroy {