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