VirtualBox

Ignore:
Timestamp:
Jun 8, 2012 1:01:44 PM (13 years ago)
Author:
vboxsync
Message:

Runtime/r0drv/Solaris: Implemented large page support. Fixed possible freeing of wrong pages with regular 4K pages.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h

    r41146 r41622  
    4141{
    4242    uint64_t *paPhysAddrs;
     43    size_t    cbPageSize;
    4344    uint_t    fPageAccess;
    4445} SEGVBOX_CRARGS;
     
    4849{
    4950    uint_t    fPageAccess;
     51    size_t    cbPageSize;
    5052} SEGVBOX_DATA;
    5153typedef SEGVBOX_DATA *PSEGVBOX_DATA;
     
    6567    AssertPtr(pData);
    6668
     69    /*
     70     * Currently we only map _4K pages but this segment driver can handle any size
     71     * supported by the Solaris HAT layer.
     72     */
     73    size_t cbPageSize  = pArgs->cbPageSize;
     74    size_t uPageShift  = 0;
     75    switch (cbPageSize)
     76    {
     77        case _4K: uPageShift = 12; break;
     78        case _2M: uPageShift = 21; break;
     79        default:  AssertReleaseMsgFailed(("Unsupported page size for mapping cbPageSize=%llx\n", cbPageSize)); break;
     80    }
     81
    6782    hat_map(pAddrSpace->a_hat, pSeg->s_base, pSeg->s_size, HAT_MAP);
    6883    pData->fPageAccess = pArgs->fPageAccess | PROT_USER;
     84    pData->cbPageSize  = cbPageSize;
    6985
    7086    pSeg->s_ops  = &s_SegVBoxOps;
     
    7591     */
    7692    caddr_t virtAddr = pSeg->s_base;
    77     pgcnt_t cPages   = (pSeg->s_size + PAGESIZE - 1) >> PAGESHIFT;
    78     for (pgcnt_t iPage = 0; iPage < cPages; ++iPage, virtAddr += PAGESIZE)
     93    pgcnt_t cPages   = (pSeg->s_size + cbPageSize - 1) >> uPageShift;
     94    for (pgcnt_t iPage = 0; iPage < cPages; ++iPage, virtAddr += cbPageSize)
    7995    {
    80         hat_devload(pAddrSpace->a_hat, virtAddr, PAGESIZE, pArgs->paPhysAddrs[iPage] >> PAGESHIFT,
    81                     pData->fPageAccess | HAT_UNORDERED_OK, HAT_LOAD | HAT_LOAD_LOCK);
     96        hat_devload(pAddrSpace->a_hat, virtAddr, cbPageSize, pArgs->paPhysAddrs[iPage] >> uPageShift,
     97                    pData->fPageAccess | HAT_UNORDERED_OK, HAT_LOAD_LOCK);
    8298    }
    8399
     
    98114
    99115    pDstData->fPageAccess  = pSrcData->fPageAccess;
     116    pDstData->cbPageSize   = pSrcData->cbPageSize;
    100117    pDstSeg->s_ops         = &s_SegVBoxOps;
    101118    pDstSeg->s_data        = pDstData;
     
    107124static int rtR0SegVBoxSolUnmap(seg_t *pSeg, caddr_t virtAddr, size_t cb)
    108125{
    109     /** @todo make these into release assertions. */
    110     if (   virtAddr < pSeg->s_base
    111         || virtAddr + cb > pSeg->s_base + pSeg->s_size
    112         || (cb & PAGEOFFSET) || ((uintptr_t)virtAddr & PAGEOFFSET))
     126    PSEGVBOX_DATA pData = pSeg->s_data;
     127
     128    AssertRelease(pData);
     129    AssertReleaseMsg(virtAddr >= pSeg->s_base, ("virtAddr=%p s_base=%p\n", virtAddr, pSeg->s_base));
     130    AssertReleaseMsg(virtAddr + cb <= pSeg->s_base + pSeg->s_size, ("virtAddr=%p cb=%llu s_base=%p s_size=%llu\n", virtAddr,
     131                                                                    cb, pSeg->s_base, pSeg->s_size));
     132    size_t cbPageOffset = pData->cbPageSize - 1;
     133    AssertRelease(!(cb & cbPageOffset));
     134    AssertRelease(!((uintptr_t)virtAddr & cbPageOffset));
     135
     136    if (   virtAddr != pSeg->s_base
     137        || cb       != pSeg->s_size)
    113138    {
    114         panic("rtRt0SegVBoxSolUnmap");
     139        return ENOTSUP;
    115140    }
    116 
    117     if (virtAddr != pSeg->s_base || cb != pSeg->s_size)
    118         return ENOTSUP;
    119141
    120142    hat_unload(pSeg->s_as->a_hat, virtAddr, cb, HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK);
     
    138160     * We would demand fault if the (u)read() path would SEGOP_FAULT() on buffers mapped in via our
    139161     * segment driver i.e. prefaults before DMA. Don't fail in such case where we're called directly,
    140      * see #5047.
     162     * see @bugref{5047}.
    141163     */
    142164    return 0;
     
    176198static size_t rtR0SegVBoxSolInCore(seg_t *pSeg, caddr_t virtAddr, size_t cb, char *pVec)
    177199{
    178     size_t cbLen = (cb + PAGEOFFSET) & PAGEMASK;
    179     for (virtAddr = 0; cbLen != 0; cbLen -= PAGESIZE, virtAddr += PAGESIZE)
     200    PSEGVBOX_DATA pData = pSeg->s_data;
     201    AssertRelease(pData);
     202    size_t uPageOffset  = pData->cbPageSize - 1;
     203    size_t uPageMask    = ~uPageOffset;
     204    size_t cbLen        = (cb + uPageOffset) & uPageMask;
     205    for (virtAddr = 0; cbLen != 0; cbLen -= pData->cbPageSize, virtAddr += pData->cbPageSize)
    180206        *pVec++ = 1;
    181207    return cbLen;
     
    295321#endif /* !___r0drv_solaris_memobj_r0drv_solaris_h */
    296322
    297 
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