kernel/eka/memmodel/epoc/flexible/mmu/mobject.h
changeset 9 96e5fb8b040d
child 20 597aaf25e343
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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 /**
       
    17  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 #ifndef MOBJECT_H
       
    22 #define MOBJECT_H
       
    23 
       
    24 #include "mrefcntobj.h"
       
    25 #include "mmappinglist.h"
       
    26 #include "mpagearray.h"
       
    27 
       
    28 class DMemoryManager;
       
    29 class DCoarseMapping;
       
    30 
       
    31 
       
    32 /**
       
    33 Base class for memory objects.
       
    34 
       
    35 A memory object is a sparse array of memory pages (#iPages) to which memory
       
    36 mappings may be attached (#iMappings). All pages in the array are managed
       
    37 in the same way (#iManager).
       
    38 */
       
    39 class DMemoryObject : public DReferenceCountedObject
       
    40 	{
       
    41 public:
       
    42 	virtual ~DMemoryObject();
       
    43 
       
    44 	/**
       
    45 	Claim ownership of memory originally allocated by the bootstrap.
       
    46 
       
    47 	This is used during system boot to initialise this object's memory to contain
       
    48 	the pages which are already mapped at a given region of virtual addresses.
       
    49 
       
    50 	For coarse memory objects, this function also takes ownership of the page tables
       
    51 	being used to map the memory.
       
    52 
       
    53 	@param aBase				Starting virtual address of memory to claim.
       
    54 
       
    55 	@param aSize				Size, in bytes, of memory region to claim.
       
    56 
       
    57 	@param aPermissions			The access permissions which the memory region
       
    58 								is mapped. As well as being required for correct object
       
    59 								initialisation this also enables the function to check
       
    60 								that the bootstrap code mapped the memory in manner
       
    61 								consistent with the flexible memory model implementation.
       
    62 
       
    63 	@param aAllowGaps			True if the memory region may have gaps (unmapped pages) in it.
       
    64 								If false, the function faults if the region is not fully
       
    65 								populated with mapped pages.
       
    66 
       
    67 	@param aAllowNonRamPages	True if the memory region contains memory pages which are
       
    68 								not RAM pages known to the kernel. I.e. are not
       
    69 								contained in the list of RAM banks supplied by the bootstrap.
       
    70 								Any such memory cannot be never be subsequently freed from the
       
    71 								memory object because the kernel can't handle this memory.
       
    72 
       
    73 	@return KErrNone if successful, otherwise one of the system wide error codes.
       
    74 	*/
       
    75 	virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false) = 0;
       
    76 
       
    77 	/**
       
    78 	Update the page table entries for all attached mappings to add entries for
       
    79 	a specified set of memory pages.
       
    80 
       
    81 	This method is called by this object's manager whenever new pages of memory are added.
       
    82 
       
    83 	@param aPages				An RPageArray::TIter which refers to a range of pages
       
    84 								in this memory object.
       
    85 								Only array entries which have state RPageArray::ECommitted
       
    86 								should be mapped into a mapping's page tables.
       
    87 
       
    88 	@return KErrNone if successful, otherwise one of the system wide error codes.
       
    89 	*/
       
    90 	virtual TInt MapPages(RPageArray::TIter aPages);
       
    91 
       
    92 	/**
       
    93 	Update the page table entries for all attached mappings to add new entry for
       
    94 	a specified memory page.
       
    95 
       
    96 	This method is called by this object's manager whenever the page is moved.
       
    97 
       
    98 	@param aPageArray			The page array entry of the page in this memory object.
       
    99 								Only array entries which have state RPageArray::ECommitted
       
   100 								should be mapped into a mapping's page tables.
       
   101 
       
   102 	@param aIndex				The index of the page in this memory object.
       
   103 
       
   104 	@param	aInvalidateTLB		Set to ETrue when the TLB entries associated with this page
       
   105 								should be invalidated.  This must be done when there is 
       
   106 								already a valid pte for this page, i.e. if the page is still 
       
   107 								mapped.
       
   108 
       
   109 	@return KErrNone if successful, otherwise one of the system wide error codes.
       
   110 	*/
       
   111 	virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB);
       
   112 
       
   113 	/**
       
   114 	Update the page table entries for all attached mappings to remove entries for
       
   115 	a specified set of memory pages.
       
   116 
       
   117 	This method is called this object's manager whenever pages of memory are removed.
       
   118 
       
   119 	@param aPages				An RPageArray::TIter which refers to a range of pages
       
   120 								in this memory object.
       
   121 								Only array entries which return true for
       
   122 								RPageArray::TargetStateIsDecommitted should be unmapped
       
   123 								from a mapping's page tables.
       
   124 
       
   125 	@param aDecommitting		True if memory is being permanently decommitted from
       
   126 								the memory object. False if the memory pages are only
       
   127 								temporarily being unmapped due to a demand paging 'page out'
       
   128 								operation.
       
   129 	*/
       
   130 	virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting);
       
   131 
       
   132 	/**
       
   133 	Update the page table entries for all attached mappings to apply access restrictions
       
   134 	to a specified set of memory pages.
       
   135 
       
   136 	This method is called by this object's manager whenever pages of memory are restricted.
       
   137 
       
   138 	@param aPages				An RPageArray::TIter which refers to a range of pages
       
   139 								in this memory object.
       
   140 								Only array entries which return true for
       
   141 								RPageArray::TargetStateIsDecommitted should be unmapped
       
   142 								from a mapping's page tables.
       
   143 
       
   144 	@param aRestriction			A value from enum #TRestrictPagesType indicating the
       
   145 								kind of restriction to apply.
       
   146 	*/
       
   147 	virtual void RestrictPages(RPageArray::TIter aPages, TRestrictPagesType aRestriction);
       
   148 
       
   149 	/**
       
   150 	Add a memory mapping to this memory object.
       
   151 
       
   152 	This is only intended for use by #DMemoryMappingBase::Attach.
       
   153 
       
   154 	After verifying that the mapping is permitted (using #CheckNewMapping)
       
   155 	the mapping is linked into this objects list of mappings #iMappings.
       
   156 
       
   157 	@param aMapping The mapping to add.
       
   158 
       
   159 	@return KErrNone if successful,
       
   160 			otherwise KErrAccessDenied to indicate that the mapping is not allowed.
       
   161 	*/
       
   162 	virtual TInt AddMapping(DMemoryMappingBase* aMapping);
       
   163 
       
   164 	/**
       
   165 	Remove a memory mapping from this memory object.
       
   166 
       
   167 	This is only intended for use by #DMemoryMappingBase::Detach.
       
   168 
       
   169 	This unlinks the mapping from the list of mappings #iMappings.
       
   170 
       
   171 	@param aMapping The mapping to remove.
       
   172 	*/
       
   173 	virtual void RemoveMapping(DMemoryMappingBase* aMapping);
       
   174 
       
   175 	/**
       
   176 	Attempt to set the memory object read only.  This will only succeed if
       
   177 	there are no writable mappings to the memory object.
       
   178 
       
   179 	NOTE - This can't be undone, page moving will break if a memory object 
       
   180 	is made writable again.
       
   181 
       
   182 	@return KErrNone on success, KErrInUse if writable mappings are found.
       
   183 	*/
       
   184 	virtual TInt SetReadOnly();
       
   185 
       
   186 	/**
       
   187 	Create a mapping object to map this memory.
       
   188 
       
   189 	This is only intended for use by #MM::MappingNew.
       
   190 	
       
   191 	The base class creates a #DFineMapping object.  It is overridden by #DCoarseMemory to create a
       
   192 	#DCoarseMapping in appropriate circumstances.
       
   193 
       
   194 	@param aIndex 		The index of the start of the mapping into this memory object.
       
   195 	@oaram aCount		The size in pages of the mapping.
       
   196 	*/
       
   197 	virtual DMemoryMapping* CreateMapping(TUint aIndex, TUint aCount);
       
   198 
       
   199 	/**
       
   200 	Get the physical address(es) for a region of pages in this memory object.
       
   201 
       
   202 	Depending on how the memory is being managed the physical addresses returned
       
   203 	may become invalid due to various reasons, e.g.
       
   204 
       
   205 	- memory being decommitted from the memory object
       
   206 	- ram defragmentation moving the memory contents to a different physical page
       
   207 	- paging out of demand paged memory
       
   208 
       
   209 	This function should therefore only be used where it is know that these
       
   210 	possibilities can't occur, e.g. this is used safely by DPhysicalPinMapping::PhysAddr.
       
   211 
       
   212 	@param aIndex			Page index, within the memory, for the start of the region.
       
   213 	@param aCount			Number of pages in the region.
       
   214 	@param aPhysicalAddress	On success, this value is set to one of two values.
       
   215 							If the specified region is physically contiguous,
       
   216 							the value is the physical address of the first page
       
   217 							in the region. If the region is discontiguous, the
       
   218 							value is set to KPhysAddrInvalid.
       
   219 	@param aPhysicalPageList If not zero, this points to an array of TPhysAddr
       
   220 							objects. On success, this array will be filled
       
   221 							with the addresses of the physical pages which
       
   222 							contain the specified region. If aPageList is
       
   223 							zero, then the function will fail with
       
   224 							KErrNotFound if the specified region is not
       
   225 							physically contiguous.
       
   226 
       
   227 	@return 0 if successful and the whole region is physically contiguous.
       
   228 			1 if successful but the region isn't physically contiguous.
       
   229 			KErrNotFound, if any page in the region is not present,
       
   230 			otherwise one of the system wide error codes.
       
   231 	*/
       
   232 	TInt PhysAddr(TUint aIndex, TUint aCount, TPhysAddr& aPhysicalAddress, TPhysAddr* aPhysicalPageList);
       
   233 
       
   234 	/**
       
   235 	Check specified region lies entirely within this memory object, and that it
       
   236 	is page aligned.
       
   237 	*/
       
   238 	TBool CheckRegion(TUint aIndex, TUint aCount);
       
   239 
       
   240 	/**
       
   241 	Clip the specified region to lie within the memory object,
       
   242 	*/
       
   243 	void ClipRegion(TUint& aIndex, TUint& aCount);
       
   244 
       
   245 	/**
       
   246 	Set the mutex used to lock operations on this memory object
       
   247 	*/
       
   248 	void SetLock(DMutex* aLock);
       
   249 
       
   250 	/**
       
   251 	Prevents any further mappings being added to this memory object.
       
   252 	*/
       
   253 	void DenyMappings();
       
   254 
       
   255 	/**
       
   256 	Return the memory attributes for this object's memory.
       
   257 	*/
       
   258 	FORCE_INLINE TMemoryAttributes Attributes()
       
   259 		{
       
   260 		return (TMemoryAttributes)iAttributes;
       
   261 		}
       
   262 
       
   263 	/**
       
   264 	Value for initialising SPageInfo::iFlags when allocating pages.
       
   265 	*/
       
   266 	FORCE_INLINE TUint8 PageInfoFlags()
       
   267 		{
       
   268 		return iAttributes;
       
   269 		}
       
   270 
       
   271 	/**
       
   272 	Value for #Mmu::TRamAllocFlags to use when allocating pages.
       
   273 	*/
       
   274 	FORCE_INLINE Mmu::TRamAllocFlags RamAllocFlags()
       
   275 		{
       
   276 		return (Mmu::TRamAllocFlags)iRamAllocFlags;
       
   277 		}
       
   278 
       
   279 	/**
       
   280 	Return true if this object is an instance of #DCoarseMemory.
       
   281 	*/
       
   282 	FORCE_INLINE TBool IsCoarse()
       
   283 		{
       
   284 		return iFlags&ECoarseObject;
       
   285 		}
       
   286 
       
   287 	/**
       
   288 	Return true if this object contains memory which is being demand paged.
       
   289 	*/
       
   290 	FORCE_INLINE TBool IsDemandPaged()
       
   291 		{
       
   292 		return iFlags&EDemandPaged;
       
   293 		}
       
   294 
       
   295 	/**
       
   296 	Return true if writeable mappings of the memory are not allowed.
       
   297 	*/
       
   298 	FORCE_INLINE TBool IsReadOnly()
       
   299 		{
       
   300 		return iFlags&EDenyWriteMappings;
       
   301 		}
       
   302 
       
   303 	/**
       
   304 	Return true if executable mappings allowed on this memory object.
       
   305 	*/
       
   306 	FORCE_INLINE TBool IsExecutable()
       
   307 		{
       
   308 		return !(iFlags&EDenyExecuteMappings);
       
   309 		}
       
   310 
       
   311 	/**
       
   312 	Clear the flag that indicates that a mapping has been added.
       
   313 	*/
       
   314 	FORCE_INLINE void ClearMappingAddedFlag()
       
   315 		{
       
   316 		__NK_ASSERT_DEBUG(iMappings.LockIsHeld());
       
   317 		__e32_atomic_and_ord8(&iFlags, (TUint8)~EMappingAdded);
       
   318 		}
       
   319 
       
   320 	/**
       
   321 	Set the flag to indicate that a mapping has been added.
       
   322 	*/
       
   323 	FORCE_INLINE void SetMappingAddedFlag()
       
   324 		{
       
   325 		__NK_ASSERT_DEBUG(iMappings.LockIsHeld());
       
   326 		__NK_ASSERT_DEBUG(MmuLock::IsHeld());
       
   327 		__e32_atomic_ior_ord8(&iFlags, (TUint8)EMappingAdded);
       
   328 		}
       
   329 
       
   330 	/**
       
   331 	Get the value of the mappings added flags
       
   332 
       
   333 	@return ETrue if a mapping has been added, EFalse otherwise.
       
   334 	*/
       
   335 	FORCE_INLINE TBool MappingAddedFlag()
       
   336 		{
       
   337 		__NK_ASSERT_DEBUG(MmuLock::IsHeld());
       
   338 		return iFlags & (TUint8)EMappingAdded;
       
   339 		}
       
   340 
       
   341 	enum
       
   342 		{
       
   343 		/**
       
   344 		Maximum number of bits which can be stored in an array entry by SetPagingManagerData.
       
   345 		*/
       
   346 		KPagingManagerDataBits = RPageArray::KPagingManagerDataBits
       
   347 		};
       
   348 
       
   349 	enum
       
   350 		{
       
   351 		/**
       
   352 		Maximum value which can be stored in an array entry by SetPagingManagerData.
       
   353 		*/
       
   354 		KMaxPagingManagerData = RPageArray::KMaxPagingManagerData
       
   355 		};
       
   356 
       
   357 	/**
       
   358 	Write \a aValue to the paging manager data for page index \a aIndex.
       
   359 	The value must not exceed KMaxPagingManagerData.
       
   360 	This must only be used for demand paged memory objects.
       
   361 	*/
       
   362 	void SetPagingManagerData(TUint aIndex, TUint aValue);
       
   363 
       
   364 	/**
       
   365 	Return the paging manager data for page index \a aIndex.
       
   366 	This must only be used for demand paged memory objects.
       
   367 	@see SetPagingManagerData
       
   368 	*/
       
   369 	TUint PagingManagerData(TUint aIndex);
       
   370 
       
   371 	/**
       
   372 	Check that a given memory mapping is allowed to be attached to this memory object.
       
   373 
       
   374 	@param aMapping	The mapping to check.
       
   375 
       
   376 	@return KErrNone if successful,
       
   377 			otherwise KErrAccessDenied to indicate that the mapping is not allowed.
       
   378 	*/
       
   379 	TInt CheckNewMapping(DMemoryMappingBase* aMapping);
       
   380 
       
   381 	/**
       
   382 	Emit BTrace traces identifying the initial attributes of this object.
       
   383 	*/
       
   384 	void BTraceCreate();
       
   385 
       
   386 protected:
       
   387 	/**
       
   388 	@param aManager		The manager object for this memory.
       
   389 	@param aFlags		Initial value for #iFlags.
       
   390 	@param aSizeInPages	Size of the memory object, in number of pages.
       
   391 	@param aAttributes	Bitmask of values from enum #TMemoryAttributes.
       
   392 	@param aCreateFlags	Bitmask of option flags from enum #TMemoryCreateFlags.
       
   393 	*/
       
   394 	DMemoryObject(DMemoryManager* aManager, TUint aFlags, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
       
   395 
       
   396 	/**
       
   397 	Second phase constructor.
       
   398 
       
   399 	@return KErrNone if successful, otherwise one of the system wide error codes.
       
   400 	*/
       
   401 	TInt Construct();
       
   402 
       
   403 public:
       
   404 	/**
       
   405 	The manager of this memory object.
       
   406 	*/
       
   407 	DMemoryManager*	iManager;
       
   408 
       
   409 	/**
       
   410 	For use by this object's manager (iManager) to store any memory objects specific state
       
   411 	it requires to keep track of.
       
   412 	*/
       
   413 	TAny*			iManagerData;
       
   414 
       
   415 	/**
       
   416 	For use by DMemoryManager::QueueCleanup to link objects which require a cleanup operation.
       
   417 	Access to this is protected by #DMemoryManager::iCleanupLock.
       
   418 	*/
       
   419 	DMemoryObject*	iCleanupNext;
       
   420 
       
   421 	/**
       
   422 	For use by DMemoryManager::QueueCleanup to store flags representing each pending cleanup operation.
       
   423 	Access to this is protected by #DMemoryManager::iCleanupLock.
       
   424 	*/
       
   425 	TUint32			iCleanupFlags;
       
   426 
       
   427 	/**
       
   428 	Bit flags stored in #iFlags giving various state and attributes of the object.
       
   429 	*/
       
   430 	enum TFlags
       
   431 		{
       
   432 		/**
       
   433 		Flag set during object construction to indicate that this mapping is of
       
   434 		class #DCoarseMemory.
       
   435 		*/
       
   436 		ECoarseObject			= 1<<0,
       
   437 
       
   438 		/**
       
   439 		Flag set during object construction to indicate that the memory for this object
       
   440 		is being demand paged in some manner.
       
   441 		*/
       
   442 		EDemandPaged			= 1<<1,
       
   443 
       
   444 		/**
       
   445 		Flag set during object construction to indicate that all resources for this
       
   446 		object are to be reserved during construction; excluding memory pages owned by
       
   447 		object. Objects constructed in this way will not require additional memory
       
   448 		allocation when committing memory to them (other than allocating the memory
       
   449 		pages being committed.)
       
   450 		*/
       
   451 		EReserveResources		= 1<<2,
       
   452 
       
   453 		/**
       
   454 		Flag set during object construction to indicate that pinned memory mappings
       
   455 		are not allowed to be attached to this object.
       
   456 		*/
       
   457 		EDenyPinning			= 1<<3,
       
   458 
       
   459 		/**
       
   460 		Flag set by DenyMappings to indicate that no additional memory mappings
       
   461 		are allowed to be attached to this object.
       
   462 		*/
       
   463 		EDenyMappings			= 1<<4,
       
   464 
       
   465 		/**
       
   466 		Flag set during object construction, or by SetReadOnly, to indicate that
       
   467 		the memory object is read-only and no writable mappings are allowed
       
   468 		to be attached to this object.
       
   469 		*/
       
   470 		EDenyWriteMappings		= 1<<5,
       
   471 
       
   472 		/**
       
   473 		Flag set during object construction to indicate that executable memory mappings
       
   474 		are not allowed to be attached to this object.
       
   475 		This is mainly an optimisation to allow demand paging to avoid instruction cache
       
   476 		maintenance operations during page fault handling.
       
   477 		*/
       
   478 		EDenyExecuteMappings	= 1<<6,
       
   479 
       
   480 		/**
       
   481 		Flag set whenever a new mapping is added to a memory object.
       
   482 		The object's mappings lock and MmuLock protects this flag when it is set
       
   483 		and the mappings lock protects when it is cleared.
       
   484 		*/
       
   485 		EMappingAdded			= 1<<7,
       
   486 		};
       
   487 
       
   488 	/**
       
   489 	Bitmask of TFlags
       
   490 	*/
       
   491 	TUint8 iFlags;
       
   492 
       
   493 	/**
       
   494 	Value from TMemoryAttributes indicating type of memory in object.
       
   495 	*/
       
   496 	TUint8 iAttributes;
       
   497 
       
   498 	/**
       
   499 	#Mmu::TRamAllocFlags value to use when allocating RAM for this memory object.
       
   500 	*/
       
   501 	TUint16 iRamAllocFlags;
       
   502 
       
   503 	/**
       
   504 	List of mappings currently attached to this object.
       
   505 	*/
       
   506 	TMappingList iMappings;
       
   507 
       
   508 	/**
       
   509 	Size, in page units, of this memory object.
       
   510 	*/
       
   511 	TUint iSizeInPages;
       
   512 
       
   513 	/**
       
   514 	Lock currently being used to serialise explicit memory operations.
       
   515 	This is assigned using #MemoryObjectLock.
       
   516 	*/
       
   517 	DMutex* iLock;
       
   518 
       
   519 	/**
       
   520 	The array of memory pages assigned to this memory object.
       
   521 	*/
       
   522 	RPageArray iPages;
       
   523 	};
       
   524 
       
   525 
       
   526 
       
   527 /**
       
   528 A memory object which has a size that is an exact multiple
       
   529 multiple of the region covered by a whole MMU page table;
       
   530 that is a 'chunk' size (#KChunkSize) bytes.
       
   531 
       
   532 When used in conjunction with DCoarseMapping this object
       
   533 allows RAM to be saved by sharing MMU page tables between multiple
       
   534 different mappings of the memory.
       
   535 
       
   536 Fine memory mappings (DFineMapping) may also be attached
       
   537 to this memory object but these won't benefit from page table
       
   538 sharing.
       
   539 */
       
   540 class DCoarseMemory : public DMemoryObject
       
   541 	{
       
   542 public:
       
   543 	// from DMemoryObject...
       
   544 	virtual ~DCoarseMemory();
       
   545 	virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false);
       
   546 	virtual TInt MapPages(RPageArray::TIter aPages);
       
   547 	virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB);
       
   548 	virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting);
       
   549 	virtual void RestrictPages(RPageArray::TIter aPages, TRestrictPagesType aRestriction);
       
   550 	virtual TInt AddMapping(DMemoryMappingBase* aMapping);
       
   551 	virtual void RemoveMapping(DMemoryMappingBase* aMapping);
       
   552 	virtual TInt SetReadOnly();
       
   553 	virtual DMemoryMapping* CreateMapping(TUint aIndex, TUint aCount);
       
   554 public:
       
   555 	/**
       
   556 	Create a new DCoarseMemory object.
       
   557 
       
   558 	@param aManager		The manager object for this memory.
       
   559 	@param aSizeInPages	Size of the memory object, in number of pages.
       
   560 						(Must represent an exact 'chunk' size.)
       
   561 	@param aAttributes	Bitmask of values from enum #TMemoryAttributes.
       
   562 	@param aCreateFlags	Bitmask of option flags from enum #TMemoryCreateFlags.
       
   563 
       
   564 	@return The newly created DCoarseMemory or the null pointer if there was
       
   565 			insufficient memory.
       
   566 	*/
       
   567 	static DCoarseMemory* New(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
       
   568 
       
   569 	/**
       
   570 	Remove an mmu page table from this memory object's ownership.
       
   571 	This is called when a RAM page containing the page table is paged out.
       
   572 	This function delegates its action to DPageTables::StealPageTable.
       
   573 
       
   574 	@param aChunkIndex	The index of the page table, i.e. the offset, in 'chunks',
       
   575 						into the object's memory that the page table is being used to map.
       
   576 						(The index into DPageTables::iTables.)
       
   577 	@param aPteType		The #TPteType the page table is being used for.
       
   578 						(The index into #iPageTables.)
       
   579 
       
   580 	@pre #MmuLock is held.
       
   581 	@pre #PageTablesLockIsHeld
       
   582 	*/
       
   583 	void StealPageTable(TUint aChunkIndex, TUint aPteType);
       
   584 
       
   585 public:
       
   586 	// Interface for DCoarseMapping
       
   587 	
       
   588 	/**
       
   589 	Get the page table to use for mapping a specified chunk if it exists.
       
   590 
       
   591 	@param aPteType		The #TPteType the page tables will be used for.
       
   592 	@param aChunkIndex	The index of the chunk.
       
   593 
       
   594 	@return The virtual address of the page table, or NULL.
       
   595 
       
   596 	@pre #MmuLock is held.
       
   597 	*/
       
   598 	TPte* GetPageTable(TUint aPteType , TUint aChunkIndex);
       
   599 
       
   600 	/**
       
   601 	Update the page tables to add entries for a specified set of demand paged memory
       
   602 	pages following a 'page in' or memory pinning operation.
       
   603 
       
   604 	@param aMapping				The mapping the pages are being paged into.
       
   605 	
       
   606 	@param aPages				An RPageArray::TIter which refers to a range of pages
       
   607 								in the memory object #iMemory.
       
   608 								Only array entries which have state RPageArray::ECommitted
       
   609 								should be mapped into the page tables.
       
   610 
       
   611 	@param aPinArgs				The resources required to pin any page tables.
       
   612 								Page table must be pinned if \a aPinArgs.iPinnedPageTables is
       
   613 								not the null pointer, in which case this the virtual address
       
   614 								of the pinned must be stored in the array this points to.
       
   615 								\a aPinArgs.iReadOnly is true if write access permissions
       
   616 								are not needed.
       
   617 
       
   618 	@return KErrNone if successful, otherwise one of the system wide error codes.
       
   619 
       
   620 	@pre #MmuLock is held.
       
   621 	@post #MmuLock has been released.
       
   622 	*/
       
   623 	TInt PageIn(DCoarseMapping* aMapping, RPageArray::TIter aPages, TPinArgs& aPinArgs, TUint aMapInstanceCount);
       
   624 
       
   625 	/**
       
   626 	Update the page table entries to renable access to a specified memory page.
       
   627 
       
   628 	This method is called by #DCoarseMapping::MovingPageIn
       
   629 
       
   630 	@param aMapping				The mapping which maps the page.
       
   631 	@param aPageArrayPtr		The page array entry of the page to map.
       
   632 								Only array entries which have state RPageArray::ECommitted
       
   633 								should be mapped into a mapping's page tables.
       
   634 
       
   635 	@param aIndex				The index of the memory page.
       
   636 	*/
       
   637 	TBool MovingPageIn(DCoarseMapping* aMapping, TPhysAddr& aPageArrayPtr, TUint aIndex);
       
   638 
       
   639 	/**
       
   640 	Function to return a page table pointer for the specified linear address and
       
   641 	index to this mapping.
       
   642 
       
   643 	This method is called by #DCoarseMapping::FindPageTable.
       
   644 	
       
   645 	@param aLinAddr		The linear address to find the page table entry for.
       
   646 	@param aMemoryIndex	The memory object index of the page to find the page 
       
   647 						table entry for.
       
   648 	
       
   649 	@return A pointer to the page table entry, if the page table entry couldn't 
       
   650 			be found this will be NULL
       
   651 	*/
       
   652 	TPte* FindPageTable(DCoarseMapping* aMapping, TLinAddr aLinAddr, TUint aMemoryIndex);
       
   653 	
       
   654 protected:
       
   655 	/**
       
   656 	For arguments, see #New.
       
   657 	*/
       
   658 	DCoarseMemory(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
       
   659 	
       
   660 public:
       
   661 	/**
       
   662 	The object which manages the page tables owned by a #DCoarseMemory object
       
   663 	and used by #DCoarseMapping objects. Each DPageTables is used for mappings
       
   664 	with a specific #TPteType e.g. set of memory access permissions, and all these
       
   665 	#DCoarseMapping objects are linked into this object whenever they are
       
   666 	attached to a DCoarseMemory.
       
   667 	*/
       
   668 	class DPageTables : public DReferenceCountedObject
       
   669 		{
       
   670 	public:
       
   671 		/**
       
   672 		Create a new DPageTables.
       
   673 
       
   674 		This object is added to DCoarseMemory::iPageTables and all of
       
   675 		the mmu page tables will be initialised to map the memory currently
       
   676 		owned by the memory object (unless memory is demand paged).
       
   677 
       
   678 
       
   679 		@param aMemory		The DCoarseMemory the new object is associated with.
       
   680 		@param aNumPages	Size of the memory object, in number of pages.
       
   681 							(Must represent an exact 'chunk' size.)
       
   682 		@param aPteType		The #TPteType the page tables will be used for.
       
   683 
       
   684 		@return The newly created DPageTables or the null pointer if there was
       
   685 				insufficient memory.
       
   686 
       
   687 		@pre The #MemoryObjectLock for the memory must be held by the current thread.
       
   688 		*/
       
   689 		static DPageTables* New(DCoarseMemory* aMemory, TUint aNumPages, TUint aPteType);
       
   690 
       
   691 		virtual ~DPageTables();
       
   692 
       
   693 		/**
       
   694 		Update the page tables to add entries for a specified set of memory pages.
       
   695 
       
   696 		This method is called by #DCoarseMemory::MapPages.
       
   697 
       
   698 		@param aPages				An RPageArray::TIter which refers to a range of pages
       
   699 									in the memory object #iMemory.
       
   700 									Only array entries which have state RPageArray::ECommitted
       
   701 									should be mapped into the page tables.
       
   702 
       
   703 		@return KErrNone if successful, otherwise one of the system wide error codes.
       
   704 		*/
       
   705 		virtual TInt MapPages(RPageArray::TIter aPages);
       
   706 
       
   707 		/**
       
   708 		Update the page table entries for a specified memory page.
       
   709 
       
   710 		This method is called by #DCoarseMemory::RemapPage
       
   711 
       
   712 		@param aPageArray			The page array entry of the page in this memory object.
       
   713 									Only array entries which have state RPageArray::ECommitted
       
   714 									should be mapped into a mapping's page tables.
       
   715 
       
   716 		@param aIndex				The index of the page in this memory object.
       
   717 
       
   718 		@param	aInvalidateTLB		Set to ETrue when the TLB entries associated with this page
       
   719 									should be invalidated.  This must be done when there is 
       
   720 									already a valid pte for this page, i.e. if the page is still 
       
   721 									mapped.
       
   722 		*/
       
   723 		virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB);
       
   724 
       
   725 		/**
       
   726 		Update the page table entries to renable access to a specified memory page.
       
   727 
       
   728 		This method is called by #DCoarseMemory::MovingPageIn
       
   729 
       
   730 		@param aPageArrayPtr		The page array entry of the page to map.
       
   731 									Only array entries which have state RPageArray::ECommitted
       
   732 									should be mapped into a mapping's page tables.
       
   733 
       
   734 		@param aIndex				The index of the memory page.
       
   735 		*/
       
   736 		virtual TBool MovingPageIn(TPhysAddr& aPageArrayPtr, TUint aIndex);
       
   737 
       
   738 
       
   739 		/**
       
   740 		Update the page tables to remove entries for a specified set of memory pages.
       
   741 
       
   742 		This method is called by #DCoarseMemory::UnmapPages.
       
   743 
       
   744 		@param aPages				An RPageArray::TIter which refers to a range of pages
       
   745 									in the memory object #iMemory.
       
   746 									Only array entries which return true for
       
   747 									RPageArray::TargetStateIsDecommitted should be unmapped
       
   748 									from the page tables.
       
   749 
       
   750 		@param aDecommitting		True if memory is being permanently decommitted from
       
   751 									the memory object. False if the memory pages are only
       
   752 									temporarily being unmapped due to a demand paging 'page out'
       
   753 									operation.
       
   754 		*/
       
   755 		virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting);
       
   756 
       
   757 		/**
       
   758 		Update the page tables to apply access restrictions to a specified set of memory pages.
       
   759 
       
   760 		This method is called by #DCoarseMemory::RestrictPagesNA.
       
   761 
       
   762 		@param aPages				An RPageArray::TIter which refers to a range of pages
       
   763 									in the memory object #iMemory.
       
   764 									Only array entries which return true for
       
   765 									RPageArray::TargetStateIsDecommitted should be unmapped
       
   766 									from the page tables.
       
   767 		*/
       
   768 		virtual void RestrictPagesNA(RPageArray::TIter aPages);
       
   769 
       
   770 		/**
       
   771 		Update the page tables to add entries for a specified set of demand paged memory
       
   772 		pages following a 'page in' or memory pinning operation.
       
   773 
       
   774 		@param aPages				An RPageArray::TIter which refers to a range of pages
       
   775 									in the memory object #iMemory.
       
   776 									Only array entries which have state RPageArray::ECommitted
       
   777 									should be mapped into the page tables.
       
   778 
       
   779 		@param aPinArgs				The resources required to pin any page tables.
       
   780 									Page table must be pinned if \a aPinArgs.iPinnedPageTables is
       
   781 									not the null pointer, in which case this the virtual address
       
   782 									of the pinned must be stored in the array this points to.
       
   783 									\a aPinArgs.iReadOnly is true if write access permissions
       
   784 									are not needed.
       
   785 
       
   786 		@param aMapping				The mapping that took the page fault or is being pinned.
       
   787 
       
   788 		@param aMapInstanceCount	The instance count of the mapping.
       
   789 
       
   790 		@return KErrNone if successful, otherwise one of the system wide error codes.
       
   791 		*/
       
   792 		virtual TInt PageIn(RPageArray::TIter aPages, TPinArgs& aPinArgs,
       
   793 							DMemoryMappingBase* aMapping, TUint aMapInstanceCount);
       
   794 
       
   795 		/**
       
   796 		Flush the MMUs TLB entries associated with all attached memory mappings
       
   797 		for a specified region of memory pages.
       
   798 
       
   799 		This is used by UnmapPages and RestrictPages.
       
   800 
       
   801 		@param aStartIndex	Page index, within the memory, for start of the region.
       
   802 		@param aEndIndex	Page index, within the memory, for the first page after
       
   803 							the end of the region.
       
   804 		*/
       
   805 		void FlushTLB(TUint aStartIndex, TUint aEndIndex);
       
   806 
       
   807 
       
   808 		/**
       
   809 		Get the page table being used for a specified chunk index if it exists.
       
   810 
       
   811 		@param aChunkIndex	The index into #iTables of the page table.
       
   812 
       
   813 		@return The virtual address of the page table,
       
   814 				or the null pointer if one wasn't found.
       
   815 		*/
       
   816 		inline TPte* GetPageTable(TUint aChunkIndex)
       
   817 			{
       
   818 			__NK_ASSERT_DEBUG(MmuLock::IsHeld());
       
   819 			return iTables[aChunkIndex];
       
   820 			}
       
   821 
       
   822 		/**
       
   823 		Get the page table being used for a specified chunk index; allocating
       
   824 		a new one if it didn't previously exist.
       
   825 
       
   826 		@param aChunkIndex	The index into #iTables of the page table.
       
   827 
       
   828 		@return The virtual address of the page table,
       
   829 				or the null pointer if one wasn't found and couldn't be allocated.
       
   830 		*/
       
   831 		TPte* GetOrAllocatePageTable(TUint aChunkIndex);
       
   832 
       
   833 		/**
       
   834 		Get and pin the page table being for a specified chunk index; allocating
       
   835 		a new one if it didn't previously exist.
       
   836 
       
   837 		@param aChunkIndex	The index into #iTables of the page table.
       
   838 		@param aPinArgs		The resources required to pin the page table.
       
   839 							On success, the page table will have been appended to
       
   840 							\a aPinArgs.iPinnedPageTables.
       
   841 
       
   842 		@return The virtual address of the page table,
       
   843 				or the null pointer if one wasn't found and couldn't be allocated.
       
   844 		*/
       
   845 		TPte* GetOrAllocatePageTable(TUint aChunkIndex, TPinArgs& aPinArgs);
       
   846 
       
   847 		/**
       
   848 		Allocate a single page table.
       
   849 
       
   850 		@param aChunkIndex	The index into #iTables of the page table.
       
   851 		@param aDemandPaged True if the page table is for mapping demand paged memory.  Most of the
       
   852 		                    time this will be determined by the #EDemandPaged bit in #iFlags.
       
   853 		@param aPermanent	True, if the page table's permanence count is to be incremented.
       
   854 
       
   855 		@return The virtual address of the page table,
       
   856 				or the null pointer if one wasn't found and couldn't be allocated.
       
   857 		*/
       
   858 		TPte* AllocatePageTable(TUint aChunkIndex, TBool aDemandPaged, TBool aPermanent=false);
       
   859 
       
   860 		/**
       
   861 		Free a single page table if it is unused.
       
   862 
       
   863 		@param aChunkIndex	The index into #iTables of the page table.
       
   864 		*/
       
   865 		void FreePageTable(TUint aChunkIndex);
       
   866 
       
   867 		/**
       
   868 		Allocate all the mmu page tables for this object (iTables) and ensure that
       
   869 		they are not freed even when they no longer map any pages.
       
   870 
       
   871 		This method increments iPermanenceCount.
       
   872 
       
   873 		This is called by DCoarseMemory::AddMapping when a memory mapping is
       
   874 		added with the #DMemoryMappingBase::EPermanentPageTables attribute is set.
       
   875 		This will also be true if the memory object has the #EReserveResources
       
   876 		attribute.
       
   877 
       
   878 		@pre The #MemoryObjectLock for the memory must be held by the current thread.
       
   879 
       
   880 		@return KErrNone if successful, otherwise one of the system wide error codes.
       
   881 		*/
       
   882 		TInt AllocatePermanentPageTables();
       
   883 
       
   884 		/**
       
   885 		Reverses the action of #AllocatePermanentPageTables.
       
   886 
       
   887 		This method decrements iPermanenceCount and if this reaches zero,
       
   888 		the mmu page tables for this object are freed if the are no longer in use.
       
   889 		*/
       
   890 		void FreePermanentPageTables();
       
   891 
       
   892 		/**
       
   893 		This is called by DCoarseMemory::AddMapping when a coarse memory mapping is
       
   894 		added.
       
   895 
       
   896 		@param aMapping	The coarse memory mapping to add.
       
   897 
       
   898 		@return KErrNone if successful, otherwise one of the system wide error codes.
       
   899 		*/
       
   900 		TInt AddMapping(DCoarseMapping* aMapping);
       
   901 
       
   902 		/**
       
   903 		This is called by DCoarseMemory::RemoveMapping when a coarse memory mapping is
       
   904 		removed.
       
   905 
       
   906 		@param aMapping	The coarse memory mapping to remove.
       
   907 		*/
       
   908 		void RemoveMapping(DCoarseMapping* aMapping);
       
   909 
       
   910 		/**
       
   911 		Overriding DReferenceCountedObject::Close.
       
   912 		This removes the linkage with #iMemory if this object is deleted.
       
   913 		*/
       
   914 		void Close();
       
   915 
       
   916 		/**
       
   917 		Overriding DReferenceCountedObject::AsyncClose.
       
   918 		This removes the linkage with #iMemory if this object is deleted.
       
   919 		*/
       
   920 		void AsyncClose();
       
   921 
       
   922 		/**
       
   923 		Remove an mmu page table from this object's ownership.
       
   924 		This is called from DCoarseMemory::StealPageTable when a RAM page containing
       
   925 		the page table is paged out.
       
   926 
       
   927 		@param aChunkIndex	The index into #iTables of the page table.
       
   928 
       
   929 		@pre #MmuLock is held.
       
   930 		@pre #PageTablesLockIsHeld
       
   931 		*/
       
   932 		void StealPageTable(TUint aChunkIndex);
       
   933 		
       
   934 	protected:
       
   935 		/**
       
   936 		For arguments, see #New.
       
   937 		*/
       
   938 		DPageTables(DCoarseMemory* aMemory, TInt aNumPts, TUint aPteType);
       
   939 
       
   940 		/**
       
   941 		Second phase constructor.
       
   942 
       
   943 		This initialises all of the mmu page tables to map the memory currently owned
       
   944 		by the memory object (#iMemory).
       
   945 
       
   946 		@return KErrNone if successful, otherwise one of the system wide error codes.
       
   947 		*/
       
   948 		TInt Construct();
       
   949 
       
   950 	private:
       
   951 		/**
       
   952 		Reverses the action of #AllocatePermanentPageTables for a range of page tables.
       
   953 
       
   954 		This is an implementation factor for #FreePermanentPageTables().
       
   955 
       
   956 		@param aChunkIndex	The index into #iTables of the first page table.
       
   957 		@param aChunkCount	The number of page tables.
       
   958 		*/
       
   959 		void FreePermanentPageTables(TUint aChunkIndex, TUint aChunkCount);
       
   960 
       
   961 		/**
       
   962 		Assign a newly allocated page table to this object.
       
   963 
       
   964 		This adds the page table to the page directory entries associated with
       
   965 		all mappings attached to this object.
       
   966 
       
   967 		@param aChunkIndex	The index into #iTables of the page table.
       
   968 		@param aPageTable	The page table.
       
   969 
       
   970 		@pre #PageTablesLockIsHeld.
       
   971 		*/
       
   972 		void AssignPageTable(TUint aChunkIndex, TPte* aPageTable);
       
   973 
       
   974 		/**
       
   975 		Unassign a page table to this object.
       
   976 
       
   977 		This removes the page table from the page directory entries associated with
       
   978 		all mappings attached to this object.
       
   979 
       
   980 		This is called by FreePageTable and StealPageTable.
       
   981 
       
   982 		@param aChunkIndex	The index into #iTables of the page table.
       
   983 
       
   984 		@pre #PageTablesLockIsHeld.
       
   985 		*/
       
   986 		void UnassignPageTable(TUint aChunkIndex);
       
   987 
       
   988 	public:
       
   989 		/**
       
   990 		The coarse memory object which owns us.
       
   991 		*/
       
   992 		DCoarseMemory* iMemory;
       
   993 
       
   994 		/**
       
   995 		The #TPteType the page tables are being used for.
       
   996 		(This object's index in #iMemory->iPageTables.)
       
   997 		*/
       
   998 		TUint iPteType;
       
   999 
       
  1000 		/**
       
  1001 		The list of coarse mappings attached to this object.
       
  1002 		These mappings use the mmu page tables owned by us.
       
  1003 		*/
       
  1004 		TMappingList iMappings;
       
  1005 
       
  1006 		/**
       
  1007 		The page table entry (PTE) value for use when mapping pages into the page tables.
       
  1008 		This value has the physical address component being zero, so a page's physical
       
  1009 		address can be simply ORed in.
       
  1010 		*/
       
  1011 		TPte iBlankPte;
       
  1012 
       
  1013 		/**
       
  1014 		Reference count for the number of times #AllocatePermanentPageTables
       
  1015 		has been called without #FreePermanentPageTables.
       
  1016 		*/
       
  1017 		TUint iPermanenceCount;
       
  1018 
       
  1019 		/**
       
  1020 		Number of entries in #iTables.
       
  1021 		*/
       
  1022 		TUint iNumPageTables;
       
  1023 
       
  1024 		/**
       
  1025 		Array of page tables owned by this object. This may extend into memory
       
  1026 		beyond the end of this object and contains #iNumPageTables entries.
       
  1027 
       
  1028 		Each entry in the array corresponds to a #KChunkSize sized region of #iMemory.
       
  1029 		The null pointer indicating that no page table exists for the corresponding
       
  1030 		region.
       
  1031 
       
  1032 		The contents of the array are protected by the PageTableAllocator lock AND #MmuLock
       
  1033 		*/
       
  1034 		TPte* iTables[1];
       
  1035 		};
       
  1036 
       
  1037 private:
       
  1038 	/**
       
  1039 	Get or allocate the page tables container for a given PTE type
       
  1040 
       
  1041 	@pre #MemoryObjectLock for this object must be held.
       
  1042 	*/
       
  1043 	DPageTables* GetOrAllocatePageTables(TUint aPteType);
       
  1044 
       
  1045 protected:
       
  1046 	/**
       
  1047 	Array of #DPageTables objects owned by this memory object.
       
  1048 	Updates to this array require the #MmuLock.
       
  1049 	*/
       
  1050 	DPageTables* iPageTables[ENumPteTypes];
       
  1051 
       
  1052 	friend class DCoarseMemory::DPageTables;  // for DPageTables::Close() / AsyncClose()
       
  1053 	};
       
  1054 
       
  1055 
       
  1056 
       
  1057 /**
       
  1058 A memory object without the special case optimisations of DCoarseMemory.
       
  1059 */
       
  1060 class DFineMemory : public DMemoryObject
       
  1061 	{
       
  1062 public:
       
  1063 	// from DMemoryObject...
       
  1064 	virtual ~DFineMemory();
       
  1065 	virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false);
       
  1066 
       
  1067 public:
       
  1068 	/**
       
  1069 	Create a new DFineMemory object.
       
  1070 
       
  1071 	@param aManager		The manager object for this memory.
       
  1072 	@param aSizeInPages	Size of the memory object, in number of pages.
       
  1073 	@param aAttributes	Bitmask of values from enum #TMemoryAttributes.
       
  1074 	@param aCreateFlags	Bitmask of option flags from enum #TMemoryCreateFlags.
       
  1075 
       
  1076 	@return The newly created DFineMemory or the null pointer if there was
       
  1077 			insufficient memory.
       
  1078 	*/
       
  1079 	static DFineMemory* New(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
       
  1080 
       
  1081 private:
       
  1082 	/**
       
  1083 	For arguments, see #New.
       
  1084 	*/
       
  1085 	DFineMemory(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
       
  1086 	};
       
  1087 
       
  1088 
       
  1089 #endif