untrusted comment: verify with openbsd-72-base.pub
RWQTKNnK3CZZ8B1toOWEoA+11dKuYC03jB4lL+9fnaHBt/kvISDdY5NQFdEruFEWsQivSzNNs9DU+wiax/1VNAWXot1VnOlkqgw=
OpenBSD 7.2 errata 006, November 26, 2022:
Incorrect reference counting and locking caused a vmm(4) performance
regression.
Apply by doing:
signify -Vep /etc/signify/openbsd-72-base.pub -x 006_vmm.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install a new kernel:
KK=`sysctl -n kern.osversion | cut -d# -f1`
cd /usr/src/sys/arch/`machine`/compile/$KK
make obj
make config
make
make install
Index: sys/arch/amd64/amd64/vmm.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/vmm.c,v
diff -u -p -r1.323 vmm.c
--- sys/arch/amd64/amd64/vmm.c 7 Sep 2022 18:44:09 -0000 1.323
+++ sys/arch/amd64/amd64/vmm.c 15 Nov 2022 22:17:48 -0000
@@ -840,11 +840,9 @@ vm_resetcpu(struct vm_resetcpu_params *v
}
rw_enter_write(&vcpu->vc_lock);
-
- if (vcpu->vc_state != VCPU_STATE_STOPPED ||
- refcnt_shared(&vcpu->vc_refcnt)) {
+ if (vcpu->vc_state != VCPU_STATE_STOPPED)
ret = EBUSY;
- } else {
+ else {
if (vcpu_reset_regs(vcpu, &vrp->vrp_init_state)) {
printf("%s: failed\n", __func__);
#ifdef VMM_DEBUG
@@ -896,9 +894,7 @@ vm_intr_pending(struct vm_intr_params *v
goto out;
}
- rw_enter_write(&vcpu->vc_lock);
vcpu->vc_intr = vip->vip_intr;
- rw_exit_write(&vcpu->vc_lock);
refcnt_rele_wake(&vcpu->vc_refcnt);
out:
@@ -1784,7 +1780,6 @@ vm_create(struct vm_create_params *vcp,
for (i = 0; i < vcp->vcp_ncpus; i++) {
vcpu = pool_get(&vcpu_pool, PR_WAITOK | PR_ZERO);
refcnt_init(&vcpu->vc_refcnt);
- refcnt_rele(&vcpu->vc_refcnt);
vcpu->vc_parent = vm;
if ((ret = vcpu_init(vcpu)) != 0) {
@@ -1794,6 +1789,7 @@ vm_create(struct vm_create_params *vcp,
}
vcpu->vc_id = vm->vm_vcpu_ct;
vm->vm_vcpu_ct++;
+ /* Publish vcpu to list, inheriting the reference. */
SLIST_INSERT_HEAD(&vm->vm_vcpu_list, vcpu, vc_vcpu_link);
}
@@ -1816,12 +1812,13 @@ vm_create(struct vm_create_params *vcp,
vm->vm_id = vmm_softc->vm_idx;
vcp->vcp_id = vm->vm_id;
- /* Publish the vm into the list and update list count. */
- SLIST_INSERT_HEAD(&vmm_softc->vm_list, vm, vm_link);
+ /* Update list counts. */
vmm_softc->vm_ct++;
vmm_softc->vcpu_ct += vm->vm_vcpu_ct;
- refcnt_rele(&vm->vm_refcnt); /* No need for wake. */
+ /* Publish vm into list, inheriting the reference. */
+ SLIST_INSERT_HEAD(&vmm_softc->vm_list, vm, vm_link);
+
rw_exit_write(&vmm_softc->vm_lock);
return (0);
@@ -4063,9 +4060,7 @@ vm_teardown(struct vm **target)
/* Free VCPUs */
rw_enter_write(&vm->vm_vcpu_lock);
SLIST_FOREACH_SAFE(vcpu, &vm->vm_vcpu_list, vc_vcpu_link, tmp) {
- refcnt_take(&vcpu->vc_refcnt);
refcnt_finalize(&vcpu->vc_refcnt, "vcputeardown");
-
SLIST_REMOVE(&vm->vm_vcpu_list, vcpu, vcpu, vc_vcpu_link);
vcpu_deinit(vcpu);
@@ -4475,6 +4470,7 @@ vm_terminate(struct vm_terminate_params
rw_enter_write(&vmm_softc->vm_lock);
SLIST_REMOVE(&vmm_softc->vm_list, vm, vm, vm_link);
rw_exit_write(&vmm_softc->vm_lock);
+ refcnt_rele_wake(&vm->vm_refcnt); /* Drop list reference. */
vm_id = vm->vm_id;
nvcpu = vm->vm_vcpu_ct;