diff -r 000000000000 -r a41df078684a kernel/eka/include/memmodel/epoc/flexible/memmodel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/include/memmodel/epoc/flexible/memmodel.h Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,541 @@ +// Copyright (c) 1998-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: +// e32/include/memmodel/epoc/flexible/memmodel.h +// Flexible Memory Model header file + +/** + @file + @internalComponent +*/ + + +#ifndef __MEMMODEL_H__ +#define __MEMMODEL_H__ + +#include +#include +#include +#include + +#ifdef __SMP__ +// SubScheduler fields for each processor +#define i_AliasLinAddr iExtras[0] +#define i_AliasPdePtr iExtras[1] +#endif + +/******************************************** + * Deterministic Scheduler Implementation + ********************************************/ + +/** +@internalComponent +*/ +#define TheCurrentAddressSpace ((DMemModelProcess*&)TheScheduler.iAddressSpace) + +class DMemoryObject; +class DMemoryMapping; + +/******************************************** + * Thread Control Block + ********************************************/ + +class DMemModelProcess; + +/** +@internalComponent +*/ +class DMemModelThread : public DThread + { +public: + TInt Alias(TLinAddr aAddr, DMemModelProcess* aProcess, TInt aSize, TLinAddr& aAliasAddr, TUint& aAliasSize); + void RemoveAlias(); + void RefreshAlias(); + virtual void DoExit1(); + static void RestoreAddressSpace(); + virtual void BTracePrime(TInt aCategory); +protected: + virtual void SetPaging(TUint& aCreateFlags); +private: + void DoRemoveAlias(TLinAddr aAddr); +public: + TLinAddr iAliasLinAddr; // linear address to access aliased memory (0 means no alias is present). + TPde* iAliasPdePtr; // Address of PDE which has been modified to make aliased memory accessible. + TPde iAliasPde; // PDE to store at iAliasPdePtr. + DMemModelProcess* iAliasProcess; // The process whose memory is aliased. + SDblQueLink iAliasLink; // link to make TheMmu.iAliasList. + TLinAddr iAliasTarget; // linear address of the memory which has been aliased + DMemoryMapping* iKernelStackMapping; + DMemoryMapping* iUserStackMapping; +#ifdef __SMP__ + TInt iCpuRestoreCookie; +#endif + }; + + +/******************************************** + * Process Control Block + ********************************************/ + +class DMemModelChunk; +class DMemModelCodeSegMemory; +class RAddressedContainer; + +#ifdef INCLUDED_FROM_ASM +#define PRIVATE_EXCEPT_ASM public +#else +#define PRIVATE_EXCEPT_ASM private +#endif + + +/** +@internalComponent +*/ +class DMemModelProcess : public DEpocProcess + { +public: + ~DMemModelProcess(); +private: + void Destruct(); +protected: + virtual TInt AttachExistingCodeSeg(TProcessCreateInfo& aInfo); + virtual TInt SetPaging(const TProcessCreateInfo& aInfo); +public: + virtual TInt DoCreate(TBool aKernelProcess, TProcessCreateInfo& aInfo); + virtual TInt NewChunk(DChunk*& aChunk, SChunkCreateInfo& aInfo, TLinAddr& aRunAddr); + virtual TInt AddChunk(DChunk* aChunk,TBool aIsReadOnly); + virtual TInt NewShPool(DShPool*& aPool, TShPoolCreateInfo& aInfo); + virtual TInt CreateDataBssStackArea(TProcessCreateInfo& aInfo); + virtual TInt MapCodeSeg(DCodeSeg* aCodeSeg); + virtual void UnmapCodeSeg(DCodeSeg* aCodeSeg); + virtual void RemoveDllData(); + virtual void FinalRelease(); + virtual void BTracePrime(TInt aCategory); +public: + TInt DoAddChunk(DMemModelChunk* aChunk, TBool aIsReadOnly); + TInt AllocateDataSectionBase(DMemModelChunk& aChunk, TUint& aBase); + TUint8* DataSectionBase(DMemModelChunk* aChunk); + void RemoveChunk(DMemModelChunk *aChunk); + void DoRemoveChunk(TInt aIndex); + TInt ChunkIndex(DMemModelChunk* aChunk); + TUint ChunkInsertIndex(DMemModelChunk* aChunk); + TInt CommitDllData(TLinAddr aBase, TInt aSize, DCodeSeg* aCodeSeg); + void DecommitDllData(TLinAddr aBase, TInt aSize); + TInt MapUserRamCode(DMemModelCodeSegMemory* aMemory); + void UnmapUserRamCode(DMemModelCodeSegMemory* aMemory); + inline TInt OsAsid() + {__NK_ASSERT_DEBUG( TheCurrentThread->iOwningProcess == this || // current thread's process so asid can't be freed. + iOsAsid == (TInt)KKernelOsAsid || // kernel process so asid can't be freed. + iContainerID != EProcess || // process not fully created yet so asid can't be freed. + iOsAsidRefCount > 1); // if none of the others are true then should have a reference + // to prevent asid being freed (this check isn't very + // robust but best we can do). + return iOsAsid; + }; + + TInt TryOpenOsAsid(); + void CloseOsAsid(); + void AsyncCloseOsAsid(); +public: + struct SChunkInfo + { + DMemModelChunk* iChunk; + DMemoryMapping* iMapping; + TInt16 iAccessCount; + TInt16 iIsReadOnly; + }; + + TInt iChunkCount; + TInt iChunkAlloc; + SChunkInfo* iChunks; + RAddressedContainer* iSharedChunks; + TPhysAddr iPageDir; + DMemoryMapping* iDataBssMapping; + /** + Size of virtual memory allocated in process for EXE code, but which hasn't yet been been + adopted by the codeseg memory mapping. + */ + TUint iCodeVirtualAllocSize; + /** + Address of virtual memory allocated in process for EXE code. + */ + TLinAddr iCodeVirtualAllocAddress; + +PRIVATE_EXCEPT_ASM: + TInt iOsAsid; // This should only be accessed directly by the scheduler, + // in all other cases use either OsAsid() or TryOpenOsAsid(). +private: + TUint iOsAsidRefCount; +public: + friend class Monitor; + }; + + +/******************************************** + * Chunk Control Block + ********************************************/ + +/** +@internalComponent +*/ +class DMemModelChunk : public DChunk + { +public: + /** + @see DChunk::TChunkAttributes for generic attribute flags + */ + enum TMemModelChunkAttributes + { + EPrivate =0x00000000, // need to be iOwningProcess in order to map or change chunk + EPublic =0x80000000, // not EPrivate + ECode =0x40000000, // contents are executable + EMMChunkAttributesMask = EPrivate | EPublic | ECode, + }; + +public: + DMemModelChunk(); + ~DMemModelChunk(); +public: + virtual TInt Close(TAny* aPtr); + virtual TInt DoCreate(SChunkCreateInfo& aInfo); + virtual TInt Adjust(TInt aNewSize); + virtual TInt AdjustDoubleEnded(TInt aBottom, TInt aTop); + virtual TInt CheckAccess(); + virtual TInt Commit(TInt aOffset, TInt aSize, TCommitType aCommitType=DChunk::ECommitDiscontiguous, TUint32* aExtraArg=0); + virtual TInt Allocate(TInt aSize, TInt aGuard=0, TInt aAlign=0); + virtual TInt Decommit(TInt aOffset, TInt aSize); + virtual TInt Lock(TInt aOffset, TInt aSize); + virtual TInt Unlock(TInt aOffset, TInt aSize); + virtual TInt Address(TInt aOffset, TInt aSize, TLinAddr& aKernelAddress); + virtual TInt PhysicalAddress(TInt aOffset, TInt aSize, TLinAddr& aKernelAddress, TUint32& aPhysicalAddress, TUint32* aPhysicalPageList=NULL); + virtual void BTracePrime(TInt aCategory); + virtual void Substitute(TInt aOffset, TPhysAddr aOldAddr, TPhysAddr aNewAddr); + virtual TUint8* Base(DProcess* aProcess); +protected: + virtual void SetPaging(TUint aCreateAtt); +public: + void SetFixedAddress(TLinAddr aAddr, TInt aInitialSize); + TInt SetAttributes(SChunkCreateInfo& aInfo); + TInt DoCommit(TInt aOffset, TInt aSize, TCommitType aCommitType=DChunk::ECommitDiscontiguous, TUint32* aExtraArg=0); + void DoDecommit(TInt aOffset, TInt aSize); + TInt CheckRegion(TInt& aOffset, TInt& aSize); +public: + TBitMapAllocator* iPageBitMap; // NULL if not disconnected chunk + TBitMapAllocator* iPermanentPageBitMap; + + /** + The memory object containing this chunk's memory. + */ + DMemoryObject* iMemoryObject; + + /** + For shared chunks and shared i/o buffers this is the mapping + which maps #iMemoryObject into the kernel's address space. + */ + DMemoryMapping* iKernelMapping; +public: + friend class Monitor; + }; + + +/** +@internalComponent +*/ +class DMemModelChunkHw : public DPlatChunkHw + { +public: + virtual TInt Close(TAny* aPtr); +public: + DMemoryObject* iMemoryObject; + DMemoryMapping* iKernelMapping; + }; + + + +/******************************************** + * Code segment + ********************************************/ + +class TPagedCodeInfo; + +/** +@internalComponent +*/ +class DMemModelCodeSegMemory : public DEpocCodeSegMemory + { +public: + DMemModelCodeSegMemory(DEpocCodeSeg* aCodeSeg); + ~DMemModelCodeSegMemory(); + TInt Create(TCodeSegCreateInfo& aInfo, DMemModelProcess* aProcess); + TInt Loaded(TCodeSegCreateInfo& aInfo); + void Destroy(); +public: + /** + The process loading this code segment. + */ + DMemModelProcess* iCreator; + + /** + Kernel side copy of the codeseg's export directory or NULL. + */ + TLinAddr* iCopyOfExportDir; + + /** + For demand paged codeseg's, pointer to saved copy of the data section. + */ + TAny* iDataSectionMemory; + + /** + The memory object containing the memory for the codeseg. + */ + DMemoryObject* iCodeMemoryObject; + + /** + A writable mapping which maps #iCodeMemoryObject into the loader + process's memory so it can be accessed by the loader. + + This mapping is destroyed once #Loaded is called. + */ + DMemoryMapping* iCodeLoadMapping; + + /** + For demand paged codeseg's, this is a writable mapping added to the + loader process's address space which maps a memory object used to + hold the initial contents of the codeseg's data section. + + This mapping, and it's memory object, is destroyed once #Loaded is called. + */ + DMemoryMapping* iDataLoadMapping; + + /** + Size of any shared virtual memory allocated for the code. + */ + TUint iVirtualAllocCommonSize; + + /** + For demand paged codeseg's, a pointer to the #TPagedCodeInfo + used with #iCodeMemoryObject. + */ + TPagedCodeInfo* iPagedCodeInfo; + }; + + +/** +@internalComponent +*/ +class DMemModelCodeSeg: public DEpocCodeSeg + { +public: + DMemModelCodeSeg(); + virtual ~DMemModelCodeSeg(); + virtual TInt DoCreateRam(TCodeSegCreateInfo& aInfo, DProcess* aProcess); + virtual TInt DoCreateXIP(DProcess* aProcess); + virtual TInt Loaded(TCodeSegCreateInfo& aInfo); + virtual void ReadExportDir(TUint32* aDest); + virtual TBool FindCheck(DProcess* aProcess); + virtual TBool OpenCheck(DProcess* aProcess); + inline DMemModelCodeSegMemory* Memory() + { return (DMemModelCodeSegMemory*)iMemory; } + virtual void BTracePrime(TInt aCategory); +public: + /** + For kernel codesegs, the address of the memory allocated for its static data. + */ + TAny* iKernelData; + + /** + The memory object containing the memory for this codeseg. + */ + DMemoryObject* iCodeMemoryObject; + + /** + A writable mapping which maps #iCodeMemoryObject into the loader + process's memory so it can be accessed by the loader. + + This mapping is destroyed once #Loaded is called. + */ + DMemoryMapping* iCodeLoadMapping; + + /** + The read=only mapping used for kernel and global codesegs to map + #iCodeMemoryObject into the global address region. + */ + DMemoryMapping* iCodeGlobalMapping; + + /** + Base address of virtual memory allocated for the codeseg's static data. + */ + TLinAddr iDataAllocBase; + + /** + Size of virtual memory allocated for the codeseg's static data. + */ + TUint iDataAllocSize; + }; + + +/******************************************** + * Shared buffers and pools + ********************************************/ + +#include + +class DShBufMapping; + + +class DMemModelNonAlignedShBuf : public DShBuf + { +public: + DMemModelNonAlignedShBuf(DShPool* aPool, TLinAddr aRelAddr); + ~DMemModelNonAlignedShBuf(); + + TInt Close(TAny*); + TInt AddToProcess(DProcess* aProcess, TUint aAttr); + +protected: + virtual TInt Pin(TPhysicalPinObject* aPinObject, TBool aReadOnly, TPhysAddr& aAddress, TPhysAddr* aPages, TUint32& aMapAttr, TUint& aColour); + virtual TInt Map(TUint, DProcess*, TLinAddr&); + virtual TInt UnMap(DProcess*); + virtual TUint8* Base(DProcess* aProcess); + virtual TUint8* Base(); + }; + + +class DMemModelAlignedShBuf : public DShBuf + { +public: + DMemModelAlignedShBuf(DShPool* aPool); + virtual ~DMemModelAlignedShBuf(); + + TInt Create(); + virtual TInt Construct(); + + TInt Close(TAny*); + TInt AddToProcess(DProcess* aProcess, TUint aAttr); + +protected: + TUint8* Base(DProcess* aProcess); + TUint8* Base(); + TInt Map(TUint, DProcess*, TLinAddr&); + TInt UnMap(DProcess*); + TInt Pin(TPhysicalPinObject* aPinObject, TBool aReadOnly, TPhysAddr& Address, TPhysAddr* aPages, TUint32& aMapAttr, TUint& aColour); + +private: + TInt FindMapping(DShBufMapping*&, DMemModelProcess*); + DMemoryObject* iMemoryObject; + DMemoryMapping* iKernelMapping; + SDblQue iMappings; + friend class DMemModelAlignedShPool; + }; + +class DMemModelShPool : public DShPool + { +public: + DMemModelShPool(); + virtual ~DMemModelShPool(); +protected: + void DestroyClientResources(DProcess* aProcess); + virtual TInt DestroyAllMappingsAndReservedHandles(DProcess* aProcess) = 0; + }; + +class DMemModelAlignedShPoolClient : public DShPoolClient + { +public: + SDblQue iMappingFreeList; + TInt iWindowSize; + }; + +class DMemModelNonAlignedShPoolClient : public DShPoolClient + { +public: + DMemoryMapping* iMapping; + }; + +class DShBufMapping; + +class DMemModelAlignedShPool : public DMemModelShPool + { +public: + DMemModelAlignedShPool(); + virtual ~DMemModelAlignedShPool(); + + TInt Close(TAny* aPtr); + TInt CreateInitialBuffers(); + TInt SetBufferWindow(DProcess* aProcess, TInt aWindowSize); + TInt AddToProcess(DProcess* aProcess, TUint aAttr); + TInt Alloc(DShBuf*&); + +private: + TInt DoCreate(TShPoolCreateInfo& aInfo); + TInt GrowPool(); + TInt ShrinkPool(); + TInt MappingNew(DShBufMapping*& aMapping, DMemModelProcess* aProcess); + TInt GetFreeMapping(DShBufMapping*& aMapping, DMemModelAlignedShPoolClient* aClient); + TInt ReleaseMapping(DShBufMapping*& aMapping, DMemModelAlignedShPoolClient* aClient); + TInt UpdateMappingsAndReservedHandles(TInt aNoOfBuffers); + TInt UpdateFreeList(); + void Free(DShBuf* aBuf); + TInt CreateMappings(DMemModelAlignedShPoolClient* aClient, TInt aNoOfMappings, DMemModelProcess* aProcess); + TInt DestroyAllMappingsAndReservedHandles(DProcess* aProcess); + TInt DestroyMappings(DMemModelAlignedShPoolClient* aClient, TInt aNoOfMappings); + + TInt DeleteInitialBuffers(); + + SDblQue iPendingList; + DMemModelAlignedShBuf* iInitialBuffersArray; + + friend class DMemModelAlignedShBuf; + }; + +class DMemModelNonAlignedShPool : public DMemModelShPool + { +public: + DMemModelNonAlignedShPool(); + virtual ~DMemModelNonAlignedShPool(); + + TInt Close(TAny* aPtr); + + TInt DoInitFreeList(); + TUint8* Base(DProcess* aProcess); + + inline TUint8* Base() + { + return reinterpret_cast(iBaseAddress); + }; + TInt AddToProcess(DProcess* aProcess, TUint aAttr); + TInt CreateInitialBuffers(); + + TInt Alloc(DShBuf*&); + +private: + void Free(DShBuf* aBuf); + TInt UpdateFreeList(); + + TInt DoCreate(TShPoolCreateInfo& aInfo); + void FreeBufferPages(TUint aOffset); + TInt GrowPool(); + TInt ShrinkPool(); + TInt DeleteInitialBuffers(); + TInt DestroyAllMappingsAndReservedHandles(DProcess* aProcess); + +private: + TLinAddr iBaseAddress; + DMemoryObject* iMemoryObject; // the 'real' memory pool (in the kernel) + DMemModelNonAlignedShBuf* iInitialBuffersArray; + TBitMapAllocator* iBufMap; + TBitMapAllocator* iPagesMap; + + friend class DMemModelNonAlignedShBuf; + }; + +#endif