kernel/eka/memmodel/epoc/flexible/mkernel.cpp
changeset 43 96e5fb8b040d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/memmodel/epoc/flexible/mkernel.cpp	Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,223 @@
+// Copyright (c) 1994-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:
+//
+
+#include <memmodel.h>
+#include "mmu/mm.h"
+#include "mmboot.h"
+
+
+/********************************************
+ * Thread
+ ********************************************/
+
+TInt DThread::AllocateSupervisorStack()
+	{
+	__KTRACE_OPT(KTHREAD,Kern::Printf("DThread::AllocateSupervisorStack %O %x",this,iSupervisorStackSize));
+	iSupervisorStackSize = MM::RoundToPageSize(iSupervisorStackSize);
+	if(iThreadType==EThreadInitial)
+		return KErrNone;
+
+	TUint guardSize = PP::SupervisorThreadStackGuard;
+	TUint virtualSize = guardSize+iSupervisorStackSize;
+	DMemoryObject* memory;
+	TInt r = MM::MemoryNew(memory,EMemoryObjectUnpaged,MM::BytesToPages(virtualSize));
+	if(r==KErrNone)
+		{
+		r = MM::MemoryAlloc(memory,MM::BytesToPages(guardSize),MM::BytesToPages(iSupervisorStackSize));
+		if(r==KErrNone)
+			{
+			DMemoryMapping* mapping;
+			r = MM::MappingNew(mapping,memory,ESupervisorReadWrite,KKernelOsAsid);
+			if(r==KErrNone)
+				{
+				__NK_ASSERT_DEBUG(!((DMemModelThread*)this)->iKernelStackMapping);
+				((DMemModelThread*)this)->iKernelStackMapping = mapping;
+				iSupervisorStack = (TAny*)(MM::MappingBase(mapping)+guardSize);
+				__KTRACE_OPT(KTHREAD,Kern::Printf("Supervisor stack at %x, size %x",iSupervisorStack,iSupervisorStackSize));
+				}
+			}
+		if(r!=KErrNone)
+			MM::MemoryDestroy(memory);
+		else
+			{
+#ifdef BTRACE_FLEXIBLE_MEM_MODEL
+			BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsSupervisorStack,memory,&iNThread);
+#endif
+			}
+		}
+	return r;
+	}
+
+
+void DThread::FreeSupervisorStack()
+	{
+	__KTRACE_OPT(KTHREAD,Kern::Printf("DThread::FreeSupervisorStack %O",this));
+	if(iThreadType==EThreadInitial) // !!!???
+		return;
+	MM::MappingAndMemoryDestroy(((DMemModelThread*)this)->iKernelStackMapping);
+	}
+
+
+TInt DThread::AllocateUserStack(TInt aSize, TBool aPaged)
+	{
+	__KTRACE_OPT(KTHREAD,Kern::Printf("DThread::AllocateUserStack %O %x",this,aSize));
+	aSize = MM::RoundToPageSize(aSize);
+	if(aSize>PP::MaxUserThreadStack)
+		return KErrTooBig;
+
+	TMemoryObjectType memoryType = (aPaged)? EMemoryObjectPaged : EMemoryObjectMovable;
+	TUint guardSize = PP::UserThreadStackGuard;
+	TUint virtualSize = guardSize+aSize;
+	// wipe user thread stack with 0x29292929
+	TMemoryCreateFlags flags = (TMemoryCreateFlags)(EMemoryCreateDefault | EMemoryCreateUseCustomWipeByte | (0x29 << EMemoryCreateWipeByteShift));
+	DMemoryObject* memory;
+	TInt r = MM::MemoryNew(memory, memoryType, MM::BytesToPages(virtualSize),flags);
+	if(r==KErrNone)
+		{
+		r = MM::MemoryAlloc(memory,MM::BytesToPages(guardSize),MM::BytesToPages(aSize));
+		if(r==KErrNone)
+			{
+			DMemoryMapping* mapping;
+			// Get os asid, no need to open a reference as this only invoked where 
+			// the current thread is owned by iOwningProcess, iOwningProcess is 
+			// the kernel process or this is the first thread of a process that 
+			// isn't fully created yet.
+			TUint osAsid = ((DMemModelProcess*)iOwningProcess)->OsAsid();
+			r = MM::MappingNew(mapping,memory,EUserReadWrite,osAsid);
+			if(r==KErrNone)
+				{
+				__NK_ASSERT_DEBUG(!((DMemModelThread*)this)->iUserStackMapping);
+				((DMemModelThread*)this)->iUserStackMapping = mapping;
+				iUserStackSize = aSize;
+				iUserStackRunAddress = MM::MappingBase(mapping)+guardSize;
+				__KTRACE_OPT(KTHREAD,Kern::Printf("User stack at %x, size %x",iUserStackRunAddress,iUserStackSize));
+				}
+			}
+		if(r!=KErrNone)
+			MM::MemoryDestroy(memory);
+		else
+			{
+#ifdef BTRACE_FLEXIBLE_MEM_MODEL
+			BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsUserStack,memory,&iNThread);
+#endif
+			}
+		}
+	return r;
+	}
+
+
+void DThread::FreeUserStack()
+	{
+	__KTRACE_OPT(KTHREAD,Kern::Printf("DThread::FreeUserStack %O",this));
+	MM::MappingAndMemoryDestroy(((DMemModelThread*)this)->iUserStackMapping);
+	}
+
+
+void DMemModelThread::SetPaging(TUint& aCreateFlags)
+	{
+	TUint pagingAtt = aCreateFlags & EThreadCreateFlagPagingMask;
+	TUint dataPolicy = TheSuperPage().KernelConfigFlags() & EKernelConfigDataPagingPolicyMask;
+	if (dataPolicy == EKernelConfigDataPagingPolicyNoPaging ||
+		!(K::MemModelAttributes & EMemModelAttrDataPaging))
+		{// No paging policy set or no data paging device installed.
+		pagingAtt = EThreadCreateFlagUnpaged;
+		}
+	else if (dataPolicy == EKernelConfigDataPagingPolicyAlwaysPage)
+		{
+		pagingAtt = EThreadCreateFlagPaged;
+		}
+	else if (pagingAtt == EThreadCreateFlagPagingUnspec)
+		{// No data paging attribute specified for this chunk so use the process's.
+		if (iOwningProcess->iAttributes & DProcess::EDataPaged)
+			pagingAtt = EThreadCreateFlagPaged;
+		else
+			pagingAtt = EThreadCreateFlagUnpaged;
+		}
+#ifdef _DEBUG
+	else
+		{
+		__NK_ASSERT_DEBUG(	pagingAtt == EThreadCreateFlagPaged || 
+							pagingAtt == EThreadCreateFlagUnpaged);
+		}
+#endif
+	// Save the paging attributes for when the stack and heap are created later.
+	aCreateFlags &= ~EThreadCreateFlagPagingMask;
+	aCreateFlags |= pagingAtt;
+	}
+
+
+void DMemModelThread::DoExit1()
+	{
+	// Regularize the thread state before main exit processing.
+	// We must remove any existing alias before we do any operation 
+	// which requires aliasing (e.g. logon completion).
+	__KTRACE_OPT(KTHREAD,Kern::Printf("DMemModelThread %O DoExit1",this));
+	RemoveAlias();
+	}
+
+
+void DThread::IpcExcHandler(TExcTrap* aTrap, DThread* aThread, TAny* aContext)
+	{
+	aThread->iIpcClient = 0;
+	TIpcExcTrap& xt=*(TIpcExcTrap*)aTrap;
+	switch (xt.ExcLocation(aThread, aContext))
+		{
+		case TIpcExcTrap::EExcRemote:
+			// problem accessing remote address - 'leave' so an error code will be returned
+			((DMemModelThread*)aThread)->RemoveAlias();
+			xt.Exception(KErrBadDescriptor);  // does not return
+
+		case TIpcExcTrap::EExcLocal:
+			// problem accessing local address - return and panic current thread as usual
+			((DMemModelThread*)aThread)->RemoveAlias();
+			return;
+
+		default:
+			// otherwise return and fault kernel
+			NKern::LockSystem();
+			return;
+		}
+	}
+
+
+void DMemModelThread::BTracePrime(TInt aCategory)
+	{
+	DThread::BTracePrime(aCategory);
+#ifdef BTRACE_FLEXIBLE_MEM_MODEL
+	if(aCategory==BTrace::EFlexibleMemModel || aCategory==-1)
+		{
+		if (iKernelStackMapping)
+			{
+			DMemoryObject* memory = MM::MappingGetAndOpenMemory(iKernelStackMapping);
+			if (memory)
+				{
+				MM::MemoryBTracePrime(memory);
+				BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsSupervisorStack,memory,&iNThread);
+				MM::MemoryClose(memory);
+				}
+			}
+		if (iUserStackMapping)
+			{
+			DMemoryObject* memory = MM::MappingGetAndOpenMemory(iUserStackMapping);
+			if (memory)
+				{
+				MM::MemoryBTracePrime(memory);
+				BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsUserStack,memory,&iNThread);
+				MM::MemoryClose(memory);
+				}
+			}
+		}
+#endif
+	}