⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flush.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
字号:
/*
================================================================================
*             Texas Instruments OMAP(TM) Platform Software
* (c) Copyright Texas Instruments, Incorporated. All Rights Reserved.
*
* Use of this software is controlled by the terms and conditions found
* in the license agreement under which this software has been supplied.
*
================================================================================
*/

//------------------------------------------------------------------------------
//
//  File:  flush.c
//
//  This file implements OEMCacheRangeFlush function suitable for ARM CPU
//  with separate data and instruction caches.
//
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <oal.h>


//
//  Defines
//

#define KERNEL_GLOBAL_ADDRESS		0x70000000          // Everything above this address is a kernel global address

//  Custom cache sync value to invalidate only data cache
#define TI_CACHE_SYNC_INVALIDATE	0x80000000

//
//  Functions
//

DWORD   OALGetContextID();
VOID    OALInvalidateDCacheLines(VOID* pAddress, UINT32 size);
VOID    OALClearITLBAsid(DWORD dwASID);
VOID    OALClearDTLBAsid(DWORD dwASID);

//
//  Externs
//

extern  DWORD   g_dwRangeLimit;


//------------------------------------------------------------------------------
//
//  Function:  OEMCacheRangeFlush
//
//  Implements entry point for all cache and TLB flush operations. It takes
//  following parameters:
//    
//      pAddress - starting VA on which the cache operation is to be performed
//      length - length of flush
//      flags  - specifies the cache operation to be performed:
//      
//          CACHE_SYNC_WRITEBACK: write back DATA cache
//          CACHE_SYNC_DISCARD: write back and discard DATA cache
//          CACHE_SYNC_INSTRUCTIONS: discard I-Cache
//          CACHE_SYNC_FLUSH_I_TLB: flush instruction TLB
//          CACHE_SYNC_FLUSH_D_TLB: flush data TLB
//          CACHE_SYNC_FLUSH_TLB: flush both I/D TLB
//          CACHE_SYNC_L2_WRITEBACK: write back L2 cache
//          CACHE_SYNC_L2_DISCARD: write back and discard L2 cache
//          CACHE_SYNC_ALL: perform all the above operations.
//            
//  If both pAddress and length are 0, the entire cache (or TLB, as directed by
//  flags) will be flushed. Only the kernel can set the TLB flush flags when
//  it calls this routine, and when a TLB flush is performed with 
//  length == PAGE_SIZE, pAddress is guaranteed to be on a page boundary.
//                


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 || 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 range limit, flush all
            if (length >= g_dwRangeLimit) {
                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 || 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 range limit, clean all
            if (length >= g_dwRangeLimit) {
                OALCleanDCache();
            } else {                
                // Flush all the indicated cache entries
                OALCleanDCacheLines((VOID*)address, length);
            }                
        }
    } else if ((flags & TI_CACHE_SYNC_INVALIDATE) != 0) {
        // Invalidate the selected portion of the data cache
        // Invalidate all data cache corrupts the execution 
        // of the operating system.  Only process with given 
        // buffers that are cache line aligned will be invalidated
        // all others will be clean & invalidated
        if ((length != 0) && (pAddress != NULL)) 
        {
            // Check for page alignment
            if( ((DWORD)(pAddress) % g_oalCacheInfo.L1DLineSize) == 0 )
            {
                // Invalidate the indicated cache entries
                OALInvalidateDCacheLines(pAddress, length);
            }
            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 range limit, flush all
                if (length >= g_dwRangeLimit) {
                    OALFlushDCache();
                } else {                
                    // Flush all the indicated cache entries
                    OALFlushDCacheLines((VOID*)address, length);
                }                
            }
        }                   
    }


    if ((flags & CACHE_SYNC_INSTRUCTIONS) != 0) {
        // WInvalidate the selected portions of the instruction cache
        if (length == 0 || pAddress == NULL) {
            OALFlushICache();
        } else {
            // Normalize address to cache line alignment
            UINT32 mask = g_oalCacheInfo.L1ILineSize - 1;
            UINT32 address = (UINT32)pAddress & ~mask;
            // Adjust size to reflect cache line alignment
            length += (UINT32)pAddress - address;
           // If range is bigger than cache range limit, flush all
            if (length >= g_dwRangeLimit) {
                OALFlushICache();
            } else {                
                // Flush all the indicated cache entries
                OALFlushICacheLines((VOID*)address, length);
            }                
        }
    }


    //
    //  Flush instruction TLB
    //
    if ((flags & CACHE_SYNC_FLUSH_I_TLB) != 0) {
        //  If the address is less than the kernel global space, OR with the ASID prior to clearing the TLB
        //  otherwise clear the global TLB entry (no ASID)
        if( length == 0 && pAddress == NULL)
        {
            // flush the whole TLB
            OALClearITLB();
        }
        else if( (DWORD) pAddress < KERNEL_GLOBAL_ADDRESS )
        {
            if( length == PAGE_SIZE )
            {
                // flush process TLB entry (with ASID)
                OALClearITLBEntry((VOID*)((DWORD)pAddress | OALGetContextID()));
            }
            else
            {
                // flush the whole TLB for that ASID
                OALClearITLBAsid(OALGetContextID());
            }
        }
        else
        {
            if( length == PAGE_SIZE )
            {
                // flush global TLB entry (no ASID)
                OALClearITLBEntry(pAddress);
            }
            else
            {
                // flush the whole TLB
                OALClearITLB();
            }
        }
    }

    //
    //  Flush data TLB
    //
    if ((flags & CACHE_SYNC_FLUSH_D_TLB) != 0) {
        //  If the address is less than the kernel global space, OR with the ASID prior to clearing the TLB
        //  otherwise clear the global TLB entry (no ASID)
        if( length == 0 && pAddress == NULL)
        {
            // flush the whole TLB
            OALClearDTLB();
        }
        else if( (DWORD) pAddress < KERNEL_GLOBAL_ADDRESS )
        {
            if( length == PAGE_SIZE )
            {
                // flush process TLB entry (with ASID)
                OALClearDTLBEntry((VOID*)((DWORD)pAddress | OALGetContextID()));
            }
            else
            {
                // flush the whole TLB for that ASID
                OALClearDTLBAsid(OALGetContextID());
            }
        }
        else
        {
            if( length == PAGE_SIZE )
            {
                // flush global TLB entry (no ASID)
                OALClearDTLBEntry(pAddress);
            }
            else
            {
                // flush the whole TLB
                OALClearDTLB();
            }
        }
   }


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

//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -