Page MenuHomeFreeBSD

D37390.id113176.diff
No OneTemporary

D37390.id113176.diff

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);
/*

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 9, 4:15 AM (20 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28535472
Default Alt Text
D37390.id113176.diff (2 KB)

Event Timeline