Download raw body.
[EXT] Re: tests wanted: vmm(4)/vmd(8) fd-ification
Hi,
On Thu, Aug 06, 2026 at 05:09:35PM -0400, Dave Voutila wrote:
> Dave Voutila <dv@sisu.io> writes:
>
> Another update, fixing building GENERIC. Missed some ifdefs for
> MULTIPROCESSOR.
>
I'm running that latest diff with both SEV and SEV-ES VMs and see no
regressions so far.
> > Updated diff that applies to the tree again. Recent commit to vmd(8)
> > broke the original diff.
> >
> > There's a different vmd commit I'm making later today but by my testing
> > that shouldn't conflict with this diff.
> >
> > Dave Voutila <dv@sisu.io> writes:
> >
> >> Calling on vmm(4)/vmd(8) users to give this diff a test please!
> >>
> >> This is a major breaking change I'm proposing to land soon. It changes
> >> the vmm(4) design to create a new file type for each VM. When a VM is
> >> created, the caller gets a new file descriptor for using ioctl(2) calls
> >> against that VM.
> >>
> >> This fundamentally changes the design from knowing a "magic number"
> >> (today, the vm id) to possessing a capability (the open file
> >> descriptor).
> >>
> >> Why do this?
> >>
> >> - Better isolate which process can manipulate a VM. Today it's a hacky
> >> combination of knowing the magic number and vmm(4) tracking an owning
> >> PID. The current design scares me.
> >>
> >> - Better scope the vmm(4) API into basically a control plane vs. data
> >> plane design. A privileged process with an open /dev/vmm special file
> >> can launch/terminate VMs, but the manipulation of each VM and VCPU is
> >> done via its own dedicated file.
> >>
> >> - Using files helps simplify the lifecycle management of VMs in the
> >> kernel by tying their lifetime to a file. vmd(8) processes emulating
> >> the VM will have their file descriptor closed by the kernel even if
> >> the process is killed (e.g. via segfault). This simplifies cleanup of
> >> dead VMs.
> >>
> >> Bonus: there's a slight chance this improves perf slightly, but since
> >> that's not the goal I'm not benchmarking. Given a new ioctl(2) path for
> >> the new VM file type, it may reduce contention on the kernel lock.
> >>
> >> Note: this is unlike Linux/KVM which uses not only a file per VM, but
> >> one per VCPU. I see no reason for that level of complication at the moment.
> >>
> >> I don't expect detailed review yet given the size of this. I plan on
> >> sending separate mails breaking this down into kernel vs. userland (the
> >> userland stuff is a lot of deck chair shuffling) as well as updates to
> >> vmm.4 man page and fstat(1).
> >>
> >> To test:
> >>
> >> 1. build and install new kernel and reboot
> >> 2. symlink (recommended) or install headers in /usr/include:
> >> amd64/vmmvar.h --> sys/arch/amd64/include/vmmvar.h
> >> dev/vmm/vmm.h --> sys/dev/vmm/vmm.h
> >> dev/ic/pspvar.h --> sys/dev/ic/pspvar.h
> >
> > Also, you need sys/file.h --> sys/sys/file.h if building fstat(1).
> >
> >> 3. build and install vmd(8) and vmctl(8) (if this fails, check your
> >> headers in /usr/include/ point to the patched ones in the tree)
> >> 4. run your existing VMs...you should see no discernable difference in
> >> behavior.
> >>
> >> If things break or behavior changes, please report to me including:
> >>
> >> * cpu0 details from dmesg(1)
> >> * details on how the vm is started (/etc/vm.conf contents or vmctl(8)
> >> args)
> >> * vmd(8) debug output if any (try running vmd in the foreground via
> >> something like: # $(which vmd) -dvv
> >>
> >> ** I specifically need help testing SEV-related usage as I have no
> >> commercial grade AMD hardware with all the cool SEV stuff. **
> >>
> >> Once I land this I'll no longer lose sleep worrying about the current
> >> design and can turn my attentions to MMIO/instruction emulation needed
> >> for getting to SMP ;)
> >>
> >> Thanks!
> >>
>
> diff refs/heads/master refs/heads/vmm-fd-jul26
> commit - 38556f9d88df4854f048afb0c11bd3147ec2e92a
> commit + 91e058aa117d01c4f432feec6553fdd866bb3818
> blob - cf3afe729cc6dee1d6789ce566d9cfef7d6141e5
> blob + 43836fe9639258c08ebaa50ea3a55cccb9d9e6ce
> --- regress/sys/arch/amd64/vmm/vcpu.c
> +++ regress/sys/arch/amd64/vmm/vcpu.c
> @@ -90,11 +90,10 @@ main(int argc, char **argv)
> struct vm_info_result *info = NULL, *ours = NULL;
> struct vm_resetcpu_params vresetp;
> struct vm_run_params vrunp;
> - struct vm_terminate_params vtp;
> struct vm_sharemem_params vsp;
>
> struct vm_mem_range *vmr;
> - int fd, ret = 1;
> + int fd, vm_fd = -1, ret = 1;
> size_t i;
> off_t off, reset = 0xFFFFFFF0, stack = 0x800;
> void *p;
> @@ -120,23 +119,21 @@ main(int argc, char **argv)
>
> if (ioctl(fd, VMM_IOC_CREATE, &vcp) == -1)
> err(1, "VMM_IOC_CREATE");
> - printf("created vm %d named \"%s\"\n", vcp.vcp_id, vcp.vcp_name);
> + printf("created vm fd %d named \"%s\"\n", vcp.vcp_fd, vcp.vcp_name);
> + vm_fd = vcp.vcp_fd;
>
> /*
> * 2. Check we can create shared memory mappings.
> */
> memset(&vsp, 0, sizeof(vsp));
> - vsp.vsp_nmemranges = vcp.vcp_nmemranges;
> - memcpy(&vsp.vsp_memranges, &vcp.vcp_memranges,
> - sizeof(vsp.vsp_memranges));
> - vsp.vsp_vm_id = vcp.vcp_id;
> + vsp.vsp_fd = vm_fd;
>
> /* Perform the shared mapping. */
> - if (ioctl(fd, VMM_IOC_SHAREMEM, &vsp) == -1)
> + if (ioctl(vm_fd, VMM_IOC_SHAREMEM, &vsp) == -1)
> err(1, "VMM_IOC_SHAREMEM");
> printf("created shared memory mappings\n");
>
> - for (i = 0; i < vsp.vsp_nmemranges; i++)
> + for (i = 0; i < vcp.vcp_nmemranges; i++)
> vcp.vcp_memranges[i].vmr_va = vsp.vsp_va[i];
>
> for (i = 0; i < vcp.vcp_nmemranges; i++) {
> @@ -178,8 +175,8 @@ main(int argc, char **argv)
> }
>
> /* We should see our reset vector instructions in the new mappings. */
> - for (i = 0; i < vsp.vsp_nmemranges; i++) {
> - vmr = &vsp.vsp_memranges[i];
> + for (i = 0; i < vcp.vcp_nmemranges; i++) {
> + vmr = &vcp.vcp_memranges[i];
> p = (void*)vmr->vmr_va;
>
> if (i == LOW_MEM) {
> @@ -229,43 +226,38 @@ main(int argc, char **argv)
> }
>
> for (i = 0; i * sizeof(*info) < vip.vip_size; i++) {
> - if (info[i].vir_id == vcp.vcp_id) {
> + if (info[i].vir_creator_pid == getpid()) {
> ours = &info[i];
> break;
> }
> }
> if (ours == NULL) {
> - warn("failed to find vm %uz", vcp.vcp_id);
> + warn("failed to find vm for pid %d", getpid());
> goto out;
> }
>
> - if (ours->vir_id != vcp.vcp_id) {
> - warnx("expected vm id %uz, got %uz", vcp.vcp_id, ours->vir_id);
> - goto out;
> - }
> if (strncmp(ours->vir_name, VM_NAME, strlen(VM_NAME)) != 0) {
> warnx("expected vm name \"%s\", got \"%s\"", VM_NAME,
> ours->vir_name);
> goto out;
> }
> - printf("found vm %d named \"%s\"\n", vcp.vcp_id, ours->vir_name);
> + printf("found vm for pid %d named \"%s\"\n", getpid(), ours->vir_name);
> ours = NULL;
>
> /*
> * 4. Reset our VCPU and initialize register state.
> */
> memset(&vresetp, 0, sizeof(vresetp));
> - vresetp.vrp_vm_id = vcp.vcp_id;
> + vresetp.vrp_fd = vm_fd;
> vresetp.vrp_vcpu_id = 0; /* XXX SP */
> memcpy(&vresetp.vrp_init_state, &vcpu_init_flat16,
> sizeof(vcpu_init_flat16));
>
> - if (ioctl(fd, VMM_IOC_RESETCPU, &vresetp) == -1) {
> + if (ioctl(vm_fd, VMM_IOC_RESETCPU, &vresetp) == -1) {
> warn("VMM_IOC_RESETCPU");
> goto out;
> }
> - printf("reset vcpu %d for vm %d\n", vresetp.vrp_vcpu_id,
> - vresetp.vrp_vm_id);
> + printf("reset vcpu %d for vm fd %d\n", vresetp.vrp_vcpu_id, vm_fd);
>
> /*
> * 5. Run the vcpu, expecting an immediate exit for IO assist.
> @@ -279,26 +271,20 @@ main(int argc, char **argv)
> memset(&vrunp, 0, sizeof(vrunp));
> vrunp.vrp_exit = exit;
> vrunp.vrp_vcpu_id = 0; /* XXX SP */
> - vrunp.vrp_vm_id = vcp.vcp_id;
> + vrunp.vrp_fd = vm_fd;
> vrunp.vrp_irqready = 1;
>
> - if (ioctl(fd, VMM_IOC_RUN, &vrunp) == -1) {
> + if (ioctl(vm_fd, VMM_IOC_RUN, &vrunp) == -1) {
> warn("VMM_IOC_RUN");
> goto out;
> }
>
> - if (vrunp.vrp_vm_id != vcp.vcp_id) {
> - warnx("expected vm id %uz, got %uz", vcp.vcp_id,
> - vrunp.vrp_vm_id);
> - goto out;
> - }
> -
> switch (vrunp.vrp_exit_reason) {
> case SVM_VMEXIT_IOIO:
> case VMX_EXIT_IO:
> - printf("vcpu %d on vm %d exited for io assist @ ip = 0x%llx, "
> + printf("vcpu %d on vm fd %d exited for io assist @ ip = 0x%llx, "
> "cs.base = 0x%llx, ss.base = 0x%llx, rsp = 0x%llx\n",
> - vrunp.vrp_vcpu_id, vrunp.vrp_vm_id,
> + vrunp.vrp_vcpu_id, vm_fd,
> vrunp.vrp_exit->vrs.vrs_gprs[VCPU_REGS_RIP],
> vrunp.vrp_exit->vrs.vrs_sregs[VCPU_REGS_CS].vsi_base,
> vrunp.vrp_exit->vrs.vrs_sregs[VCPU_REGS_SS].vsi_base,
> @@ -333,7 +319,7 @@ main(int argc, char **argv)
> vrunp.vrp_inject.vie_errorcode = 0x11223344;
> vrunp.vrp_inject.vie_type = VCPU_INJECT_EX;
> printf("injecting exception 0x%x\n", vrunp.vrp_inject.vie_vector);
> - if (ioctl(fd, VMM_IOC_RUN, &vrunp) == -1) {
> + if (ioctl(vm_fd, VMM_IOC_RUN, &vrunp) == -1) {
> warn("VMM_IOC_RUN 2");
> goto out;
> }
> @@ -341,8 +327,8 @@ main(int argc, char **argv)
> switch (vrunp.vrp_exit_reason) {
> case SVM_VMEXIT_IOIO:
> case VMX_EXIT_IO:
> - printf("vcpu %d on vm %d exited for io assist @ ip = 0x%llx, "
> - "cs.base = 0x%llx\n", vrunp.vrp_vcpu_id, vrunp.vrp_vm_id,
> + printf("vcpu %d on vm fd %d exited for io assist @ ip = 0x%llx, "
> + "cs.base = 0x%llx\n", vrunp.vrp_vcpu_id, vm_fd,
> vrunp.vrp_exit->vrs.vrs_gprs[VCPU_REGS_RIP],
> vrunp.vrp_exit->vrs.vrs_sregs[VCPU_REGS_CS].vsi_base);
> break;
> @@ -372,13 +358,13 @@ out:
> if (i > 0)
> printf(" ");
> printf("%02x", *(uint8_t*)
> - (vsp.vsp_memranges[UPPER_MEM].vmr_va + off + i));
> + (vcp.vcp_memranges[UPPER_MEM].vmr_va + off + i));
> }
> printf("\n--- STACK @ gpa 0x%llx ---\n", stack);
> for (i=0; i<16; i++) {
> if (i > 0)
> printf(" ");
> - printf("%02x", *(uint8_t*)(vsp.vsp_memranges[LOW_MEM].vmr_va
> + printf("%02x", *(uint8_t*)(vcp.vcp_memranges[LOW_MEM].vmr_va
> + stack - i - 1));
> }
> printf("\n");
> @@ -386,13 +372,8 @@ out:
> /*
> * 6. Terminate our VM and clean up.
> */
> - memset(&vtp, 0, sizeof(vtp));
> - vtp.vtp_vm_id = vcp.vcp_id;
> - if (ioctl(fd, VMM_IOC_TERM, &vtp) == -1) {
> - warn("VMM_IOC_TERM");
> - ret = 1;
> - } else
> - printf("terminated vm %d\n", vtp.vtp_vm_id);
> + if (vm_fd != -1)
> + close(vm_fd);
>
> close(fd);
> free(info);
> blob - cc621a8eee3faf2521b1c9ba014b8dee77cacfc9
> blob + 05ae299446902adcf3489b3a1dea4e7231fc18d9
> --- share/man/man4/man4.amd64/vmm.4
> +++ share/man/man4/man4.amd64/vmm.4
> @@ -14,7 +14,7 @@
> .\"ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> .\"OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> .\"
> -.Dd $Mdocdate: November 5 2024 $
> +.Dd $Mdocdate: March 2 2026 $
> .Dt VMM 4 amd64
> .Os
> .Sh NAME
> @@ -72,23 +72,53 @@ For more information, consult the CPU vendor's documen
> .Pp
> The following
> .Xr ioctl 2
> -commands are provided for managing
> -.Nm
> -guests:
> +commands are provided through two interfaces:
> .Bl -tag -width Ds -offset indent
> +.It Pa /dev/vmm
> +Control device for creating VMs and querying system-wide VM information.
> +.It VM file descriptor
> +Per-VM handle returned by
> +.Dv VMM_IOC_CREATE .
> +The lifetime of a VM is tied to this descriptor; closing it tears down the VM.
> +.El
> +.Pp
> +The following ioctl calls apply to the
> +.Pa /dev/vmm
> +control device:
> +.Bl -tag -width Ds -offset indent
> .It Dv VMM_IOC_CREATE Fa "struct vm_create_params *"
> -Create a VM, initializing
> +Create a VM via
> +.Pa /dev/vmm ,
> +initializing
> .Nm
> if not yet started.
> +Returns a VM file descriptor in
> +.Fa vcp_fd .
> (Does not start the VCPU.)
> -.It Dv VMM_IOC_RUN Fa "struct vm_run_params *"
> -Run a VCPU for a defined VM.
> -Return on VM-exit, when the VCPU stopped, or an error occurred.
> .It Dv VMM_IOC_INFO Fa "struct vm_info_params *"
> Get information about the VMs currently hosted by
> .Nm .
> .It Dv VMM_IOC_TERM Fa "struct vm_terminate_params *"
> -Terminate a given VM.
> +Request termination of the VM whose creator PID matches
> +.Fa vtp_creator_pid .
> +This ioctl is issued on
> +.Pa /dev/vmm .
> +It marks the VM for termination and requests running VCPUs to stop.
> +Final cleanup happens when the last VM file descriptor reference is closed.
> +.Pp
> +All other ioctls, including
> +.Dv VMM_IOC_INTR ,
> +are unsupported on
> +.Pa /dev/vmm
> +and return
> +.Dv ENOTTY .
> +.El
> +.Pp
> +The following ioctl calls apply to the VM file descriptor returned by
> +.Dv VMM_IOC_CREATE .
> +.Bl -tag -width Ds -offset indent
> +.It Dv VMM_IOC_RUN Fa "struct vm_run_params *"
> +Run a VCPU and return on VM-exit, when the VCPU stopped, or on error.
> .It Dv VMM_IOC_RESETCPU Fa "struct vm_resetcpu_params *"
> Reset a VCPU to power-on-init state using the provided register state.
> .It Dv VMM_IOC_INTR Fa "struct vm_intr_params *"
> @@ -105,6 +135,8 @@ version) for a VM.
> Write paravirtualized hardware parameters (such as
> .Xr pvclock 4
> guest physical address) for a VM.
> +.It Dv VMM_IOC_SHAREMEM Fa "struct vm_sharemem_params *"
> +Create shared mappings for the VM memory ranges into the calling process.
> .El
> .Sh SEE ALSO
> .Xr cpu 4 ,
> blob - 787b65e29e167453c2d5492d5658833d5a75f5af
> blob + 1fd7df73f156a0968bbdeff7b7ae7235b1651ae3
> --- sys/arch/amd64/amd64/vmm_machdep.c
> +++ sys/arch/amd64/amd64/vmm_machdep.c
> @@ -68,12 +68,8 @@ void *l1tf_flush_region;
> void vmx_dump_vmcs_field(uint16_t, const char *);
> int vmm_enabled(void);
> void vmm_activate_machdep(struct device *, int);
> -int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *);
> int vmm_quiesce_vmx(void);
> -int vm_run(struct vm_run_params *);
> -int vm_intr_pending(struct vm_intr_params *);
> -int vm_rwregs(struct vm_rwregs_params *, int);
> -int vm_rwvmparams(struct vm_rwvmparams_params *, int);
> +int vm_intr_pending(struct vm *, struct vm_intr_params *);
> int vcpu_readregs_vmx(struct vcpu *, uint64_t, int, struct vcpu_reg_state *);
> int vcpu_readregs_svm(struct vcpu *, uint64_t, struct vcpu_reg_state *);
> int vcpu_writeregs_vmx(struct vcpu *, uint64_t, int, struct vcpu_reg_state *);
> @@ -148,7 +144,6 @@ void vmx_setmsrbw(struct vcpu *, uint32_t);
> void vmx_setmsrbrw(struct vcpu *, uint32_t);
> void svm_set_clean(struct vcpu *, uint32_t);
> void svm_set_dirty(struct vcpu *, uint32_t);
> -int svm_get_vmsa_pa(uint32_t, uint32_t, uint64_t *);
>
> int vmm_gpa_is_valid(struct vcpu *vcpu, paddr_t gpa, size_t obj_size);
> void vmm_init_pvclock(struct vcpu *, paddr_t);
> @@ -438,34 +433,6 @@ vmm_activate_machdep(struct device *self, int act)
> }
> }
>
> -int
> -vmmioctl_machdep(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
> -{
> - int ret;
> -
> - switch (cmd) {
> - case VMM_IOC_INTR:
> - ret = vm_intr_pending((struct vm_intr_params *)data);
> - break;
> - default:
> - DPRINTF("%s: unknown ioctl code 0x%lx\n", __func__, cmd);
> - ret = ENOTTY;
> - }
> -
> - return (ret);
> -}
> -
> -int
> -pledge_ioctl_vmm_machdep(struct proc *p, long com)
> -{
> - switch (com) {
> - case VMM_IOC_INTR:
> - return (0);
> - }
> -
> - return (EPERM);
> -}
> -
> /*
> * vm_intr_pending
> *
> @@ -480,22 +447,14 @@ pledge_ioctl_vmm_machdep(struct proc *p, long com)
> * ENOENT: if the VM/VCPU defined by 'vip' cannot be found
> */
> int
> -vm_intr_pending(struct vm_intr_params *vip)
> +vm_intr_pending(struct vm *vm, struct vm_intr_params *vip)
> {
> - struct vm *vm;
> struct vcpu *vcpu;
> #ifdef MULTIPROCESSOR
> struct cpu_info *ci;
> #endif
> - int error, ret = 0;
> + int ret = 0;
>
> - /* Find the desired VM */
> - error = vm_find(vip->vip_vm_id, &vm);
> -
> - /* Not found? exit. */
> - if (error != 0)
> - return (error);
> -
> vcpu = vm_find_vcpu(vm, vip->vip_vcpu_id);
>
> if (vcpu == NULL) {
> @@ -511,7 +470,6 @@ vm_intr_pending(struct vm_intr_params *vip)
> #endif
>
> out:
> - refcnt_rele_wake(&vm->vm_refcnt);
> return (ret);
> }
>
> @@ -531,19 +489,11 @@ out:
> * EINVAL: if an error occurred reading the registers of the guest
> */
> int
> -vm_rwvmparams(struct vm_rwvmparams_params *vpp, int dir)
> +vm_rwvmparams(struct vm *vm, struct vm_rwvmparams_params *vpp, int dir)
> {
> - struct vm *vm;
> struct vcpu *vcpu;
> - int error, ret = 0;
> + int ret = 0;
>
> - /* Find the desired VM */
> - error = vm_find(vpp->vpp_vm_id, &vm);
> -
> - /* Not found? exit. */
> - if (error != 0)
> - return (error);
> -
> vcpu = vm_find_vcpu(vm, vpp->vpp_vcpu_id);
>
> if (vcpu == NULL) {
> @@ -565,7 +515,6 @@ vm_rwvmparams(struct vm_rwvmparams_params *vpp, int di
> }
> }
> out:
> - refcnt_rele_wake(&vm->vm_refcnt);
> return (ret);
> }
>
> @@ -587,20 +536,12 @@ out:
> * EPERM: if the vm cannot be accessed from the calling process
> */
> int
> -vm_rwregs(struct vm_rwregs_params *vrwp, int dir)
> +vm_rwregs(struct vm *vm, struct vm_rwregs_params *vrwp, int dir)
> {
> - struct vm *vm;
> struct vcpu *vcpu;
> struct vcpu_reg_state *vrs = &vrwp->vrwp_regs;
> - int error, ret = 0;
> + int ret = 0;
>
> - /* Find the desired VM */
> - error = vm_find(vrwp->vrwp_vm_id, &vm);
> -
> - /* Not found? exit. */
> - if (error != 0)
> - return (error);
> -
> vcpu = vm_find_vcpu(vm, vrwp->vrwp_vcpu_id);
>
> if (vcpu == NULL) {
> @@ -623,7 +564,6 @@ vm_rwregs(struct vm_rwregs_params *vrwp, int dir)
> }
> rw_exit_write(&vcpu->vc_lock);
> out:
> - refcnt_rele_wake(&vm->vm_refcnt);
> return (ret);
> }
>
> @@ -3348,20 +3288,12 @@ vcpu_vmx_compute_ctrl(uint64_t ctrlval, uint16_t ctrl,
> * 0: the run loop exited and no help is needed from vmd(8)
> */
> int
> -vm_run(struct vm_run_params *vrp)
> +vm_run(struct vm *vm, struct vm_run_params *vrp)
> {
> - struct vm *vm;
> struct vcpu *vcpu;
> int ret = 0, vcpu_rv = 0;
> u_int old, next;
>
> - /*
> - * Find desired VM
> - */
> - ret = vm_find(vrp->vrp_vm_id, &vm);
> - if (ret)
> - return (ret);
> -
> vcpu = vm_find_vcpu(vm, vrp->vrp_vcpu_id);
> if (vcpu == NULL) {
> ret = ENOENT;
> @@ -3419,7 +3351,6 @@ vm_run(struct vm_run_params *vrp)
> out_unlock:
> rw_exit_write(&vcpu->vc_lock);
> out:
> - refcnt_rele_wake(&vm->vm_refcnt);
> return (ret);
> }
>
> @@ -7412,13 +7343,13 @@ vcpu_state_decode(u_int state)
> * Return physical address of VMSA for specified VCPU.
> */
> int
> -svm_get_vmsa_pa(uint32_t vmid, uint32_t vcpuid, uint64_t *vmsapa)
> +svm_get_vmsa_pa(struct proc *p, int fd, uint32_t vcpuid, uint64_t *vmsapa)
> {
> struct vm *vm;
> struct vcpu *vcpu;
> int error, ret = 0;
>
> - error = vm_find(vmid, &vm);
> + error = vm_find_file(fd, p, &vm);
> if (error)
> return (error);
>
> blob - 25b1618ad1ff6590eb030e9a89729da2c954c9d0
> blob + 3f594cb58dcd585f50bd6ba89bf4fd14824d0b4b
> --- sys/arch/amd64/include/vmmvar.h
> +++ sys/arch/amd64/include/vmmvar.h
> @@ -23,6 +23,8 @@
>
> #ifndef _LOCORE
>
> +struct vm;
> +
> #define VMM_HV_SIGNATURE "OpenBSDVMM58"
>
> /* VMX: Basic Exit Reasons */
> @@ -477,7 +479,6 @@ struct vm_exit {
>
> struct vm_intr_params {
> /* Input parameters to VMM_IOC_INTR */
> - uint32_t vip_vm_id;
> uint32_t vip_vcpu_id;
> uint16_t vip_intr;
> };
> @@ -495,7 +496,6 @@ struct vm_rwregs_params {
> * Input/output parameters to VMM_IOC_READREGS /
> * VMM_IOC_WRITEREGS
> */
> - uint32_t vrwp_vm_id;
> uint32_t vrwp_vcpu_id;
> uint64_t vrwp_mask;
> struct vcpu_reg_state vrwp_regs;
> @@ -1056,17 +1056,15 @@ void vmclear_on_cpu(struct cpu_info *);
> int vmm_probe_machdep(struct device *, void *, void *);
> void vmm_attach_machdep(struct device *, struct device *, void *);
> void vmm_activate_machdep(struct device *, int);
> -int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *);
> -int pledge_ioctl_vmm_machdep(struct proc *, long);
> int vmm_start(void);
> int vmm_stop(void);
> int vm_impl_init(struct vm *, struct proc *);
> void vm_impl_deinit(struct vm *);
> int vcpu_init(struct vcpu *, struct vm_create_params *);
> void vcpu_deinit(struct vcpu *);
> -int vm_rwregs(struct vm_rwregs_params *, int);
> +int vm_rwregs(struct vm *, struct vm_rwregs_params *, int);
> int vcpu_reset_regs(struct vcpu *, struct vcpu_reg_state *);
> -int svm_get_vmsa_pa(uint32_t, uint32_t, uint64_t *);
> +int svm_get_vmsa_pa(struct proc *, int, uint32_t, uint64_t *);
>
> #endif /* _KERNEL */
>
> blob - fb64df87384303d04ed6112d3f3866b261bb2899
> blob + 47973afbc9688f9acab4991fac557abddef0e63f
> --- sys/arch/arm64/include/vmmvar.h
> +++ sys/arch/arm64/include/vmmvar.h
> @@ -63,7 +63,6 @@ struct vm_exit {
>
> struct vm_intr_params {
> /* Input parameters to VMM_IOC_INTR */
> - uint32_t vip_vm_id;
> uint32_t vip_vcpu_id;
> uint16_t vip_intr;
> };
> @@ -76,7 +75,6 @@ struct vm_rwregs_params {
> * Input/output parameters to VMM_IOC_READREGS /
> * VMM_IOC_WRITEREGS
> */
> - uint32_t vrwp_vm_id;
> uint32_t vrwp_vcpu_id;
> uint64_t vrwp_mask;
> struct vcpu_reg_state vrwp_regs;
> blob - 48c463b28898dddfce5e5a7d77ddc4b1e7c57abb
> blob + d6765901c6c7a265a84a2c3e170827e414b0e7a9
> --- sys/dev/ic/psp.c
> +++ sys/dev/ic/psp.c
> @@ -697,13 +697,14 @@ psp_activate(struct psp_softc *sc, struct psp_activate
> }
>
> int
> -psp_encrypt_state(struct psp_softc *sc, struct psp_encrypt_state *ues)
> +psp_encrypt_state(struct psp_softc *sc, struct psp_encrypt_state *ues,
> + struct proc *p)
> {
> struct psp_launch_update_vmsa luvmsa;
> uint64_t vmsa_paddr;
> int error;
>
> - error = svm_get_vmsa_pa(ues->vmid, ues->vcpuid, &vmsa_paddr);
> + error = svm_get_vmsa_pa(p, ues->vmfd, ues->vcpuid, &vmsa_paddr);
> if (error != 0)
> return (error);
>
> @@ -922,7 +923,8 @@ pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag
> (struct psp_snp_platform_status *)data);
> break;
> case PSP_IOC_ENCRYPT_STATE:
> - error = psp_encrypt_state(sc, (struct psp_encrypt_state *)data);
> + error = psp_encrypt_state(sc, (struct psp_encrypt_state *)data,
> + p);
> break;
> default:
> error = ENOTTY;
> blob - d319357e8426770b15f9193dd8ba111f16e90ab5
> blob + 2c2f24ade1c35ff21d8b94585da699d94c930e19
> --- sys/dev/ic/pspvar.h
> +++ sys/dev/ic/pspvar.h
> @@ -154,7 +154,7 @@ struct psp_encrypt_state {
> /* Input parameters state encryption */
> uint32_t handle;
> uint32_t asid;
> - uint32_t vmid;
> + int vmfd;
> uint32_t vcpuid;
> } __packed;
>
> blob - 42fc6933911239c956034f4f6c6538fe8486c980
> blob + 86fe6b5292f8b770d8d410314b1caafd474443f1
> --- sys/dev/vmm/vmm.c
> +++ sys/dev/vmm/vmm.c
> @@ -18,12 +18,16 @@
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/device.h>
> +#include <sys/fcntl.h>
> +#include <sys/file.h>
> +#include <sys/filedesc.h>
> #include <sys/pool.h>
> #include <sys/pledge.h>
> #include <sys/proc.h>
> #include <sys/ioctl.h>
> #include <sys/malloc.h>
> #include <sys/signalvar.h>
> +#include <sys/stat.h>
>
> #include <uvm/uvm_extern.h>
> #include <uvm/uvm_aobj.h>
> @@ -36,6 +40,13 @@ struct vmm_softc *vmm_softc;
> struct pool vm_pool;
> struct pool vcpu_pool;
>
> +int vmm_probe(struct device *, void *, void *);
> +int vmm_activate(struct device *, int);
> +void vmm_attach(struct device *, struct device *, void *);
> +int vmmopen(dev_t, int, int, struct proc *);
> +int vmmclose(dev_t, int, int, struct proc *);
> +int vm_find_file(int, struct proc *, struct vm **);
> +
> struct cfdriver vmm_cd = {
> NULL, "vmm", DV_DULL, CD_SKIPHIBERNATE
> };
> @@ -44,6 +55,39 @@ const struct cfattach vmm_ca = {
> sizeof(struct vmm_softc), vmm_probe, vmm_attach, NULL, vmm_activate
> };
>
> +int pledge_ioctl_vmm_dev(struct proc *, long);
> +int vmm_dev_enter(void);
> +void vmm_dev_exit(void);
> +int vm_create(struct vm_create_params *, struct proc *, struct vm **);
> +size_t vm_create_check_mem_ranges(struct vm_create_params *);
> +int vm_create_file(struct vm_create_params *, struct proc *, struct vm *);
> +int vm_find_pid(pid_t, struct vm **);
> +int vm_get_info(struct vm_info_params *);
> +int vm_intr_pending(struct vm *, struct vm_intr_params *);
> +int vm_terminate(struct vm_terminate_params *);
> +int vm_resetcpu(struct vm *, struct vm_resetcpu_params *);
> +int vm_rwvmparams(struct vm *, struct vm_rwvmparams_params *, int);
> +int vm_share_mem(struct vm *, struct vm_sharemem_params *, struct proc *);
> +void vm_teardown(struct vm **);
> +void vm_request_stop(struct vm *);
> +
> +int vm_read(struct file *, struct uio *, int);
> +int vm_write(struct file *, struct uio *, int);
> +int vm_close(struct file *, struct proc *);
> +int vm_kqfilter(struct file *, struct knote *);
> +int vm_ioctl(struct file *, u_long, caddr_t, struct proc *);
> +int vm_stat(struct file *, struct stat *, struct proc *);
> +
> +static const struct fileops vmops = {
> + .fo_read = vm_read,
> + .fo_write = vm_write,
> + .fo_ioctl = vm_ioctl,
> + .fo_kqfilter = vm_kqfilter,
> + .fo_stat = vm_stat,
> + .fo_close = vm_close,
> + .fo_seek = NULL, /* lseek(2) checks for NULL. */
> +};
> +
> int
> vmm_probe(struct device *parent, void *match, void *aux)
> {
> @@ -154,126 +198,137 @@ vmmclose(dev_t dev, int flag, int mode, struct proc *p
> return 0;
> }
>
> -/*
> - * vm_find
> - *
> - * Function to find an existing VM by its identifier.
> - * Must be called under the global vm_lock.
> - *
> - * Parameters:
> - * id: The VM identifier.
> - * *res: A pointer to the VM or NULL if not found
> - *
> - * Return values:
> - * 0: if successful
> - * ENOENT: if the VM defined by 'id' cannot be found
> - * EPERM: if the VM cannot be accessed by the current process
> - */
> int
> -vm_find(uint32_t id, struct vm **res)
> +vm_find_file(int fd, struct proc *p, struct vm **res)
> {
> - struct proc *p = curproc;
> + struct filedesc *fdp = p->p_fd;
> + struct file *fp;
> + struct vm *vm = NULL;
> +
> + *res = NULL;
> +
> + if ((fp = fd_getfile(fdp, fd)) == NULL)
> + return (EBADF);
> +
> + if (fp->f_type != DTYPE_VMM) {
> + FRELE(fp, p);
> + return (EINVAL);
> + }
> +
> + vm = (struct vm *)fp->f_data;
> + refcnt_take(&vm->vm_refcnt);
> + *res = vm;
> + FRELE(fp, p);
> +
> + return (0);
> +}
> +
> +int
> +vm_find_pid(pid_t pid, struct vm **res)
> +{
> struct vm *vm;
> - int ret = ENOENT;
>
> *res = NULL;
>
> + if (pid <= 0)
> + return (EINVAL);
> +
> rw_enter_read(&vmm_softc->vm_lock);
> SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link) {
> - if (vm->vm_id == id) {
> - /*
> - * In the pledged VM process, only allow to find
> - * the VM that is running in the current process.
> - * The managing vmm parent process can lookup all
> - * all VMs and is indicated by PLEDGE_PROC.
> - */
> - if (((p->p_pledge &
> - (PLEDGE_VMM | PLEDGE_PROC)) == PLEDGE_VMM) &&
> - (vm->vm_creator_pid != p->p_p->ps_pid))
> - ret = EPERM;
> - else {
> - refcnt_take(&vm->vm_refcnt);
> - *res = vm;
> - ret = 0;
> - }
> + if (vm->vm_creator_pid == pid) {
> + refcnt_take(&vm->vm_refcnt);
> + *res = vm;
> break;
> }
> }
> rw_exit_read(&vmm_softc->vm_lock);
>
> - if (ret == EPERM)
> - return (pledge_fail(p, EPERM, PLEDGE_VMM));
> - return (ret);
> + if (*res == NULL)
> + return (ENOENT);
> +
> + return (0);
> }
>
> /*
> - * vmmioctl
> + * vmm_dev_enter
> *
> - * Main ioctl dispatch routine for /dev/vmm. Parses ioctl type and calls
> - * appropriate lower level handler routine. Returns result to ioctl caller.
> + * Acquire a reference to the vmm softc instance, sleeping if it's not
> + * currently active due to power management (i.e. suspend/resume).
> */
> int
> -vmmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
> +vmm_dev_enter(void)
> {
> int ret;
>
> - KERNEL_UNLOCK();
> -
> ret = rw_enter(&vmm_softc->sc_slock, RW_READ | RW_INTR);
> if (ret != 0)
> - goto out;
> + return (ret);
> while (vmm_softc->sc_status != VMM_ACTIVE) {
> ret = rwsleep_nsec(&vmm_softc->sc_status, &vmm_softc->sc_slock,
> PWAIT | PCATCH, "vmmresume", INFSLP);
> if (ret != 0) {
> rw_exit(&vmm_softc->sc_slock);
> - goto out;
> + return (ret);
> }
> }
> refcnt_take(&vmm_softc->sc_refcnt);
> rw_exit(&vmm_softc->sc_slock);
> + return (0);
> +}
>
> +/*
> + * vmm_dev_exit
> + *
> + * Release a reference to the vmm softc, waking any waiters.
> + */
> +void
> +vmm_dev_exit(void)
> +{
> + refcnt_rele_wake(&vmm_softc->sc_refcnt);
> +}
> +
> +/*
> + * vmmioctl
> + *
> + * Main ioctl dispatch for vmm(4) providing global operations for
> + * creating, terminating, and inspecting virtual machines.
> + */
> +int
> +vmmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
> +{
> + struct vm *vm = NULL;
> + int ret = ENOTTY;
> +
> + KERNEL_UNLOCK();
> +
> + ret = vmm_dev_enter();
> + if (ret != 0)
> + goto out;
> +
> switch (cmd) {
> case VMM_IOC_CREATE:
> - if ((ret = vmm_start()) != 0) {
> + ret = vmm_start();
> + if (ret) {
> vmm_stop();
> break;
> }
> - ret = vm_create((struct vm_create_params *)data, p);
> + ret = vm_create((struct vm_create_params *)data, p, &vm);
> + if (ret)
> + break;
> + ret = vm_create_file((struct vm_create_params *)data, p, vm);
> break;
> - case VMM_IOC_RUN:
> - ret = vm_run((struct vm_run_params *)data);
> - break;
> case VMM_IOC_INFO:
> ret = vm_get_info((struct vm_info_params *)data);
> break;
> case VMM_IOC_TERM:
> ret = vm_terminate((struct vm_terminate_params *)data);
> break;
> - case VMM_IOC_RESETCPU:
> - ret = vm_resetcpu((struct vm_resetcpu_params *)data);
> - break;
> - case VMM_IOC_READREGS:
> - ret = vm_rwregs((struct vm_rwregs_params *)data, 0);
> - break;
> - case VMM_IOC_WRITEREGS:
> - ret = vm_rwregs((struct vm_rwregs_params *)data, 1);
> - break;
> - case VMM_IOC_READVMPARAMS:
> - ret = vm_rwvmparams((struct vm_rwvmparams_params *)data, 0);
> - break;
> - case VMM_IOC_WRITEVMPARAMS:
> - ret = vm_rwvmparams((struct vm_rwvmparams_params *)data, 1);
> - break;
> - case VMM_IOC_SHAREMEM:
> - ret = vm_share_mem((struct vm_sharemem_params *)data, p);
> - break;
> default:
> - ret = vmmioctl_machdep(dev, cmd, data, flag, p);
> + ret = ENOTTY;
> break;
> }
>
> - refcnt_rele_wake(&vmm_softc->sc_refcnt);
> + vmm_dev_exit();
> out:
> KERNEL_LOCK();
>
> @@ -281,39 +336,6 @@ out:
> }
>
> /*
> - * pledge_ioctl_vmm
> - *
> - * Restrict the allowed ioctls in a pledged process context.
> - * Is called from pledge_ioctl().
> - */
> -int
> -pledge_ioctl_vmm(struct proc *p, long com)
> -{
> - switch (com) {
> - case VMM_IOC_CREATE:
> - case VMM_IOC_INFO:
> - case VMM_IOC_SHAREMEM:
> - /* The "parent" process in vmd forks and manages VMs */
> - if (p->p_pledge & PLEDGE_PROC)
> - return (0);
> - break;
> - case VMM_IOC_TERM:
> - /* XXX VM processes should only terminate themselves */
> - case VMM_IOC_RUN:
> - case VMM_IOC_RESETCPU:
> - case VMM_IOC_READREGS:
> - case VMM_IOC_WRITEREGS:
> - case VMM_IOC_READVMPARAMS:
> - case VMM_IOC_WRITEVMPARAMS:
> - return (0);
> - default:
> - return pledge_ioctl_vmm_machdep(p, com);
> - }
> -
> - return (EPERM);
> -}
> -
> -/*
> * vm_find_vcpu
> *
> * Lookup VMM VCPU by ID number
> @@ -353,7 +375,7 @@ vm_find_vcpu(struct vm *vm, uint32_t id)
> * various other errors from vcpu_init/vm_impl_init
> */
> int
> -vm_create(struct vm_create_params *vcp, struct proc *p)
> +vm_create(struct vm_create_params *vcp, struct proc *p, struct vm **out)
> {
> int i, ret = EINVAL;
> size_t memsize;
> @@ -363,6 +385,8 @@ vm_create(struct vm_create_params *vcp, struct proc *p
> struct vm_mem_range *vmr;
> unsigned int uvmflags = 0;
>
> + *out = NULL;
> +
> memsize = vm_create_check_mem_ranges(vcp);
> if (memsize == 0)
> return (EINVAL);
> @@ -474,7 +498,6 @@ vm_create(struct vm_create_params *vcp, struct proc *p
> rw_enter_write(&vmm_softc->vm_lock);
> vmm_softc->vm_idx++;
> vm->vm_id = vmm_softc->vm_idx;
> - vcp->vcp_id = vm->vm_id;
>
> refcnt_init(&vm->vm_refcnt);
> SLIST_INSERT_HEAD(&vmm_softc->vm_list, vm, vm_link);
> @@ -484,6 +507,7 @@ vm_create(struct vm_create_params *vcp, struct proc *p
> memcpy(vcp->vcp_memranges, vm->vm_memranges,
> vcp->vcp_nmemranges * sizeof(vcp->vcp_memranges[0]));
>
> + *out = vm;
> return (0);
>
> err:
> @@ -639,10 +663,12 @@ vm_get_info(struct vm_info_params *vip)
> struct vm *vm;
> struct vcpu *vcpu;
> int i = 0, j;
> - size_t need, vm_ct;
> + size_t alloc, need, vm_ct;
>
> rw_enter_read(&vmm_softc->vm_lock);
> - vm_ct = vmm_softc->vm_ct;
> + vm_ct = 0;
> + SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link)
> + vm_ct++;
> rw_exit_read(&vmm_softc->vm_lock);
>
> need = vm_ct * sizeof(struct vm_info_result);
> @@ -652,14 +678,19 @@ vm_get_info(struct vm_info_params *vip)
> return (0);
> }
>
> - out = malloc(need, M_DEVBUF, M_NOWAIT|M_ZERO);
> + if (vm_ct == 0) {
> + vip->vip_info_ct = 0;
> + vip->vip_size = 0;
> + return (0);
> + }
> +
> + alloc = need;
> + out = malloc(alloc, M_DEVBUF, M_NOWAIT|M_ZERO);
> if (out == NULL) {
> vip->vip_info_ct = 0;
> return (ENOMEM);
> }
>
> - vip->vip_info_ct = vm_ct;
> -
> rw_enter_read(&vmm_softc->vm_lock);
> SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link) {
> refcnt_take(&vm->vm_refcnt);
> @@ -668,7 +699,6 @@ vm_get_info(struct vm_info_params *vip)
> out[i].vir_used_size =
> pmap_resident_count(vm->vm_pmap) * PAGE_SIZE;
> out[i].vir_ncpus = vm->vm_vcpu_ct;
> - out[i].vir_id = vm->vm_id;
> out[i].vir_creator_pid = vm->vm_creator_pid;
> strlcpy(out[i].vir_name, vm->vm_name, VMM_MAX_NAME_LEN);
>
> @@ -678,7 +708,7 @@ vm_get_info(struct vm_info_params *vip)
> vc_vcpu_link) {
> if (vcpu->vc_id == j)
> out[i].vir_vcpu_state[j] =
> - vcpu->vc_state;
> + atomic_load_int(&vcpu->vc_state);
> }
> }
>
> @@ -688,75 +718,94 @@ vm_get_info(struct vm_info_params *vip)
> break; /* Truncate to keep within bounds of 'out'. */
> }
> rw_exit_read(&vmm_softc->vm_lock);
> + vip->vip_info_ct = i;
> + need = i * sizeof(struct vm_info_result);
> + vip->vip_size = need;
>
> if (copyout(out, vip->vip_info, need) == EFAULT) {
> - free(out, M_DEVBUF, need);
> + free(out, M_DEVBUF, alloc);
> return (EFAULT);
> }
>
> - free(out, M_DEVBUF, need);
> + free(out, M_DEVBUF, alloc);
> return (0);
> }
>
> -/*
> - * vm_terminate
> - *
> - * Terminates the VM indicated by 'vtp'.
> - *
> - * Parameters:
> - * vtp: structure defining the VM to terminate
> - *
> - * Return values:
> - * 0: the VM was terminated
> - * !0: the VM could not be located
> - */
> +void
> +vm_request_stop(struct vm *vm)
> +{
> + struct vcpu *vcpu;
> + u_int old;
> +#ifdef MULTIPROCESSOR
> + struct cpu_info *ci;
> +#endif
> +
> + SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) {
> + do {
> + old = atomic_load_int(&vcpu->vc_state);
> + if (old == VCPU_STATE_REQTERM ||
> + old == VCPU_STATE_TERMINATED)
> + break;
> + } while (atomic_cas_uint(&vcpu->vc_state, old,
> + VCPU_STATE_REQTERM) != old);
> +
> +#ifdef MULTIPROCESSOR
> + /*
> + * If this vCPU is currently running in guest mode, nudge the
> + * host CPU so it exits promptly and observes REQTERM.
> + */
> + if (old != VCPU_STATE_TERMINATED) {
> + ci = READ_ONCE(vcpu->vc_curcpu);
> + if (ci != NULL)
> + x86_send_ipi(ci, X86_IPI_NOP);
> + }
> +#endif
> + }
> +}
> +
> int
> vm_terminate(struct vm_terminate_params *vtp)
> {
> struct vm *vm;
> - int error, nvcpu, vm_id;
> + int error;
>
> +#ifdef MULTIPROCESSOR
> + int relock = _kernel_lock_held();
> + if (relock)
> + KERNEL_UNLOCK();
> +#endif
> +
> + error = vm_find_pid(vtp->vtp_creator_pid, &vm);
> + if (error != 0)
> + goto out;
> +
> + /* Only proceed through remove once. */
> + if (atomic_cas_uint(&vm->vm_dying, VMM_VM_ALIVE, VMM_VM_DYING) !=
> + VMM_VM_ALIVE) {
> + /*
> + * Already terminating; kick again in case the caller is retrying
> + * while a VCPU is still running.
> + */
> + vm_request_stop(vm);
> + refcnt_rele_wake(&vm->vm_refcnt);
> + error = EBUSY;
> + goto out;
> + }
> +
> /*
> - * Find desired VM
> + * Request VCPU exit. Teardown is deferred to vm_close() so TERM only
> + * initiates termination and does not wait for VM file references.
> */
> - error = vm_find(vtp->vtp_vm_id, &vm);
> - if (error)
> - return (error);
> + vm_request_stop(vm);
> + refcnt_rele_wake(&vm->vm_refcnt);
>
> - /* Only proceed through remove and teardown once. */
> - if (atomic_cas_uint(&vm->vm_dying, 0, 1) == 1) {
> - refcnt_rele_wake(&vm->vm_refcnt);
> - return (EBUSY);
> - }
> -
> - /* Pop the vm out of the global vm list. */
> - rw_enter_write(&vmm_softc->vm_lock);
> - SLIST_REMOVE(&vmm_softc->vm_list, vm, vm, vm_link);
> - rw_exit_write(&vmm_softc->vm_lock);
> -
> - /* Drop the vm_list's reference to the vm. */
> - if (refcnt_rele(&vm->vm_refcnt))
> - panic("%s: vm %d(%p) vm_list refcnt drop was the last",
> - __func__, vm->vm_id, vm);
> -
> - /* Wait for our reference (taken from vm_find) is the last active. */
> - refcnt_finalize(&vm->vm_refcnt, __func__);
> -
> - vm_id = vm->vm_id;
> - nvcpu = vm->vm_vcpu_ct;
> -
> - vm_teardown(&vm);
> -
> - if (vm_id > 0) {
> - rw_enter_write(&vmm_softc->vm_lock);
> - vmm_softc->vm_ct--;
> - vmm_softc->vcpu_ct -= nvcpu;
> - if (vmm_softc->vm_ct < 1)
> - vmm_stop();
> - rw_exit_write(&vmm_softc->vm_lock);
> - }
> -
> - return (0);
> + error = 0;
> +out:
> +#ifdef MULTIPROCESSOR
> + if (relock)
> + KERNEL_LOCK();
> +#endif
> + return (error);
> }
>
> /*
> @@ -774,27 +823,16 @@ vm_terminate(struct vm_terminate_params *vtp)
> * EIO if the indicated VCPU failed to reset
> */
> int
> -vm_resetcpu(struct vm_resetcpu_params *vrp)
> +vm_resetcpu(struct vm *vm, struct vm_resetcpu_params *vrp)
> {
> - struct vm *vm;
> struct vcpu *vcpu;
> - int error, ret = 0;
> + int ret = 0;
>
> - /* Find the desired VM */
> - error = vm_find(vrp->vrp_vm_id, &vm);
> -
> - /* Not found? exit. */
> - if (error != 0) {
> - DPRINTF("%s: vm id %u not found\n", __func__,
> - vrp->vrp_vm_id);
> - return (error);
> - }
> -
> vcpu = vm_find_vcpu(vm, vrp->vrp_vcpu_id);
>
> if (vcpu == NULL) {
> - DPRINTF("%s: vcpu id %u of vm %u not found\n", __func__,
> - vrp->vrp_vcpu_id, vrp->vrp_vm_id);
> + DPRINTF("%s: vcpu id %u not found\n", __func__,
> + vrp->vrp_vcpu_id);
> ret = ENOENT;
> goto out;
> }
> @@ -813,8 +851,6 @@ vm_resetcpu(struct vm_resetcpu_params *vrp)
> }
> rw_exit_write(&vcpu->vc_lock);
> out:
> - refcnt_rele_wake(&vm->vm_refcnt);
> -
> return (ret);
> }
>
> @@ -838,7 +874,7 @@ vcpu_must_stop(struct vcpu *vcpu)
> {
> struct proc *p = curproc;
>
> - if (vcpu->vc_state == VCPU_STATE_REQTERM)
> + if (atomic_load_int(&vcpu->vc_state) == VCPU_STATE_REQTERM)
> return (1);
> if (SIGPENDING(p) != 0)
> return (1);
> @@ -856,58 +892,26 @@ vcpu_must_stop(struct vcpu *vcpu)
> * other errno on uvm_map or uvm_map_immutable failures
> */
> int
> -vm_share_mem(struct vm_sharemem_params *vsp, struct proc *p)
> +vm_share_mem(struct vm *vm, struct vm_sharemem_params *vsp, struct proc *p)
> {
> int ret = EINVAL, unmap = 0;
> - size_t i, failed_uao = 0, n;
> - struct vm *vm;
> - struct vm_mem_range *src, *dst;
> + size_t i, failed_uao = 0;
> + struct vm_mem_range *vmr;
> struct uvm_object *uao;
> unsigned int uvmflags;
>
> - ret = vm_find(vsp->vsp_vm_id, &vm);
> - if (ret)
> - return (ret);
> -
> - /* Check we have the expected number of ranges. */
> - if (vm->vm_nmemranges != vsp->vsp_nmemranges)
> - goto out;
> - n = vm->vm_nmemranges;
> -
> - /* Check their types, sizes, and gpa's (implying page alignment). */
> - for (i = 0; i < n; i++) {
> - src = &vm->vm_memranges[i];
> - dst = &vsp->vsp_memranges[i];
> -
> - /*
> - * The vm memranges were already checked during creation, so
> - * compare to them to confirm validity of mapping request.
> - */
> - if (src->vmr_type != dst->vmr_type)
> - goto out;
> - if (src->vmr_gpa != dst->vmr_gpa)
> - goto out;
> - if (src->vmr_size != dst->vmr_size)
> - goto out;
> -
> - /* The virtual addresses will be chosen by uvm_map(). */
> - if (vsp->vsp_va[i] != 0)
> - goto out;
> - }
> -
> /* Share each UVM aobj with the calling process. */
> uvmflags = UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
> MAP_INHERIT_NONE, MADV_NORMAL, UVM_FLAG_CONCEAL);
> - for (i = 0; i < n; i++) {
> - dst = &vsp->vsp_memranges[i];
> - if (dst->vmr_type == VM_MEM_MMIO)
> + for (i = 0; i < vm->vm_nmemranges; i++) {
> + vmr = &vm->vm_memranges[i];
> + if (vmr->vmr_type == VM_MEM_MMIO)
> continue;
>
> uao = vm->vm_memory_slot[i];
> KASSERT(uao != NULL);
> -
> ret = uvm_map(&p->p_p->ps_vmspace->vm_map, &vsp->vsp_va[i],
> - dst->vmr_size, uao, 0, 0, uvmflags);
> + vmr->vmr_size, uao, 0, 0, uvmflags);
> if (ret) {
> printf("%s: uvm_map failed: %d\n", __func__, ret);
> unmap = (i > 0) ? 1 : 0;
> @@ -917,7 +921,7 @@ vm_share_mem(struct vm_sharemem_params *vsp, struct pr
> uao_reference(uao); /* Add a reference for the process. */
>
> ret = uvm_map_immutable(&p->p_p->ps_vmspace->vm_map,
> - vsp->vsp_va[i], vsp->vsp_va[i] + dst->vmr_size, 1);
> + vsp->vsp_va[i], vsp->vsp_va[i] + vmr->vmr_size, 1);
> if (ret) {
> printf("%s: uvm_map_immutable failed: %d\n",
> __func__, ret);
> @@ -931,11 +935,228 @@ out:
> if (unmap) {
> /* Unmap mapped aobjs, which drops the process's reference. */
> for (i = 0; i < failed_uao; i++) {
> - dst = &vsp->vsp_memranges[i];
> + vmr = &vm->vm_memranges[i];
> uvm_unmap(&p->p_p->ps_vmspace->vm_map,
> - vsp->vsp_va[i], vsp->vsp_va[i] + dst->vmr_size);
> + vsp->vsp_va[i], vsp->vsp_va[i] + vmr->vmr_size);
> }
> }
> + return (ret);
> +}
> +
> +int
> +vm_create_file(struct vm_create_params *vcp, struct proc *p, struct vm *vm)
> +{
> + int fd = -1, ret = 0;
> + struct file *fp = NULL;
> + struct filedesc *fdp = p->p_fd;
> +
> + fdplock(fdp);
> +
> + ret = falloc(p, &fp, &fd);
> + if (ret)
> + goto err;
> +
> + fp->f_flag = FREAD | FWRITE;
> + fp->f_type = DTYPE_VMM;
> + fp->f_data = vm;
> + fp->f_ops = &vmops;
> +
> + fdinsert(fdp, fd, 0, fp);
> + vcp->vcp_fd = fd;
> +
> + /* Take a reference for the file descriptor. */
> + refcnt_take(&vm->vm_refcnt);
> + FRELE(fp, p);
> +err:
> + fdpunlock(fdp);
> +
> + return (ret);
> +}
> +
> +int
> +vm_read(struct file *fp, struct uio *uio, int fflags)
> +{
> + return (ENXIO);
> +}
> +
> +int
> +vm_write(struct file *fp, struct uio *uio, int fflags)
> +{
> + return (ENXIO);
> +}
> +
> +int
> +vm_kqfilter(struct file *fp, struct knote *kn)
> +{
> + return (EINVAL);
> +}
> +
> +/*
> + * vm_ioctl
> + *
> + * Dispatcher for all virtual machine operations for the vm referenced
> + * by the file fp.
> + */
> +int
> +vm_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
> +{
> + struct vm *vm = (struct vm *)fp->f_data;
> + int ret = 0;
> +
> + if (vm == NULL)
> + return (ENXIO);
> +
> + KERNEL_ASSERT_UNLOCKED();
> +
> + refcnt_take(&vm->vm_refcnt);
> + ret = vmm_dev_enter();
> + if (ret != 0)
> + goto out;
> +
> + if (atomic_load_int(&vm->vm_dying) != VMM_VM_ALIVE) {
> + if (cmd == VMM_IOC_RUN) {
> + ((struct vm_run_params *)data)->vrp_exit_reason =
> + VM_EXIT_TERMINATED;
> + ret = 0;
> + } else {
> + ret = EBUSY;
> + }
> + goto out_active;
> + }
> +
> + switch (cmd) {
> + case VMM_IOC_RUN:
> + ret = vm_run(vm, (struct vm_run_params *)data);
> + break;
> + case VMM_IOC_RESETCPU:
> + ret = vm_resetcpu(vm, (struct vm_resetcpu_params *)data);
> + break;
> + case VMM_IOC_READREGS:
> + ret = vm_rwregs(vm, (struct vm_rwregs_params *)data, 0);
> + break;
> + case VMM_IOC_WRITEREGS:
> + ret = vm_rwregs(vm, (struct vm_rwregs_params *)data, 1);
> + break;
> + case VMM_IOC_READVMPARAMS:
> + ret = vm_rwvmparams(vm, (struct vm_rwvmparams_params *)data, 0);
> + break;
> + case VMM_IOC_WRITEVMPARAMS:
> + ret = vm_rwvmparams(vm, (struct vm_rwvmparams_params *)data, 1);
> + break;
> + case VMM_IOC_SHAREMEM:
> + ret = vm_share_mem(vm, (struct vm_sharemem_params *)data, p);
> + break;
> + case VMM_IOC_INTR:
> + ret = vm_intr_pending(vm, (struct vm_intr_params *)data);
> + break;
> + default:
> + ret = ENOTTY;
> + break;
> + }
> +
> +out_active:
> + vmm_dev_exit();
> +out:
> refcnt_rele_wake(&vm->vm_refcnt);
> return (ret);
> }
> +
> +int
> +vm_close(struct file *fp, struct proc *p)
> +{
> + int nvcpu, vm_id;
> + int teardown_owner = 0;
> + int remove_from_list = 0;
> + int account = 0;
> + struct vm *vm = (struct vm *)fp->f_data;
> +
> + if (vm == NULL)
> + return (0);
> +
> + /*
> + * vm_close is called from multiple contexts within the kernel,
> + * inside and outside of vmm(4). Some callers hold the kernel lock.
> + * Since vmm(4) operates without the kernel lock, we need to
> + * unlock and relock before return.
> + */
> +#ifdef MULTIPROCESSOR
> + int relock = _kernel_lock_held();
> + if (relock)
> + KERNEL_UNLOCK();
> +#endif
> +
> + fp->f_ops = NULL;
> + fp->f_data = NULL;
> +
> + /* No active teardown owner; this close owns teardown now. */
> + if (atomic_cas_uint(&vm->vm_dying, VMM_VM_ALIVE, VMM_VM_TEARDOWN) ==
> + VMM_VM_ALIVE) {
> + teardown_owner = 1;
> + remove_from_list = 1;
> + account = 1;
> + vm_request_stop(vm);
> + } else if (atomic_cas_uint(&vm->vm_dying, VMM_VM_DYING,
> + VMM_VM_TEARDOWN) == VMM_VM_DYING) {
> + teardown_owner = 1;
> + remove_from_list = 1;
> + account = 1;
> + vm_request_stop(vm);
> + }
> + if (!teardown_owner) {
> + refcnt_rele_wake(&vm->vm_refcnt);
> +#ifdef MULTIPROCESSOR
> + if (relock)
> + KERNEL_LOCK();
> +#endif
> + return (0);
> + }
> +
> + if (remove_from_list) {
> + /* Remove the vm from the global vm list. */
> + rw_enter_write(&vmm_softc->vm_lock);
> + SLIST_REMOVE(&vmm_softc->vm_list, vm, vm, vm_link);
> + rw_exit_write(&vmm_softc->vm_lock);
> +
> + /* Drop the vm_list's reference. */
> + if (refcnt_rele(&vm->vm_refcnt))
> + panic("%s: vm refcnt is 0 (%p)", __func__, vm);
> + }
> +
> + /* Wait for all VM references, including this close's, to drain. */
> + refcnt_finalize(&vm->vm_refcnt, __func__);
> +
> + vm_id = vm->vm_id;
> + nvcpu = vm->vm_vcpu_ct;
> + vm_teardown(&vm);
> +
> + if (account && vm_id > 0) {
> + rw_enter_write(&vmm_softc->vm_lock);
> + vmm_softc->vm_ct--;
> + vmm_softc->vcpu_ct -= nvcpu;
> + if (vmm_softc->vm_ct < 1)
> + vmm_stop();
> + rw_exit_write(&vmm_softc->vm_lock);
> + }
> +
> +#ifdef MULTIPROCESSOR
> + if (relock)
> + KERNEL_LOCK();
> +#endif
> + return (0);
> +}
> +
> +int
> +vm_stat(struct file *fp, struct stat *st, struct proc *p)
> +{
> + struct vm *vm = (struct vm *)fp->f_data;
> +
> + if (vm == NULL)
> + return (0);
> +
> + memset(st, 0, sizeof(*st));
> + st->st_mode = S_IFCHR;
> + st->st_blksize = PAGE_SIZE;
> + st->st_blocks = pmap_resident_count(vm->vm_pmap);
> +
> + return (0);
> +}
> blob - f50c974f67d68da56fc7fc3469eb27348b2c249e
> blob + 6b5195b0fbb3ea71a7d7953c68c943c04a5475de
> --- sys/dev/vmm/vmm.h
> +++ sys/dev/vmm/vmm.h
> @@ -54,11 +54,10 @@ struct vm_create_params {
> char vcp_name[VMM_MAX_NAME_LEN];
> int vcp_sev;
> int vcp_seves;
> -
> - /* Output parameter from VMM_IOC_CREATE */
> - uint32_t vcp_id;
> - uint32_t vcp_poscbit;
> - uint32_t vcp_asid[VMM_MAX_VCPUS];
> + /* Output parameters from VMM_IOC_CREATE */
> + uint32_t vcp_poscbit;
> + uint32_t vcp_asid[VMM_MAX_VCPUS];
> + int vcp_fd;
> };
>
> struct vm_info_result {
> @@ -68,7 +67,6 @@ struct vm_info_result {
> size_t vir_ncpus;
> uint8_t vir_vcpu_state[VMM_MAX_VCPUS_PER_VM];
> pid_t vir_creator_pid;
> - uint32_t vir_id;
> char vir_name[VMM_MAX_NAME_LEN];
> };
>
> @@ -83,29 +81,22 @@ struct vm_info_params {
>
> struct vm_terminate_params {
> /* Input parameters to VMM_IOC_TERM */
> - uint32_t vtp_vm_id;
> + pid_t vtp_creator_pid;
> };
>
> struct vm_resetcpu_params {
> /* Input parameters to VMM_IOC_RESETCPU */
> - uint32_t vrp_vm_id;
> uint32_t vrp_vcpu_id;
> struct vcpu_reg_state vrp_init_state;
> };
>
> struct vm_sharemem_params {
> - /* Input parameters to VMM_IOC_SHAREMEM */
> - uint32_t vsp_vm_id;
> - size_t vsp_nmemranges;
> - struct vm_mem_range vsp_memranges[VMM_MAX_MEM_RANGES];
> -
> /* Output parameters from VMM_IOC_SHAREMEM */
> vaddr_t vsp_va[VMM_MAX_MEM_RANGES];
> };
>
> struct vm_run_params {
> /* Input parameters to VMM_IOC_RUN */
> - uint32_t vrp_vm_id;
> uint32_t vrp_vcpu_id;
> struct vcpu_inject_event vrp_inject;
> uint8_t vrp_intr_pending; /* Additional intrs pending? */
> @@ -125,7 +116,6 @@ struct vm_run_params {
>
> struct vm_rwvmparams_params {
> /* Input parameters to VMM_IOC_READVMPARAMS/VMM_IOC_WRITEVMPARAMS */
> - uint32_t vpp_vm_id;
> uint32_t vpp_vcpu_id;
> uint32_t vpp_mask;
> paddr_t vpp_pvclock_system_gpa;
> @@ -163,6 +153,10 @@ enum {
> VCPU_STATE_UNKNOWN,
> };
>
> +#define VMM_VM_ALIVE 0U
> +#define VMM_VM_DYING 1U
> +#define VMM_VM_TEARDOWN 2U
> +
> /*
> * Virtual Machine
> *
> @@ -187,7 +181,7 @@ struct vm {
>
> char vm_name[VMM_MAX_NAME_LEN];
> struct refcnt vm_refcnt; /* [a] */
> - unsigned int vm_dying; /* [a] */
> + unsigned int vm_dying; /* [a] VMM_VM_* */
>
> struct vcpu_head vm_vcpu_list; /* [v] */
> uint32_t vm_vcpu_ct; /* [v] */
> @@ -244,25 +238,11 @@ extern struct pool vcpu_pool;
> extern struct cfdriver vmm_cd;
> extern const struct cfattach vmm_ca;
>
> -int vmm_probe(struct device *, void *, void *);
> -int vmm_activate(struct device *, int);
> -void vmm_attach(struct device *, struct device *, void *);
> -int vmmopen(dev_t, int, int, struct proc *);
> -int vmmclose(dev_t, int, int, struct proc *);
> -int vm_find(uint32_t, struct vm **);
> -int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *);
> -int pledge_ioctl_vmm(struct proc *, long);
> +int vm_find_file(int, struct proc *, struct vm **);
> struct vcpu *vm_find_vcpu(struct vm *, uint32_t);
> -int vm_create(struct vm_create_params *, struct proc *);
> -size_t vm_create_check_mem_ranges(struct vm_create_params *);
> -void vm_teardown(struct vm **);
> -int vm_get_info(struct vm_info_params *);
> -int vm_terminate(struct vm_terminate_params *);
> -int vm_resetcpu(struct vm_resetcpu_params *);
> -int vm_rwvmparams(struct vm_rwvmparams_params *, int);
> +int vm_rwvmparams(struct vm *, struct vm_rwvmparams_params *, int);
> int vcpu_must_stop(struct vcpu *);
> -int vm_share_mem(struct vm_sharemem_params *, struct proc *);
> -int vm_run(struct vm_run_params *);
> +int vm_run(struct vm *, struct vm_run_params *);
>
> #ifdef VMM_DEBUG
> void dump_vcpu(struct vcpu *);
> blob - a891eecd1182383629cb4923bee2e879a840c447
> blob + e5c5dbf15ab0262e080ad902b5713cb02dceb9e1
> --- sys/kern/kern_pledge.c
> +++ sys/kern/kern_pledge.c
> @@ -75,6 +75,7 @@
> #include "vmm.h"
> #include "psp.h"
> #include <machine/conf.h>
> +#include <dev/vmm/vmm.h>
> #endif
>
> #include "drm.h"
> @@ -1348,12 +1349,30 @@ pledge_ioctl(struct proc *p, long com, struct file *fp
>
> #if NVMM > 0
> if ((pledge & PLEDGE_VMM)) {
> + if (fp->f_type == DTYPE_VMM) {
> + switch (com) {
> + case VMM_IOC_RUN:
> + case VMM_IOC_RESETCPU:
> + case VMM_IOC_READREGS:
> + case VMM_IOC_WRITEREGS:
> + case VMM_IOC_READVMPARAMS:
> + case VMM_IOC_WRITEVMPARAMS:
> + case VMM_IOC_SHAREMEM:
> + case VMM_IOC_INTR:
> + return (0);
> + default:
> + break;
> + }
> + }
> if (fp->f_type == DTYPE_VNODE &&
> vp->v_type == VCHR &&
> cdevsw[major(vp->v_rdev)].d_open == vmmopen) {
> - error = pledge_ioctl_vmm(p, com);
> - if (error == 0)
> - return 0;
> + switch (com) {
> + case VMM_IOC_CREATE:
> + case VMM_IOC_INFO:
> + case VMM_IOC_TERM:
> + return (0);
> + }
> }
> }
> #endif
> blob - 25c8267ae5d1761a3c872157d68507d1d4be1e9c
> blob + dfec6d00cb98178ba3ca5155c121f57f9bfa17a6
> --- sys/kern/uipc_usrreq.c
> +++ sys/kern/uipc_usrreq.c
> @@ -1293,8 +1293,8 @@ morespace:
> if (error)
> goto fail;
>
> - /* kqueue descriptors cannot be copied */
> - if (fp->f_type == DTYPE_KQUEUE) {
> + /* kqueue and vmm descriptors cannot be copied */
> + if (fp->f_type == DTYPE_KQUEUE || fp->f_type == DTYPE_VMM) {
> error = EINVAL;
> goto fail;
> }
> blob - b29b43122a4755a18c9b0b0cd3733566f09dda5b
> blob + 7aa3c1cedbc827cce93b3abdd611d82ee89ce81f
> --- sys/sys/file.h
> +++ sys/sys/file.h
> @@ -46,6 +46,7 @@
> #define DTYPE_KQUEUE 4 /* event queue */
> #define DTYPE_DMABUF 5 /* DMA buffer (for DRM) */
> #define DTYPE_SYNC 6 /* sync file (for DRM) */
> +#define DTYPE_VMM 7 /* vmm(4) virtual machine */
>
> #ifdef _KERNEL
> struct proc;
> blob - 3379671505b1ffe9f7ef66c32fc8e57113730a0d
> blob + dcf07d38bde5c7062a4ad614e7ce9777cf3819d1
> --- sys/sys/pledge.h
> +++ sys/sys/pledge.h
> @@ -128,7 +128,7 @@ int pledge_sockopt(struct proc *p, int set, int level,
> int pledge_socket(struct proc *p, int domain, unsigned int state);
> int pledge_ioctl(struct proc *p, long com, struct file *);
> int pledge_ioctl_drm(struct proc *p, long com, dev_t device);
> -int pledge_ioctl_vmm(struct proc *p, long com);
> +int pledge_ioctl_vmm_dev(struct proc *p, long com);
> int pledge_ioctl_psp(struct proc *p, long com);
> int pledge_flock(struct proc *p);
> int pledge_fcntl(struct proc *p, int cmd);
> blob - bbafef0e084b639c6c7c47d67188b1d52988191b
> blob + 6c8446643d730bf88e3271f586732e7d90e8131b
> --- usr.bin/fstat/fstat.c
> +++ usr.bin/fstat/fstat.c
> @@ -127,6 +127,7 @@ void print_inet6_details(struct kinfo_file *);
> void print_sock_details(struct kinfo_file *);
> void socktrans(struct kinfo_file *);
> void vtrans(struct kinfo_file *);
> +void vmmtrans(struct kinfo_file *);
> const char *inet6_addrstr(struct in6_addr *);
> int signame_to_signum(char *);
> void hide(void *p);
> @@ -414,6 +415,10 @@ fstat_dofile(struct kinfo_file *kf)
> if (checkfile == 0)
> kqueuetrans(kf);
> break;
> + case DTYPE_VMM:
> + if (checkfile == 0)
> + vmmtrans(kf);
> + break;
> default:
> if (vflg) {
> warnx("unknown file type %d for file %d of pid %ld",
> @@ -525,6 +530,18 @@ vtrans(struct kinfo_file *kf)
> }
>
> void
> +vmmtrans(struct kinfo_file *kf)
> +{
> + PREFIX(kf->fd_fd);
> +
> + printf(" ");
> +
> + printf("vmm ");
> + hide((void *)(uintptr_t)kf->f_data);
> + putchar('\n');
> +}
> +
> +void
> pipetrans(struct kinfo_file *kf)
> {
> void *maxaddr;
> blob - b05fb152b254d31155d1d75cf3603dbe69be4306
> blob + 26b77db4c52b83ab25bb4f750efd30b087ceb1e0
> --- usr.sbin/vmd/arm64_vm.c
> +++ usr.sbin/vmd/arm64_vm.c
> @@ -104,13 +104,13 @@ intr_ack(struct vmd_vm *vm)
> }
>
> void
> -vcpu_assert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq)
> +vcpu_assert_irq(int fd, uint32_t vcpu_id, int irq)
> {
> fatalx("%s: unimplemented", __func__);
> }
>
> void
> -vcpu_deassert_irq(uint32_t vm_id, uint32_t vcpu_id, int irq)
> +vcpu_deassert_irq(int fd, uint32_t vcpu_id, int irq)
> {
> fatalx("%s: unimplemented", __func__);
> }
> blob - 09907635f0690399c4aa7ab2d804baf372df97b3
> blob + 25fd0cbcf5f345041e659da67afa09e7857b7aee
> --- usr.sbin/vmd/dhcp.c
> +++ usr.sbin/vmd/dhcp.c
> @@ -139,7 +139,7 @@ dhcp_request(struct virtio_dev *dev, char *buf, size_t
>
> if (vionet->pxeboot) {
> strlcpy(resp.file, "auto_install", sizeof resp.file);
> - vm = vm_getbyid(dev->vmm_id);
> + vm = vm_getbyvmid(dev->vm_id);
> if (vm && res_hnok(vm->vm_params.vmc_name))
> hostname = vm->vm_params.vmc_name;
> }
> blob - 00b0945da33e131f897f18a0fb692cc660f97114
> blob + 469dc82f6eb439b97f7cce5baa38015199572673
> --- usr.sbin/vmd/i8253.c
> +++ usr.sbin/vmd/i8253.c
> @@ -73,29 +73,29 @@ i8253_pipe_dispatch(int fd, short event, void *arg)
> * Initialize the emulated i8253 PIT.
> *
> * Parameters:
> - * vm_id: vmm(4)-assigned ID of the VM
> + * vm_fd: file descriptor of the VM
> */
> void
> -i8253_init(uint32_t vm_id)
> +i8253_init(int vm_fd)
> {
> memset(&i8253_channel, 0, sizeof(struct i8253_channel));
> clock_gettime(CLOCK_MONOTONIC, &i8253_channel[0].ts);
> i8253_channel[0].start = 0xFFFF;
> i8253_channel[0].mode = TIMER_INTTC;
> i8253_channel[0].last_r = 1;
> - i8253_channel[0].vm_id = vm_id;
> + i8253_channel[0].vm_fd = vm_fd;
> i8253_channel[0].state = 0;
>
> i8253_channel[1].start = 0xFFFF;
> i8253_channel[1].mode = TIMER_INTTC;
> i8253_channel[1].last_r = 1;
> - i8253_channel[1].vm_id = vm_id;
> + i8253_channel[1].vm_fd = vm_fd;
> i8253_channel[1].state = 0;
>
> i8253_channel[2].start = 0xFFFF;
> i8253_channel[2].mode = TIMER_INTTC;
> i8253_channel[2].last_r = 1;
> - i8253_channel[2].vm_id = vm_id;
> + i8253_channel[2].vm_fd = vm_fd;
> i8253_channel[2].state = 0;
>
> evtimer_set(&i8253_channel[0].timer, i8253_fire, &i8253_channel[0]);
> @@ -370,7 +370,7 @@ i8253_fire(int fd, short type, void *arg)
> struct timeval tv;
> struct i8253_channel *ctr = (struct i8253_channel *)arg;
>
> - vcpu_assert_irq(ctr->vm_id, 0, 0);
> + vcpu_assert_irq(ctr->vm_fd, 0, 0);
>
> if (ctr->mode != TIMER_INTTC) {
> timerclear(&tv);
> blob - c938c42d4cb9030011b009928ba8e2df5483da37
> blob + cd173ac300a3532eab1ee5c45cd9aa4fde3d6b29
> --- usr.sbin/vmd/i8253.h
> +++ usr.sbin/vmd/i8253.h
> @@ -39,12 +39,12 @@ struct i8253_channel {
> uint8_t mode; /* counter mode */
> uint8_t rbs; /* channel is in readback status mode */
> struct event timer; /* timer event for this counter */
> - uint32_t vm_id; /* owning VM id */
> + int vm_fd; /* owning VM fd */
> int in_use; /* denotes if this counter was ever used */
> uint8_t state; /* 0 if channel is counting, 1 if fired */
> };
>
> -void i8253_init(uint32_t);
> +void i8253_init(int);
> void i8253_reset(uint8_t);
> void i8253_fire(int, short, void *);
> uint8_t vcpu_exit_i8253(struct vm_run_params *);
> blob - 0105cfae4292ce1fd50e82c93cdc45a569acc46c
> blob + 39b3c9d9d41c86acf2687801a5a0d7b5dc996b59
> --- usr.sbin/vmd/mc146818.c
> +++ usr.sbin/vmd/mc146818.c
> @@ -50,7 +50,7 @@ struct mc146818 {
> time_t now;
> uint8_t idx;
> uint8_t regs[NVRAM_SIZE];
> - uint32_t vm_id;
> + int vm_fd;
> struct event sec;
> struct timeval sec_tv;
> struct event per;
> @@ -158,12 +158,12 @@ rtc_fireper(int fd, short type, void *arg)
> * Initializes the emulated RTC/NVRAM
> *
> * Parameters:
> - * vm_id: VM ID to which this RTC belongs
> + * vm_fd: vm file descriptor to which this RTC belongs
> * memlo: size of memory in bytes between 16MB .. 4GB
> * memhi: size of memory in bytes after 4GB
> */
> void
> -mc146818_init(uint32_t vm_id, uint64_t memlo, uint64_t memhi)
> +mc146818_init(int vm_fd, uint64_t memlo, uint64_t memhi)
> {
> memset(&rtc, 0, sizeof(rtc));
> time(&rtc.now);
> @@ -182,7 +182,7 @@ mc146818_init(uint32_t vm_id, uint64_t memlo, uint64_t
> rtc.regs[NVRAM_SMP_COUNT] = 0;
>
> rtc_updateregs();
> - rtc.vm_id = vm_id;
> + rtc.vm_fd = vm_fd;
>
> timerclear(&rtc.sec_tv);
> rtc.sec_tv.tv_sec = 1;
> @@ -192,7 +192,7 @@ mc146818_init(uint32_t vm_id, uint64_t memlo, uint64_t
> evtimer_set(&rtc.sec, rtc_fire1, NULL);
> evtimer_add(&rtc.sec, &rtc.sec_tv);
>
> - evtimer_set(&rtc.per, rtc_fireper, (void *)(intptr_t)rtc.vm_id);
> + evtimer_set(&rtc.per, rtc_fireper, (void *)(intptr_t)rtc.vm_fd);
>
> vm_pipe_init(&dev_pipe, mc146818_pipe_dispatch);
> event_add(&dev_pipe.read_ev, NULL);
> blob - e7cef801303643a57cb905e1698a8dae3b7f5a9b
> blob + 64118764de1e79e6aa3dcdf9964819819a03217c
> --- usr.sbin/vmd/mc146818.h
> +++ usr.sbin/vmd/mc146818.h
> @@ -15,7 +15,7 @@
> * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> */
>
> -void mc146818_init(uint32_t, uint64_t, uint64_t);
> +void mc146818_init(int, uint64_t, uint64_t);
> uint8_t vcpu_exit_mc146818(struct vm_run_params *vrp);
> void mc146818_stop(void);
> void mc146818_start(void);
> blob - 97970e2155b0890e1914d923d8bcedc1e5dc93ab
> blob + 01164b93dffc9ab87897b9c5be6b1b6c57970127
> --- usr.sbin/vmd/ns8250.c
> +++ usr.sbin/vmd/ns8250.c
> @@ -36,7 +36,7 @@ struct ns8250_dev com1_dev;
> static struct vm_dev_pipe dev_pipe;
>
> static void com_rcv_event(int, short, void *);
> -static void com_rcv(struct ns8250_dev *, uint32_t, uint32_t);
> +static void com_rcv(struct ns8250_dev *, uint32_t);
>
> /*
> * ns8250_pipe_dispatch
> @@ -78,12 +78,12 @@ ratelimit(int fd, short type, void *arg)
> com1_dev.regs.iir |= IIR_TXRDY;
> com1_dev.regs.iir &= ~IIR_NOPEND;
>
> - vcpu_assert_irq(com1_dev.vmid, 0, com1_dev.irq);
> + vcpu_assert_irq(com1_dev.vm_fd, 0, com1_dev.irq);
> mutex_unlock(&com1_dev.mutex);
> }
>
> void
> -ns8250_init(int fd, uint32_t vmid)
> +ns8250_init(int fd, int vm_fd)
> {
> int ret;
>
> @@ -95,9 +95,9 @@ ns8250_init(int fd, uint32_t vmid)
> }
>
> com1_dev.fd = fd;
> + com1_dev.vm_fd = vm_fd;
> com1_dev.irq = 4;
> com1_dev.portid = NS8250_COM1;
> - com1_dev.vmid = vmid;
> com1_dev.byte_out = 0;
> com1_dev.regs.divlo = 1;
> com1_dev.baudrate = 115200;
> @@ -118,7 +118,7 @@ ns8250_init(int fd, uint32_t vmid)
> com1_dev.pause_ct = (com1_dev.baudrate / 8) / 1000 * 10;
>
> event_set(&com1_dev.event, com1_dev.fd, EV_READ | EV_PERSIST,
> - com_rcv_event, (void *)(intptr_t)vmid);
> + com_rcv_event, (void *)(intptr_t)vm_fd);
>
> /*
> * Whenever fd is writable implies that the pty slave is connected.
> @@ -126,7 +126,7 @@ ns8250_init(int fd, uint32_t vmid)
> * be reached.
> */
> event_set(&com1_dev.wake, com1_dev.fd, EV_WRITE,
> - com_rcv_event, (void *)(intptr_t)vmid);
> + com_rcv_event, (void *)(intptr_t)vm_fd);
> event_add(&com1_dev.wake, NULL);
>
> /* Rate limiter for simulating baud rate */
> @@ -150,12 +150,12 @@ com_rcv_event(int fd, short kind, void *arg)
> }
>
> if ((com1_dev.regs.lsr & LSR_RXRDY) == 0)
> - com_rcv(&com1_dev, (uintptr_t)arg, 0);
> + com_rcv(&com1_dev, 0);
>
> /* If pending interrupt, inject */
> if ((com1_dev.regs.iir & IIR_NOPEND) == 0) {
> /* XXX: vcpu_id */
> - vcpu_assert_irq((uintptr_t)arg, 0, com1_dev.irq);
> + vcpu_assert_irq(com1_dev.vm_fd, 0, com1_dev.irq);
> }
>
> mutex_unlock(&com1_dev.mutex);
> @@ -192,7 +192,7 @@ com_rcv_handle_break(struct ns8250_dev *com, uint8_t c
> * Must be called with the mutex of the com device acquired
> */
> static void
> -com_rcv(struct ns8250_dev *com, uint32_t vm_id, uint32_t vcpu_id)
> +com_rcv(struct ns8250_dev *com, uint32_t vcpu_id)
> {
> char buf[2];
> ssize_t sz;
> @@ -245,7 +245,7 @@ com_rcv(struct ns8250_dev *com, uint32_t vm_id, uint32
> * interrupt to inject, or 0xFF if nothing to inject
> */
> uint8_t
> -vcpu_process_com_data(struct vm_exit *vei, uint32_t vm_id, uint32_t vcpu_id)
> +vcpu_process_com_data(struct vm_exit *vei, uint32_t vcpu_id)
> {
> /*
> * vei_dir == VEI_DIR_OUT : out instruction
> @@ -612,8 +612,7 @@ vcpu_exit_com(struct vm_run_params *vrp)
> vcpu_process_com_scr(vei);
> break;
> case COM1_DATA:
> - intr = vcpu_process_com_data(vei, vrp->vrp_vm_id,
> - vrp->vrp_vcpu_id);
> + intr = vcpu_process_com_data(vei, vrp->vrp_vcpu_id);
> break;
> }
>
> blob - 7ff4f524d92f1a89eee796b01e3049a1e026db7f
> blob + e4ec36d1da494536b71086930de0d4df6386e772
> --- usr.sbin/vmd/ns8250.h
> +++ usr.sbin/vmd/ns8250.h
> @@ -68,16 +68,16 @@ struct ns8250_dev {
> struct timeval rate_tv;
> enum ns8250_portid portid;
> int fd;
> + int vm_fd;
> int irq;
> - uint32_t vmid;
> uint64_t byte_out;
> uint32_t baudrate;
> uint32_t pause_ct;
> };
>
> -void ns8250_init(int, uint32_t);
> +void ns8250_init(int, int);
> uint8_t vcpu_exit_com(struct vm_run_params *);
> -uint8_t vcpu_process_com_data(struct vm_exit *, uint32_t, uint32_t);
> +uint8_t vcpu_process_com_data(struct vm_exit *, uint32_t);
> void vcpu_process_com_lcr(struct vm_exit *);
> void vcpu_process_com_lsr(struct vm_exit *);
> void vcpu_process_com_ier(struct vm_exit *);
> blob - b60f51711dbb30d2ab9d5f917607c77d3dee28eb
> blob + e24c794037233838424b137df11ae5d212157262
> --- usr.sbin/vmd/psp.c
> +++ usr.sbin/vmd/psp.c
> @@ -174,15 +174,14 @@ psp_launch_update(uint32_t handle, vaddr_t v, size_t l
> * log it for now.
> */
> int
> -psp_encrypt_state(uint32_t handle, uint32_t asid, uint32_t vmid,
> - uint32_t vcpuid)
> +psp_encrypt_state(uint32_t handle, uint32_t asid, int vmfd, uint32_t vcpuid)
> {
> struct psp_encrypt_state es;
>
> memset(&es, 0, sizeof(es));
> es.handle = handle;
> es.asid = asid;
> - es.vmid = vmid;
> + es.vmfd = vmfd;
> es.vcpuid = vcpuid;
>
> if (ioctl(env->vmd_psp_fd, PSP_IOC_ENCRYPT_STATE, &es) < 0) {
> blob - 0fc14a3ce218bfbf85417191c40c6456e204ce89
> blob + 57b428a8a12a478e166033d4435345ade089eb21
> --- usr.sbin/vmd/sev.c
> +++ usr.sbin/vmd/sev.c
> @@ -208,7 +208,7 @@ sev_encrypt_state(struct vmd_vm *vm, int vcpu_id)
> return (0);
>
> if (psp_encrypt_state(vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id],
> - vm->vm_vmmid, vcpu_id)) {
> + vm->vm_fd, vcpu_id)) {
> log_warnx("%s: failed to encrypt state: 0x%x 0x%x 0x%0x 0x%0x",
> __func__, vm->vm_sev_handle, vm->vm_sev_asid[vcpu_id],
> vm->vm_vmid, vcpu_id);
> blob - 6523170fc35095565d2b6627c2adea9667e52d48
> blob + adc14142bfd8daa0834a9d2343c0cdc37a5f8981
> --- usr.sbin/vmd/vioblk.c
> +++ usr.sbin/vmd/vioblk.c
> @@ -61,7 +61,7 @@ disk_type(enum vm_disk_fmt type)
> }
>
> __dead void
> -vioblk_main(int fd, int fd_vmm)
> +vioblk_main(int fd, int vm_fd)
> {
> struct virtio_dev dev;
> struct vioblk_dev *vioblk = NULL;
> @@ -99,9 +99,9 @@ vioblk_main(int fd, int fd_vmm)
> vioblk = &dev.vioblk;
>
> log_debug("%s: got viblk dev. num disk fds = %d, sync fd = %d, "
> - "async fd = %d, capacity = %lld seg_max = %u, vmm fd = %d",
> + "async fd = %d, capacity = %lld seg_max = %u, vm fd = %d",
> __func__, vioblk->ndisk_fd, dev.sync_fd, dev.async_fd,
> - vioblk->capacity, vioblk->seg_max, fd_vmm);
> + vioblk->capacity, vioblk->seg_max, vm_fd);
>
> /* Receive our vm information from the vm process. */
> memset(&vm, 0, sizeof(vm));
> @@ -117,7 +117,7 @@ vioblk_main(int fd, int fd_vmm)
> log_procinit("vm/%s/vioblk%d", vm.vm_params.vmc_name, vioblk->idx);
>
> /* Now that we have our vm information, we can remap memory. */
> - ret = remap_guest_mem(&vm, fd_vmm);
> + ret = remap_guest_mem(&vm, vm_fd);
> if (ret) {
> log_warnx("failed to remap guest memory");
> goto fail;
> @@ -126,7 +126,7 @@ vioblk_main(int fd, int fd_vmm)
> /*
> * We no longer need /dev/vmm access.
> */
> - close_fd(fd_vmm);
> + close_fd(vm_fd);
> if (pledge("stdio", NULL) == -1)
> fatal("pledge2");
>
> blob - 5ba13f4e9ce09879dc39ff5ca6ce149865810976
> blob + d1c7e3feb97767265c410410941f46a932850942
> --- usr.sbin/vmd/vionet.c
> +++ usr.sbin/vmd/vionet.c
> @@ -105,7 +105,7 @@ pthread_rwlock_t lock = NULL; /* Guards device config
> int rx_enabled = 0; /* 1: we expect to read the tap, 0: wait for notify. */
>
> __dead void
> -vionet_main(int fd, int fd_vmm)
> +vionet_main(int fd, int vm_fd)
> {
> struct virtio_dev dev;
> struct vionet_dev *vionet = NULL;
> @@ -141,8 +141,8 @@ vionet_main(int fd, int fd_vmm)
> vionet = &dev.vionet;
>
> log_debug("%s: got vionet dev. tap fd = %d, syncfd = %d, asyncfd = %d"
> - ", vmm fd = %d", __func__, vionet->data_fd, dev.sync_fd,
> - dev.async_fd, fd_vmm);
> + ", vm fd = %d", __func__, vionet->data_fd, dev.sync_fd,
> + dev.async_fd, vm_fd);
>
> /* Receive our vm information from the vm process. */
> memset(&vm, 0, sizeof(vm));
> @@ -157,7 +157,7 @@ vionet_main(int fd, int fd_vmm)
> log_procinit("vm/%s/vionet%d", vm.vm_params.vmc_name, vionet->idx);
>
> /* Now that we have our vm information, we can remap memory. */
> - ret = remap_guest_mem(&vm, fd_vmm);
> + ret = remap_guest_mem(&vm, vm_fd);
> if (ret) {
> fatal("%s: failed to remap", __func__);
> goto fail;
> @@ -166,7 +166,7 @@ vionet_main(int fd, int fd_vmm)
> /*
> * We no longer need /dev/vmm access.
> */
> - close_fd(fd_vmm);
> + close_fd(vm_fd);
> if (pledge("stdio", NULL) == -1)
> fatal("pledge2");
>
> blob - 355ce4069ff94b056a5f649dca64e4f49acf66ad
> blob + b012d39fcfe5ff475c962d58d38b312eb27ed640
> --- usr.sbin/vmd/vioscsi.c
> +++ usr.sbin/vmd/vioscsi.c
> @@ -57,7 +57,7 @@ static uint32_t vioscsi_read(struct virtio_dev *, stru
> static int vioscsi_write(struct virtio_dev *, struct viodev_msg *);
>
> __dead void
> -vioscsi_main(int fd, int fd_vmm)
> +vioscsi_main(int fd, int vm_fd)
> {
> struct virtio_dev dev;
> struct vioscsi_dev *vioscsi = NULL;
> @@ -90,8 +90,8 @@ vioscsi_main(int fd, int fd_vmm)
> vioscsi = &dev.vioscsi;
>
> log_debug("%s: got vioscsi dev. cdrom fd = %d, syncfd = %d, "
> - "asyncfd = %d, vmm fd = %d", __func__, vioscsi->cdrom_fd,
> - dev.sync_fd, dev.async_fd, fd_vmm);
> + "asyncfd = %d, vm fd = %d", __func__, vioscsi->cdrom_fd,
> + dev.sync_fd, dev.async_fd, vm_fd);
>
> /* Receive our vm information from the vm process. */
> memset(&vm, 0, sizeof(vm));
> @@ -107,16 +107,16 @@ vioscsi_main(int fd, int fd_vmm)
> log_procinit("vm/%s/vioscsi", vm.vm_params.vmc_name);
>
> /* Now that we have our vm information, we can remap memory. */
> - ret = remap_guest_mem(&vm, fd_vmm);
> + ret = remap_guest_mem(&vm, vm_fd);
> if (ret) {
> log_warnx("failed to remap guest memory");
> goto fail;
> }
>
> /*
> - * We no longer need /dev/vmm access.
> + * We no longer need VM fd access.
> */
> - close_fd(fd_vmm);
> + close_fd(vm_fd);
> if (pledge("stdio", NULL) == -1)
> fatal("pledge2");
>
> blob - 03a6e761dfc183f147434028b796ec1c03f3790d
> blob + e24a5b4478ce61ba85514c93c1e4570023bd7cef
> --- usr.sbin/vmd/virtio.c
> +++ usr.sbin/vmd/virtio.c
> @@ -33,6 +33,7 @@
>
> #include <errno.h>
> #include <event.h>
> +#include <fcntl.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> @@ -696,7 +697,7 @@ virtio_io_isr(int dir, uint16_t reg, uint32_t *data, u
> if (dir == VEI_DIR_IN) {
> *data = dev->isr;
> dev->isr = 0;
> - vcpu_deassert_irq(dev->vmm_id, 0, dev->irq);
> + vcpu_deassert_irq(dev->vm_fd, 0, dev->irq);
> }
>
> return (0);
> @@ -795,7 +796,7 @@ vmmci_ctl(struct virtio_dev *dev, unsigned int cmd)
>
> /* Trigger interrupt */
> dev->isr = VIRTIO_CONFIG_ISR_CONFIG_CHANGE;
> - vcpu_assert_irq(dev->vmm_id, 0, dev->irq);
> + vcpu_assert_irq(dev->vm_fd, 0, dev->irq);
>
> /* Add ACK timeout */
> tv.tv_sec = VMMCI_TIMEOUT_SHORT;
> @@ -807,7 +808,7 @@ vmmci_ctl(struct virtio_dev *dev, unsigned int cmd)
> v->cmd = cmd;
>
> dev->isr = VIRTIO_CONFIG_ISR_CONFIG_CHANGE;
> - vcpu_assert_irq(dev->vmm_id, 0, dev->irq);
> + vcpu_assert_irq(dev->vm_fd, 0, dev->irq);
> } else {
> log_debug("%s: RTC sync skipped (guest does not "
> "support RTC sync)", __func__);
> @@ -851,7 +852,7 @@ vmmci_ack(struct virtio_dev *dev, unsigned int cmd)
> */
> if (v->cmd == 0) {
> log_debug("%s: vm %u requested shutdown", __func__,
> - dev->vmm_id);
> + dev->vm_fd);
> vm_pipe_send(&v->dev_pipe, VMMCI_SET_TIMEOUT_SHORT);
> return;
> }
> @@ -866,13 +867,13 @@ vmmci_ack(struct virtio_dev *dev, unsigned int cmd)
> */
> if (cmd == v->cmd) {
> log_debug("%s: vm %u acknowledged shutdown request",
> - __func__, dev->vmm_id);
> + __func__, dev->vm_fd);
> vm_pipe_send(&v->dev_pipe, VMMCI_SET_TIMEOUT_LONG);
> }
> break;
> case VMMCI_SYNCRTC:
> log_debug("%s: vm %u acknowledged RTC sync request",
> - __func__, dev->vmm_id);
> + __func__, dev->vm_fd);
> v->cmd = VMMCI_NONE;
> break;
> default:
> @@ -891,7 +892,7 @@ vmmci_timeout(int fd, short type, void *arg)
> fatalx("%s: device is not a vmmci device", __func__);
> v = &dev->vmmci;
>
> - log_debug("vm %u shutdown", dev->vmm_id);
> + log_debug("vm %u shutdown", dev->vm_fd);
> vm_shutdown(v->cmd == VMMCI_REBOOT ? VMMCI_REBOOT : VMMCI_SHUTDOWN);
> }
>
> @@ -980,7 +981,7 @@ vmmci_io(int dir, uint16_t reg, uint32_t *data, uint8_
> case VIRTIO_CONFIG_ISR_STATUS:
> *data = dev->isr;
> dev->isr = 0;
> - vcpu_deassert_irq(dev->vmm_id, 0, dev->irq);
> + vcpu_deassert_irq(dev->vm_fd, 0, dev->irq);
> break;
> }
> }
> @@ -1111,7 +1112,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
>
> /* Device specific initializiation. */
> dev->dev_type = VMD_DEVTYPE_NET;
> - dev->vmm_id = vm->vm_vmmid;
> + dev->vm_fd = vm->vm_fd;
> dev->vionet.data_fd = child_taps[i];
>
> /* MAC address has been assigned by the parent */
> @@ -1180,7 +1181,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
>
> /* Device specific initialization. */
> dev->dev_type = VMD_DEVTYPE_DISK;
> - dev->vmm_id = vm->vm_vmmid;
> + dev->vm_fd = vm->vm_fd;
> dev->vioblk.seg_max = VIOBLK_SEG_MAX_DEFAULT;
>
> /*
> @@ -1228,7 +1229,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom,
>
> /* Device specific initialization. */
> dev->dev_type = VMD_DEVTYPE_SCSI;
> - dev->vmm_id = vm->vm_vmmid;
> + dev->vm_fd = vm->vm_fd;
> dev->vioscsi.cdrom_fd = child_cdrom;
> dev->vioscsi.locked = 0;
> dev->vioscsi.lba = 0;
> @@ -1421,7 +1422,7 @@ virtio_dev_init(struct vmd_vm *vm, struct virtio_dev *
> dev->irq = pci_get_dev_irq(pci_id);
> dev->isr = 0;
> dev->vm_id = vm->vm_vmid;
> - dev->vmm_id = vm->vm_vmmid;
> + dev->vm_fd = vm->vm_fd;
>
> dev->device_feature = features;
>
> @@ -1684,14 +1685,24 @@ virtio_dev_launch(struct vmd_vm *vm, struct virtio_dev
> if (virtio_dev_closefds(dev_entry) == -1)
> fatalx("unable to close other virtio devs");
> }
> + /*
> + * Device helpers only need the VM file descriptor passed via
> + * argv -i for remap_guest_mem(); close inherited control fds.
> + */
> + if (env->vmd_vmm_fd != -1 && env->vmd_vmm_fd != vm->vm_fd)
> + close_fd(env->vmd_vmm_fd);
> + if (env->vmd_psp_fd != -1 && env->vmd_psp_fd != vm->vm_fd)
> + close_fd(env->vmd_psp_fd);
>
> memset(num, 0, sizeof(num));
> snprintf(num, sizeof(num), "%d", sync_fds[1]);
> memset(vmm_fd, 0, sizeof(vmm_fd));
> - snprintf(vmm_fd, sizeof(vmm_fd), "%d", env->vmd_vmm_fd);
> + snprintf(vmm_fd, sizeof(vmm_fd), "%d", vm->vm_fd);
> memset(vm_name, 0, sizeof(vm_name));
> snprintf(vm_name, sizeof(vm_name), "%s",
> vm->vm_params.vmc_name);
> + if (vm->vm_fd > 0)
> + fcntl(vm->vm_fd, F_SETFD, 0); /* keep vm fd across exec */
>
> t[0] = dev->dev_type;
> t[1] = '\0';
> @@ -1820,14 +1831,14 @@ virtio_dispatch_dev(int fd, short event, void *arg)
> static int
> handle_dev_msg(struct viodev_msg *msg, struct virtio_dev *gdev)
> {
> - uint32_t vmm_id = gdev->vmm_id;
> + int vm_fd = gdev->vm_fd;
>
> switch (msg->type) {
> case VIODEV_MSG_KICK:
> if (msg->state == INTR_STATE_ASSERT)
> - vcpu_assert_irq(vmm_id, msg->vcpu, msg->irq);
> + vcpu_assert_irq(vm_fd, msg->vcpu, msg->irq);
> else if (msg->state == INTR_STATE_DEASSERT)
> - vcpu_deassert_irq(vmm_id, msg->vcpu, msg->irq);
> + vcpu_deassert_irq(vm_fd, msg->vcpu, msg->irq);
> break;
> case VIODEV_MSG_READY:
> log_debug("%s: device reports ready", __func__);
> @@ -1931,9 +1942,9 @@ virtio_pci_io(int dir, uint16_t reg, uint32_t *data, u
> * device performs a register read.
> */
> if (msg.state == INTR_STATE_ASSERT)
> - vcpu_assert_irq(dev->vmm_id, msg.vcpu, msg.irq);
> + vcpu_assert_irq(dev->vm_fd, msg.vcpu, msg.irq);
> else if (msg.state == INTR_STATE_DEASSERT)
> - vcpu_deassert_irq(dev->vmm_id, msg.vcpu, msg.irq);
> + vcpu_deassert_irq(dev->vm_fd, msg.vcpu, msg.irq);
> } else {
> log_warnx("%s: expected IO_READ, got %d", __func__,
> msg.type);
> blob - 0af586eb6c5e599d8641020555f2f57411154b03
> blob + ba591e18bd8dd5952bbd2090bdad573d387bff27
> --- usr.sbin/vmd/virtio.h
> +++ usr.sbin/vmd/virtio.h
> @@ -341,10 +341,10 @@ struct virtio_dev {
> /* Multi-process enabled. */
> struct vioblk_dev vioblk;
> struct vionet_dev vionet;
> + struct vioscsi_dev vioscsi;
>
> /* In-process only. */
> struct vmmci_dev vmmci;
> - struct vioscsi_dev vioscsi;
> };
>
> struct virtio_io_cfg cfg; /* Virtio 0.9 */
> @@ -369,8 +369,8 @@ struct virtio_dev {
> int sync_fd; /* fd for synchronous channel */
> int async_fd; /* fd for async channel */
>
> + int vm_fd; /* vmm(4) vm file descriptor [r] */
> uint32_t vm_id; /* vmd(8) vm identifier [r] */
> - uint32_t vmm_id; /* vmm(4) vm identifier [r] */
> pid_t dev_pid; /* pid of emulator process */
> char dev_type; /* device type (as char) */
> SLIST_ENTRY(virtio_dev) dev_next;
> blob - ff4551814eafc8d0284ae40e63d53824737d8431
> blob + 6d9dd95ed0c33bd783d6d5475aabe82d0c7392c8
> --- usr.sbin/vmd/vm.c
> +++ usr.sbin/vmd/vm.c
> @@ -194,10 +194,8 @@ start_vm(struct vmd_vm *vm, int fd)
> errno = ret;
> log_warn("could not create vm");
> }
> -
> - /* Let the vmm process know we failed by sending a 0 vm id. */
> - vm->vm_vmmid = 0;
> - atomicio(vwrite, fd, &vm->vm_vmmid, sizeof(vm->vm_vmmid));
> + /* Let the vmm process know we failed by sending the error code. */
> + atomicio(vwrite, fd, &ret, sizeof(ret));
> return (ret);
> }
>
> @@ -217,14 +215,10 @@ start_vm(struct vmd_vm *vm, int fd)
> log_warn("failed to set nonblocking mode on console");
> return (1);
> }
> -
> - /*
> - * We now let the vmm process know we were successful by sending it our
> - * vmm(4) assigned vm id.
> - */
> - if (atomicio(vwrite, fd, &vm->vm_vmmid, sizeof(vm->vm_vmmid)) !=
> - sizeof(vm->vm_vmmid)) {
> - log_warn("failed to send created vm id to vmm process");
> + /* We now let the vmm process know we were successful. */
> + ret = 0;
> + if (atomicio(vwrite, fd, &ret, sizeof(ret)) != sizeof(ret)) {
> + log_warn("failed to send vm start status to vmm process");
> return (1);
> }
>
> @@ -485,7 +479,7 @@ unpause_vm(struct vmd_vm *vm)
> * the register state provided
> *
> * Parameters
> - * vmid: VM ID to reset
> + * fd: vm file descriptor to reset
> * vcpu_id: VCPU ID to reset
> * vrs: the register state to initialize
> *
> @@ -495,18 +489,17 @@ unpause_vm(struct vmd_vm *vm)
> * valid)
> */
> int
> -vcpu_reset(uint32_t vmid, uint32_t vcpu_id, struct vcpu_reg_state *vrs)
> +vcpu_reset(int fd, uint32_t vcpu_id, struct vcpu_reg_state *vrs)
> {
> struct vm_resetcpu_params vrp;
>
> memset(&vrp, 0, sizeof(vrp));
> - vrp.vrp_vm_id = vmid;
> vrp.vrp_vcpu_id = vcpu_id;
> memcpy(&vrp.vrp_init_state, vrs, sizeof(struct vcpu_reg_state));
>
> - log_debug("%s: resetting vcpu %d for vm %d", __func__, vcpu_id, vmid);
> + log_debug("%s: resetting vcpu %d", __func__, vcpu_id);
>
> - if (ioctl(env->vmd_vmm_fd, VMM_IOC_RESETCPU, &vrp) == -1)
> + if (ioctl(fd, VMM_IOC_RESETCPU, &vrp) == -1)
> return (errno);
>
> return (0);
> @@ -556,10 +549,15 @@ vmm_create_vm(struct vmd_vm *vm)
> vcp.vcp_sev = vmc->vmc_sev;
> vcp.vcp_seves = vmc->vmc_seves;
>
> - if (ioctl(env->vmd_vmm_fd, VMM_IOC_CREATE, &vcp) == -1)
> + if (ioctl(env->vmd_vmm_fd, VMM_IOC_CREATE, &vcp) == -1) {
> + close_fd(env->vmd_vmm_fd);
> + env->vmd_vmm_fd = -1;
> return (errno);
> + }
> + close_fd(env->vmd_vmm_fd);
> + env->vmd_vmm_fd = -1;
>
> - vm->vm_vmmid = vcp.vcp_id;
> + vm->vm_fd = vcp.vcp_fd;
> for (i = 0; i < vcp.vcp_ncpus; i++)
> vm->vm_sev_asid[i] = vcp.vcp_asid[i];
> for (i = 0; i < vmc->vmc_nmemranges; i++)
> @@ -640,10 +638,9 @@ run_vm(struct vmd_vm *vm, struct vcpu_reg_state *vrs)
> /* caller will exit, so skip freeing */
> return (ENOMEM);
> }
> - vrp[i]->vrp_vm_id = vm->vm_vmmid;
> vrp[i]->vrp_vcpu_id = i;
>
> - if (vcpu_reset(vm->vm_vmmid, i, vrs)) {
> + if (vcpu_reset(vm->vm_fd, i, vrs)) {
> log_warnx("cannot reset vcpu %zu", i);
> return (EIO);
> }
> @@ -893,7 +890,7 @@ vcpu_run_loop(void *arg)
> /* Still more interrupts pending? */
> vrp->vrp_intr_pending = intr_pending(current_vm);
>
> - if (ioctl(env->vmd_vmm_fd, VMM_IOC_RUN, vrp) == -1) {
> + if (ioctl(current_vm->vm_fd, VMM_IOC_RUN, vrp) == -1) {
> /* If run ioctl failed, exit */
> ret = errno;
> log_warn("%s: vm %d / vcpu %d run ioctl failed",
> @@ -930,17 +927,16 @@ vcpu_run_loop(void *arg)
> }
>
> int
> -vcpu_intr(uint32_t vmm_id, uint32_t vcpu_id, uint8_t intr)
> +vcpu_intr(int fd, uint32_t vcpu_id, uint8_t intr)
> {
> struct vm_intr_params vip;
>
> memset(&vip, 0, sizeof(vip));
>
> - vip.vip_vm_id = vmm_id;
> vip.vip_vcpu_id = vcpu_id; /* XXX always 0? */
> vip.vip_intr = intr;
>
> - if (ioctl(env->vmd_vmm_fd, VMM_IOC_INTR, &vip) == -1)
> + if (ioctl(fd, VMM_IOC_INTR, &vip) == -1)
> return (errno);
>
> return (0);
> @@ -1095,7 +1091,7 @@ vm_pipe_recv(struct vm_dev_pipe *p)
> * Returns 0 on success or an errno in event of failure.
> */
> int
> -remap_guest_mem(struct vmd_vm *vm, int vmm_fd)
> +remap_guest_mem(struct vmd_vm *vm, int vm_fd)
> {
> size_t i;
> struct vm_sharemem_params vsp;
> @@ -1105,17 +1101,12 @@ remap_guest_mem(struct vmd_vm *vm, int vmm_fd)
>
> /* Initialize using our original creation parameters. */
> memset(&vsp, 0, sizeof(vsp));
> - vsp.vsp_nmemranges = vm->vm_params.vmc_nmemranges;
> - vsp.vsp_vm_id = vm->vm_vmmid;
> - memcpy(&vsp.vsp_memranges, &vm->vm_params.vmc_memranges,
> - sizeof(vsp.vsp_memranges));
> -
> /* Ask vmm(4) to enter a shared mapping to guest memory. */
> - if (ioctl(vmm_fd, VMM_IOC_SHAREMEM, &vsp) == -1)
> + if (ioctl(vm_fd, VMM_IOC_SHAREMEM, &vsp) == -1)
> return (errno);
>
> /* Update with the location of the new mappings. */
> - for (i = 0; i < vsp.vsp_nmemranges; i++)
> + for (i = 0; i < vm->vm_params.vmc_nmemranges; i++)
> vm->vm_params.vmc_memranges[i].vmr_va = vsp.vsp_va[i];
>
> return (0);
> blob - 45be7b08b02cb06e87b3f34360743510332727ae
> blob + 0c998bd8242ff364364bba1bcef2bd67cfce2c22
> --- usr.sbin/vmd/vmd.c
> +++ usr.sbin/vmd/vmd.c
> @@ -28,6 +28,7 @@
> #include <stdlib.h>
> #include <string.h>
> #include <errno.h>
> +#include <limits.h>
> #include <event.h>
> #include <fcntl.h>
> #include <pwd.h>
> @@ -238,7 +239,7 @@ vmd_dispatch_control(int fd, struct privsep_proc *p, s
> } else {
> vid.vid_id = vm->vm_vmid;
> }
> - } else if ((vm = vm_getbyid(vid.vid_id)) == NULL) {
> + } else if ((vm = vm_getbyvmid(vid.vid_id)) == NULL) {
> res = ENOENT;
> cmd = type == IMSG_VMDOP_PAUSE_VM
> ? IMSG_VMDOP_PAUSE_VM_RESPONSE
> @@ -323,7 +324,6 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struc
> if ((vm = vm_getbyvmid(vmr.vmr_id)) == NULL)
> break;
> vm->vm_pid = vmr.vmr_pid;
> - vm->vm_vmmid = vmr.vmr_id;
>
> /*
> * If the peerid is not -1, forward the response back to the
> @@ -599,13 +599,13 @@ main(int argc, char **argv)
> break;
> case 'V':
> vm_launch = VMD_LAUNCH_VM;
> - vm_fd = strtonum(optarg, 0, 128, &errp);
> + vm_fd = strtonum(optarg, 0, INT_MAX, &errp);
> if (errp)
> fatalx("invalid vm fd");
> break;
> case 'X':
> vm_launch = VMD_LAUNCH_DEV;
> - vm_fd = strtonum(optarg, 0, 128, &errp);
> + vm_fd = strtonum(optarg, 0, INT_MAX, &errp);
> if (errp)
> fatalx("invalid device fd");
> break;
> @@ -620,13 +620,13 @@ main(int argc, char **argv)
> }
> break;
> case 'i':
> - vmm_fd = strtonum(optarg, 0, 128, &errp);
> + vmm_fd = strtonum(optarg, 0, INT_MAX, &errp);
> if (errp)
> fatalx("invalid vmm fd");
> break;
> case 'j':
> /* -1 means no PSP available */
> - psp_fd = strtonum(optarg, -1, 128, &errp);
> + psp_fd = strtonum(optarg, -1, INT_MAX, &errp);
> if (errp)
> fatalx("invalid psp fd");
> break;
> @@ -962,43 +962,7 @@ vm_getbyvmid(uint32_t vmid)
> return (NULL);
> }
>
> -/* Find a vm in the list by it's vmm(4) id. */
> struct vmd_vm *
> -vm_getbyid(uint32_t id)
> -{
> - struct vmd_vm *vm;
> -
> - if (id == 0)
> - return (NULL);
> - TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) {
> - if (vm->vm_vmmid == id) // XXX check this
> - return (vm);
> - }
> -
> - return (NULL);
> -}
> -
> -/* Translate a kernel/vmm(4) vm id to a vmd(8) id. */
> -uint32_t
> -vm_id2vmid(uint32_t id, struct vmd_vm *vm)
> -{
> - if (vm == NULL && (vm = vm_getbyid(id)) == NULL)
> - return (0);
> - DPRINTF("%s: vmm id %u is vmid %u", __func__,
> - id, vm->vm_vmid);
> - return (vm->vm_vmid);
> -}
> -
> -uint32_t
> -vm_vmid2id(uint32_t vmid, struct vmd_vm *vm)
> -{
> - if (vm == NULL && (vm = vm_getbyvmid(vmid)) == NULL)
> - return (0);
> - DPRINTF("%s: vmid %u is vmm id %u", __func__, vmid, vm->vm_vmmid);
> - return (vm->vm_vmmid);
> -}
> -
> -struct vmd_vm *
> vm_getbyname(const char *name)
> {
> struct vmd_vm *vm;
> @@ -1221,6 +1185,7 @@ vm_register(struct privsep *ps, struct vmop_create_par
> vmc = &vm->vm_params;
> vm->vm_pid = -1;
> vm->vm_tty = -1;
> + vm->vm_fd = -1;
> vm->vm_kernel = -1;
> vm->vm_state &= ~VM_STATE_PAUSED;
>
> blob - bfd2402fb03a98a0d0e08b20b18030519b410b89
> blob + 260e4fbf72cd7eb78f44e845776092c715b2fc6f
> --- usr.sbin/vmd/vmd.h
> +++ usr.sbin/vmd/vmd.h
> @@ -308,7 +308,7 @@ struct vmd_vm {
> pid_t vm_pid;
> uid_t vm_uid;
> uint32_t vm_vmid; /* vmd(8) identifier */
> - uint32_t vm_vmmid; /* vmm(4) identifier */
> + int vm_fd; /* vmm(4) vm file descriptor */
> uint32_t vm_peerid;
>
> /* AMD SEV features */
> @@ -471,10 +471,7 @@ ssize_t decode_udp_ip_header(unsigned char *, size_t,
>
> /* vmd.c */
> int vmd_reload(unsigned int, const char *);
> -struct vmd_vm *vm_getbyid(uint32_t);
> struct vmd_vm *vm_getbyvmid(uint32_t);
> -uint32_t vm_id2vmid(uint32_t, struct vmd_vm *);
> -uint32_t vm_vmid2id(uint32_t, struct vmd_vm *);
> struct vmd_vm *vm_getbyname(const char *);
> struct vmd_vm *vm_getbypid(pid_t);
> void vm_stop(struct vmd_vm *, int, const char *);
> @@ -525,7 +522,7 @@ void create_memory_map(struct vmd_vm *);
> int load_firmware(struct vmd_vm *, struct vcpu_reg_state *);
> int init_emulated_hw(struct vmd_vm *, int, int[][VM_MAX_BASE_PER_DISK],
> int *);
> -int vcpu_reset(uint32_t, uint32_t, struct vcpu_reg_state *);
> +int vcpu_reset(int, uint32_t, struct vcpu_reg_state *);
> void pause_vm_md(struct vmd_vm *);
> void unpause_vm_md(struct vmd_vm *);
> void *hvaddr_mem(paddr_t, size_t);
> @@ -536,8 +533,8 @@ int read_mem(paddr_t, void *, size_t);
> int intr_ack(struct vmd_vm *);
> int intr_pending(struct vmd_vm *);
> void intr_toggle_el(struct vmd_vm *, int, int);
> -void vcpu_assert_irq(uint32_t, uint32_t, int);
> -void vcpu_deassert_irq(uint32_t, uint32_t, int);
> +void vcpu_assert_irq(int, uint32_t, int);
> +void vcpu_deassert_irq(int, uint32_t, int);
> int vcpu_exit(struct vm_run_params *);
> uint8_t vcpu_exit_pci(struct vm_run_params *);
>
> @@ -551,7 +548,7 @@ void get_input_data(struct vm_exit *, uint32_t *);
> void vcpu_halt(uint32_t);
> void vcpu_unhalt(uint32_t);
> void vcpu_signal_run(uint32_t);
> -int vcpu_intr(uint32_t, uint32_t, uint8_t);
> +int vcpu_intr(int, uint32_t, uint8_t);
> void vm_main(int, int);
> void mutex_lock(pthread_mutex_t *);
> void mutex_unlock(pthread_mutex_t *);
> @@ -600,7 +597,7 @@ int psp_df_flush(void);
> int psp_get_gstate(uint32_t, uint32_t *, uint32_t *, uint8_t *);
> int psp_launch_start(uint32_t *, int);
> int psp_launch_update(uint32_t, vaddr_t, size_t);
> -int psp_encrypt_state(uint32_t, uint32_t, uint32_t, uint32_t);
> +int psp_encrypt_state(uint32_t, uint32_t, int, uint32_t);
> int psp_launch_measure(uint32_t);
> int psp_launch_finish(uint32_t);
> int psp_activate(uint32_t, uint32_t);
> blob - 47b393cb5742bb3c2cf411aea27b32234c8ae04f
> blob + 2da0e8da179f32238ec2c7b8cb5c6c1ba0b4b894
> --- usr.sbin/vmd/vmm.c
> +++ usr.sbin/vmd/vmm.c
> @@ -21,6 +21,7 @@
> #include <sys/queue.h>
> #include <sys/wait.h>
> #include <sys/socket.h>
> +#include <signal.h>
>
> #include <dev/vmm/vmm.h>
>
> @@ -45,7 +46,7 @@ int vmm_start_vm(struct imsg *, uint32_t *, pid_t *);
> int vmm_dispatch_parent(int, struct privsep_proc *, struct imsg *);
> void vmm_run(struct privsep *, struct privsep_proc *, void *);
> void vmm_dispatch_vm(int, short, void *);
> -int terminate_vm(struct vm_terminate_params *);
> +int terminate_vm(pid_t);
> int get_info_vm(struct privsep *, struct imsg *, int);
> int opentap(char *);
>
> @@ -108,7 +109,6 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, st
> struct privsep *ps = p->p_ps;
> int res = 0, cmd = IMSG_NONE, verbose;
> struct vmd_vm *vm = NULL;
> - struct vm_terminate_params vtp;
> struct vmop_id vid;
> struct vmop_result vmr;
> struct vmop_addr_result var;
> @@ -153,9 +153,6 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, st
> break;
> case IMSG_VMDOP_START_VM_END:
> res = vmm_start_vm(imsg, &id, &vm_pid);
> - /* Check if the ID can be mapped correctly */
> - if (res == 0 && (id = vm_id2vmid(id, NULL)) == 0)
> - res = ENOENT;
> cmd = IMSG_VMDOP_START_VM_RESPONSE;
> break;
> case IMSG_VMDOP_TERMINATE_VM_REQUEST:
> @@ -171,10 +168,8 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, st
> res = ENOENT;
> } else if ((vm = vm_getbyvmid(id)) != NULL) {
> if (flags & VMOP_FORCE) {
> - vtp.vtp_vm_id = vm_vmid2id(vm->vm_vmid, vm);
> vm->vm_state |= VM_STATE_SHUTDOWN;
> - (void)terminate_vm(&vtp);
> - res = 0;
> + res = terminate_vm(vm->vm_pid);
> } else if (!(vm->vm_state & VM_STATE_SHUTDOWN)) {
> log_debug("%s: sending shutdown request"
> " to vm %d", __func__, id);
> @@ -199,7 +194,7 @@ vmm_dispatch_parent(int fd, struct privsep_proc *p, st
> * Check to see if the VM process is still
> * active. If not, return VMD_VM_STOP_INVALID.
> */
> - if (vm_vmid2id(vm->vm_vmid, vm) == 0) {
> + if (kill(vm->vm_pid, 0) == -1 && errno == ESRCH) {
> log_debug("%s: no vm running anymore",
> __func__);
> res = VMD_VM_STOP_INVALID;
> @@ -327,11 +322,10 @@ void
> vmm_sighdlr(int sig, short event, void *arg)
> {
> struct privsep *ps = arg;
> - int status, ret = 0;
> + int status, ret;
> pid_t pid;
> struct vmop_result vmr;
> struct vmd_vm *vm;
> - struct vm_terminate_params vtp;
>
> log_debug("%s: handling signal %d", __func__, sig);
> switch (sig) {
> @@ -340,6 +334,7 @@ vmm_sighdlr(int sig, short event, void *arg)
> pid = waitpid(-1, &status, WNOHANG);
> if (pid <= 0)
> continue;
> + ret = 0;
>
> if (WIFEXITED(status) || WIFSIGNALED(status)) {
> vm = vm_getbypid(pid);
> @@ -354,24 +349,21 @@ vmm_sighdlr(int sig, short event, void *arg)
>
> if (WIFEXITED(status))
> ret = WEXITSTATUS(status);
> + else if (WIFSIGNALED(status))
> + ret = EIO;
>
> /* Don't reboot on pending shutdown */
> if (ret == EAGAIN &&
> (vm->vm_state & VM_STATE_SHUTDOWN))
> ret = 0;
>
> - /* XXX check this */
> - vtp.vtp_vm_id = vm->vm_vmmid;
> + log_debug("%s: vm %s exited (id %d)",
> + __func__, vm->vm_params.vmc_name,
> + vm->vm_vmid);
>
> - if (terminate_vm(&vtp) == 0)
> - log_debug("%s: terminated vm %s"
> - " (id %d)", __func__,
> - vm->vm_params.vmc_name,
> - vm->vm_vmid);
> -
> memset(&vmr, 0, sizeof(vmr));
> vmr.vmr_result = ret;
> - vmr.vmr_id = vm_id2vmid(vm->vm_vmmid, vm);
> + vmr.vmr_id = vm->vm_vmid;
> if (proc_compose_imsg(ps, PROC_PARENT,
> IMSG_VMDOP_TERMINATE_VM_EVENT,
> vm->vm_peerid, -1, &vmr, sizeof(vmr)) == -1)
> @@ -397,14 +389,11 @@ vmm_sighdlr(int sig, short event, void *arg)
> void
> vmm_shutdown(void)
> {
> - struct vm_terminate_params vtp;
> struct vmd_vm *vm, *vm_next;
>
> TAILQ_FOREACH_SAFE(vm, env->vmd_vms, vm_entry, vm_next) {
> - vtp.vtp_vm_id = vm_vmid2id(vm->vm_vmid, vm);
> -
> /* XXX suspend or request graceful shutdown */
> - (void)terminate_vm(&vtp);
> + (void)terminate_vm(vm->vm_pid);
> vm_remove(vm, __func__);
> }
> }
> @@ -514,23 +503,18 @@ vmm_dispatch_vm(int fd, short event, void *arg)
> imsg_event_add(iev);
> }
>
> -/*
> - * terminate_vm
> - *
> - * Requests vmm(4) to terminate the VM whose ID is provided in the
> - * supplied vm_terminate_params structure (vtp->vtp_vm_id)
> - *
> - * Parameters
> - * vtp: vm_terminate_params struct containing the ID of the VM to terminate
> - *
> - * Return values:
> - * 0: success
> - * !0: ioctl to vmm(4) failed (eg, ENOENT if the supplied VM is not valid)
> - */
> int
> -terminate_vm(struct vm_terminate_params *vtp)
> +terminate_vm(pid_t pid)
> {
> - if (ioctl(env->vmd_vmm_fd, VMM_IOC_TERM, vtp) == -1)
> + struct vm_terminate_params vtp;
> +
> + if (pid <= 0)
> + return (EINVAL);
> +
> + memset(&vtp, 0, sizeof(vtp));
> + vtp.vtp_creator_pid = pid;
> +
> + if (ioctl(env->vmd_vmm_fd, VMM_IOC_TERM, &vtp) == -1)
> return (errno);
>
> return (0);
> @@ -588,7 +572,7 @@ opentap(char *ifname)
> *
> * Parameters:
> * imsg: The VM data structure that is including the VM create parameters.
> - * id: Returns the VM id as reported by the kernel and obtained from the VM.
> + * id: Returns the vmd(8) VM identifier.
> * pid: Returns the VM pid to the parent.
> *
> * Return values:
> @@ -686,22 +670,19 @@ vmm_start_vm(struct imsg *imsg, uint32_t *id, pid_t *p
> goto err;
> }
>
> - /* Read back the kernel-generated vm id from the child */
> - sz = atomicio(read, fds[0], &vm->vm_vmmid,
> - sizeof(vm->vm_vmmid));
> - if (sz != sizeof(vm->vm_vmmid)) {
> - log_debug("%s: failed to receive vm id from vm %s",
> + /* Read back the VM start status from the child. */
> + sz = atomicio(read, fds[0], &ret, sizeof(ret));
> + if (sz != sizeof(ret)) {
> + log_debug("%s: failed to receive vm start status from vm %s",
> __func__, vm->vm_params.vmc_name);
> - /* vmd could not allocate memory for the vm. */
> - ret = ENOMEM;
> + ret = EIO;
> goto err;
> }
>
> - /* Check for an invalid id. This indicates child failure. */
> - if (vm->vm_vmmid == 0)
> + if (ret != 0)
> goto err;
>
> - *id = vm->vm_vmmid;
> + *id = vm->vm_vmid;
> *pid = vm->vm_pid;
>
> /* Wire up our pipe into the event handling. */
> @@ -724,6 +705,8 @@ vmm_start_vm(struct imsg *imsg, uint32_t *id, pid_t *p
> close(dev_null);
> }
>
> + if (env->vmd_vmm_fd > 0)
> + fcntl(env->vmd_vmm_fd, F_SETFD, 0); /* /dev/vmm fd */
> if (env->vmd_psp_fd > 0)
> fcntl(env->vmd_psp_fd, F_SETFD, 0); /* psp device fd */
>
> @@ -795,8 +778,8 @@ get_info_vm(struct privsep *ps, struct imsg *imsg, int
> size_t ct, i;
> struct vm_info_params vip;
> struct vm_info_result *info;
> - struct vm_terminate_params vtp;
> struct vmop_info_result vir;
> + struct vmd_vm *vm;
> uint32_t peer_id;
>
> /*
> @@ -839,11 +822,10 @@ get_info_vm(struct privsep *ps, struct imsg *imsg, int
> ct = vip.vip_size / sizeof(struct vm_info_result);
> for (i = 0; i < ct; i++) {
> if (terminate) {
> - vtp.vtp_vm_id = info[i].vir_id;
> - if ((ret = terminate_vm(&vtp)) != 0)
> + if ((ret = terminate_vm(info[i].vir_creator_pid)) != 0)
> break;
> - log_debug("%s: terminated vm %s (id %d)", __func__,
> - info[i].vir_name, info[i].vir_id);
> + log_debug("%s: terminated vm %s (pid %d)", __func__,
> + info[i].vir_name, info[i].vir_creator_pid);
> continue;
> }
>
> @@ -854,7 +836,9 @@ get_info_vm(struct privsep *ps, struct imsg *imsg, int
> memcpy(vir.vir_vcpu_state, info[i].vir_vcpu_state,
> sizeof(vir.vir_vcpu_state));
> vir.vir_creator_pid = info[i].vir_creator_pid;
> - vir.vir_id = vm_id2vmid(info[i].vir_id, NULL);
> + if ((vm = vm_getbypid(info[i].vir_creator_pid)) == NULL)
> + continue;
> + vir.vir_id = vm->vm_vmid;
> memcpy(vir.vir_name, info[i].vir_name, sizeof(vir.vir_name));
>
> peer_id = imsg_get_id(imsg);
> blob - 1b5ade90f9b3152a37bcc54a2fadd6e8a71fbac7
> blob + 235cb1f2c53747da6955850a2f94e7e8aad3aba3
> --- usr.sbin/vmd/x86_vm.c
> +++ usr.sbin/vmd/x86_vm.c
> @@ -368,7 +368,7 @@ init_emulated_hw(struct vmd_vm *vm, int child_cdrom,
> memset(&ioports_map, 0, sizeof(io_fn_t) * MAX_PORTS);
>
> /* Init i8253 PIT */
> - i8253_init(vm->vm_vmmid);
> + i8253_init(vm->vm_fd);
> ioports_map[TIMER_CTRL] = vcpu_exit_i8253;
> ioports_map[TIMER_BASE + TIMER_CNTR0] = vcpu_exit_i8253;
> ioports_map[TIMER_BASE + TIMER_CNTR1] = vcpu_exit_i8253;
> @@ -376,7 +376,7 @@ init_emulated_hw(struct vmd_vm *vm, int child_cdrom,
> ioports_map[PCKBC_AUX] = vcpu_exit_i8253_misc;
>
> /* Init mc146818 RTC */
> - mc146818_init(vm->vm_vmmid, memlo, memhi);
> + mc146818_init(vm->vm_fd, memlo, memhi);
> ioports_map[IO_RTC] = vcpu_exit_mc146818;
> ioports_map[IO_RTC + 1] = vcpu_exit_mc146818;
>
> @@ -390,7 +390,7 @@ init_emulated_hw(struct vmd_vm *vm, int child_cdrom,
> ioports_map[ELCR1] = vcpu_exit_elcr;
>
> /* Init ns8250 UART */
> - ns8250_init(con_fd, vm->vm_vmmid);
> + ns8250_init(con_fd, vm->vm_fd);
> for (i = COM1_DATA; i <= COM1_SCR; i++)
> ioports_map[i] = vcpu_exit_com;
>
> @@ -482,7 +482,7 @@ vcpu_exit_inout(struct vm_run_params *vrp)
> vei->vrs.vrs_gprs[VCPU_REGS_RIP] += vei->vei.vei_insn_len;
>
> if (intr != 0xFF)
> - vcpu_assert_irq(vrp->vrp_vm_id, vrp->vrp_vcpu_id, intr);
> + vcpu_assert_irq(current_vm->vm_fd, vrp->vrp_vcpu_id, intr);
> }
>
> /*
> @@ -883,17 +883,17 @@ hvaddr_mem(paddr_t gpa, size_t len)
> * Injects the specified IRQ on the supplied vcpu/vm
> *
> * Parameters:
> - * vm_id: VMM vm ID to inject to
> + * fd: vmm(4) vm file descriptor to inject to
> * vcpu_id: VCPU ID to inject to
> * irq: IRQ to inject
> */
> void
> -vcpu_assert_irq(uint32_t vmm_id, uint32_t vcpu_id, int irq)
> +vcpu_assert_irq(int fd, uint32_t vcpu_id, int irq)
> {
> i8259_assert_irq(irq);
>
> if (i8259_is_pending()) {
> - if (vcpu_intr(vmm_id, vcpu_id, 1))
> + if (vcpu_intr(fd, vcpu_id, 1))
> fatalx("%s: can't assert INTR", __func__);
>
> vcpu_unhalt(vcpu_id);
> @@ -907,19 +907,19 @@ vcpu_assert_irq(uint32_t vmm_id, uint32_t vcpu_id, int
> * Clears the specified IRQ on the supplied vcpu/vm
> *
> * Parameters:
> - * vm_id: VMM vm ID to clear in
> + * fd: vmm(4) vm file descriptor to clear in
> * vcpu_id: VCPU ID to clear in
> * irq: IRQ to clear
> */
> void
> -vcpu_deassert_irq(uint32_t vmm_id, uint32_t vcpu_id, int irq)
> +vcpu_deassert_irq(int fd, uint32_t vcpu_id, int irq)
> {
> i8259_deassert_irq(irq);
>
> if (!i8259_is_pending()) {
> - if (vcpu_intr(vmm_id, vcpu_id, 0))
> - fatalx("%s: can't deassert INTR for vmm_id %d, "
> - "vcpu_id %d", __func__, vmm_id, vcpu_id);
> + if (vcpu_intr(fd, vcpu_id, 0))
> + fatalx("%s: can't deassert INTR for vm fd %d, "
> + "vcpu_id %d", __func__, fd, vcpu_id);
> }
> }
>
--
Dr. Hans-Jörg Höxer Hans-Joerg_Hoexer@genua.de
Senior Expert Kryptographie
eXtreme Kernel and Crypto Development
genua GmbH
Domagkstrasse 7, 85551 Kirchheim bei München
tel +49 89 991950-0, fax -999, www.genua.eu
Geschäftsführer: Matthias Ochs, Marc Tesch
Amtsgericht München HRB 98238
genua ist ein Unternehmen der Bundesdruckerei-Gruppe.
[EXT] Re: tests wanted: vmm(4)/vmd(8) fd-ification