From 22ee75e59c47eb84dd91ce5d6083aec95c19845e Mon Sep 17 00:00:00 2001 From: dv Date: Fri, 3 May 2024 13:48:29 +0000 Subject: [PATCH] vmm: merge VMX and SVM vm initialization functions. They do the same uvmspace/pmap dance, so just reduce to a single function. Kernel lock is moved to the uvmspace_free call. In addition, we should be using the pmap mutex in pmap_convert, called by the vm initialization routine. ok mlarkin@ --- sys/arch/amd64/amd64/pmap.c | 4 +- sys/arch/amd64/amd64/vmm_machdep.c | 119 +++++------------------------ 2 files changed, 23 insertions(+), 100 deletions(-) diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 4d86cb3f20d..c66389d0f19 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.166 2024/04/03 18:43:32 miod Exp $ */ +/* $OpenBSD: pmap.c,v 1.167 2024/05/03 13:48:29 dv Exp $ */ /* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */ /* @@ -3119,6 +3119,7 @@ pmap_convert(struct pmap *pmap, int mode) { pt_entry_t *pte; + mtx_enter(&pmap->pm_mtx); pmap->pm_type = mode; if (mode == PMAP_TYPE_EPT) { @@ -3132,6 +3133,7 @@ pmap_convert(struct pmap *pmap, int mode) pmap->pm_pdir_intel = NULL; } } + mtx_leave(&pmap->pm_mtx); } #ifdef MULTIPROCESSOR diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c index 9338b96b02f..b2b7c340163 100644 --- a/sys/arch/amd64/amd64/vmm_machdep.c +++ b/sys/arch/amd64/amd64/vmm_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm_machdep.c,v 1.25 2024/04/29 14:47:05 dv Exp $ */ +/* $OpenBSD: vmm_machdep.c,v 1.26 2024/05/03 13:48:29 dv Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -91,10 +91,6 @@ int vcpu_run_svm(struct vcpu *, struct vm_run_params *); void vcpu_deinit(struct vcpu *); void vcpu_deinit_svm(struct vcpu *); void vcpu_deinit_vmx(struct vcpu *); -int vm_impl_init(struct vm *, struct proc *); -int vm_impl_init_vmx(struct vm *, struct proc *); -int vm_impl_init_svm(struct vm *, struct proc *); -void vm_impl_deinit(struct vm *); int vcpu_vmx_check_cap(struct vcpu *, uint32_t, uint32_t, int); int vcpu_vmx_compute_ctrl(uint64_t, uint16_t, uint32_t, uint32_t, uint32_t *); int vmx_get_exit_info(uint64_t *, uint64_t *); @@ -1205,9 +1201,9 @@ vmx_remote_vmclear(struct cpu_info *ci, struct vcpu *vcpu) #endif /* MULTIPROCESSOR */ /* - * vm_impl_init_vmx + * vm_impl_init * - * Intel VMX specific VM initialization routine + * VM address space initialization routine * * Parameters: * vm: the VM being initialized @@ -1215,75 +1211,29 @@ vmx_remote_vmclear(struct cpu_info *ci, struct vcpu *vcpu) * * Return values: * 0: the initialization was successful + * EINVAL: unsupported vmm mode * ENOMEM: the initialization failed (lack of resources) */ int -vm_impl_init_vmx(struct vm *vm, struct proc *p) +vm_impl_init(struct vm *vm, struct proc *p) { - int i, ret; + int i, mode, ret; vaddr_t mingpa, maxgpa; struct vm_mem_range *vmr; - /* If not EPT, nothing to do here */ - if (vmm_softc->mode != VMM_MODE_EPT) - return (0); - - vmr = &vm->vm_memranges[0]; - mingpa = vmr->vmr_gpa; - vmr = &vm->vm_memranges[vm->vm_nmemranges - 1]; - maxgpa = vmr->vmr_gpa + vmr->vmr_size; - - /* - * uvmspace_alloc (currently) always returns a valid vmspace - */ - vm->vm_vmspace = uvmspace_alloc(mingpa, maxgpa, TRUE, FALSE); - vm->vm_map = &vm->vm_vmspace->vm_map; - - /* Map the new map with an anon */ - DPRINTF("%s: created vm_map @ %p\n", __func__, vm->vm_map); - for (i = 0; i < vm->vm_nmemranges; i++) { - vmr = &vm->vm_memranges[i]; - ret = uvm_share(vm->vm_map, vmr->vmr_gpa, - PROT_READ | PROT_WRITE | PROT_EXEC, - &p->p_vmspace->vm_map, vmr->vmr_va, vmr->vmr_size); - if (ret) { - printf("%s: uvm_share failed (%d)\n", __func__, ret); - /* uvmspace_free calls pmap_destroy for us */ - uvmspace_free(vm->vm_vmspace); - vm->vm_vmspace = NULL; - return (ENOMEM); - } + /* If not EPT or RVI, nothing to do here */ + switch (vmm_softc->mode) { + case VMM_MODE_EPT: + mode = PMAP_TYPE_EPT; + break; + case VMM_MODE_RVI: + mode = PMAP_TYPE_RVI; + break; + default: + printf("%s: invalid vmm mode %d\n", __func__, vmm_softc->mode); + return (EINVAL); } - pmap_convert(vm->vm_map->pmap, PMAP_TYPE_EPT); - - return (0); -} - -/* - * vm_impl_init_svm - * - * AMD SVM specific VM initialization routine - * - * Parameters: - * vm: the VM being initialized - * p: vmd process owning the VM - * - * Return values: - * 0: the initialization was successful - * ENOMEM: the initialization failed (lack of resources) - */ -int -vm_impl_init_svm(struct vm *vm, struct proc *p) -{ - int i, ret; - vaddr_t mingpa, maxgpa; - struct vm_mem_range *vmr; - - /* If not RVI, nothing to do here */ - if (vmm_softc->mode != VMM_MODE_RVI) - return (0); - vmr = &vm->vm_memranges[0]; mingpa = vmr->vmr_gpa; vmr = &vm->vm_memranges[vm->vm_nmemranges - 1]; @@ -1305,48 +1255,19 @@ vm_impl_init_svm(struct vm *vm, struct proc *p) if (ret) { printf("%s: uvm_share failed (%d)\n", __func__, ret); /* uvmspace_free calls pmap_destroy for us */ + KERNEL_LOCK(); uvmspace_free(vm->vm_vmspace); vm->vm_vmspace = NULL; + KERNEL_UNLOCK(); return (ENOMEM); } } - /* Convert pmap to RVI */ - pmap_convert(vm->vm_map->pmap, PMAP_TYPE_RVI); + pmap_convert(vm->vm_map->pmap, mode); return (0); } -/* - * vm_impl_init - * - * Calls the architecture-specific VM init routine - * - * Parameters: - * vm: the VM being initialized - * p: vmd process owning the VM - * - * Return values (from architecture-specific init routines): - * 0: the initialization was successful - * ENOMEM: the initialization failed (lack of resources) - */ -int -vm_impl_init(struct vm *vm, struct proc *p) -{ - int ret; - - KERNEL_LOCK(); - if (vmm_softc->mode == VMM_MODE_EPT) - ret = vm_impl_init_vmx(vm, p); - else if (vmm_softc->mode == VMM_MODE_RVI) - ret = vm_impl_init_svm(vm, p); - else - panic("%s: unknown vmm mode: %d", __func__, vmm_softc->mode); - KERNEL_UNLOCK(); - - return (ret); -} - void vm_impl_deinit(struct vm *vm) { -- 2.20.1