mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-24 17:44:17 +01:00
vmm: Add a device file interface for creating and destroying VMs
This supersedes the sysctl interface, which has the limitations of being root-only and not supporting automatic resource destruction, i.e., we cannot easily destroy VMs automatically when bhyve terminates. For now, two ioctls are implemented VMMCTL_VM_CREATE and VMMCTL_VM_DESTROY. Eventually I would like to support tying a VM's lifetime to that of the descriptor, so that it is automatically destroyed when the descriptor is closed. However, this will require some work in bhyve: when the guest wants to reboot, bhyve exits with a status that indicates that it is to be restarted. This is incompatible with the idea of tying a VM's lifetime to that of a descriptor, since we want to avoid creating and destroying a VM across each reboot (as this involves freeing all of the guest memory, among other things). One possible design would be to decompose bhyve into two processes, a parent which handles reboots, and a child which runs in capability mode and handles guest execution. In any case, this gets us closer to addressing the shortcomings mentioned above. Reviewed by: jhb Differential Revision: https://reviews.freebsd.org/D47028
This commit is contained in:
parent
8b54d874c7
commit
a97f683fe3
@ -465,7 +465,9 @@ vmm_handler(module_t mod, int what, void *arg)
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
if (vmm_is_hw_supported()) {
|
||||
vmmdev_init();
|
||||
error = vmmdev_init();
|
||||
if (error != 0)
|
||||
break;
|
||||
error = vmm_init();
|
||||
if (error == 0)
|
||||
vmm_initialized = 1;
|
||||
|
@ -362,7 +362,9 @@ vmm_handler(module_t mod, int what, void *arg)
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
/* TODO: if (vmm_is_hw_supported()) { */
|
||||
vmmdev_init();
|
||||
error = vmmdev_init();
|
||||
if (error != 0)
|
||||
break;
|
||||
error = vmm_init();
|
||||
if (error == 0)
|
||||
vmm_initialized = true;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/ioccom.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -917,11 +918,88 @@ SYSCTL_PROC(_hw_vmm, OID_AUTO, create,
|
||||
NULL, 0, sysctl_vmm_create, "A",
|
||||
NULL);
|
||||
|
||||
void
|
||||
static int
|
||||
vmmctl_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = vmm_priv_check(td->td_ucred);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if ((flags & FWRITE) == 0)
|
||||
return (EPERM);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vmmctl_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (cmd) {
|
||||
case VMMCTL_VM_CREATE: {
|
||||
struct vmmctl_vm_create *vmc;
|
||||
|
||||
vmc = (struct vmmctl_vm_create *)data;
|
||||
vmc->name[VM_MAX_NAMELEN] = '\0';
|
||||
for (size_t i = 0; i < nitems(vmc->reserved); i++) {
|
||||
if (vmc->reserved[i] != 0) {
|
||||
error = EINVAL;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
error = vmmdev_create(vmc->name, td->td_ucred);
|
||||
break;
|
||||
}
|
||||
case VMMCTL_VM_DESTROY: {
|
||||
struct vmmctl_vm_destroy *vmd;
|
||||
|
||||
vmd = (struct vmmctl_vm_destroy *)data;
|
||||
vmd->name[VM_MAX_NAMELEN] = '\0';
|
||||
for (size_t i = 0; i < nitems(vmd->reserved); i++) {
|
||||
if (vmd->reserved[i] != 0) {
|
||||
error = EINVAL;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
error = vmmdev_lookup_and_destroy(vmd->name, td->td_ucred);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error = ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct cdevsw vmmctlsw = {
|
||||
.d_name = "vmmctl",
|
||||
.d_version = D_VERSION,
|
||||
.d_open = vmmctl_open,
|
||||
.d_ioctl = vmmctl_ioctl,
|
||||
};
|
||||
|
||||
int
|
||||
vmmdev_init(void)
|
||||
{
|
||||
struct cdev *cdev;
|
||||
int error;
|
||||
|
||||
error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &vmmctlsw, NULL,
|
||||
UID_ROOT, GID_WHEEL, 0600, "vmmctl");
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
pr_allow_flag = prison_add_allow(NULL, "vmm", NULL,
|
||||
"Allow use of vmm in a jail.");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -18,7 +18,7 @@ struct thread;
|
||||
struct vm;
|
||||
struct vcpu;
|
||||
|
||||
void vmmdev_init(void);
|
||||
int vmmdev_init(void);
|
||||
int vmmdev_cleanup(void);
|
||||
int vmmdev_machdep_ioctl(struct vm *vm, struct vcpu *vcpu, u_long cmd,
|
||||
caddr_t data, int fflag, struct thread *td);
|
||||
@ -54,4 +54,17 @@ extern const size_t vmmdev_machdep_ioctl_count;
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
struct vmmctl_vm_create {
|
||||
char name[VM_MAX_NAMELEN + 1];
|
||||
int reserved[16];
|
||||
};
|
||||
|
||||
struct vmmctl_vm_destroy {
|
||||
char name[VM_MAX_NAMELEN + 1];
|
||||
int reserved[16];
|
||||
};
|
||||
|
||||
#define VMMCTL_VM_CREATE _IOWR('V', 0, struct vmmctl_vm_create)
|
||||
#define VMMCTL_VM_DESTROY _IOWR('V', 1, struct vmmctl_vm_destroy)
|
||||
|
||||
#endif /* _DEV_VMM_DEV_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user