diff -r 000000000000 -r a41df078684a kernel/eka/memmodel/epoc/direct/mutils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/memmodel/epoc/direct/mutils.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,674 @@ +// 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: +// eka\memmodel\epoc\direct\mutils.cpp +// +// + +#include +#include "execs.h" +#include "cache_maintenance.h" +#include + +#ifdef BTRACE_KERNEL_MEMORY +TInt Epoc::DriverAllocdPhysRam = 0; +#endif + +void RHeapK::Mutate(TInt aOffset, TInt aMaxLength) +// +// Used by the kernel to mutate a fixed heap into a chunk heap. +// + { + (void)aOffset; + (void)aMaxLength; + } + +void MM::Panic(MM::TMemModelPanic aPanic) + { + Kern::Fault("MemModel", aPanic); + } + +TInt M::PageSizeInBytes() + { + return MM::RamBlockSize; + } + +EXPORT_C TUint32 Kern::RoundToPageSize(TUint32 aSize) + { + return MM::RoundToBlockSize(aSize); + } + +EXPORT_C TUint32 Kern::RoundToChunkSize(TUint32 aSize) + { + return MM::RoundToBlockSize(aSize); + } + + +/** +Allows the variant/BSP to specify the details of the RAM zones. +This should to be invoked by the variant in its implementation of +the pure virtual function Asic::Init1(). + +There are some limitations to the how RAM zones can be specified: +- Each RAM zone's address space must be distinct and not overlap with any +other RAM zone's address space +- Each RAM zone's address space must have a size that is multiples of the +ASIC's MMU small page size and be aligned to the ASIC's MMU small page size, +usually 4KB on ARM MMUs. +- When taken together all of the RAM zones must cover the whole of the physical RAM +address space as specified by the bootstrap in the SuperPage members iTotalRamSize +and iRamBootData;. +- There can be no more than KMaxRamZones RAM zones specified by the base port + +Note the verification of the RAM zone data is not performed here but by the ram +allocator later in the boot up sequence. This is because it is only possible to +verify the zone data once the physical RAM configuration has been read from +the super page. Any verification errors will result in a "RAM-ALLOC" panic +faulting the kernel during initialisation. + +@param aZones Pointer to an array of SRamZone structs containing each zone's details +The end of the array is specified by an element with iSize==0. The array must +remain in memory at least until the kernel has successfully booted. + +@param aCallback Pointer to call back function that kernel may invoke to request +one of the opeartions specified from enum TRamZoneOp is performed + +@return KErrNone if successful, otherwise one of the system wide error codes +*/ +EXPORT_C TInt Epoc::SetRamZoneConfig(const SRamZone* /*aZones*/, TRamZoneCallback /*aCallback*/) + {// RAM zones not supported for this memory model + return KErrNotSupported; + } + + +/** +Gets the current count of a paricular RAM zone's free and allocated pages. + +@param aId The ID of the RAM zone to enquire about +@param aPageData If successful, on return this will contain the page counts + +@return KErrNone if successful, KErrArgument if a RAM zone of aId is not found or +one of the system wide error codes +*/ +EXPORT_C TInt Epoc::GetRamZonePageCount(TUint /*aId*/, SRamZonePageCount& /*aPageData*/) + {// RAM zones not supported for this memory model + return KErrNotSupported; + } + +/** +Modify the specified RAM zone's flags. + +This allows the BSP or device driver to configure which type of pages, if any, +can be allocated into a RAM zone by the system. + +Note updating a RAM zone's flags can result in + 1 - memory allocations failing despite there being enough free RAM in the system. + 2 - the methods TRamDefragRequest::EmptyRamZone(), TRamDefragRequest::ClaimRamZone() + or TRamDefragRequest::DefragRam() never succeeding. + +The flag masks KRamZoneFlagDiscardOnly, KRamZoneFlagMovAndDisOnly and KRamZoneFlagNoAlloc +are intended to be used with this method. + + +@param aId The ID of the RAM zone to modify. +@param aClearFlags The bit flags to clear, each of which must already be set on the RAM zone. +@param aSetFlags The bit flags to set. + +@return KErrNone on success, KErrArgument if the RAM zone of aId not found +or if any of aClearFlags are not already set. +*/ +EXPORT_C TInt Epoc::ModifyRamZoneFlags(TUint /*aId*/, TUint /*aClearMask*/, TUint /*aSetMask*/) + {// RAM zone not supported for this memory model + return KErrNotSupported; + } + +/** + @pre Call in a thread context. + @pre Interrupts must be enabled. + @pre Kernel must be unlocked. + @pre No fast mutex can be held. + @pre Calling thread must be in a critical section. + */ +EXPORT_C TInt Epoc::AllocShadowPage(TLinAddr aRomAddr) + { + CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::AllocShadowPage"); + return KErrNotSupported; + } + +/** + @pre Call in a thread context. + @pre Interrupts must be enabled. + @pre Kernel must be unlocked. + @pre No fast mutex can be held. + @pre Calling thread must be in a critical section. + */ +EXPORT_C TInt Epoc::FreeShadowPage(TLinAddr aRomAddr) + { + CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::FreeShadowPage"); + return KErrNotSupported; + } + +/** +@pre Calling thread must be in a critical section. +@pre Interrupts must be enabled. +@pre Kernel must be unlocked. +@pre No fast mutex can be held. +@pre Call in a thread context. +*/ +EXPORT_C TInt Epoc::CopyToShadowMemory(TLinAddr /*aDest*/, TLinAddr /*aSrc*/, TUint32 /*aLength*/) + { + CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::CopyToShadowPage"); + return KErrNotSupported; + } + +/** + @pre Call in a thread context. + @pre Interrupts must be enabled. + @pre Kernel must be unlocked. + @pre No fast mutex can be held. + @pre Calling thread must be in a critical section. + */ +EXPORT_C TInt Epoc::FreezeShadowPage(TLinAddr aRomAddr) + { + CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::FreezeShadowPage"); + return KErrNotSupported; + } + +/** + @pre Call in a thread context. + @pre Interrupts must be enabled. + @pre Kernel must be unlocked. + @pre No fast mutex can be held. + @pre Calling thread must be in a critical section. + */ +EXPORT_C TInt Epoc::AllocPhysicalRam(TInt aSize, TPhysAddr& aPhysAddr, TInt aAlign) + { + CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::AllocPhysicalRam"); + MM::WaitRamAlloc(); + TLinAddr lin; + TInt r=MM::AllocContiguousRegion(lin, aSize, aAlign); + if (r!=KErrNone) + MM::AllocFailed=ETrue; + else + { + aPhysAddr = LinearToPhysical(lin); +#if defined(__CPU_HAS_CACHE) && !defined(__CPU_X86) + CacheMaintenance::MemoryToReuse(lin, aSize); +#endif +#ifdef BTRACE_KERNEL_MEMORY + TUint size = Kern::RoundToPageSize(aSize); + BTrace8(BTrace::EKernelMemory, BTrace::EKernelMemoryDrvPhysAlloc, size, aPhysAddr); + Epoc::DriverAllocdPhysRam += size; +#endif + } + MM::SignalRamAlloc(); + return r; + } + +/** + @pre Call in a thread context. + @pre Interrupts must be enabled. + @pre Kernel must be unlocked. + @pre No fast mutex can be held. + @pre Calling thread must be in a critical section. + */ +EXPORT_C TInt Epoc::FreePhysicalRam(TPhysAddr aPhysAddr, TInt aSize) + { + CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"Epoc::FreePhysicalRam"); + MM::WaitRamAlloc(); +#ifndef __CPU_HAS_MMU + MM::FreeRegion(aPhysAddr, aSize); +#else + TInt bn = MM::BlockNumber(aPhysAddr); + TInt bn0 = MM::BlockNumber(MM::UserDataSectionBase); + TLinAddr lin = TLinAddr((bn - bn0)<iHoldCount==1) + { + MM::InitialFreeMemory=Kern::FreeRamInBytes(); + MM::AllocFailed=EFalse; + } + } + +void MM::SignalRamAlloc() + { + if (RamAllocatorMutex->iHoldCount>1) + { + Kern::MutexSignal(*RamAllocatorMutex); + return; + } + TInt initial=MM::InitialFreeMemory; + TBool failed=MM::AllocFailed; + TInt final=Kern::FreeRamInBytes(); + Kern::MutexSignal(*RamAllocatorMutex); + K::CheckFreeMemoryLevel(initial,final,failed); + } + +EXPORT_C TInt TInternalRamDrive::MaxSize() + { + return PP::RamDriveMaxSize; + } + +void M::FsRegisterThread() + { + } + +void M::BTracePrime(TUint aCategory) + { + (void)aCategory; +#ifdef BTRACE_KERNEL_MEMORY + // Must check for -1 as that is the default value of aCategory for + // BTrace::Prime() which is intended to prime all categories that are + // currently enabled via a single invocation of BTrace::Prime(). + if(aCategory==BTrace::EKernelMemory || (TInt)aCategory == -1) + { + BTrace4(BTrace::EKernelMemory,BTrace::EKernelMemoryInitialFree,TheSuperPage().iTotalRamSize); + BTrace4(BTrace::EKernelMemory,BTrace::EKernelMemoryCurrentFree,Kern::FreeRamInBytes()); + BTrace8(BTrace::EKernelMemory,BTrace::EKernelMemoryDrvPhysAlloc, Epoc::DriverAllocdPhysRam, -1); + } +#endif + } + +EXPORT_C DDemandPagingLock::DDemandPagingLock() + : iLockedPageCount(0) + { + } + +EXPORT_C TInt DDemandPagingLock::Alloc(TInt /*aSize*/) + { + return KErrNone; + } + +EXPORT_C TBool DDemandPagingLock::Lock(DThread* /*aThread*/, TLinAddr /*aStart*/, TInt /*aSize*/) + { + return EFalse; + } + +EXPORT_C void DDemandPagingLock::DoUnlock() + { + } + +EXPORT_C void DDemandPagingLock::Free() + { + } + +EXPORT_C TInt Kern::InstallPagingDevice(DPagingDevice* aDevice) + { + return KErrNotSupported; + } + +// Dummy implementation of kernel pin APIs + +class TVirtualPinObject + { + }; + +TInt M::CreateVirtualPinObject(TVirtualPinObject*& aPinObject) + { + aPinObject = new TVirtualPinObject; + return aPinObject != NULL ? KErrNone : KErrNoMemory; + } + +TInt M::PinVirtualMemory(TVirtualPinObject* aPinObject, TLinAddr, TUint, DThread*) + { + __ASSERT_DEBUG(aPinObject, K::Fault(K::EVirtualPinObjectBad)); + (void)aPinObject; + return KErrNone; + } + +TInt M::CreateAndPinVirtualMemory(TVirtualPinObject*& aPinObject, TLinAddr, TUint) + { + aPinObject = 0; + return KErrNone; + } + +void M::UnpinVirtualMemory(TVirtualPinObject* aPinObject) + { + __ASSERT_DEBUG(aPinObject, K::Fault(K::EVirtualPinObjectBad)); + (void)aPinObject; + } + +void M::DestroyVirtualPinObject(TVirtualPinObject*& aPinObject) + { + TVirtualPinObject* object = (TVirtualPinObject*)__e32_atomic_swp_ord_ptr(&aPinObject, 0); + if (object) + Kern::AsyncFree(object); + } + +TInt M::CreatePhysicalPinObject(TPhysicalPinObject*& aPinObject) + { + return KErrNotSupported; + } + +TInt M::PinPhysicalMemory(TPhysicalPinObject*, TLinAddr, TUint, TBool, TPhysAddr& , TPhysAddr*, TUint32&, TUint&, DThread*) + { + K::Fault(K::EPhysicalPinObjectBad); + return KErrNone; + } + +void M::UnpinPhysicalMemory(TPhysicalPinObject* aPinObject) + { + K::Fault(K::EPhysicalPinObjectBad); + } + +void M::DestroyPhysicalPinObject(TPhysicalPinObject*& aPinObject) + { + K::Fault(K::EPhysicalPinObjectBad); + } + +// Misc DPagingDevice methods + +EXPORT_C void DPagingDevice::NotifyIdle() + { + // Not used on this memory model + } + +EXPORT_C void DPagingDevice::NotifyBusy() + { + // Not used on this memory model + } + +EXPORT_C TInt Cache::SyncPhysicalMemoryBeforeDmaWrite(TPhysAddr* , TUint , TUint , TUint , TUint32 ) + { + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"Cache::SyncPhysicalMemoryBeforeDmaWrite"); + return KErrNotSupported; + } + +EXPORT_C TInt Cache::SyncPhysicalMemoryBeforeDmaRead(TPhysAddr* , TUint , TUint , TUint , TUint32 ) + { + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"Cache::SyncPhysicalMemoryBeforeDmaRead"); + return KErrNotSupported; + } +EXPORT_C TInt Cache::SyncPhysicalMemoryAfterDmaRead(TPhysAddr* , TUint , TUint , TUint , TUint32 ) + { + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"Cache::SyncPhysicalMemoryAfterDmaRead"); + return KErrNotSupported; + }