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