VirtualBox

Ignore:
Timestamp:
Apr 15, 2009 8:59:03 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
45983
Message:

Runtime/R0/FreeBSD: Implement method to map kernel memory into user space

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c

    r14824 r18920  
    4444#include "internal/memobj.h"
    4545
    46 
    4746/*******************************************************************************
    4847*   Structures and Typedefs                                                    *
     
    137136        case RTR0MEMOBJTYPE_MAPPING:
    138137        {
    139             /** @todo Figure out mapping... */
     138            vm_map_t pMap = kernel_map;
     139
     140            /* vm_map_remove will unmap the pages we inserted with pmap_enter */
     141            AssertMsg(pMemFreeBSD->pMappingObject != NULL, ("MappingObject is NULL\n"));
     142            if (pMemFreeBSD->Core.u.Mapping.R0Process != NIL_RTR0PROCESS)
     143                pMap = &((struct proc *)pMemFreeBSD->Core.u.Mapping.R0Process)->p_vmspace->vm_map;
     144
     145            rc = vm_map_remove(pMap,
     146                                (vm_offset_t)pMemFreeBSD->Core.pv,
     147                                (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeBSD->Core.cb);
     148            AssertMsg(rc == KERN_SUCCESS, ("%#x", rc));
     149            break;
    140150        }
    141151
     
    148158            return VERR_INTERNAL_ERROR;
    149159    }
    150 
    151     Assert(!pMemFreeBSD->pMappingObject);
    152160
    153161    return VINF_SUCCESS;
     
    212220                         MapAddress + cb);
    213221        }
    214         else
    215             vm_object_deallocate(pMemFreeBSD->pObject);
    216222        rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
    217223    }
     
    344350     */
    345351    rc = vm_map_wire(&((struct proc *)R0Process)->p_vmspace->vm_map, /* the map */
    346                      (vm_offset_t)R3Ptr,                            /* start */
    347                      (vm_offset_t)R3Ptr + cb,                       /* end */
    348                      VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES);     /* flags - SYSTEM? */
     352                     (vm_offset_t)R3Ptr,                             /* start */
     353                     (vm_offset_t)R3Ptr + cb,                        /* end */
     354                     VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);        /* flags */
    349355    if (rc == KERN_SUCCESS)
    350356    {
     
    415421        vm_offset_t MapAddress = pvFixed != (void *)-1
    416422                               ? (vm_offset_t)pvFixed
    417                                : vm_map_min(kernel_map);
     423                               : vm_map_min(pMap);
    418424        if (pvFixed)
    419425            vm_map_remove(pMap,
     
    429435                         VM_PROT_NONE,                  /* protection */
    430436                         VM_PROT_ALL,                   /* max(_prot) ?? */
    431                          FALSE);                        /* cow (copy-on-write) */
     437                         0);                            /* cow (copy-on-write) */
    432438        if (rc == KERN_SUCCESS)
    433439        {
     
    543549}
    544550
    545 
     551/* see http://markmail.org/message/udhq33tefgtyfozs */
    546552int rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
    547553{
     
    549555    AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
    550556
    551 #if 0
    552557    int rc;
    553     void *pvR0;
    554     void *pvR3 = NULL;
    555     PRTR0MEMOBJFREEBSD pMemToMapOs2 = (PRTR0MEMOBJFREEBSD)pMemToMap;
    556     switch (pMemToMapOs2->Core.enmType)
     558    vm_object_t pObjectToMap = ((PRTR0MEMOBJFREEBSD)pMemToMap)->pObject;
     559    struct proc   *pProc     = (struct proc *)R0Process;
     560    struct vm_map *pProcMap  = &pProc->p_vmspace->vm_map;
     561    vm_offset_t AddrR3 = 0;
     562    vm_prot_t   ProtectionFlags = 0;
     563
     564    if ((fProt & RTMEM_PROT_NONE) == RTMEM_PROT_NONE)
     565        ProtectionFlags = VM_PROT_NONE;
     566    if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ)
     567        ProtectionFlags |= VM_PROT_READ;
     568    if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE)
     569        ProtectionFlags |= VM_PROT_WRITE;
     570    if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC)
     571        ProtectionFlags |= VM_PROT_EXECUTE;
     572
     573    PROC_LOCK(pProc);
     574    AddrR3 = round_page((vm_offset_t)pProc->p_vmspace->vm_daddr + lim_max(pProc, RLIMIT_DATA));
     575    PROC_UNLOCK(pProc);
     576
     577    /*
     578     * Mapping into R3 is easy if the mem object has a associated VM object.
     579     * If there is not such an object we have to get it from the address.
     580     */
     581    if (!pObjectToMap)
     582    {
     583        vm_object_t pObjectNew = vm_object_allocate(OBJT_PHYS, pMemToMap->cb >> PAGE_SHIFT);
     584        if (pObjectNew)
     585        {
     586            /* Insert the object in the map. */
     587            rc = vm_map_find(pProcMap,              /* Map to insert the object in */
     588                             pObjectNew  ,          /* Object to map */
     589                             0,                     /* Start offset in the object */
     590                             &AddrR3,               /* Start address IN/OUT */
     591                             pMemToMap->cb,         /* Size of the mapping */
     592                             TRUE,                  /* Whether a suitable address should be searched for first */
     593                             ProtectionFlags,       /* protection flags */
     594                             VM_PROT_ALL,           /* Maximum protection flags */
     595                             0);                    /* Copy on write */
     596            if (rc == KERN_SUCCESS)
     597            {
     598                int            cPages = pMemToMap->cb >> PAGE_SHIFT;
     599                int            iPage;
     600                void          *AddrToMap    = pMemToMap->pv;
     601                pmap_t         pPhysicalMap = pProcMap->pmap;
     602                vm_offset_t    AddrR3Dest   = AddrR3;
     603
     604                /* Insert the memory page by page into the mapping. */
     605                for (iPage = 0; iPage < cPages; iPage++)
     606                {
     607                    vm_page_t Page = PHYS_TO_VM_PAGE(vtophys(AddrToMap));
     608
     609                    pmap_enter(pPhysicalMap, AddrR3Dest, Page, ProtectionFlags, TRUE);
     610                    AddrToMap   = (uint8_t *)AddrToMap + PAGE_SIZE;
     611                    AddrR3Dest += PAGE_SIZE;
     612                }
     613            }
     614            else
     615                vm_object_deallocate(pObjectNew);
     616        }
     617        else
     618        {
     619            AssertMsgFailed(("Could not allocate VM object\n"));
     620            rc = 1; /* @todo fix */
     621        }
     622    }
     623    else
     624    {
     625        /*
     626         * Reference the object. If this isn't done the object will removed from kernel space
     627         * if the mapping is destroyed.
     628         */
     629        vm_object_reference(pObjectToMap);
     630
     631        rc = vm_map_find(pProcMap,              /* Map to insert the object in */
     632                         pObjectToMap,          /* Object to map */
     633                         0,                     /* Start offset in the object */
     634                         &AddrR3,               /* Start address IN/OUT */
     635                         pMemToMap->cb,         /* Size of the mapping */
     636                         TRUE,                  /* Whether a suitable address should be searched for first */
     637                         ProtectionFlags,       /* protection flags */
     638                         VM_PROT_ALL,           /* Maximum protection flags */
     639                         0);                    /* Copy on write */
     640    }
     641
     642    if (rc == KERN_SUCCESS)
    557643    {
    558644        /*
    559          * These has kernel mappings.
     645         * Create a mapping object for it.
    560646         */
     647        PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(RTR0MEMOBJFREEBSD),
     648                                                                           RTR0MEMOBJTYPE_MAPPING,
     649                                                                           (void *)AddrR3,
     650                                                                           pMemToMap->cb);
     651        if (pMemFreeBSD)
     652        {
     653            Assert(pMemFreeBSD->Core.pv == (void *)AddrR3);
     654            pMemFreeBSD->Core.u.Mapping.R0Process = R0Process;
     655            pMemFreeBSD->pMappingObject = pObjectToMap;
     656            *ppMem = &pMemFreeBSD->Core;
     657            return VINF_SUCCESS;
     658        }
     659
     660        rc = vm_map_remove(pProcMap, ((vm_offset_t)AddrR3), ((vm_offset_t)AddrR3) + pMemToMap->cb);
     661        AssertMsg(rc == KERN_SUCCESS, ("Deleting mapping failed\n"));
     662    }
     663
     664    if (pObjectToMap)
     665        vm_object_deallocate(pObjectToMap);
     666
     667    return VERR_NO_MEMORY;
     668}
     669
     670
     671RTHCPHYS rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
     672{
     673    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)pMem;
     674
     675    switch (pMemFreeBSD->Core.enmType)
     676    {
     677        case RTR0MEMOBJTYPE_LOCK:
     678        {
     679            if (    pMemFreeBSD->Core.u.Lock.R0Process != NIL_RTR0PROCESS
     680                &&  pMemFreeBSD->Core.u.Lock.R0Process != (RTR0PROCESS)curproc)
     681            {
     682                /* later */
     683                return NIL_RTHCPHYS;
     684            }
     685        }
    561686        case RTR0MEMOBJTYPE_PAGE:
    562         case RTR0MEMOBJTYPE_LOW:
     687        case RTR0MEMOBJTYPE_MAPPING:
     688        {
     689            uint8_t *pb = (uint8_t *)pMemFreeBSD->Core.pv + ((size_t)iPage << PAGE_SHIFT);
     690            return vtophys(pb);
     691        }
     692
    563693        case RTR0MEMOBJTYPE_CONT:
    564             pvR0 = pMemToMapOs2->Core.pv;
    565             break;
     694            return pMemFreeBSD->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
    566695
    567696        case RTR0MEMOBJTYPE_PHYS:
    568             pvR0 = pMemToMapOs2->Core.pv;
    569 #if 0/* this is wrong. */
    570             if (!pvR0)
    571             {
    572                 /* no ring-0 mapping, so allocate a mapping in the process. */
    573                 AssertMsgReturn(uAlignment == PAGE_SIZE, ("%#zx\n", uAlignment), VERR_NOT_SUPPORTED);
    574                 AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED);
    575                 Assert(!pMemToMapOs2->Core.u.Phys.fAllocated);
    576                 ULONG ulPhys = pMemToMapOs2->Core.u.Phys.PhysBase;
    577                 rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS | VMDHA_PROCESS, &pvR3, (PPVOID)&ulPhys, NULL);
    578                 if (rc)
    579                     return RTErrConvertFromOS2(rc);
    580             }
    581             break;
    582 #endif
    583             return VERR_NOT_SUPPORTED;
    584 
    585         case RTR0MEMOBJTYPE_LOCK:
    586             if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
    587                 return VERR_NOT_SUPPORTED; /** @todo implement this... */
    588             pvR0 = pMemToMapOs2->Core.pv;
    589             break;
     697            return pMemFreeBSD->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
    590698
    591699        case RTR0MEMOBJTYPE_PHYS_NC:
    592700        case RTR0MEMOBJTYPE_RES_VIRT:
    593         case RTR0MEMOBJTYPE_MAPPING:
    594         default:
    595             AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType));
    596             return VERR_INTERNAL_ERROR;
    597     }
    598 
    599     /*
    600      * Map the ring-0 memory into the current process.
    601      */
    602     if (!pvR3)
    603     {
    604         Assert(pvR0);
    605         ULONG flFlags = 0;
    606         if (uAlignment == PAGE_SIZE)
    607             flFlags |= VMDHGP_4MB;
    608         if (fProt & RTMEM_PROT_WRITE)
    609             flFlags |= VMDHGP_WRITE;
    610         rc = RTR0Os2DHVMGlobalToProcess(flFlags, pvR0, pMemToMapOs2->Core.cb, &pvR3);
    611         if (rc)
    612             return RTErrConvertFromOS2(rc);
    613     }
    614     Assert(pvR3);
    615 
    616     /*
    617      * Create a mapping object for it.
    618      */
    619     PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING, pvR3, pMemToMapOs2->Core.cb);
    620     if (pMemFreeBSD)
    621     {
    622         Assert(pMemFreeBSD->Core.pv == pvR3);
    623         pMemFreeBSD->Core.u.Mapping.R0Process = R0Process;
    624         *ppMem = &pMemFreeBSD->Core;
    625         return VINF_SUCCESS;
    626     }
    627     KernVMFree(pvR3);
    628     return VERR_NO_MEMORY;
    629 #endif
    630     return VERR_NOT_IMPLEMENTED;
    631 }
    632 
    633 
    634 RTHCPHYS rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
    635 {
    636     PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)pMem;
    637 
    638     switch (pMemFreeBSD->Core.enmType)
    639     {
    640         case RTR0MEMOBJTYPE_LOCK:
    641         {
    642             if (    pMemFreeBSD->Core.u.Lock.R0Process != NIL_RTR0PROCESS
    643                 &&  pMemFreeBSD->Core.u.Lock.R0Process != (RTR0PROCESS)curproc)
    644             {
    645                 /* later */
    646                 return NIL_RTHCPHYS;
    647             }
    648         }
    649         case RTR0MEMOBJTYPE_PAGE:
    650         {
    651             uint8_t *pb = (uint8_t *)pMemFreeBSD->Core.pv + ((size_t)iPage << PAGE_SHIFT);
    652             return vtophys(pb);
    653         }
    654 
    655         case RTR0MEMOBJTYPE_CONT:
    656             return pMemFreeBSD->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
    657 
    658         case RTR0MEMOBJTYPE_PHYS:
    659             return pMemFreeBSD->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
    660 
    661         case RTR0MEMOBJTYPE_PHYS_NC:
    662         case RTR0MEMOBJTYPE_RES_VIRT:
    663         case RTR0MEMOBJTYPE_MAPPING:
    664701        case RTR0MEMOBJTYPE_LOW:
    665702        default:
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette