1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/mmu/d_sharedio.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,573 @@
1.4 +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\mmu\d_sharedio.cpp
1.18 +// LDD for testing SharedIoBuffers
1.19 +//
1.20 +//
1.21 +
1.22 +#include <kernel/kern_priv.h>
1.23 +#include "d_sharedio.h"
1.24 +
1.25 +//
1.26 +// LDD factory
1.27 +//
1.28 +
1.29 +class DSharedIoTestFactory : public DLogicalDevice
1.30 + {
1.31 +public:
1.32 + DSharedIoTestFactory();
1.33 + ~DSharedIoTestFactory();
1.34 + virtual TInt Install();
1.35 + virtual void GetCaps(TDes8& aDes) const;
1.36 + virtual TInt Create(DLogicalChannelBase*& aChannel);
1.37 +public:
1.38 + DSharedIoBuffer* iGlobalBuffer;
1.39 + };
1.40 +
1.41 +//
1.42 +// Logical Channel
1.43 +//
1.44 +
1.45 +class DSharedIoTest : public DLogicalChannelBase
1.46 + {
1.47 +public:
1.48 + virtual ~DSharedIoTest();
1.49 +protected:
1.50 + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
1.51 + virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
1.52 +public:
1.53 + DSharedIoBuffer* iIoBuffer;
1.54 + DSharedIoBuffer* iGlobalBuffer;
1.55 + DSharedIoTestFactory* iFactory;
1.56 +#ifndef __WINS__
1.57 + TPhysAddr iPhysAddress;
1.58 +#endif
1.59 + };
1.60 +
1.61 +//
1.62 +// LDD factory
1.63 +//
1.64 +
1.65 +DSharedIoTestFactory::DSharedIoTestFactory()
1.66 + {
1.67 + iGlobalBuffer=NULL;
1.68 + }
1.69 +
1.70 +DSharedIoTestFactory::~DSharedIoTestFactory()
1.71 + {
1.72 + delete iGlobalBuffer;
1.73 + }
1.74 +TInt DSharedIoTestFactory::Create(DLogicalChannelBase*& aChannel)
1.75 + {
1.76 + __KTRACE_OPT(KMMU,Kern::Printf(">DSharedIoTestFactory::Create iGlobalBuffer=%x",iGlobalBuffer));
1.77 + if(!iGlobalBuffer)
1.78 + {
1.79 +#ifdef __WINS__
1.80 + TUint aAttribs=0;
1.81 +#else
1.82 + TUint aAttribs=EMapAttrSupRw | EMapAttrFullyBlocking;
1.83 +#endif
1.84 + TInt r=DSharedIoBuffer::New(iGlobalBuffer,KSizeGlobalBuffer,aAttribs);
1.85 + if(r!=KErrNone)
1.86 + return r;
1.87 + }
1.88 + aChannel=new DSharedIoTest;
1.89 + if(!aChannel)
1.90 + return KErrNoMemory;
1.91 + ((DSharedIoTest*)aChannel)->iGlobalBuffer=iGlobalBuffer;
1.92 + ((DSharedIoTest*)aChannel)->iFactory=this;
1.93 + __KTRACE_OPT(KMMU,Kern::Printf("<DSharedIoTestFactory::Create iGlobalBuffer=%x",iGlobalBuffer));
1.94 + return KErrNone;
1.95 + }
1.96 +
1.97 +TInt DSharedIoTestFactory::Install()
1.98 + {
1.99 + return SetName(&KSharedIoTestLddName);
1.100 + }
1.101 +
1.102 +void DSharedIoTestFactory::GetCaps(TDes8& /* aDes */) const
1.103 + {
1.104 + //aDes.FillZ(aDes.MaxLength());
1.105 + }
1.106 +
1.107 +DECLARE_STANDARD_LDD()
1.108 + {
1.109 + return new DSharedIoTestFactory;
1.110 + }
1.111 +
1.112 +//
1.113 +// Logical Channel
1.114 +//
1.115 +
1.116 +TInt DSharedIoTest::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
1.117 + {
1.118 + return KErrNone;
1.119 + }
1.120 +
1.121 +DSharedIoTest::~DSharedIoTest()
1.122 + {
1.123 + delete iIoBuffer;
1.124 + }
1.125 +
1.126 +TInt checkBuffer(TAny* buffer, TUint32 aSize, TUint32 key)
1.127 + {
1.128 + TInt r=KErrNone;
1.129 + TUint8* m=(TUint8*)buffer;
1.130 + for(TUint32 size=0;size<aSize;size++,key+=5,m++)
1.131 + {
1.132 + if(*m!=(TUint8)(key%256))
1.133 + {
1.134 + r=KErrCorrupt;
1.135 + break;
1.136 + }
1.137 + }
1.138 + return r;
1.139 + }
1.140 +
1.141 +TInt fillBuffer(TAny* buffer, TUint32 aSize, TUint32 key)
1.142 + {
1.143 + TUint8* m=(TUint8*)buffer;
1.144 + for(TUint32 size=0;size<aSize;size++,key+=5,m++)
1.145 + {
1.146 + *m=(TUint8)(key%256);
1.147 + }
1.148 + return KErrNone;
1.149 + }
1.150 +
1.151 +static void AppendNumToBuf(TDes8& aDes, const TDesC& aNum, TInt width, char fill)
1.152 +{
1.153 + TInt l = aNum.Length();
1.154 + for (; l < width; ++l)
1.155 + aDes.Append(TChar(fill));
1.156 + aDes.Append(aNum);
1.157 +}
1.158 +
1.159 +static void DumpMemory(TUint8* aStart, TInt aSize)
1.160 +{
1.161 + TBuf8<80> line;
1.162 + TBuf8<24> val;
1.163 + TChar space(' ');
1.164 +
1.165 + TInt i = (TInt)aStart & 0xF; // first byte in this line to dump
1.166 + TInt n = 16; // end byte in this line
1.167 +
1.168 + while (aSize > 0)
1.169 + {
1.170 + if (i + aSize < 16)
1.171 + n = i + aSize;
1.172 +
1.173 + val.Num((TUint32)aStart & ~0xF, EHex);
1.174 + AppendNumToBuf(line, val, 8, '0');
1.175 + line.Append(space);
1.176 + line.Append(space);
1.177 +
1.178 + TInt j;
1.179 +
1.180 + for (j = 0; j < i; ++j)
1.181 + {
1.182 + line.Append(space);
1.183 + line.Append(space);
1.184 + line.Append(space);
1.185 +
1.186 + if (j == 7) line.Append(space);
1.187 + }
1.188 +
1.189 + for (; j < n; ++j)
1.190 + {
1.191 + val.Num(aStart[j-i], EHex);
1.192 + line.Append(space);
1.193 + AppendNumToBuf(line, val, 2, '0');
1.194 +
1.195 + if (j == 7) line.Append(space);
1.196 + }
1.197 +
1.198 + for (; j < 16; ++j)
1.199 + {
1.200 + line.Append(space);
1.201 + line.Append(space);
1.202 + line.Append(space);
1.203 +
1.204 + if (j == 7) line.Append(space);
1.205 + }
1.206 +
1.207 + line.Append(space);
1.208 + line.Append(space);
1.209 +
1.210 + for (j = 0; j < i; ++j)
1.211 + line.Append(space);
1.212 +
1.213 + for (; j < n; ++j)
1.214 + {
1.215 + char c = aStart[j-i];
1.216 + if (c < ' ' || c > 126) c = '.';
1.217 + line.Append(TChar(c));
1.218 + }
1.219 +
1.220 + Kern::Printf("%S", &line);
1.221 +
1.222 + line.SetLength(0);
1.223 +
1.224 + aStart += (n - i);
1.225 + aSize -= (n - i);
1.226 +
1.227 + i = 0;
1.228 + }
1.229 +}
1.230 +
1.231 +TBool CheckMemCleared(TLinAddr aAddress, TInt aSize)
1.232 +{
1.233 + TUint8* aPtr = (TUint8*)aAddress;
1.234 + for(TInt i = 0; i<aSize; i++)
1.235 + {
1.236 + if(aPtr[i] != 0x03)
1.237 + {
1.238 + Kern::Printf("CheckMemCleared(0x%x, %d) failed at i = 0x%x", aAddress, aSize, i);
1.239 + // Start on current line & ~0xF, run for 16 lines x 16 bytes
1.240 + TUint8 *p = (TUint8*)((aAddress + i) & ~0x0F);
1.241 + TInt n = 256;
1.242 +
1.243 + if (p < aPtr) p = aPtr;
1.244 + if (p - aPtr > aSize - n) // if (p + n > aPtr + aSize) rearranged (to avoid overflow)
1.245 + n = aPtr + aSize - p;
1.246 +
1.247 + DumpMemory(p, n);
1.248 + return EFalse;
1.249 + }
1.250 + }
1.251 + return ETrue;
1.252 +}
1.253 +
1.254 +TInt DSharedIoTest::Request(TInt aFunction, TAny* a1, TAny* a2)
1.255 + {
1.256 + TInt r=KErrNone;
1.257 + switch (aFunction)
1.258 + {
1.259 + case RTestLdd::ECreateBuffer:
1.260 + {
1.261 + TUint32 size = (TUint32)a1;
1.262 + r = KErrNoMemory;
1.263 +#ifdef __WINS__
1.264 + TUint aAttribs1=0;
1.265 + TUint aAttribs2=0;
1.266 + TUint aAttribs3=0;
1.267 +#else
1.268 + TUint aAttribs1=EMapAttrSupRw | EMapAttrBufferedNC;
1.269 + TUint aAttribs2=EMapAttrSupRw | EMapAttrFullyBlocking;
1.270 + TUint aAttribs3=EMapAttrSupRw | EMapAttrCachedMax;
1.271 +#endif
1.272 + NKern::ThreadEnterCS();
1.273 + r=DSharedIoBuffer::New(iIoBuffer,size,aAttribs1);
1.274 + if(r!=KErrNone)
1.275 + {
1.276 + Kern::Printf("Error creating buffer r=%d\n",r);
1.277 + NKern::ThreadLeaveCS();
1.278 + return r;
1.279 + }
1.280 +
1.281 + //Check the buffer is properly initialized (the previous content
1.282 + //deleted by inserting all 0x03s)
1.283 + if (!CheckMemCleared(iIoBuffer->iAddress, iIoBuffer->iSize))
1.284 + {
1.285 + Kern::Printf("Error memory zeroing test for shared io buffers");
1.286 + NKern::ThreadLeaveCS();
1.287 + return KErrCorrupt;
1.288 + }
1.289 +
1.290 + //just test that we can construct a second shared buffer
1.291 + DSharedIoBuffer* ptr;
1.292 + r=DSharedIoBuffer::New(ptr,size,aAttribs2);
1.293 + if(r!=KErrNone)
1.294 + {
1.295 + Kern::Printf("Error creating the 2nd buffer r=%d\n",r);
1.296 + delete iIoBuffer;
1.297 + iIoBuffer=NULL;
1.298 + NKern::ThreadLeaveCS();
1.299 + return r;
1.300 + }
1.301 + delete ptr; //creation successfull, simply delete the object
1.302 +
1.303 + // and the third one, this time fully cached.
1.304 + r=DSharedIoBuffer::New(ptr,size,aAttribs3);
1.305 + if(r!=KErrNone)
1.306 + {
1.307 + Kern::Printf("Error creating the 3rd buffer r=%d\n",r);
1.308 + delete iIoBuffer;
1.309 + iIoBuffer=NULL;
1.310 + NKern::ThreadLeaveCS();
1.311 + return r;
1.312 + }
1.313 + delete ptr; //creation successfull, simply delete the object
1.314 +
1.315 + NKern::ThreadLeaveCS();
1.316 + if(iIoBuffer->iSize!=size) // test
1.317 + {
1.318 + Kern::Printf("Error checking size iIoBuffer->iSize=%d size=%d\n",iIoBuffer->iSize,size);
1.319 + return KErrGeneral;
1.320 + }
1.321 + memset((void*)iIoBuffer->iAddress,0,size);
1.322 + }
1.323 + return r;
1.324 +
1.325 + case RTestLdd::EMapInGlobalBuffer:
1.326 + {
1.327 + if(!iGlobalBuffer)
1.328 + return KErrGeneral;
1.329 +
1.330 + TUint id;
1.331 + kumemget32(&id,a1,sizeof(TUint));
1.332 +
1.333 + NKern::ThreadEnterCS();
1.334 + Kern::Containers()[EProcess]->Wait();
1.335 + DProcess* process=Kern::ProcessFromId(id);
1.336 + if(process)
1.337 + process->Open();
1.338 + Kern::Containers()[EProcess]->Signal();
1.339 + if(process)
1.340 + {
1.341 + r=iGlobalBuffer->UserMap(process);
1.342 + process->Close(0);
1.343 + }
1.344 + else
1.345 + r = KErrGeneral;
1.346 + NKern::ThreadLeaveCS();
1.347 +
1.348 + if(r!=KErrNone)
1.349 + return r;
1.350 +
1.351 + if(iGlobalBuffer->UserToKernel(iGlobalBuffer->iUserAddress,iGlobalBuffer->iSize)!=iGlobalBuffer->iAddress)
1.352 + return KErrGeneral;
1.353 +
1.354 + if(iGlobalBuffer->UserToKernel(iGlobalBuffer->iUserAddress,iGlobalBuffer->iSize+1)!=NULL)
1.355 + return KErrGeneral;
1.356 +
1.357 + if(iGlobalBuffer->KernelToUser(iGlobalBuffer->iAddress)!=iGlobalBuffer->iUserAddress)
1.358 + return KErrGeneral;
1.359 +
1.360 + kumemput32(a1,&iGlobalBuffer->iUserAddress,sizeof(TAny*));
1.361 + kumemput32(a2,&iGlobalBuffer->iSize,sizeof(TInt));
1.362 +
1.363 + return KErrNone;
1.364 + }
1.365 +
1.366 + case RTestLdd::EMapOutGlobalBuffer:
1.367 + {
1.368 + if(!iGlobalBuffer)
1.369 + return KErrGeneral;
1.370 + r=iGlobalBuffer->UserUnmap();
1.371 + if(r==KErrNone)
1.372 + if(iGlobalBuffer->iUserProcess)
1.373 + r = KErrGeneral;
1.374 + return r;
1.375 + }
1.376 +
1.377 + case RTestLdd::EDestroyGlobalBuffer:
1.378 + {
1.379 + NKern::ThreadEnterCS();
1.380 + delete iGlobalBuffer;
1.381 + iGlobalBuffer = NULL;
1.382 + iFactory->iGlobalBuffer=NULL;
1.383 + NKern::ThreadLeaveCS();
1.384 + return KErrNone;
1.385 + }
1.386 +
1.387 + case RTestLdd::ECreateBufferPhysAddr:
1.388 + {
1.389 +#ifdef __WINS__
1.390 + return KErrNotSupported;
1.391 +#else
1.392 + TUint32 size=Kern::RoundToPageSize(1);
1.393 + NKern::ThreadEnterCS();
1.394 + r=Epoc::AllocPhysicalRam(size,iPhysAddress);
1.395 + Kern::Printf("phys addr = %X!\n",iPhysAddress);
1.396 + if(r!=KErrNone)
1.397 + {
1.398 + NKern::ThreadLeaveCS();
1.399 + return r;
1.400 + }
1.401 + r = KErrNoMemory;
1.402 +
1.403 + //test that we can construct a fully cached sharedio
1.404 + DSharedIoBuffer* ptr;
1.405 + r=DSharedIoBuffer::New(ptr,iPhysAddress,size,EMapAttrSupRw|EMapAttrCachedMax);
1.406 + if(r!=KErrNone)
1.407 + {
1.408 + Kern::Printf("Error creating the physical cached buffer r=%d\n",r);
1.409 + Epoc::FreePhysicalRam(iPhysAddress,size);
1.410 + iPhysAddress=0;
1.411 + NKern::ThreadLeaveCS();
1.412 + return r;
1.413 + }
1.414 + delete ptr; //creation successfull, simply delete the object
1.415 +
1.416 +
1.417 + r=DSharedIoBuffer::New(iIoBuffer,iPhysAddress,size,EMapAttrSupRw|EMapAttrFullyBlocking);
1.418 + if(r!=KErrNone)
1.419 + {
1.420 + Epoc::FreePhysicalRam(iPhysAddress,size);
1.421 + iPhysAddress=0;
1.422 + NKern::ThreadLeaveCS();
1.423 + return r;
1.424 + }
1.425 +
1.426 + if(iIoBuffer->iSize!=size) // test
1.427 + {
1.428 + delete iIoBuffer;
1.429 + iIoBuffer=NULL;
1.430 + Epoc::FreePhysicalRam(iPhysAddress,size);
1.431 + iPhysAddress=0;
1.432 + NKern::ThreadLeaveCS();
1.433 + return KErrGeneral;
1.434 + }
1.435 +
1.436 + fillBuffer((TAny*)iIoBuffer->iAddress,size,180);
1.437 +
1.438 + DPlatChunkHw* hwChunk;
1.439 + r=DPlatChunkHw::New(hwChunk, iPhysAddress, size, EMapAttrSupRw|EMapAttrFullyBlocking);
1.440 + if(r!=KErrNone)
1.441 + {
1.442 + delete iIoBuffer;
1.443 + iIoBuffer=NULL;
1.444 + Epoc::FreePhysicalRam(iPhysAddress,size);
1.445 + iPhysAddress=0;
1.446 + NKern::ThreadLeaveCS();
1.447 + return r;
1.448 + }
1.449 +
1.450 + r=checkBuffer((TAny*)hwChunk->LinearAddress(),size,180);
1.451 + if(r!=KErrNone)
1.452 + {
1.453 + delete iIoBuffer;
1.454 + iIoBuffer=NULL;
1.455 + hwChunk->Close(NULL);
1.456 + Epoc::FreePhysicalRam(iPhysAddress,size);
1.457 + iPhysAddress=0;
1.458 + NKern::ThreadLeaveCS();
1.459 + return r;
1.460 + }
1.461 +
1.462 + hwChunk->Close(NULL);
1.463 + NKern::ThreadLeaveCS();
1.464 + return r;
1.465 +#endif
1.466 + }
1.467 +
1.468 + case RTestLdd::EDestroyBufferPhysAddr:
1.469 + {
1.470 +#ifdef __WINS__
1.471 + return KErrNotSupported;
1.472 +#else
1.473 + TUint32 size=Kern::RoundToPageSize(1);
1.474 + NKern::ThreadEnterCS();
1.475 + delete iIoBuffer;
1.476 + iIoBuffer = NULL;
1.477 + r=Epoc::FreePhysicalRam(iPhysAddress,size);
1.478 + iPhysAddress=0;
1.479 + NKern::ThreadLeaveCS();
1.480 + return r;
1.481 +#endif
1.482 + }
1.483 +
1.484 +
1.485 + case RTestLdd::EMapInBuffer:
1.486 + {
1.487 + r=iIoBuffer->UserMap(&Kern::CurrentProcess());
1.488 + if(r!=KErrNone)
1.489 + return r;
1.490 +
1.491 + TAny** p = (TAny**)iIoBuffer->iAddress;
1.492 + TAny* ua = (TAny*)iIoBuffer->iUserAddress;
1.493 + TAny** end = (TAny**)((TInt)p+iIoBuffer->iSize);
1.494 + while(p<end)
1.495 + {
1.496 + *p++ = ua;
1.497 + ua = (TAny*)((TInt)ua+sizeof(TAny*));
1.498 + }
1.499 + if(iIoBuffer->UserToKernel(iIoBuffer->iUserAddress,iIoBuffer->iSize)!=iIoBuffer->iAddress)
1.500 + return KErrGeneral;
1.501 +
1.502 + if(iIoBuffer->UserToKernel(iIoBuffer->iUserAddress,iIoBuffer->iSize+1)!=NULL)
1.503 + return KErrGeneral;
1.504 +
1.505 + if(iIoBuffer->KernelToUser(iIoBuffer->iAddress)!=iIoBuffer->iUserAddress)
1.506 + return KErrGeneral;
1.507 + kumemput32(a1,&iIoBuffer->iUserAddress,sizeof(TAny*));
1.508 + kumemput32(a2,&iIoBuffer->iSize,sizeof(TInt));
1.509 + return r;
1.510 + }
1.511 +
1.512 + case RTestLdd::EMapOutBuffer:
1.513 + {
1.514 + r=iIoBuffer->UserUnmap();
1.515 + if(r==KErrNone)
1.516 + if(iIoBuffer->iUserProcess)
1.517 + r = KErrGeneral;
1.518 + return r;
1.519 + }
1.520 +
1.521 + case RTestLdd::EDestroyBuffer:
1.522 + NKern::ThreadEnterCS();
1.523 + delete iIoBuffer;
1.524 + iIoBuffer = NULL;
1.525 + NKern::ThreadLeaveCS();
1.526 + return KErrNone;
1.527 +
1.528 + case RTestLdd::ECheckBuffer:
1.529 + if(!iIoBuffer->iAddress || !iIoBuffer->iUserAddress || !iIoBuffer->iUserProcess)
1.530 + return KErrGeneral;
1.531 + return checkBuffer((TAny*)iIoBuffer->iAddress,iIoBuffer->iSize,(TUint32)a1);
1.532 +
1.533 + case RTestLdd::EFillBuffer:
1.534 + if(!iIoBuffer->iAddress || !iIoBuffer->iUserAddress || !iIoBuffer->iUserProcess)
1.535 + return KErrGeneral;
1.536 + return fillBuffer((TAny*)iIoBuffer->iAddress,iIoBuffer->iSize,(TUint32)a1);
1.537 +
1.538 + case RTestLdd::EThreadRW:
1.539 + {
1.540 + TInt dummy;
1.541 + TPckg<TInt> a(dummy);
1.542 + DThread* pT;
1.543 + if((TInt)a2==-1)
1.544 + {
1.545 + pT=&Kern::CurrentThread();
1.546 + }
1.547 + else
1.548 + {
1.549 + NKern::ThreadEnterCS();
1.550 + DObjectCon* pC=Kern::Containers()[EThread];
1.551 + pC->Wait();
1.552 + pT=Kern::ThreadFromId((TInt)a2);
1.553 + pC->Signal();
1.554 + if(!pT)
1.555 + return KErrNotFound;
1.556 + NKern::ThreadLeaveCS();
1.557 + }
1.558 + r=Kern::ThreadDesRead(pT,a1,a,0,KChunkShiftBy0);
1.559 + if(r!=KErrNone)
1.560 + return r;
1.561 + if(dummy!=KMagic1)
1.562 + return KErrCorrupt;
1.563 + dummy=KMagic2;
1.564 + r=Kern::ThreadDesWrite(pT,a1,a,0,KChunkShiftBy0,&Kern::CurrentThread());
1.565 + if(r!=KErrNone)
1.566 + return r;
1.567 + return KErrNone;
1.568 + }
1.569 +
1.570 + default:
1.571 + r=KErrNotSupported;
1.572 + break;
1.573 + }
1.574 + return r;
1.575 + }
1.576 +