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