kernel/eka/include/memmodel/epoc/moving/memmodel.h
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
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\moving\memmodel.h
// 
// WARNING: This file contains some APIs which are internal and are subject
//          to change without notice. Such APIs should therefore not be used
//          outside the Kernel and Hardware Services package.
//

#ifndef __MEMMODEL_H__
#define __MEMMODEL_H__
#include <memmodel/epoc/mmubase/mmubase.h>

/********************************************
 * Deterministic Scheduler Implementation
 ********************************************/

/**
@internalComponent
*/
#define TheCurrentAddressSpace			((DMemModelProcess*&)TheScheduler.iAddressSpace)

/**
@internalComponent
*/
#define TheCurrentVMProcess				((DMemModelProcess*&)TheScheduler.iExtras[0])

/**
@internalComponent
*/
#define TheCurrentDataSectionProcess	((DMemModelProcess*&)TheScheduler.iExtras[1])

/**
@internalComponent
*/
#define TheCompleteDataSectionProcess	((DMemModelProcess*&)TheScheduler.iExtras[2])

/**
@internalComponent
*/
#define FlushProgress					((TInt&)TheScheduler.iExtras[3])


/********************************************
 * Process Control Block
 ********************************************/
/**
@internalComponent
*/
const TInt KMaxChunksInProcess=16;

class DMemModelChunk;
/**
@internalComponent
*/
class DMemModelProcess : public DEpocProcess
	{
public:
	void Destruct();
public:
	virtual TInt DoCreate(TBool aKernelProcess, TProcessCreateInfo& aInfo);
	virtual TInt NewChunk(DChunk*& aChunk, SChunkCreateInfo& anInfo, TLinAddr& aRunAddr);
	virtual TInt AddChunk(DChunk* aChunk,TBool isReadOnly);
	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();
public:
	virtual TInt GetNewChunk(DMemModelChunk*& aChunk, SChunkCreateInfo& anInfo)=0;
	virtual TInt AddFixedAccessChunk(DMemModelChunk *aChunk)=0;
	virtual TInt RemoveFixedAccessChunk(DMemModelChunk *aChunk)=0;
	virtual void CheckForFixedAccess()=0;
	virtual void DoAttributeChange()=0;
public:
	TInt AddChunk(DMemModelChunk* aChunk, TLinAddr& aDataSectionBase, TBool isReadOnly);
	TInt AllocateDataSectionBase(DMemModelChunk& aChunk, TUint& aBase);
	TUint8* DataSectionBase(DMemModelChunk* aChunk);
	void RemoveChunk(DMemModelChunk *aChunk);
	void DoRemoveChunk(TInt aIndex);
	TInt ChunkIndex(DMemModelChunk* aChunk,TInt& aPos);
	TInt CreateDllDataChunk();
	void FreeDllDataChunk();
	TInt CommitDllData(TLinAddr aBase, TInt aSize);
	void DecommitDllData(TLinAddr aBase, TInt aSize);
public:
	enum TMemModelProcessAttributes
		{
		EFixedAddress=1,
		EMoving=0x40000000,
		EVariableAccess=0x20000000,
//		EMovingCode=0x10000000,		NEVER USED
		EVariableCode=0x04000000,
		EMMProcessAttributesMask = EFixedAddress|EMoving|EVariableAccess|EVariableCode,
		};

	struct SChunkInfo
		{
		TLinAddr iDataSectionBase;
		DMemModelChunk *iChunk;
		TInt16 iAccessCount;
		TInt16 isReadOnly;
		};

	TInt iNumChunks;
	SChunkInfo iChunks[KMaxChunksInProcess];
	TInt iNumMovingChunks;
	TInt iNumNonFixedAccessChunks;
	TInt iNumNonFixedAccessCodeChunks;
	DMemModelChunk* iDllDataChunk;
public:
	friend class Monitor;
	};


/********************************************
 * Chunk Control Block
 ********************************************/
