diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -313,10 +313,9 @@ #endif /* _SYS__CPUSET_H_ */ static __inline int -vcpu_rendezvous_pending(struct vm_eventinfo *info) +vcpu_rendezvous_pending(int vcpuid, struct vm_eventinfo *info) { - - return (*((uintptr_t *)(info->rptr)) != 0); + return CPU_ISSET(vcpuid, (cpuset_t *)info->rptr); } static __inline int diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c --- a/sys/amd64/vmm/amd/svm.c +++ b/sys/amd64/vmm/amd/svm.c @@ -2066,7 +2066,7 @@ break; } - if (vcpu_rendezvous_pending(evinfo)) { + if (vcpu_rendezvous_pending(vcpu, evinfo)) { enable_gintr(); vm_exit_rendezvous(vm, vcpu, state->rip); break; diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c --- a/sys/amd64/vmm/intel/vmx.c +++ b/sys/amd64/vmm/intel/vmx.c @@ -3065,7 +3065,7 @@ break; } - if (vcpu_rendezvous_pending(evinfo)) { + if (vcpu_rendezvous_pending(vcpu, evinfo)) { enable_intr(); vm_exit_rendezvous(vmx->vm, vcpu, rip); break; 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 @@ -1325,6 +1325,20 @@ &vm->rendezvous_done_cpus) == 0) { VCPU_CTR0(vm, vcpuid, "Rendezvous completed"); vm->rendezvous_func = NULL; + /* + * Clear the rendezvous_req_cpus to avoid that any vcpu + * tries to reenter the rendezvous. We don't need any + * memory barrier/order here because: + * 1. The field is cleared. So, no additional vcpu will + * try to enter the rendezvous. + * 2. All vcpus that take part in the rendezvous are + * sleeping at mtx_sleep a few lines below. + * 3. This code is protected by rendezvous_mtx which + * ensures that all vcpu taking part at the + * rendezvous will see an empty rendezvous_req_cpus + * when they exit the rendezvous. + */ + CPU_ZERO(&vm->rendezvous_req_cpus); wakeup(&vm->rendezvous_func); break; } @@ -1755,7 +1769,7 @@ pmap = vmspace_pmap(vm->vmspace); vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; - evinfo.rptr = &vm->rendezvous_func; + evinfo.rptr = &vm->rendezvous_req_cpus; evinfo.sptr = &vm->suspend; evinfo.iptr = &vcpu->reqidle; restart: @@ -2616,10 +2630,17 @@ "rendezvous is still in progress")); RENDEZVOUS_CTR0(vm, vcpuid, "Initiating rendezvous"); - vm->rendezvous_req_cpus = dest; CPU_ZERO(&vm->rendezvous_done_cpus); vm->rendezvous_arg = arg; vm->rendezvous_func = func; + /* + * If a vcpu sees that it's vcpu bit is set in rendezvous_req_cpus, + * it'll try to enter the rendezvous code. Therefore, make sure that all + * rendezvous parameter are seen by all vcpus before setting + * rendezvous_req_cpus. + */ + rmb(); + vm->rendezvous_req_cpus = dest; mtx_unlock(&vm->rendezvous_mtx); /*