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 @@ -214,6 +214,7 @@ static int vmm_initialized; static void vmmops_panic(void); +static void vm_handle_rendezvous_help_one(struct vcpu *vcpu); static void vmmops_panic(void) @@ -1335,6 +1336,9 @@ */ if (from_idle) { while (vcpu->state != VCPU_IDLE) { + vm_handle_rendezvous_help_one(vcpu); + if (vcpu->state == VCPU_IDLE) + break; vcpu->reqidle = 1; vcpu_notify_event_locked(vcpu, false); VMM_CTR1(vcpu, "vcpu state change from %s to " @@ -1410,12 +1414,36 @@ panic("Error %d setting state to %d", error, newstate); } +static void +vm_handle_rendezvous_help_one(struct vcpu *vcpu) +{ + struct vm *vm = vcpu->vm; + int vcpuid; + + if (vm->rendezvous_func == NULL) + return; + vcpu_unlock(vcpu); + mtx_lock(&vm->rendezvous_mtx); + vcpuid = vcpu->vcpuid; + if (vm->rendezvous_func != NULL && + CPU_ISSET(vcpuid, &vm->rendezvous_req_cpus) && + !CPU_ISSET(vcpuid, &vm->rendezvous_done_cpus)) { + VMM_CTR0(vcpu, "Calling rendezvous func"); + (*vm->rendezvous_func)(vcpu, vm->rendezvous_arg); + CPU_SET(vcpuid, &vm->rendezvous_done_cpus); + wakeup(&vm->rendezvous_func); + } + mtx_unlock(&vm->rendezvous_mtx); + vcpu_lock(vcpu); +} + static int vm_handle_rendezvous(struct vcpu *vcpu) { struct vm *vm = vcpu->vm; struct thread *td; - int error, vcpuid; + struct vcpu *vcpu1; + int error, i, vcpuid; error = 0; vcpuid = vcpu->vcpuid; @@ -1423,7 +1451,8 @@ mtx_lock(&vm->rendezvous_mtx); while (vm->rendezvous_func != NULL) { /* 'rendezvous_req_cpus' must be a subset of 'active_cpus' */ - CPU_AND(&vm->rendezvous_req_cpus, &vm->rendezvous_req_cpus, &vm->active_cpus); + CPU_AND(&vm->rendezvous_req_cpus, &vm->rendezvous_req_cpus, + &vm->active_cpus); if (CPU_ISSET(vcpuid, &vm->rendezvous_req_cpus) && !CPU_ISSET(vcpuid, &vm->rendezvous_done_cpus)) { @@ -1438,7 +1467,14 @@ wakeup(&vm->rendezvous_func); break; } + VMM_CTR0(vcpu, "Wait for rendezvous completion"); + CPU_FOREACH_ISSET(i, &vm->rendezvous_req_cpus) { + vcpu1 = vm_vcpu(vm, i); + if (vcpu1->state != VCPU_IDLE && + vcpu1->state != VCPU_RUNNING) + wakeup(&vcpu1->state); + } mtx_sleep(&vm->rendezvous_func, &vm->rendezvous_mtx, 0, "vmrndv", hz); if (td_ast_pending(td, TDA_SUSPEND)) {