/**
@internalComponent
*/
class DMemModelChunk : public DChunk
	{
public:
	/**
	@see DChunk::TChunkAttributes for generic attribute flags
	*/
	enum TMemModelChunkAttributes
		{
		EFixedAccess	=0x80000000,
		EFixedAddress	=0x40000000,
		EPrivate		=0x10000000,
		ECode			=0x08000000,

		EMMChunkAttributesMask = EFixedAccess | EFixedAddress | EPrivate | ECode,
		};

	enum TChunkState {ENotRunning=0, ERunningRO=1, ERunningRW=2};
public:
	DMemModelChunk();
	void Destruct();
public:
	virtual TInt Close(TAny* aPtr);
	virtual TInt DoCreate(SChunkCreateInfo& anInfo);
	virtual TInt Adjust(TInt aNewSize);
	virtual TInt AdjustDoubleEnded(TInt aBottom, TInt aTop);
	virtual TInt CheckAccess();
	virtual TInt Commit(TInt anOffset, TInt aSize, TCommitType aCommitType=DChunk::ECommitDiscontiguous, TUint32* aExtraArg=0);
	virtual TInt Allocate(TInt aSize, TInt aGuard=0, TInt aAlign=0);
	TInt Decommit(TInt anOffset, TInt aSize);
	virtual TInt Lock(TInt anOffset, TInt aSize);
	virtual TInt Unlock(TInt anOffset, 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);
	inline TUint8* Base() const { return DChunk::Base(); }
public:
	TInt Decommit(TInt aOffset, TInt aSize, TDecommitType aDecommitType);
	TInt FindFree(TInt aSize, TInt aGuard, TInt aAlign);
	void SetFixedAddress(TLinAddr anAddr, TInt anInitialSize);
	TInt Reserve(TInt anInitialSize);
	TUint32 ApplyTopLevelPermissions(TChunkState aChunkState);
	TUint32 MoveToRunAddress(TLinAddr aLinearAddr,TChunkState aChunkState);
	TUint32 MoveToHomeSection();
	TZonePageType GetPageType();
protected:
	TInt DoCommit(TInt aOffset, TInt aSize, TCommitType aCommitType=DChunk::ECommitDiscontiguous, TUint32* aExtraArg=0);
	void DoDecommit(TInt aOffset, TInt aSize, TDecommitType aDecommitType=EDecommitNormal);
private:
	void ClaimInitialPages();
	TInt ExpandHomeRegion(TInt anOffset, TInt aSize);
	TLinAddr AllocateHomeAddress(TInt aSize);
	void DeallocateHomeAddress();
	TLinAddr ReallocateHomeAddress(TInt aNewSize);
	TInt DoAllocate(TInt aSize, TInt aGuard, TInt aAlign, TBool aCommit);
private:
	virtual TInt SetupPermissions()=0;
	virtual void AddPde(TInt anOffset)=0;
	virtual void RemovePde(TInt anOffset)=0;
	virtual void MoveHomePdes(TLinAddr anOldAddr, TLinAddr aNewAddr)=0;
	virtual void MoveCurrentPdes(TLinAddr anOldAddr, TLinAddr aNewAddr)=0;
public:
	TChunkState iChunkState;
	TPte iPtePermissions;
	TPde iPdePermissions[3];	// indexed by iChunkState
	TInt iHomeRegionOffset;
	TInt iHomeRegionSize;
	TLinAddr iHomeRegionBase;
	TLinAddr iHomeBase;
	TInt iNumPdes;
	TPde* iPdes;
	TPde* iHomePdes;
	TUint32* iPdeBitMap;
	TBitMapAllocator* iPageBitMap;
	TBitMapAllocator* iPermanentPageBitMap;
public:
	friend class Monitor;
	};


/********************************************
 * Code segment
 ********************************************/

