os/kernelhwsrv/kerneltest/e32test/mmu/t_demandpaging.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 	}