Index: amd64/vmm.c =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/vmm.c,v retrieving revision 1.324 diff -u -p -r1.324 vmm.c --- amd64/vmm.c 1 Nov 2022 01:01:14 -0000 1.324 +++ amd64/vmm.c 6 Nov 2022 12:05:30 -0000 @@ -79,7 +79,6 @@ void *l1tf_flush_region; * I immutable after create * K kernel lock * r reference count - * v vcpu list rwlock (vm_vcpu_list) * V vmm_softc's vm_lock */ struct vm { @@ -505,9 +504,6 @@ vmm_quiesce_vmx(void) /* Iterate over each vm... */ SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link) { - if ((err = rw_enter(&vm->vm_vcpu_lock, RW_READ | RW_NOSLEEP))) - break; - /* Iterate over each vcpu... */ SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { err = rw_enter(&vcpu->vc_lock, RW_WRITE | RW_NOSLEEP); @@ -550,7 +546,6 @@ vmm_quiesce_vmx(void) DPRINTF("%s: cleared vcpu %d for vm %d\n", __func__, vcpu->vc_id, vm->vm_id); } - rw_exit_read(&vm->vm_vcpu_lock); if (err) break; } @@ -786,19 +781,14 @@ vm_find_vcpu(struct vm *vm, uint32_t id) if (vm == NULL) return NULL; - rw_enter_read(&vm->vm_vcpu_lock); SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { - refcnt_take(&vcpu->vc_refcnt); if (vcpu->vc_id == id) - break; - refcnt_rele_wake(&vcpu->vc_refcnt); + return (vcpu); } - rw_exit_read(&vm->vm_vcpu_lock); - return vcpu; + return (NULL); } - /* * vm_resetcpu * @@ -841,10 +831,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 @@ -855,8 +844,6 @@ vm_resetcpu(struct vm_resetcpu_params *v } rw_exit_write(&vcpu->vc_lock); out: - if (vcpu != NULL) - refcnt_rele_wake(&vcpu->vc_refcnt); refcnt_rele_wake(&vm->vm_refcnt); return (ret); @@ -900,7 +887,6 @@ vm_intr_pending(struct vm_intr_params *v vcpu->vc_intr = vip->vip_intr; rw_exit_write(&vcpu->vc_lock); - refcnt_rele_wake(&vcpu->vc_refcnt); out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); @@ -935,7 +921,6 @@ vm_rwvmparams(struct vm_rwvmparams_param return (error); vcpu = vm_find_vcpu(vm, vpp->vpp_vcpu_id); - if (vcpu == NULL) { ret = ENOENT; goto out; @@ -954,7 +939,6 @@ vm_rwvmparams(struct vm_rwvmparams_param vmm_init_pvclock(vcpu, vpp->vpp_pvclock_system_gpa); } } - refcnt_rele_wake(&vcpu->vc_refcnt); out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); @@ -1015,7 +999,6 @@ vm_rwregs(struct vm_rwregs_params *vrwp, ret = EINVAL; } rw_exit_write(&vcpu->vc_lock); - refcnt_rele_wake(&vcpu->vc_refcnt); out: refcnt_rele_wake(&vm->vm_refcnt); return (ret); @@ -1183,7 +1166,6 @@ vm_mprotect_ept(struct vm_mprotect_ept_p out: if (vcpu != NULL) { rw_exit_write(&vcpu->vc_lock); - refcnt_rele_wake(&vcpu->vc_refcnt); } out_nolock: refcnt_rele_wake(&vm->vm_refcnt); @@ -1352,7 +1334,6 @@ vm_find(uint32_t id, struct vm **res) rw_enter_read(&vmm_softc->vm_lock); SLIST_FOREACH(vm, &vmm_softc->vm_list, vm_link) { - refcnt_take(&vm->vm_refcnt); if (vm->vm_id == id) { /* * In the pledged VM process, only allow to find @@ -1365,12 +1346,12 @@ vm_find(uint32_t id, struct vm **res) (vm->vm_creator_pid != p->p_p->ps_pid)) ret = EPERM; else { + refcnt_take(&vm->vm_refcnt); *res = vm; ret = 0; } break; } - refcnt_rele_wake(&vm->vm_refcnt); } rw_exit_read(&vmm_softc->vm_lock); @@ -1759,10 +1740,8 @@ vm_create(struct vm_create_params *vcp, /* Instantiate and configure the new vm. */ vm = pool_get(&vm_pool, PR_WAITOK | PR_ZERO); - refcnt_init(&vm->vm_refcnt); /* Do not release yet. */ SLIST_INIT(&vm->vm_vcpu_list); - rw_init(&vm->vm_vcpu_lock, "vcpu_list"); vm->vm_creator_pid = p->p_p->ps_pid; vm->vm_nmemranges = vcp->vcp_nmemranges; @@ -1783,8 +1762,6 @@ vm_create(struct vm_create_params *vcp, /* Initialize each VCPU defined in '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) { @@ -1817,11 +1794,11 @@ vm_create(struct vm_create_params *vcp, vcp->vcp_id = vm->vm_id; /* Publish the vm into the list and update list count. */ + refcnt_init(&vm->vm_refcnt); SLIST_INSERT_HEAD(&vmm_softc->vm_list, vm, vm_link); vmm_softc->vm_ct++; vmm_softc->vcpu_ct += vm->vm_vcpu_ct; - refcnt_rele(&vm->vm_refcnt); /* No need for wake. */ rw_exit_write(&vmm_softc->vm_lock); return (0); @@ -4062,21 +4039,14 @@ vm_teardown(struct vm **target) KERNEL_ASSERT_UNLOCKED(); - refcnt_finalize(&vm->vm_refcnt, "vmteardown"); - /* 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); pool_put(&vcpu_pool, vcpu); nvcpu++; } - rw_exit_write(&vm->vm_vcpu_lock); vm_impl_deinit(vm); @@ -4401,19 +4371,15 @@ vm_get_info(struct vm_info_params *vip) out[i].vir_creator_pid = vm->vm_creator_pid; strlcpy(out[i].vir_name, vm->vm_name, VMM_MAX_NAME_LEN); - rw_enter_read(&vm->vm_vcpu_lock); for (j = 0; j < vm->vm_vcpu_ct; j++) { out[i].vir_vcpu_state[j] = VCPU_STATE_UNKNOWN; SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { - refcnt_take(&vcpu->vc_refcnt); if (vcpu->vc_id == j) out[i].vir_vcpu_state[j] = vcpu->vc_state; - refcnt_rele_wake(&vcpu->vc_refcnt); } } - rw_exit_read(&vm->vm_vcpu_lock); refcnt_rele_wake(&vm->vm_refcnt); i++; @@ -4458,10 +4424,22 @@ vm_terminate(struct vm_terminate_params if (error) return (error); + /* Pop the vm out of the global vm list. */ + rw_enter_write(&vmm_softc->vm_lock); + SLIST_REMOVE(&vmm_softc->vm_list, vm, vm, vm_link); + rw_exit_write(&vmm_softc->vm_lock); + + /* Drop the vm_list reference */ + if (refcnt_rele(&vm->vm_refcnt)) { + panic("%s: vm %d(%p) vm_list refcnt drop was the last", + __func__, vm->vm_id, vm); + } + + /* Wait for everything else to get off the VM */ + refcnt_finalize(&vm->vm_refcnt, "vmterm"); + /* Stop all vcpu's for the vm. */ - rw_enter_read(&vm->vm_vcpu_lock); SLIST_FOREACH(vcpu, &vm->vm_vcpu_list, vc_vcpu_link) { - refcnt_take(&vcpu->vc_refcnt); do { old = vcpu->vc_state; if (old == VCPU_STATE_RUNNING) @@ -4471,14 +4449,7 @@ vm_terminate(struct vm_terminate_params else /* must be REQTERM or TERMINATED */ break; } while (old != atomic_cas_uint(&vcpu->vc_state, old, next)); - refcnt_rele_wake(&vcpu->vc_refcnt); } - rw_exit_read(&vm->vm_vcpu_lock); - - /* Pop the vm out of the global vm list. */ - rw_enter_write(&vmm_softc->vm_lock); - SLIST_REMOVE(&vmm_softc->vm_list, vm, vm, vm_link); - rw_exit_write(&vmm_softc->vm_lock); vm_id = vm->vm_id; nvcpu = vm->vm_vcpu_ct; @@ -4591,8 +4562,6 @@ vm_run(struct vm_run_params *vrp) out_unlock: rw_exit_write(&vcpu->vc_lock); out: - if (vcpu != NULL) - refcnt_rele_wake(&vcpu->vc_refcnt); refcnt_rele_wake(&vm->vm_refcnt); return (ret); } Index: include/vmmvar.h =================================================================== RCS file: /cvs/src/sys/arch/amd64/include/vmmvar.h,v retrieving revision 1.81 diff -u -p -r1.81 vmmvar.h --- include/vmmvar.h 1 Sep 2022 22:01:40 -0000 1.81 +++ include/vmmvar.h 6 Nov 2022 12:05:30 -0000 @@ -932,7 +932,6 @@ struct vcpu { uint8_t vc_virt_mode; /* [I] */ struct rwlock vc_lock; - struct refcnt vc_refcnt; /* [a] */ struct cpu_info *vc_last_pcpu; /* [v] */ struct vm_exit vc_exit; /* [v] */