class DMemModelCodeSegMemory : public DMmuCodeSegMemory
	{
public:
	DMemModelCodeSegMemory(DEpocCodeSeg* aCodeSeg);
	~DMemModelCodeSegMemory();
	TInt Create(TCodeSegCreateInfo& aInfo);
	TInt Loaded(TCodeSegCreateInfo& aInfo);
	void Destroy();
	};

/**
@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; }
public:
	TInt iCodeAllocBase;
	TInt iDataAllocBase;
	TAny* iKernelData;			// only for kernel modules
	};


/********************************************
 * MMU stuff
 ********************************************/

typedef void (*TCopyPageFn)(TLinAddr aDest, TLinAddr aSrc);

/**
@internalComponent
*/
class Mmu : public MmuBase
	{
public:
	enum TFlushFlags	{
						EFlushDTLB=0x01,
						EFlushDCache=0x02,
						EFlushITLB=0x04,
						EFlushICache=0x08,
						EFlushDDecommit=0x80000000,
						EFlushDPermChg=0x20000000,		// =DProcess::EVariableAccess
						EFlushDMove=0x40000000,			// =DProcess::EMoving
						EFlushIPermChg=0x04000000,		// =DProcess::EVariableCode
						EFlushIMove=0x10000000,			// =DProcess::EMovingCode
						EFlushInheritMask=EFlushDPermChg|EFlushDMove|EFlushIPermChg|EFlushIMove,
						};

	enum TPanic
		{
		EBadInitialPageAddr,
		EAssignPageTableInvalidUsage,
		EUserCodeAllocatorCreateFailed,
		EDllDataAllocatorCreateFailed,
		ERomUserDataAddressInvalid,
		ERomUserDataSizeInvalid,
		ERomLinearAddressInvalid,
		ERemapPageFailed,
		ERemapPageTableFailed,
		ENoCopyPageFunction,
		EFixupXPTFailed,
		ECacheMaintenance,
		EDefragDisablePageFailed,
		EDefragFaultWhilstFMHeld,
		EDefragKernelChunkNoPageTable,
		};

public:
	inline TPde& PDE(TLinAddr aAddr)
		{return *(((TPde*)iPdeBase)+(aAddr>>iChunkShift));}

	// virtual - inherited/overridden from MmuBase
	virtual void Init1();
//	virtual void Init2();
	virtual void DoInit2();
//	virtual TBool PteIsPresent(TPte aPte)=0;
//	virtual TPhysAddr PtePhysAddr(TPte aPte, TInt aPteIndex)=0;
//	virtual TPhysAddr PdePhysAddr(TLinAddr aAddr)=0;
	virtual void SetupInitialPageInfo(SPageInfo* aPageInfo, TLinAddr aChunkAddr, TInt aPdeIndex);
	virtual void SetupInitialPageTableInfo(TInt aId, TLinAddr aChunkAddr, TInt aNumPtes);
	virtual void AssignPageTable(TInt aId, TInt aUsage, TAny* aObject, TLinAddr aAddr, TPde aPdePerm);
	virtual TInt UnassignPageTable(TLinAddr aAddr);
//	virtual void BootstrapPageTable(TInt aXptId, TPhysAddr aXptPhys, TInt aId, TPhysAddr aPhysAddr)=0;
	virtual TInt PageTableId(TLinAddr aAddr);
//	virtual TInt BootPageTableId(TLinAddr aAddr, TPhysAddr& aPtPhys)=0;
//	virtual void ClearPageTable(TInt aId, TInt aFirstIndex=0)=0;
//	virtual TPhysAddr LinearToPhysical(TLinAddr aAddr)=0;
//	virtual TInt LinearToPhysical(TLinAddr aAddr, TInt aSize, TPhysAddr& aPhysicalAddress, TPhysAddr* aPhysicalPageList=NULL)=0;
//	virtual void MapRamPages(TInt aId, SPageInfo::TType aType, TAny* aPtr, TUint32 aOffset, const TPhysAddr* aPageList, TInt aNumPages, TPte aPtePerm)=0;
//	virtual void MapPhysicalPages(TInt aId, SPageInfo::TType aType, TAny* aPtr, TUint32 aOffset, TPhysAddr aPhysAddr, TInt aNumPages, TPte aPtePerm)=0;
//	virtual TInt UnmapPages(TInt aId, TUint32 aAddr, TInt aNumPages, TPhysAddr* aPageList, TBool aSetPagesFree, TInt& aNumPtes, TInt& aNumFree, DProcess* aProcess)=0;
//	virtual void ClearRamDrive(TLinAddr aStart)=0;
//	virtual TInt PdePtePermissions(TUint& aMapAttr, TPde& aPde, TPte& aPte)=0;
//	virtual void Map(TLinAddr aLinAddr, TPhysAddr aPhysAddr, TInt aSize, TPde aPdePerm, TPte aPtePerm, TInt aMapShift)=0;
//	virtual void Unmap(TLinAddr aLinAddr, TInt aSize)=0;
//	virtual void InitShadowPageTable(TInt aId, TLinAddr aRomAddr, TPhysAddr aOrigPhys)=0;
//	virtual void InitShadowPage(TPhysAddr aShadowPhys, TLinAddr aRomAddr)=0;
//	virtual void DoUnmapShadowPage(TInt aId, TLinAddr aRomAddr, TPhysAddr aOrigPhys)=0;
//	virtual TInt UnassignShadowPageTable(TLinAddr aRomAddr, TPhysAddr aOrigPhys)=0;
//	virtual void DoFreezeShadowPage(TInt aId, TLinAddr aRomAddr)=0;
//	virtual void FlushShadow(TLinAddr aRomAddr)=0;
//	virtual void AssignShadowPageTable(TInt aId, TLinAddr aRomAddr)=0;
//	virtual void ClearPages(TInt aNumPages, TPhysAddr* aPageList)=0;
	virtual TPte PtePermissions(TChunkType aChunkType)=0;
	virtual TInt MoveKernelPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest);
	virtual TInt MoveCodeSegMemoryPage(DMemModelCodeSegMemory* aCodeSegMemory, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest);
	virtual TInt MoveCodeChunkPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest);
	virtual TInt MoveDataChunkPage(DChunk* aChunk, TUint32 aOffset, TPhysAddr aOld, TPhysAddr& aNew, TUint aBlockZoneId, TBool aBlockRest);

	// pure virtual - new in Mmu
	virtual void DoAssignPageTable(TInt aId, TLinAddr aAddr, TPde aPdePerm)=0;
	virtual void RemapPageTable(TPhysAddr aOld, TPhysAddr aNewId, TLinAddr aAddr)=0;
	virtual void DoUnassignPageTable(TLinAddr aAddr)=0;
	virtual void MoveChunk(TLinAddr anInitAddr, TUint aSize, TLinAddr aFinalAddr, TPde aPermissions)=0;
	virtual void MoveChunk(TLinAddr anInitAddr, TLinAddr aFinalAddr, TInt aNumPdes)=0;
	virtual void ApplyTopLevelPermissions(TLinAddr anAddr, TUint aChunkSize, TPde aPermissions)=0;
	virtual void ApplyPagePermissions(TInt aId, TInt aPageOffset, TInt aNumPages, TPte aPtePerm)=0;
	virtual void SyncCodeMappings()=0;
	virtual void GenericFlush(TUint32 aMask)=0;
	virtual TPde PdePermissions(TChunkType aChunkType, TInt aChunkState)=0;
	virtual TInt UnlockRamCachePages(TUint8* volatile & aBase, TInt aFirstPage, TInt aNumPages)=0;
	virtual TInt LockRamCachePages(TUint8* volatile & aBase, TInt aFirstPage, TInt aNumPages)=0;
	virtual void MapVirtual(TInt aId, TInt aNumPages)=0;
	virtual TInt UnmapVirtual(TInt aId, TUint32 aAddr, TInt aNumPages, TPhysAddr* aPageList, TBool aSetPagesFree, TInt& aNumPtes, TInt& aNumFree, DProcess* aProcess)=0;
	virtual TLinAddr MapTemp(TPhysAddr aPage, TBool aCached)=0;
	virtual TLinAddr MapSecondTemp(TPhysAddr aPage, TBool aCached)=0;
	virtual void UnmapTemp()=0;
	virtual void UnmapSecondTemp()=0;
	virtual void RemapKernelPage(TInt aId, TLinAddr aSrc, TLinAddr aDest, TPhysAddr aNewPhys, TPte aPtePerm)=0;
	virtual TInt PreparePagesForDMA(TLinAddr aAddr, TInt aSize, TPhysAddr* aPhysicalPageList)=0;
	virtual TInt ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount)=0;
	
