VirtualBox

Ignore:
Timestamp:
May 31, 2011 9:32:44 PM (14 years ago)
Author:
vboxsync
Message:

IPRT/r0drv/solaris: Working on large page allocation optimization. Some cleanup.

Location:
trunk/src/VBox/Runtime/r0drv/solaris/vbi
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/solaris/vbi/i86pc/os/vbi.c

    r36623 r37281  
    2020 */
    2121/*
    22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
     22 * Copyright 2010-2011 Sun Microsystems, Inc.  All rights reserved.
    2323 * Use is subject to license terms.
    2424 */
     
    5858#include <sys/utsname.h>
    5959
     60#include <iprt/assert.h>
     61
    6062#include "vbi.h"
    6163
     
    7678/* Introduced in v9 */
    7779static int use_kflt = 0;
    78 page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr);
     80static page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr);
    7981
    8082
     
    562564
    563565void *
    564 vbi_thread_create(void *func, void *arg, size_t len, int priority)
     566vbi_thread_create(void (*func)(void *), void *arg, size_t len, int priority)
    565567{
    566568        kthread_t *t;
     
    10131015        map_addr(va, len, 0, 0, MAP_SHARED);
    10141016        if (*va != NULL)
    1015         {
    10161017                error = as_map(as, *va, len, segvbi_create, &args);
    1017         }
    10181018        else
    10191019                error = ENOMEM;
     
    10301030
    10311031struct vbi_cpu_watch {
    1032         void (*vbi_cpu_func)();
     1032        void (*vbi_cpu_func)(void *, int, int);
    10331033        void *vbi_cpu_arg;
    10341034};
     
    10511051
    10521052vbi_cpu_watch_t *
    1053 vbi_watch_cpus(void (*func)(), void *arg, int current_too)
     1053vbi_watch_cpus(void (*func)(void *, int, int), void *arg, int current_too)
    10541054{
    10551055        int c;
     
    12111211        t->g_cyclic = CYCLIC_NONE;
    12121212
    1213         omni.cyo_online = (void (*)())vbi_gtimer_online;
     1213        omni.cyo_online = (void (*)(void *, cpu_t *, cyc_handler_t *, cyc_time_t *))vbi_gtimer_online;
    12141214        omni.cyo_offline = NULL;
    12151215        omni.cyo_arg = t;
     
    14341434
    14351435
    1436 /*
    1437  * This is revision 9 of the interface.
    1438  */
    1439 page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr)
     1436
     1437static page_t *vbi_page_get_fromlist(uint_t freelist, caddr_t virtAddr)
    14401438{
    14411439        seg_t kernseg;
     
    14741472
    14751473/*
     1474 * Large page code.
     1475 */
     1476
     1477page_t *
     1478vbi_large_page_alloc(uint64_t *pphys, size_t pgsize)
     1479{
     1480        pgcnt_t const npages = pgsize >> PAGESHIFT;
     1481        page_t *pproot, *pp, *pplist;
     1482        pgcnt_t ipage;
     1483        caddr_t vaddr;
     1484        seg_t kernseg;
     1485        int rc;
     1486
     1487        /*
     1488         * Reserve available memory for a large page and create it.
     1489         */
     1490        rc = page_resv(npages, KM_NOSLEEP);
     1491        if (!rc) {
     1492                return NULL;
     1493        }
     1494        rc = page_create_wait(npages, 0 /* flags */);
     1495        if (!rc) {
     1496                page_unresv(npages);
     1497                return NULL;
     1498        }
     1499
     1500        /*
     1501         * Get a page off the free list.  We set vaddr to 0 since we don't know
     1502         * where the memory is going to be mapped.
     1503         */
     1504        vaddr = NULL;
     1505        kernseg.s_as = &kas;
     1506        pproot = page_get_freelist(&vbipagevp, 0 /* offset */, &kernseg,
     1507                vaddr, pgsize, 0x0000 /* flags */, NULL /*lgrp*/);
     1508        if (!pproot && use_kflt) {
     1509                pproot = page_get_freelist(&vbipagevp, 0 /* offset */, &kernseg,
     1510                        vaddr, pgsize, 0x0200 /* PG_KFLT */, NULL /*lgrp*/);
     1511                if (!pproot) {
     1512                        page_create_putback(npages);
     1513                        page_unresv(npages);
     1514                        return NULL;
     1515                }
     1516        }
     1517        AssertMsg(!(page_pptonum(pproot) & (npages - 1)), ("%p:%lx npages=%lx\n", pproot, page_pptonum(pproot), npages));
     1518
     1519        /*
     1520         * Mark all the sub-pages as non-free and not-hashed-in.
     1521         * It is paramount that we destroy the list (before freeing it).
     1522         */
     1523        pplist = pproot;
     1524        for (ipage = 0; ipage < npages; ipage++) {
     1525                pp = pplist;
     1526                AssertPtr(pp);
     1527                AssertMsg(page_pptonum(pp) == ipage + page_pptonum(pproot),
     1528                        ("%p:%lx %lx+%lx\n", pp, page_pptonum(pp), ipage, page_pptonum(pproot)));
     1529                page_sub(&pplist, pp);
     1530                AssertMsg(PP_ISFREE(pp), ("%p\n", pp));
     1531                AssertMsg(pp->p_szc == pproot->p_szc, ("%p - %d expected %d \n", pp, pp->p_szc, pproot->p_szc));
     1532
     1533                PP_CLRFREE(pp);
     1534                PP_CLRAGED(pp);
     1535        }
     1536
     1537        *pphys = (uint64_t)page_pptonum(pproot) << PAGESHIFT;
     1538        AssertMsg(!(*pphys & (pgsize - 1)), ("%llx %zx\n", *pphys, pgsize));
     1539        return pproot;
     1540}
     1541
     1542void
     1543vbi_large_page_free(page_t *pproot, size_t pgsize)
     1544{
     1545        pgcnt_t const npages = pgsize >> PAGESHIFT;
     1546        pgcnt_t ipage;
     1547
     1548        Assert(page_get_pagecnt(pproot->p_szc) == npages);
     1549        AssertMsg(!(page_pptonum(pproot) & (npages - 1)), ("%p:%lx npages=%lx\n", pproot, page_pptonum(pproot), npages));
     1550
     1551        /*
     1552         * We need to exclusively lock the sub-pages before freeing
     1553         * the large one.
     1554         */
     1555        for (ipage = 0; ipage < npages; ipage++) {
     1556                page_t *pp = page_nextn(pproot, ipage);
     1557                AssertMsg(page_pptonum(pp) == ipage + page_pptonum(pproot),
     1558                        ("%p:%lx %lx+%lx\n", pp, page_pptonum(pp), ipage, page_pptonum(pproot)));
     1559                AssertMsg(!PP_ISFREE(pp), ("%p\n", pp));
     1560
     1561                int rc = page_tryupgrade(pp);
     1562                if (!rc) {
     1563                        page_unlock(pp);
     1564                        while (!page_lock(pp, SE_EXCL, NULL /* mutex */, P_RECLAIM)) {
     1565                                /*nothing*/;
     1566                        }
     1567                }
     1568        }
     1569
     1570        /*
     1571         * Free the large page and unreserve the memory.
     1572         */
     1573        page_free_pages(pproot);
     1574        page_unresv(npages);
     1575}
     1576
     1577int
     1578vbi_large_page_premap(page_t *pproot, size_t pgsize)
     1579{
     1580        pgcnt_t const npages = pgsize >> PAGESHIFT;
     1581        pgcnt_t ipage;
     1582
     1583        Assert(page_get_pagecnt(pproot->p_szc) == npages);
     1584        AssertMsg(!(page_pptonum(pproot) & (npages - 1)), ("%p:%lx npages=%lx\n", pproot, page_pptonum(pproot), npages));
     1585
     1586        /*
     1587         * We need to downgrade the sub-pages from exclusive to shared locking
     1588         * because otherwise we cannot <you go figure>.
     1589         */
     1590        for (ipage = 0; ipage < npages; ipage++) {
     1591            page_t *pp = page_nextn(pproot, ipage);
     1592            AssertMsg(page_pptonum(pp) == ipage + page_pptonum(pproot),
     1593                    ("%p:%lx %lx+%lx\n", pp, page_pptonum(pp), ipage, page_pptonum(pproot)));
     1594            AssertMsg(!PP_ISFREE(pp), ("%p\n", pp));
     1595
     1596            if (page_tryupgrade(pp) == 1)
     1597                    page_downgrade(pp);
     1598            AssertMsg(!PP_ISFREE(pp), ("%p\n", pp));
     1599        }
     1600
     1601        return 0;
     1602}
     1603
     1604
     1605/*
    14761606 * As more functions are added, they should start with a comment indicating
    14771607 * the revision and above this point in the file and the revision level should
    14781608 * be increased. Also change vbi_modlmisc at the top of the file.
     1609 *
     1610 * NOTE! We'll start care about this if anything in here ever makes it into
     1611 *       the solaris kernel proper.
    14791612 */
    14801613uint_t vbi_revision_level = 9;
  • trunk/src/VBox/Runtime/r0drv/solaris/vbi/i86pc/sys/vbi.h

    r27727 r37281  
    138138 */
    139139extern void vbi_set_priority(void *thread, int priority);
    140 extern void *vbi_thread_create(void *func, void *arg, size_t len, int priority);
     140extern void *vbi_thread_create(void (*func)(void *), void *arg, size_t len, int priority);
    141141extern void vbi_thread_exit(void);
    142142
     
    249249 */
    250250typedef struct vbi_cpu_watch vbi_cpu_watch_t;
    251 extern vbi_cpu_watch_t *vbi_watch_cpus(void (*func)(void), void *arg,
     251extern vbi_cpu_watch_t *vbi_watch_cpus(void (*func)(void *, int, int), void *arg,
    252252    int current_too);
    253253extern void vbi_ignore_cpus(vbi_cpu_watch_t *);
     
    345345/* begin interfaces defined for version 7 */
    346346/*
    347  * Allocate and free physically limited, aligned as specified continuous or non-continuous memory. 
     347 * Allocate and free physically limited, aligned as specified continuous or non-continuous memory.
    348348 *
    349349 * return value is a) NULL if memory below "phys" not available or
     
    369369 * phys on input is set to the physical address of the first page allocated.
    370370 *
    371  * size is the amount to allocate and must be a multiple of PAGESIZE
     371 * size is the amount to allocate and must be a multiple of PAGESIZE.
    372372 */
    373373extern page_t **vbi_pages_alloc(uint64_t *phys, size_t size);
     
    400400/* end of interfaces defined for version 8 */
    401401
     402/*
     403 * Allocate, free and map one large page.
     404 *
     405 * The size of the large page is hardware specific and must be specified
     406 * correctly or we'll panic. :-)
     407 */
     408extern page_t *vbi_large_page_alloc(uint64_t *pphys, size_t pgsize);
     409extern void vbi_large_page_free(page_t *ppage, size_t pgsize);
     410extern int vbi_large_page_premap(page_t *pproot, size_t pgsize);
     411
     412
    402413#ifdef  __cplusplus
    403414}
  • trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c

    r36555 r37281  
    3333#include <iprt/memobj.h>
    3434
     35#include <iprt/asm.h>
    3536#include <iprt/assert.h>
    3637#include <iprt/err.h>
     
    5758    /** Access during locking. */
    5859    int                 fAccess;
     60    /** Set if large pages are involved in an RTR0MEMOBJTYPE_PHYS
     61     *  allocation. */
     62    bool                fLargePage;
    5963} RTR0MEMOBJSOLARIS, *PRTR0MEMOBJSOLARIS;
    6064
     
    7175            break;
    7276
    73         case RTR0MEMOBJTYPE_CONT:
    7477        case RTR0MEMOBJTYPE_PHYS:
    75             vbi_phys_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
     78            if (!pMemSolaris->Core.u.Phys.fAllocated)
     79            {   /* nothing to do here */;   }
     80            else if (pMemSolaris->fLargePage)
     81                vbi_large_page_free(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
     82            else
     83                vbi_phys_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
    7684            break;
    7785
    7886        case RTR0MEMOBJTYPE_PHYS_NC:
    79 #if 0
    80             vbi_phys_free(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
    81 #else
    82             if (pMemSolaris->Core.u.Phys.fAllocated == true)
    83                 ddi_umem_free(pMemSolaris->Cookie);
    84             else
    85                 vbi_pages_free(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
    86 #endif
     87            vbi_pages_free(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
    8788            break;
    8889
     
    108109        }
    109110
     111        case RTR0MEMOBJTYPE_CONT: /* we don't use this type here. */
    110112        default:
    111113            AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType));
     
    131133    }
    132134
    133     pMemSolaris->Core.pv = virtAddr;
     135    pMemSolaris->Core.pv  = virtAddr;
    134136    pMemSolaris->pvHandle = NULL;
    135137    *ppMem = &pMemSolaris->Core;
     
    176178        return VERR_NO_MEMORY;
    177179
    178     /* Allocate physically non-contiguous page-aligned memory. */
    179     uint64_t physAddr = PhysHighest;
    180 
    181 # if 0
    182     /*
    183      * The contig_alloc() way of allocating NC pages is broken or does not match our semantics. Refer #4716 for details.
    184      */
    185 #  if 0
    186     /* caddr_t virtAddr  = vbi_phys_alloc(&physAddr, cb, PAGE_SIZE, 0 /* non-contiguous */);
    187 #  endif
    188     caddr_t virtAddr = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie);
    189     if (RT_UNLIKELY(virtAddr == NULL))
    190     {
    191         rtR0MemObjDelete(&pMemSolaris->Core);
    192         return VERR_NO_MEMORY;
    193     }
    194     pMemSolaris->Core.pv = virtAddr;
    195     pMemSolaris->Core.u.Phys.PhysBase = physAddr;
    196     pMemSolaris->Core.u.Phys.fAllocated = true;
    197     pMemSolaris->pvHandle = NULL;
    198 # else
    199     void *pvPages = vbi_pages_alloc(&physAddr, cb);
     180    uint64_t PhysAddr = PhysHighest;
     181    void *pvPages = vbi_pages_alloc(&PhysAddr, cb);
    200182    if (!pvPages)
    201183    {
     
    204186        return VERR_NO_MEMORY;
    205187    }
    206     pMemSolaris->Core.pv = NULL;
    207     pMemSolaris->Core.u.Phys.PhysBase = physAddr;
    208     pMemSolaris->Core.u.Phys.fAllocated = false;
    209     pMemSolaris->pvHandle = pvPages;
    210 # endif
    211 
    212     Assert(!(physAddr & PAGE_OFFSET_MASK));
    213     *ppMem = &pMemSolaris->Core;
    214     return VINF_SUCCESS;
    215 #else
    216     /** @todo rtR0MemObjNativeAllocPhysNC / solaris */
     188    pMemSolaris->Core.pv   = NULL;
     189    pMemSolaris->pvHandle  = pvPages;
     190
     191    Assert(!(PhysAddr & PAGE_OFFSET_MASK));
     192    *ppMem = &pMemSolaris->Core;
     193    return VINF_SUCCESS;
     194
     195#else /* 32 bit: */
    217196    return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */
    218197#endif
     
    228207        return VERR_NO_MEMORY;
    229208
    230     AssertCompile(NIL_RTHCPHYS == UINT64_MAX);
    231 
    232     /* Allocate physically contiguous memory aligned as specified. */
    233     uint64_t physAddr = PhysHighest;
    234     caddr_t  virtAddr = vbi_phys_alloc(&physAddr, cb, uAlignment, 1 /* contiguous */);
    235     if (RT_UNLIKELY(virtAddr == NULL))
    236     {
    237         rtR0MemObjDelete(&pMemSolaris->Core);
    238         return VERR_NO_CONT_MEMORY;
    239     }
    240     Assert(!(physAddr & PAGE_OFFSET_MASK));
    241     Assert(physAddr < PhysHighest);
    242     Assert(physAddr + cb <= PhysHighest);
    243 #if 0
    244     if (uAlignment != PAGE_SIZE)
    245     {
    246         /* uAlignment is always a multiple of PAGE_SIZE */
    247         pgcnt_t cPages = (cb + uAlignment - 1) >> PAGE_SHIFT;
    248         void *pvPage = virtAddr;
    249         while (cPages-- > 0)
    250         {
    251             uint64_t u64Page = vbi_va_to_pa(pvPage);
    252             if (u64Page & (uAlignment - 1))
    253             {
    254                 LogRel(("rtR0MemObjNativeAllocPhys: alignment mismatch! cb=%u uAlignment=%u physAddr=%#x\n", cb, uAlignment, u64Page));
    255                 vbi_phys_free(virtAddr, cb);
    256                 rtR0MemObjDelete(&pMemSolaris->Core);
    257                 return VERR_NO_MEMORY;
    258             }
    259             pvPage = (void *)((uintptr_t)pvPage + PAGE_SIZE);
    260         }
    261     }
     209    /*
     210     * Allocating one large page gets special treatment.
     211     */
     212    static uint32_t s_cbLargePage = UINT32_MAX;
     213    if (s_cbLargePage == UINT32_MAX)
     214    {
     215#if 0 /* currently not entirely stable, so disabled. */
     216        if (page_num_pagesizes() > 1)
     217            ASMAtomicWriteU32(&s_cbLargePage, page_get_pagesize(1));
     218        else
    262219#endif
    263     pMemSolaris->Core.pv = virtAddr;
    264     pMemSolaris->Core.u.Cont.Phys = physAddr;
    265     pMemSolaris->pvHandle = NULL;
    266     *ppMem = &pMemSolaris->Core;
    267     return VINF_SUCCESS;
     220            ASMAtomicWriteU32(&s_cbLargePage, 0);
     221    }
     222    uint64_t PhysAddr;
     223    if (   cb == s_cbLargePage
     224        && cb == uAlignment
     225        && PhysHighest == NIL_RTHCPHYS)
     226    {
     227        /*
     228         * Allocate one large page.
     229         */
     230        void *pvPages = vbi_large_page_alloc(&PhysAddr, cb);
     231        if (pvPages)
     232        {
     233            AssertMsg(!(PhysAddr & (cb - 1)), ("%RHp\n", PhysAddr));
     234            pMemSolaris->Core.pv                = NULL;
     235            pMemSolaris->Core.u.Phys.PhysBase   = PhysAddr;
     236            pMemSolaris->Core.u.Phys.fAllocated = true;
     237            pMemSolaris->pvHandle               = pvPages;
     238            pMemSolaris->fLargePage             = true;
     239
     240            *ppMem = &pMemSolaris->Core;
     241            return VINF_SUCCESS;
     242        }
     243    }
     244    else
     245    {
     246        /*
     247         * Allocate physically contiguous memory aligned as specified.
     248         */
     249        AssertCompile(NIL_RTHCPHYS == UINT64_MAX);
     250        PhysAddr = PhysHighest;
     251        caddr_t pvMem = vbi_phys_alloc(&PhysAddr, cb, uAlignment, 1 /* contiguous */);
     252        if (RT_LIKELY(pvMem))
     253        {
     254            Assert(!(PhysAddr & PAGE_OFFSET_MASK));
     255            Assert(PhysAddr < PhysHighest);
     256            Assert(PhysAddr + cb <= PhysHighest);
     257
     258            pMemSolaris->Core.pv                = pvMem;
     259            pMemSolaris->Core.u.Phys.PhysBase   = PhysAddr;
     260            pMemSolaris->Core.u.Phys.fAllocated = true;
     261            pMemSolaris->pvHandle               = NULL;
     262            pMemSolaris->fLargePage             = false;
     263
     264            *ppMem = &pMemSolaris->Core;
     265            return VINF_SUCCESS;
     266        }
     267    }
     268    rtR0MemObjDelete(&pMemSolaris->Core);
     269    return VERR_NO_CONT_MEMORY;
    268270}
    269271
     
    279281
    280282    /* There is no allocation here, it needs to be mapped somewhere first. */
    281     pMemSolaris->Core.u.Phys.fAllocated = false;
    282     pMemSolaris->Core.u.Phys.PhysBase = Phys;
     283    pMemSolaris->Core.u.Phys.fAllocated   = false;
     284    pMemSolaris->Core.u.Phys.PhysBase     = Phys;
    283285    pMemSolaris->Core.u.Phys.uCachePolicy = uCachePolicy;
    284286    *ppMem = &pMemSolaris->Core;
     
    298300        return VERR_NO_MEMORY;
    299301
     302    /* Lock down user pages. */
    300303    int fPageAccess = S_READ;
    301304    if (fAccess & RTMEM_PROT_WRITE)
     
    304307        fPageAccess = S_EXEC;
    305308    void *pvPageList = NULL;
    306 
    307     /* Lock down user pages */
    308309    int rc = vbi_lock_va((caddr_t)R3Ptr, cb, fPageAccess, &pvPageList);
    309310    if (rc != 0)
     
    314315    }
    315316
    316     pMemSolaris->Core.u.Lock.R0Process = (RTR0PROCESS)vbi_proc();
    317     pMemSolaris->pvHandle = pvPageList;
    318     pMemSolaris->fAccess = fPageAccess;
     317    /* Fill in the object attributes and return successfully. */
     318    pMemSolaris->Core.u.Lock.R0Process  = R0Process;
     319    pMemSolaris->pvHandle               = pvPageList;
     320    pMemSolaris->fAccess                = fPageAccess;
    319321    *ppMem = &pMemSolaris->Core;
    320322    return VINF_SUCCESS;
     
    330332        return VERR_NO_MEMORY;
    331333
     334    /* Lock down kernel pages. */
    332335    int fPageAccess = S_READ;
    333336    if (fAccess & RTMEM_PROT_WRITE)
     
    344347    }
    345348
     349    /* Fill in the object attributes and return successfully. */
    346350    pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
    347351    pMemSolaris->pvHandle = pvPageList;
     
    360364     */
    361365    void *pv = vmem_xalloc(heap_arena, cb, uAlignment, 0 /*phase*/, 0 /*nocross*/,
    362                      NULL /*minaddr*/, NULL /*maxaddr*/, VM_SLEEP);
     366                           NULL /*minaddr*/, NULL /*maxaddr*/, VM_SLEEP);
    363367    if (RT_UNLIKELY(!pv))
    364368        return VERR_NO_MEMORY;
     
    386390
    387391DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
    388                               unsigned fProt, size_t offSub, size_t cbSub)
     392                                          unsigned fProt, size_t offSub, size_t cbSub)
    389393{
    390394    /** @todo rtR0MemObjNativeMapKernel / Solaris - Should be fairly simple alloc kernel memory and memload it. */
     
    396400                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
    397401{
     402    /*
     403     * Fend off things we cannot do.
     404     */
    398405    AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
    399406    AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
     
    401408        return VERR_NOT_SUPPORTED;
    402409
    403     PRTR0MEMOBJSOLARIS pMemToMapSolaris = (PRTR0MEMOBJSOLARIS)pMemToMap;
    404     size_t cb        = pMemToMapSolaris->Core.cb;
    405     void *pv         = pMemToMapSolaris->Core.pv;
    406     pgcnt_t cPages   = (cb + PAGE_SIZE - 1) >> PAGE_SHIFT;
    407 
    408     /* Create the mapping object */
    409     PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb);
     410    /*
     411     * Get parameters from the source object.
     412     */
     413    PRTR0MEMOBJSOLARIS  pMemToMapSolaris = (PRTR0MEMOBJSOLARIS)pMemToMap;
     414    void               *pv               = pMemToMapSolaris->Core.pv;
     415    size_t              cb               = pMemToMapSolaris->Core.cb;
     416    pgcnt_t             cPages           = cb >> PAGE_SHIFT;
     417
     418    /*
     419     * Create the mapping object
     420     */
     421    PRTR0MEMOBJSOLARIS pMemSolaris;
     422    pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb);
    410423    if (RT_UNLIKELY(!pMemSolaris))
    411424        return VERR_NO_MEMORY;
    412425
     426    int rc = VINF_SUCCESS;
    413427    uint64_t *paPhysAddrs = kmem_zalloc(sizeof(uint64_t) * cPages, KM_SLEEP);
    414     if (RT_UNLIKELY(!paPhysAddrs))
    415         return VERR_NO_MEMORY;
    416 
    417     if (   pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC
    418         && pMemSolaris->Core.u.Phys.fAllocated == false)
     428    if (RT_LIKELY(paPhysAddrs))
    419429    {
    420430        /*
    421          * The PhysNC object has no kernel mapping backing it. The call to vbi_pages_premap()
    422          * prepares the physical pages to be mapped into user or kernel space.
     431         * Prepare the pages according to type.
    423432         */
    424         int rc = vbi_pages_premap(pMemToMapSolaris->pvHandle, cb, paPhysAddrs);
    425         if (rc)
    426         {
    427             LogRel(("rtR0MemObjNativeMapUser: vbi_pages_premap failed. rc=%d\n", rc));
    428             kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
    429             rtR0MemObjDelete(&pMemSolaris->Core);
    430             return VERR_MAP_FAILED;
    431         }
     433        if (pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC)
     434            rc = vbi_pages_premap(pMemToMapSolaris->pvHandle, cb, paPhysAddrs);
     435        else if (   pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS
     436                 && pMemToMapSolaris->fLargePage)
     437        {
     438            RTHCPHYS Phys = pMemToMapSolaris->Core.u.Phys.PhysBase;
     439            for (pgcnt_t iPage = 0; iPage < cPages; iPage++, Phys += PAGE_SIZE)
     440                paPhysAddrs[iPage] = Phys;
     441            rc = vbi_large_page_premap(pMemToMapSolaris->pvHandle, cb);
     442        }
     443        else
     444        {
     445            /* Have kernel mapping, just translate virtual to physical. */
     446            AssertPtr(pv);
     447            rc = 0;
     448            for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
     449            {
     450                paPhysAddrs[iPage] = vbi_va_to_pa(pv);
     451                if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1))
     452                {
     453                    LogRel(("rtR0MemObjNativeMapUser: no page to map.\n"));
     454                    rc = -1;
     455                    break;
     456                }
     457                pv = (void *)((uintptr_t)pv + PAGE_SIZE);
     458            }
     459        }
     460        if (!rc)
     461        {
     462            /*
     463             * Perform the actual mapping.
     464             */
     465            caddr_t UserAddr = NULL;
     466            rc = vbi_user_map(&UserAddr, fProt, paPhysAddrs, cb);
     467            if (!rc)
     468            {
     469                pMemSolaris->Core.u.Mapping.R0Process = R0Process;
     470                pMemSolaris->Core.pv                  = UserAddr;
     471
     472                *ppMem = &pMemSolaris->Core;
     473                kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
     474                return VINF_SUCCESS;
     475            }
     476
     477            LogRel(("rtR0MemObjNativeMapUser: vbi_user_map failed.\n"));
     478        }
     479        rc = VERR_MAP_FAILED;
     480        kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
    432481    }
    433482    else
    434     {
    435         /*
    436          * All other memory object types have allocated memory with kernel mappings.
    437          */
    438         for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
    439         {
    440             paPhysAddrs[iPage] = vbi_va_to_pa(pv);
    441             if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1))
    442             {
    443                 LogRel(("rtR0MemObjNativeMapUser: no page to map.\n"));
    444                 kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
    445                 rtR0MemObjDelete(&pMemSolaris->Core);
    446                 return VERR_MAP_FAILED;
    447             }
    448             pv = (void *)((uintptr_t)pv + PAGE_SIZE);
    449         }
    450     }
    451 
    452     caddr_t virtAddr = NULL;
    453     int rc = vbi_user_map(&virtAddr, fProt, paPhysAddrs, cb);
    454     if (rc != 0)
    455     {
    456         LogRel(("rtR0MemObjNativeMapUser: vbi mapping failure.\n"));
    457         kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
    458         rtR0MemObjDelete(&pMemSolaris->Core);
    459         return VERR_MAP_FAILED;
    460     }
    461 
    462     pMemSolaris->Core.u.Mapping.R0Process = (RTR0PROCESS)vbi_proc();
    463     pMemSolaris->Core.pv = virtAddr;
    464     *ppMem = &pMemSolaris->Core;
    465     kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
    466     return VINF_SUCCESS;
     483        rc = VERR_NO_MEMORY;
     484    rtR0MemObjDelete(&pMemSolaris->Core);
     485    return rc;
    467486}
    468487
     
    484503    switch (pMemSolaris->Core.enmType)
    485504    {
     505        case RTR0MEMOBJTYPE_PHYS_NC:
     506            if (pMemSolaris->Core.u.Phys.fAllocated)
     507            {
     508                uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
     509                return vbi_va_to_pa(pb);
     510            }
     511            return vbi_page_to_pa(pMemSolaris->pvHandle, iPage);
     512
    486513        case RTR0MEMOBJTYPE_PAGE:
    487514        case RTR0MEMOBJTYPE_LOW:
     
    501528        case RTR0MEMOBJTYPE_CONT:
    502529        case RTR0MEMOBJTYPE_PHYS:
    503             return pMemSolaris->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
    504 
    505         case RTR0MEMOBJTYPE_PHYS_NC:
    506             if (pMemSolaris->Core.u.Phys.fAllocated == true)
    507             {
    508                 uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
    509                 return vbi_va_to_pa(pb);
    510             }
    511             return vbi_page_to_pa(pMemSolaris->pvHandle, iPage);
    512 
     530            AssertFailed(); /* handled by the caller */
    513531        case RTR0MEMOBJTYPE_RES_VIRT:
    514532        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