kernel/eka/include/memmodel/epoc/flexible/memmodel.h
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
child 43 c1f20ce4abcf
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// 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