public:
	TInt GetPageTableId(TLinAddr aAddr);
public:
	inline static Mmu& Get()
		{return *(Mmu*)TheMmu;}
	inline void CopyPageForRemap(TLinAddr aDest, TLinAddr aSrc)
		{iCopyPageFn(aDest, aSrc);}
	static void Panic(TPanic aPanic);
public:
	TLinAddr iDataSectionBase;		// lowest data section address
	TLinAddr iDllDataBase;			// start of DLL static data area
	TLinAddr iDataSectionEnd;		// highest data section address + 1
	TInt iMaxDllDataSize;
	TLinAddr iUserCodeBase;
	TInt iMaxUserCodeSize;
	TLinAddr iKernelCodeBase;
	TInt iMaxKernelCodeSize;
	TLinAddr iPdeBase;
	TPte iUserCodeLoadPtePerm;
	TPte iKernelCodePtePerm;
	TUint32* iHomePdeMap;
	TCopyPageFn iCopyPageFn;
	TPte* iSecondTempPte;		// second PTE used for temporary mappings
	TLinAddr iSecondTempAddr;	// address corresponding to iSecondTempPte
	};


/********************************************
 * Functions/Data defined in memory model
 ********************************************/

/**
@internalComponent
*/
class MM
	{
public:
	enum TMemModelPanic
		{
		EUserCodeNotFixed=0,
		EClaimInitialPagesBadPageTable=1,
		EFreeInvalidDomain=2,
		EFreeDomainNotAllocated=3,
		EFixedChunkMoving=4,
		EChunkDecommitNoPageTable=5,
		ECommitInvalidDllDataAddress=6,
		EDecommitInvalidDllDataAddress=7,
		EPdeAlreadyInUse=8,
		EPteAlreadyInUse=9,
		EMmuMapNoPageTable=10,
		EUnmapBadAlignment=11,
		EBootstrapPageTableBadAddr=12,
		EAddFixedBadPerm=13,
		ERemoveFixedBadPerm=14,
		EUnexpectedPageType=15,
		EOperationNotImplemented=16,
		ECodeAddressOutOfRange=17,
		ETempMappingAlreadyInUse=18,
		EChunkRemapNoPageTable=19,
		EChunkRemapWrongPageTable=20,
		};

	static void Panic(TMemModelPanic aPanic);
public:
	static void Init1();
	static TAny* CurrentAddress(DThread* aThread, const TAny* aAddress, TInt aSize, TBool aWrite);
	static void StartCrashDebugger();
	static TInt CreateCodeChunk(TBool aKernel);
public:
	static TInt MaxPagesInOneGo;
	static DMemModelChunk* SvStackChunk;
	static DMemModelChunk* TheRamDriveChunk;
	static DMemModelChunk* UserCodeChunk;
	static DMemModelChunk* KernelCodeChunk;
	static TBitMapAllocator* DllDataAllocator;
	};

#endif