Page MenuHomeFreeBSD

D52781.id.diff
No OneTemporary

D52781.id.diff

diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -276,6 +276,7 @@
&vm_maxcpu, 0, "Maximum number of vCPUs");
static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr);
+static int vm_handle_rendezvous(struct vcpu *vcpu, bool wait);
/* global statistics */
VMM_STAT(VCPU_MIGRATIONS, "vcpu migration across host cpus");
@@ -997,7 +998,9 @@
vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
bool from_idle)
{
+ struct vcpu *rendezvous_vcpu;
int error;
+ uint16_t maxcpus;
vcpu_assert_locked(vcpu);
@@ -1012,6 +1015,30 @@
vcpu_notify_event_locked(vcpu, false);
VMM_CTR1(vcpu, "vcpu state change from %s to "
"idle requested", vcpu_state2str(vcpu->state));
+ /*
+ * If the vCPU we're requesting a state change for, is currently
+ * waiting for rendezvous completion, we're going to deadlock
+ * because we're waiting for the other vCPU to transition to IDLE
+ * and the other vCPU waits for us completing the rendezvous.
+ * Therefore, we have to handle any pending rendezvous.
+ */
+ if (__predict_false(
+ atomic_load_ptr(&vcpu->vm->rendezvous_func) !=
+ NULL)) {
+ vcpu_unlock(vcpu);
+ maxcpus = vm_get_maxcpus(vcpu->vm);
+ for (uint16_t i = 0; i < maxcpus; i++) {
+ rendezvous_vcpu = vm_vcpu(vcpu->vm, i);
+ if (rendezvous_vcpu == NULL)
+ continue;
+ vm_handle_rendezvous(rendezvous_vcpu, false);
+ }
+ vcpu_lock(vcpu);
+ /* Recheck vCPU state to avoid an unnecessary sleep. */
+ if (vcpu->state == VCPU_IDLE) {
+ break;
+ }
+ }
msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz);
}
} else {
@@ -1084,7 +1111,7 @@
}
static int
-vm_handle_rendezvous(struct vcpu *vcpu)
+vm_handle_rendezvous(struct vcpu *vcpu, bool wait)
{
struct vm *vm = vcpu->vm;
struct thread *td;
@@ -1112,6 +1139,12 @@
wakeup(&vm->rendezvous_func);
break;
}
+
+ if (!wait) {
+ mtx_unlock(&vm->rendezvous_mtx);
+ return (0);
+ }
+
VMM_CTR0(vcpu, "Wait for rendezvous completion");
mtx_sleep(&vm->rendezvous_func, &vm->rendezvous_mtx, 0,
"vmrndv", hz);
@@ -1386,7 +1419,7 @@
} else {
VMM_CTR0(vcpu, "Rendezvous during suspend");
vcpu_unlock(vcpu);
- error = vm_handle_rendezvous(vcpu);
+ error = vm_handle_rendezvous(vcpu, true);
vcpu_lock(vcpu);
}
}
@@ -1602,7 +1635,7 @@
vioapic_process_eoi(vm, vme->u.ioapic_eoi.vector);
break;
case VM_EXITCODE_RENDEZVOUS:
- error = vm_handle_rendezvous(vcpu);
+ error = vm_handle_rendezvous(vcpu, true);
break;
case VM_EXITCODE_HLT:
intr_disabled = ((vme->u.hlt.rflags & PSL_I) == 0);
@@ -2345,7 +2378,7 @@
*/
VMM_CTR0(vcpu, "Rendezvous already in progress");
mtx_unlock(&vm->rendezvous_mtx);
- error = vm_handle_rendezvous(vcpu);
+ error = vm_handle_rendezvous(vcpu, true);
if (error != 0)
return (error);
goto restart;
@@ -2369,7 +2402,7 @@
vcpu_notify_event(vm_vcpu(vm, i), false);
}
- return (vm_handle_rendezvous(vcpu));
+ return (vm_handle_rendezvous(vcpu, true));
}
struct vatpic *

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 19, 3:36 AM (9 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31744321
Default Alt Text
D52781.id.diff (3 KB)

Event Timeline