kerneltest/e32test/mmu/t_demandpaging.cpp
changeset 0 a41df078684a
child 117 5b5d147c7838
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\mmu\t_demandpaging.cpp
       
    15 // Functional tests for demand paging. The test suite covers simple
       
    16 // paging operations as well as HAL configuration and tuning functions.
       
    17 // 001.01 DPTest::Attributes
       
    18 // 001.02 DPTest::FlushCache
       
    19 // 001.03 DPTest::CacheSize
       
    20 // 001.04 DPTest::SetCacheSize
       
    21 // 001.04.01 Changing size of flushed VM cache
       
    22 // 001.04.02 Changing size of full VM cache
       
    23 // 002 Loading test drivers
       
    24 // 003 Test thread realtime state
       
    25 // 003.01 Enable KREALTIME tracing
       
    26 // 003.02 Test ERealtimeStateOff
       
    27 // 003.03 Test ERealtimeStateOn
       
    28 // 003.04 Test ERealtimeStateWarn
       
    29 // 003.05 Test server with ERealtimeStateOff
       
    30 // 003.06 Test server with ERealtimeStateOn
       
    31 // 003.07 Test server with ERealtimeStateWarn
       
    32 // 003.08 Disable KREALTIME tracing
       
    33 // 004 Lock Test
       
    34 // 005 Lock Test again
       
    35 // 006 Test writing to paged ROM
       
    36 // 007 Test IPC read from paged memory
       
    37 // 007.01 Create server
       
    38 // 007.02 IPC read from ROM
       
    39 // 007.03 Stop server
       
    40 // 008 Test contiguous RAM allocation reclaims paged memory
       
    41 // 008.01 Start...
       
    42 // 008.02 Contiguous RAM test: alloc size = 128K align = 16
       
    43 // 008.03 Contiguous RAM test: alloc size = 128K align = 0
       
    44 // 008.04 Contiguous RAM test: alloc size = 64K align = 15
       
    45 // 008.05 Contiguous RAM test: alloc size = 64K align = 14
       
    46 // 008.06 Contiguous RAM test: alloc size = 64K align = 13
       
    47 // 008.07 Contiguous RAM test: alloc size = 64K align = 12
       
    48 // 008.08 Contiguous RAM test: alloc size = 64K align = 0
       
    49 // 008.09 Contiguous RAM test: alloc size = 8K align = 13
       
    50 // 008.10 Contiguous RAM test: alloc size = 8K align = 12
       
    51 // 008.11 Contiguous RAM test: alloc size = 8K align = 0
       
    52 // 008.12 Contiguous RAM test: alloc size = 4K align = 13
       
    53 // 008.13 Contiguous RAM test: alloc size = 4K align = 12
       
    54 // 008.14 Contiguous RAM test: alloc size = 4K align = 0
       
    55 // 009 Test no kernel faults when copying data from unpaged rom with mutex held
       
    56 // 010 Close test driver
       
    57 // 011 Test setting publish and subscribe properties from paged area
       
    58 // 012 Rom Paging Benchmark
       
    59 // 012.01 Benchmark ROM paging...
       
    60 // 
       
    61 //
       
    62 
       
    63 //! @SYMTestCaseID			KBASE-T_DEMANDPAGING-0334
       
    64 //! @SYMTestType			UT
       
    65 //! @SYMPREQ				PREQ1110
       
    66 //! @SYMTestCaseDesc		Demand Paging functional tests.
       
    67 //! @SYMTestActions			001 Test HAL interface
       
    68 //! @SYMTestExpectedResults All tests should pass.
       
    69 //! @SYMTestPriority        High
       
    70 //! @SYMTestStatus          Implemented
       
    71 
       
    72 #define __E32TEST_EXTENSION__
       
    73 #include <e32test.h>
       
    74 #include <dptest.h>
       
    75 #include <e32kpan.h>
       
    76 #include <e32property.h>
       
    77 #include <e32rom.h>
       
    78 #include "d_memorytest.h"
       
    79 #include "d_demandpaging.h"
       
    80 #include "d_gobble.h"
       
    81 #include "mmudetect.h"
       
    82 #include "t_codepaging_dll.h"
       
    83 #include "freeram.h"
       
    84 
       
    85 RTest test(_L("T_DEMANDPAGING"));
       
    86 
       
    87 _LIT(KTCodePagingDll4, "t_codepaging_dll4.dll");
       
    88 const TInt KMinBufferSize = 16384;
       
    89 const TInt KMaxIPCSize = 256*1024;
       
    90 
       
    91 TInt PageSize = 0;
       
    92 RDemandPagingTestLdd Ldd;
       
    93 RLibrary PagedLibrary;
       
    94 
       
    95 // A buffer containing paged memory, contents may or may not be paged in
       
    96 const TUint8* LargeBuffer = NULL;
       
    97 TInt LargeBufferSize = 0;
       
    98 
       
    99 // A buffer containing paged memeory, contents always paged out before access
       
   100 const TUint8* SmallBuffer = NULL;
       
   101 TInt SmallBufferSize = 0;
       
   102 
       
   103 // A shared buffer mapped to the global address range
       
   104 TInt SharedBufferSize = KMaxIPCSize+4096;
       
   105 TLinAddr SharedBufferAddr = 0;
       
   106 TUint8* SharedBuffer = NULL;
       
   107 
       
   108 // A descriptor whose header is in paged memory (actually just a pointer to a zero word)
       
   109 TDesC8* PagedHeaderDes = NULL;
       
   110 
       
   111 // A data paged chunk used as a buffer, if data paging is supported
       
   112 _LIT(KChunkName, "t_demandpaging chunk");
       
   113 RChunk DataPagedChunk;
       
   114 TBool DataPagingSupported = EFalse;
       
   115 TUint8* DataPagedBuffer = NULL;
       
   116 
       
   117 TUint8 ReadByte(volatile TUint8* aPtr)
       
   118 	{
       
   119 	return *aPtr;
       
   120 	}
       
   121 
       
   122 #define READ(a) ReadByte((volatile TUint8*)(a))
       
   123 
       
   124 void ThrashPaging(TUint aMaxBytes=KMaxTUint)
       
   125 	{
       
   126 	TUint size = LargeBufferSize;
       
   127 	if(size>aMaxBytes)
       
   128 		size = aMaxBytes;
       
   129 
       
   130 	// read all ROM pages about 10 times each in a random order...
       
   131 	TUint32 random=1;
       
   132 	for(TInt i=size/(PageSize/10); i>0; --i)
       
   133 		{
       
   134 		READ(LargeBuffer+((TInt64(random)*TInt64(size))>>32));
       
   135 		random = random*69069+1;
       
   136 		}
       
   137 	}
       
   138 
       
   139 void FragmentPagingCache(TUint aMaxBytes)
       
   140 	{
       
   141 	DPTest::FlushCache();
       
   142 
       
   143 	TUint size = Min(LargeBufferSize, aMaxBytes);
       
   144 	if(size<aMaxBytes)
       
   145 		test.Printf(_L("WARNING: LargeBuffer not large enough!  Have you built a full test ROM?\n"));
       
   146 
       
   147 	RChunk chunk;
       
   148 	test(KErrNone==chunk.CreateDisconnectedLocal(0,0,size));
       
   149 
       
   150 	TUint32 random = 0;
       
   151 	for(TUint i=0; i<size; i += PageSize)
       
   152 		{
       
   153 		random = random*69069+1;
       
   154 		if(random<0x40000000)
       
   155 			chunk.Commit(i,PageSize); // to make paging cache fragmented
       
   156 		READ(LargeBuffer + i);
       
   157 		}
       
   158 
       
   159 	CLOSE_AND_WAIT(chunk);
       
   160 
       
   161 	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
       
   162 	}
       
   163 
       
   164 
       
   165 void RomPagingBenchmark()
       
   166 	{
       
   167 	TInt r=DPTest::FlushCache();
       
   168 	if(r!=KErrNone)
       
   169 		return;
       
   170 
       
   171 	test.Start(_L("Benchmark ROM paging..."));
       
   172 
       
   173 	// change live list to be a small as possible
       
   174 	test(KErrNone==DPTest::SetCacheSize(1,1));
       
   175 
       
   176 	RTimer timer;
       
   177 	test(KErrNone==timer.CreateLocal());
       
   178 	TRequestStatus status;
       
   179 	timer.After(status,1);
       
   180 	User::WaitForRequest(status);
       
   181 
       
   182 	TPckgBuf<DPTest::TEventInfo> events0;
       
   183 	DPTest::EventInfo(events0);
       
   184 
       
   185 	TInt KRunTime = 10*1000*1000;
       
   186 	timer.After(status,KRunTime);
       
   187 	while(status==KRequestPending)
       
   188 		for(const TUint8* ptr=LargeBuffer; ptr<(LargeBuffer+LargeBufferSize); ptr+=PageSize)
       
   189 			{
       
   190 			READ(ptr);
       
   191 			if(status!=KRequestPending)
       
   192 				break;
       
   193 			}
       
   194 
       
   195 	TPckgBuf<DPTest::TEventInfo> events1;
       
   196 	DPTest::EventInfo(events1);
       
   197 
       
   198 	User::WaitForRequest(status);
       
   199 
       
   200 	TUint pages = events1().iPageInReadCount-events0().iPageInReadCount;
       
   201 	test.Printf(_L("%d pages in %d seconds = %d us/page\n"),pages,KRunTime/1000/1000,KRunTime/pages);
       
   202 
       
   203 	// restore live list to default size...
       
   204 	test(KErrNone==DPTest::SetCacheSize(0,0));
       
   205 
       
   206 	test.End();
       
   207 	}
       
   208 
       
   209 
       
   210 void TestResizeVMCache()
       
   211 	{
       
   212 	TInt r = DPTest::SetCacheSize(0,0); // restore cache size to defaults
       
   213 	test(r==KErrNone);
       
   214 	TUint sizeMin = 0;
       
   215 	TUint sizeMax = 0;
       
   216 	TUint currentSize = 0;
       
   217 	DPTest::CacheSize(sizeMin,sizeMax,currentSize);
       
   218 	TUint originalMin = sizeMin;
       
   219 	TUint originalMax = sizeMax;
       
   220 	test.Printf(_L("original min=%u, original max=%u, current=%u\n"),originalMin/PageSize,originalMax/PageSize,currentSize/PageSize);
       
   221 
       
   222 	int K = currentSize/PageSize+4;
       
   223 
       
   224 	struct
       
   225 		{
       
   226 		TUint iMinPages;
       
   227 		TUint iMaxPages;
       
   228 		TInt iResult;
       
   229 		}
       
   230 	testArgs[] =
       
   231 		{
       
   232 			{	K,		K,		KErrNone},
       
   233 			{	K-4,	K,		KErrNone},
       
   234 			{	K,		K,		KErrNone},
       
   235 			{	K,		K*2,	KErrNone},
       
   236 			{	K,		K,		KErrNone},
       
   237 			{	K-1,	K,		KErrNone},
       
   238 			{	K,		K,		KErrNone},
       
   239 			{	K,		K+1,	KErrNone},
       
   240 			{	K,		K,		KErrNone},
       
   241 			{	K+1,	K,		KErrArgument},
       
   242 			{	K,		K-1,	KErrArgument},
       
   243 			{	KMaxTInt,	KMaxTInt,	KErrNoMemory},
       
   244 			{	K,		K,		KErrNone},
       
   245 
       
   246 			{	0,		0,		KErrNone}, // restore defaults
       
   247 			{	0,		0,		KMaxTInt} // list end marker
       
   248 		};
       
   249 
       
   250 	for(TInt j=0; j<2; ++j)
       
   251 		{
       
   252 		if(!j)
       
   253 			{
       
   254 			test.Start(_L("Changing size of flushed VM cache"));
       
   255 			test.Printf(_L("Original cache size min == %u, max == %u\n"),originalMin/PageSize,originalMax/PageSize);
       
   256 			}
       
   257 		else
       
   258 			test.Next(_L("Changing size of full VM cache"));
       
   259 		TInt i=0;
       
   260 		while(testArgs[i].iResult!=KMaxTInt)
       
   261 			{
       
   262 			TUint min=testArgs[i].iMinPages*PageSize;
       
   263 			TUint max=testArgs[i].iMaxPages*PageSize;
       
   264 			TInt result=testArgs[i].iResult;
       
   265 
       
   266 			ThrashPaging(max*2);
       
   267 			if(!j)
       
   268 				DPTest::FlushCache();
       
   269 
       
   270 			test.Printf(_L("DPTest::SetCacheSize min=%u, max=%u, expected result=%d\n"),min/PageSize,max/PageSize,result);
       
   271 			TInt r=DPTest::SetCacheSize(min,max);
       
   272 			if(r!=result)
       
   273 				{
       
   274 				test.Printf(_L("result=%d\n"),r);
       
   275 				test(0);
       
   276 				}
       
   277 			if(r==KErrNone)
       
   278 				{
       
   279 				// we've successfully changed the cache size...
       
   280 				if(max)
       
   281 					{
       
   282 					sizeMin = min;
       
   283 					sizeMax = max;
       
   284 					}
       
   285 				else
       
   286 					{
       
   287 					sizeMin = originalMin;
       
   288 					sizeMax = originalMax;
       
   289 					}
       
   290 				}
       
   291 			if(r==KErrNoMemory)
       
   292 				{
       
   293 				// cache size after OOM is unpredictable, so reset our values
       
   294 				DPTest::SetCacheSize(sizeMin,sizeMax);
       
   295 				}
       
   296 			else
       
   297 				{
       
   298 				// test 'get' function returns expected cache size
       
   299 				r=DPTest::CacheSize(min,max,currentSize);
       
   300 				test.Printf(_L("DPTest::CacheSize result=%d min=%u max=%u current=%u\n"),r,min/PageSize,max/PageSize,currentSize/PageSize);
       
   301 				if(r!=KErrNone || min!=sizeMin || max!=sizeMax)
       
   302 					test(0);
       
   303 				test(currentSize >= min && currentSize <= max);
       
   304 				}
       
   305 			++i;
       
   306 			}
       
   307 		}
       
   308 
       
   309 	test.End();
       
   310 	}
       
   311 
       
   312 
       
   313 
       
   314 void TestResizeVMCache2()
       
   315 	{
       
   316 	TUint originalMin = 0;
       
   317 	TUint originalMax = 0;
       
   318 	TUint currentSize = 0;
       
   319 	test_KErrNone(DPTest::CacheSize(originalMax, originalMax, currentSize));
       
   320 	test_KErrNone(DPTest::SetCacheSize(1, originalMax));
       
   321 	TUint sizeMin = 0;
       
   322 	TUint sizeMax = 0;
       
   323 	test_KErrNone(DPTest::CacheSize(sizeMin, sizeMax, currentSize));
       
   324 	test(sizeMin > 1);
       
   325 	test_KErrNone(DPTest::SetCacheSize(originalMin, originalMax));
       
   326 	}
       
   327 
       
   328 
       
   329 void TestHAL()
       
   330 	{
       
   331 	test.Start(_L("DPTest::Attributes"));
       
   332 	TUint32 attr=DPTest::Attributes();
       
   333 	test.Printf(_L("Attributes = %08x\n"),attr);
       
   334 
       
   335 	test.Next(_L("DPTest::FlushCache"));
       
   336 	TInt r=DPTest::FlushCache();
       
   337 	if(r==KErrNotSupported)
       
   338 		test.Printf(_L("Not Supported\n"));
       
   339 	else if(r<0)
       
   340 		{
       
   341 		test.Printf(_L("Error = %d\n"),r);
       
   342 		test(0);
       
   343 		}
       
   344 
       
   345 	test.Next(_L("DPTest::CacheSize"));
       
   346 	TUint oldMin = 0;
       
   347 	TUint oldMax = 0;
       
   348 	TUint currentSize = 0;
       
   349 	r=DPTest::CacheSize(oldMin,oldMax,currentSize);
       
   350 	if(r==KErrNotSupported)
       
   351 		test.Printf(_L("Not Supported\n"));
       
   352 	else if(r<0)
       
   353 		{
       
   354 		test.Printf(_L("Error = %d\n"),r);
       
   355 		test(0);
       
   356 		}
       
   357 	else
       
   358 		{
       
   359 		test.Printf(_L("Size = %dk,%dk,%dk\n"),oldMin>>10,oldMax>>10,currentSize>>10);
       
   360 		}
       
   361 
       
   362 	test.Next(_L("DPTest::SetCacheSize"));
       
   363 	r=DPTest::SetCacheSize(oldMin,oldMax);
       
   364 	if(r==KErrNotSupported)
       
   365 		test.Printf(_L("Not Supported\n"));
       
   366 	else if(r<0)
       
   367 		{
       
   368 		test.Printf(_L("Error = %d\n"),r);
       
   369 		test(0);
       
   370 		}
       
   371 	if(r==KErrNone)
       
   372 		{
       
   373 		TestResizeVMCache();
       
   374 		TestResizeVMCache2();
       
   375 		}
       
   376 
       
   377 	test.End();
       
   378 	}
       
   379 
       
   380 // Test IPC and realtime state
       
   381 
       
   382 enum TIpcDir
       
   383 	{
       
   384 	EServerRead,
       
   385 	EServerWrite
       
   386 	};
       
   387 
       
   388 enum TIpcObjectPaged
       
   389 	{
       
   390 	ENothingPaged,
       
   391 	EDesHeaderPaged,
       
   392 	EDesContentPaged
       
   393 	};
       
   394 
       
   395 enum TRealtimeOutcome
       
   396 	{
       
   397 	ENoError,
       
   398 	EBadDescriptor,
       
   399 	EServerTerminated,
       
   400 	ERealtimePanic
       
   401 	};
       
   402 
       
   403 class RTestSession : public RSessionBase
       
   404 	{
       
   405 public:
       
   406 	TInt Create(RServer2 aServer)
       
   407 		{
       
   408 		return CreateSession(aServer,TVersion(),-1);
       
   409 		}
       
   410 	inline TInt Send(const TIpcArgs& aArgs)
       
   411 		{
       
   412 		return RSessionBase::SendReceive(0,aArgs);
       
   413 		}
       
   414 	};
       
   415 
       
   416 RServer2 TestServer;
       
   417 
       
   418 TInt IpcTestServerFunc(TAny* aArg)
       
   419 	{
       
   420 	TIpcDir dir = (TIpcDir)(((TInt)aArg) & 0xff);
       
   421 	TIpcObjectPaged paged = (TIpcObjectPaged)((((TInt)aArg) >> 8) & 0xff);
       
   422 	User::TRealtimeState realtime = (User::TRealtimeState)((((TInt)aArg) >> 16) & 0xff);
       
   423 	User::TRealtimeState clientRealtime = (User::TRealtimeState)((((TInt)aArg) >> 24) & 0xff);
       
   424 
       
   425 	TInt r;
       
   426 	// We want the server to fault the client when it is realtime 
       
   427 	// and accessing paged out memory.
       
   428 	r = TestServer.CreateGlobal(KNullDesC, EIpcSession_Sharable, EServerRole_Default, EServerOpt_PinClientDescriptorsDisable);
       
   429 	if (r != KErrNone)
       
   430 		return r;
       
   431 	RThread::Rendezvous(KErrNone);
       
   432 	
       
   433 	RMessage2 message;
       
   434 	TestServer.Receive(message);
       
   435 	if ((clientRealtime == User::ERealtimeStateOn) != message.ClientIsRealtime())
       
   436 		return KErrGeneral;
       
   437 	message.Complete(KErrNone); // complete connection request
       
   438 
       
   439 	TRequestStatus s;
       
   440 	TestServer.Receive(message,s);
       
   441 	User::WaitForRequest(s);
       
   442 	if (s != KErrNone)
       
   443 		return s.Int();
       
   444 
       
   445 	TInt32 unpagedContent;
       
   446 	TPtr8 unpagedDes((TUint8*)&unpagedContent, 4, 4);
       
   447 	TPtrC8 pagedContentBuf(SmallBuffer,sizeof(TInt));
       
   448 
       
   449 	TPtr8* dataPagedHeaderDes = (TPtr8*)DataPagedBuffer;
       
   450 	if (DataPagingSupported)
       
   451 		new (dataPagedHeaderDes) TPtr8((TUint8*)&unpagedContent, 4);
       
   452 	
       
   453 	TPtr8 dataPagedContentDes(DataPagedBuffer + PageSize, 4);
       
   454 				
       
   455 	r = DPTest::FlushCache();
       
   456 	if(r != KErrNone)
       
   457 		return r;
       
   458 	
       
   459 	User::SetRealtimeState(realtime);
       
   460 	if (dir == EServerRead)
       
   461 		{
       
   462 		switch (paged)
       
   463 			{
       
   464 			case ENothingPaged:
       
   465 				r = message.Read(0,unpagedDes);
       
   466 				break;
       
   467 				
       
   468 			case EDesHeaderPaged:
       
   469 				r = DataPagingSupported ? message.Read(0,*dataPagedHeaderDes) : KErrNotSupported;
       
   470 				break;
       
   471 				
       
   472 			case EDesContentPaged:
       
   473 				r = DataPagingSupported ? message.Read(0,dataPagedContentDes) : KErrNotSupported;
       
   474 				break;
       
   475 
       
   476 			default:
       
   477 				r = KErrArgument;
       
   478 				break;
       
   479 			}
       
   480 		}
       
   481 	else if (dir == EServerWrite)
       
   482 		{
       
   483 		switch (paged)
       
   484 			{
       
   485 			case ENothingPaged:
       
   486 				r = message.Write(0,unpagedDes);
       
   487 				break;
       
   488 				
       
   489 			case EDesHeaderPaged:
       
   490 				r = message.Write(0,*PagedHeaderDes);
       
   491 				break;
       
   492 				
       
   493 			case EDesContentPaged:
       
   494 				r = message.Write(0,pagedContentBuf);
       
   495 				break;
       
   496 
       
   497 			default:
       
   498 				r = KErrArgument;
       
   499 				break;
       
   500 			}
       
   501 		}
       
   502 	else
       
   503 		r = KErrArgument;
       
   504 	User::SetRealtimeState(User::ERealtimeStateOff);
       
   505 
       
   506 	message.Complete(KErrNone);
       
   507 	return r;
       
   508 	}
       
   509 
       
   510 TInt IpcTestClientFunc(TAny* aArg)
       
   511 	{
       
   512 	TIpcDir dir = (TIpcDir)(((TInt)aArg) & 0xff);
       
   513 	TIpcObjectPaged paged = (TIpcObjectPaged)((((TInt)aArg) >> 8) & 0xff);
       
   514 	User::TRealtimeState realtime = (User::TRealtimeState)((((TInt)aArg) >> 16) & 0xff);
       
   515 
       
   516 	RTestSession session;
       
   517 	TInt r = session.Create(TestServer);
       
   518 	if(r != KErrNone)
       
   519 		return r;
       
   520 
       
   521 	TInt32 unpagedContent;
       
   522 	TPtr8 unpagedDes((TUint8*)&unpagedContent, 4, 4);
       
   523 	TPtrC8 pagedContentBuf(SmallBuffer + PageSize, sizeof(TInt));
       
   524 
       
   525 	TPtr8* dataPagedHeaderDes = (TPtr8*)(DataPagedBuffer + (2 * PageSize));
       
   526 	if (DataPagingSupported)
       
   527 		new (dataPagedHeaderDes) TPtr8((TUint8*)&unpagedContent, 4);
       
   528 	
       
   529 	TPtr8 dataPagedContentDes(DataPagedBuffer + (3 * PageSize), 4);
       
   530 
       
   531 	r = DPTest::FlushCache();
       
   532 	if(r != KErrNone)
       
   533 		return r;
       
   534 	
       
   535 	User::SetRealtimeState(realtime);
       
   536 	if (dir == EServerRead)
       
   537 		{
       
   538 		switch (paged)
       
   539 			{
       
   540 			case ENothingPaged:
       
   541 				r = session.Send(TIpcArgs(&unpagedDes));
       
   542 				break;
       
   543 				
       
   544 			case EDesHeaderPaged:
       
   545 				r = session.Send(TIpcArgs(PagedHeaderDes));
       
   546 				break;
       
   547 				
       
   548 			case EDesContentPaged:
       
   549 				r = session.Send(TIpcArgs(&pagedContentBuf));
       
   550 				break;
       
   551 
       
   552 			default:
       
   553 				r = KErrArgument;
       
   554 				break;
       
   555 			}
       
   556 		}
       
   557 	else if (dir == EServerWrite)
       
   558 		{
       
   559 		switch (paged)
       
   560 			{
       
   561 			case ENothingPaged:
       
   562 				r = session.Send(TIpcArgs(&unpagedDes));
       
   563 				break;
       
   564 				
       
   565 			case EDesHeaderPaged:
       
   566 				r = DataPagingSupported ? session.Send(TIpcArgs(dataPagedHeaderDes)) : KErrNotSupported;
       
   567 				break;
       
   568 				
       
   569 			case EDesContentPaged:
       
   570 				r = DataPagingSupported ? session.Send(TIpcArgs(&dataPagedContentDes)) : KErrNotSupported;
       
   571 				break;
       
   572 
       
   573 			default:
       
   574 				r = KErrArgument;
       
   575 				break;
       
   576 			}
       
   577 		}
       
   578 	else
       
   579 		r = KErrArgument;
       
   580 	User::SetRealtimeState(User::ERealtimeStateOff);
       
   581 
       
   582 	session.Close();
       
   583 	return r;
       
   584 	}
       
   585 
       
   586 void TestRealtimeOutcome(RThread aThread, TRealtimeOutcome aOutcome)
       
   587 	{
       
   588 	switch(aOutcome)
       
   589 		{
       
   590 		case ENoError:
       
   591 			test_Equal(EExitKill, aThread.ExitType());
       
   592 			test_KErrNone(aThread.ExitReason());
       
   593 			break;
       
   594 			
       
   595 		case EBadDescriptor:
       
   596 			test_Equal(EExitKill, aThread.ExitType());
       
   597 			test_Equal(KErrBadDescriptor, aThread.ExitReason());
       
   598 			break;
       
   599 
       
   600 		case EServerTerminated:
       
   601 			test_Equal(EExitKill, aThread.ExitType());
       
   602 			test_Equal(KErrServerTerminated, aThread.ExitReason());
       
   603 			break;
       
   604 
       
   605 		case ERealtimePanic:
       
   606 			test_Equal(EExitPanic, aThread.ExitType());
       
   607 			test(aThread.ExitCategory()==_L("KERN-EXEC"));
       
   608 			test_Equal(EIllegalFunctionForRealtimeThread, aThread.ExitReason());
       
   609 			break;
       
   610 
       
   611 		default:
       
   612 			test(EFalse);
       
   613 		}
       
   614 	}
       
   615 
       
   616 void TestPagedIpc(TIpcDir aIpcDir,
       
   617 				  TIpcObjectPaged aClientPaged,
       
   618 				  TIpcObjectPaged aServerPaged,
       
   619 				  User::TRealtimeState aClientState,
       
   620 				  User::TRealtimeState aServerState,
       
   621 				  TRealtimeOutcome aClientOutcome,
       
   622 				  TRealtimeOutcome aServerOutcome)
       
   623 	{
       
   624 	test.Printf(_L("TestPagedIpc %d %d %d %d %d %d %d\n"), aIpcDir, aClientPaged, aServerPaged,
       
   625 				aClientState, aServerState, aClientOutcome, aServerOutcome);
       
   626 	
       
   627 	RThread serverThread;
       
   628 	RThread clientThread;
       
   629 	TRequestStatus serverStatus;
       
   630 	TRequestStatus clientStatus;
       
   631 
       
   632 	TInt serverArg = aIpcDir | (aServerPaged << 8) | (aServerState << 16) | (aClientState << 24);
       
   633 	test_KErrNone(serverThread.Create(KNullDesC, &IpcTestServerFunc, 0x1000, NULL, (TAny*)serverArg));
       
   634 	TName name;
       
   635 	name = serverThread.Name();
       
   636 	test.Printf(_L("  server: %S\n"), &name);
       
   637 	serverThread.Rendezvous(serverStatus);
       
   638 	serverThread.Resume();
       
   639 	User::WaitForRequest(serverStatus);
       
   640 	test_KErrNone(serverStatus.Int());
       
   641 	serverThread.Logon(serverStatus);
       
   642 	
       
   643 	TInt clientArg = aIpcDir | (aClientPaged << 8) | (aClientState << 16);
       
   644 	test_KErrNone(clientThread.Create(KNullDesC, &IpcTestClientFunc, 0x1000, NULL, (TAny*)clientArg));
       
   645 	name = clientThread.Name();
       
   646 	test.Printf(_L("  client: %S\n"), &name);
       
   647 	clientThread.Logon(clientStatus);
       
   648 	clientThread.Resume();
       
   649 
       
   650 	User::WaitForRequest(serverStatus);
       
   651 	test.Printf(_L("  server exit type is %d %d\n"), serverThread.ExitType(), serverThread.ExitReason());
       
   652 	TestServer.Close();  // because handle is process-relative, it's not closed if the server dies
       
   653 
       
   654 	User::WaitForRequest(clientStatus);
       
   655 	test.Printf(_L("  client exit type is %d %d\n"), clientThread.ExitType(), clientThread.ExitReason());
       
   656 
       
   657 	TestRealtimeOutcome(serverThread, aServerOutcome);
       
   658 	TestRealtimeOutcome(clientThread, aClientOutcome);
       
   659 	
       
   660 	CLOSE_AND_WAIT(serverThread);
       
   661 	CLOSE_AND_WAIT(clientThread);
       
   662 	}
       
   663 
       
   664 TInt TestThreadFunction(TAny* aType)
       
   665 	{
       
   666 	// Ensure that pageable memory is paged out
       
   667 	TInt r=DPTest::FlushCache();
       
   668 	if(r!=KErrNone)
       
   669 		return r;
       
   670 
       
   671 	// Access pageable data whilst thread is in specified realttime state.
       
   672 	User::SetRealtimeState((User::TRealtimeState)(TInt)aType);
       
   673 	READ(SmallBuffer);
       
   674 	return KErrNone;
       
   675 	}
       
   676 
       
   677 TInt RunTestThread(User::TRealtimeState aType, TRealtimeOutcome aOutcome)
       
   678 	{
       
   679 	RThread thread;
       
   680 	TInt r=thread.Create(KNullDesC, &TestThreadFunction, 0x1000, NULL, (TAny*)aType);
       
   681 	if(r!=KErrNone)
       
   682 		return r;
       
   683 	TRequestStatus s;
       
   684 	thread.Logon(s);
       
   685 	if(s.Int()!=KRequestPending)
       
   686 		return s.Int();
       
   687 	thread.Resume();
       
   688 	User::WaitForRequest(s);
       
   689 	TestRealtimeOutcome(thread, aOutcome);
       
   690 	CLOSE_AND_WAIT(thread);
       
   691 	return KErrNone;
       
   692 	}
       
   693 
       
   694 void TestRealtimeState()
       
   695 	{
       
   696 	// make sure live list is big enough
       
   697 	test(KErrNone==DPTest::SetCacheSize(256*PageSize,256*PageSize));
       
   698 
       
   699 	test.Start(_L("Enable KREALTIME tracing"));
       
   700 	Ldd.SetRealtimeTrace(ETrue);
       
   701 
       
   702 	test.Next(_L("Test ERealtimeStateOff"));
       
   703 	RunTestThread(User::ERealtimeStateOff, ENoError);
       
   704 
       
   705 	test.Next(_L("Test ERealtimeStateOn"));
       
   706 	RunTestThread(User::ERealtimeStateOn, ERealtimePanic);
       
   707 
       
   708 	test.Next(_L("Test ERealtimeStateWarn"));
       
   709 	RunTestThread(User::ERealtimeStateWarn, ENoError);
       
   710 
       
   711 	test.Next(_L("Test combinations of IPC with realtime state"));
       
   712 
       
   713 	//           ipc dir:      client paged:     server paged:     client state:             server state:             client outcome:    server outcome:
       
   714 	TestPagedIpc(EServerRead,  ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   715 	TestPagedIpc(EServerRead,  EDesHeaderPaged,  ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   716 	TestPagedIpc(EServerRead,  EDesContentPaged, ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   717 	TestPagedIpc(EServerWrite, ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   718 	TestPagedIpc(EServerWrite, ENothingPaged,    EDesHeaderPaged,  User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   719 	TestPagedIpc(EServerWrite, ENothingPaged,    EDesContentPaged, User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   720 
       
   721 	if (DataPagingSupported)
       
   722 		{
       
   723 	TestPagedIpc(EServerRead,  ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   724 	TestPagedIpc(EServerRead,  ENothingPaged,    EDesHeaderPaged,  User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   725 	TestPagedIpc(EServerRead,  ENothingPaged,    EDesContentPaged, User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   726 	TestPagedIpc(EServerWrite, ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   727 	TestPagedIpc(EServerWrite, EDesHeaderPaged,  ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   728 	TestPagedIpc(EServerWrite, EDesContentPaged, ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOff,  ENoError,          ENoError);
       
   729 		}
       
   730 
       
   731 	TestPagedIpc(EServerRead,  ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   732 	TestPagedIpc(EServerRead,  EDesHeaderPaged,  ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   733 	TestPagedIpc(EServerRead,  EDesContentPaged, ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   734 	TestPagedIpc(EServerWrite, ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   735 	TestPagedIpc(EServerWrite, ENothingPaged,    EDesHeaderPaged,  User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   736 	TestPagedIpc(EServerWrite, ENothingPaged,    EDesContentPaged, User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   737 
       
   738 	if (DataPagingSupported)
       
   739 		{
       
   740 	TestPagedIpc(EServerRead,  ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   741 	TestPagedIpc(EServerRead,  ENothingPaged,    EDesHeaderPaged,  User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   742 	TestPagedIpc(EServerRead,  ENothingPaged,    EDesContentPaged, User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   743 	TestPagedIpc(EServerWrite, ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   744 	TestPagedIpc(EServerWrite, EDesHeaderPaged,  ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   745 	TestPagedIpc(EServerWrite, EDesContentPaged, ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateWarn, ENoError,          ENoError);
       
   746 		}
       
   747 
       
   748 	TestPagedIpc(EServerRead,  ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ENoError,          ENoError);
       
   749 	TestPagedIpc(EServerRead,  EDesHeaderPaged,  ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ENoError,          ENoError);
       
   750 	TestPagedIpc(EServerRead,  EDesContentPaged, ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ERealtimePanic,    EBadDescriptor);
       
   751 	TestPagedIpc(EServerWrite, ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ENoError,          ENoError);
       
   752 	TestPagedIpc(EServerWrite, ENothingPaged,    EDesHeaderPaged,  User::ERealtimeStateOff,  User::ERealtimeStateOn,   EServerTerminated, ERealtimePanic);
       
   753 	TestPagedIpc(EServerWrite, ENothingPaged,    EDesContentPaged, User::ERealtimeStateOff,  User::ERealtimeStateOn,   EServerTerminated, ERealtimePanic);
       
   754 
       
   755 	if (DataPagingSupported)
       
   756 		{
       
   757 	TestPagedIpc(EServerRead,  ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ENoError,          ENoError);
       
   758 	TestPagedIpc(EServerRead,  ENothingPaged,    EDesHeaderPaged,  User::ERealtimeStateOff,  User::ERealtimeStateOn,   EServerTerminated, ERealtimePanic);
       
   759 	TestPagedIpc(EServerRead,  ENothingPaged,    EDesContentPaged, User::ERealtimeStateOff,  User::ERealtimeStateOn,   EServerTerminated, ERealtimePanic);
       
   760 	TestPagedIpc(EServerWrite, ENothingPaged,    ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ENoError,          ENoError);
       
   761 	TestPagedIpc(EServerWrite, EDesHeaderPaged,  ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ENoError,          ENoError);
       
   762 	TestPagedIpc(EServerWrite, EDesContentPaged, ENothingPaged,    User::ERealtimeStateOff,  User::ERealtimeStateOn,   ERealtimePanic,    EBadDescriptor);
       
   763 		}
       
   764 	
       
   765 	test.End();
       
   766 
       
   767 	// retore size of live list
       
   768 	test(KErrNone==DPTest::SetCacheSize(0,0));
       
   769 	}
       
   770 
       
   771 void TestLock()
       
   772 	{
       
   773 	// make sure live list is big enough
       
   774 	test(KErrNone==DPTest::SetCacheSize(128 * PageSize, 256 * PageSize));
       
   775 
       
   776 	TInt r = Ldd.LockTest(SmallBuffer,SmallBufferSize);
       
   777 	if(r==KErrNone)
       
   778 		{
       
   779 		test.Next(_L("Lock Test again"));
       
   780 		r = Ldd.LockTest(SmallBuffer,SmallBufferSize);
       
   781 		}
       
   782 	if(r)
       
   783 		{
       
   784 		test.Printf(_L("failed at D_DEMANPAGING.CPP line %d\n"),r);
       
   785 		test(0);
       
   786 		}
       
   787 		
       
   788 	// restore live list to default size...
       
   789 	test(KErrNone==DPTest::SetCacheSize(0,0));
       
   790 	}
       
   791 
       
   792 const TInt KSmallPropertySize = 512;
       
   793 const TInt KLargePropertySize = 16384;
       
   794 	
       
   795 struct SSetPropertyInfo
       
   796 	{
       
   797 	TUid iCategory;
       
   798 	TInt iKey;
       
   799 	TUint8* iData;
       
   800 	TInt iLength;
       
   801 	};
       
   802 
       
   803 TInt SetPropertyThreadFunction(TAny* aArg)
       
   804 	{
       
   805 	SSetPropertyInfo* info = (SSetPropertyInfo*)aArg;
       
   806 	TInt r;
       
   807 	r = DPTest::FlushCache();
       
   808 	if (r != KErrNone)
       
   809 		return r;
       
   810 	TPtrC8 data(info->iData, info->iLength);
       
   811 	r = RProperty::Set(info->iCategory, info->iKey, data);
       
   812 	if (r != KErrNone)
       
   813 		return r;
       
   814 	RBuf8 buffer;
       
   815 	r = buffer.Create(KLargePropertySize);
       
   816 	if (r != KErrNone)
       
   817 		return r;
       
   818 	r = RProperty::Get(info->iCategory, info->iKey, buffer);
       
   819 	if (r == KErrNone && buffer != data)
       
   820 		r = KErrGeneral;
       
   821 	buffer.Close();
       
   822 	return r;
       
   823 	}
       
   824 
       
   825 void TestPublishAndSubscribe()
       
   826 	{
       
   827 	RProcess thisProcess;
       
   828 	TUid category = thisProcess.SecureId();
       
   829 
       
   830 	TSecurityPolicy alwaysPass(TSecurityPolicy::EAlwaysPass);
       
   831 	test(RProperty::Define(category, 0, RProperty::EByteArray, alwaysPass, alwaysPass) == KErrNone);
       
   832 	test(RProperty::Define(category, 1, RProperty::ELargeByteArray, alwaysPass, alwaysPass) == KErrNone);
       
   833 	
       
   834 	TPtrC8 smallData(SmallBuffer, KSmallPropertySize);
       
   835 	TPtrC8 largeData(SmallBuffer, KLargePropertySize);
       
   836 	
       
   837 	RBuf8 buffer;
       
   838 	test(buffer.Create(KLargePropertySize) == KErrNone);
       
   839 
       
   840 	// Set small property from paged data, method 1
       
   841 	test(DPTest::FlushCache() == KErrNone);
       
   842 	test(RProperty::Set(category, 0, smallData) == KErrNone);
       
   843 	test(RProperty::Get(category, 0, buffer) == KErrNone);
       
   844 	test(buffer == smallData);
       
   845 	
       
   846 	// Set small property from paged data, method 2
       
   847 	RProperty smallProp;
       
   848 	test(smallProp.Attach(category, 0) == KErrNone);
       
   849 	test(DPTest::FlushCache() == KErrNone);
       
   850 	test(smallProp.Set(smallData) == KErrNone);
       
   851 	test(smallProp.Get(buffer) == KErrNone);
       
   852 	test(buffer == smallData);
       
   853 
       
   854 	// Set large property from paged data, method 1
       
   855 	test(DPTest::FlushCache() == KErrNone);
       
   856 	test(RProperty::Set(category, 1, largeData) == KErrNone);
       
   857 	test(RProperty::Get(category, 1, buffer) == KErrNone);
       
   858 	test(buffer == largeData);
       
   859 	
       
   860 	// Set large property from paged data, method 2
       
   861 	RProperty largeProp;
       
   862 	test(largeProp.Attach(category, 1) == KErrNone);
       
   863 	test(DPTest::FlushCache() == KErrNone);
       
   864 	test(largeProp.Set(largeData) == KErrNone);
       
   865 	test(largeProp.Get(buffer) == KErrNone);
       
   866 	test(buffer == largeData);
       
   867 
       
   868 	// Set small property from unmapped address
       
   869 	RThread thread;
       
   870 #if !defined( __VC32__)
       
   871 	SSetPropertyInfo info = { category, 0, 0, KSmallPropertySize };
       
   872 #else
       
   873 	SSetPropertyInfo info = { category.iUid, 0, 0, KSmallPropertySize };
       
   874 #endif
       
   875 	test(thread.Create(_L("SetPropertyThread"), SetPropertyThreadFunction, 4096, NULL, &info) == KErrNone);
       
   876 	thread.Resume();
       
   877 	TRequestStatus status;
       
   878 	thread.Logon(status);
       
   879 	User::WaitForRequest(status);
       
   880 	test(thread.ExitType()==EExitPanic);
       
   881 	test(thread.ExitCategory()==_L("KERN-EXEC"));
       
   882 	test(thread.ExitReason()==ECausedException);
       
   883 	thread.Close();
       
   884 
       
   885 	// Set large property from unmapped address
       
   886 	info.iKey = 1;
       
   887 	info.iLength = KLargePropertySize;
       
   888 	test(thread.Create(_L("SetPropertyThread"), SetPropertyThreadFunction, 4096, NULL, &info) == KErrNone);
       
   889 	thread.Resume();
       
   890 	thread.Logon(status);
       
   891 	User::WaitForRequest(status);
       
   892 	test(thread.ExitType()==EExitPanic);
       
   893 	test(thread.ExitCategory()==_L("KERN-EXEC"));
       
   894 	test(thread.ExitReason()==ECausedException);
       
   895 	thread.Close();
       
   896 	
       
   897 	test(RProperty::Delete(category, 0) == KErrNone);
       
   898 	test(RProperty::Delete(category, 1) == KErrNone);
       
   899 	}
       
   900 
       
   901 void TestWriteToPagedArea()
       
   902 	{
       
   903 	RMemoryTestLdd memoryTest;
       
   904 	test(KErrNone==memoryTest.Open());
       
   905 
       
   906 	TModuleMemoryInfo exeInfo;
       
   907 	test(KErrNone==RProcess().GetMemoryInfo(exeInfo));
       
   908 	test.Printf(_L("test program code is %x+%x"),exeInfo.iCodeBase,exeInfo.iCodeSize);
       
   909 
       
   910 	TUint8* ptr = const_cast<TUint8*>(LargeBuffer);
       
   911 	TUint8* end = ptr + LargeBufferSize;
       
   912 	while(ptr<end)
       
   913 		{
       
   914 		if(ptr>=(TUint8*)_ALIGN_DOWN(exeInfo.iCodeBase,PageSize) && ptr<(TUint8*)_ALIGN_UP(exeInfo.iCodeBase+exeInfo.iCodeSize,PageSize))
       
   915 			{
       
   916 			// avoid testing the ROM which contains this test program
       
   917 			ptr += PageSize;
       
   918 			continue;
       
   919 			}
       
   920 	
       
   921 		DPTest::FlushCache();
       
   922 
       
   923 		TInt stateBits = UserSvr::HalFunction(EHalGroupVM, EVMPageState, ptr, 0);
       
   924 		test(stateBits>=0);
       
   925 		// write to paged out memory should cause exception...
       
   926 		test(KErrBadDescriptor==memoryTest.WriteMemory(ptr,0));
       
   927 		// page state should be unchanged...
       
   928 		TInt newStateBits = UserSvr::HalFunction(EHalGroupVM, EVMPageState, ptr, 0);
       
   929 		if(stateBits!=newStateBits)
       
   930 			{
       
   931 			test.Printf(_L("ptr=%x stateBits=%x newStateBits=%x"),ptr,stateBits,newStateBits);
       
   932 			test(0);
       
   933 			}
       
   934 		// page-in in memory...
       
   935 		TUint32 value = *(TUint32*)ptr;
       
   936 		// write to paged out memory should still cause exception...
       
   937 		test(KErrBadDescriptor==memoryTest.WriteMemory(ptr,~value));
       
   938 		// memory should be unchanged...
       
   939 		test(value==*(TUint32*)ptr);
       
   940 		ptr += PageSize;
       
   941 		}
       
   942 
       
   943 	memoryTest.Close();
       
   944 	}
       
   945 
       
   946 void TestContiguousRamAlloc()
       
   947 	{
       
   948 	test.Start(_L("Start..."));
       
   949 
       
   950 	const TInt KCacheSize = 1024*1024;
       
   951 
       
   952 	DPTest::SetCacheSize(0, KCacheSize); // make sure paging cache is a reasonable size
       
   953 
       
   954 	TInt testData[][2] = /* array of page size (in units of 'half pages')  and align values */
       
   955 		{
       
   956 			{64,5},
       
   957 			{64,0},
       
   958 			{32,4},
       
   959 			{32,3},
       
   960 			{32,2},
       
   961 			{32,1},
       
   962 			{32,0},
       
   963 			{4,2},
       
   964 			{4,1},
       
   965 			{4,0},
       
   966 			{2,2},
       
   967 			{2,1},
       
   968 			{2,0},
       
   969 			{1,0},
       
   970 			{0,0}
       
   971 		};
       
   972 	TInt pageShift = 1;
       
   973 	while((1<<pageShift)<PageSize)
       
   974 		++pageShift;
       
   975 
       
   976 	TInt* params = (TInt*)&testData;
       
   977 	while(*params)
       
   978 		{
       
   979 		TInt size =  *params++<<(pageShift-1);	//Size is units of half pages, so one less shift to get required memory size
       
   980 		TInt align = *params++;
       
   981 		if(align)
       
   982 			align += pageShift - 1;
       
   983 		TBuf<256> title;
       
   984 		title.AppendFormat(_L("Contiguous RAM test: alloc size = %dK align = %d"),size>>10, align);
       
   985 		test.Next(title);
       
   986 		FragmentPagingCache(KCacheSize);
       
   987 		TInt r = Ldd.DoConsumeContiguousRamTest(align, size);
       
   988 		if(r)
       
   989 			{
       
   990 			test.Printf(_L("failed at D_DEMANPAGING.CPP line %d\n"),r);
       
   991 			test(0);
       
   992 			}
       
   993 		}
       
   994 
       
   995 	DPTest::SetCacheSize(0,0); // back to defaults
       
   996 	test.End();
       
   997 	}
       
   998 
       
   999 void TestReadHoldingMutex()
       
  1000 	{
       
  1001 	TUint8 localBuf[16];
       
  1002 	TUint8* localPtr = localBuf;
       
  1003 	if(DPTest::Attributes() & DPTest::EDataPaging) // if data paging supported...
       
  1004 		localPtr = 0; // use zero to make driver use kernel memory as data destination
       
  1005 	test(Ldd.ReadHoldingMutexTest(localPtr) == KErrNone);
       
  1006 	}
       
  1007 
       
  1008 #if 0 // rom dump code...
       
  1009 #include <f32file.h>
       
  1010 	RFs fs;
       
  1011 	RFile file;
       
  1012 	test(KErrNone==fs.Connect());
       
  1013 	test(KErrNone==file.Replace(fs, _L("d:\\ROMDUMP"),EFileWrite));
       
  1014 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
       
  1015 	TPtrC8 rom((TUint8*)romHeader,romHeader->iRomSize);
       
  1016 	test(KErrNone==file.Write(rom));
       
  1017 	file.Close();
       
  1018 	fs.Close();
       
  1019 	return 0;
       
  1020 #endif
       
  1021 
       
  1022 
       
  1023 class RMySession : public RSessionBase
       
  1024 	{
       
  1025 public:
       
  1026 	TInt Connect(RServer2 aSrv,TRequestStatus& aStat)
       
  1027 		{
       
  1028 		TInt r=CreateSession(aSrv,TVersion(),-1,EIpcSession_Sharable,NULL,&aStat);
       
  1029 		if(!r) ShareAuto(); return r;
       
  1030 		}
       
  1031 	TInt Send(TInt function,const TIpcArgs& args)
       
  1032 		{return SendReceive(function,args);}
       
  1033 	};
       
  1034 
       
  1035 
       
  1036 TUint8* TestBuffer = 0;
       
  1037 RMySession MySession;
       
  1038 
       
  1039 LOCAL_C TInt TestServerThread(TAny* aSize)
       
  1040 	{
       
  1041 	TInt r = TestServer.CreateGlobal(KNullDesC, EIpcSession_GlobalSharable);
       
  1042 	if(r==KErrNone)
       
  1043 		{
       
  1044 		TestBuffer = (TUint8*)User::Alloc(KMaxIPCSize);
       
  1045 		if(!TestBuffer)
       
  1046 			r = KErrNoMemory;
       
  1047 		}
       
  1048 	TPtr8 buffer(TestBuffer,KMaxIPCSize);
       
  1049 	RThread::Rendezvous(r);
       
  1050 	if (r != KErrNone)
       
  1051 		return r;
       
  1052 
       
  1053 	RMessage2 m;
       
  1054 	TestServer.Receive(m);
       
  1055 	m.Complete(KErrNone);	// connect message
       
  1056 
       
  1057 	TBool running = ETrue;
       
  1058 	while (running)
       
  1059 		{
       
  1060 		TestServer.Receive(m);
       
  1061 		RDebug::Printf("Server received: %d", m.Function());
       
  1062 
       
  1063 		TInt r = KErrNone;
       
  1064 		switch(m.Function())
       
  1065 			{
       
  1066 			case 0:
       
  1067 				// Kill server
       
  1068 				running = EFalse;
       
  1069 				break;
       
  1070 
       
  1071 			case 2:
       
  1072 				buffer.Set(SharedBuffer,KMaxIPCSize,KMaxIPCSize);
       
  1073 				// fall through...
       
  1074 			case 1:
       
  1075 				// Perform CRC of data passed
       
  1076 				{
       
  1077 				DPTest::FlushCache();
       
  1078 				r=m.Read(0,buffer);
       
  1079 				if (r!=KErrNone)
       
  1080 					break;
       
  1081 				TUint32 crc=0;
       
  1082 				Mem::Crc32(crc,buffer.Ptr(),buffer.Size());
       
  1083 				r = crc;
       
  1084 				}
       
  1085 				break;
       
  1086 
       
  1087 			case 4:
       
  1088 				buffer.Set(SharedBuffer,KMaxIPCSize,KMaxIPCSize);
       
  1089 				// fall through...
       
  1090 			case 3:
       
  1091 				// Write data to client descriptor
       
  1092 				{
       
  1093 				DPTest::FlushCache();
       
  1094 				RDebug::Printf("Server writing %08x+%x", m.Int1(), m.Int2());
       
  1095 				TPtrC8 ptr((TUint8*)m.Int1(),m.Int2());
       
  1096 				r=m.Write(0,ptr);
       
  1097 				}
       
  1098 				break;
       
  1099 			
       
  1100 			default:
       
  1101 				// Just complete anything else
       
  1102 				break;
       
  1103 			}
       
  1104 		m.Complete(r);
       
  1105 		}
       
  1106 
       
  1107 	RDebug::Printf("Server exiting");
       
  1108 	User::Free(TestBuffer);
       
  1109 	TestBuffer = NULL;
       
  1110 	TestServer.Close();
       
  1111 	return KErrNone;
       
  1112 	}
       
  1113 
       
  1114 void TestIPC()
       
  1115 	{
       
  1116 	__KHEAP_MARK;
       
  1117 		
       
  1118 	const TUint8* start = LargeBuffer + 0x3df; // make range not page aligned
       
  1119 	const TUint8* end = start + Min(LargeBufferSize, KMaxIPCSize * 10) - 0x130; // make range not page aligned
       
  1120 	const TUint8* pos;
       
  1121 	
       
  1122 	test.Start(_L("Create server"));
       
  1123 	RThread t;
       
  1124 	TInt r=t.Create(KNullDesC,TestServerThread,0x1000,KMaxIPCSize+0x1000,KMaxIPCSize+0x1000,(void*)0);
       
  1125 	test(r==KErrNone);
       
  1126 	t.SetPriority(EPriorityMore);
       
  1127 	TRequestStatus s;
       
  1128 	t.Rendezvous(s);
       
  1129 	t.Resume();
       
  1130 	User::WaitForRequest(s);
       
  1131 	test(TestServer.Handle() != KNullHandle);
       
  1132 
       
  1133 	test(MySession.Connect(TestServer,s) == KErrNone);
       
  1134 	User::WaitForRequest(s);	// connected
       
  1135 
       
  1136 	TInt bufferType; // 0=server uses heap, 1=server uses SharedBuffer
       
  1137 	for(bufferType=0; bufferType<=1; ++bufferType)
       
  1138 		{
       
  1139 		test.Next(_L("IPC read from ROM"));
       
  1140 		pos = start;
       
  1141 		while(pos<end)
       
  1142 			{
       
  1143 			TInt size = end-pos;
       
  1144 			if(size>KMaxIPCSize)
       
  1145 				size = KMaxIPCSize;
       
  1146 			RDebug::Printf("read %x+%x",pos,size);
       
  1147 			TPtrC8 ptr(pos,size);
       
  1148 			TInt r = MySession.Send(1+bufferType,TIpcArgs(&ptr));
       
  1149 			DPTest::FlushCache();
       
  1150 			TUint32 crc=0;
       
  1151 			Mem::Crc32(crc,pos,size);
       
  1152 			RDebug::Printf("crc %08x %08x",r,crc);
       
  1153 			if((TUint32)r!=crc)
       
  1154 				{
       
  1155 				RDebug::Printf("FAIL");
       
  1156 				DPTest::FlushCache();
       
  1157 				TInt count = 0;
       
  1158 				for(TInt i=0; i<size; i+=4)
       
  1159 					{
       
  1160 					TUint32 a = pos[i];
       
  1161 					TUint32 b = TestBuffer[i];
       
  1162 					if(a!=b)
       
  1163 						RDebug::Printf("%08x %02x!=%02x",pos+i,a,b);
       
  1164 					if (++count > 100)
       
  1165 						break;
       
  1166 					}
       
  1167 				}
       
  1168 			test((TUint32)r==crc);
       
  1169 			pos+=size;
       
  1170 			}
       
  1171 
       
  1172 		test.Next(_L("IPC write from ROM"));
       
  1173 		pos = start;
       
  1174 		while(pos<end)
       
  1175 			{
       
  1176 			TInt size = end-pos;
       
  1177 			if(size>KMaxIPCSize)
       
  1178 				size = KMaxIPCSize;
       
  1179 			RDebug::Printf("write %x+%x",pos,size);
       
  1180 			memclr(TestBuffer, KMaxIPCSize);
       
  1181 			TPtr8 ptr(TestBuffer,KMaxIPCSize);	// reuse the server's buffer
       
  1182 			TInt r = MySession.Send(3+bufferType,TIpcArgs(&ptr,pos,size));
       
  1183 			test_KErrNone(r);
       
  1184 			DPTest::FlushCache();
       
  1185 			TUint32 crc=0;
       
  1186 			Mem::Crc32(crc,pos,size);
       
  1187 			TUint32 crc2=0;
       
  1188 			Mem::Crc32(crc2,TestBuffer,size);
       
  1189 			RDebug::Printf("crc %08x %08x",crc,crc2);
       
  1190 			if((TUint32)crc!=crc2)
       
  1191 				{
       
  1192 				RDebug::Printf("FAIL");
       
  1193 				DPTest::FlushCache();
       
  1194 				TInt count = 0;
       
  1195 				for(TInt i=0; i<size; i+=4)
       
  1196 					{
       
  1197 					TUint32 a = pos[i];
       
  1198 					TUint32 b = TestBuffer[i];
       
  1199 					if(a!=b)
       
  1200 						RDebug::Printf("%08x %02x!=%02x",pos+i,a,b);
       
  1201 					if (++count > 100)
       
  1202 						break;
       
  1203 					}
       
  1204 				}
       
  1205 			test((TUint32)crc==crc2);
       
  1206 			pos+=size;
       
  1207 			}
       
  1208 		}
       
  1209 
       
  1210 	if (DPTest::Attributes() & DPTest::ERomPaging)
       
  1211 		{
       
  1212 		test.Next(_L("Test passing descriptor headers in paged-out memory"));
       
  1213 		__KHEAP_MARK;
       
  1214 
       
  1215 		DPTest::FlushCache();
       
  1216 		TInt r = MySession.Send(5,TIpcArgs(PagedHeaderDes));
       
  1217 		test_Equal(KErrNone, r);
       
  1218 		
       
  1219 		UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
       
  1220 		__KHEAP_MARKEND;
       
  1221 		}
       
  1222 	
       
  1223 	test.Next(_L("Stop server"));
       
  1224 	MySession.Send(0,TIpcArgs(0));
       
  1225 	MySession.Close();
       
  1226 	t.Logon(s);
       
  1227 	User::WaitForRequest(s);
       
  1228 	test_Equal(EExitKill, t.ExitType());
       
  1229 	test_Equal(KErrNone, t.ExitReason());
       
  1230 	CLOSE_AND_WAIT(t);	
       
  1231 	test.End();
       
  1232 	
       
  1233 	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);
       
  1234 	__KHEAP_MARKEND;
       
  1235 	}
       
  1236 
       
  1237 
       
  1238 TInt E32Main()
       
  1239 	{
       
  1240 	test.Title();
       
  1241 	
       
  1242 	test_KErrNone(UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&PageSize,0));
       
  1243 	
       
  1244 	if (DPTest::Attributes() & DPTest::ERomPaging)
       
  1245 		test.Printf(_L("Rom paging supported\n"));
       
  1246 	if (DPTest::Attributes() & DPTest::ECodePaging)
       
  1247 		test.Printf(_L("Code paging supported\n"));
       
  1248 	if (DPTest::Attributes() & DPTest::EDataPaging)
       
  1249 		{
       
  1250 		test.Printf(_L("Data paging supported\n"));
       
  1251 		DataPagingSupported = ETrue;
       
  1252 		TChunkCreateInfo createInfo;
       
  1253 		createInfo.SetNormal(KMinBufferSize, KMinBufferSize);
       
  1254 		createInfo.SetPaging(TChunkCreateInfo::EPaged);
       
  1255 		createInfo.SetOwner(EOwnerProcess);
       
  1256 		createInfo.SetGlobal(KChunkName);
       
  1257 		test_KErrNone(DataPagedChunk.Create(createInfo));
       
  1258 		test(DataPagedChunk.IsPaged()); // this is only ever called if data paging is supported
       
  1259 		DataPagedBuffer = (TUint8*)DataPagedChunk.Base();
       
  1260 		}
       
  1261 		
       
  1262 	test.Start(_L("Test HAL interface"));
       
  1263 	TestHAL();
       
  1264 
       
  1265 	if (DPTest::Attributes() & DPTest::ERomPaging)
       
  1266 		{
       
  1267 		// Use paged part of rom for testing
       
  1268 		TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
       
  1269 		test(romHeader->iPageableRomStart);
       
  1270 		// todo: for some reason the first part of page of paged rom doesn't seem to get paged out
       
  1271 		// when we flush the paging cache, hence LargeBuffer starts some way into this
       
  1272 		LargeBuffer = (TUint8*)romHeader + romHeader->iPageableRomStart + 64 * PageSize; 
       
  1273 		LargeBufferSize = romHeader->iPageableRomSize - 64 * PageSize;
       
  1274 		test(LargeBufferSize > 0);
       
  1275 		// Find a zero word in rom to set PagedHeaderDes to
       
  1276 		TUint* ptr = (TUint*)LargeBuffer;
       
  1277 		TUint* end = (TUint*)(LargeBuffer + LargeBufferSize);
       
  1278 		while (*ptr && ptr < end)
       
  1279 			++ptr;
       
  1280 		test(*ptr == 0);
       
  1281 		test.Printf(_L("Found zero word at %08x\n"), ptr);
       
  1282 		PagedHeaderDes = (TDesC8*)ptr;
       
  1283 		}
       
  1284 	else if (DPTest::Attributes() & DPTest::ECodePaging)
       
  1285 		{
       
  1286 		// Use code paged DLL for testing
       
  1287 		test_KErrNone(PagedLibrary.Load(KTCodePagingDll4));		
       
  1288 		TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)PagedLibrary.Lookup(KGetAddressOfDataFunctionOrdinal);
       
  1289 		LargeBuffer = (TUint8*)func(LargeBufferSize);
       
  1290 		test_NotNull(LargeBuffer);
       
  1291 		PagedHeaderDes = (TDesC8*)LargeBuffer + 4;
       
  1292 		}
       
  1293 	else if (DPTest::Attributes() & DPTest::EDataPaging)
       
  1294 		{
       
  1295 		// Use data paged chunk for testing
       
  1296 		LargeBuffer = DataPagedBuffer;
       
  1297 		LargeBufferSize = KMinBufferSize;
       
  1298 		}
       
  1299 	else
       
  1300 		{
       
  1301 		test.Printf(_L("Demand Paging not supported\n"));
       
  1302 		test.End();
       
  1303 		return 0;
       
  1304 		}
       
  1305 	
       
  1306 	test(LargeBufferSize >= KMinBufferSize);
       
  1307 	SmallBuffer = LargeBuffer;
       
  1308 	SmallBufferSize = KMinBufferSize;
       
  1309 
       
  1310 	test.Next(_L("Loading test drivers"));
       
  1311 	TInt r = User::LoadLogicalDevice(KDemandPagingTestLddName);
       
  1312 	test(r==KErrNone || r==KErrAlreadyExists);
       
  1313 	test(Ldd.Open()==KErrNone);
       
  1314 
       
  1315 	test_KErrNone(Ldd.CreatePlatHwChunk(SharedBufferSize, SharedBufferAddr));
       
  1316 	SharedBuffer = (TUint8*)SharedBufferAddr;
       
  1317 
       
  1318 	RDebug::Printf("SmallBuffer=%x, LargeBuffer=%x, SharedBuffer=%x\n",
       
  1319 		SmallBuffer, LargeBuffer, SharedBuffer);
       
  1320 
       
  1321 	test.Next(_L("Gobble RAM"));
       
  1322 	r = User::LoadLogicalDevice(KGobblerLddFileName);
       
  1323 	test(r==KErrNone || r==KErrAlreadyExists);
       
  1324 	RGobbler gobbler;
       
  1325 	r = gobbler.Open();
       
  1326 	test(r==KErrNone);
       
  1327 	TUint32 taken = gobbler.GobbleRAM(64*1024*1024); // leave 64MB of free RAM
       
  1328 	test.Printf(_L("Gobbled: %dK\n"), taken/1024);
       
  1329 	test.Printf(_L("Free RAM 0x%08X bytes\n"),FreeRam());
       
  1330 
       
  1331 	test.Next(_L("Test contiguous RAM allocation reclaims paged memory"));
       
  1332 	TestContiguousRamAlloc();
       
  1333 
       
  1334 	test.Next(_L("Test thread realtime state"));
       
  1335 	TestRealtimeState();
       
  1336 
       
  1337 	test.Next(_L("Lock Test"));
       
  1338 	TestLock();
       
  1339 
       
  1340 	test.Next(_L("Test writing to paged area"));
       
  1341 	TestWriteToPagedArea();
       
  1342 
       
  1343 	test.Next(_L("Test IPC read from paged memory"));
       
  1344 	TestIPC();
       
  1345 
       
  1346 	test.Next(_L("Test no kernel faults when copying data from unpaged rom with mutex held"));
       
  1347 	TestReadHoldingMutex();
       
  1348 
       
  1349 	test.Next(_L("Close test driver"));
       
  1350 	Ldd.DestroyPlatHwChunk();
       
  1351 	Ldd.Close();
       
  1352 
       
  1353 	test.Next(_L("Test setting publish and subscribe properties from paged area"));
       
  1354 	TestPublishAndSubscribe();
       
  1355 
       
  1356 	if (DPTest::Attributes() & DPTest::ERomPaging)
       
  1357 		{
       
  1358 		test.Next(_L("Rom Paging Benchmark"));
       
  1359 		RomPagingBenchmark();
       
  1360 		}
       
  1361 
       
  1362 	PagedLibrary.Close();
       
  1363 	gobbler.Close();
       
  1364 	test.End();
       
  1365 
       
  1366 	return 0;
       
  1367 	}