kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp
changeset 201 43365a9b78a3
parent 109 b3a1d9898418
child 245 647ab20fee2e
equal deleted inserted replaced
200:73ea206103e6 201:43365a9b78a3
    12 //
    12 //
    13 // Description:
    13 // Description:
    14 //
    14 //
    15 
    15 
    16 #include <plat_priv.h>
    16 #include <plat_priv.h>
       
    17 #include <kernel/cache.h>
    17 #include "mm.h"
    18 #include "mm.h"
    18 #include "mmu.h"
    19 #include "mmu.h"
    19 
    20 
    20 #include "mmanager.h"
    21 #include "mmanager.h"
    21 #include "mobject.h"
    22 #include "mobject.h"
    23 #include "mpager.h"
    24 #include "mpager.h"
    24 #include "mswap.h"
    25 #include "mswap.h"
    25 
    26 
    26 
    27 
    27 /**
    28 /**
       
    29 Log2 of minimum number of pages to attempt to write at a time.
       
    30 
       
    31 The value of 2 gives a minimum write size of 16KB.
       
    32 */
       
    33 const TUint KMinPreferredWriteShift = 2;
       
    34 
       
    35 /**
       
    36 Log2 of maximum number of pages to attempt to write at a time.
       
    37 
       
    38 The value of 4 gives a maximum write size of 64KB.
       
    39 */
       
    40 const TUint KMaxPreferredWriteShift = 4;
       
    41 
       
    42 __ASSERT_COMPILE((1 << KMaxPreferredWriteShift) <= KMaxPagesToClean);
       
    43 
       
    44 
       
    45 /**
       
    46 Whether the CPU has the page colouring restriction, where pages must be mapped in sequential colour
       
    47 order.
       
    48 */
       
    49 #ifdef __CPU_CACHE_HAS_COLOUR	
       
    50 const TBool KPageColouringRestriction = ETrue;
       
    51 #else
       
    52 const TBool KPageColouringRestriction = EFalse;
       
    53 #endif
       
    54 
       
    55 
       
    56 /**
    28 Manages the swap via the data paging device.
    57 Manages the swap via the data paging device.
    29 */
    58 */
    30 class DSwapManager
    59 class DSwapManager
    31 	{
    60 	{
    32 public:
    61 public:
    55 
    84 
    56 	TInt ReserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount);
    85 	TInt ReserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount);
    57 	TInt UnreserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount);
    86 	TInt UnreserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount);
    58 	TBool IsReserved(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount);
    87 	TBool IsReserved(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount);
    59 
    88 
    60 	TInt ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, DPageReadRequest* aRequest, TPhysAddr* aPhysAddrs);
    89 	TInt ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs);
    61 	TInt WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TBool aBackground);
    90 	TInt WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs, TBool aBackground);
    62 
    91 
    63 	void GetSwapInfo(SVMSwapInfo& aInfoOut);
    92 	void GetSwapInfo(SVMSwapInfo& aInfoOut);
    64 	TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds);
    93 	TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds);
       
    94 	void SetSwapAlign(TUint aSwapAlign);
    65 
    95 
    66 private:
    96 private:
    67 	inline TSwapState SwapState(TUint aSwapData);
    97 	inline TSwapState SwapState(TUint aSwapData);
    68 	inline TInt SwapIndex(TUint aSwapData);
    98 	inline TInt SwapIndex(TUint aSwapData);
    69 	inline TUint SwapData(TSwapState aSwapState, TInt aSwapIndex);
    99 	inline TUint SwapData(TSwapState aSwapState, TInt aSwapIndex);
    70 	
   100 	
    71 	TInt AllocSwapIndex(TInt aCount);
   101 	TInt AllocSwapIndex(TUint aCount);
    72 	void FreeSwapIndex(TInt aSwapIndex);
   102 	void FreeSwapIndex(TInt aSwapIndex);
    73 	void CheckSwapThresholdsAndUnlock(TUint aInitial);
   103 	void CheckSwapThresholdsAndUnlock(TUint aInitial);
    74 	
   104 	
    75 	void DoDeleteNotify(TUint aSwapIndex);
   105 	void DoDeleteNotify(TUint aSwapIndex);
    76 	TInt DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aSwapIndex, TBool aBackground);
   106 	TInt DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aPageIndex, TPhysAddr* aPhysAddrs, TInt aSwapIndex, TBool aBackground);
    77 	
   107 	
    78 private:
   108 private:
    79 	DPagingDevice* iDevice;			///< Paging device used to read and write swap pages
   109 	DPagingDevice* iDevice;			///< Paging device used to read and write swap pages
    80 	
   110 	
    81 	NFastMutex iSwapLock;			///< Fast mutex protecting access to all members below
   111 	NFastMutex iSwapLock;			///< Fast mutex protecting access to all members below
    82 	TUint iFreePageCount;			///< Number of swap pages that have not been reserved
   112 	TUint iFreePageCount;			///< Number of swap pages that have not been reserved
    83 	TBitMapAllocator* iBitMap;		///< Bitmap of swap pages that have been allocated
   113 	TBitMapAllocator* iBitMap;		///< Bitmap of swap pages that have been allocated
       
   114 	TUint iSwapAlign;				///< Log2 number of pages to align swap writes to
    84 	TUint iAllocOffset;				///< Next offset to try when allocating a swap page
   115 	TUint iAllocOffset;				///< Next offset to try when allocating a swap page
    85  	TUint iSwapThesholdLow;
   116  	TUint iSwapThesholdLow;
    86  	TUint iSwapThesholdGood;
   117  	TUint iSwapThesholdGood;
    87 	};
   118 	};
    88 
   119 
    89 
   120 
    90 /**
   121 /**
    91 Manager for demand paged memory objects which contain writeable data.
   122    Manager for demand paged memory objects which contain writeable data.
    92 The contents of the memory are written to a backing store whenever its
   123    The contents of the memory are written to a backing store whenever its
    93 pages are 'paged out'.
   124    pages are 'paged out'.
    94 
   125 
    95 @see DSwapManager
   126    @see DSwapManager
    96 */
   127 */
    97 class DDataPagedMemoryManager : public DPagedMemoryManager
   128 class DDataPagedMemoryManager : public DPagedMemoryManager
    98 	{
   129 	{
    99 private:
   130 private:
   100 	// from DMemoryManager...
   131 	// from DMemoryManager...
   112 	virtual TBool IsAllocated(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
   143 	virtual TBool IsAllocated(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
   113 
   144 
   114 public:
   145 public:
   115 	void GetSwapInfo(SVMSwapInfo& aInfoOut);
   146 	void GetSwapInfo(SVMSwapInfo& aInfoOut);
   116 	TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds);
   147 	TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds);
       
   148 	TBool PhysicalAccessSupported();
       
   149 	TBool UsePhysicalAccess();
       
   150 	void SetUsePhysicalAccess(TBool aUsePhysicalAccess);
       
   151 	TUint PreferredWriteSize();
       
   152 	TUint PreferredSwapAlignment();
       
   153 	TInt SetWriteSize(TUint aWriteShift);
   117 
   154 
   118 private:
   155 private:
   119 	TInt WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest *aRequest, TBool aAnyExecutable, TBool aBackground);
   156 	TInt WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest *aRequest, TBool aAnyExecutable, TBool aBackground);
   120 
   157 
   121 private:
   158 private:
   128 	/**
   165 	/**
   129 	The instance of #DSwapManager being used by this manager.
   166 	The instance of #DSwapManager being used by this manager.
   130 	*/
   167 	*/
   131 	DSwapManager* iSwapManager;
   168 	DSwapManager* iSwapManager;
   132 
   169 
       
   170 	/**
       
   171 	Whether to read and write pages by physical address without mapping them first.
       
   172 
       
   173 	Set if the paging media driver supports it.
       
   174 	*/
       
   175 	TBool iUsePhysicalAccess;
       
   176 
   133 public:
   177 public:
   134 	/**
   178 	/**
   135 	The single instance of this manager class.
   179 	The single instance of this manager class.
   136 	*/
   180 	*/
   137 	static DDataPagedMemoryManager TheManager;
   181 	static DDataPagedMemoryManager TheManager;
   173 	iAllocOffset = 0;
   217 	iAllocOffset = 0;
   174 	return KErrNone;
   218 	return KErrNone;
   175 	}
   219 	}
   176 
   220 
   177 
   221 
       
   222 void DSwapManager::SetSwapAlign(TUint aSwapAlign)
       
   223 	{
       
   224 	TRACE(("WDP: Set swap alignment to %d (%d KB)", aSwapAlign, 4 << aSwapAlign));
       
   225 	NKern::FMWait(&iSwapLock);
       
   226 	iSwapAlign = aSwapAlign;
       
   227 	NKern::FMSignal(&iSwapLock);
       
   228 	}
       
   229 
       
   230 
   178 inline DSwapManager::TSwapState DSwapManager::SwapState(TUint aSwapData)
   231 inline DSwapManager::TSwapState DSwapManager::SwapState(TUint aSwapData)
   179 	{
   232 	{
   180 	TSwapState state = (TSwapState)(aSwapData & ESwapStateMask);
   233 	TSwapState state = (TSwapState)(aSwapData & ESwapStateMask);
   181 	__NK_ASSERT_DEBUG(state >= EStateWritten || (aSwapData & ~ESwapStateMask) == 0);
   234 	__NK_ASSERT_DEBUG(state >= EStateWritten || (aSwapData & ~ESwapStateMask) == 0);
   182 	return state;
   235 	return state;
   202 
   255 
   203 @param aCount The number of page's worth of space to allocate.
   256 @param aCount The number of page's worth of space to allocate.
   204 
   257 
   205 @return The swap index of the first location allocated.
   258 @return The swap index of the first location allocated.
   206 */
   259 */
   207 TInt DSwapManager::AllocSwapIndex(TInt aCount)
   260 TInt DSwapManager::AllocSwapIndex(TUint aCount)
   208 	{
   261 	{
   209 	__NK_ASSERT_DEBUG(aCount > 0 && aCount <= KMaxPagesToClean);
   262 	TRACE2(("DSwapManager::AllocSwapIndex %d", aCount));
       
   263 		
       
   264 	__NK_ASSERT_DEBUG(aCount <= KMaxPagesToClean);
   210 	NKern::FMWait(&iSwapLock);
   265 	NKern::FMWait(&iSwapLock);
   211 
   266 
   212 	// search for run of aCount from iAllocOffset to end
   267 	TInt carry;
   213 	TInt carry = 0;
       
   214 	TInt l = KMaxTInt;
   268 	TInt l = KMaxTInt;
   215 	TInt swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, iAllocOffset);
   269 	TInt swapIndex = -1;
   216 
   270 
   217 	// if search failed, retry from beginning
   271 	// if size suitable for alignment, search for aligned run of aCount from iAllocOffset to end,
       
   272 	// then from beginning
       
   273 	// 
       
   274 	// note that this aligns writes that at least as large as the alignment size - an alternative
       
   275 	// policy might be to align writes that are an exact multiple of the alignment size
       
   276 	if (iSwapAlign && aCount >= (1u << iSwapAlign))
       
   277 		{
       
   278 		carry = 0;
       
   279 		swapIndex = iBitMap->AllocAligned(aCount, iSwapAlign, 0, EFalse, carry, l, iAllocOffset);
       
   280 		if (swapIndex < 0)
       
   281 			{
       
   282 			carry = 0;
       
   283 			swapIndex = iBitMap->AllocAligned(aCount, iSwapAlign, 0, EFalse, carry, l, 0);
       
   284 			}
       
   285 		}
       
   286 	
       
   287 	// if not doing aligned search, or aligned search failed, retry without alignment
   218 	if (swapIndex < 0)
   288 	if (swapIndex < 0)
   219 		{
   289 		{
   220 		iAllocOffset = 0;
       
   221 		carry = 0;
   290 		carry = 0;
   222 		swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, iAllocOffset);
   291 		swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, iAllocOffset);
       
   292 		if (swapIndex < 0)
       
   293 			{
       
   294 			carry = 0;
       
   295 			swapIndex = iBitMap->AllocAligned(aCount, 0, 0, EFalse, carry, l, 0);
       
   296 			}
   223 		}
   297 		}
   224 
   298 
   225 	// if we found one then mark it as allocated and update iAllocOffset
   299 	// if we found one then mark it as allocated and update iAllocOffset
   226 	if (swapIndex >= 0)
   300 	if (swapIndex >= 0)
   227 		{
   301 		{
   228 		__NK_ASSERT_DEBUG(swapIndex <= (iBitMap->iSize - aCount));
   302 		__NK_ASSERT_DEBUG(swapIndex <= (TInt)(iBitMap->iSize - aCount));
   229 		iBitMap->Alloc(swapIndex, aCount);
   303 		iBitMap->Alloc(swapIndex, aCount);
   230 		iAllocOffset = (swapIndex + aCount) % iBitMap->iSize;
   304 		iAllocOffset = (swapIndex + aCount) % iBitMap->iSize;
   231 		}
   305 		}
   232 	
   306 	
   233 	NKern::FMSignal(&iSwapLock);
   307 	NKern::FMSignal(&iSwapLock);
   234 	__NK_ASSERT_DEBUG(swapIndex >= 0 || aCount > 1); // can't fail to allocate single page
   308 	__NK_ASSERT_DEBUG(swapIndex >= 0 || aCount > 1); // can't fail to allocate single page
       
   309 
       
   310 	TRACE2(("DSwapManager::AllocSwapIndex returns %d", swapIndex));	
   235 	return swapIndex;
   311 	return swapIndex;
   236 	}
   312 	}
   237 
   313 
   238 
   314 
   239 /**
   315 /**
   382 @param aCount	The number of pages to read.
   458 @param aCount	The number of pages to read.
   383 @param aLinAddr	The address to copy the pages to.
   459 @param aLinAddr	The address to copy the pages to.
   384 @param aRequest	The request to use for the read.
   460 @param aRequest	The request to use for the read.
   385 @param aPhysAddrs	An array of the physical addresses for each page to read in.
   461 @param aPhysAddrs	An array of the physical addresses for each page to read in.
   386 */
   462 */
   387 TInt DSwapManager::ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, DPageReadRequest* aRequest, TPhysAddr* aPhysAddrs)
   463 TInt DSwapManager::ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs)
   388 	{
   464 	{
   389 	__ASSERT_CRITICAL;
   465 	__ASSERT_CRITICAL;
   390 	
   466 	
   391 	TInt r = KErrNone;
   467 	TInt r = KErrNone;
   392 	const TUint readUnitShift = iDevice->iReadUnitShift;
   468 	const TUint readUnitShift = iDevice->iReadUnitShift;
   456 @param  aBackground Whether this is being called in the background by the page cleaning thread
   532 @param  aBackground Whether this is being called in the background by the page cleaning thread
   457                     as opposed to on demand when a free page is required.
   533                     as opposed to on demand when a free page is required.
   458 
   534 
   459 @pre Called with page cleaning lock held
   535 @pre Called with page cleaning lock held
   460 */
   536 */
   461 TInt DSwapManager::WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TBool aBackground)
   537 TInt DSwapManager::WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs, TBool aBackground)
   462 	{
   538 	{
       
   539 	TRACE(("DSwapManager::WriteSwapPages %d pages", aCount));
       
   540 	
   463 	__ASSERT_CRITICAL;  // so we can pass the paging device a stack-allocated TThreadMessage
   541 	__ASSERT_CRITICAL;  // so we can pass the paging device a stack-allocated TThreadMessage
   464 	__NK_ASSERT_DEBUG(PageCleaningLock::IsHeld());
   542 	__NK_ASSERT_DEBUG(PageCleaningLock::IsHeld());
   465 
   543 
   466 	START_PAGING_BENCHMARK;
   544 	START_PAGING_BENCHMARK;
   467 	
   545 	
   501 		else
   579 		else
   502 			{
   580 			{
   503 			if (startIndex != -1)
   581 			if (startIndex != -1)
   504 				{
   582 				{
   505 				// write pages from startIndex to i exclusive
   583 				// write pages from startIndex to i exclusive
   506 				TInt count = i - startIndex;
   584 				TUint count = i - startIndex;
   507 				__NK_ASSERT_DEBUG(count > 0 && count <= KMaxPagesToClean);
   585 				__NK_ASSERT_DEBUG(count > 0 && count <= KMaxPagesToClean);
   508 
   586 
   509 				// Get a new swap location for these pages, writing them all together if possible
   587 				// Get a new swap location for these pages, writing them all together if possible
   510 				TInt swapIndex = AllocSwapIndex(count);
   588 				TInt swapIndex = AllocSwapIndex(count);
   511 				if (swapIndex >= 0)
   589 				if (swapIndex >= 0)
   512 					r = DoWriteSwapPages(&aMemory[startIndex], &aIndex[startIndex], count, aLinAddr + (startIndex << KPageShift), swapIndex, aBackground);
   590 					r = DoWriteSwapPages(&aMemory[startIndex], &aIndex[startIndex], count, aLinAddr, startIndex, aPhysAddrs, swapIndex, aBackground);
   513 				else
   591 				else
   514 					{
   592 					{
   515 					// Otherwise, write them individually
   593 					// Otherwise, write them individually
   516 					for (TUint j = startIndex ; j < i ; ++j)
   594 					for (TUint j = startIndex ; j < i ; ++j)
   517 						{
   595 						{
   518 						swapIndex = AllocSwapIndex(1);
   596 						swapIndex = AllocSwapIndex(1);
   519 						__NK_ASSERT_DEBUG(swapIndex >= 0);
   597 						__NK_ASSERT_DEBUG(swapIndex >= 0);
   520 						r = DoWriteSwapPages(&aMemory[j], &aIndex[j], 1, aLinAddr + (j << KPageShift), swapIndex, aBackground);
   598 						r = DoWriteSwapPages(&aMemory[j], &aIndex[j], 1, aLinAddr, j, &aPhysAddrs[j], swapIndex, aBackground);
   521 						if (r != KErrNone)
   599 						if (r != KErrNone)
   522 							break;
   600 							break;
   523 						}
   601 						}
   524 					}
   602 					}
   525 
   603 
   531 	END_PAGING_BENCHMARK_N(EPagingBmWriteDataPage, aCount);
   609 	END_PAGING_BENCHMARK_N(EPagingBmWriteDataPage, aCount);
   532 	
   610 	
   533 	return r;
   611 	return r;
   534 	}
   612 	}
   535 
   613 
   536 TInt DSwapManager::DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aSwapIndex, TBool aBackground)
   614 TInt DSwapManager::DoWriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TInt aPageIndex, TPhysAddr* aPhysAddrs, TInt aSwapIndex, TBool aBackground)
   537 	{	
   615 	{	
       
   616 	TRACE2(("DSwapManager::DoWriteSwapPages %d pages to %d", aCount, aSwapIndex));
   538 		
   617 		
   539 	const TUint readUnitShift = iDevice->iReadUnitShift;
   618 	const TUint readUnitShift = iDevice->iReadUnitShift;
   540 	const TUint writeSize = aCount << (KPageShift - readUnitShift);
   619 	const TUint writeSize = aCount << (KPageShift - readUnitShift);
   541 	const TUint writeOffset = aSwapIndex << (KPageShift - readUnitShift);
   620 	const TUint writeOffset = aSwapIndex << (KPageShift - readUnitShift);
   542 		
   621 
   543 	TThreadMessage msg;
   622 	TThreadMessage msg;
   544 	START_PAGING_BENCHMARK;
   623 	START_PAGING_BENCHMARK;
   545 	TInt r = iDevice->Write(&msg, aLinAddr, writeOffset, writeSize, aBackground);
   624 	TInt r;
       
   625 	if (aLinAddr == 0)
       
   626 		r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground);
       
   627 	else
       
   628 		r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground);
       
   629 		
   546 	if (r != KErrNone)
   630 	if (r != KErrNone)
   547 		{
   631 		{
   548 		__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r));
   632 		__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r));
   549 		}
   633 		}
   550 	__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
   634 	__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
   641 	NKern::FMSignal(&iSwapLock);
   725 	NKern::FMSignal(&iSwapLock);
   642 	return KErrNone;
   726 	return KErrNone;
   643 	}
   727 	}
   644 
   728 
   645 
   729 
       
   730 TBool DDataPagedMemoryManager::PhysicalAccessSupported()
       
   731 	{
       
   732 	return (iDevice->iFlags & DPagingDevice::ESupportsPhysicalAccess) != 0;
       
   733 	}
       
   734 
       
   735 
       
   736 TBool DDataPagedMemoryManager::UsePhysicalAccess()
       
   737 	{
       
   738 	return iUsePhysicalAccess;
       
   739 	}
       
   740 
       
   741 
       
   742 void DDataPagedMemoryManager::SetUsePhysicalAccess(TBool aUsePhysicalAccess)
       
   743 	{
       
   744 	TRACE(("WDP: Use physical access set to %d", aUsePhysicalAccess));
       
   745 	NKern::ThreadEnterCS();
       
   746 	PageCleaningLock::Lock();
       
   747 	iUsePhysicalAccess = aUsePhysicalAccess;
       
   748 	ThePager.SetCleanInSequence(!iUsePhysicalAccess && KPageColouringRestriction);
       
   749 	PageCleaningLock::Unlock();
       
   750 	NKern::ThreadLeaveCS();
       
   751 	}
       
   752 
       
   753 
       
   754 TUint DDataPagedMemoryManager::PreferredWriteSize()
       
   755 	{
       
   756 	return MaxU(iDevice->iPreferredWriteShift, KMinPreferredWriteShift + KPageShift) - KPageShift;
       
   757 	}
       
   758 
       
   759 
       
   760 TUint DDataPagedMemoryManager::PreferredSwapAlignment()
       
   761 	{
       
   762 	return MaxU(iDevice->iPreferredWriteShift, KPageShift) - KPageShift;
       
   763 	}
       
   764 
       
   765 
       
   766 TInt DDataPagedMemoryManager::SetWriteSize(TUint aWriteShift)
       
   767 	{
       
   768 	TRACE(("WDP: Set write size to %d (%d KB)", aWriteShift, 4 << aWriteShift));
       
   769 	// Check value is sensible
       
   770 	if (aWriteShift > 31)
       
   771 		return KErrArgument;
       
   772 	if (aWriteShift > KMaxPreferredWriteShift)
       
   773 		{
       
   774 		aWriteShift = KMaxPreferredWriteShift;
       
   775 		TRACE(("WDP: Reduced write size to %d (%d KB)",
       
   776 			   aWriteShift, 4 << aWriteShift));
       
   777 
       
   778 		}
       
   779 	NKern::ThreadEnterCS();
       
   780 	PageCleaningLock::Lock();
       
   781 	ThePager.SetPagesToClean(1 << aWriteShift);
       
   782 	PageCleaningLock::Unlock();
       
   783 	NKern::ThreadLeaveCS();
       
   784 	return KErrNone;
       
   785 	}
       
   786 
   646 
   787 
   647 TInt DDataPagedMemoryManager::InstallPagingDevice(DPagingDevice* aDevice)
   788 TInt DDataPagedMemoryManager::InstallPagingDevice(DPagingDevice* aDevice)
   648 	{
   789 	{
   649 	TRACEB(("DDataPagedMemoryManager::InstallPagingDevice(0x%08x)",aDevice));
   790 	TRACEB(("DDataPagedMemoryManager::InstallPagingDevice(0x%08x)",aDevice));
   650 
   791 
   671 		return KErrAlreadyExists;
   812 		return KErrAlreadyExists;
   672 		}
   813 		}
   673 
   814 
   674 	// Now we can determine the size of the swap, create the swap manager.
   815 	// Now we can determine the size of the swap, create the swap manager.
   675 	iSwapManager = new DSwapManager;
   816 	iSwapManager = new DSwapManager;
   676 	__NK_ASSERT_ALWAYS(iSwapManager);
   817 	if (!iSwapManager)
   677 
   818 		return KErrNoMemory;
   678 	TInt r = iSwapManager->Create(iDevice);
   819 
       
   820 	// Create swap manager object
       
   821 	TInt r = iSwapManager->Create(aDevice);
   679 	if (r != KErrNone)
   822 	if (r != KErrNone)
   680 		{// Couldn't create the swap manager.
   823 		{// Couldn't create the swap manager.
   681 		delete iSwapManager;
   824 		delete iSwapManager;
   682 		iSwapManager = NULL;
   825 		iSwapManager = NULL;
   683 		NKern::SafeSwap(NULL, (TAny*&)iDevice);
   826 		NKern::SafeSwap(NULL, (TAny*&)iDevice);
   684 		return r;
   827 		return r;
   685 		}
   828 		}
       
   829 
       
   830 	// Enable physical access where supported
       
   831 	SetUsePhysicalAccess(PhysicalAccessSupported());
       
   832 	
       
   833 	// Determine swap alignment and number of pages to clean at once from device's preferred write
       
   834 	// size, if set
       
   835 	TRACE(("WDP: Preferred write shift is %d", iDevice->iPreferredWriteShift));
       
   836 	r = SetWriteSize(PreferredWriteSize());
       
   837 	if (r != KErrNone)
       
   838 		{
       
   839 		delete iSwapManager;
       
   840 		iSwapManager = NULL;
       
   841 		NKern::SafeSwap(NULL, (TAny*&)iDevice);
       
   842 		return r;
       
   843 		}
       
   844 
       
   845 	// Set swap alignment
       
   846 	iSwapManager->SetSwapAlign(PreferredSwapAlignment());
       
   847 	
   686  	NKern::LockedSetClear(K::MemModelAttributes, 0, EMemModelAttrDataPaging);
   848  	NKern::LockedSetClear(K::MemModelAttributes, 0, EMemModelAttrDataPaging);
   687 
   849 
   688 	return r;
   850 	return r;
   689 	}
   851 	}
   690 
   852 
   753 
   915 
   754 TInt DDataPagedMemoryManager::ReadPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages, DPageReadRequest* aRequest)
   916 TInt DDataPagedMemoryManager::ReadPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages, DPageReadRequest* aRequest)
   755 	{
   917 	{
   756 	__NK_ASSERT_DEBUG(aRequest->CheckUseContiguous(aMemory,aIndex,aCount));
   918 	__NK_ASSERT_DEBUG(aRequest->CheckUseContiguous(aMemory,aIndex,aCount));
   757 
   919 
       
   920 	// todo: Possible to read using physical addresses here, but not sure it's worth it because it's
       
   921 	// not much saving and we may need to map the page anyway if it's blank to clear it
       
   922 	// 
       
   923 	// todo: Could move clearing pages up to here maybe?
       
   924 
   758 	// Map pages temporarily so that we can copy into them.
   925 	// Map pages temporarily so that we can copy into them.
   759 	const TLinAddr linAddr = aRequest->MapPages(aIndex, aCount, aPages);
   926 	const TLinAddr linAddr = aRequest->MapPages(aIndex, aCount, aPages);
   760 
   927 
   761 	TInt r = iSwapManager->ReadSwapPages(aMemory, aIndex, aCount, linAddr, aRequest, aPages);
   928 	TInt r = iSwapManager->ReadSwapPages(aMemory, aIndex, aCount, linAddr, aPages);
   762 
   929 
   763 	// The memory object allows executable mappings then need IMB.
   930 	// The memory object allows executable mappings then need IMB.
   764 	aRequest->UnmapPages(aMemory->IsExecutable());
   931 	aRequest->UnmapPages(aMemory->IsExecutable());
   765 
   932 
   766 	return r;
   933 	return r;
   767 	}
   934 	}
   768 
   935 
   769 
   936 
   770 TInt DDataPagedMemoryManager::WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest* aRequest, TBool aAnyExecutable, TBool aBackground)
   937 TInt DDataPagedMemoryManager::WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest* aRequest, TBool aAnyExecutable, TBool aBackground)
   771 	{
   938 	{
   772 	// Map pages temporarily so that we can copy into them.
   939 	// Note: this method used to do an IMB for executable pages (like ReadPages) but it was thought
   773 	const TLinAddr linAddr = aRequest->MapPages(aIndex[0], aCount, aPages);
   940 	// that this was uncessessary and so was removed
   774 
   941 
   775 	TInt r = iSwapManager->WriteSwapPages(aMemory, aIndex, aCount, linAddr, aBackground);
   942 	TLinAddr linAddr = 0;
   776 
   943 
   777 	// The memory object allows executable mappings then need IMB.
   944 	if (iUsePhysicalAccess)
   778 	aRequest->UnmapPages(aAnyExecutable);
   945 		{
       
   946 		// must maps pages to perform cache maintenance but can map each page individually
       
   947 		for (TUint i = 0 ; i < aCount ; ++i)
       
   948 			{
       
   949 			TLinAddr addr = aRequest->MapPages(aIndex[i], 1, &aPages[i]);
       
   950 			Cache::SyncMemoryBeforeDmaWrite(addr, KPageSize);
       
   951 			aRequest->UnmapPages(EFalse);
       
   952 			}
       
   953 		}
       
   954 	else
       
   955 		linAddr = aRequest->MapPages(aIndex[0], aCount, aPages);
       
   956 	
       
   957 	TInt r = iSwapManager->WriteSwapPages(aMemory, aIndex, aCount, linAddr, aPages, aBackground);
       
   958 
       
   959 	if (linAddr != 0)
       
   960 		aRequest->UnmapPages(EFalse);
   779 
   961 
   780 	return r;
   962 	return r;
   781 	}
   963 	}
   782 
   964 
   783 
   965 
   784 void DDataPagedMemoryManager::CleanPages(TUint aPageCount, SPageInfo** aPageInfos, TBool aBackground)
   966 void DDataPagedMemoryManager::CleanPages(TUint aPageCount, SPageInfo** aPageInfos, TBool aBackground)
   785 	{
   967 	{
       
   968 	TRACE(("DDataPagedMemoryManager::CleanPages %d", aPageCount));
       
   969 	
   786 	__NK_ASSERT_DEBUG(PageCleaningLock::IsHeld());
   970 	__NK_ASSERT_DEBUG(PageCleaningLock::IsHeld());
   787 	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
   971 	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
   788 	__NK_ASSERT_DEBUG(aPageCount <= (TUint)KMaxPagesToClean);
   972 	__NK_ASSERT_DEBUG(aPageCount <= (TUint)KMaxPagesToClean);
   789 	
   973 	
   790 	TUint i;
   974 	TUint i;
   791 	DMemoryObject* memory[KMaxPagesToClean];
   975 	DMemoryObject* memory[KMaxPagesToClean];
   792 	TUint index[KMaxPagesToClean];
   976 	TUint index[KMaxPagesToClean];
   793 	TPhysAddr physAddr[KMaxPagesToClean];
   977 	TPhysAddr physAddr[KMaxPagesToClean];
   794 	TBool anyExecutable = EFalse;
   978 	TBool anyExecutable = EFalse;
   795 	
   979 
   796 	for (i = 0 ; i < aPageCount ; ++i)
   980 	for (i = 0 ; i < aPageCount ; ++i)
   797 		{
   981 		{
   798 		SPageInfo* pi = aPageInfos[i];
   982 		SPageInfo* pi = aPageInfos[i];
   799 
   983 
   800 		__NK_ASSERT_DEBUG(!pi->IsWritable());
   984 		__NK_ASSERT_DEBUG(!pi->IsWritable());
   826 
  1010 
   827 	for (i = 0 ; i < aPageCount ; ++i)
  1011 	for (i = 0 ; i < aPageCount ; ++i)
   828 		{
  1012 		{
   829 		SPageInfo* pi = aPageInfos[i];
  1013 		SPageInfo* pi = aPageInfos[i];
   830 		// check if page is clean...
  1014 		// check if page is clean...
   831 		if(pi->CheckModified(&memory[0]) || pi->IsWritable())
  1015 		if(pi->CheckModified(&memory[0]) ||
       
  1016 		   pi->IsWritable())
   832 			{
  1017 			{
   833 			// someone else modified the page, or it became writable, so mark as not cleaned
  1018 			// someone else modified the page, or it became writable, so mark as not cleaned
   834 			aPageInfos[i] = NULL;
  1019 			aPageInfos[i] = NULL;
   835 			}
  1020 			}
   836 		else
  1021 		else
   873 
  1058 
   874 TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds)
  1059 TInt SetSwapThresholds(const SVMSwapThresholds& aThresholds)
   875 	{
  1060 	{
   876 	return ((DDataPagedMemoryManager*)TheDataPagedMemoryManager)->SetSwapThresholds(aThresholds);
  1061 	return ((DDataPagedMemoryManager*)TheDataPagedMemoryManager)->SetSwapThresholds(aThresholds);
   877 	}
  1062 	}
   878   
  1063 
       
  1064 
       
  1065 TBool GetPhysicalAccessSupported()
       
  1066 	{
       
  1067 	return ((DDataPagedMemoryManager*)TheDataPagedMemoryManager)->PhysicalAccessSupported();
       
  1068 	}
       
  1069 
       
  1070 
       
  1071 TBool GetUsePhysicalAccess()
       
  1072 	{
       
  1073 	return ((DDataPagedMemoryManager*)TheDataPagedMemoryManager)->UsePhysicalAccess();
       
  1074 	}
       
  1075 
       
  1076 
       
  1077 void SetUsePhysicalAccess(TBool aUsePhysicalAccess)
       
  1078 	{
       
  1079 	((DDataPagedMemoryManager*)TheDataPagedMemoryManager)->SetUsePhysicalAccess(aUsePhysicalAccess);
       
  1080 	}
       
  1081 
       
  1082 
       
  1083 TUint GetPreferredDataWriteSize()
       
  1084 	{
       
  1085 	return ((DDataPagedMemoryManager*)TheDataPagedMemoryManager)->PreferredWriteSize();
       
  1086 	}
       
  1087 
       
  1088 
       
  1089 TInt SetDataWriteSize(TUint aWriteShift)
       
  1090 	{
       
  1091 	return	((DDataPagedMemoryManager*)TheDataPagedMemoryManager)->SetWriteSize(aWriteShift);
       
  1092 	}
       
  1093