示例#1
0
void OEMCacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags)
{

    // cache maintenance constants
    const DWORD PAGE_SIZE = 4096;       // 4KB pages used by winCE on XScale

    // these are defined in assembly language
    extern void OALFlushICache(void);
    extern void XScaleFlushICacheLines(LPVOID, DWORD, DWORD);
    extern void XScaleFlushDCache(DWORD, DWORD, DWORD);
    extern void XScaleFlushDCacheLines(PVOID, DWORD, DWORD);
    extern void XScaleCleanDCacheLines(LPVOID, DWORD, DWORD);
    extern void OALClearITLB(void);
    extern void OALClearITLBEntry(LPVOID);
    extern void OALClearDTLB(void);
    extern void OALClearDTLBEntry(LPVOID);
    extern void OALClearUTLB(void);
    extern const PVOID gpvCacheFlushBaseMemoryAddress;


    ///////////////////////////////////////////////////////////////////////////
    //  Flush DCACHE 
    ///////////////////////////////////////////////////////////////////////////
    
    if(dwFlags & CACHE_SYNC_DISCARD)
    {
        // Write-back and invalidate either all or a range
        //
        if (!(dwLength || (DWORD)pAddr))    // If length and address are both zero, flush all.
        {
            XScaleFlushDCache(DCACHE_LINES, ARMCacheInfo.dwL1DCacheLineSize, (DWORD) gpvCacheFlushBaseMemoryAddress);
        }
        else if (dwLength >= (DWORD) ARMCacheInfo.dwL1DCacheSize)
        {
            XScaleFlushDCache(DCACHE_LINES, ARMCacheInfo.dwL1DCacheLineSize, (DWORD) gpvCacheFlushBaseMemoryAddress);
        }
        else
        {
            // normalize address and length
            DWORD dwNormalizedAddress, dwNormalizedLength;
            dwNormalizedAddress = (DWORD) pAddr & ~(ARMCacheInfo.dwL1DCacheLineSize - 1);
            dwNormalizedLength = dwLength + ((DWORD) pAddr - dwNormalizedAddress);

            // invalidate all the indicated cache entries
            XScaleFlushDCacheLines((LPVOID) dwNormalizedAddress, dwNormalizedLength, ARMCacheInfo.dwL1DCacheLineSize);
        }
    }
    else if(dwFlags & CACHE_SYNC_WRITEBACK)
    {
        // write back the address range
        //
        if (!(dwLength || (DWORD)pAddr))    // If length and address are both zero, flush all.
        {
            XScaleFlushDCache(DCACHE_LINES, ARMCacheInfo.dwL1DCacheLineSize, (DWORD) gpvCacheFlushBaseMemoryAddress);
        }
        else if (dwLength >= (DWORD) ARMCacheInfo.dwL1DCacheSize)
        {
            XScaleFlushDCache(DCACHE_LINES, ARMCacheInfo.dwL1DCacheLineSize, (DWORD) gpvCacheFlushBaseMemoryAddress);
        }
        else
        {
            // normalize address to cache line alignment and adjust the length accordingly
            DWORD dwNormalizedAddress = (DWORD) pAddr & ~(ARMCacheInfo.dwL1DCacheLineSize - 1);
            DWORD dwNormalizedLength = dwLength + ((DWORD) pAddr - dwNormalizedAddress);

            // write back all the indicated cache entries
            XScaleCleanDCacheLines((LPVOID) dwNormalizedAddress, dwNormalizedLength, ARMCacheInfo.dwL1DCacheLineSize);
        }
    }


    ///////////////////////////////////////////////////////////////////////////
    //  Flush ICACHE
    ///////////////////////////////////////////////////////////////////////////

    if(dwFlags & CACHE_SYNC_INSTRUCTIONS)
    {

        if (!(dwLength || (DWORD)pAddr))    // If length and address are both zero, flush all.
        {
            OALFlushICache();
        }
        else if (dwLength >= (DWORD) ARMCacheInfo.dwL1ICacheSize)
        {
            OALFlushICache();
        }
        else
        {
            // normalize address and length
            DWORD dwNormalizedAddress, dwNormalizedLength;
            dwNormalizedAddress = (DWORD) pAddr & ~(ARMCacheInfo.dwL1ICacheLineSize - 1);
            dwNormalizedLength = dwLength + ((DWORD) pAddr - dwNormalizedAddress);
            
            // invalidate all the indicated cache entries
            XScaleFlushICacheLines((LPVOID) dwNormalizedAddress, dwNormalizedLength, ARMCacheInfo.dwL1ICacheLineSize);
        }
    }


    ///////////////////////////////////////////////////////////////////////////
    //  Flush I-TLB
    ///////////////////////////////////////////////////////////////////////////

    if(dwFlags & CACHE_SYNC_FLUSH_I_TLB)
    {

        if(dwLength == PAGE_SIZE)
        {
            // flush a single entry from the I-TLB
            //
            OALClearITLBEntry(pAddr);         
        }
        else
        {
            // flush the entire TLB
            //
            OALClearITLB();
        }
    }


    ///////////////////////////////////////////////////////////////////////////
    //  Flush D-TLB
    ///////////////////////////////////////////////////////////////////////////

    if(dwFlags & CACHE_SYNC_FLUSH_D_TLB)
    {

        if(dwLength == PAGE_SIZE)
        {
            // flush a single entry from the I-TLB
            //
            OALClearDTLBEntry(pAddr);
        }
        else
        {
            // flush the entire TLB
            //
            OALClearDTLB();
        }
    }

}
示例#2
0
void OEMCacheRangeFlush(VOID *pAddress, DWORD length, DWORD flags)
{
    OALMSG(OAL_CACHE&&OAL_VERBOSE, (
        L"+OEMCacheRangeFlush(0x%08x, %d, 0x%08x)\r\n", pAddress, length, flags
    ));

    if ((flags & CACHE_SYNC_DISCARD) != 0) {
        // Write back and invalidate the selected portions of the data cache
        if (length == 0) {
            if (pAddress == NULL) OALFlushDCache();
        } else {
            // Normalize address to cache line alignment
            UINT32 mask = g_oalCacheInfo.L1DLineSize - 1;
            UINT32 address = (UINT32)pAddress & ~mask;
            // Adjust size to reflect cache line alignment
            length += (UINT32)pAddress - address;
            // If range is bigger than cache size flush all
            if (length >= g_oalCacheInfo.L1DSize) {
                OALFlushDCache();
            } else {                
                // Flush all the indicated cache entries
                OALFlushDCacheLines((VOID*)address, length);
            }                
        }
    } else if ((flags & CACHE_SYNC_WRITEBACK) != 0) {
        // Write back the selected portion of the data cache
        if (length == 0) {
            if (pAddress == NULL) OALCleanDCache();
        } else {
            // Normalize address to cache line alignment
            UINT32 mask = g_oalCacheInfo.L1DLineSize - 1;
            UINT32 address = (UINT32)pAddress & ~mask;
            // Adjust size to reflect cache line alignment
            length += (UINT32)pAddress - address;
            // If range is bigger than cache size clean all
            if (length >= g_oalCacheInfo.L1DSize) {
                OALCleanDCache();
            } else {                
                // Flush all the indicated cache entrie
                OALCleanDCacheLines((VOID*)address, length);
            }                
        }
    }
    
    if ((flags & CACHE_SYNC_INSTRUCTIONS) != 0) {
        if (length == 0) {
            if (pAddress == NULL) OALFlushICache();
        } else {
            // Normalize address to cache line alignment
            UINT32 mask = g_oalCacheInfo.L1ILineSize - 1;
            UINT32 address = (UINT32)pAddress & ~mask;
            length += (UINT32)pAddress - address;
            if (length >= g_oalCacheInfo.L1ISize) {
                OALFlushICache();
            } else {        
                OALFlushICacheLines((VOID*)address, length);
            }                
        }
    }

    if ((flags & CACHE_SYNC_FLUSH_I_TLB) != 0) {
        if (length == PAGE_SIZE) {
            // flush one TLB entry
            OALClearITLBEntry(pAddress);
        } else {
            // flush the whole TLB
            OALClearITLB();
        }
    }

    if ((flags & CACHE_SYNC_FLUSH_D_TLB) != 0) {
        // check first for TLB updates forced by paging
        if (length == PAGE_SIZE) {
            // flush one TLB entry
            OALClearDTLBEntry(pAddress);
        } else {
            // flush the whole TLB
            OALClearDTLB();
        }
    }

    OALMSG(OAL_CACHE&&OAL_VERBOSE, (L"-OEMCacheRangeFlush\r\n"));
}