Re: [EXT] Re: tests wanted: vmm(4)/vmd(8) fd-ification
Hans-Jörg Höxer <[email protected]>
| Newsgroups | gmane.os.openbsd.tech |
|---|---|
| Message-ID | <[email protected]> |
Hi, On Thu, Aug 06, 2026 at 05:09:35PM -0400, Dave Voutila wrote: > Dave Voutila <[email protected]> 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 <[email protected]> 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 [email protected] 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.
smime.p7s
(application/pkcs7-signature, 6.1 KB) - not displayed