--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/include/memmodel/epoc/flexible/memmodel.h Thu Dec 17 09:24:54 2009 +0200
@@ -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 <plat_priv.h>
+#include <memmodel/epoc/mmubase/kblockmap.h>
+#include <mmtypes.h>
+#include <mmboot.h>
+
+#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 <kernel/sshbuf.h>
+
+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<TUint8*>(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