Skip to content

Commit 3d39856

Browse files
committed
vmm: Suspend the VM before destroying it
Otherwise we don't do anything to kick vcpu threads out of a sleep state when destroying a VM. For instance, suppose a guest executes hlt on amd64 or wfi on arm64 with interrupts disabled. Then, bhyvectl --destroy will hang until the vcpu thread somehow comes out of vm_handle_hlt()/vm_handle_wfi() since destroy_dev() is waiting for vCPU threads to drain. Note that on amd64, if hw.vmm.halt_detection is set to 1 (the default), the guest will automatically exit in this case since it's treated as a shutdown. But, the above should not hang if halt_detection is set to 0. Here, vm_suspend() wakes up vcpu threads, and a subsequent attempt to run the vCPU will result in an error which gets propagated to userspace, allowing destroy_dev() to proceed. Add a new suspend code for this purpose. Modify bhyve to exit with status 4 ("exited due to an error") when it's received, since that's what'll happen generally when the VM is destroyed asynchronously. Reported by: def MFC after: 2 weeks Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D51761
1 parent b653a28 commit 3d39856

File tree

11 files changed

+24
-6
lines changed

11 files changed

+24
-6
lines changed

sys/amd64/include/vmm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ enum vm_suspend_how {
4646
VM_SUSPEND_POWEROFF,
4747
VM_SUSPEND_HALT,
4848
VM_SUSPEND_TRIPLEFAULT,
49+
VM_SUSPEND_DESTROY,
4950
VM_SUSPEND_LAST
5051
};
5152

sys/arm64/include/vmm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum vm_suspend_how {
4242
VM_SUSPEND_RESET,
4343
VM_SUSPEND_POWEROFF,
4444
VM_SUSPEND_HALT,
45+
VM_SUSPEND_DESTROY,
4546
VM_SUSPEND_LAST
4647
};
4748

sys/arm64/vmm/vmm.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,8 +1342,14 @@ vm_handle_smccc_call(struct vcpu *vcpu, struct vm_exit *vme, bool *retu)
13421342
static int
13431343
vm_handle_wfi(struct vcpu *vcpu, struct vm_exit *vme, bool *retu)
13441344
{
1345+
struct vm *vm;
1346+
1347+
vm = vcpu->vm;
13451348
vcpu_lock(vcpu);
13461349
while (1) {
1350+
if (vm->suspend)
1351+
break;
1352+
13471353
if (vgic_has_pending_irq(vcpu->cookie))
13481354
break;
13491355

sys/dev/vmm/vmm_dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,7 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred)
901901
sc->cdev = NULL;
902902
sx_xunlock(&vmmdev_mtx);
903903

904+
vm_suspend(sc->vm, VM_SUSPEND_DESTROY);
904905
destroy_dev(cdev);
905906
vmmdev_destroy(sc);
906907

sys/riscv/include/vmm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum vm_suspend_how {
4949
VM_SUSPEND_RESET,
5050
VM_SUSPEND_POWEROFF,
5151
VM_SUSPEND_HALT,
52+
VM_SUSPEND_DESTROY,
5253
VM_SUSPEND_LAST
5354
};
5455

sys/riscv/vmm/vmm.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,10 +1036,14 @@ vm_raise_msi(struct vm *vm, uint64_t msg, uint64_t addr, int bus, int slot,
10361036
static int
10371037
vm_handle_wfi(struct vcpu *vcpu, struct vm_exit *vme, bool *retu)
10381038
{
1039+
struct vm *vm;
10391040

1041+
vm = vcpu->vm;
10401042
vcpu_lock(vcpu);
1041-
10421043
while (1) {
1044+
if (vm->suspend)
1045+
break;
1046+
10431047
if (aplic_check_pending(vcpu->cookie))
10441048
break;
10451049

usr.sbin/bhyve/aarch64/vmexit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ vmexit_suspend(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun)
122122
exit(1);
123123
case VM_SUSPEND_HALT:
124124
exit(2);
125+
case VM_SUSPEND_DESTROY:
126+
exit(4);
125127
default:
126128
fprintf(stderr, "vmexit_suspend: invalid reason %d\n", how);
127129
exit(100);

usr.sbin/bhyve/amd64/vmexit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ vmexit_suspend(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun)
418418
exit(2);
419419
case VM_SUSPEND_TRIPLEFAULT:
420420
exit(3);
421+
case VM_SUSPEND_DESTROY:
422+
exit(4);
421423
default:
422424
EPRINTLN("vmexit_suspend: invalid reason %d", how);
423425
exit(100);

usr.sbin/bhyve/bhyve.8

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ powered off
11261126
.It 2
11271127
halted
11281128
.It 3
1129-
triple fault
1129+
triple fault (amd64 only)
11301130
.It 4
11311131
exited due to an error
11321132
.El

usr.sbin/bhyve/bhyverun.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,10 +561,8 @@ fbsdrun_start_thread(void *param)
561561
#endif
562562

563563
vm_loop(vi->ctx, vi->vcpu);
564-
565-
/* not reached */
566-
exit(1);
567-
return (NULL);
564+
/* We get here if the VM was destroyed asynchronously. */
565+
exit(4);
568566
}
569567

570568
void

0 commit comments

Comments
 (0)