os/kernelhwsrv/kerneltest/e32test/mmu/d_sharedio.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2003-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\d_sharedio.cpp
    15 // LDD for testing SharedIoBuffers
    16 // 
    17 //
    18 
    19 #include <kernel/kern_priv.h>
    20 #include "d_sharedio.h"
    21 
    22 //
    23 // LDD factory
    24 //
    25 
    26 class DSharedIoTestFactory : public DLogicalDevice
    27 	{
    28 public:
    29 	DSharedIoTestFactory();
    30 	~DSharedIoTestFactory();
    31 	virtual TInt Install();
    32 	virtual void GetCaps(TDes8& aDes) const;
    33 	virtual TInt Create(DLogicalChannelBase*& aChannel);
    34 public:
    35 	DSharedIoBuffer* iGlobalBuffer;
    36 	};
    37 
    38 //
    39 // Logical Channel
    40 //
    41 
    42 class DSharedIoTest : public DLogicalChannelBase
    43 	{
    44 public:
    45 	virtual ~DSharedIoTest();
    46 protected:
    47 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
    48 	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
    49 public:
    50 	DSharedIoBuffer* iIoBuffer;
    51 	DSharedIoBuffer* iGlobalBuffer;
    52 	DSharedIoTestFactory* iFactory;
    53 #ifndef __WINS__
    54 	TPhysAddr iPhysAddress;
    55 #endif
    56 	};
    57 
    58 //
    59 // LDD factory
    60 //
    61 
    62 DSharedIoTestFactory::DSharedIoTestFactory()
    63 	{
    64 	iGlobalBuffer=NULL;
    65 	}
    66 
    67 DSharedIoTestFactory::~DSharedIoTestFactory()
    68 	{
    69 	delete iGlobalBuffer;
    70 	}
    71 TInt DSharedIoTestFactory::Create(DLogicalChannelBase*& aChannel)
    72 	{
    73 	__KTRACE_OPT(KMMU,Kern::Printf(">DSharedIoTestFactory::Create iGlobalBuffer=%x",iGlobalBuffer));
    74 	if(!iGlobalBuffer)
    75 		{
    76 #ifdef __WINS__
    77 		TUint aAttribs=0;
    78 #else
    79 		TUint aAttribs=EMapAttrSupRw | EMapAttrFullyBlocking;
    80 #endif
    81 		TInt r=DSharedIoBuffer::New(iGlobalBuffer,KSizeGlobalBuffer,aAttribs);
    82 		if(r!=KErrNone)
    83 			return r;
    84 		}
    85 	aChannel=new DSharedIoTest;
    86 	if(!aChannel)
    87 		return KErrNoMemory;
    88 	((DSharedIoTest*)aChannel)->iGlobalBuffer=iGlobalBuffer;
    89 	((DSharedIoTest*)aChannel)->iFactory=this;
    90 	__KTRACE_OPT(KMMU,Kern::Printf("<DSharedIoTestFactory::Create iGlobalBuffer=%x",iGlobalBuffer));
    91 	return KErrNone;
    92 	}
    93 
    94 TInt DSharedIoTestFactory::Install()
    95 	{
    96 	return SetName(&KSharedIoTestLddName);
    97 	}
    98 
    99 void DSharedIoTestFactory::GetCaps(TDes8& /* aDes */) const
   100 	{
   101 	//aDes.FillZ(aDes.MaxLength());
   102 	}
   103 
   104 DECLARE_STANDARD_LDD()
   105 	{
   106 	return new DSharedIoTestFactory;
   107 	}
   108 
   109 //
   110 // Logical Channel
   111 //
   112 
   113 TInt DSharedIoTest::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
   114 	{
   115 	return KErrNone;
   116 	}
   117 
   118 DSharedIoTest::~DSharedIoTest()
   119 	{
   120 	delete iIoBuffer;
   121 	}
   122 
   123 TInt checkBuffer(TAny* buffer, TUint32 aSize, TUint32 key)
   124 	{
   125 	TInt r=KErrNone;
   126 	TUint8* m=(TUint8*)buffer;
   127 	for(TUint32 size=0;size<aSize;size++,key+=5,m++)
   128 		{
   129 		if(*m!=(TUint8)(key%256))
   130 			{
   131 			r=KErrCorrupt;
   132 			break;
   133 			}
   134 		}
   135 	return r;
   136 	}
   137 
   138 TInt fillBuffer(TAny* buffer, TUint32 aSize, TUint32 key)
   139 	{
   140 	TUint8* m=(TUint8*)buffer;
   141 	for(TUint32 size=0;size<aSize;size++,key+=5,m++)
   142 		{
   143 		*m=(TUint8)(key%256);
   144 		}
   145 	return KErrNone;
   146 	}
   147 
   148 static void AppendNumToBuf(TDes8& aDes, const TDesC& aNum, TInt width, char fill)
   149 {
   150 	TInt l = aNum.Length();
   151 	for (; l < width; ++l)
   152 		aDes.Append(TChar(fill));
   153 	aDes.Append(aNum);
   154 }
   155 
   156 static void DumpMemory(TUint8* aStart, TInt aSize)
   157 {
   158 	TBuf8<80> line;
   159 	TBuf8<24> val;
   160 	TChar space(' ');
   161 
   162 	TInt i = (TInt)aStart & 0xF;	// first byte in this line to dump
   163 	TInt n = 16;					// end byte in this line
   164 
   165 	while (aSize > 0)
   166 		{
   167 		if (i + aSize < 16)
   168 			n = i + aSize;
   169 
   170 		val.Num((TUint32)aStart & ~0xF, EHex);
   171 		AppendNumToBuf(line, val, 8, '0');
   172 		line.Append(space);
   173 		line.Append(space);
   174 
   175 		TInt j;
   176 
   177 		for (j = 0; j < i; ++j)
   178 			{
   179 			line.Append(space);
   180 			line.Append(space);
   181 			line.Append(space);
   182 
   183 			if (j == 7) line.Append(space);
   184 			}
   185 
   186 		for (; j < n; ++j)
   187 			{
   188 			val.Num(aStart[j-i], EHex);
   189 			line.Append(space);
   190 			AppendNumToBuf(line, val, 2, '0');
   191 
   192 			if (j == 7) line.Append(space);
   193 			}
   194 
   195 		for (; j < 16; ++j)
   196 			{
   197 			line.Append(space);
   198 			line.Append(space);
   199 			line.Append(space);
   200 
   201 			if (j == 7) line.Append(space);
   202 			}
   203 
   204 		line.Append(space);
   205 		line.Append(space);
   206 
   207 		for (j = 0; j < i; ++j)
   208 			line.Append(space);
   209 
   210 		for (; j < n; ++j)
   211 			{
   212 			char c = aStart[j-i];
   213 			if (c < ' ' || c > 126) c = '.';
   214 			line.Append(TChar(c));
   215 			}
   216 
   217 		Kern::Printf("%S", &line);
   218 
   219 		line.SetLength(0);
   220 
   221 		aStart += (n - i);
   222 		aSize -= (n - i);
   223 
   224 		i = 0;
   225 		}
   226 }
   227 
   228 TBool CheckMemCleared(TLinAddr aAddress, TInt aSize)
   229 {
   230 	TUint8* aPtr = (TUint8*)aAddress;
   231 	for(TInt i = 0; i<aSize; i++)
   232 		{
   233 		if(aPtr[i] != 0x03)
   234 			{
   235 			Kern::Printf("CheckMemCleared(0x%x, %d) failed at i = 0x%x", aAddress, aSize, i);
   236 			// Start on current line & ~0xF, run for 16 lines x 16 bytes
   237 			TUint8 *p = (TUint8*)((aAddress + i) & ~0x0F);
   238 			TInt n = 256;
   239 
   240 			if (p < aPtr) p = aPtr;
   241 			if (p - aPtr > aSize - n)	// if (p + n > aPtr + aSize) rearranged (to avoid overflow)
   242 				n = aPtr + aSize - p;
   243 
   244 			DumpMemory(p, n);
   245 			return EFalse;
   246 			}
   247 		}
   248 	return ETrue;
   249 }
   250 
   251 TInt DSharedIoTest::Request(TInt aFunction, TAny* a1, TAny* a2)
   252 	{
   253 	TInt r=KErrNone;
   254 	switch (aFunction)
   255 		{
   256 		case RTestLdd::ECreateBuffer:
   257 			{
   258 			TUint32 size = (TUint32)a1;
   259 			r = KErrNoMemory;
   260 #ifdef __WINS__
   261 			TUint aAttribs1=0;
   262 			TUint aAttribs2=0;
   263 			TUint aAttribs3=0;
   264 #else
   265 			TUint aAttribs1=EMapAttrSupRw | EMapAttrBufferedNC;
   266 			TUint aAttribs2=EMapAttrSupRw | EMapAttrFullyBlocking;
   267 			TUint aAttribs3=EMapAttrSupRw | EMapAttrCachedMax;
   268 #endif
   269 			NKern::ThreadEnterCS();
   270 			r=DSharedIoBuffer::New(iIoBuffer,size,aAttribs1);
   271 			if(r!=KErrNone)
   272 				{
   273 				Kern::Printf("Error creating buffer r=%d\n",r);
   274 				NKern::ThreadLeaveCS();
   275 				return r;
   276 				}
   277 
   278 			//Check the buffer is properly initialized (the previous content 
   279 			//deleted by inserting all 0x03s)
   280 			if (!CheckMemCleared(iIoBuffer->iAddress, iIoBuffer->iSize))
   281 				{
   282 				Kern::Printf("Error memory zeroing test for shared io buffers");
   283 				NKern::ThreadLeaveCS();
   284 				return KErrCorrupt;
   285 				}
   286 
   287 			//just test that we can construct a second shared buffer
   288 			DSharedIoBuffer* ptr;
   289 			r=DSharedIoBuffer::New(ptr,size,aAttribs2);
   290 			if(r!=KErrNone)
   291 				{
   292 				Kern::Printf("Error creating the 2nd buffer r=%d\n",r);
   293 				delete iIoBuffer;
   294 				iIoBuffer=NULL;
   295 				NKern::ThreadLeaveCS();
   296 				return r;
   297 				}
   298 			delete ptr; //creation successfull, simply delete the object
   299 
   300 			// and the third one, this time fully cached.
   301 			r=DSharedIoBuffer::New(ptr,size,aAttribs3);
   302 			if(r!=KErrNone)
   303 				{
   304 				Kern::Printf("Error creating the 3rd buffer r=%d\n",r);
   305 				delete iIoBuffer;
   306 				iIoBuffer=NULL;
   307 				NKern::ThreadLeaveCS();
   308 				return r;
   309 				}
   310 			delete ptr; //creation successfull, simply delete the object
   311 
   312 			NKern::ThreadLeaveCS();
   313 			if(iIoBuffer->iSize!=size)   // test
   314 				{
   315 				Kern::Printf("Error checking size iIoBuffer->iSize=%d size=%d\n",iIoBuffer->iSize,size);
   316 				return KErrGeneral;
   317 				}
   318 			memset((void*)iIoBuffer->iAddress,0,size);
   319 			}
   320 			return r;
   321 
   322 		case RTestLdd::EMapInGlobalBuffer:
   323 			{
   324 			if(!iGlobalBuffer)
   325 				return KErrGeneral;
   326 
   327 			TUint id;
   328 			kumemget32(&id,a1,sizeof(TUint));
   329 
   330 			NKern::ThreadEnterCS();
   331 			Kern::Containers()[EProcess]->Wait();
   332 			DProcess* process=Kern::ProcessFromId(id);
   333 			if(process)
   334 				process->Open();
   335 			Kern::Containers()[EProcess]->Signal();
   336 			if(process)
   337 				{
   338 				r=iGlobalBuffer->UserMap(process);
   339 				process->Close(0);
   340 				}
   341 			else
   342 				r = KErrGeneral;
   343 			NKern::ThreadLeaveCS();
   344 
   345 			if(r!=KErrNone)
   346 				return r;
   347 
   348 			if(iGlobalBuffer->UserToKernel(iGlobalBuffer->iUserAddress,iGlobalBuffer->iSize)!=iGlobalBuffer->iAddress)
   349 				return KErrGeneral;
   350 			
   351 			if(iGlobalBuffer->UserToKernel(iGlobalBuffer->iUserAddress,iGlobalBuffer->iSize+1)!=NULL)
   352 				return KErrGeneral;
   353 
   354 			if(iGlobalBuffer->KernelToUser(iGlobalBuffer->iAddress)!=iGlobalBuffer->iUserAddress)
   355 				return KErrGeneral;
   356 
   357 			kumemput32(a1,&iGlobalBuffer->iUserAddress,sizeof(TAny*));
   358 			kumemput32(a2,&iGlobalBuffer->iSize,sizeof(TInt));
   359 
   360 			return KErrNone;
   361 			}
   362 
   363 		case RTestLdd::EMapOutGlobalBuffer:
   364 			{
   365 			if(!iGlobalBuffer)
   366 				return KErrGeneral;
   367 			r=iGlobalBuffer->UserUnmap();
   368 			if(r==KErrNone)
   369 				if(iGlobalBuffer->iUserProcess)
   370 					r = KErrGeneral;
   371 			return r;
   372 			}
   373 
   374 		case RTestLdd::EDestroyGlobalBuffer:
   375 			{
   376 			NKern::ThreadEnterCS();
   377 			delete iGlobalBuffer;
   378 			iGlobalBuffer = NULL;
   379 			iFactory->iGlobalBuffer=NULL;
   380 			NKern::ThreadLeaveCS();
   381 			return KErrNone;
   382 			}
   383 
   384 		case RTestLdd::ECreateBufferPhysAddr:
   385 			{
   386 #ifdef __WINS__
   387 			return KErrNotSupported;
   388 #else
   389 			TUint32 size=Kern::RoundToPageSize(1);
   390 			NKern::ThreadEnterCS();
   391 			r=Epoc::AllocPhysicalRam(size,iPhysAddress);
   392 			Kern::Printf("phys addr = %X!\n",iPhysAddress);
   393 			if(r!=KErrNone)
   394 				{
   395 				NKern::ThreadLeaveCS();
   396 				return r;
   397 				}
   398 			r = KErrNoMemory;
   399 
   400 			//test that we can construct a fully cached sharedio
   401 			DSharedIoBuffer* ptr;
   402 			r=DSharedIoBuffer::New(ptr,iPhysAddress,size,EMapAttrSupRw|EMapAttrCachedMax);
   403 			if(r!=KErrNone)
   404 				{
   405 				Kern::Printf("Error creating the physical cached buffer r=%d\n",r);
   406 				Epoc::FreePhysicalRam(iPhysAddress,size);
   407 				iPhysAddress=0;
   408 				NKern::ThreadLeaveCS();
   409 				return r;
   410 				}
   411 			delete ptr; //creation successfull, simply delete the object
   412 
   413 
   414 			r=DSharedIoBuffer::New(iIoBuffer,iPhysAddress,size,EMapAttrSupRw|EMapAttrFullyBlocking);
   415 			if(r!=KErrNone)
   416 				{
   417 				Epoc::FreePhysicalRam(iPhysAddress,size);
   418 				iPhysAddress=0;
   419 				NKern::ThreadLeaveCS();
   420 				return r;
   421 				}
   422 
   423 			if(iIoBuffer->iSize!=size)   // test
   424 				{
   425 				delete iIoBuffer;
   426 				iIoBuffer=NULL;
   427 				Epoc::FreePhysicalRam(iPhysAddress,size);
   428 				iPhysAddress=0;
   429 				NKern::ThreadLeaveCS();
   430 				return KErrGeneral;
   431 				}
   432 
   433 			fillBuffer((TAny*)iIoBuffer->iAddress,size,180);
   434 
   435 			DPlatChunkHw* hwChunk;
   436 			r=DPlatChunkHw::New(hwChunk, iPhysAddress, size, EMapAttrSupRw|EMapAttrFullyBlocking);
   437 			if(r!=KErrNone)
   438 				{
   439 				delete iIoBuffer;
   440 				iIoBuffer=NULL;
   441 				Epoc::FreePhysicalRam(iPhysAddress,size);
   442 				iPhysAddress=0;
   443 				NKern::ThreadLeaveCS();
   444 				return r;
   445 				}
   446 			
   447 			r=checkBuffer((TAny*)hwChunk->LinearAddress(),size,180);
   448 			if(r!=KErrNone)
   449 				{
   450 				delete iIoBuffer;
   451 				iIoBuffer=NULL;
   452 				hwChunk->Close(NULL);
   453 				Epoc::FreePhysicalRam(iPhysAddress,size);
   454 				iPhysAddress=0;
   455 				NKern::ThreadLeaveCS();
   456 				return r;
   457 				}
   458 
   459 			hwChunk->Close(NULL);
   460 			NKern::ThreadLeaveCS();
   461 			return r;
   462 #endif
   463 			}
   464 
   465 		case RTestLdd::EDestroyBufferPhysAddr:
   466 			{
   467 #ifdef __WINS__
   468 			return KErrNotSupported;
   469 #else
   470 			TUint32 size=Kern::RoundToPageSize(1);
   471 			NKern::ThreadEnterCS();
   472 			delete iIoBuffer;
   473 			iIoBuffer = NULL;
   474 			r=Epoc::FreePhysicalRam(iPhysAddress,size);
   475 			iPhysAddress=0;
   476 			NKern::ThreadLeaveCS();
   477 			return r;
   478 #endif
   479 			}
   480 
   481 
   482 		case RTestLdd::EMapInBuffer:
   483 			{
   484 			r=iIoBuffer->UserMap(&Kern::CurrentProcess());
   485 			if(r!=KErrNone)
   486 				return r;
   487 
   488 			TAny** p = (TAny**)iIoBuffer->iAddress;
   489 			TAny* ua = (TAny*)iIoBuffer->iUserAddress;
   490 			TAny** end = (TAny**)((TInt)p+iIoBuffer->iSize);
   491 			while(p<end)
   492 				{
   493 				*p++ = ua;
   494 				ua = (TAny*)((TInt)ua+sizeof(TAny*));
   495 				}
   496 			if(iIoBuffer->UserToKernel(iIoBuffer->iUserAddress,iIoBuffer->iSize)!=iIoBuffer->iAddress)
   497 				return KErrGeneral;
   498 			
   499 			if(iIoBuffer->UserToKernel(iIoBuffer->iUserAddress,iIoBuffer->iSize+1)!=NULL)
   500 				return KErrGeneral;
   501 
   502 			if(iIoBuffer->KernelToUser(iIoBuffer->iAddress)!=iIoBuffer->iUserAddress)
   503 				return KErrGeneral;
   504 			kumemput32(a1,&iIoBuffer->iUserAddress,sizeof(TAny*));
   505 			kumemput32(a2,&iIoBuffer->iSize,sizeof(TInt));
   506 			return r;
   507 			}
   508 
   509 		case RTestLdd::EMapOutBuffer:
   510 			{
   511 			r=iIoBuffer->UserUnmap();
   512 			if(r==KErrNone)
   513 				if(iIoBuffer->iUserProcess)
   514 					r = KErrGeneral;
   515 			return r;
   516 			}
   517 
   518 		case RTestLdd::EDestroyBuffer:
   519 			NKern::ThreadEnterCS();
   520 			delete iIoBuffer;
   521 			iIoBuffer = NULL;
   522 			NKern::ThreadLeaveCS();
   523 			return KErrNone;
   524 
   525 		case RTestLdd::ECheckBuffer:
   526 			if(!iIoBuffer->iAddress || !iIoBuffer->iUserAddress || !iIoBuffer->iUserProcess)
   527 				return KErrGeneral;
   528 			return checkBuffer((TAny*)iIoBuffer->iAddress,iIoBuffer->iSize,(TUint32)a1);
   529 			
   530 		case RTestLdd::EFillBuffer:
   531 			if(!iIoBuffer->iAddress || !iIoBuffer->iUserAddress || !iIoBuffer->iUserProcess)
   532 				return KErrGeneral;
   533 			return fillBuffer((TAny*)iIoBuffer->iAddress,iIoBuffer->iSize,(TUint32)a1);
   534 
   535 		case RTestLdd::EThreadRW:
   536 			{
   537 			TInt dummy;
   538 			TPckg<TInt> a(dummy);
   539 			DThread* pT;
   540 			if((TInt)a2==-1)
   541 				{
   542 				pT=&Kern::CurrentThread();
   543 				}
   544 			else
   545 				{
   546 				NKern::ThreadEnterCS();
   547 				DObjectCon* pC=Kern::Containers()[EThread];
   548 				pC->Wait();
   549 				pT=Kern::ThreadFromId((TInt)a2);
   550 				pC->Signal();
   551 				if(!pT)
   552 					return KErrNotFound;
   553 				NKern::ThreadLeaveCS();
   554 				}
   555 			r=Kern::ThreadDesRead(pT,a1,a,0,KChunkShiftBy0);
   556 			if(r!=KErrNone)
   557 				return r;
   558 			if(dummy!=KMagic1)
   559 				return KErrCorrupt;
   560 			dummy=KMagic2;
   561 			r=Kern::ThreadDesWrite(pT,a1,a,0,KChunkShiftBy0,&Kern::CurrentThread());
   562 			if(r!=KErrNone)
   563 				return r;
   564 			return KErrNone;
   565 			}
   566 
   567 		default:
   568 			r=KErrNotSupported;
   569 			break;
   570 		}
   571 	return r;
   572 	}
   573