diff -r 000000000000 -r a41df078684a kernel/eka/include/kernel/cache_maintenance.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/kernel/cache_maintenance.h Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,891 @@ +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// eka\include\kernel\cache_maintenance.h +// +// Contains Kernel's internal API for cache maintenance + +/** + @file + @internalComponent +*/ + +#ifndef __CACHE_MAINTENANCE_H__ +#define __CACHE_MAINTENANCE_H__ + +#include +#include + +#if defined(__CPU_HAS_CACHE) +#include +#include + +/* + * Specifies the number of different cache types/levels in InternalCache class. + */ +#if defined(__CPU_ARMV7) +const TInt KNumCacheInfos=3; // ICache, DCache_PoC & DCache_PoU +#else // defined(__CPU_ARMV7) +const TInt KNumCacheInfos=2; // ICache & DCache +#endif//else defined(__CPU_ARMV7) + +const TInt KCacheInfoI=0; // InternalCache info for ICache. On ARMv7, this applies to the point-of-unification. +const TInt KCacheInfoD=1; // InternalCache info for DCache. On ARMv7, this applies to the point-of-coherency. +const TInt KCacheInfoD_PoU=2; // InternalCache info for ARMv7 DCache for the point-of-unification. + +/* + * Cache info of particular cache type or level. + */ +struct SCacheInfo + { + TUint32 iSize; // Total size in cache lines + TUint16 iAssoc; // Associativity + TUint16 iLineLength; // Line length in bytes. For multilevel cache, this is minimum length. + TUint32 iInvalidateThreshold; // Size threshold for line-by-line Invalidate (in cache lines) + TUint32 iCleanThreshold; // Size threshold for line-by-line Clean (in cache lines) + TUint32 iCleanAndInvalidateThreshold;// Size threshold for line-by-line CleanAndInvalidate (in cache lines) +#if !defined(__CPU_ARMV7) + TUint iCleanAndInvalidatePtr; // CleanAndInvalidate pointer + TUint iCleanAndInvalidateMask; // Mask to wrap CleanAndInvalidate pointer +#endif + TUint8 iLineLenLog2; // log2(iLineLength) + TUint8 iPreemptBlock; // Number of cache lines to clean before checking for system lock contention + inline TUint InvalidateThresholdBytes() + { return iInvalidateThreshold<> (KPageShift-iLineLenLog2);} + }; + +/* + * A set of static utility functions for internal (MMU controlled) cache memory. + * Unless otherwise specified, the following is assumed: + * - All DCache maintenance primitives apply to the Point of Coherency. + * - All ICache maintenance primitives apply to the Point of Unification. + * - Multilevel caches are maintained either: + * - starting from the level closest to CPU, or + * - all level are maintained simultaneously. + */ +class InternalCache + { + friend class CacheMaintenance; + friend class Cache; + +public: +/* + * Initializes internal data structure for different cache types/levels. + * Must be called during Init1 boot phase. + * @pre All internal cache memory is already configured and switched on in bootstrap. + * Single thread environment is assumed (e.g. during boot time). + */ + static void Init1(); +/* + * @return MMU's cache type register. + */ + static TUint32 TypeRegister(); + +/* + * @return Internal and external cache attributes (orred TMappingAttributes enums) + * that match aType memory type. + * @panic: If aType 4-7 is specified on platform with no __CPU_MEMORY_TYPE_REMAPPING. + */ + static TUint32 TypeToCachingAttributes(TMemoryType aType); + +#if defined(__CPU_ARMV7) + +/* + * @return MMU's cache level ID register + */ + static TUint32 LevelIDRegister(); + +/* + * @return MMU's cache size ID register for given cache type & cache level. + * @arg aType 0 for data or unified cache, 1 for instruction cache. + * @arg aLevel 0-7 where 0 indicates the closest level to CPU. + */ + static TUint32 SizeIdRegister(TUint32 aType, TUint32 aLevel); + +#endif //defined(__CPU_ARMV7) + +#if !defined(__MEMMODEL_MOVING__) +// Moving memory model is aware of cache implementation on ARMv5 and does some direct calls to +// InternalCache class. +private: +#endif + +/* + * Invalidates a memory region from cache(s) on all the cores. If ICache is specified in aMask, + * it also drains branch predictors and instruction pipelines(ISB barrier). + * If aSize is bigger than invalidate-threshold of any specified cache, it may clean + * and invalidate entire cache. + * @arg See Clean method for details. + * + * @note CacheMaintanance assumes that on H/W with NOT (defined(__CPU_ARMV7) && defined(__SMP__), + * this will clean and invalidate entire DCache if invalidate threshold is reached. + */ + static void Invalidate(TUint aMask, TLinAddr aBase, TUint aSize); + +/* + * Drains the buffers in cache memory. On ARMv6 onwards, this operation is known as DSB (Data + * Synchronisation Barrier). + * On SMP, only the buffers of the running core are drained. + */ + static void DrainBuffers(); + +/* + * Holds thresholds, cache line size,... for different types/levels of cache. + */ + static SCacheInfo Info[KNumCacheInfos]; + +private: +#if defined(__BROADCAST_CACHE_MAINTENANCE__) + +// __BROADCAST_CACHE_MAINTENANCE__ is specified when cache maintenance has to be broadcasted +// across all cores on SMP platforms by software. +// This is only defined on arm11 SMP HW as it doesn't have HW broadcasting any cache maintenance. +// CORTEX_A9 SMP has H/W broadcasting of line-by-line maintenance, while index/way is not used. + +/* + * Cleans a memory region from cache(s) & drain write buffers (DSB barrier) + * on a core that executes the call. + * @arg See Clean method for other details. + */ + static void LocalClean(TUint aMask, TLinAddr aBase, TUint aSize); + +/* + * Invalidates a memory region from cache(s) on a core that executes the call. + * @arg See Invalidate method for other details. + */ + static void LocalInvalidate(TUint aMask, TLinAddr aBase, TUint aSize); + +/* + * Cleans and invalidates a memory region from cache(s) & drain write buffers (DSB barrier) + * on a core that executes the call. + * @arg See CleanAndInvalidate method for details. + */ + static void LocalCleanAndInvalidate(TUint aMask, TLinAddr aBase, TUint aSize); + +#endif //defined(__BROADCAST_CACHE_MAINTENANCE__) + +/* + * Cleans a memory region from cache(s) & drain write buffers (DSB barrier) on all the cores. + * If aSize is bigger than clean threshold of any specified cache, it may clean entire cache. + * @arg aMask Specifies which caches to clean by orring KCacheSelectI (for ICache) and + * KCacheSelectD (for DCache or unified cache). + * @arg aBase Linear address of the start of the region to clean. + * @arg aSize Size of the region in bytes. + */ + static void Clean(TUint aMask, TLinAddr aBase, TUint aSize); + +#if defined(__CPU_ARMV7) +/* + * Cleans a memory region from DCache to the Point of Unification & drains write buffers(DSB barrier) + * on all the cores. If aSize is bigger than clean-to-the-point-to-unification threshold, it + * may clean the entire cache(s) to the point-of-unification. + * @arg See Clean method for details. + */ + static void CleanPoU(TLinAddr aBase, TUint aSize); +#endif // defined(__CPU_ARMV7) + +/* + * Invalidates a memory region from data and unified cache(s) on all the cores. It either: + * - starts from the level which is the furthest from CPU, or + * - invalidates all levels at once. + * If aSize is bigger than invalidate-threshold of any specified cache, it may clean + * and invalidate the entire cache. + * @arg aBase Linear address of the start of the region to clean. + * @arg aSize Size of the region in bytes. + */ + static void Invalidate_DCache_Reverse(TLinAddr aBase, TUint aSize); + +/* + * Cleans and invalidates a memory region from cache(s) & drain write buffers (DSB barrier) on + * all the cores. + * If ICache is specified in aMask, it drains branch predictor and instruction pipeline(ISB barrier). + * If aSize is bigger than CleanAndInvalidate threshold of any specified cache, it may clean and + * invalidate the entire cache(s). + * @arg See Clean method for details. + */ + static void CleanAndInvalidate(TUint aMask, TLinAddr aBase, TUint aSize); + +/* + * Invalidates a region of memory in instruction cache and drains branch predictor and + * instruction pipeline(ISB barrier). + * On SMP arm11mpcore, only the running core is maintained. + * On SMP ArmV7 onwards, this maintains all the cores. However, ISB barrier applies only + * to the running core. The caller must ensure ISB is broadcasted by other maens. + * @arg aBase Linear address of the start of the region. + * @arg aSize Size of the region in bytes. + */ + static void Invalidate_ICache_Region(TLinAddr aBase, TUint aSize); + +/* + * Invalidates entire content of instruction cache(s) and drains branch predictor and + * instruction pipeline(ISB barrier). + * On SMP arm11mpcore, only the running core is maintained. + * On SMP ArmV7 onwards, this maintains all the cores. However, ISB barrier applies only + * to the running core. The caller must ensure ISB is broadcasted by other maens. + */ + static void Invalidate_ICache_All(); + +/* + * Invalidates a region of memory in data and unified cache(s). + * On SMP arm11mpcore, only the running core is maintained. + * On SMP ArmV7 onwards, this maintains all the cores. + * @arg aBase Linear address of the start of the region. + * @arg aSize Size of the region in bytes. + */ + static void Invalidate_DCache_Region(TLinAddr aBase, TUint aSize); + +/* + * Cleans a region of memory in data and unified cache(s) and drains write buffers (DSB barrier). + * On SMP arm11mpcore, only the running core is maintained. + * On SMP ArmV7 onwards, this maintains all the cores. + * @arg aBase Linear address of the start of the region. + * @arg aSize The size of the region in bytes. + */ + static void Clean_DCache_Region(TLinAddr aBase, TUint aSize); + +#if defined(__CPU_ARMV7) +/* + * Cleans a region of memory in data and unified cache(s) to the point-of-unification and drains + * write buffers (DSB barrier). + * On SMP, it maintains all the cores. + * @arg aBase Linear address of the start of the region. + * @arg aSize Size of the region in bytes. + */ + static void Clean_PoU_DCache_Region(TLinAddr aBase, TUint aSize); +#endif //defined(__CPU_ARMV7) + +/* + * Cleans the entire content of data and unified caches and drains write buffers (DSB barrier). + * On SMP, only the running core is maintained. + */ + static void Clean_DCache_All(); + +#if defined(__CPU_ARMV7) +/* + * Cleans the entire content of data and unified cache(s) to the point-of-unification and drains + * write buffers (DSB barrier). + * On SMP, only the running core is maintained. + */ + static void Clean_PoU_DCache_All(); +#endif //defined(__CPU_ARMV7) + +/* + * Cleans and invalidates a region of memory in data and unified cache(s) and drains + * write buffers (DSB barrier). + * On SMP arm11mpcore, only the running core is maintained. + * On SMP ArmV7 onwards, this maintains all the cores. + */ + static void CleanAndInvalidate_DCache_Region(TLinAddr aBase, TUint aSize); + +/* + * Cleans and invalidates the entire content of data and unified cache(s) and drains + * write buffers (DSB barrier).. + * On SMP, only the running core is maintained. + */ + static void CleanAndInvalidate_DCache_All(); + +/* + * Synchronises a single line of cache(s) for instruction execution. + * On SMP, only the running core is maintained. + * + * @arg aAddr Virtual address that belongs to the cache line. + * + * NOTE: On SMP this is guaranted NOT to broadcast to other cores. + * NOTE: It assumes the same line size for ICache and DCache + */ + static void IMB_CacheLine(TLinAddr aAddr); + +private: +#if !defined(__CPU_ARMV7) +/* + * A primitive that parses the content of cache type MMU register. + */ + static void ParseCacheSizeInfo(TUint32 aValue, SCacheInfo& aInfo); +#endif + +#if defined(__CPU_MEMORY_TYPE_REMAPPING) +/* + * @return The content of Primary Region Remap Register. + */ + static TUint32 PrimaryRegionRemapRegister(); + +/* + * @return The content of Normal Memory Remap Register. + */ + static TUint32 NormalMemoryRemapRegister(); +#endif // defined(__CPU_MEMORY_TYPE_REMAPPING) + +#if defined(__CPU_ARMV7) + static TInt DmaBufferAlignementLog2; // Holds the alignement requirement for DMA buffers. +#endif + }; + +#ifdef __HAS_EXTERNAL_CACHE__ +//ARM External Cache register offsets +const TUint ARML2C_AuxiliaryControl = 0x104; + const TUint ARML2C_WaySize_Mask = 0xe0000; + const TUint ARML2C_WaySize_Shift = 17; +#if defined (__ARM_PL310_CACHE__) + const TUint ARML2C_Assoc_Mask = 0x10000; +#else + const TUint ARML2C_Assoc_Mask = 0x1e000; + const TUint ARML2C_Assoc_Shift = 13; +#endif + +const TUint ARML2C_CacheSync = 0x730; + +const TUint ARML2C_InvalidateLineByPA = 0x770; +const TUint ARML2C_CleanLineByPA = 0x7b0; +const TUint ARML2C_CleanInvalidateLineByPA = 0x7f0; + +const TUint ARML2C_CleanByIndexWay = 0x7b8; +const TUint ARML2C_CleanInvalidateByIndexWay = 0x7f8; + +const TUint ARML2C_CleanByWay = 0x7bc; +const TUint ARML2C_InvalidateByWay = 0x77c; +const TUint ARML2C_CleanInvalidateByWay = 0x7fc; + +/* + * A set of static utility functions for external cache memory. + * The following external cache controllers are supported: + * - L210 + * - L220 + * - PL310 + */ +class ExternalCache + { + friend class CacheMaintenance; + friend class Cache; + +public: +/* + * Initializes internal cache infos. Must be called during Init1 boot phase. + * @pre External cache controller is already configured and started in bootstrap. + * Single thread environment is assumed (e.g. during boot time). + */ + static void Init1(); +private: +/* + * Cleans a region of memory in cache and drains its buffers. + * If aSize is bigger than clean threshold, it may clean the entire cache. + * @arg aBase Linear address of the start of the region. + * @arg aSize Size of the region in bytes. + */ + static void Clean(TLinAddr aBase, TUint aSize); +/* + * Invalidates a region of memory in cache. + * If aSize is bigger than invalidate threshold, it may clean and invalidate the entire cache. + * @arg aBase Linear address of the start of the region. + * @arg aSize Size of the region in bytes. + */ + static void Invalidate(TLinAddr aBase, TUint aSize); + +/* + * Cleans and invalidates a region of memory in cache and drains its buffers. + * If aSize is bigger than clean and invalidate threshold, it may clean and invalidate the entire cache. + * @arg aBase Linear address of the start of the region. + * @arg aSize Size of the region in bytes. + */ + static void CleanAndInvalidate(TLinAddr aBase, TUint aSize); + +/* + * Cleans a region of contiguous physical memory in cache and drains its buffers. + * It doesn't check clean threshold. + * @arg aBase Physical address of the start of the region. + * @arg aAddr Size of the region in bytes. + */ + static void CleanPhysicalMemory(TPhysAddr aAddr, TUint aSize); + +/* + * Invalidates a region of contiguous physical memory in cache. + * It doesn't check invalidate threshold. + * @arg aBase Physical address of the start of the region. + * @arg aAddr Size of the region in bytes. + */ + static void InvalidatePhysicalMemory(TPhysAddr aAddr, TUint aSize); + +/* + * Clean and invalidates a region of contiguous physical memory in cache and drains its buffers. + * It doesn't check clean and invalidate threshold. + * @arg aBase Physical address of the start of the region. + * @arg aAddr Size of the region in bytes. + */ + static void CleanAndInvalidatePhysicalMemory(TPhysAddr aAddr, TUint aSize); + +/* + * Ensures the entire content of cache is copied back to main memory. + * On some platforms, it may not invalidate cache content. + * @pre Interupts are disabled. + */ + static void AtomicSync(); + +private: + +/* + * Generic function that cleans and/or invalidates memory region. + * @arg aBase Linear address of the start of the region. + * @arg aSize Size of the region in bytes. + * @param aCtrlReg The address of the register to access in order to trigger the maintenance + * operation. The following values are valid: + * - to invalidate the region: + * ExternalControllerBaseAddress+ARML2C_InvalidateLineByPA + * - to clean the region: + * - ExternalControllerBaseAddress+ARML2C_CleanLineByPA + * - to clean and invalidate the region: + * ExternalControllerBaseAddress+ARML2C_CleanInvalidateLineByPA + */ + static void Maintain_Region(TLinAddr aBase, TUint aSize, TInt* aCtrlReg); + +/* + * Generic function that cleans or clean&invalidates the entire content of cache. + * @param aCtrlReg The address of the register to access in order to trigger the maintenance + * operation. The following values are valid: + * - to clean: + * ExternalControllerBaseAddress+ARML2C_CleanByIndexWay + * - to clean and invalidate: + * ExternalControllerBaseAddress+ARML2C_CleanInvalidateByWay + */ + static void Maintain_All(TInt* aCtrlReg); + +/* + * Drains all the buffers in the cache controller. + */ + static void DrainBuffers(); + +#if defined(__ARM_PL310_CACHE__) + static TInt Lock(); + static void FlashLock(TInt aIrq); + static void Unlock(TInt iIrq); + const static TUint KMaxCacheLinesPerSpinLock = 10;//Max number of cache lines to maintain while spin lock is held. + static TSpinLock iLock; +#endif //defined(__ARM_PL310_CACHE__) + + static TLinAddr Base; //Base address of the external cache controller. + static SCacheInfo Info; + }; +#endif //#ifdef __HAS_EXTERNAL_CACHE__ + + +/* + * Collector class of cache memory maintenance primitives. + * They do not maintain TLBs, branch predictor nor CPU pipeline unless specified otherwise. + * No preconditions are assumed unless specified otherwise. + * @internalComponent + */ +class CacheMaintenance + { +public: +/* + * Initializes internal structures of cache configuration. Must be called during Init1 boot phase. + * + * @pre Single thread environment is assumed (e.g. during boot time). + */ + static void Init1(); + +/* + * Maintains cache(s) for a single page of physical memory that is about to change + * its mapping/caching attributes. Note that the content of the memory may be lost. + * + * The client may call this method either: + * - during the process of invalidating old mapping(s), or + * - as background maintenance of free physical memory, or + * - when the physical memory is about to be reused again. + * + * Either this method or PageToPreserveAndReuse should be called for every page that was mapped + * as normal memory. To check whether memory type is normal, use CacheMaintenance::IsNormal. + * + * The old mapping(s) should be removed before calling this method to ensure + * no accidental/speculative access occurs afterwards, as it would negate the effect of this + * procedure on cache memory. + * + * Since linear address is required for aBase input parameter, the caller may need to apply + * temporary mapping. Memory type of the temporary mapping must be as it is specified + * by CacheMaintenance::TemporaryMapping. In addition, the page colouring of the + * old mapping(s) must apply to the temporary mapping. + * + * @arg aBase Linear address of the page. + * @arg aOldType Memory type of the old mapping. + * @arg aPhysAddr Physical adress of the page or KPhysAddrInvalid. If known, physical address + * should be always specified (for performance reason). + * @arg aMask Orred values of TPageToReuseMask enum: + * EThresholdReached: + * If set, the method will trigger the maintenance on entire cache(s)(as + * opposed to maintenance of only the specified region). This will effectively + * sort out cache maintenance for all free pages waiting for PageToReuse call. + * However, some cache levels may be unaffected by this global maintenance. + * Therefore, the method still has to be called for all freed pages, but + * those that follow should have EPageHasBeenPartiallySynced set in aMask. + * EPageHasBeenPartiallySynced: + * Indicates if the page was in the queue for cache maintenance when the + * maintenance of a whole cache(s) is triggered by the previous call + * of this method with EThresholdReached in aMask. + * If true, the method will sort out only those caches not affected by + * the global cache maintenance. + * EOldAndNewMappingMatch: + * Indicates that the old and new caching attributes for the page are the same. + * If true, the method may avoid unnecessary maintenance on some platforms. + * + * @return True if page has been removed from cache memory. + * False if it wasn't because aOldType doesn't require it, or + * EOldAndNewMappingMatch is set on H/W platform where it is safe not + * to remove page from cache if the mapping remains the same. + */ + static TBool PageToReuse (TLinAddr aBase, TMemoryType aOldType, TPhysAddr aPhysAddr, TInt aMask=0); + +/* + * Indicates whether the number of pages waiting for PageToReuse maintenance is big enough to + * trigger the maintenance of the entire cache(s) on particular levels. Use this method to decide + * whether to set EThresholdReached in aMask when PageToReuse is called. + * + * @arg aPageCount Number of pages waiting in queue for CacheMaintenance::PageToReuse call. + * @return True if aPageCount is big enough to trigger the maintenance of entire cache(s) + * In that case, client may decide to call CacheMaintenance::PageToReuse with + * EThresholdReached in aMask argument. + * + * Note: H/W platforms which are not able to maintain entire cache always returns EFalse. + */ + static TBool IsPageToReuseThresholdReached(TUint aPageCount); + +/* + * Specifies additional argument in aMask when CacheMaintenance::PageToReuse is called. + */ + enum TPageToReuseMask + { + /* + * Indicates that the call of PageToReuse maintenance must trigger the maintenance + * of entire cache(s) on particular level(s). The client should set + * this only if CacheMaintenance::IsPageToReuseThresholdReached returns ETrue. + */ + EThresholdReached = 1, + /* + * Indicates that the page was in the queue for CacheMaintenance::PageToReuse + * call when the maintenance of a whole cache(s) is triggered by the previous + * call of CacheMaintenance::PageToReuse with EThresholdReached set in aMask. + */ + EPageHasBeenPartiallySynced = 2, + /* + * Indicates that the old and new cacing attributes for the page are the same. + */ + EOldAndNewMappingMatch = 4, + }; + +/* + * Preserves the content and maintains cache(s) for a single page of physical memory that + * is about to change its mapping or caching attributes. + * + * The client may call this method either: + * - during the process of invalidating old mapping(s), or + * - as background maintenance of free physical memory, or + * - when the physical memory is about to be reused again. + * + * Either PageToReuse or this method should be called for every page that was mapped as normal + * memory. To check whether memory type is normal, use CacheMaintenance::IsNormal. + + * The old mapping(s) should be removed before calling this method to ensure + * no accidental/speculative access occurs afterwards, as it would negate the effect of this + * procedure on cache memory. + * + * Since linear address is required for aBase input parameter, the caller may need to apply + * temporary mapping. Memory type of the temporary mapping must be as it is specified + * by CacheMaintenance::TemporaryMapping. In addition, the page colouring of the + * old mapping(s) must apply to the temporary mapping. + * + * @arg aBase Linear address of the page. + * @arg aOldType Memory type of the old mapping. + * @arg aPhysAddr Physical adress of the page or KPhysAddrInvalid. + */ + static void PageToPreserveAndReuse(TLinAddr aBase, TMemoryType aOldType, TPhysAddr aPhysAddr); + +/* + * @return Memory type for the temporary mapping for a physical page when PageToReuse or + * PageToPreserveAndReuse is called. + */ + static TMemoryType TemporaryMapping(); + +/* + * Specifies how the source code has been changed when CodeChanged is called. + */ + enum TCodeChangedBy + { + /* + * The content of executable memory is overwritten through cached mapping. + */ + ECPUThroughCache, + /* + * The content of executable memory is overwritten through uncached mapping. + */ + ECPUUncached, + /* + * The executable memory region is remapped. + */ + EMemoryRemap, + /* + * Code is changed by code modifier. It is assumed that: + * - the range of modified code is within a single cache line, + * - code modifier has its own way to broadcast primitives, therefore, any cache + * maintenance caused by this call will NOT be broadcasted by S/W. + */ + ECodeModifier + }; + +/* + * Maintains cache for newly loaded or changed code. It also ensures branch predictor & execution + * pipeline are drained accordingly. + * Call this method after the code has been changed and before it executes. + * + * The method may generate data abort exception if any part of defined memory region is not valid. + * + * @arg aBase Linear address of the start of code. + * @arg aSize The size of the region (in bytes) whose code has been changed. + * @arg aChangedBy Specifies the way source code has been changed. + */ + static void CodeChanged(TLinAddr aBase, TUint aSize, TCodeChangedBy aChangedBy = ECPUThroughCache); + +/* + * Ensures the changes in the specified memory region made by CPUs are visible to the + * external agents/observers. + * + * The method may generate data abort exception if any part of the region is not valid. + * + * @arg aBase Linear address of the start of memory region. + * @arg aSize The size of the region in bytes. + * @arg aMapAttr The attributes of the region(orred TMappingAttributes enum values). + * @arg aPhysAddr Physical address that corresponds to aBase linear address. KPhysAddrInvalid if + * unspecified. Specify this argument only if the region is contiguously mapped. + * + * @pre As specified by MASK_THREAD_STANDARD mask. + */ + static void MakeCPUChangesVisible(TLinAddr aBase, TUint aSize, TUint32 aMapAttr, TPhysAddr aPhysAddr = KPhysAddrInvalid); + +/* + * Prepares memory region for the external agents' write access. + * It ensures that cache doesn't accidentally overwrite physical memory that the external agent is + * about to write into. CPUs must not rely on the content of the region nor write into it. Once the + * external writes are completed, CacheMaintenance::MakeExternalChangesVisible must be called. + * + * Note that this will invalidate CPU writes in the region even if no external write occures. + * + * The method may generate data abort exception if any part of the region is not valid. + * + * @arg aBase Linear address of the start of memory region. + * @arg aSize The size of the region in bytes. + * @arg aMapAttr The attributes of the region(orred TMappingAttributes enum values). + * @arg aPhysAddr Physical address that corresponds to aBase linear address. KPhysAddrInvalid if + * unspecified. Specify this argument only if the region is contiguously mapped. + * + * @pre As specified by MASK_THREAD_STANDARD mask. + */ + static void PrepareMemoryForExternalWrites(TLinAddr aBase, TUint aSize, TUint32 aMapAttr, TPhysAddr aPhysAddr = KPhysAddrInvalid); + +/* + * Ensures the changes in the specified memory region made by the external agent are visible by CPUs. + * + * The method may generate data abort exception if any part of the region is not valid. + * + * @arg aBase Linear address of the start of memory region. + * @arg aSize The size of the region in bytes. + * @arg aMapAttr The attributes of the region(orred TMappingAttributes enum values). + * @arg aPhysAddr Physical address that corresponds to aBase linear address. KPhysAddrInvalid if + * unspecified. Specify this argument only if the region is contiguously mapped. + */ + static void MakeExternalChangesVisible(TLinAddr aBase, TUint aSize, TUint32 aMapAttr, TPhysAddr aPhysAddr = KPhysAddrInvalid); + +#if defined(__MEMMODEL_MULTIPLE__) || defined(__MEMMODEL_FLEXIBLE__) +// The following method maintain cache on page table/directory change. +// Moving memory always model maps page table as write-through memory so +// InternalCache::DrainBuffers is sufficient in that case. + +/* + * Ensures the change in page table is visible by MMU's Page-Table Walk. + * Client should call this method when a single entry in a page table has been changed. + * + * @arg aBase Linear address of page table entry that has been changed. + * + * @see CACHE_MAINTENANCE_PDE_PTE_UPDATED is alternative assembler macro for cia files. + */ + inline static void SinglePteUpdated(TLinAddr aAddr); + +/* + * Ensures the changes in a page table are visible by MMU's Page-Table Walk. + * Client should call this method when two and more consecutive entries in a page table + * have been changed. + * + * @arg aBase Linear address of the first page table entry that has been changed. + * @arg aSize The size of the region (in bytes) of the altered page table entries. + */ + inline static void MultiplePtesUpdated(TLinAddr aAddr, TUint aSize); + +/* + * Ensures the change in page directory is visible by MMU's Page-Table Walk. + * Client should call this method when a single entry in a page directory has been changed. + * In case of page mapping, it should also ensure that the content of page table pointed by the new + * value is either initialised or marked as invalid (no random values are allowed). + * + * @arg aBase Linear address of page directory entry that has been changed. + * + * @see CACHE_MAINTENANCE_PDE_PTE_UPDATED is alternative assembler macro for cia files. + */ + inline static void SinglePdeUpdated(TLinAddr aAddr); + +/* + * Ensures the change in page directory is visible by MMU's Page-Table Walk. + * Client should call this method when two and more consecutive entries in a directory table + * have been changed. + * In case of page mapping, it should also ensure that the content of page table pointed by the new + * value is either initialised or marked as invalid (no random values are allowed). + * + * @arg aBase Linear address of the first page directory entry that has been changed. + * @arg aSize The size of the region (in bytes) of the altered page table entries. + */ + inline static void PdesInitialised(TLinAddr aPde, TUint aSize); + +#endif //#if defined(__MEMMODEL_MULTIPLE__) || defined(__MEMMODEL_FLEXIBLE__) + +/* + * @arg aType Memory Type + * @return False if memory type is guaranteed not to be normal memory. + * True if memory type may be normal memory. + * + * @note Normal uncached memory is not held in cache but may use cache buffers. + */ + static TBool IsNormal(TMemoryType aType); + +/* + * @arg aType Memory Type + * @return False if memory type is guaranteed not to be cached at any level. + * True if memory type may be cached at any level. + */ + static TBool IsCached(TMemoryType aType); + +#if defined(__MEMMODEL_MOVING__) || defined(__MEMMODEL_MULTIPLE__) + +/* + * Ensures the changes in the specified memory region made by CPUs are visible to the + * external agents/observers. The region is also removed from the caches. + * + * On multiple memory model, memory region should be unmapped from its original mapping and + * temporary mapping should be applied, as described in PageToReuse & PageToPreserveAndReuse methods. + * On moving memory model, call this function before unmappppping occures. + * + * The method may generate data abort exception if any part of the region is not valid. + * + * @arg aBase Linear address of the start of memory region. + * @arg aSize The size of the region in bytes. + * @arg aMapAttr The attributes of the region(orred TMappingAttributes enum values). + */ + static void MemoryToPreserveAndReuse(TLinAddr aLinAddr, TUint aSize, TUint32 aMapAttr); + +/* + * Ensures the entire content of physical (VIPT & PIPT) data cache(s) is written down + * to memory and the cache is emptied. + */ + static void SyncPhysicalCache_All(); + +/* + * @return Performance threshold for SyncPhysicalCache_All method in page count. + * If the number of pages to be recommitted is bigger than the threshold, + * the client may decide to use CacheMaintenance::SyncPhysicalCache_All + * instead of CacheMaintenance::PageToReuse. + */ + static TUint SyncAllPerformanceThresholdPages() + { + return InternalCache::Info[KCacheInfoD].InvalidateThresholdPages(); + } + +#endif // #if defined(__MEMMODEL_MOVING__) || defined(__MEMMODEL_MULTIPLE__) + +#if defined(__MEMMODEL_MOVING__) +// Moving memory model is based on ARMv5 architecture and requires virtual cache memory to be +// flushed away on process switch. For that reason, this memory model needs separate sets +// of primitives for virtual (VIVT) and physical (VIPT or PIPT) cache. + +/* + * Perform any cache/memory synchronisation required prior to a change + * in virtual to physical address mappings. + * Enter and return with system locked. + */ + static void OnProcessSwitch(); + +/* + * Maintains virtual cache for a single page of physical memory that is about to change + * its mapping/caching attributes. It is presumed the memory is fully cached. + * @arg aBase Linear address of the page. + */ + static void PageToReuseVirtualCache(TLinAddr aBase); + +/* + * Maintains virtual cache for a single page of physical memory that is about to change + * its mapping/caching attributes. In addition, the content of physical memory is preserved. + * It is presumed the memory is fully cached. + * @arg aBase Linear address of the page. + */ + static void PageToPreserveAndReuseVirtualCache(TLinAddr aBase); + +/* + * Maintains physical cache for a single page of physical memory that is about to change + * its mapping/caching attributes. It is presumed the memory is fully cached. + * @arg aPhysAddr Physical adress of the page. + */ + static void PageToReusePhysicalCache(TPhysAddr aPhysAddr); + +#endif // defined(__MEMMODEL_MOVING__) + +#if defined(__MEMMODEL_DIRECT__) +/* + * Maintains cache(s) for a memory region that is about to change its mapping/caching attributes. + * @arg aBase Linear address of the page. + * @arg aSize The size of the region. + */ + static void MemoryToReuse (TLinAddr aBase, TUint aSize); +#endif //defined(__MEMMODEL_DIRECT__) + +private: + +#if defined (__CPU_OUTER_CACHE_IS_INTERNAL_CACHE) +/* + * Combines inner and outer caching attributes. + * + * @arg aMapAttr On entry, holds inner and outer caching attributes (orred + * TMappingAttributes enum values). + * On exit, inner caching attribute holds combined inner and outer values, + * while outer caching attribute remains unchanged. + * + * Note: On __CPU_CORTEX_A8__ both inner & outer caches are MMU controlled. + */ + static void CombineCacheAttributes (TUint32& aMapAttr); +#endif + }; + + +#if defined(__SMP__) && !defined(__BROADCAST_CACHE_MAINTENANCE__) +//Platforms that rely on H/W broadcast of cache maintenance have to broadcast ISB by softwer. +#define __BROADCAST_ISB + +class T_ISB_IPI : public TGenericIPI + { +public: + T_ISB_IPI(); + static void ISBIsr(TGenericIPI*); + void Do(); + }; +#endif //defined(__SMP__) && !defined(__BROADCAST_CACHE_MAINTENANCE__) + +#endif // defined(__CPU_HAS_CACHE) + +#endif //#ifndef __CACHE_MAINTENANCE_H__