--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mm.h Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1187 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#ifndef MM_H
+#define MM_H
+
+#include <mmtypes.h>
+#include <platform.h>
+
+
+class DMemoryObject;
+class DMemoryMapping;
+class DMemModelThread;
+class DPhysicalPinMapping;
+
+/**
+Memory object types for MM::MemoryNew which indicates how the
+contents of a memory object are to be managed.
+*/
+enum TMemoryObjectType
+ {
+ /**
+ Memory object for containing memory mapped hardware devices or special
+ purpose memory for which the physical addresses are fixed. The contents of
+ these type of objects are manipulated with the functions:
+ - MM::MemoryAddPages
+ - MM::MemoryAddContiguous
+ - MM::MemoryRemovePages
+ */
+ EMemoryObjectHardware = 0,
+
+ /**
+ Memory object containing normal program memory (RAM) which is allocated from a
+ system wide pool. The contents of these type of objects are manipulated with
+ the functions:
+ - MM::MemoryAlloc
+ - MM::MemoryAllocContiguous
+ - MM::MemoryFree
+ */
+ EMemoryObjectUnpaged = 1,
+
+ /**
+ Memory object containing normal program memory (RAM) which is allocated from a
+ system wide pool. This is the same basic management as EMemoryObjectUnpaged however
+ RAM defragmentation activity may substituted physical RAM pages with others and
+ this process may cause transient page faults which make this memory not suitable
+ for most kernel-side usage.
+
+ The contents of these type of objects are manipulated with the functions:
+ - MM::MemoryAlloc
+ - MM::MemoryAllocContiguous
+ - MM::MemoryFree
+ */
+ EMemoryObjectMovable = 2,
+
+ /**
+ Memory object containing normal program memory (RAM) which is demand paged
+ from a backing store. The contents of these type of objects are manipulated
+ with the functions.
+ - MM::MemoryAlloc
+ - MM::MemoryFree
+ */
+ EMemoryObjectPaged = 3,
+
+ /**
+ Memory object containing normal program memory (RAM) in the same way as
+ EMemoryObjectMovable but with the additional option of marking pages as
+ 'discardable'. Discardable pages may be reclaimed (remove) by the system at
+ any time, this state is controlled using the functions:
+ - MM::MemoryAllowDiscard
+ - MM::MemoryDisallowDiscard
+ */
+ EMemoryObjectDiscardable = 4
+ };
+
+
+/**
+Bitmask of flags to specify options to MM:MemoryNew.
+*/
+enum TMemoryCreateFlags
+ {
+ /**
+ Default value which has all flags false.
+ */
+ EMemoryCreateDefault = 0,
+
+ /**
+ Memory allocated for the memory object contents does not need wiping.
+ IMPORTANT, memory is normally wiped for security purposes, this attribute
+ should only be used when the old contents of any memory allocated can not
+ be read by any process without TCB capability.
+ */
+ EMemoryCreateNoWipe = 1<<0,
+
+ /**
+ Use the custom wipe byte value when wiping memory, rather than the default value.
+ @see EMemoryCreateUseCustomWipeByte
+ */
+ EMemoryCreateUseCustomWipeByte = 1<<1,
+
+ /**
+ Pre-create all resources the memory object needs so that operations on it
+ can not fail due to low memory conditions. This excludes any explicit
+ allocation of memory pages for use as the objects contents.
+ */
+ EMemoryCreateReserveAllResources = 1<<2,
+
+ /**
+ Memory object contents are not allowed to be pinned.
+ */
+ EMemoryCreateDisallowPinning = 1<<3,
+
+ /**
+ Memory object contents are read-only. Mappings with write permissions are
+ not allowed.
+ */
+ EMemoryCreateReadOnly = 1<<4,
+
+ /**
+ Memory object contents may be executed. Mappings with execute permissions
+ are allowed.
+ */
+ EMemoryCreateAllowExecution = 1<<5,
+
+ /**
+ Bit position for the least significant bit of an 8 bit value to use for
+ wiping newly allocated memory.
+ @see EMemoryCreateUseCustomWipeByte
+ @see EMemoryCreateNoWipe
+ */
+ EMemoryCreateWipeByteShift = 8,
+
+ // for selected internal use only...
+
+ /**
+ The TMemoryObjectType specified is actually a pointer to the DMemoryManager to use.
+ */
+ EMemoryCreateCustomManager = 1<<30,
+
+ /**
+ Memory object contents are to be demand paged.
+ */
+ EMemoryCreateDemandPaged = 1<<31
+ };
+
+
+/**
+Attributes that the memory in a memory object has.
+
+These govern how the MMU and caching systems treat the memory. The following
+terms have meanings as specified in the ARM Architecture Reference Manual - see
+the section 'Memory types and attributes and the Memory order model'.
+
+- Memory types 'normal', 'device' and 'strongly-ordered'.
+- 'Shareable' attribute.
+*/
+enum TMemoryAttributes
+ {
+ // memory types (copy of TMemoryType)...
+
+ EMemoryAttributeStronglyOrdered = EMemAttStronglyOrdered,
+ EMemoryAttributeDevice = EMemAttDevice,
+ EMemoryAttributeNormalUncached = EMemAttNormalUncached,
+ EMemoryAttributeNormalCached = EMemAttNormalCached,
+ EMemoryAttributeKernelInternal4 = EMemAttKernelInternal4,
+ EMemoryAttributePlatformSpecific5 = EMemAttPlatformSpecific5,
+ EMemoryAttributePlatformSpecific6 = EMemAttPlatformSpecific6,
+ EMemoryAttributePlatformSpecific7 = EMemAttPlatformSpecific7,
+
+ /**
+ Bitmask to extract TMemoryType value from this enum. E.g.
+ @code
+ TMemoryAttributes attr;
+ TMemoryType type = (TMemoryType)(attr&EMemoryAttributeTypeMask);
+ @endcode
+ */
+ EMemoryAttributeTypeMask = KMemoryTypeMask,
+
+ /**
+ Set if memory is Shareable.
+ */
+ EMemoryAttributeShareable = 0x08,
+
+ /**
+ Legacy (and little-used/unused?) ARM attribute.
+ */
+ EMemoryAttributeUseECC = 0x10,
+
+
+ /**
+ Number of bits required to store memory attribute value.
+ @internalComponent
+ */
+ EMemoryAttributeShift = 5,
+
+ /**
+ Bitmask for all significant attribute bits.
+ @internalComponent
+ */
+ EMemoryAttributeMask = (1<<EMemoryAttributeShift)-1,
+
+ // pseudo attributes...
+
+ /**
+ Indicates the Shareable attribute should be the default value for the system.
+ See macro __CPU_USE_SHARED_MEMORY
+ */
+ EMemoryAttributeDefaultShareable = 0x80000000,
+
+ // popular combinations...
+
+ /**
+ Normal program memory for use by software.
+ */
+ EMemoryAttributeStandard = EMemoryAttributeNormalCached|EMemoryAttributeDefaultShareable
+ };
+
+
+/**
+Access permissions applied to Memory Mappings.
+*/
+enum TMappingPermissions
+ {
+ EUser = 1<<0, ///< Unprivileged (user mode) access allowed.
+ EReadWrite = 1<<1, ///< Memory contents may be modified
+ EExecute = 1<<2, ///< Memory contents may be executed as code.
+
+ // popular combinations...
+ EUserReadOnly = EUser,
+ EUserReadWrite = EUser|EReadWrite,
+ EUserExecute = EUser|EExecute,
+ ESupervisorReadOnly = 0,
+ ESupervisorReadWrite = EReadWrite,
+ ESupervisorExecute = EExecute
+ };
+
+
+/**
+Bitmask of flags to specify options to MM::MappingNew.
+*/
+enum TMappingCreateFlags
+ {
+ /**
+ Default value which has all flags false.
+ */
+ EMappingCreateDefault = 0,
+
+ /**
+ Allocate the specified virtual address.
+ */
+ EMappingCreateExactVirtual = 1<<0,
+
+ /**
+ Pre-create all resources (like page tables) that the memory mapping
+ needs so that operations on it can not fail due to low memory conditions.
+ */
+ EMappingCreateReserveAllResources = 1<<1,
+
+ // for selected internal use only...
+
+ /**
+ Flag memory as being demand paged.
+ Exclusive with EMappingCreatePinning and EMappingCreateReserveAllResources.
+ @internalTechnology
+ */
+ EMappingCreateDemandPaged = 1<<27,
+
+ /**
+ Flag memory as requiring a common address across all address spaces, also
+ implies EMappingCreateExactVirtual.
+ @internalTechnology
+ */
+ EMappingCreateCommonVirtual = 1<<28,
+
+ /**
+ Allocate virtual address in the global region which it to be used for
+ user-mode access. (KGlobalMemoryBase<=address<KUserMemoryLimit).
+ @internalTechnology
+ */
+ EMappingCreateUserGlobalVirtual = 1<<29,
+
+ /**
+ Don't allocate any virtual memory in the address space, use the specified
+ address and assume ownership of this.
+ @internalTechnology
+ */
+ EMappingCreateAdoptVirtual = 1<<30,
+
+ /**
+ Don't allocate any virtual memory in the address space, just used the
+ specified address.
+ @internalTechnology
+ */
+ EMappingCreateFixedVirtual = 1<<31
+ };
+
+
+class DMemModelChunk;
+class TPagedCodeInfo;
+
+/**
+Static interface to the Flexible Memory Model implementation
+for use by the Symbian OS aware part of the memory model codebase.
+*/
+class MM
+ {
+public:
+ //
+ // Memory Object functions
+ //
+
+ /**
+ Create a new memory object.
+
+ A memory object is a sparse array of memory pages to which memory mappings
+ may be attached. All pages in the array are managed using the same methods
+ (see TMemoryObjectType) and have the same attributes (see TMemoryAttributes).
+
+ On creation it contains no pages.
+
+ @param[out] aMemory Pointer reference which on success is set to the address
+ of the created memory object.
+ @param aType Value from TMemoryObjectType which indicates how the
+ contents of the memory object are to be managed.
+ @param aPageCount Size of the memory object, in number of pages.
+ @param aCreateFlags Bitmask of option flags from enum TMemoryCreateFlags.
+ @param aAttributes Bitmask of values from enum TMemoryAttributes.
+
+ @return KErrNone, if successful;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MemoryNew(DMemoryObject*& aMemory, TMemoryObjectType aType, TUint aPageCount, TMemoryCreateFlags aCreateFlags=EMemoryCreateDefault, TMemoryAttributes aAttributes=EMemoryAttributeStandard);
+
+ /**
+ Assign a mutex which will be used to serialise explicit modifications to the
+ specified memory object.
+
+ If a lock hasn't been specified for a particular object, it will make use of
+ one allocated dynamically allocated from a shared pool; this mutex will be of 'order'
+ #KMutexOrdMemoryObject.
+
+ @see MemoryObjectLock.
+ */
+ static void MemorySetLock(DMemoryObject* aMemory, DMutex* aLock);
+
+ /**
+ Wait on the specified memory object's lock mutex.
+ */
+ static void MemoryLock(DMemoryObject* aMemory);
+
+ /**
+ Signal the specified memory object's lock mutex.
+ */
+ static void MemoryUnlock(DMemoryObject* aMemory);
+
+ /**
+ Remove all memory from a memory object and close a reference on it.
+
+ If there are no longer any mappings to the memory, or other references,
+ this will result in the memory object being destroyed. However whilst
+ other references exist, cleanup of memory and other resources may be
+ delayed indefinitely.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ @param aMemory Pointer reference to memory object to be destroyed.
+ On return from the function this is set to the null-pointer.
+ No action is performed if the reference was already the
+ null-pointer on entry to this function.
+ */
+ static void MemoryDestroy(DMemoryObject*& aMemory);
+
+ /**
+ Allocate memory for a specified region within a memory object.
+ Memory is allocated as appropriate for the object type, e.g.
+ For Unpaged objects, from the system RAM pool; for Paged objects, in the
+ backing store.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ Supported for memory object types:
+ - EMemoryObjectUnpaged
+ - EMemoryObjectMovable
+ - EMemoryObjectPaged
+ - EMemoryObjectDiscardable
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+
+ @return KErrNone, if successful;
+ KErrAlreadyExists, if any part of the region was already allocated;
+ KErrArgument, if the region exceeds the bounds of the memory object;
+ KErrNotSupported, if the memory object doesn't support this operation;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MemoryAlloc(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+
+ /**
+ Allocate memory for a specified region within a memory object.
+ The allocated memory will have contiguous physical addresses.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ Important note, this function can unexpectedly fail with KErrAlreadyExists
+ if any part of the the region previously contained allocated memory which
+ had been freed but which was pinned. It is therefore not suitable for general
+ use.
+
+ Supported for memory object types:
+ - EMemoryObjectUnpaged
+ - EMemoryObjectDiscardable
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+ @param aAlign Log2 of the alignment (in bytes) that the address of the allocated physical RAM must have.
+ @param[out] aPhysAddr On success, this is set to the start address of the allocated physical RAM.
+
+ @return KErrNone, if successful;
+ KErrAlreadyExists, if any part of the region was already allocated;
+ KErrArgument, if the region exceeds the bounds of the memory object;
+ KErrNotSupported, if the memory object doesn't support this operation;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MemoryAllocContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TUint aAlign, TPhysAddr& aPhysAddr);
+
+ /**
+ Free (unallocate) memory for a specified region within a memory object.
+ This is the inverse operation to MemoryAlloc and MemoryAllocContiguous.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ Supported for memory object types:
+ - EMemoryObjectUnpaged
+ - EMemoryObjectMovable
+ - EMemoryObjectPaged
+ - EMemoryObjectDiscardable
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+ */
+ static void MemoryFree(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+
+ /**
+ Add the specified pages to a region in a memory object.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ Supported for memory object types:
+ - EMemoryObjectHardware
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+ @param aPages Pointer to array of pages to add. This must contain \a aCount
+ number of physical page addresses which are page aligned.
+
+ @return KErrNone, if successful;
+ KErrAlreadyExists, if any part of the region already contains pages;
+ KErrArgument, if the region exceeds the bounds of the memory object;
+ KErrNotSupported, if the memory object doesn't support this operation;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MemoryAddPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages);
+
+ /**
+ Add a contiguous range of pages to a region in a memory object.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ Supported for memory object types:
+ - EMemoryObjectHardware
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+ @param aPhysAddr The page aligned start address of the pages to be added.
+
+ @return KErrNone, if successful;
+ KErrAlreadyExists, if any part of the region already contains pages;
+ KErrArgument, if the region exceeds the bounds of the memory object;
+ KErrNotSupported, if the memory object doesn't support this operation;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MemoryAddContiguous(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr aPhysAddr);
+
+ /**
+ Remove pages from a region in a memory object.
+
+ This is the inverse operation to MemoryAdd and MemoryAddContiguous.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ Supported for memory object types:
+ - EMemoryObjectHardware
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+ @param[out] aPages Pointer to an array of physical addresses which has a
+ length of \a aCount. The contents of this will be set to
+ the addresses of the pages which were removed by this
+ function. The number of valid entries in this array is
+ given by the return value of this function.
+ aPages may be the null-pointer, to indicate that these
+ page addresses aren't required by the caller.
+
+ @return The number of pages successfully removed from the memory object.
+ This gives the number of valid entries in the array \a aPages and is
+ less-than or equal to \a aCount.
+ */
+ static TUint MemoryRemovePages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr* aPages);
+
+ /**
+ Mark a region in a memory object as discardable.
+
+ The system may remove discardable pages from the memory object at any time,
+ to be reused for other purposes.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ Supported for memory object types:
+ - EMemoryObjectDiscardable
+
+ @see MemoryDisallowDiscard
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+
+ @return KErrNone, if successful;
+ KErrNotSupported, if the memory object doesn't support this operation;
+ otherwise another of the system wide error codes.
+
+ */
+ static TInt MemoryAllowDiscard(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+
+ /**
+ Mark a region in a memory object as no longer discardable.
+ This undoes the operation of MemoryAllowDiscard.
+
+ If any pages in the region are no longer present, then the operation will
+ fail with KErrNotFound. In this case, the state of the pages in the region
+ is indeterminate; they may be either still discardable, not discardable, or
+ not present.
+
+ Supported for memory object types:
+ - EMemoryObjectDiscardable
+
+ @see MemoryAllowDiscard
+
+ @param aMemory The memory object.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+
+ @return KErrNone, if successful;
+ KErrNotFound, if any page in the region was no longer present;
+ KErrNotSupported, if the memory object doesn't support this operation;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MemoryDisallowDiscard(DMemoryObject* aMemory, TUint aIndex, TUint aCount);
+
+ /**
+ This function only exists to support DMemModelChunk::PhysicalAddress and may be removed.
+ DO NOT USE.
+ */
+ static TInt MemoryPhysAddr(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TPhysAddr& aPhysicalAddress, TPhysAddr* aPhysicalPageList);
+
+ /**
+ Prime BTrace for a memory object - internal use only.
+ */
+ static void MemoryBTracePrime(DMemoryObject* aMemory);
+
+ /**
+ Close a memory object.
+
+ This should be called on the memory object returned by #MappingGetAndOpenMemory.
+ */
+ static void MemoryClose(DMemoryObject* aMemory);
+
+ /**
+ Return true if aMemory has any mappings associated with it.
+ */
+ static TBool MemoryIsNotMapped(DMemoryObject* aMemory);
+
+ /**
+ Wipe the entire memory contents of the memory object so they are in the
+ same state as if the memory had been newly allocated with #MemoryAlloc.
+
+ This is useful for situations where a memory object is being re-purposed and
+ confidentiality requires that the old memory contents are not disclosed.
+ For this reason, the function asserts that the memory object has no mappings.
+
+ @see EMemoryCreateUseCustomWipeByte
+ @see EMemoryCreateNoWipe
+
+ @return KErrNone, if successful;
+ otherwise KErrNotSupported, to indicate the memory object doesn't support this operation.
+ */
+ static TInt MemoryWipe(DMemoryObject* aMemory);
+
+ /**
+ Set the memory object to be read only, i.e. to no longer allow writable mappings.
+
+ NOTE - This can't be undone, page moving will break if a memory object is made
+ writable again.
+
+ @param aMemory The memory object to update.
+ @return KErrNone on success, KErrInUse if the memory object has writable mappings
+ KErrNotSupported if the objects manager doesn't support this.
+ */
+ static TInt MemorySetReadOnly(DMemoryObject* aMemory);
+
+ /**
+ Pins physical memory associated with the memory object and returns the physical
+ memory characteristics, e.g. address, map attributes and colour
+
+ @param aMemory The memory object.
+ @param aPinObject The physical pin mapping.
+ @param aIndex Page index for start of the region.
+ @param aCount Number of pages in the region.
+ @param aReadOnly Indicates whether memory should be pinned as read only.
+ @param aAddress[out] The value is the physical address of the first page
+ in the region.
+ @param aPages[out] If not zero, this points to an array of TPhysAddr
+ objects. On success, this array will be filled
+ with the addresses of the physical pages which
+ contain the specified region. If aPages is
+ zero, then the function will fail with
+ KErrNotFound if the specified region is not
+ physically contiguous.
+ @param aMapAttr[out] Memory attributes defined by TMappingAttributes2.
+ @param aColour[out] The mapping colour of the first physical page.
+
+
+ @return The number of pages successfully removed from the memory object.
+ This gives the number of entries in the array aPages and is
+ less-than or equal to aCount.
+ */
+
+ static TInt PinPhysicalMemory(DMemoryObject* aMemory, DPhysicalPinMapping* aPinObject, TUint aIndex,
+ TUint aCount, TBool aReadOnly, TPhysAddr& aAddress, TPhysAddr* aPages,
+ TUint32& aMapAttr, TUint& aColour);
+
+ //
+ // Memory Mapping functions
+ //
+
+ /**
+ Create a new memory mapping for a specific memory object.
+
+ A memory mapping represents the MMU resources required to make a region of a
+ memory object accessible to software within a single address space (process).
+ Each mapping has an associated set of access permissions (see
+ #TMappingPermissions).
+
+ @param[out] aMapping Pointer reference which on success is set to the address
+ of the created memory mapping.
+ @param aMemory The memory object with which the mapping is associated.
+ @param aPermissions Bitmask of values from enum #TMappingPermissions which
+ give the access permissions for this mapping.
+ @param aOsAsid The identifier for the address space in which this
+ mapping is to appear.
+ @param aFlags Bitmask of option flags from enum #TMappingCreateFlags
+ @param aAddr Optional virtual address at which the memory mapped
+ by this mapping is to appear within the specified
+ address space.
+ @param aIndex Optional start page index within \a aMemory for this
+ mapping.
+ @param aCount Optional page count for size of mapping. A value of
+ the maximum integer indicates that the mapping is to
+ extend to the end of the memory object.
+
+ @return KErrNone, if successful;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MappingNew(DMemoryMapping*& aMapping, DMemoryObject* aMemory, TMappingPermissions aPermissions, TInt aOsAsid, TMappingCreateFlags aFlags=EMappingCreateDefault, TLinAddr aAddr=0, TUint aIndex=0, TUint aCount=~0u);
+
+ /**
+ Create a new memory mapping with is not associated with any memory object.
+
+ This mapping may be used and reused with different memory objects by using
+ the #MappingMap and #MappingUnmap methods.
+
+ @param[out] aMapping Pointer reference which on success is set to the address
+ of the created memory mapping.
+ @param aCount Page count for size of mapping.
+ @param aOsAsid The identifier for the address space in which this
+ mapping is to appear.
+ @param aFlags Bitmask of option flags from enum #TMappingCreateFlags
+ @param aAddr Optional virtual address at which the mapping is to
+ appear within the specified address space.
+ @param aColourOffset The byte offset within a memory object's memory which this mapping
+ is to start. This is used to adjust virtual memory allocation to
+ meet page colouring restrictions. If this value is not known leave
+ this argument unspecified; however, it must be specified if \a aAddr
+ is specified.
+
+ @return KErrNone, if successful;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MappingNew(DMemoryMapping*& aMapping, TUint aCount, TInt aOsAsid, TMappingCreateFlags aFlags=EMappingCreateDefault, TLinAddr aAddr=0, TLinAddr aColourOffset=~0);
+
+ /**
+ Apply a memory mapping to a memory object.
+
+ @param aMapping The memory mapping to be used to map \a aMemory.
+ @param aPermissions Bitmask of values from enum #TMappingPermissions which
+ give the access permissions for this mapping.
+ @param aMemory The memory object with which the mapping is to be associated.
+ @param aIndex Optional start page index within aMemory for this
+ mapping.
+ @param aCount Optional page count for size of mapping. A value of
+ the maximum integer indicates that the mapping is to
+ extend to the end of the memory object.
+
+ @return KErrNone, if successful;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MappingMap(DMemoryMapping* aMapping, TMappingPermissions aPermissions, DMemoryObject* aMemory, TUint aIndex=0, TUint aCount=~0u);
+
+ /**
+ Remove a mapping from the memory object with which it is associated.
+ */
+ static void MappingUnmap(DMemoryMapping* aMapping);
+
+ /**
+ Remove a memory mapping from its associated address space and close a
+ reference on it.
+
+ If there are no longer any other references, this will result in the memory
+ object being destroyed,
+
+ @param aMapping Pointer reference to memory mapping to be destroyed.
+ On return from the function this is set to the null-pointer.
+ No action is performed if the reference was already the
+ null-pointer on entry to this function.
+ */
+ static void MappingDestroy(DMemoryMapping*& aMapping);
+
+ /**
+ Remove a memory mapping from its associated address space and close a
+ reference on it.
+
+ The mapping is found based on the virtual address region within which it
+ maps memory. The caller must that such a mapping exists and that it will not
+ be unmapped by another thread.
+
+ @param aAddr Virtual address which lies within the region covered by the
+ memory mapping.
+ @param aOsAsid Address space in which the mapping appears.
+ */
+ static void MappingDestroy(TLinAddr aAddr, TInt aOsAsid);
+
+ /**
+ Perform the action of #MappingDestroy on a memory mapping then #MemoryDestroy
+ on its associated memory object.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ NOTE - This should not be used on mappings that are reused as the mapping's
+ instance count is not checked.
+
+ @param aMapping Pointer reference to memory mapping to be destroyed.
+ On return from the function this is set to the null-pointer.
+ No action is performed if the reference was already the
+ null-pointer on entry to this function.
+ */
+ static void MappingAndMemoryDestroy(DMemoryMapping*& aMapping);
+
+ /**
+ Perform the action of #MappingDestroy on a memory mapping then #MemoryDestroy
+ on its associated memory object.
+
+ The mapping is found based on the virtual address region within which it
+ maps memory. The caller must that such a mapping exists and that it will not
+ be unmapped by another thread.
+
+ This function acquires and releases the memory objects lock.
+ See MM::MemorySetLock.
+
+ NOTE - This should not be used on mappings that are reused as the mapping's
+ instance count is not checked.
+
+ @param aAddr Virtual address which lies within the region covered by the
+ memory mapping.
+ @param aOsAsid Address space in which the mapping appears.
+ */
+ static void MappingAndMemoryDestroy(TLinAddr aAddr, TInt aOsAsid);
+
+ /**
+ Return the virtual address at which the memory mapped by a memory mapping
+ starts.
+
+ @param aMapping A memory mapping.
+
+ @return The base address.
+ */
+ static TLinAddr MappingBase(DMemoryMapping* aMapping);
+
+ /**
+ Return the OS Address Space ID (OS ASID) of the address space the mapping is within.
+
+ @param aMapping A memory mapping.
+
+ @return OS Address Space ID (OS ASID).
+ */
+ static TInt MappingOsAsid(DMemoryMapping* aMapping);
+
+ /**
+ Open the memory object mapped by a mapping and return it.
+
+ The memory object can be closed again by calling #MemoryClose.
+
+ NOTE - This should not be used on mappings that are reused as the mapping's
+ instance count is not checked.
+
+ @param aMapping A memory mapping.
+
+ @return The memory object, or NULL.
+ */
+ static DMemoryObject* MappingGetAndOpenMemory(DMemoryMapping* aMapping);
+
+ /**
+ Close a mapping
+
+ @param aMapping A memory mapping.
+ */
+ static void MappingClose(DMemoryMapping* aMapping);
+
+ /**
+ Find and open the mapping that maps a virtual address in the address space of the specified
+ thread.
+
+ The caller must close the mapping when it has finished using it.
+
+ @param aThread The thread whose address space is to be searched.
+ @param aAddr The virtual address for which the mapping is to be found.
+ @param aSize The size, in bytes, of the region at aAddr.
+ @param aOffsetInMapping A reference which is set to the offset, in bytes, into the
+ mapping of the start address.
+ @param aInstanceCount The instance count of the found mapping.
+
+ @return The mapping, or NULL if no mapping was found.
+
+ @pre Calling thread must be in a critical section.
+ */
+ static DMemoryMapping* FindMappingInThread( DMemModelThread* aThread, TLinAddr aAddr, TUint aSize,
+ TUint& aOffsetInMapping, TUint& aInstanceCount);
+
+ /**
+ Find and open the mapping that maps a virtual address in the address space of the specified
+ process.
+
+ The caller must close the mapping when it has finished using it. The caller must ensure that
+ the process can't be destroyed while calling this method.
+
+ @param aOsAsid The identifier for the address space in which the mapping appears.
+ @param aAddr The virtual address for which the mapping is to be found.
+ @param aSize The size, in bytes, of the region at aAddr.
+ @param aOffsetInMapping A reference which is set to the offset, in bytes, into the
+ mapping of the start address.
+ @param aInstanceCount The instance count of the found mapping.
+
+ @return The mapping, or NULL if no mapping was found.
+
+ @pre Calling thread must be in a critical section.
+ */
+ static DMemoryMapping* FindMappingInAddressSpace( TUint aOsAsid, TLinAddr aAddr, TUint aSize,
+ TUint& aOffsetInMapping, TUint& aInstanceCount);
+
+
+ //
+ // Conversion utilities
+ //
+
+ /**
+ Round a size in bytes up to the next integer multiple of the page size.
+
+ @param aSize A size in bytes.
+
+ @return The rounded size.
+ */
+ static TUint RoundToPageSize(TUint aSize);
+
+ /**
+ Round a size in bytes up to the next integer multiple of the page size
+ then convert it into a page count by dividing it by the page size.
+
+ @param aSize A size in bytes.
+
+ @return The rounded page count.
+ */
+ static TUint RoundToPageCount(TUint aSize);
+
+ /**
+ Round a bit shift value representing the log2 of a size in bytes, up to
+ a shift value representing the log2 of a size in pages.
+
+ @param aShift log2 of a size in bytes.
+
+ @return aShift-KPageShift, or zero if aShift<=KPageShift.
+ */
+ static TUint RoundToPageShift(TUint aShift);
+
+ /**
+ Convert a size in bytes to a size in pages.
+
+ @param aBytes A size in bytes.
+
+ @return aBytes/KPageSize.
+
+ @panic MemModel #EBadBytesToPages if aBytes is not an integer multiple of
+ the page size.
+ */
+ static TUint BytesToPages(TUint aBytes);
+
+ /**
+ Construct a #TMappingPermissions value base on individual permission flags.
+
+ @param aUser True to allow unprivileged (user mode) access.
+ @param aWrite True to allow memory contents to be modified.
+ @param aExecute True to allow memory contents to be executed as code.
+
+ @return Permissions expressed as an #TMappingPermissions value.
+ */
+ static TMappingPermissions MappingPermissions(TBool aUser, TBool aWrite, TBool aExecute);
+
+ /**
+ Extract the mapping permissions from a TMappingAttributes2
+ (or TMappingAttributes) value.
+
+ @param[out] aPermissions If successful, mapping permissions extracted from aLegacyAttributes.
+ @param aLegacyAttributes A legacy combined permission/attribute value.
+
+ @return KErrNone, if successful;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MappingPermissions(TMappingPermissions& aPermissions, TMappingAttributes2 aLegacyAttributes);
+
+ /**
+ Extract the memory attributes from a TMappingAttributes2
+ (or TMappingAttributes) value.
+
+ @param[out] aAttributes If successful, memory attributes extracted from \a aLegacyAttributes.
+ @param aLegacyAttributes A legacy combined permission/attribute value.
+
+ @return KErrNone, if successful;
+ otherwise another of the system wide error codes.
+ */
+ static TInt MemoryAttributes(TMemoryAttributes& aAttributes, TMappingAttributes2 aLegacyAttributes);
+
+ /**
+ Construct a legacy combined permission/memory-type value based on a
+ #TMemoryAttributes and #TMappingPermissions value.
+
+ @param aAttributes A memory attributes value.
+ @param aPermissions A mapping permissions value.
+
+ @return A TMappingAttributes2 value combining \a aAttributes and \a aPermissions.
+ */
+ static TMappingAttributes2 LegacyMappingAttributes(TMemoryAttributes aAttributes, TMappingPermissions aPermissions);
+
+ //
+ // Code paging
+ //
+
+ /**
+ Create a new memory object which will contain demand paged code.
+
+ @param[out] aMemory Pointer reference which on success is set to the address
+ of the created memory object.
+ @param aPageCount Size of the memory object, in number of pages.
+ @param aInfo Pointer reference which on success it set to a #TPagedCodeInfo
+ object which should be initialised with information required
+ for demand paging the code. (Call #PagedCodeLoaded when this is done.)
+
+ @return KErrNone, if successful;
+ otherwise another of the system wide error codes.
+ */
+ static TInt PagedCodeNew(DMemoryObject*& aMemory, TUint aPageCount, TPagedCodeInfo*& aInfo);
+
+ /**
+ Call this to indicate that a memory object created with #PagedCodeNew has had its
+ #TPagedCodeInfo object initialised.
+
+ @param aMemory The memory object.
+ @param aLoadAddress An address at which \a aMemory is mapped with write permissions.
+ */
+ static void PagedCodeLoaded(DMemoryObject* aMemory, TLinAddr aLoadAddress);
+
+ //
+ // Misc
+ //
+
+ // Initialisation...
+ static void Init1();
+ static void Init2();
+ static void Init3();
+ static TInt InitFixedKernelMemory(DMemoryObject*& aMemory, TLinAddr aStart, TLinAddr aEnd, TUint aInitSize, TMemoryObjectType aType, TMemoryCreateFlags aMemoryCreateFlags, TMemoryAttributes aMemoryAttributes, TMappingCreateFlags aMappingCreateFlags);
+ static TInt MemoryClaimInitialPages(DMemoryObject* aMemory, TLinAddr aBase, TUint aSize, TMappingPermissions aPermissions, TBool aAllowGaps=false, TBool aAllowNonRamPages=false);
+
+ // IPC helpers...
+ static void ValidateLocalIpcAddress(TLinAddr aAddr, TUint aSize, TBool aWrite);
+#ifndef __SMP__
+ static void IpcAliasPde(TPde*& aPdePtr, TUint aOsAsid);
+#endif
+ static void UserPermissionFault(TLinAddr aAddr, TBool aWrite);
+
+ // Address space...
+ static TInt AddressSpaceAlloc(TPhysAddr& aPageDirectory);
+ static void AddressSpaceFree(TUint aOsAsid);
+ static void AsyncAddressSpaceFree(TUint aOsAsid);
+ static TInt VirtualAllocCommon(TLinAddr& aLinAddr, TUint aSize, TBool aDemandPaged);
+ static void VirtualFreeCommon(TLinAddr aLinAddr, TUint aSize);
+ static TInt VirtualAlloc(TInt aOsAsid, TLinAddr& aLinAddr, TUint aSize, TBool aDemandPaged);
+ static void VirtualFree(TInt aOsAsid, TLinAddr aLinAddr, TUint aSize);
+
+ /**
+ Enumeration of panic values for category "MemModel".
+ */
+ enum TMemModelPanic
+ {
+ EFsRegisterThread,
+ EProcessDestructChunksRemaining,
+ ECommitInvalidDllDataAddress,
+ ECodeSegLoadedNotCreator,
+ ETempMappingAlreadyInUse,
+ EUnsupportedOperation,
+ EBadBytesToPages,
+ ECodeSegSetReadOnlyFailure,
+ EProcessDestructOsAsidRemaining,
+ };
+ static void Panic(TMemModelPanic aPanic);
+ };
+
+
+
+template <class T>
+FORCE_INLINE void FlagSet(T& a,const T b)
+ { a = (T)(a|b); }
+
+template <class T>
+FORCE_INLINE void FlagSet(T& a,const T b,const T c)
+ { a = (T)(a|b|c); }
+
+template <class T>
+FORCE_INLINE void FlagSet(T& a,const T b,const T c,const T d)
+ { a = (T)(a|b|c|d); }
+
+template <class T>
+FORCE_INLINE void FlagClear(T& a,const T b)
+ { a = (T)(a&~b); }
+
+template <class T>
+FORCE_INLINE void FlagClear(T& a,const T b,const T c)
+ { a = (T)(a&~b&~c); }
+
+template <class T>
+FORCE_INLINE void FlagClear(T& a,const T b,const T c,const T d)
+ { a = (T)(a&~b&~c&~d); }
+
+
+#include <memmodel/epoc/mmubase/kblockmap.h>
+
+/**
+Structure containing the information about a demand paged code segment
+which is required to load and fixup its code section.
+*/
+class TPagedCodeInfo
+ {
+public:
+ ~TPagedCodeInfo();
+ TInt ReadBlockMap(const TCodeSegCreateInfo& aInfo);
+ TInt ReadFixupTables(const TCodeSegCreateInfo& aInfo);
+ void ApplyFixups(TLinAddr aBuffer, TUint iIndex);
+public:
+ TBool iLoaded; ///< True once initial loading has finished and paging should start applying fixups.
+ TUint iCodeRelocTableSize; ///< Size, in bytes, of #iCodeRelocTable.
+ TUint8* iCodeRelocTable; ///< Code relocation information.
+ TUint iImportFixupTableSize; ///< Size, in bytes, of #iImportFixupTable.
+ TUint8* iImportFixupTable; ///< Import fixup information.
+ TUint32 iCodeDelta; ///< Delta to apply to relocate words referring to the code section.
+ TUint32 iDataDelta; ///< Delta to apply to relocate words referring to the data section.
+
+ TUint iCodeSize; ///< Size, in bytes, of the code section.
+ TUint32 iCompressionType; ///< Compression scheme in use, (KUidCompressionBytePair or KFormatNotCompressed).
+ TInt32* iCodePageOffsets; ///< Array of compressed page offsets within the file.
+ TInt iCodeLocalDrive; ///< Local drive number.
+ TInt iCodeStartInFile; ///< Offset of (possibly compressed) code from start of file.
+ TBlockMap iBlockMap; ///< Kernel-side representation of block map.
+ };
+
+
+
+/**
+A pool of DMutex objects that can be dynamically assigned for use.
+
+This is intended as a memory saving alternative to having each object in a class of objects
+owning their own mutex for locking purposes and provides a concurrency improvement over using
+a single global lock.
+*/
+class DMutexPool : public DBase
+ {
+public:
+ /**
+ @param aCount Number of mutexes to allocated in the pool.
+ Must be smaller than #EMaxPoolSize.
+ @param aName Base name for mutexes. Each mutex in the pool has a number appended to this base name.
+ @param aOrder A value representing the order of the mutex with respect to deadlock prevention.
+ */
+ TInt Create(TUint aCount, const TDesC* aName, TUint aOrder);
+
+ ~DMutexPool();
+
+ /**
+ Wait on the mutex specified by \a aMutexRef.
+
+ If \a aMutexRef contains the null pointer then a member of this pool is selected and waited on,
+ and \a aMutexRef is set to a cookie value identifying that mutex; this cookie has its least
+ significant bit set to distinguish it from a normal DMutex pointer. Subsequent concurrent
+ Wait operations will use the same pool mutex; possibly modifying the value of the cookie.
+ */
+ void Wait(DMutex*& aMutexRef);
+
+ /**
+ Signal the mutex specified by \a aMutexRef.
+
+ If mutex is identified as one from this pool then the value of \a aMutexRef will be modified
+ and if there are no pending Wait operations it will be set to the null pointer to indicate
+ that no mutex is assigned.
+ */
+ void Signal(DMutex*& aMutexRef);
+
+ /**
+ Return true if the mutex specified by \a aMutexRef is held by the current thread.
+ */
+ TBool IsHeld(DMutex*& aMutexRef);
+
+ enum
+ {
+ /** Maximum number of mutexes allowed in a pool. */
+ EMaxPoolSize = 64
+ };
+
+private:
+ /** Structure for storing information about each member of the pool. */
+ struct SMember
+ {
+ DMutex* iMutex; ///< The mutex
+ TUint iUseCount; ///< Number of times this mutex has been used
+ };
+ TUint iCount; ///< Number of mutexes in pool. (Number of entries in iMembers).
+ TUint iNext; ///< Index of next pool mutex to use.
+ SMember* iMembers; ///< Info about each memory of pool.
+ };
+
+
+#endif