1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/epoc/flexible/mmu/mobject.h Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1089 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +/**
1.20 + @file
1.21 + @internalComponent
1.22 +*/
1.23 +
1.24 +#ifndef MOBJECT_H
1.25 +#define MOBJECT_H
1.26 +
1.27 +#include "mrefcntobj.h"
1.28 +#include "mmappinglist.h"
1.29 +#include "mpagearray.h"
1.30 +
1.31 +class DMemoryManager;
1.32 +class DCoarseMapping;
1.33 +
1.34 +
1.35 +/**
1.36 +Base class for memory objects.
1.37 +
1.38 +A memory object is a sparse array of memory pages (#iPages) to which memory
1.39 +mappings may be attached (#iMappings). All pages in the array are managed
1.40 +in the same way (#iManager).
1.41 +*/
1.42 +class DMemoryObject : public DReferenceCountedObject
1.43 + {
1.44 +public:
1.45 + virtual ~DMemoryObject();
1.46 +
1.47 + /**
1.48 + Claim ownership of memory originally allocated by the bootstrap.
1.49 +
1.50 + This is used during system boot to initialise this object's memory to contain
1.51 + the pages which are already mapped at a given region of virtual addresses.
1.52 +
1.53 + For coarse memory objects, this function also takes ownership of the page tables
1.54 + being used to map the memory.
1.55 +
1.56 + @param aBase Starting virtual address of memory to claim.
1.57 +
1.58 + @param aSize Size, in bytes, of memory region to claim.
1.59 +
1.60 + @param aPermissions The access permissions which the memory region
1.61 + is mapped. As well as being required for correct object
1.62 + initialisation this also enables the function to check
1.63 + that the bootstrap code mapped the memory in manner
1.64 + consistent with the flexible memory model implementation.
1.65 +
1.66 + @param aAllowGaps True if the memory region may have gaps (unmapped pages) in it.
1.67 + If false, the function faults if the region is not fully
1.68 + populated with mapped pages.
1.69 +
1.70 + @param aAllowNonRamPages True if the memory region contains memory pages which are
1.71 + not RAM pages known to the kernel. I.e. are not
1.72 + contained in the list of RAM banks supplied by the bootstrap.
1.73 + Any such memory cannot be never be subsequently freed from the
1.74 + memory object because the kernel can't handle this memory.
1.75 +
1.76 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.77 + */
1.78 + virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false) = 0;
1.79 +
1.80 + /**
1.81 + Update the page table entries for all attached mappings to add entries for
1.82 + a specified set of memory pages.
1.83 +
1.84 + This method is called by this object's manager whenever new pages of memory are added.
1.85 +
1.86 + @param aPages An RPageArray::TIter which refers to a range of pages
1.87 + in this memory object.
1.88 + Only array entries which have state RPageArray::ECommitted
1.89 + should be mapped into a mapping's page tables.
1.90 +
1.91 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.92 + */
1.93 + virtual TInt MapPages(RPageArray::TIter aPages);
1.94 +
1.95 + /**
1.96 + Update the page table entries for all attached mappings to add new entry for
1.97 + a specified memory page.
1.98 +
1.99 + This method is called by this object's manager whenever the page is moved.
1.100 +
1.101 + @param aPageArray The page array entry of the page in this memory object.
1.102 + Only array entries which have state RPageArray::ECommitted
1.103 + should be mapped into a mapping's page tables.
1.104 +
1.105 + @param aIndex The index of the page in this memory object.
1.106 +
1.107 + @param aInvalidateTLB Set to ETrue when the TLB entries associated with this page
1.108 + should be invalidated. This must be done when there is
1.109 + already a valid pte for this page, i.e. if the page is still
1.110 + mapped.
1.111 +
1.112 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.113 + */
1.114 + virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB);
1.115 +
1.116 + /**
1.117 + Update the page table entries for all attached mappings to remove entries for
1.118 + a specified set of memory pages.
1.119 +
1.120 + This method is called this object's manager whenever pages of memory are removed.
1.121 +
1.122 + @param aPages An RPageArray::TIter which refers to a range of pages
1.123 + in this memory object.
1.124 + Only array entries which return true for
1.125 + RPageArray::TargetStateIsDecommitted should be unmapped
1.126 + from a mapping's page tables.
1.127 +
1.128 + @param aDecommitting True if memory is being permanently decommitted from
1.129 + the memory object. False if the memory pages are only
1.130 + temporarily being unmapped due to a demand paging 'page out'
1.131 + operation.
1.132 + */
1.133 + virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting);
1.134 +
1.135 + /**
1.136 + Update the page table entries for all attached mappings to apply access restrictions
1.137 + to a specified set of memory pages.
1.138 +
1.139 + This method is called by this object's manager whenever pages of memory are restricted.
1.140 +
1.141 + @param aPages An RPageArray::TIter which refers to a range of pages
1.142 + in this memory object.
1.143 + Only array entries which return true for
1.144 + RPageArray::TargetStateIsDecommitted should be unmapped
1.145 + from a mapping's page tables.
1.146 +
1.147 + @param aRestriction A value from enum #TRestrictPagesType indicating the
1.148 + kind of restriction to apply.
1.149 + */
1.150 + virtual void RestrictPages(RPageArray::TIter aPages, TRestrictPagesType aRestriction);
1.151 +
1.152 + /**
1.153 + Add a memory mapping to this memory object.
1.154 +
1.155 + This is only intended for use by #DMemoryMappingBase::Attach.
1.156 +
1.157 + After verifying that the mapping is permitted (using #CheckNewMapping)
1.158 + the mapping is linked into this objects list of mappings #iMappings.
1.159 +
1.160 + @param aMapping The mapping to add.
1.161 +
1.162 + @return KErrNone if successful,
1.163 + otherwise KErrAccessDenied to indicate that the mapping is not allowed.
1.164 + */
1.165 + virtual TInt AddMapping(DMemoryMappingBase* aMapping);
1.166 +
1.167 + /**
1.168 + Remove a memory mapping from this memory object.
1.169 +
1.170 + This is only intended for use by #DMemoryMappingBase::Detach.
1.171 +
1.172 + This unlinks the mapping from the list of mappings #iMappings.
1.173 +
1.174 + @param aMapping The mapping to remove.
1.175 + */
1.176 + virtual void RemoveMapping(DMemoryMappingBase* aMapping);
1.177 +
1.178 + /**
1.179 + Attempt to set the memory object read only. This will only succeed if
1.180 + there are no writable mappings to the memory object.
1.181 +
1.182 + NOTE - This can't be undone, page moving will break if a memory object
1.183 + is made writable again.
1.184 +
1.185 + @return KErrNone on success, KErrInUse if writable mappings are found.
1.186 + */
1.187 + virtual TInt SetReadOnly();
1.188 +
1.189 + /**
1.190 + Create a mapping object to map this memory.
1.191 +
1.192 + This is only intended for use by #MM::MappingNew.
1.193 +
1.194 + The base class creates a #DFineMapping object. It is overridden by #DCoarseMemory to create a
1.195 + #DCoarseMapping in appropriate circumstances.
1.196 +
1.197 + @param aIndex The index of the start of the mapping into this memory object.
1.198 + @oaram aCount The size in pages of the mapping.
1.199 + */
1.200 + virtual DMemoryMapping* CreateMapping(TUint aIndex, TUint aCount);
1.201 +
1.202 + /**
1.203 + Get the physical address(es) for a region of pages in this memory object.
1.204 +
1.205 + Depending on how the memory is being managed the physical addresses returned
1.206 + may become invalid due to various reasons, e.g.
1.207 +
1.208 + - memory being decommitted from the memory object
1.209 + - ram defragmentation moving the memory contents to a different physical page
1.210 + - paging out of demand paged memory
1.211 +
1.212 + This function should therefore only be used where it is know that these
1.213 + possibilities can't occur, e.g. this is used safely by DPhysicalPinMapping::PhysAddr.
1.214 +
1.215 + @param aIndex Page index, within the memory, for the start of the region.
1.216 + @param aCount Number of pages in the region.
1.217 + @param aPhysicalAddress On success, this value is set to one of two values.
1.218 + If the specified region is physically contiguous,
1.219 + the value is the physical address of the first page
1.220 + in the region. If the region is discontiguous, the
1.221 + value is set to KPhysAddrInvalid.
1.222 + @param aPhysicalPageList If not zero, this points to an array of TPhysAddr
1.223 + objects. On success, this array will be filled
1.224 + with the addresses of the physical pages which
1.225 + contain the specified region. If aPageList is
1.226 + zero, then the function will fail with
1.227 + KErrNotFound if the specified region is not
1.228 + physically contiguous.
1.229 +
1.230 + @return 0 if successful and the whole region is physically contiguous.
1.231 + 1 if successful but the region isn't physically contiguous.
1.232 + KErrNotFound, if any page in the region is not present,
1.233 + otherwise one of the system wide error codes.
1.234 + */
1.235 + TInt PhysAddr(TUint aIndex, TUint aCount, TPhysAddr& aPhysicalAddress, TPhysAddr* aPhysicalPageList);
1.236 +
1.237 + /**
1.238 + Check specified region lies entirely within this memory object, and that it
1.239 + is page aligned.
1.240 + */
1.241 + TBool CheckRegion(TUint aIndex, TUint aCount);
1.242 +
1.243 + /**
1.244 + Clip the specified region to lie within the memory object,
1.245 + */
1.246 + void ClipRegion(TUint& aIndex, TUint& aCount);
1.247 +
1.248 + /**
1.249 + Set the mutex used to lock operations on this memory object
1.250 + */
1.251 + void SetLock(DMutex* aLock);
1.252 +
1.253 + /**
1.254 + Prevents any further mappings being added to this memory object.
1.255 + */
1.256 + void DenyMappings();
1.257 +
1.258 + /**
1.259 + Return the memory attributes for this object's memory.
1.260 + */
1.261 + FORCE_INLINE TMemoryAttributes Attributes()
1.262 + {
1.263 + return (TMemoryAttributes)iAttributes;
1.264 + }
1.265 +
1.266 + /**
1.267 + Value for initialising SPageInfo::iFlags when allocating pages.
1.268 + */
1.269 + FORCE_INLINE TUint8 PageInfoFlags()
1.270 + {
1.271 + return iAttributes;
1.272 + }
1.273 +
1.274 + /**
1.275 + Value for #Mmu::TRamAllocFlags to use when allocating pages.
1.276 + */
1.277 + FORCE_INLINE Mmu::TRamAllocFlags RamAllocFlags()
1.278 + {
1.279 + return (Mmu::TRamAllocFlags)iRamAllocFlags;
1.280 + }
1.281 +
1.282 + /**
1.283 + Return true if this object is an instance of #DCoarseMemory.
1.284 + */
1.285 + FORCE_INLINE TBool IsCoarse()
1.286 + {
1.287 + return iFlags&ECoarseObject;
1.288 + }
1.289 +
1.290 + /**
1.291 + Return true if this object contains memory which is being demand paged.
1.292 + */
1.293 + FORCE_INLINE TBool IsDemandPaged()
1.294 + {
1.295 + return iFlags&EDemandPaged;
1.296 + }
1.297 +
1.298 + /**
1.299 + Return true if writeable mappings of the memory are not allowed.
1.300 + */
1.301 + FORCE_INLINE TBool IsReadOnly()
1.302 + {
1.303 + return iFlags&EDenyWriteMappings;
1.304 + }
1.305 +
1.306 + /**
1.307 + Return true if executable mappings allowed on this memory object.
1.308 + */
1.309 + FORCE_INLINE TBool IsExecutable()
1.310 + {
1.311 + return !(iFlags&EDenyExecuteMappings);
1.312 + }
1.313 +
1.314 + /**
1.315 + Clear the flag that indicates that a mapping has been added.
1.316 + */
1.317 + FORCE_INLINE void ClearMappingAddedFlag()
1.318 + {
1.319 + __NK_ASSERT_DEBUG(iMappings.LockIsHeld());
1.320 + __e32_atomic_and_ord8(&iFlags, (TUint8)~EMappingAdded);
1.321 + }
1.322 +
1.323 + /**
1.324 + Set the flag to indicate that a mapping has been added.
1.325 + */
1.326 + FORCE_INLINE void SetMappingAddedFlag()
1.327 + {
1.328 + __NK_ASSERT_DEBUG(iMappings.LockIsHeld());
1.329 + __NK_ASSERT_DEBUG(MmuLock::IsHeld());
1.330 + __e32_atomic_ior_ord8(&iFlags, (TUint8)EMappingAdded);
1.331 + }
1.332 +
1.333 + /**
1.334 + Get the value of the mappings added flags
1.335 +
1.336 + @return ETrue if a mapping has been added, EFalse otherwise.
1.337 + */
1.338 + FORCE_INLINE TBool MappingAddedFlag()
1.339 + {
1.340 + __NK_ASSERT_DEBUG(MmuLock::IsHeld());
1.341 + return iFlags & (TUint8)EMappingAdded;
1.342 + }
1.343 +
1.344 + enum
1.345 + {
1.346 + /**
1.347 + Maximum number of bits which can be stored in an array entry by SetPagingManagerData.
1.348 + */
1.349 + KPagingManagerDataBits = RPageArray::KPagingManagerDataBits
1.350 + };
1.351 +
1.352 + enum
1.353 + {
1.354 + /**
1.355 + Maximum value which can be stored in an array entry by SetPagingManagerData.
1.356 + */
1.357 + KMaxPagingManagerData = RPageArray::KMaxPagingManagerData
1.358 + };
1.359 +
1.360 + /**
1.361 + Write \a aValue to the paging manager data for page index \a aIndex.
1.362 + The value must not exceed KMaxPagingManagerData.
1.363 + This must only be used for demand paged memory objects.
1.364 + */
1.365 + void SetPagingManagerData(TUint aIndex, TUint aValue);
1.366 +
1.367 + /**
1.368 + Return the paging manager data for page index \a aIndex.
1.369 + This must only be used for demand paged memory objects.
1.370 + @see SetPagingManagerData
1.371 + */
1.372 + TUint PagingManagerData(TUint aIndex);
1.373 +
1.374 + /**
1.375 + Check that a given memory mapping is allowed to be attached to this memory object.
1.376 +
1.377 + @param aMapping The mapping to check.
1.378 +
1.379 + @return KErrNone if successful,
1.380 + otherwise KErrAccessDenied to indicate that the mapping is not allowed.
1.381 + */
1.382 + TInt CheckNewMapping(DMemoryMappingBase* aMapping);
1.383 +
1.384 + /**
1.385 + Emit BTrace traces identifying the initial attributes of this object.
1.386 + */
1.387 + void BTraceCreate();
1.388 +
1.389 +protected:
1.390 + /**
1.391 + @param aManager The manager object for this memory.
1.392 + @param aFlags Initial value for #iFlags.
1.393 + @param aSizeInPages Size of the memory object, in number of pages.
1.394 + @param aAttributes Bitmask of values from enum #TMemoryAttributes.
1.395 + @param aCreateFlags Bitmask of option flags from enum #TMemoryCreateFlags.
1.396 + */
1.397 + DMemoryObject(DMemoryManager* aManager, TUint aFlags, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
1.398 +
1.399 + /**
1.400 + Second phase constructor.
1.401 +
1.402 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.403 + */
1.404 + TInt Construct();
1.405 +
1.406 +public:
1.407 + /**
1.408 + The manager of this memory object.
1.409 + */
1.410 + DMemoryManager* iManager;
1.411 +
1.412 + /**
1.413 + For use by this object's manager (iManager) to store any memory objects specific state
1.414 + it requires to keep track of.
1.415 + */
1.416 + TAny* iManagerData;
1.417 +
1.418 + /**
1.419 + For use by DMemoryManager::QueueCleanup to link objects which require a cleanup operation.
1.420 + Access to this is protected by #DMemoryManager::iCleanupLock.
1.421 + */
1.422 + DMemoryObject* iCleanupNext;
1.423 +
1.424 + /**
1.425 + For use by DMemoryManager::QueueCleanup to store flags representing each pending cleanup operation.
1.426 + Access to this is protected by #DMemoryManager::iCleanupLock.
1.427 + */
1.428 + TUint32 iCleanupFlags;
1.429 +
1.430 + /**
1.431 + Bit flags stored in #iFlags giving various state and attributes of the object.
1.432 + */
1.433 + enum TFlags
1.434 + {
1.435 + /**
1.436 + Flag set during object construction to indicate that this mapping is of
1.437 + class #DCoarseMemory.
1.438 + */
1.439 + ECoarseObject = 1<<0,
1.440 +
1.441 + /**
1.442 + Flag set during object construction to indicate that the memory for this object
1.443 + is being demand paged in some manner.
1.444 + */
1.445 + EDemandPaged = 1<<1,
1.446 +
1.447 + /**
1.448 + Flag set during object construction to indicate that all resources for this
1.449 + object are to be reserved during construction; excluding memory pages owned by
1.450 + object. Objects constructed in this way will not require additional memory
1.451 + allocation when committing memory to them (other than allocating the memory
1.452 + pages being committed.)
1.453 + */
1.454 + EReserveResources = 1<<2,
1.455 +
1.456 + /**
1.457 + Flag set during object construction to indicate that pinned memory mappings
1.458 + are not allowed to be attached to this object.
1.459 + */
1.460 + EDenyPinning = 1<<3,
1.461 +
1.462 + /**
1.463 + Flag set by DenyMappings to indicate that no additional memory mappings
1.464 + are allowed to be attached to this object.
1.465 + */
1.466 + EDenyMappings = 1<<4,
1.467 +
1.468 + /**
1.469 + Flag set during object construction, or by SetReadOnly, to indicate that
1.470 + the memory object is read-only and no writable mappings are allowed
1.471 + to be attached to this object.
1.472 + */
1.473 + EDenyWriteMappings = 1<<5,
1.474 +
1.475 + /**
1.476 + Flag set during object construction to indicate that executable memory mappings
1.477 + are not allowed to be attached to this object.
1.478 + This is mainly an optimisation to allow demand paging to avoid instruction cache
1.479 + maintenance operations during page fault handling.
1.480 + */
1.481 + EDenyExecuteMappings = 1<<6,
1.482 +
1.483 + /**
1.484 + Flag set whenever a new mapping is added to a memory object.
1.485 + The object's mappings lock and MmuLock protects this flag when it is set
1.486 + and the mappings lock protects when it is cleared.
1.487 + */
1.488 + EMappingAdded = 1<<7,
1.489 + };
1.490 +
1.491 + /**
1.492 + Bitmask of TFlags
1.493 + */
1.494 + TUint8 iFlags;
1.495 +
1.496 + /**
1.497 + Value from TMemoryAttributes indicating type of memory in object.
1.498 + */
1.499 + TUint8 iAttributes;
1.500 +
1.501 + /**
1.502 + #Mmu::TRamAllocFlags value to use when allocating RAM for this memory object.
1.503 + */
1.504 + TUint16 iRamAllocFlags;
1.505 +
1.506 + /**
1.507 + List of mappings currently attached to this object.
1.508 + */
1.509 + TMappingList iMappings;
1.510 +
1.511 + /**
1.512 + Size, in page units, of this memory object.
1.513 + */
1.514 + TUint iSizeInPages;
1.515 +
1.516 + /**
1.517 + Lock currently being used to serialise explicit memory operations.
1.518 + This is assigned using #MemoryObjectLock.
1.519 + */
1.520 + DMutex* iLock;
1.521 +
1.522 + /**
1.523 + The array of memory pages assigned to this memory object.
1.524 + */
1.525 + RPageArray iPages;
1.526 + };
1.527 +
1.528 +
1.529 +
1.530 +/**
1.531 +A memory object which has a size that is an exact multiple
1.532 +multiple of the region covered by a whole MMU page table;
1.533 +that is a 'chunk' size (#KChunkSize) bytes.
1.534 +
1.535 +When used in conjunction with DCoarseMapping this object
1.536 +allows RAM to be saved by sharing MMU page tables between multiple
1.537 +different mappings of the memory.
1.538 +
1.539 +Fine memory mappings (DFineMapping) may also be attached
1.540 +to this memory object but these won't benefit from page table
1.541 +sharing.
1.542 +*/
1.543 +class DCoarseMemory : public DMemoryObject
1.544 + {
1.545 +public:
1.546 + // from DMemoryObject...
1.547 + virtual ~DCoarseMemory();
1.548 + virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false);
1.549 + virtual TInt MapPages(RPageArray::TIter aPages);
1.550 + virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB);
1.551 + virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting);
1.552 + virtual void RestrictPages(RPageArray::TIter aPages, TRestrictPagesType aRestriction);
1.553 + virtual TInt AddMapping(DMemoryMappingBase* aMapping);
1.554 + virtual void RemoveMapping(DMemoryMappingBase* aMapping);
1.555 + virtual TInt SetReadOnly();
1.556 + virtual DMemoryMapping* CreateMapping(TUint aIndex, TUint aCount);
1.557 +public:
1.558 + /**
1.559 + Create a new DCoarseMemory object.
1.560 +
1.561 + @param aManager The manager object for this memory.
1.562 + @param aSizeInPages Size of the memory object, in number of pages.
1.563 + (Must represent an exact 'chunk' size.)
1.564 + @param aAttributes Bitmask of values from enum #TMemoryAttributes.
1.565 + @param aCreateFlags Bitmask of option flags from enum #TMemoryCreateFlags.
1.566 +
1.567 + @return The newly created DCoarseMemory or the null pointer if there was
1.568 + insufficient memory.
1.569 + */
1.570 + static DCoarseMemory* New(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
1.571 +
1.572 + /**
1.573 + Remove an mmu page table from this memory object's ownership.
1.574 + This is called when a RAM page containing the page table is paged out.
1.575 + This function delegates its action to DPageTables::StealPageTable.
1.576 +
1.577 + @param aChunkIndex The index of the page table, i.e. the offset, in 'chunks',
1.578 + into the object's memory that the page table is being used to map.
1.579 + (The index into DPageTables::iTables.)
1.580 + @param aPteType The #TPteType the page table is being used for.
1.581 + (The index into #iPageTables.)
1.582 +
1.583 + @pre #MmuLock is held.
1.584 + @pre #PageTablesLockIsHeld
1.585 + */
1.586 + void StealPageTable(TUint aChunkIndex, TUint aPteType);
1.587 +
1.588 +public:
1.589 + // Interface for DCoarseMapping
1.590 +
1.591 + /**
1.592 + Get the page table to use for mapping a specified chunk if it exists.
1.593 +
1.594 + @param aPteType The #TPteType the page tables will be used for.
1.595 + @param aChunkIndex The index of the chunk.
1.596 +
1.597 + @return The virtual address of the page table, or NULL.
1.598 +
1.599 + @pre #MmuLock is held.
1.600 + */
1.601 + TPte* GetPageTable(TUint aPteType , TUint aChunkIndex);
1.602 +
1.603 + /**
1.604 + Update the page tables to add entries for a specified set of demand paged memory
1.605 + pages following a 'page in' or memory pinning operation.
1.606 +
1.607 + @param aMapping The mapping the pages are being paged into.
1.608 +
1.609 + @param aPages An RPageArray::TIter which refers to a range of pages
1.610 + in the memory object #iMemory.
1.611 + Only array entries which have state RPageArray::ECommitted
1.612 + should be mapped into the page tables.
1.613 +
1.614 + @param aPinArgs The resources required to pin any page tables.
1.615 + Page table must be pinned if \a aPinArgs.iPinnedPageTables is
1.616 + not the null pointer, in which case this the virtual address
1.617 + of the pinned must be stored in the array this points to.
1.618 + \a aPinArgs.iReadOnly is true if write access permissions
1.619 + are not needed.
1.620 +
1.621 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.622 +
1.623 + @pre #MmuLock is held.
1.624 + @post #MmuLock has been released.
1.625 + */
1.626 + TInt PageIn(DCoarseMapping* aMapping, RPageArray::TIter aPages, TPinArgs& aPinArgs, TUint aMapInstanceCount);
1.627 +
1.628 + /**
1.629 + Update the page table entries to renable access to a specified memory page.
1.630 +
1.631 + This method is called by #DCoarseMapping::MovingPageIn
1.632 +
1.633 + @param aMapping The mapping which maps the page.
1.634 + @param aPageArrayPtr The page array entry of the page to map.
1.635 + Only array entries which have state RPageArray::ECommitted
1.636 + should be mapped into a mapping's page tables.
1.637 +
1.638 + @param aIndex The index of the memory page.
1.639 + */
1.640 + TBool MovingPageIn(DCoarseMapping* aMapping, TPhysAddr& aPageArrayPtr, TUint aIndex);
1.641 +
1.642 + /**
1.643 + Function to return a page table pointer for the specified linear address and
1.644 + index to this mapping.
1.645 +
1.646 + This method is called by #DCoarseMapping::FindPageTable.
1.647 +
1.648 + @param aLinAddr The linear address to find the page table entry for.
1.649 + @param aMemoryIndex The memory object index of the page to find the page
1.650 + table entry for.
1.651 +
1.652 + @return A pointer to the page table entry, if the page table entry couldn't
1.653 + be found this will be NULL
1.654 + */
1.655 + TPte* FindPageTable(DCoarseMapping* aMapping, TLinAddr aLinAddr, TUint aMemoryIndex);
1.656 +
1.657 +protected:
1.658 + /**
1.659 + For arguments, see #New.
1.660 + */
1.661 + DCoarseMemory(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
1.662 +
1.663 +public:
1.664 + /**
1.665 + The object which manages the page tables owned by a #DCoarseMemory object
1.666 + and used by #DCoarseMapping objects. Each DPageTables is used for mappings
1.667 + with a specific #TPteType e.g. set of memory access permissions, and all these
1.668 + #DCoarseMapping objects are linked into this object whenever they are
1.669 + attached to a DCoarseMemory.
1.670 + */
1.671 + class DPageTables : public DReferenceCountedObject
1.672 + {
1.673 + public:
1.674 + /**
1.675 + Create a new DPageTables.
1.676 +
1.677 + This object is added to DCoarseMemory::iPageTables and all of
1.678 + the mmu page tables will be initialised to map the memory currently
1.679 + owned by the memory object (unless memory is demand paged).
1.680 +
1.681 +
1.682 + @param aMemory The DCoarseMemory the new object is associated with.
1.683 + @param aNumPages Size of the memory object, in number of pages.
1.684 + (Must represent an exact 'chunk' size.)
1.685 + @param aPteType The #TPteType the page tables will be used for.
1.686 +
1.687 + @return The newly created DPageTables or the null pointer if there was
1.688 + insufficient memory.
1.689 +
1.690 + @pre The #MemoryObjectLock for the memory must be held by the current thread.
1.691 + */
1.692 + static DPageTables* New(DCoarseMemory* aMemory, TUint aNumPages, TUint aPteType);
1.693 +
1.694 + virtual ~DPageTables();
1.695 +
1.696 + /**
1.697 + Update the page tables to add entries for a specified set of memory pages.
1.698 +
1.699 + This method is called by #DCoarseMemory::MapPages.
1.700 +
1.701 + @param aPages An RPageArray::TIter which refers to a range of pages
1.702 + in the memory object #iMemory.
1.703 + Only array entries which have state RPageArray::ECommitted
1.704 + should be mapped into the page tables.
1.705 +
1.706 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.707 + */
1.708 + virtual TInt MapPages(RPageArray::TIter aPages);
1.709 +
1.710 + /**
1.711 + Update the page table entries for a specified memory page.
1.712 +
1.713 + This method is called by #DCoarseMemory::RemapPage
1.714 +
1.715 + @param aPageArray The page array entry of the page in this memory object.
1.716 + Only array entries which have state RPageArray::ECommitted
1.717 + should be mapped into a mapping's page tables.
1.718 +
1.719 + @param aIndex The index of the page in this memory object.
1.720 +
1.721 + @param aInvalidateTLB Set to ETrue when the TLB entries associated with this page
1.722 + should be invalidated. This must be done when there is
1.723 + already a valid pte for this page, i.e. if the page is still
1.724 + mapped.
1.725 + */
1.726 + virtual void RemapPage(TPhysAddr& aPageArray, TUint aIndex, TBool aInvalidateTLB);
1.727 +
1.728 + /**
1.729 + Update the page table entries to renable access to a specified memory page.
1.730 +
1.731 + This method is called by #DCoarseMemory::MovingPageIn
1.732 +
1.733 + @param aPageArrayPtr The page array entry of the page to map.
1.734 + Only array entries which have state RPageArray::ECommitted
1.735 + should be mapped into a mapping's page tables.
1.736 +
1.737 + @param aIndex The index of the memory page.
1.738 + */
1.739 + virtual TBool MovingPageIn(TPhysAddr& aPageArrayPtr, TUint aIndex);
1.740 +
1.741 +
1.742 + /**
1.743 + Update the page tables to remove entries for a specified set of memory pages.
1.744 +
1.745 + This method is called by #DCoarseMemory::UnmapPages.
1.746 +
1.747 + @param aPages An RPageArray::TIter which refers to a range of pages
1.748 + in the memory object #iMemory.
1.749 + Only array entries which return true for
1.750 + RPageArray::TargetStateIsDecommitted should be unmapped
1.751 + from the page tables.
1.752 +
1.753 + @param aDecommitting True if memory is being permanently decommitted from
1.754 + the memory object. False if the memory pages are only
1.755 + temporarily being unmapped due to a demand paging 'page out'
1.756 + operation.
1.757 + */
1.758 + virtual void UnmapPages(RPageArray::TIter aPages, TBool aDecommitting);
1.759 +
1.760 + /**
1.761 + Update the page tables to apply access restrictions to a specified set of memory pages.
1.762 +
1.763 + This method is called by #DCoarseMemory::RestrictPagesNA.
1.764 +
1.765 + @param aPages An RPageArray::TIter which refers to a range of pages
1.766 + in the memory object #iMemory.
1.767 + Only array entries which return true for
1.768 + RPageArray::TargetStateIsDecommitted should be unmapped
1.769 + from the page tables.
1.770 + */
1.771 + virtual void RestrictPagesNA(RPageArray::TIter aPages);
1.772 +
1.773 + /**
1.774 + Update the page tables to add entries for a specified set of demand paged memory
1.775 + pages following a 'page in' or memory pinning operation.
1.776 +
1.777 + @param aPages An RPageArray::TIter which refers to a range of pages
1.778 + in the memory object #iMemory.
1.779 + Only array entries which have state RPageArray::ECommitted
1.780 + should be mapped into the page tables.
1.781 +
1.782 + @param aPinArgs The resources required to pin any page tables.
1.783 + Page table must be pinned if \a aPinArgs.iPinnedPageTables is
1.784 + not the null pointer, in which case this the virtual address
1.785 + of the pinned must be stored in the array this points to.
1.786 + \a aPinArgs.iReadOnly is true if write access permissions
1.787 + are not needed.
1.788 +
1.789 + @param aMapping The mapping that took the page fault or is being pinned.
1.790 +
1.791 + @param aMapInstanceCount The instance count of the mapping.
1.792 +
1.793 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.794 + */
1.795 + virtual TInt PageIn(RPageArray::TIter aPages, TPinArgs& aPinArgs,
1.796 + DMemoryMappingBase* aMapping, TUint aMapInstanceCount);
1.797 +
1.798 + /**
1.799 + Flush the MMUs TLB entries associated with all attached memory mappings
1.800 + for a specified region of memory pages.
1.801 +
1.802 + This is used by UnmapPages and RestrictPages.
1.803 +
1.804 + @param aStartIndex Page index, within the memory, for start of the region.
1.805 + @param aEndIndex Page index, within the memory, for the first page after
1.806 + the end of the region.
1.807 + */
1.808 + void FlushTLB(TUint aStartIndex, TUint aEndIndex);
1.809 +
1.810 +
1.811 + /**
1.812 + Get the page table being used for a specified chunk index if it exists.
1.813 +
1.814 + @param aChunkIndex The index into #iTables of the page table.
1.815 +
1.816 + @return The virtual address of the page table,
1.817 + or the null pointer if one wasn't found.
1.818 + */
1.819 + inline TPte* GetPageTable(TUint aChunkIndex)
1.820 + {
1.821 + __NK_ASSERT_DEBUG(MmuLock::IsHeld());
1.822 + return iTables[aChunkIndex];
1.823 + }
1.824 +
1.825 + /**
1.826 + Get the page table being used for a specified chunk index; allocating
1.827 + a new one if it didn't previously exist.
1.828 +
1.829 + @param aChunkIndex The index into #iTables of the page table.
1.830 +
1.831 + @return The virtual address of the page table,
1.832 + or the null pointer if one wasn't found and couldn't be allocated.
1.833 + */
1.834 + TPte* GetOrAllocatePageTable(TUint aChunkIndex);
1.835 +
1.836 + /**
1.837 + Get and pin the page table being for a specified chunk index; allocating
1.838 + a new one if it didn't previously exist.
1.839 +
1.840 + @param aChunkIndex The index into #iTables of the page table.
1.841 + @param aPinArgs The resources required to pin the page table.
1.842 + On success, the page table will have been appended to
1.843 + \a aPinArgs.iPinnedPageTables.
1.844 +
1.845 + @return The virtual address of the page table,
1.846 + or the null pointer if one wasn't found and couldn't be allocated.
1.847 + */
1.848 + TPte* GetOrAllocatePageTable(TUint aChunkIndex, TPinArgs& aPinArgs);
1.849 +
1.850 + /**
1.851 + Allocate a single page table.
1.852 +
1.853 + @param aChunkIndex The index into #iTables of the page table.
1.854 + @param aDemandPaged True if the page table is for mapping demand paged memory. Most of the
1.855 + time this will be determined by the #EDemandPaged bit in #iFlags.
1.856 + @param aPermanent True, if the page table's permanence count is to be incremented.
1.857 +
1.858 + @return The virtual address of the page table,
1.859 + or the null pointer if one wasn't found and couldn't be allocated.
1.860 + */
1.861 + TPte* AllocatePageTable(TUint aChunkIndex, TBool aDemandPaged, TBool aPermanent=false);
1.862 +
1.863 + /**
1.864 + Free a single page table if it is unused.
1.865 +
1.866 + @param aChunkIndex The index into #iTables of the page table.
1.867 + */
1.868 + void FreePageTable(TUint aChunkIndex);
1.869 +
1.870 + /**
1.871 + Allocate all the mmu page tables for this object (iTables) and ensure that
1.872 + they are not freed even when they no longer map any pages.
1.873 +
1.874 + This method increments iPermanenceCount.
1.875 +
1.876 + This is called by DCoarseMemory::AddMapping when a memory mapping is
1.877 + added with the #DMemoryMappingBase::EPermanentPageTables attribute is set.
1.878 + This will also be true if the memory object has the #EReserveResources
1.879 + attribute.
1.880 +
1.881 + @pre The #MemoryObjectLock for the memory must be held by the current thread.
1.882 +
1.883 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.884 + */
1.885 + TInt AllocatePermanentPageTables();
1.886 +
1.887 + /**
1.888 + Reverses the action of #AllocatePermanentPageTables.
1.889 +
1.890 + This method decrements iPermanenceCount and if this reaches zero,
1.891 + the mmu page tables for this object are freed if the are no longer in use.
1.892 + */
1.893 + void FreePermanentPageTables();
1.894 +
1.895 + /**
1.896 + This is called by DCoarseMemory::AddMapping when a coarse memory mapping is
1.897 + added.
1.898 +
1.899 + @param aMapping The coarse memory mapping to add.
1.900 +
1.901 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.902 + */
1.903 + TInt AddMapping(DCoarseMapping* aMapping);
1.904 +
1.905 + /**
1.906 + This is called by DCoarseMemory::RemoveMapping when a coarse memory mapping is
1.907 + removed.
1.908 +
1.909 + @param aMapping The coarse memory mapping to remove.
1.910 + */
1.911 + void RemoveMapping(DCoarseMapping* aMapping);
1.912 +
1.913 + /**
1.914 + Overriding DReferenceCountedObject::Close.
1.915 + This removes the linkage with #iMemory if this object is deleted.
1.916 + */
1.917 + void Close();
1.918 +
1.919 + /**
1.920 + Overriding DReferenceCountedObject::AsyncClose.
1.921 + This removes the linkage with #iMemory if this object is deleted.
1.922 + */
1.923 + void AsyncClose();
1.924 +
1.925 + /**
1.926 + Remove an mmu page table from this object's ownership.
1.927 + This is called from DCoarseMemory::StealPageTable when a RAM page containing
1.928 + the page table is paged out.
1.929 +
1.930 + @param aChunkIndex The index into #iTables of the page table.
1.931 +
1.932 + @pre #MmuLock is held.
1.933 + @pre #PageTablesLockIsHeld
1.934 + */
1.935 + void StealPageTable(TUint aChunkIndex);
1.936 +
1.937 + protected:
1.938 + /**
1.939 + For arguments, see #New.
1.940 + */
1.941 + DPageTables(DCoarseMemory* aMemory, TInt aNumPts, TUint aPteType);
1.942 +
1.943 + /**
1.944 + Second phase constructor.
1.945 +
1.946 + This initialises all of the mmu page tables to map the memory currently owned
1.947 + by the memory object (#iMemory).
1.948 +
1.949 + @return KErrNone if successful, otherwise one of the system wide error codes.
1.950 + */
1.951 + TInt Construct();
1.952 +
1.953 + private:
1.954 + /**
1.955 + Reverses the action of #AllocatePermanentPageTables for a range of page tables.
1.956 +
1.957 + This is an implementation factor for #FreePermanentPageTables().
1.958 +
1.959 + @param aChunkIndex The index into #iTables of the first page table.
1.960 + @param aChunkCount The number of page tables.
1.961 + */
1.962 + void FreePermanentPageTables(TUint aChunkIndex, TUint aChunkCount);
1.963 +
1.964 + /**
1.965 + Assign a newly allocated page table to this object.
1.966 +
1.967 + This adds the page table to the page directory entries associated with
1.968 + all mappings attached to this object.
1.969 +
1.970 + @param aChunkIndex The index into #iTables of the page table.
1.971 + @param aPageTable The page table.
1.972 +
1.973 + @pre #PageTablesLockIsHeld.
1.974 + */
1.975 + void AssignPageTable(TUint aChunkIndex, TPte* aPageTable);
1.976 +
1.977 + /**
1.978 + Unassign a page table to this object.
1.979 +
1.980 + This removes the page table from the page directory entries associated with
1.981 + all mappings attached to this object.
1.982 +
1.983 + This is called by FreePageTable and StealPageTable.
1.984 +
1.985 + @param aChunkIndex The index into #iTables of the page table.
1.986 +
1.987 + @pre #PageTablesLockIsHeld.
1.988 + */
1.989 + void UnassignPageTable(TUint aChunkIndex);
1.990 +
1.991 + public:
1.992 + /**
1.993 + The coarse memory object which owns us.
1.994 + */
1.995 + DCoarseMemory* iMemory;
1.996 +
1.997 + /**
1.998 + The #TPteType the page tables are being used for.
1.999 + (This object's index in #iMemory->iPageTables.)
1.1000 + */
1.1001 + TUint iPteType;
1.1002 +
1.1003 + /**
1.1004 + The list of coarse mappings attached to this object.
1.1005 + These mappings use the mmu page tables owned by us.
1.1006 + */
1.1007 + TMappingList iMappings;
1.1008 +
1.1009 + /**
1.1010 + The page table entry (PTE) value for use when mapping pages into the page tables.
1.1011 + This value has the physical address component being zero, so a page's physical
1.1012 + address can be simply ORed in.
1.1013 + */
1.1014 + TPte iBlankPte;
1.1015 +
1.1016 + /**
1.1017 + Reference count for the number of times #AllocatePermanentPageTables
1.1018 + has been called without #FreePermanentPageTables.
1.1019 + */
1.1020 + TUint iPermanenceCount;
1.1021 +
1.1022 + /**
1.1023 + Number of entries in #iTables.
1.1024 + */
1.1025 + TUint iNumPageTables;
1.1026 +
1.1027 + /**
1.1028 + Array of page tables owned by this object. This may extend into memory
1.1029 + beyond the end of this object and contains #iNumPageTables entries.
1.1030 +
1.1031 + Each entry in the array corresponds to a #KChunkSize sized region of #iMemory.
1.1032 + The null pointer indicating that no page table exists for the corresponding
1.1033 + region.
1.1034 +
1.1035 + The contents of the array are protected by the PageTableAllocator lock AND #MmuLock
1.1036 + */
1.1037 + TPte* iTables[1];
1.1038 + };
1.1039 +
1.1040 +private:
1.1041 + /**
1.1042 + Get or allocate the page tables container for a given PTE type
1.1043 +
1.1044 + @pre #MemoryObjectLock for this object must be held.
1.1045 + */
1.1046 + DPageTables* GetOrAllocatePageTables(TUint aPteType);
1.1047 +
1.1048 +protected:
1.1049 + /**
1.1050 + Array of #DPageTables objects owned by this memory object.
1.1051 + Updates to this array require the #MmuLock.
1.1052 + */
1.1053 + DPageTables* iPageTables[ENumPteTypes];
1.1054 +
1.1055 + friend class DCoarseMemory::DPageTables; // for DPageTables::Close() / AsyncClose()
1.1056 + };
1.1057 +
1.1058 +
1.1059 +
1.1060 +/**
1.1061 +A memory object without the special case optimisations of DCoarseMemory.
1.1062 +*/
1.1063 +class DFineMemory : public DMemoryObject
1.1064 + {
1.1065 +public:
1.1066 + // from DMemoryObject...
1.1067 + virtual ~DFineMemory();
1.1068 + virtual TInt ClaimInitialPages(TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false);
1.1069 +
1.1070 +public:
1.1071 + /**
1.1072 + Create a new DFineMemory object.
1.1073 +
1.1074 + @param aManager The manager object for this memory.
1.1075 + @param aSizeInPages Size of the memory object, in number of pages.
1.1076 + @param aAttributes Bitmask of values from enum #TMemoryAttributes.
1.1077 + @param aCreateFlags Bitmask of option flags from enum #TMemoryCreateFlags.
1.1078 +
1.1079 + @return The newly created DFineMemory or the null pointer if there was
1.1080 + insufficient memory.
1.1081 + */
1.1082 + static DFineMemory* New(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
1.1083 +
1.1084 +private:
1.1085 + /**
1.1086 + For arguments, see #New.
1.1087 + */
1.1088 + DFineMemory(DMemoryManager* aManager, TUint aSizeInPages, TMemoryAttributes aAttributes, TMemoryCreateFlags aCreateFlags);
1.1089 + };
1.1090 +
1.1091 +
1.1092 +#endif