kernel/eka/memmodel/epoc/flexible/mmu/mrom.cpp
changeset 0 a41df078684a
child 87 2f92ad2dc5db
child 90 947f0dc9f7a8
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <plat_priv.h>
       
    17 #include <kernel/cache.h>
       
    18 #include "mm.h"
       
    19 #include "mmu.h"
       
    20 #include "mrom.h"
       
    21 #include "mpager.h"
       
    22 #include "mmanager.h"
       
    23 #include "mobject.h"
       
    24 #include "mmapping.h"
       
    25 #include "maddrcont.h"
       
    26 #include "mptalloc.h"
       
    27 #include "mlargemappings.h"
       
    28 
       
    29 #include "cache_maintenance.inl"
       
    30 
       
    31 
       
    32 /**
       
    33 Class representing the resources allocated for a ROM shadow page.
       
    34 
       
    35 A shadow page is a page of RAM which is mapped by the MMU to replace
       
    36 a prior existing page at a particular virtual address.
       
    37 */
       
    38 class DShadowPage : public DVirtualPinMapping
       
    39 	{
       
    40 public:
       
    41 	/**
       
    42 	Create a new #DShadowPage to shadow a specified memory page.
       
    43 
       
    44 	On success, #iOriginalPage holds the physical address of the original page
       
    45 	and #iNewPage the physical address of the newly allocated RAM page; the
       
    46 	contents of this are a copy of the original.
       
    47 
       
    48 	No MMU entries for the shadow page are changed - it is the responsibility
       
    49 	of the caller to handle this. However, the new #DShadowPage object will
       
    50 	have pinned the page table used by \a aMapping which maps the page being
       
    51 	shadowed, prevent demand paging from discarding any modifications made to
       
    52 	this.
       
    53 
       
    54 	@param aMemory		The memory object whose memory is to be shadowed.
       
    55 	@param aIndex		Page index, within the memory, of the page to shadow.
       
    56 	@param aMapping		A memory mapping which currently maps the page to be
       
    57 						shadowed.
       
    58 
       
    59 	@return The newly created DShadowPage or the null pointer if there was
       
    60 			insufficient memory.
       
    61 	*/
       
    62 	static DShadowPage* New(DMemoryObject* aMemory, TUint aIndex, DMemoryMappingBase* aMapping);
       
    63 
       
    64 	/**
       
    65 	Free the allocated shadow page (#iNewPage) and unpin any pages table which
       
    66 	was pinned, then free this shadow page object.
       
    67 
       
    68 	The called of this function must ensure that all references to the shadow
       
    69 	RAM page have been removed from any MMU mappings.
       
    70 	*/
       
    71 	void Destroy();
       
    72 
       
    73 private:
       
    74 	DShadowPage();
       
    75 	~DShadowPage();
       
    76 
       
    77 	/**
       
    78 	Second phase constructor. For arguments, see #New.
       
    79 	*/
       
    80 	TInt Construct(DMemoryObject* aMemory, TUint aIndex, DMemoryMappingBase* aMapping);
       
    81 
       
    82 public:
       
    83 	/**
       
    84 	The physical address of the original page being shadowed.
       
    85 	*/
       
    86 	TPhysAddr iOriginalPage;
       
    87 
       
    88 	/**
       
    89 	The physical address of the allocated shadow page.
       
    90 	*/
       
    91 	TPhysAddr iNewPage;
       
    92 	};
       
    93 
       
    94 
       
    95 /**
       
    96 Specialised manager for the memory object representing the system ROM.
       
    97 This handles demand paging of the ROM contents if it is not stored in a memory
       
    98 device capable of execute-in-place random access. E.g. when stored in NAND
       
    99 flash.
       
   100 */
       
   101 class DRomMemoryManager : public DPagedMemoryManager
       
   102 	{
       
   103 public:
       
   104 	DRomMemoryManager();
       
   105 
       
   106 	/**
       
   107 	Allocate a shadow page for the specified ROM address.
       
   108 
       
   109 	Shadow pages are pages of RAM which are mapped by the MMU so that 
       
   110 	they replace the original ROM memory. The contents of a shadow page
       
   111 	are initially the same as the ROM they replace, but may be modified with
       
   112 	#CopyToShadowMemory.
       
   113 
       
   114 	@param aRomAddr	An virtual address which lies within the ROM.
       
   115 
       
   116 	@return KErrNone if successful,
       
   117 			KErrAlreadyExists if the specified address already has a show page,
       
   118 			otherwise one of the system wide error codes.
       
   119 	*/
       
   120 	TInt AllocShadowPage(TLinAddr aRomAddr);
       
   121 
       
   122 	/**
       
   123 	Free a shadow page previously allocated with #AllocShadowPage.
       
   124 
       
   125 	The original ROM memory page is again mapped at the specified address.
       
   126 
       
   127 	@param aRomAddr	An virtual address which lies within the ROM.
       
   128 
       
   129 	@return KErrNone if successful,
       
   130 			otherwise one of the system wide error codes.
       
   131 	*/
       
   132 	TInt FreeShadowPage(TLinAddr aRomAddr);
       
   133 
       
   134 	/**
       
   135 	Copy data into a shadow page, modifying its contents.
       
   136 
       
   137 	@param aDst		An virtual address which lies within the ROM for which a shadow
       
   138 					page has previously been allocated with #AllocShadowPage.
       
   139 	@param aSrc		The start address of the data to copy to \a aDst.
       
   140 	@param aSize	The size, in bytes, of the data to copy.
       
   141 
       
   142 	@return KErrNone if successful,
       
   143 			KErrNotFound if the specified address didn't have a shadow page,
       
   144 			otherwise one of the system wide error codes.
       
   145 	*/
       
   146 	TInt CopyToShadowMemory(TLinAddr aDst, TLinAddr aSrc, TUint32 aSize);
       
   147 
       
   148 protected:
       
   149 
       
   150 	// from DPagedMemoryManager...
       
   151 	virtual TInt PageInPinnedDone(DMemoryObject* aMemory, TUint aIndex, SPageInfo* aPageInfo, TPhysAddr* aPageArrayEntry, TPinArgs& aPinArgs);
       
   152 
       
   153 private:
       
   154 	// from DMemoryManager...
       
   155 	virtual void Destruct(DMemoryObject* aMemory);
       
   156 	virtual TInt HandleFault(	DMemoryObject* aMemory, TUint aIndex, DMemoryMapping* aMapping, 
       
   157 								TUint aMapInstanceCount, TUint aAccessPermissions);
       
   158 	virtual TInt Pin(DMemoryObject* aMemory, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs);
       
   159 	virtual void Unpin(DMemoryObject* aMemory, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs);
       
   160 
       
   161 	// methods inherited from DPagedMemoryManager
       
   162 
       
   163 	/**
       
   164 	@copydoc DPagedMemoryManager::Init3
       
   165 	This acts as a second phase constructor for the manager which
       
   166 	creates the memory objects and mappings to represent the ROM.
       
   167 	*/
       
   168 	virtual void Init3();
       
   169 
       
   170 	virtual TInt InstallPagingDevice(DPagingDevice* aDevice);
       
   171 	virtual TInt AcquirePageReadRequest(DPageReadRequest*& aRequest, DMemoryObject* aMemory, TUint aIndex, TUint aCount);
       
   172 	virtual TInt ReadPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages, DPageReadRequest* aRequest);
       
   173 	virtual TBool IsAllocated(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
       
   174 	virtual void DoUnpin(DMemoryObject* aMemory, TUint aIndex, TUint aCount, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs);
       
   175 
       
   176 	/**
       
   177 	Acquire the mutex used to protect shadow page allocation.
       
   178 	*/
       
   179 	void ShadowLock();
       
   180 
       
   181 	/**
       
   182 	Release the mutex used to protect shadow page allocation.
       
   183 	*/
       
   184 	void ShadowUnlock();
       
   185 
       
   186 private:
       
   187 	/**
       
   188 	The ROM paging device which was passed to #InstallPagingDevice.
       
   189 	*/
       
   190 	DPagingDevice* iDevice;
       
   191 
       
   192 	/**
       
   193 	The memory object containing the ROM.
       
   194 	*/
       
   195 	DMemoryObject* iRomMemory;
       
   196 
       
   197 	/**
       
   198 	The memory mapping which maps the ROM into a global visible virtual address.
       
   199 	*/
       
   200 	DMemoryMapping* iRomMapping;
       
   201 
       
   202 	/**
       
   203 	The virtual address for the start of the ROM in the global memory region.
       
   204 	*/
       
   205 	TLinAddr iBase;
       
   206 
       
   207 	/**
       
   208 	The size, in bytes, of the ROM image.
       
   209 	This may not be an exact multiple of a page size.
       
   210 	*/
       
   211 	TUint iSize;
       
   212 
       
   213 	/**
       
   214 	The size, in pages, of the ROM image.
       
   215 	*/
       
   216 	TUint iSizeInPages;
       
   217 
       
   218 	/**
       
   219 	The offset from the ROM start, in bytes, for the region of the
       
   220 	ROM which is demand paged.
       
   221 	*/
       
   222 	TUint iPagedStart;
       
   223 
       
   224 	/**
       
   225 	The size, in bytes, for the region of the ROM which is demand paged.
       
   226 	*/
       
   227 	TUint iPagedSize;
       
   228 
       
   229 	/**
       
   230 	The address within the ROM for the ROM page index.
       
   231 	@see TRomHeader::iRomPageIndex.
       
   232 	*/
       
   233 	SRomPageInfo* iRomPageIndex;
       
   234 
       
   235 	/**
       
   236 	The mutex used to protect shadow page allocation.
       
   237 	*/
       
   238 	DMutex* iShadowLock;
       
   239 
       
   240 	/**
       
   241 	Container for all allocated DShadowPage objects.
       
   242 	*/
       
   243 	RAddressedContainer iShadowPages;
       
   244 
       
   245 #ifdef __SUPPORT_DEMAND_PAGING_EMULATION__
       
   246 	TInt iOriginalRomPageCount;
       
   247 	TPhysAddr* iOriginalRomPages;
       
   248 	friend void RomOriginalPages(TPhysAddr*& aPages, TUint& aPageCount);
       
   249 #endif
       
   250 
       
   251 	friend TBool IsUnpagedRom(TLinAddr aBase, TUint aSize);
       
   252 
       
   253 public:
       
   254 	/**
       
   255 	The single instance of this manager class.
       
   256 	*/
       
   257 	static DRomMemoryManager TheManager;
       
   258 	};
       
   259 
       
   260 
       
   261 DRomMemoryManager DRomMemoryManager::TheManager;
       
   262 DPagedMemoryManager* TheRomMemoryManager = &DRomMemoryManager::TheManager;
       
   263 
       
   264 
       
   265 const TInt KMutexOrdRomMemory = KMutexOrdPageIn+1;
       
   266 
       
   267 
       
   268 #ifdef __SUPPORT_DEMAND_PAGING_EMULATION__
       
   269 /**
       
   270 For use by the emulated paging device to get the location and size of the ROM.
       
   271 
       
   272 @param aPages		A reference to store a pointer to an array of the physical addresses of each ROM page.
       
   273 @param aPageCount	A reference to store the number of rom pages.
       
   274 */
       
   275 void RomOriginalPages(TPhysAddr*& aPages, TUint& aPageCount)
       
   276 	{
       
   277 	aPages = DRomMemoryManager::TheManager.iOriginalRomPages;
       
   278 	aPageCount = DRomMemoryManager::TheManager.iOriginalRomPageCount;
       
   279 	}
       
   280 
       
   281 #endif
       
   282 
       
   283 
       
   284 TBool IsUnpagedRom(TLinAddr aBase, TUint aSize)
       
   285 	{
       
   286 	TUint offset = aBase-DRomMemoryManager::TheManager.iBase;
       
   287 	TUint limit = DRomMemoryManager::TheManager.iPagedStart;
       
   288 	if(offset>=limit)
       
   289 		return false;
       
   290 	offset += aSize;
       
   291 	if(offset>limit || offset<aSize)
       
   292 		return false;
       
   293 	return true;
       
   294 	}
       
   295 
       
   296 
       
   297 TInt PagifyChunk(TLinAddr aAddress)
       
   298 	{
       
   299 	TRACE(("PagifyChunk(0x%08x)",aAddress));
       
   300 
       
   301 	aAddress &= ~KChunkMask;
       
   302 	TPde* pPde = Mmu::PageDirectoryEntry(KKernelOsAsid,aAddress);
       
   303 
       
   304 retry:
       
   305 	// check there is actually some memory mapped...
       
   306 	TPde pde = *pPde;
       
   307 	if(pde==KPdeUnallocatedEntry)
       
   308 		{
       
   309 		TRACE(("PagifyChunk returns %d",KErrNotFound));
       
   310 		return KErrNotFound;
       
   311 		}
       
   312 
       
   313 	// end if memory is not a section mapping...
       
   314 	TPhysAddr pdePhys = Mmu::PdePhysAddr(pde);
       
   315 	if(pdePhys==KPhysAddrInvalid)
       
   316 		{
       
   317 		TRACE(("PagifyChunk returns %d",KErrAlreadyExists));
       
   318 		return KErrAlreadyExists;
       
   319 		}
       
   320 
       
   321 	// get a new page table...
       
   322 	::PageTables.Lock();
       
   323 	TPte* pt = ::PageTables.Alloc(false);
       
   324 	if(!pt)
       
   325 		{
       
   326 		TRACE(("PagifyChunk returns %d",KErrNoMemory));
       
   327 		::PageTables.Unlock();
       
   328 		return KErrNoMemory;
       
   329 		}
       
   330 
       
   331 	// fill page table so it maps the same physical addresses as the section mapping...
       
   332 	TPte pte = Mmu::SectionToPageEntry(pde);
       
   333 	pte |= pdePhys;
       
   334 	TPte* pPte = pt;
       
   335 	do
       
   336 		{
       
   337 		TRACE2(("!PTE %x=%x",pPte,pte));
       
   338 		*pPte++ = pte;
       
   339 		pte += KPageSize;
       
   340 		}
       
   341 	while(TLinAddr(pPte)&(KPageTableMask/sizeof(TPte)*sizeof(TPte)));
       
   342 	CacheMaintenance::MultiplePtesUpdated((TLinAddr)pt,KPageTableSize);
       
   343 
       
   344 	// check memory not changed...
       
   345 	MmuLock::Lock();
       
   346 	if(Mmu::PdePhysAddr(*pPde)!=pdePhys)
       
   347 		{
       
   348 		// pde was changed whilst we were creating a new page table, need to retry...
       
   349 		MmuLock::Unlock();
       
   350 		::PageTables.Free(pt);
       
   351 		::PageTables.Unlock();
       
   352 		goto retry;
       
   353 		}
       
   354 
       
   355 	// update page counts...
       
   356 	SPageTableInfo* pti = SPageTableInfo::FromPtPtr(pt);
       
   357 	TUint count = pti->IncPageCount(KPageTableSize/sizeof(TPte));
       
   358 	(void)count;
       
   359 	TRACE2(("pt %x page count=%d",pt,pti->PageCount()));
       
   360 	__NK_ASSERT_DEBUG(pti->CheckPageCount());
       
   361 
       
   362 	// swap pde entry to point to new page table...
       
   363 	pde |= Mmu::PageTablePhysAddr(pt);
       
   364 	TRACE2(("!PDE %x=%x",pPde,pde));
       
   365 	*pPde = pde;
       
   366 	SinglePdeUpdated(pPde);
       
   367 	InvalidateTLB();
       
   368 
       
   369 	// done...
       
   370 	MmuLock::Unlock();
       
   371 	::PageTables.Unlock();
       
   372 	TRACE(("PagifyChunk returns %d",KErrNone));
       
   373 	return KErrNone;
       
   374 	}
       
   375 
       
   376 
       
   377 void UnmapROM(TLinAddr aStart, TLinAddr aEnd)
       
   378 	{
       
   379 	TRACEB(("UnmapROM 0x%08x..0x%08x",aStart,aEnd));
       
   380 
       
   381 	TLinAddr p = aStart;
       
   382 	if(p>=aEnd)
       
   383 		return;
       
   384 
       
   385 	PagifyChunk(p);
       
   386 
       
   387 	MmuLock::Lock(); // hold MmuLock for long time, shouldn't matter as this is only done during boot
       
   388 
       
   389 	TPte* pPte = Mmu::PtePtrFromLinAddr(p,KKernelOsAsid);
       
   390 	__NK_ASSERT_ALWAYS(pPte);
       
   391 	while(p<aEnd && p&KChunkMask)
       
   392 		{
       
   393 		*pPte++ = KPteUnallocatedEntry;
       
   394 		p += KPageSize;
       
   395 		}
       
   396 
       
   397 	if(p<aEnd)
       
   398 		{
       
   399 		TPde* pPde = Mmu::PageDirectoryEntry(KKernelOsAsid,p);
       
   400 		while(p<aEnd)
       
   401 			{
       
   402 			*pPde++ = KPdeUnallocatedEntry;
       
   403 			p += KChunkSize;
       
   404 			}
       
   405 		}
       
   406 
       
   407 	MmuLock::Unlock();
       
   408 
       
   409 	__NK_ASSERT_DEBUG(p==aEnd);
       
   410 	}
       
   411 
       
   412 
       
   413 DRomMemoryManager::DRomMemoryManager()
       
   414 	: iShadowPages(0,iShadowLock)
       
   415 	{
       
   416 	}
       
   417 
       
   418 
       
   419 void DRomMemoryManager::Init3()
       
   420 	{
       
   421 	// get ROM info...
       
   422 	const TRomHeader& romHeader = TheRomHeader();
       
   423 	iBase = (TLinAddr)&romHeader;
       
   424 	iSize = romHeader.iUncompressedSize;
       
   425 	iSizeInPages = MM::RoundToPageCount(iSize);
       
   426 	TUint chunkSize = ((iSize+KChunkMask)&~KChunkMask);
       
   427 	TUint committedSize = TheSuperPage().iTotalRomSize; // size of memory loaded by bootstrap
       
   428 	TRACEB(("DRomMemoryManager::Init3 rom=0x%08x+0x%x",iBase,iSize));
       
   429 
       
   430 	// get paged rom info...
       
   431 	if(romHeader.iRomPageIndex)
       
   432 		iRomPageIndex = (SRomPageInfo*)((TInt)&romHeader+romHeader.iRomPageIndex);
       
   433 	iPagedSize = romHeader.iPageableRomSize;
       
   434 	iPagedStart = iPagedSize ? romHeader.iPageableRomStart : 0;
       
   435 	if(iPagedStart)
       
   436 		{
       
   437 		TRACEB(("DRomMemoryManager::Init3() paged=0x%08x+0x%x",(TLinAddr)&romHeader+iPagedStart,iPagedSize));
       
   438 		__NK_ASSERT_ALWAYS(iPagedStart<iSize && iPagedStart+iPagedSize>iPagedStart && iPagedStart+iPagedSize<=iSize);
       
   439 
       
   440 #ifdef __SUPPORT_DEMAND_PAGING_EMULATION__
       
   441 		// get physical addresses of ROM pages...
       
   442 		iOriginalRomPageCount = iSizeInPages;
       
   443 		iOriginalRomPages = new TPhysAddr[iOriginalRomPageCount];
       
   444 		__NK_ASSERT_ALWAYS(iOriginalRomPages);
       
   445 		MmuLock::Lock(); // hold MmuLock for long time, shouldn't matter as this is only done during boot
       
   446 		TInt i;
       
   447 		for(i=0; i<iOriginalRomPageCount; i++)
       
   448 			iOriginalRomPages[i] = Mmu::LinearToPhysical(iBase+i*KPageSize);
       
   449 		MmuLock::Unlock();
       
   450 
       
   451 		// unmap paged part of ROM as the bootstrap will have left it mapped.
       
   452 		// See CFG_SupportEmulatedRomPaging in the bootstrap code.
       
   453 		// todo: use FMM for this after memory object created
       
   454 		UnmapROM(iBase+iPagedStart,iBase+chunkSize);
       
   455 		committedSize = iPagedStart;
       
   456 #endif
       
   457 		}
       
   458 
       
   459 	if(iPagedStart && committedSize!=iPagedStart)
       
   460 		{
       
   461 		// unmap any paged ROM which the bootstrap mapped...
       
   462 		TRACEB(("DRomMemoryManager::Init3() unmapping unpaged ROM offsets 0x%x thru 0x%x",iPagedStart,committedSize));
       
   463 		// todo: use FMM for this after memory object created
       
   464 		UnmapROM(iBase+iPagedStart,iBase+committedSize);
       
   465 		committedSize = iPagedStart;
       
   466 		}
       
   467 
       
   468 	// create memory object for ROM...
       
   469 	TRACEB(("DRomMemoryManager::Init3() committed ROM memory 0x%x of 0x%x",committedSize,chunkSize));
       
   470 	TMemoryCreateFlags flags = (TMemoryCreateFlags)(EMemoryCreateNoWipe | EMemoryCreateReadOnly | 
       
   471 													EMemoryCreateDemandPaged | EMemoryCreateAllowExecution);
       
   472 	iRomMemory = DLargeMappedMemory::New(&DRomMemoryManager::TheManager,chunkSize>>KPageShift,EMemoryAttributeStandard,flags);
       
   473 	__NK_ASSERT_ALWAYS(iRomMemory);
       
   474 	TInt r = MM::MemoryClaimInitialPages(iRomMemory,iBase,committedSize,EUserExecute,false,true);
       
   475 	__NK_ASSERT_ALWAYS(r==KErrNone);
       
   476 	r = iRomMemory->iPages.Alloc(committedSize>>KPageShift,(chunkSize-committedSize)>>KPageShift);
       
   477 	__NK_ASSERT_ALWAYS(r==KErrNone);
       
   478 
       
   479 	// create mapping for ROM...
       
   480 	r = MM::MappingNew(iRomMapping, iRomMemory, EUserExecute, KKernelOsAsid, EMappingCreateExactVirtual, iBase);
       
   481 	__NK_ASSERT_ALWAYS(r==KErrNone);
       
   482 	__NK_ASSERT_ALWAYS(iRomMapping->IsLarge());
       
   483 
       
   484 	// Set the paging device to be uninstalled, i.e. NULL.
       
   485 	iDevice = NULL;
       
   486 
       
   487 	_LIT(KRomMemoryLockName,"RomMemory");
       
   488 	r = K::MutexCreate(iShadowLock, KRomMemoryLockName, NULL, EFalse, KMutexOrdRomMemory);
       
   489 	__NK_ASSERT_ALWAYS(r==KErrNone);
       
   490 	MM::MemorySetLock(iRomMemory,iShadowLock);
       
   491 	}
       
   492 
       
   493 
       
   494 TInt DRomMemoryManager::InstallPagingDevice(DPagingDevice* aDevice)
       
   495 	{
       
   496 	TRACEB(("DRomMemoryManager::InstallPagingDevice(0x%08x)",aDevice));
       
   497 
       
   498 	if(!iPagedStart)
       
   499 		{
       
   500 		TRACEB(("ROM is not paged"));
       
   501 		return KErrNone;
       
   502 		}
       
   503 
       
   504 	TAny* null = 0;
       
   505 	if(!__e32_atomic_cas_ord_ptr(&iDevice, &null, aDevice)) // set iDevice=aDevice if it was originally 0
       
   506 		{
       
   507 		// ROM paging device already registered...
       
   508 		TRACEB(("DRomMemoryManager::InstallPagingDevice returns ALREADY EXISTS!"));
       
   509 		return KErrAlreadyExists;
       
   510 		}
       
   511 
       
   512 	__e32_atomic_ior_ord32(&K::MemModelAttributes, (TUint32)EMemModelAttrRomPaging);
       
   513 
       
   514 	return KErrNone;
       
   515 	}
       
   516 
       
   517 
       
   518 TInt DRomMemoryManager::AcquirePageReadRequest(DPageReadRequest*& aRequest, DMemoryObject* aMemory, TUint aIndex, TUint aCount)
       
   519 	{
       
   520 	aRequest = iDevice->iRequestPool->AcquirePageReadRequest(aMemory,aIndex,aCount);
       
   521 	return KErrNone;
       
   522 	}
       
   523 
       
   524 
       
   525 void DRomMemoryManager::Destruct(DMemoryObject* aMemory)
       
   526 	{
       
   527 	__NK_ASSERT_DEBUG(0);
       
   528 	}
       
   529 
       
   530 
       
   531 TInt DRomMemoryManager::ReadPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages, DPageReadRequest* aRequest)
       
   532 	{
       
   533 	__NK_ASSERT_DEBUG(aRequest->CheckUse(aMemory,aIndex,aCount));
       
   534 
       
   535 	TLinAddr linAddr = aRequest->MapPages(aIndex,aCount,aPages);
       
   536 	TInt r = KErrNone;
       
   537 
       
   538 	const TInt readUnitShift = iDevice->iReadUnitShift;
       
   539 
       
   540 	for(; aCount; ++aIndex, --aCount, linAddr+=KPageSize)
       
   541 		{
       
   542 		START_PAGING_BENCHMARK;
       
   543 		if(!iRomPageIndex)
       
   544 			{
       
   545 			// ROM not broken into pages, so just read it in directly.
       
   546 			// KPageShift > readUnitShift so page size is exact multiple of read 
       
   547 			// units.  Therefore it is ok to just shift offset and KPageSize 
       
   548 			// by readUnitShift.
       
   549 			const TInt dataOffset = aIndex << KPageShift;
       
   550 			START_PAGING_BENCHMARK;
       
   551 			r = iDevice->Read(	const_cast<TThreadMessage*>(&aRequest->iMessage), 
       
   552 								linAddr, dataOffset >> readUnitShift, 
       
   553 								KPageSize >> readUnitShift, DPagingDevice::EDriveRomPaging);
       
   554 			__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocated memory, therefore can't fail with KErrNoMemory
       
   555 			END_PAGING_BENCHMARK(EPagingBmReadMedia);
       
   556 			}
       
   557 		else
       
   558 			{
       
   559 			// Work out where data for page is located
       
   560 			SRomPageInfo* romPageInfo = iRomPageIndex + aIndex;
       
   561 			const TInt dataOffset = romPageInfo->iDataStart;
       
   562 			const TInt dataSize = romPageInfo->iDataSize;
       
   563 			if(!dataSize)
       
   564 				{
       
   565 				// empty page, fill it with 0xff...
       
   566 				memset((TAny*)linAddr, 0xff, KPageSize);
       
   567 				r = KErrNone;
       
   568 				}
       
   569 			else
       
   570 				{
       
   571 				__NK_ASSERT_ALWAYS(romPageInfo->iPagingAttributes & SRomPageInfo::EPageable);
       
   572 
       
   573 				// Read data for page...
       
   574 				TThreadMessage* msg = const_cast<TThreadMessage*>(&aRequest->iMessage);
       
   575 				const TLinAddr buffer = aRequest->iBuffer;
       
   576 				const TUint readStart = dataOffset >> readUnitShift;
       
   577 				const TUint readSize = ((dataOffset + dataSize - 1) >> readUnitShift) - readStart + 1;
       
   578 				__NK_ASSERT_DEBUG((readSize << readUnitShift) <= (DPageReadRequest::EMaxPages << KPageShift));
       
   579 				START_PAGING_BENCHMARK;
       
   580 				r = iDevice->Read(msg, buffer, readStart, readSize, DPagingDevice::EDriveRomPaging);
       
   581 				__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocated memory, therefore can't fail with KErrNoMemory
       
   582 				END_PAGING_BENCHMARK(EPagingBmReadMedia);
       
   583 				if(r==KErrNone)
       
   584 					{
       
   585 					// Decompress data, remembering that the data to decompress may be offset from 
       
   586 					// the start of the data just read in, due to reads having to be aligned by 
       
   587 					// readUnitShift.
       
   588 					const TLinAddr data = buffer + dataOffset - (readStart << readUnitShift);
       
   589 					__ASSERT_COMPILE(SRomPageInfo::ENoCompression==0); // decompress assumes this
       
   590 					r = Decompress(romPageInfo->iCompressionType, linAddr, KPageSize, data, dataSize);
       
   591 					if(r >= 0)
       
   592 						{
       
   593 						if (r != KPageSize)
       
   594 							__KTRACE_OPT(KPANIC, Kern::Printf("DRomMemoryManager::ReadPage: error decompressing page at %08x + %x: %d", dataOffset, dataSize, r));
       
   595 						__NK_ASSERT_ALWAYS(r == KPageSize);
       
   596 						r = KErrNone;
       
   597 						}
       
   598 					}
       
   599 				else
       
   600 					__KTRACE_OPT(KPANIC, Kern::Printf("DRomMemoryManager::ReadPage: error reading media at %08x + %x: %d", dataOffset, dataSize, r));
       
   601 				}
       
   602 			}
       
   603 		END_PAGING_BENCHMARK(EPagingBmReadRomPage);
       
   604 
       
   605 		if(r!=KErrNone)
       
   606 			break;
       
   607 		}
       
   608 
       
   609 	aRequest->UnmapPages(true);
       
   610 
       
   611 	return r;
       
   612 	}
       
   613 
       
   614 
       
   615 TBool DRomMemoryManager::IsAllocated(DMemoryObject* aMemory, TUint aIndex, TUint aCount)
       
   616 	{
       
   617 	// all pages in the ROM memory object are always allocated...
       
   618 	return true;
       
   619 	}
       
   620 
       
   621 
       
   622 TInt DRomMemoryManager::HandleFault(DMemoryObject* aMemory, TUint aIndex, DMemoryMapping* aMapping, 
       
   623 									TUint aMapInstanceCount, TUint aAccessPermissions)
       
   624 	{
       
   625 	__NK_ASSERT_DEBUG(aMemory==iRomMemory);
       
   626 
       
   627 	TUint offset = aIndex*KPageSize;
       
   628 	if(offset<iPagedStart || offset>=iPagedStart+iPagedSize)
       
   629 		return KErrAbort;
       
   630 
       
   631 	return DPagedMemoryManager::HandleFault(aMemory, aIndex, aMapping, aMapInstanceCount, aAccessPermissions);
       
   632 	}
       
   633 
       
   634 
       
   635 TInt DRomMemoryManager::Pin(DMemoryObject* aMemory, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs)
       
   636 	{
       
   637 	TRACE(("DRomMemoryManager::Pin %08x %08x", aMemory, aMapping));
       
   638 	TUint index = aMapping->iStartIndex;
       
   639 	TUint endIndex = index+aMapping->iSizeInPages;
       
   640 	if(endIndex>iSizeInPages)
       
   641 		return KErrNotFound;
       
   642 
       
   643 	TInt r = KErrNone;
       
   644 	TUint pagedIndex = iPagedStart>>KPageShift;
       
   645 	if(pagedIndex && pagedIndex<endIndex)
       
   646 		{
       
   647 		TUint start = index;
       
   648 		if(start<pagedIndex)
       
   649 			start = pagedIndex;
       
   650 		r = DoPin(aMemory,start,endIndex-start,aMapping,aPinArgs);
       
   651 		}
       
   652 
       
   653 	return r;
       
   654 	}
       
   655 
       
   656 
       
   657 TInt DRomMemoryManager::PageInPinnedDone(DMemoryObject* aMemory, TUint aIndex, SPageInfo* aPageInfo, TPhysAddr* aPageArrayEntry, TPinArgs& aPinArgs)
       
   658 	{
       
   659 	TRACE(("DRomMemoryManager::PageInPinnedDone %08x %d", aMemory, aIndex));
       
   660 	
       
   661 	// Only the paged part of rom should be pinned.
       
   662 	__NK_ASSERT_DEBUG(aIndex >= iPagedStart >> KPageShift);
       
   663 
       
   664 	TInt r = DoPageInDone(aMemory,aIndex,aPageInfo,aPageArrayEntry,true);
       
   665 
       
   666 	// Rom page can't be decommitted so this must succeed.
       
   667 	__NK_ASSERT_DEBUG(r >= 0);
       
   668 
       
   669 	if (aPageInfo->Type() == SPageInfo::EShadow)
       
   670 		{// The page is being shadowed so pin the original page.
       
   671 		// This is safe as the original page was physically pinned when shadowed.
       
   672 		__NK_ASSERT_DEBUG(RPageArray::IsPresent(*aPageArrayEntry));
       
   673 		aPageInfo = aPageInfo->GetOriginalPage();
       
   674 		}
       
   675 
       
   676 	ThePager.PagedInPinned(aPageInfo,aPinArgs);
       
   677 
       
   678 	// check page assigned correctly...
       
   679 #ifdef _DEBUG
       
   680 	if(RPageArray::IsPresent(*aPageArrayEntry))
       
   681 		{
       
   682 		SPageInfo* pi = SPageInfo::FromPhysAddr(*aPageArrayEntry);
       
   683 		if (pi->Type() != SPageInfo::EShadow)
       
   684 			{
       
   685 			__NK_ASSERT_DEBUG(pi->Type() == SPageInfo::EManaged);
       
   686 			__NK_ASSERT_DEBUG(pi->Owner()==aMemory);
       
   687 			__NK_ASSERT_DEBUG(pi->Index()==aIndex);
       
   688 			__NK_ASSERT_DEBUG(pi->PagedState()==SPageInfo::EPagedPinned);
       
   689 			}
       
   690 		}
       
   691 #endif
       
   692 	return r;
       
   693 	}
       
   694 
       
   695 
       
   696 void DRomMemoryManager::Unpin(DMemoryObject* aMemory, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs)
       
   697 	{
       
   698 	TRACE(("DRomMemoryManager::Unpin %08x %08x", aMemory, aMapping));
       
   699 	
       
   700 	__ASSERT_CRITICAL;
       
   701 	TUint index = aMapping->iStartIndex;
       
   702 	TUint endIndex = index+aMapping->iSizeInPages;
       
   703 	__NK_ASSERT_DEBUG(endIndex<=iSizeInPages); // Pin() should have already ensured this
       
   704 
       
   705 	TUint pagedIndex = iPagedStart>>KPageShift;
       
   706 	if(pagedIndex && pagedIndex<endIndex)
       
   707 		{
       
   708 		TUint start = index;
       
   709 		if(start<pagedIndex)
       
   710 			start = pagedIndex;
       
   711 		// unpin pages (but only if they were successfully pinned)...
       
   712 		if(aMapping->Flags()&DMemoryMapping::EPagesPinned)
       
   713 			DoUnpin(aMemory,start,endIndex-start,aMapping,aPinArgs);
       
   714 		}
       
   715 
       
   716 	__NK_ASSERT_DEBUG((aMapping->Flags()&DMemoryMapping::EPageUnmapVetoed)==0); // we shouldn't have tried to Free paged ROM
       
   717 	}
       
   718 
       
   719 
       
   720 void DRomMemoryManager::DoUnpin(DMemoryObject* aMemory, TUint aIndex, TUint aCount, DMemoryMappingBase* aMapping, TPinArgs& aPinArgs)
       
   721 	{
       
   722 	TRACE(("DRomMemoryManager::DoUnpin(0x%08x,0x%08x,0x%08x,0x%08x,?)",aMemory, aIndex, aCount, aMapping));
       
   723 
       
   724 	// This should only be invoked on the paged part of rom.
       
   725 	__NK_ASSERT_DEBUG(iPagedStart && aIndex >= (iPagedStart >> KPageShift));
       
   726 
       
   727 	MmuLock::Lock();
       
   728 	TUint endIndex = aIndex+aCount;
       
   729 	for(TUint i = aIndex; i < endIndex; ++i)
       
   730 		{
       
   731 		TPhysAddr page = aMemory->iPages.Page(i);
       
   732 		__NK_ASSERT_DEBUG(RPageArray::IsPresent(page));
       
   733 		SPageInfo* pi = SPageInfo::FromPhysAddr(page);
       
   734 		if(pi->Type() == SPageInfo::EShadow)
       
   735 			{
       
   736 			pi = pi->GetOriginalPage();
       
   737 			}
       
   738 		ThePager.Unpin(pi,aPinArgs);
       
   739 		MmuLock::Flash();
       
   740 		}
       
   741 
       
   742 	MmuLock::Unlock();
       
   743 
       
   744 	// clear EPagesPinned flag...
       
   745 	__e32_atomic_and_ord8(&aMapping->Flags(), TUint8(~DMemoryMapping::EPagesPinned));
       
   746 	}
       
   747 
       
   748 
       
   749 void DRomMemoryManager::ShadowLock()
       
   750 	{
       
   751 	MM::MemoryLock(iRomMemory);
       
   752 	}
       
   753 
       
   754 
       
   755 void DRomMemoryManager::ShadowUnlock()
       
   756 	{
       
   757 	MM::MemoryUnlock(iRomMemory);
       
   758 	}
       
   759 
       
   760 
       
   761 TInt DRomMemoryManager::AllocShadowPage(TLinAddr aRomAddr)
       
   762 	{
       
   763 	TRACE(("DRomMemoryManager::AllocShadowPage %08x", aRomAddr));
       
   764 	
       
   765 	TUint index = (aRomAddr-iBase)>>KPageShift;
       
   766 	if (index >= iSizeInPages)
       
   767 		return KErrArgument;
       
   768 	__NK_ASSERT_DEBUG(iRomMemory->CheckRegion(index,1));
       
   769 
       
   770 	TInt r;
       
   771 
       
   772 	ShadowLock();
       
   773 
       
   774 	DShadowPage* shadow = (DShadowPage*)iShadowPages.Find(index);
       
   775 	if(shadow)
       
   776 		r = KErrAlreadyExists;
       
   777 	else
       
   778 		{
       
   779 		shadow = DShadowPage::New(iRomMemory,index,iRomMapping);
       
   780 		if(!shadow)
       
   781 			r = KErrNoMemory;
       
   782 		else
       
   783 			{
       
   784 			r = iShadowPages.Add(index,shadow);
       
   785 			if(r!=KErrNone)
       
   786 				{
       
   787 				shadow->Destroy();
       
   788 				}
       
   789 			else
       
   790 				{
       
   791 				// Remap the shadowed rom page to the shadow page.  Update the 
       
   792 				// page array entry for the page being shadowed, this ensures 
       
   793 				// that any page moving attempts will remap the shadow page when
       
   794 				// they realise that the page is physically pinned.
       
   795 				MmuLock::Lock();
       
   796 				TPhysAddr& pageEntry = *iRomMemory->iPages.PageEntry(index);
       
   797 				TPhysAddr newPageAddr = shadow->iNewPage;
       
   798 				pageEntry = (pageEntry & KPageMask) | newPageAddr;
       
   799 
       
   800 				// Mark the SPageInfo of the shadow page with pointer to the original page's
       
   801 				// SPageInfo, this is safe as we've physically pinned the original page
       
   802 				// so it can't be freed or reused until this shadow page is destroyed.
       
   803 				SPageInfo* origPi = SPageInfo::FromPhysAddr(shadow->iOriginalPage);
       
   804 				SPageInfo* newPi = SPageInfo::FromPhysAddr(newPageAddr);
       
   805 				newPi->SetOriginalPage(origPi);
       
   806 				MmuLock::Unlock();
       
   807 
       
   808 				iRomMemory->RemapPage(pageEntry, index, ETrue);
       
   809 				}
       
   810 			}
       
   811 		}
       
   812 
       
   813 	ShadowUnlock();
       
   814 
       
   815 	return r;
       
   816 	}
       
   817 
       
   818 
       
   819 TInt DRomMemoryManager::FreeShadowPage(TLinAddr aRomAddr)
       
   820 	{
       
   821 	TUint index = (aRomAddr-iBase)>>KPageShift;
       
   822 	if(!iRomMemory->CheckRegion(index,1))
       
   823 		return KErrArgument;
       
   824 
       
   825 	TInt r;
       
   826 
       
   827 	ShadowLock();
       
   828 
       
   829 	DShadowPage* shadow = (DShadowPage*)iShadowPages.Remove(index);
       
   830 	if(!shadow)
       
   831 		{
       
   832 		r = KErrNotFound;
       
   833 		}
       
   834 	else
       
   835 		{
       
   836 		// Remap the rom page and update the page array entry for the page
       
   837 		// back to the original rom page.  This is safe as the page is physically 
       
   838 		// pinned until shadow is destroyed.
       
   839 		MmuLock::Lock();
       
   840 		TPhysAddr& pageEntry = *iRomMemory->iPages.PageEntry(index);
       
   841 		pageEntry = (pageEntry & KPageMask) | shadow->iOriginalPage;
       
   842 		MmuLock::Unlock();
       
   843 
       
   844 		iRomMemory->RemapPage(pageEntry, index, ETrue);
       
   845 		
       
   846 		shadow->Destroy();
       
   847 		r = KErrNone;
       
   848 		}
       
   849 
       
   850 	ShadowUnlock();
       
   851 
       
   852 	return r;
       
   853 	}
       
   854 
       
   855 
       
   856 TInt DRomMemoryManager::CopyToShadowMemory(TLinAddr aDst, TLinAddr aSrc, TUint32 aSize)
       
   857 	{
       
   858 	TRACE(("DRomMemoryManager::CopyToShadowMemory(0x%08x,0x%08x,0x%x)",aDst,aSrc,aSize));
       
   859 	Mmu& m = TheMmu;
       
   860 	TLinAddr offset = aDst-iBase;
       
   861 	TLinAddr end = offset+aSize;
       
   862 	if(end<offset || end>iSize)
       
   863 		return KErrArgument;
       
   864 
       
   865 	while(aSize)
       
   866 		{
       
   867 		TUint size = KPageSize-(offset&KPageMask); // bytes left in page at 'offset'
       
   868 		if(size>aSize)
       
   869 			size = aSize;
       
   870 
       
   871 		TInt r;
       
   872 
       
   873 		ShadowLock();
       
   874 
       
   875 		DShadowPage* shadow = (DShadowPage*)iShadowPages.Find(offset>>KPageShift);
       
   876 		if(!shadow)
       
   877 			{
       
   878 			r = KErrNotFound;
       
   879 			}
       
   880 		else
       
   881 			{
       
   882 			RamAllocLock::Lock();
       
   883 			TLinAddr dst = m.MapTemp(shadow->iNewPage,offset>>KPageShift);
       
   884 			dst += offset&KPageMask;
       
   885 			memcpy((TAny*)dst,(TAny*)aSrc,size);
       
   886 			m.UnmapTemp();
       
   887 			RamAllocLock::Unlock();
       
   888 
       
   889 			r = KErrNone;
       
   890 			}
       
   891 
       
   892 		ShadowUnlock();
       
   893 
       
   894 		if(r!=KErrNone)
       
   895 			return r;
       
   896 
       
   897 		offset += size;
       
   898 		aSrc += size;
       
   899 		aSize -= size;
       
   900 		}
       
   901 
       
   902 	return KErrNone;
       
   903 	}
       
   904 
       
   905 
       
   906 //
       
   907 // DShadowPage
       
   908 //
       
   909 
       
   910 DShadowPage* DShadowPage::New(DMemoryObject* aMemory, TUint aIndex, DMemoryMappingBase* aMapping)
       
   911 	{
       
   912 	TRACE(("DShadowPage::New(0x%08x,0x%x,0x%08x)",aMemory, aIndex, aMapping));
       
   913 	__NK_ASSERT_DEBUG(MemoryObjectLock::IsHeld(aMemory));
       
   914 
       
   915 	DShadowPage* self = new DShadowPage;
       
   916 	if(self)
       
   917 		if(self->Construct(aMemory,aIndex,aMapping)!=KErrNone)
       
   918 			{
       
   919 			self->Destroy();
       
   920 			self = 0;
       
   921 			}
       
   922 
       
   923 	TRACE(("DShadowPage::New(0x%08x,0x%x,0x%08x) returns 0x%08x",aMemory, aIndex, aMapping, self));
       
   924 	return self;
       
   925 	}
       
   926 
       
   927 
       
   928 DShadowPage::DShadowPage()
       
   929 	: iOriginalPage(KPhysAddrInvalid), iNewPage(KPhysAddrInvalid)
       
   930 	{
       
   931 	// Set flag so that the rom page that is being shadowed can't be moved, 
       
   932 	// otherwise iOriginalPage will become invalid if the page is moved.
       
   933 	Flags() |= EPhysicalPinningMapping;
       
   934 	}
       
   935 
       
   936 
       
   937 
       
   938 
       
   939 TInt DShadowPage::Construct(DMemoryObject* aMemory, TUint aIndex, DMemoryMappingBase* aMapping)
       
   940 	{
       
   941 	__NK_ASSERT_DEBUG(MemoryObjectLock::IsHeld(aMemory));
       
   942 
       
   943 	// Pin the page.  It is ok to get the mapping instance count here without
       
   944 	// MmuLock as there is only one permenant mapping used for the ROM.
       
   945 	TInt r = Pin(aMemory,aIndex,1,EUserReadOnly,aMapping,aMapping->MapInstanceCount());
       
   946 	if(r!=KErrNone)
       
   947 		return r;
       
   948 
       
   949 	r = PhysAddr(0,1,iOriginalPage,0);
       
   950 	__NK_ASSERT_DEBUG(r>=0);
       
   951 	if(r<0)
       
   952 		return r;
       
   953 
       
   954 	RamAllocLock::Lock();
       
   955 
       
   956 	Mmu& m = TheMmu;
       
   957 	r = m.AllocRam(&iNewPage, 1, aMemory->RamAllocFlags(), EPageFixed);
       
   958 	if(r==KErrNone)
       
   959 		{
       
   960 		TLinAddr dst = m.MapTemp(iNewPage,aIndex,0);
       
   961 		TLinAddr src = m.MapTemp(iOriginalPage,aIndex,1);
       
   962 		pagecpy((TAny*)dst,(TAny*)src);
       
   963 		CacheMaintenance::CodeChanged(dst,KPageSize); // IMB not needed, just clean to PoU (but we don't have a function to do that)
       
   964 
       
   965 		m.UnmapTemp(0);
       
   966 		m.UnmapTemp(1);
       
   967 		MmuLock::Lock();
       
   968 		SPageInfo::FromPhysAddr(iNewPage)->SetShadow(aIndex,aMemory->PageInfoFlags());
       
   969 		MmuLock::Unlock();
       
   970 		}
       
   971 
       
   972 	RamAllocLock::Unlock();
       
   973 
       
   974 	if(r!=KErrNone)
       
   975 		return r;
       
   976 
       
   977 	return r;
       
   978 	}
       
   979 
       
   980 
       
   981 DShadowPage::~DShadowPage()
       
   982 	{
       
   983 	}
       
   984 
       
   985 
       
   986 void DShadowPage::Destroy()
       
   987 	{
       
   988 	TRACE2(("DShadowPage[%x]::Destroy()",this));
       
   989 	if(iNewPage!=KPhysAddrInvalid)
       
   990 		{
       
   991 		RamAllocLock::Lock();
       
   992 		TheMmu.FreeRam(&iNewPage, 1, EPageFixed);
       
   993 		RamAllocLock::Unlock();
       
   994 		}
       
   995 	if(IsAttached())
       
   996 		Unpin();
       
   997 	Close();
       
   998 	}
       
   999 
       
  1000 
       
  1001 /**
       
  1002 Replace a page of the system's execute-in-place (XIP) ROM image with a page of
       
  1003 RAM having the same contents. This RAM can subsequently be written to in order
       
  1004 to apply patches to the XIP ROM or to insert software breakpoints for debugging
       
  1005 purposes.
       
  1006 Call Epoc::FreeShadowPage() when you wish to revert to the original ROM page.
       
  1007 
       
  1008 @param	aRomAddr	The virtual address of the ROM page to be replaced.
       
  1009 @return	KErrNone if the operation completed successfully.
       
  1010 		KErrArgument if the specified address is not a valid XIP ROM address.
       
  1011 		KErrNoMemory if the operation failed due to insufficient free RAM.
       
  1012 		KErrAlreadyExists if the XIP ROM page at the specified address has
       
  1013 			already been shadowed by a RAM page.
       
  1014 
       
  1015 @pre Calling thread must be in a critical section.
       
  1016 @pre Interrupts must be enabled.
       
  1017 @pre Kernel must be unlocked.
       
  1018 @pre No fast mutex can be held.
       
  1019 @pre Call in a thread context.
       
  1020 */
       
  1021 EXPORT_C TInt Epoc::AllocShadowPage(TLinAddr aRomAddr)
       
  1022 	{
       
  1023 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::AllocShadowPage");
       
  1024 	return DRomMemoryManager::TheManager.AllocShadowPage(aRomAddr);
       
  1025 	}
       
  1026 
       
  1027 
       
  1028 /**
       
  1029 Copies data into shadow memory. Source data is presumed to be in Kernel memory.
       
  1030 
       
  1031 @param	aSrc	Data to copy from.
       
  1032 @param	aDest	Address to copy into.
       
  1033 @param	aLength	Number of bytes to copy. Maximum of 32 bytes of data can be copied.
       
  1034 
       
  1035 @return	KErrNone 		if the operation completed successfully.
       
  1036 		KErrArgument 	if any part of destination region is not shadow page or
       
  1037 						if aLength is greater then 32 bytes.
       
  1038 
       
  1039 @pre Calling thread must be in a critical section.
       
  1040 @pre Interrupts must be enabled.
       
  1041 @pre Kernel must be unlocked.
       
  1042 @pre No fast mutex can be held.
       
  1043 @pre Call in a thread context.
       
  1044 */
       
  1045 EXPORT_C TInt Epoc::CopyToShadowMemory(TLinAddr aDest, TLinAddr aSrc, TUint32 aLength)
       
  1046 	{
       
  1047 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::CopyToShadowMemory");
       
  1048 	return DRomMemoryManager::TheManager.CopyToShadowMemory(aDest,aSrc,aLength);
       
  1049 	}
       
  1050 
       
  1051 
       
  1052 /**
       
  1053 Revert an XIP ROM address which has previously been shadowed to the original
       
  1054 page of ROM.
       
  1055 
       
  1056 @param	aRomAddr	The virtual address of the ROM page to be reverted.
       
  1057 @return	KErrNone if the operation completed successfully.
       
  1058 		KErrArgument if the specified address is not a valid XIP ROM address.
       
  1059 		KErrGeneral if the specified address has not previously been shadowed
       
  1060 			using Epoc::AllocShadowPage().
       
  1061 
       
  1062 @pre Calling thread must be in a critical section.
       
  1063 @pre Interrupts must be enabled.
       
  1064 @pre Kernel must be unlocked.
       
  1065 @pre No fast mutex can be held.
       
  1066 @pre Call in a thread context.
       
  1067 */
       
  1068 EXPORT_C TInt Epoc::FreeShadowPage(TLinAddr aRomAddr)
       
  1069 	{
       
  1070 	return DRomMemoryManager::TheManager.FreeShadowPage(aRomAddr);
       
  1071 	}
       
  1072 
       
  1073 
       
  1074 /**
       
  1075 Change the permissions on an XIP ROM address which has previously been shadowed
       
  1076 by a RAM page so that the RAM page may no longer be written to.
       
  1077 
       
  1078 Note: Shadow page on the latest platforms (that use the reduced set of access permissions:
       
  1079 arm11mpcore, arm1176, cortex) is implemented with read only permissions. Therefore, calling
       
  1080 this function in not necessary, as shadow page is already created as 'frozen'.
       
  1081 
       
  1082 @param	aRomAddr	The virtual address of the shadow RAM page to be frozen.
       
  1083 @return	KErrNone if the operation completed successfully.
       
  1084 		KErrArgument if the specified address is not a valid XIP ROM address.
       
  1085 		KErrGeneral if the specified address has not previously been shadowed
       
  1086 			using Epoc::AllocShadowPage().
       
  1087 
       
  1088 @pre Calling thread must be in a critical section.
       
  1089 @pre Interrupts must be enabled.
       
  1090 @pre Kernel must be unlocked.
       
  1091 @pre No fast mutex can be held.
       
  1092 @pre Call in a thread context.
       
  1093 */
       
  1094 EXPORT_C TInt Epoc::FreezeShadowPage(TLinAddr aRomAddr)
       
  1095 	{
       
  1096 	// Null operation for flexible memory model...
       
  1097 	return KErrNone;
       
  1098 	}
       
  1099 
       
  1100