vmm: merge VMX and SVM vm initialization functions.
authordv <dv@openbsd.org>
Fri, 3 May 2024 13:48:29 +0000 (13:48 +0000)
committerdv <dv@openbsd.org>
Fri, 3 May 2024 13:48:29 +0000 (13:48 +0000)
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
sys/arch/amd64/amd64/vmm_machdep.c

index 4d86cb3..c66389d 100644 (file)
@@ -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
index 9338b96..b2b7c34 100644 (file)
@@ -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 <mlarkin@openbsd.org>
  *
@@ -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)
 {