diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32test/mmu/t_pin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/mmu/t_pin.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,753 @@ +// Copyright (c) 2008-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: +// e32test\mmu\t_pin.cpp +// Tests kernel APIs for logical pinning by pinning memory and using a realtime thread to check that +// no page faults are taken while accessing it. +// +// + +#define __E32TEST_EXTENSION__ +#include +#include +#include +#include +#include +#include +#include "d_memorytest.h" +#include "t_codepaging_dll.h" +#include "mmudetect.h" +#include "freeram.h" + +RTest test(_L("T_PIN")); + +_LIT(KTCodePagingDll4, "t_codepaging_dll4.dll"); +const TInt KMinBufferSize = 16384; + +RMemoryTestLdd Ldd; +RMemoryTestLdd Ldd2; +RLibrary PagedLibrary; +const TUint8* PagedBuffer = NULL; +const TUint8* UnpagedBuffer = NULL; +TInt PageSize; + +TInt FreeRamNoWait() + { + TMemoryInfoV1Buf meminfo; + UserHal::MemoryInfo(meminfo); + return meminfo().iFreeRamInBytes; + } + +void CheckMemoryPresent(const TUint8* aBuffer, TInt aSize, TBool aExpected) + { + if (aExpected) + test.Printf(_L(" Checking memory at %08x is present\n"), aBuffer); + else + test.Printf(_L(" Checking memory at %08x is not present\n"), aBuffer); + for (TInt i = 0 ; i < aSize ; i += PageSize) + test_Equal(aExpected, Ldd.IsMemoryPresent(aBuffer + i)); + } + +void FlushPagingCache() + { + test_KErrNone(DPTest::FlushCache()); + } + +void TestPinVirtualMemoryUnpaged() + { + test.Printf(_L("Create logical pin object\n")); + test_KErrNone(Ldd.CreateVirtualPinObject()); +#ifdef __EPOC32__ + CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue); + test.Printf(_L("Perform logical pin operation on zero-length buffer\n")); + test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, 0)); + CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue); + test.Printf(_L("Perform logical unpin operation\n")); + test_KErrNone(Ldd.UnpinVirtualMemory()); + CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue); + test.Printf(_L("Perform logical pin operation on whole buffer\n")); + test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, KMinBufferSize)); + CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue); + test.Printf(_L("Perform logical unpin operation\n")); + test_KErrNone(Ldd.UnpinVirtualMemory()); + CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue); +#else + // Don't check for memory presence on emulator as paging not supported. + test.Printf(_L("Perform logical pin operation on zero-length buffer\n")); + test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, 0)); + test.Printf(_L("Perform logical unpin operation\n")); + test_KErrNone(Ldd.UnpinVirtualMemory()); + test.Printf(_L("Perform logical pin operation on whole buffer\n")); + test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, KMinBufferSize)); + test.Printf(_L("Perform logical unpin operation\n")); + test_KErrNone(Ldd.UnpinVirtualMemory()); +#endif + test.Printf(_L("Perform logical unpin operation (again)\n")); + test_KErrNone(Ldd.UnpinVirtualMemory()); // test double unpin ok + test.Printf(_L("Destroy logical pin object\n")); + test_KErrNone(Ldd.DestroyVirtualPinObject()); + test.Printf(_L("Destroy logical pin object (again)\n")); + test_KErrNone(Ldd.DestroyVirtualPinObject()); // test double destroy ok + } + +void TestPinPhysicalMemory() + { + + TInt mm = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0) & EMemModelTypeMask; + if (mm < EMemModelTypeFlexible) + { + test.Printf(_L("Memory model (%d) doesn't support physical pining\n"),mm); + return; + } + TInt i; + TInt8* UCBase; + RChunk chunk; + + test.Printf(_L("Allocate user chunk\n")); + TChunkCreateInfo createInfo; + createInfo.SetDisconnected(0,UCPageCount*PageSize,UCPageCount*PageSize); + createInfo.SetPaging(TChunkCreateInfo::EPaged); + test_KErrNone(chunk.Create(createInfo)); + UCBase = (TInt8*)chunk.Base(); + + test.Printf(_L("Create physical pin object\n")); + test_KErrNone(Ldd.CreatePhysicalPinObject()); + + test.Printf(_L("Perform physical pin operation on zero-length buffer\n")); + test_KErrNone(Ldd.PinPhysicalMemory((TLinAddr)UCBase, 0)); + + test.Printf(_L("Perform physical unpin operation\n")); + test_KErrNone(Ldd.UnpinPhysicalMemory()); + + test.Printf(_L("Perform Physical pin operation on the chunk\n")); + test_KErrNone(Ldd.PinPhysicalMemory((TLinAddr)UCBase, UCPageCount*PageSize)); + + test.Printf(_L("Test that pinned physical memory preserves its mapping when recommited\n")); + test_KErrNone(chunk.Decommit(0,UCPageCount*PageSize)); //Decommit all + for (i=UCPageCount-1;i>=0;i--) test_KErrNone(chunk.Commit(i*PageSize,PageSize)); //Commit in reverse order + for (i=0;i>32); } +private: + TUint iSeed; + }; + +#define SOAK_CHECK(r) \ + if(r!=KErrNone) \ + { \ + RDebug::Printf("SOAK_CHECK fail at line %d",__LINE__); \ + return r; \ + } \ + +TInt SoakThread(TAny*) + { + RMemoryTestLdd ldd; + TInt r = ldd.Open(); + SOAK_CHECK(r) + + r = ldd.CreateVirtualPinObject(); + SOAK_CHECK(r) + + TRandom random((TUint32)&ldd); + + while(!SoakEnd) + { + TUint start = random(KMinBufferSize); + TUint end = random(KMinBufferSize); + if(start>end) + { + TUint temp = start; + start = end; + end = temp; + } + const TUint32 KPageMask = 0xfff; + start &= ~KPageMask; + end = (end+KPageMask)&~KPageMask; + + r = ldd.PinVirtualMemory((TLinAddr)(PagedBuffer+start),end-start); + SOAK_CHECK(r) + + r = ldd.UnpinVirtualMemory(); + SOAK_CHECK(r) + } + + r = ldd.DestroyVirtualPinObject(); + SOAK_CHECK(r) + + CLOSE_AND_WAIT(ldd); + return KErrNone; + } + + +void TestPinVirtualMemoryPagedSoak() + { + test.Start(_L("Create timer")); + RTimer timer; + test_KErrNone(timer.CreateLocal()); + + test.Next(_L("Create threads")); + const TUint KNumThreads = 4; + TRequestStatus status[KNumThreads]; + RThread thread[KNumThreads]; + TUint i; + for(i=0; iiPageableRomStart ? romHeader->iPageableRomStart : romHeader->iUncompressedSize; + test(size >= KMinBufferSize); + + if (DPTest::Attributes() & DPTest::ERomPaging) + { + // Use end of paged ROM for our paged buffer + test(romHeader->iPageableRomStart); + TInt offset = romHeader->iPageableRomStart + romHeader->iPageableRomSize - KMinBufferSize; + offset &= ~0xfff; + test(offset>=romHeader->iPageableRomStart); + PagedBuffer = (TUint8*)romHeader + offset; + } + else if (DPTest::Attributes() & DPTest::ECodePaging) + { + // Use code paged DLL for our paged buffer + test_KErrNone(PagedLibrary.Load(KTCodePagingDll4)); + TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)PagedLibrary.Lookup(KGetAddressOfDataFunctionOrdinal); + TInt size; + PagedBuffer = (TUint8*)func(size); + test_NotNull(PagedBuffer); + test(size >= KMinBufferSize); + } +#else + UnpagedBuffer = (TUint8*)User::Alloc(KMinBufferSize); + test_NotNull(UnpagedBuffer); +#endif + + RDebug::Printf("UnpagedBuffer=%x\n",UnpagedBuffer); + RDebug::Printf("PagedBuffer=%x\n",PagedBuffer); + + __KHEAP_MARK; + + test.Next(_L("Logical pin unpaged memory")); + TestPinVirtualMemoryUnpaged(); + + test.Next(_L("Logical pin invalid memory")); + TestPinVirtualMemoryInvalid(); + + test.Next(_L("Physical pinning")); + TestPinPhysicalMemory(); + + test.Next(_L("Physical pinning OOM")); + TestPhysicalPinOutOfMemory(); + + test.Next(_L("Pin OOM Tests")); + TestPinOutOfMemory(); + + if (PagedBuffer) + { + test.Next(_L("Logical pin paged memory")); + TestPinVirtualMemoryPaged(); + + test.Next(_L("Logical pin paged memory soak test")); + TestPinVirtualMemoryPagedSoak(); + } + + if (DPTest::Attributes() & DPTest::EDataPaging) + { + test.Next(_L("Logical pin then decommit memory")); + TestPinVirtualMemoryDecommit(); + } + + // wait for any async cleanup in the supervisor to finish first... + UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0); + __KHEAP_MARKEND; + +#ifndef __EPOC32__ + User::Free((TAny*)UnpagedBuffer); +#endif + + PagedLibrary.Close(); + Ldd.Close(); + Ldd2.Close(); + test.End(); + + return KErrNone; + }