VirtualBox

Changeset 39657 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Dec 19, 2011 6:34:13 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
75471
Message:

IPRT/FreeBSD: Rewrite of R0 memory objects handling, thanks to Andriy Gapon and Bernhard Froehlich

File:
1 edited

Legend:

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

    r39521 r39657  
    66/*
    77 * Copyright (c) 2007 knut st. osmundsen <[email protected]>
     8 * Copyright (c) 2011 Andriy Gapon <[email protected]>
    89 *
    910 * Permission is hereby granted, free of charge, to any person
     
    5455    /** The core structure. */
    5556    RTR0MEMOBJINTERNAL  Core;
    56     /** Type dependent data */
    57     union
    58     {
    59         /** Non physical memory allocations */
    60         struct
    61         {
    62             /** The VM object associated with the allocation. */
    63             vm_object_t         pObject;
    64         } NonPhys;
    65         /** Physical memory allocations */
    66         struct
    67         {
    68             /** Number of pages */
    69             uint32_t            cPages;
    70             /** Array of pages - variable */
    71             vm_page_t           apPages[1];
    72         } Phys;
    73     } u;
     57    /** The VM object associated with the allocation. */
     58    vm_object_t         pObject;
    7459} RTR0MEMOBJFREEBSD, *PRTR0MEMOBJFREEBSD;
    7560
    7661
    7762MALLOC_DEFINE(M_IPRTMOBJ, "iprtmobj", "IPRT - R0MemObj");
    78 
    79 
    8063
    8164/**
     
    126109    switch (pMemFreeBSD->Core.enmType)
    127110    {
     111        case RTR0MEMOBJTYPE_PAGE:
     112        case RTR0MEMOBJTYPE_LOW:
    128113        case RTR0MEMOBJTYPE_CONT:
    129             contigfree(pMemFreeBSD->Core.pv, pMemFreeBSD->Core.cb, M_IPRTMOBJ);
    130             break;
    131 
    132         case RTR0MEMOBJTYPE_PAGE:
    133114        {
    134115            rc = vm_map_remove(kernel_map,
     
    136117                                (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeBSD->Core.cb);
    137118            AssertMsg(rc == KERN_SUCCESS, ("%#x", rc));
    138 
    139             vm_page_lock_queues();
    140             for (uint32_t iPage = 0; iPage < pMemFreeBSD->u.Phys.cPages; iPage++)
    141             {
    142                 vm_page_t pPage = pMemFreeBSD->u.Phys.apPages[iPage];
    143                 vm_page_unwire(pPage, 0);
    144                 vm_page_free(pPage);
    145             }
    146             vm_page_unlock_queues();
    147119            break;
    148120        }
     
    166138        {
    167139            vm_map_t pMap = kernel_map;
    168             if (pMemFreeBSD->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
    169                 pMap = &((struct proc *)pMemFreeBSD->Core.u.Lock.R0Process)->p_vmspace->vm_map;
     140            if (pMemFreeBSD->Core.u.ResVirt.R0Process != NIL_RTR0PROCESS)
     141                pMap = &((struct proc *)pMemFreeBSD->Core.u.ResVirt.R0Process)->p_vmspace->vm_map;
    170142            rc = vm_map_remove(pMap,
    171143                               (vm_offset_t)pMemFreeBSD->Core.pv,
     
    181153            if (pMemFreeBSD->Core.u.Mapping.R0Process != NIL_RTR0PROCESS)
    182154                pMap = &((struct proc *)pMemFreeBSD->Core.u.Mapping.R0Process)->p_vmspace->vm_map;
    183 
    184155            rc = vm_map_remove(pMap,
    185156                               (vm_offset_t)pMemFreeBSD->Core.pv,
     
    192163        case RTR0MEMOBJTYPE_PHYS_NC:
    193164        {
     165            VM_OBJECT_LOCK(pMemFreeBSD->pObject);
     166            vm_page_t pPage = vm_page_find_least(pMemFreeBSD->pObject, 0);
    194167            vm_page_lock_queues();
    195             for (uint32_t iPage = 0; iPage < pMemFreeBSD->u.Phys.cPages; iPage++)
     168            for (vm_page_t pPage = vm_page_find_least(pMemFreeBSD->pObject, 0);
     169                 pPage != NULL;
     170                 pPage = vm_page_next(pPage))
    196171            {
    197                 vm_page_t pPage = pMemFreeBSD->u.Phys.apPages[iPage];
    198172                vm_page_unwire(pPage, 0);
    199                 vm_page_free(pPage);
    200173            }
    201174            vm_page_unlock_queues();
     175            VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
     176            vm_object_deallocate(pMemFreeBSD->pObject);
    202177            break;
    203178        }
    204179
    205 #ifdef USE_KMEM_ALLOC_ATTR
    206         case RTR0MEMOBJTYPE_LOW:
    207         {
    208             kmem_free(kernel_map, (vm_offset_t)pMemFreeBSD->Core.pv, pMemFreeBSD->Core.cb);
    209             break;
    210         }
    211 #else
    212         case RTR0MEMOBJTYPE_LOW: /* unused */
    213 #endif
    214180        default:
    215181            AssertMsgFailed(("enmType=%d\n", pMemFreeBSD->Core.enmType));
     
    221187
    222188
     189static vm_page_t rtR0MemObjFreeBSDContigPhysAllocHelper(vm_object_t pObject, vm_pindex_t iPIndex,
     190                                                        u_long cPages, vm_paddr_t VmPhysAddrHigh,
     191                                                        u_long uAlignment, bool fWire)
     192{
     193    vm_page_t pPages;
     194#if __FreeBSD_version > 1000000
     195    int fFlags = VM_ALLOC_INTERRUPT | VM_ALLOC_NOBUSY;
     196    if (fWire)
     197        fFlags |= VM_ALLOC_WIRED;
     198    VM_OBJECT_LOCK(pObject);
     199    pPages = vm_page_alloc_contig(pObject, iPIndex, fFlags, cPages, 0, VmPhysAddrHigh, uAlignment, 0, VM_MEMATTR_DEFAULT);
     200    VM_OBJECT_UNLOCK(pObject);
     201    return pPages;
     202#else
     203    pPages = vm_phys_alloc_contig(cPages, 0, VmPhysAddrHigh, uAlignment, 0);
     204    if (!pPages)
     205        return pPages;
     206    VM_OBJECT_LOCK(pObject);
     207    for (vm_pindex_t iPage = 0; iPage < cPages; iPage++)
     208    {
     209        vm_page_t pPage = pPages + iPage;
     210        vm_page_insert(pPage, pObject, iPIndex + iPage);
     211        pPage->valid = VM_PAGE_BITS_ALL;
     212        if (fWire)
     213        {
     214            pPage->wire_count = 1;
     215            atomic_add_int(&cnt.v_wire_count, 1);
     216        }
     217    }
     218    VM_OBJECT_UNLOCK(pObject);
     219    return pPages;
     220#endif
     221}
     222
     223static int rtR0MemObjFreeBSDPhysAllocHelper(vm_object_t pObject, u_long cPages,
     224                                            vm_paddr_t VmPhysAddrHigh, u_long uAlignment,
     225                                            bool fContiguous, bool fWire)
     226{
     227    if (fContiguous)
     228    {
     229        if (rtR0MemObjFreeBSDContigPhysAllocHelper(pObject, 0, cPages, VmPhysAddrHigh,
     230                                                   uAlignment, fWire) != NULL)
     231            return VINF_SUCCESS;
     232        else
     233            return VERR_NO_MEMORY;
     234    }
     235
     236    for (vm_pindex_t iPage = 0; iPage < cPages; iPage++)
     237    {
     238        vm_page_t pPage = rtR0MemObjFreeBSDContigPhysAllocHelper(pObject, iPage, 1, VmPhysAddrHigh,
     239                                                                 uAlignment, fWire);
     240        if (!pPage)
     241        {
     242            /* Free all allocated pages */
     243            VM_OBJECT_LOCK(pObject);
     244            while (iPage-- > 0)
     245            {
     246                pPage = vm_page_lookup(pObject, iPage);
     247                vm_page_lock_queues();
     248                if (fWire)
     249                    vm_page_unwire(pPage, 0);
     250                vm_page_free(pPage);
     251                vm_page_unlock_queues();
     252            }
     253            VM_OBJECT_UNLOCK(pObject);
     254            return VERR_NO_MEMORY;
     255        }
     256    }
     257    return VINF_SUCCESS;
     258}
     259
     260static int rtR0MemObjFreeBSDAllocHelper(PRTR0MEMOBJFREEBSD pMemFreeBSD, bool fExecutable,
     261                                        vm_paddr_t VmPhysAddrHigh, bool fContiguous)
     262{
     263    int rc;
     264    size_t cPages = atop(pMemFreeBSD->Core.cb);
     265
     266    pMemFreeBSD->pObject = vm_object_allocate(OBJT_PHYS, cPages);
     267    vm_offset_t MapAddress;
     268
     269    /* No additional object reference for auto-deallocation upon unmapping. */
     270    rc = vm_map_find(kernel_map, pMemFreeBSD->pObject, 0,
     271                     &MapAddress, pMemFreeBSD->Core.cb, VMFS_ANY_SPACE,
     272                     fExecutable ? VM_PROT_ALL : VM_PROT_RW, VM_PROT_ALL, 0);
     273
     274    if (rc == KERN_SUCCESS)
     275    {
     276        rc = rtR0MemObjFreeBSDPhysAllocHelper(pMemFreeBSD->pObject, cPages,
     277                                              VmPhysAddrHigh, PAGE_SIZE, fContiguous, false);
     278        if (RT_SUCCESS(rc)) {
     279            vm_map_wire(kernel_map, MapAddress, MapAddress + pMemFreeBSD->Core.cb,
     280                        VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES);
     281
     282            /* Store start address */
     283            pMemFreeBSD->Core.pv = (void *)MapAddress;
     284            return VINF_SUCCESS;
     285        }
     286
     287        vm_map_remove(kernel_map, MapAddress, MapAddress + pMemFreeBSD->Core.cb);
     288    }
     289    rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
     290
     291    vm_object_deallocate(pMemFreeBSD->pObject);
     292    rtR0MemObjDelete(&pMemFreeBSD->Core);
     293    return rc;
     294}
    223295DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
    224296{
    225     int rc;
    226     size_t cPages = cb >> PAGE_SHIFT;
    227 
    228     /* create the object. */
    229     PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJFREEBSD, u.Phys.apPages[cPages]),
     297    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
    230298                                                                       RTR0MEMOBJTYPE_PAGE, NULL, cb);
    231299    if (!pMemFreeBSD)
    232300        return VERR_NO_MEMORY;
    233301
    234     pMemFreeBSD->u.Phys.cPages = cPages;
    235 
    236     vm_offset_t MapAddress = vm_map_min(kernel_map);
    237     rc = vm_map_find(kernel_map,                /* map */
    238                      NULL,                      /* object */
    239                      0,                         /* offset */
    240                      &MapAddress,               /* addr (IN/OUT) */
    241                      cb,                        /* length */
    242                      TRUE,                      /* find_space */
    243                      fExecutable                /* protection */
    244                      ? VM_PROT_ALL
    245                      : VM_PROT_RW,
    246                      VM_PROT_ALL,               /* max(_prot) */
    247                      0);                        /* cow (copy-on-write) */
    248     if (rc == KERN_SUCCESS)
    249     {
    250         rc = VINF_SUCCESS;
    251 
    252         for (size_t iPage = 0; iPage < cPages; iPage++)
    253         {
    254             vm_page_t   pPage;
    255 
    256             pPage = vm_page_alloc(NULL, iPage,
    257                                   VM_ALLOC_SYSTEM |
    258                                   VM_ALLOC_WIRED | VM_ALLOC_NOOBJ);
    259 
    260             if (!pPage)
    261             {
    262                 /*
    263                     * Out of pages
    264                     * Remove already allocated pages
    265                     */
    266                 while (iPage-- > 0)
    267                 {
    268                     pPage = pMemFreeBSD->u.Phys.apPages[iPage];
    269                     vm_page_lock_queues();
    270                     vm_page_unwire(pPage, 0);
    271                     vm_page_free(pPage);
    272                     vm_page_unlock_queues();
    273                 }
    274                 rc = VERR_NO_MEMORY;
    275                 break;
    276             }
    277 
    278             pPage->valid = VM_PAGE_BITS_ALL;
    279             pMemFreeBSD->u.Phys.apPages[iPage] = pPage;
    280         }
    281 
    282         if (rc == VINF_SUCCESS)
    283         {
    284             vm_offset_t AddressDst = MapAddress;
    285 
    286             for (size_t iPage = 0; iPage < cPages; iPage++)
    287             {
    288                 vm_page_t pPage = pMemFreeBSD->u.Phys.apPages[iPage];
    289 
    290                 MY_PMAP_ENTER(kernel_map->pmap, AddressDst, pPage,
    291                               fExecutable
    292                               ? VM_PROT_ALL
    293                               : VM_PROT_RW,
    294                               TRUE);
    295 
    296                 AddressDst += PAGE_SIZE;
    297             }
    298 
    299             /* Store start address */
    300             pMemFreeBSD->Core.pv = (void *)MapAddress;
    301             *ppMem = &pMemFreeBSD->Core;
    302             return VINF_SUCCESS;
    303         }
    304     }
    305     rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
    306 
    307     rtR0MemObjDelete(&pMemFreeBSD->Core);
     302    int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, ~(vm_paddr_t)0, false);
     303    if (RT_FAILURE(rc))
     304    {
     305        rtR0MemObjDelete(&pMemFreeBSD->Core);
     306        return rc;
     307    }
     308
     309    *ppMem = &pMemFreeBSD->Core;
    308310    return rc;
    309311}
     
    312314DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
    313315{
    314 #ifdef USE_KMEM_ALLOC_ATTR
    315     /*
    316      * Use kmem_alloc_attr, fExectuable is not needed because the
    317      * memory will be executable by default
    318      */
    319     NOREF(fExecutable);
    320 
    321     /* create the object. */
    322     PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_LOW, NULL, cb);
     316    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
     317                                                                       RTR0MEMOBJTYPE_LOW, NULL, cb);
    323318    if (!pMemFreeBSD)
    324319        return VERR_NO_MEMORY;
    325320
    326     pMemFreeBSD->Core.pv = (void *)kmem_alloc_attr(kernel_map,          /* Kernel */
    327                                                    cb,                  /* Amount */
    328                                                    M_ZERO,              /* Zero memory */
    329                                                    0,                   /* Low physical address */
    330                                                    _4G - PAGE_SIZE,     /* Highest physical address */
    331                                                    VM_MEMATTR_DEFAULT); /* Default memory attributes */
    332     if (!pMemFreeBSD->Core.pv)
    333         return VERR_NO_MEMORY;
     321    int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G, false);
     322    if (RT_FAILURE(rc))
     323    {
     324        rtR0MemObjDelete(&pMemFreeBSD->Core);
     325        return rc;
     326    }
    334327
    335328    *ppMem = &pMemFreeBSD->Core;
    336 
    337     return VINF_SUCCESS;
    338 #else
    339     /*
    340      * Try a Alloc first and see if we get luck, if not try contigmalloc.
    341      * Might wish to try find our own pages or something later if this
    342      * turns into a problemspot on AMD64 boxes.
    343      */
    344     int rc = rtR0MemObjNativeAllocPage(ppMem, cb, fExecutable);
    345     if (RT_SUCCESS(rc))
    346     {
    347         size_t iPage = cb >> PAGE_SHIFT;
    348         while (iPage-- > 0)
    349             if (rtR0MemObjNativeGetPagePhysAddr(*ppMem, iPage) > (_4G - PAGE_SIZE))
    350             {
    351                 RTR0MemObjFree(*ppMem, false);
    352                 *ppMem = NULL;
    353                 rc = VERR_NO_MEMORY;
    354                 break;
    355             }
    356     }
    357     if (RT_FAILURE(rc))
    358         rc = rtR0MemObjNativeAllocCont(ppMem, cb, fExecutable);
    359329    return rc;
    360 #endif
    361330}
    362331
     
    364333DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
    365334{
    366     /* create the object. */
    367     PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_CONT, NULL, cb);
     335    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
     336                                                                      RTR0MEMOBJTYPE_CONT, NULL, cb);
    368337    if (!pMemFreeBSD)
    369338        return VERR_NO_MEMORY;
    370339
    371     /* do the allocation. */
    372     pMemFreeBSD->Core.pv = contigmalloc(cb,                   /* size */
    373                                         M_IPRTMOBJ,           /* type */
    374                                         M_NOWAIT | M_ZERO,    /* flags */
    375                                         0,                    /* lowest physical address*/
    376                                         _4G-1,                /* highest physical address */
    377                                         PAGE_SIZE,            /* alignment. */
    378                                         0);                   /* boundary */
    379     if (pMemFreeBSD->Core.pv)
    380     {
    381         pMemFreeBSD->Core.u.Cont.Phys = vtophys(pMemFreeBSD->Core.pv);
    382         *ppMem = &pMemFreeBSD->Core;
    383         return VINF_SUCCESS;
    384     }
    385 
    386     NOREF(fExecutable);
    387     rtR0MemObjDelete(&pMemFreeBSD->Core);
    388     return VERR_NO_MEMORY;
    389 }
    390 
    391 
    392 static void rtR0MemObjFreeBSDPhysPageInit(vm_page_t pPage, vm_pindex_t iPage)
    393 {
    394 #if __FreeBSD_version <= 1000000
    395     pPage->wire_count = 1;
    396     pPage->pindex     = iPage;
    397     pPage->act_count  = 0;
    398     atomic_add_int(&cnt.v_wire_count, 1);
    399 
    400 #if __FreeBSD_version >= 900040
    401     Assert(pPage->oflags & VPO_UNMANAGED != 0);
    402 #else
    403     Assert(pPage->flags & PG_UNMANAGED != 0);
    404 #endif
    405 #endif
     340    int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G, true);
     341    if (RT_FAILURE(rc))
     342    {
     343        rtR0MemObjDelete(&pMemFreeBSD->Core);
     344        return rc;
     345    }
     346
     347    pMemFreeBSD->Core.u.Cont.Phys = vtophys(pMemFreeBSD->Core.pv);
     348    *ppMem = &pMemFreeBSD->Core;
     349    return rc;
    406350}
    407351
     
    412356                                           bool fContiguous)
    413357{
    414     int        rc = VINF_SUCCESS;
    415     uint32_t   cPages = cb >> PAGE_SHIFT;
     358    uint32_t   cPages = atop(cb);
    416359    vm_paddr_t VmPhysAddrHigh;
    417 #if __FreeBSD_version >= 1000001
    418     int        pFlags = VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED;
    419 #endif
    420360
    421361    /* create the object. */
    422     PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJFREEBSD, u.Phys.apPages[cPages]),
     362    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD),
    423363                                                                       enmType, NULL, cb);
    424364    if (!pMemFreeBSD)
    425365        return VERR_NO_MEMORY;
    426366
    427     pMemFreeBSD->u.Phys.cPages = cPages;
     367    pMemFreeBSD->pObject = vm_object_allocate(OBJT_PHYS, atop(cb));
    428368
    429369    if (PhysHighest != NIL_RTHCPHYS)
     
    432372        VmPhysAddrHigh = ~(vm_paddr_t)0;
    433373
    434     if (fContiguous)
    435     {
    436 #if __FreeBSD_version >= 1000001
    437         vm_page_t pPage = vm_page_alloc_contig(NULL, 0, pFlags, cPages, 0, VmPhysAddrHigh, uAlignment, 0, VM_MEMATTR_DEFAULT);
    438 #else
    439         vm_page_t pPage = vm_phys_alloc_contig(cPages, 0, VmPhysAddrHigh, uAlignment, 0);
    440 #endif
    441 
    442         if (pPage)
    443             for (uint32_t iPage = 0; iPage < cPages; iPage++)
    444             {
    445                 rtR0MemObjFreeBSDPhysPageInit(&pPage[iPage], iPage);
    446                 pMemFreeBSD->u.Phys.apPages[iPage] = &pPage[iPage];
    447             }
    448         else
    449             rc = VERR_NO_MEMORY;
     374    int rc = rtR0MemObjFreeBSDPhysAllocHelper(pMemFreeBSD->pObject, cPages, VmPhysAddrHigh,
     375                                              uAlignment, fContiguous, true);
     376
     377    if (RT_FAILURE(rc)) {
     378        vm_object_deallocate(pMemFreeBSD->pObject);
     379        rtR0MemObjDelete(&pMemFreeBSD->Core);
    450380    }
    451381    else
    452382    {
    453         /* Allocate page by page */
    454         for (uint32_t iPage = 0; iPage < cPages; iPage++)
    455         {
    456 #if __FreeBSD_version >= 1000001
    457             vm_page_t pPage = vm_page_alloc_contig(NULL, iPage, pFlags, 1, 0, VmPhysAddrHigh, uAlignment, 0, VM_MEMATTR_DEFAULT);
    458 #else
    459             vm_page_t pPage = vm_phys_alloc_contig(1, 0, VmPhysAddrHigh, uAlignment, 0);
    460 #endif
    461 
    462             if (!pPage)
    463             {
    464                 /* Free all allocated pages */
    465                 while (iPage-- > 0)
    466                 {
    467                     pPage = pMemFreeBSD->u.Phys.apPages[iPage];
    468                     vm_page_lock_queues();
    469                     vm_page_unwire(pPage, 0);
    470                     vm_page_free(pPage);
    471                     vm_page_unlock_queues();
    472                 }
    473                 rc = VERR_NO_MEMORY;
    474                 break;
    475             }
    476             rtR0MemObjFreeBSDPhysPageInit(pPage, iPage);
    477             pMemFreeBSD->u.Phys.apPages[iPage] = pPage;
    478         }
    479     }
    480 
    481     if (RT_FAILURE(rc))
    482         rtR0MemObjDelete(&pMemFreeBSD->Core);
    483     else
    484     {
    485         if (enmType == RTR0MEMOBJTYPE_PHYS)
    486         {
    487             pMemFreeBSD->Core.u.Phys.PhysBase = VM_PAGE_TO_PHYS(pMemFreeBSD->u.Phys.apPages[0]);
     383        if (fContiguous)
     384        {
     385            Assert(enmType == RTR0MEMOBJTYPE_PHYS);
     386            VM_OBJECT_LOCK(pMemFreeBSD->pObject);
     387            pMemFreeBSD->Core.u.Phys.PhysBase = VM_PAGE_TO_PHYS(vm_page_find_least(pMemFreeBSD->pObject, 0));
     388            VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
    488389            pMemFreeBSD->Core.u.Phys.fAllocated = true;
    489390        }
     
    498399DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
    499400{
    500 #if 1
    501401    return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS, cb, PhysHighest, uAlignment, true);
    502 #else
    503     /* create the object. */
    504     PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_CONT, NULL, cb);
    505     if (!pMemFreeBSD)
    506         return VERR_NO_MEMORY;
    507 
    508     /* do the allocation. */
    509     pMemFreeBSD->Core.pv = contigmalloc(cb,                   /* size */
    510                                         M_IPRTMOBJ,           /* type */
    511                                         M_NOWAIT | M_ZERO,    /* flags */
    512                                         0,                    /* lowest physical address*/
    513                                         _4G-1,                /* highest physical address */
    514                                         uAlignment,           /* alignment. */
    515                                         0);                   /* boundary */
    516     if (pMemFreeBSD->Core.pv)
    517     {
    518         pMemFreeBSD->Core.u.Cont.Phys = vtophys(pMemFreeBSD->Core.pv);
    519         *ppMem = &pMemFreeBSD->Core;
    520         return VINF_SUCCESS;
    521     }
    522 
    523     rtR0MemObjDelete(&pMemFreeBSD->Core);
    524     return VERR_NO_MEMORY;
    525 #endif
    526402}
    527403
     
    529405DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
    530406{
    531 #if 1
    532407    return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS_NC, cb, PhysHighest, PAGE_SIZE, false);
    533 #else
    534     return VERR_NOT_SUPPORTED;
    535 #endif
    536408}
    537409
     
    643515        return VERR_NO_MEMORY;
    644516
    645     /*
    646      * Allocate an empty VM object and map it into the requested map.
    647      */
    648     pMemFreeBSD->u.NonPhys.pObject = vm_object_allocate(OBJT_DEFAULT, cb >> PAGE_SHIFT);
    649     if (pMemFreeBSD->u.NonPhys.pObject)
    650     {
    651         vm_offset_t MapAddress = pvFixed != (void *)-1
    652                                ? (vm_offset_t)pvFixed
    653                                : vm_map_min(pMap);
    654         if (pvFixed != (void *)-1)
    655             vm_map_remove(pMap,
    656                           MapAddress,
    657                           MapAddress + cb);
    658 
    659         rc = vm_map_find(pMap,                          /* map */
    660                          pMemFreeBSD->u.NonPhys.pObject, /* object */
    661                          0,                             /* offset */
    662                          &MapAddress,                   /* addr (IN/OUT) */
    663                          cb,                            /* length */
    664                          pvFixed == (void *)-1,         /* find_space */
    665                          VM_PROT_NONE,                  /* protection */
    666                          VM_PROT_ALL,                   /* max(_prot) ?? */
    667                          0);                            /* cow (copy-on-write) */
    668         if (rc == KERN_SUCCESS)
    669         {
    670             if (R0Process != NIL_RTR0PROCESS)
    671             {
    672                 rc = vm_map_inherit(pMap,
    673                                     MapAddress,
    674                                     MapAddress + cb,
    675                                     VM_INHERIT_SHARE);
    676                 AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
    677             }
    678             pMemFreeBSD->Core.pv = (void *)MapAddress;
    679             pMemFreeBSD->Core.u.ResVirt.R0Process = R0Process;
    680             *ppMem = &pMemFreeBSD->Core;
    681             return VINF_SUCCESS;
    682         }
    683         vm_object_deallocate(pMemFreeBSD->u.NonPhys.pObject);
    684         rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
    685     }
    686     else
    687         rc = VERR_NO_MEMORY;
     517    vm_offset_t MapAddress = pvFixed != (void *)-1
     518                           ? (vm_offset_t)pvFixed
     519                           : vm_map_min(pMap);
     520    if (pvFixed != (void *)-1)
     521        vm_map_remove(pMap,
     522                      MapAddress,
     523                      MapAddress + cb);
     524
     525    rc = vm_map_find(pMap,                          /* map */
     526                     NULL,                          /* object */
     527                     0,                             /* offset */
     528                     &MapAddress,                   /* addr (IN/OUT) */
     529                     cb,                            /* length */
     530                     pvFixed == (void *)-1 ? VMFS_ANY_SPACE : VMFS_NO_SPACE,
     531                                                    /* find_space */
     532                     VM_PROT_NONE,                  /* protection */
     533                     VM_PROT_ALL,                   /* max(_prot) ?? */
     534                     0);                            /* cow (copy-on-write) */
     535    if (rc == KERN_SUCCESS)
     536    {
     537        if (R0Process != NIL_RTR0PROCESS)
     538        {
     539            rc = vm_map_inherit(pMap,
     540                                MapAddress,
     541                                MapAddress + cb,
     542                                VM_INHERIT_SHARE);
     543            AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
     544        }
     545        pMemFreeBSD->Core.pv = (void *)MapAddress;
     546        pMemFreeBSD->Core.u.ResVirt.R0Process = R0Process;
     547        *ppMem = &pMemFreeBSD->Core;
     548        return VINF_SUCCESS;
     549    }
     550
     551    rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
    688552    rtR0MemObjDelete(&pMemFreeBSD->Core);
    689553    return rc;
     
    708572                                          unsigned fProt, size_t offSub, size_t cbSub)
    709573{
    710     AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED);
     574//  AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED);
    711575    AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED);
    712576
     
    717581        return VERR_NOT_SUPPORTED;
    718582
    719 /* Phys: see pmap_mapdev in i386/i386/pmap.c (http://fxr.watson.org/fxr/source/i386/i386/pmap.c?v=RELENG62#L2860) */
    720 /** @todo finish the implementation. */
    721 
    722     return VERR_NOT_SUPPORTED;
    723 }
    724 
    725 
    726 /* see http://markmail.org/message/udhq33tefgtyfozs */
    727 DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
    728 {
    729     /*
    730      * Check for unsupported stuff.
    731      */
    732     AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
    733     AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
    734     if (uAlignment > PAGE_SIZE)
    735         return VERR_NOT_SUPPORTED;
    736 
    737583    int                rc;
    738584    PRTR0MEMOBJFREEBSD pMemToMapFreeBSD = (PRTR0MEMOBJFREEBSD)pMemToMap;
    739     struct proc       *pProc            = (struct proc *)R0Process;
    740     struct vm_map     *pProcMap         = &pProc->p_vmspace->vm_map;
    741585
    742586    /* calc protection */
     
    751595        ProtectionFlags |= VM_PROT_EXECUTE;
    752596
     597    vm_offset_t  Addr = vm_map_min(kernel_map);
     598    if (cbSub == 0)
     599        cbSub = pMemToMap->cb - offSub;
     600
     601    vm_object_reference(pMemToMapFreeBSD->pObject);
     602    rc = vm_map_find(kernel_map,            /* Map to insert the object in */
     603                     pMemToMapFreeBSD->pObject, /* Object to map */
     604                     offSub,                /* Start offset in the object */
     605                     &Addr,                 /* Start address IN/OUT */
     606                     cbSub,                 /* Size of the mapping */
     607                     VMFS_ANY_SPACE,        /* Whether a suitable address should be searched for first */
     608                     ProtectionFlags,       /* protection flags */
     609                     VM_PROT_ALL,           /* Maximum protection flags */
     610                     0);                    /* copy-on-write and similar flags */
     611
     612    if (rc == KERN_SUCCESS)
     613    {
     614        rc = vm_map_wire(kernel_map, Addr, Addr + cbSub, VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
     615        AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
     616
     617        PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(RTR0MEMOBJFREEBSD),
     618                                                                           RTR0MEMOBJTYPE_MAPPING,
     619                                                                           (void *)Addr,
     620                                                                           cbSub);
     621        if (pMemFreeBSD)
     622        {
     623            Assert((vm_offset_t)pMemFreeBSD->Core.pv == Addr);
     624            pMemFreeBSD->Core.u.Mapping.R0Process = NIL_RTR0PROCESS;
     625            *ppMem = &pMemFreeBSD->Core;
     626            return VINF_SUCCESS;
     627        }
     628        rc = vm_map_remove(kernel_map, Addr, Addr + cbSub);
     629        AssertMsg(rc == KERN_SUCCESS, ("Deleting mapping failed\n"));
     630    }
     631    else
     632        vm_object_deallocate(pMemToMapFreeBSD->pObject);
     633
     634    return VERR_NO_MEMORY;
     635}
     636
     637
     638DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
     639                                        unsigned fProt, RTR0PROCESS R0Process)
     640{
     641    /*
     642     * Check for unsupported stuff.
     643     */
     644    AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
     645    if (uAlignment > PAGE_SIZE)
     646        return VERR_NOT_SUPPORTED;
     647
     648    int                rc;
     649    PRTR0MEMOBJFREEBSD pMemToMapFreeBSD = (PRTR0MEMOBJFREEBSD)pMemToMap;
     650    struct proc       *pProc            = (struct proc *)R0Process;
     651    struct vm_map     *pProcMap         = &pProc->p_vmspace->vm_map;
     652
     653    /* calc protection */
     654    vm_prot_t       ProtectionFlags = 0;
     655    if ((fProt & RTMEM_PROT_NONE) == RTMEM_PROT_NONE)
     656        ProtectionFlags = VM_PROT_NONE;
     657    if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ)
     658        ProtectionFlags |= VM_PROT_READ;
     659    if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE)
     660        ProtectionFlags |= VM_PROT_WRITE;
     661    if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC)
     662        ProtectionFlags |= VM_PROT_EXECUTE;
     663
    753664    /* calc mapping address */
    754     PROC_LOCK(pProc);
    755     vm_offset_t AddrR3 = round_page((vm_offset_t)pProc->p_vmspace->vm_daddr + lim_max(pProc, RLIMIT_DATA));
    756     PROC_UNLOCK(pProc);
    757 
    758     /* Insert the object in the map. */
     665    vm_offset_t AddrR3;
     666    if (R3PtrFixed == (RTR3PTR)-1)
     667    {
     668        /** @todo: is this needed?. */
     669        PROC_LOCK(pProc);
     670        AddrR3 = round_page((vm_offset_t)pProc->p_vmspace->vm_daddr + lim_max(pProc, RLIMIT_DATA));
     671        PROC_UNLOCK(pProc);
     672    }
     673    else
     674        AddrR3 = (vm_offset_t)R3PtrFixed;
     675
     676    /* Insert the pObject in the map. */
     677    vm_object_reference(pMemToMapFreeBSD->pObject);
    759678    rc = vm_map_find(pProcMap,              /* Map to insert the object in */
    760                      NULL,                  /* Object to map */
     679                     pMemToMapFreeBSD->pObject, /* Object to map */
    761680                     0,                     /* Start offset in the object */
    762681                     &AddrR3,               /* Start address IN/OUT */
    763682                     pMemToMap->cb,         /* Size of the mapping */
    764                      TRUE,                  /* Whether a suitable address should be searched for first */
     683                     R3PtrFixed == (RTR3PTR)-1 ? VMFS_ANY_SPACE : VMFS_NO_SPACE,
     684                                            /* Whether a suitable address should be searched for first */
    765685                     ProtectionFlags,       /* protection flags */
    766686                     VM_PROT_ALL,           /* Maximum protection flags */
    767                      0);                    /* Copy on write */
    768 
    769     /* Map the memory page by page into the destination map. */
     687                     0);                    /* copy-on-write and similar flags */
     688
    770689    if (rc == KERN_SUCCESS)
    771690    {
    772         size_t         cPages       = pMemToMap->cb >> PAGE_SHIFT;;
    773         pmap_t         pPhysicalMap = pProcMap->pmap;
    774         vm_offset_t    AddrR3Dst    = AddrR3;
    775 
    776         if (   pMemToMap->enmType == RTR0MEMOBJTYPE_PHYS
    777             || pMemToMap->enmType == RTR0MEMOBJTYPE_PHYS_NC
    778             || pMemToMap->enmType == RTR0MEMOBJTYPE_PAGE)
    779         {
    780             /* Mapping physical allocations */
    781             Assert(cPages == pMemToMapFreeBSD->u.Phys.cPages);
    782 
    783             /* Insert the memory page by page into the mapping. */
    784             for (uint32_t iPage = 0; iPage < cPages; iPage++)
    785             {
    786                 vm_page_t pPage = pMemToMapFreeBSD->u.Phys.apPages[iPage];
    787 
    788                 MY_PMAP_ENTER(pPhysicalMap, AddrR3Dst, pPage, ProtectionFlags, TRUE);
    789                 AddrR3Dst += PAGE_SIZE;
    790             }
    791         }
    792         else
    793         {
    794             /* Mapping cont or low memory types */
    795             vm_offset_t AddrToMap = (vm_offset_t)pMemToMap->pv;
    796 
    797             for (uint32_t iPage = 0; iPage < cPages; iPage++)
    798             {
    799                 vm_page_t pPage = PHYS_TO_VM_PAGE(vtophys(AddrToMap));
    800 
    801                 MY_PMAP_ENTER(pPhysicalMap, AddrR3Dst, pPage, ProtectionFlags, TRUE);
    802                 AddrR3Dst += PAGE_SIZE;
    803                 AddrToMap += PAGE_SIZE;
    804             }
    805         }
    806     }
    807 
    808     if (RT_SUCCESS(rc))
    809     {
     691        rc = vm_map_wire(pProcMap, AddrR3, AddrR3 + pMemToMap->cb, VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
     692        AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
     693
     694        rc = vm_map_inherit(pProcMap, AddrR3, AddrR3 + pMemToMap->cb, VM_INHERIT_SHARE);
     695        AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
     696
    810697        /*
    811698         * Create a mapping object for it.
     
    823710        }
    824711
    825         rc = vm_map_remove(pProcMap, ((vm_offset_t)AddrR3), ((vm_offset_t)AddrR3) + pMemToMap->cb);
     712        rc = vm_map_remove(pProcMap, AddrR3, AddrR3 + pMemToMap->cb);
    826713        AssertMsg(rc == KERN_SUCCESS, ("Deleting mapping failed\n"));
    827714    }
     715    else
     716        vm_object_deallocate(pMemToMapFreeBSD->pObject);
    828717
    829718    return VERR_NO_MEMORY;
     
    873762            }
    874763
    875             vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + (iPage << PAGE_SHIFT);
     764            vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + ptoa(iPage);
    876765
    877766            struct proc    *pProc     = (struct proc *)pMemFreeBSD->Core.u.Lock.R0Process;
    878767            struct vm_map  *pProcMap  = &pProc->p_vmspace->vm_map;
    879             pmap_t pPhysicalMap       = pProcMap->pmap;
     768            pmap_t pPhysicalMap       = vm_map_pmap(pProcMap);
    880769
    881770            return pmap_extract(pPhysicalMap, pb);
     
    884773        case RTR0MEMOBJTYPE_MAPPING:
    885774        {
    886             vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + (iPage << PAGE_SHIFT);
     775            vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + ptoa(iPage);
    887776
    888777            if (pMemFreeBSD->Core.u.Mapping.R0Process != NIL_RTR0PROCESS)
     
    890779                struct proc    *pProc     = (struct proc *)pMemFreeBSD->Core.u.Mapping.R0Process;
    891780                struct vm_map  *pProcMap  = &pProc->p_vmspace->vm_map;
    892                 pmap_t pPhysicalMap       = pProcMap->pmap;
     781                pmap_t pPhysicalMap       = vm_map_pmap(pProcMap);
    893782
    894783                return pmap_extract(pPhysicalMap, pb);
     
    897786        }
    898787
     788        case RTR0MEMOBJTYPE_PAGE:
     789        case RTR0MEMOBJTYPE_LOW:
     790        case RTR0MEMOBJTYPE_PHYS_NC:
     791        {
     792            RTHCPHYS addr;
     793            VM_OBJECT_LOCK(pMemFreeBSD->pObject);
     794            addr = VM_PAGE_TO_PHYS(vm_page_lookup(pMemFreeBSD->pObject, iPage));
     795            VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
     796            return addr;
     797        }
     798
     799        case RTR0MEMOBJTYPE_PHYS:
     800            return pMemFreeBSD->Core.u.Cont.Phys + ptoa(iPage);
     801
    899802        case RTR0MEMOBJTYPE_CONT:
    900             return pMemFreeBSD->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
    901 
    902         case RTR0MEMOBJTYPE_PHYS:
    903             return pMemFreeBSD->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
    904 
    905         case RTR0MEMOBJTYPE_PAGE:
    906         case RTR0MEMOBJTYPE_PHYS_NC:
    907             return VM_PAGE_TO_PHYS(pMemFreeBSD->u.Phys.apPages[iPage]);
    908 
    909 #ifdef USE_KMEM_ALLOC_ATTR
    910         case RTR0MEMOBJTYPE_LOW:
    911         {
    912             vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + (iPage << PAGE_SHIFT);
    913             return vtophys(pb);
    914         }
    915 #else
    916         case RTR0MEMOBJTYPE_LOW:
    917 #endif
     803            return pMemFreeBSD->Core.u.Phys.PhysBase + ptoa(iPage);
     804
    918805        case RTR0MEMOBJTYPE_RES_VIRT:
    919806        default:
Note: See TracChangeset for help on using the changeset viewer.

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