diff -r 0bf4040442f9 -r 46fffbe7b5a7 kernel/eka/memmodel/epoc/flexible/mmu/mmu.cpp --- a/kernel/eka/memmodel/epoc/flexible/mmu/mmu.cpp Fri Jan 22 11:03:55 2010 +0200 +++ b/kernel/eka/memmodel/epoc/flexible/mmu/mmu.cpp Tue Jan 26 13:13:38 2010 +0200 @@ -733,8 +733,6 @@ if(mapping) { - // Pinning mappings should not be found from within an address space. - __NK_ASSERT_DEBUG(!mapping->IsPinned()); MmuLock::Lock(); // check if we need to process page fault... @@ -747,6 +745,10 @@ } else { + // Should not be able to take a fault on a pinned mapping if accessing it + // with the correct permissions. + __NK_ASSERT_DEBUG(!mapping->IsPinned()); + // we do need to handle fault so is this a demand paging or page moving fault DMemoryObject* memory = mapping->Memory(); if(!memory) @@ -2161,7 +2163,7 @@ TInt M::PinVirtualMemory(TVirtualPinObject* aPinObject, TLinAddr aStart, TUint aSize, DThread* aThread) { - NKern::ThreadEnterCS(); + __ASSERT_CRITICAL; TUint offsetInMapping; TUint mapInstanceCount; DMemoryMapping* mapping = MM::FindMappingInThread( (DMemModelThread*)aThread, @@ -2205,16 +2207,14 @@ } } mapping->Close(); - } - NKern::ThreadLeaveCS(); - + } return r; } TInt M::CreateAndPinVirtualMemory(TVirtualPinObject*& aPinObject, TLinAddr aStart, TUint aSize) { + __ASSERT_CRITICAL; aPinObject = 0; - NKern::ThreadEnterCS(); TUint offsetInMapping; TUint mapInstanceCount; DMemoryMapping* mapping = MM::FindMappingInThread( (DMemModelThread*)&Kern::CurrentThread(), @@ -2264,9 +2264,7 @@ } } mapping->Close(); - } - NKern::ThreadLeaveCS(); - + } return r; } @@ -2288,20 +2286,20 @@ } } +// +// Physical pinning +// + TInt M::CreatePhysicalPinObject(TPhysicalPinObject*& aPinObject) { aPinObject = (TPhysicalPinObject*)new DPhysicalPinMapping; return aPinObject != NULL ? KErrNone : KErrNoMemory; } -// -// Physical pinning -// - TInt M::PinPhysicalMemory(TPhysicalPinObject* aPinObject, TLinAddr aStart, TUint aSize, TBool aReadOnly, TPhysAddr& aAddress, TPhysAddr* aPages, TUint32& aMapAttr, TUint& aColour, DThread* aThread) { - NKern::ThreadEnterCS(); + __ASSERT_CRITICAL; TUint offsetInMapping; TUint mapInstanceCount; DMemoryMapping* mapping = MM::FindMappingInThread( (DMemModelThread*)aThread, @@ -2345,7 +2343,6 @@ } mapping->Close(); } - NKern::ThreadLeaveCS(); aColour = (aStart >>KPageShift) & KPageColourMask; return r; } @@ -2369,6 +2366,111 @@ } +// +// Kernel map and pin. +// + +TInt M::CreateKernelMapObject(TKernelMapObject*& aMapObject, TUint aMaxReserveSize) + { + DKernelPinMapping* pinObject = new DKernelPinMapping(); + aMapObject = (TKernelMapObject*) pinObject; + if (pinObject == NULL) + { + return KErrNoMemory; + } + // Ensure we reserve enough bytes for all possible alignments of the start and + // end of the region to map. + TUint reserveBytes = aMaxReserveSize? ((aMaxReserveSize + KPageMask) & ~KPageMask) + KPageSize : 0; + TInt r = pinObject->Construct(reserveBytes); + if (r != KErrNone) + {// Failed so delete the kernel mapping object. + pinObject->Close(); + aMapObject = NULL; + } + return r; + } + + +TInt M::MapAndPinMemory(TKernelMapObject* aMapObject, DThread* aThread, TLinAddr aStart, + TUint aSize, TUint aMapAttributes, TLinAddr& aKernelAddr, TPhysAddr* aPages) + { + __ASSERT_CRITICAL; + TUint offsetInMapping; + TUint mapInstanceCount; + DMemoryMapping* mapping = MM::FindMappingInThread( (DMemModelThread*)aThread, + aStart, + aSize, + offsetInMapping, + mapInstanceCount); + TInt r = KErrBadDescriptor; + if (mapping) + { + DKernelPinMapping* kernelMap = (DKernelPinMapping*)aMapObject; + TInt count = (((aStart + aSize + KPageMask) & ~KPageMask) - (aStart & ~KPageMask)) >> KPageShift; + if (kernelMap->iReservePages && kernelMap->iReservePages < count) + { + mapping->Close(); + return KErrArgument; + } + + MmuLock::Lock(); + DMemoryObject* memory = mapping->Memory(); + if (mapInstanceCount == mapping->MapInstanceCount() && memory) + { + memory->Open(); + MmuLock::Unlock(); + + TUint startInMemory = (offsetInMapping >> KPageShift) + mapping->iStartIndex; + TBool readOnly = aMapAttributes & Kern::EKernelMap_ReadOnly; + TMappingPermissions permissions = readOnly ? ESupervisorReadOnly : ESupervisorReadWrite; + r = kernelMap->MapAndPin(memory, startInMemory, count, permissions); + if (r == KErrNone) + { + __NK_ASSERT_DEBUG(!kernelMap->IsUserMapping()); + aKernelAddr = kernelMap->Base(); + TPhysAddr contigAddr; // Ignore this value as aPages will be populated + // whether the memory is contiguous or not. + r = kernelMap->PhysAddr(0, count, contigAddr, aPages); + if (r>=KErrNone) + { + r = KErrNone; //Do not report discontiguous memory in return value. + } + else + { + UnmapAndUnpinMemory((TKernelMapObject*)kernelMap); + } + } + memory->Close(); + } + else // mapping has been reused or no memory... + { + MmuLock::Unlock(); + } + mapping->Close(); + } + return r; + } + + +void M::UnmapAndUnpinMemory(TKernelMapObject* aMapObject) + { + DKernelPinMapping* mapping = (DKernelPinMapping*)aMapObject; + if (mapping->IsAttached()) + mapping->UnmapAndUnpin(); + } + + +void M::DestroyKernelMapObject(TKernelMapObject*& aMapObject) + { + DKernelPinMapping* mapping = (DKernelPinMapping*)__e32_atomic_swp_ord_ptr(&aMapObject, 0); + if (mapping) + { + if (mapping->IsAttached()) + mapping->UnmapAndUnpin(); + mapping->AsyncClose(); + } + } + // // Cache sync operations