From f38437abf72b4a234cf587af2819a5a5f8daa90d Mon Sep 17 00:00:00 2001 From: dv Date: Sun, 6 Nov 2022 19:00:37 +0000 Subject: [PATCH] vmm(4): allocate reference for vm and vcpu SLISTs Mischa Peters reported a performance regression in 7.2 when hosting numerous guests under vmm(4). While iterating through the list of vms during servicing an ioctl, vmm was triggering excessive wakeup calls due to hitting zero refcnt. Much guidance from dlg@ and testing from Mischa. OK mlarkin@. --- sys/arch/amd64/amd64/vmm.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index ee06cb01451..d17038f0ed0 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.324 2022/11/01 01:01:14 cheloha Exp $ */ +/* $OpenBSD: vmm.c,v 1.325 2022/11/06 19:00:37 dv Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -840,11 +840,9 @@ vm_resetcpu(struct vm_resetcpu_params *vrp) } 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 @@ -1784,7 +1782,6 @@ vm_create(struct vm_create_params *vcp, struct proc *p) 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 +1791,7 @@ vm_create(struct vm_create_params *vcp, struct proc *p) } 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 +1814,13 @@ vm_create(struct vm_create_params *vcp, struct proc *p) 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); @@ -4067,9 +4066,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); @@ -4479,6 +4476,7 @@ vm_terminate(struct vm_terminate_params *vtp) 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; -- 2.20.1