os/kernelhwsrv/kerneltest/e32test/mmu/t_pin.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.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\mmu\t_pin.cpp
sl@0
    15
// Tests kernel APIs for logical pinning by pinning memory and using a realtime thread to check that
sl@0
    16
// no page faults are taken while accessing it.
sl@0
    17
// 
sl@0
    18
//
sl@0
    19
sl@0
    20
#define __E32TEST_EXTENSION__
sl@0
    21
#include <e32test.h>
sl@0
    22
#include <e32svr.h>
sl@0
    23
#include <e32rom.h>
sl@0
    24
#include <e32kpan.h>
sl@0
    25
#include <u32hal.h>
sl@0
    26
#include <dptest.h>
sl@0
    27
#include "d_memorytest.h"
sl@0
    28
#include "t_codepaging_dll.h"
sl@0
    29
#include "mmudetect.h"
sl@0
    30
#include "freeram.h"
sl@0
    31
sl@0
    32
RTest test(_L("T_PIN"));
sl@0
    33
sl@0
    34
_LIT(KTCodePagingDll4, "t_codepaging_dll4.dll");
sl@0
    35
const TInt KMinBufferSize = 16384;
sl@0
    36
sl@0
    37
RMemoryTestLdd Ldd;
sl@0
    38
RMemoryTestLdd Ldd2;
sl@0
    39
RLibrary PagedLibrary;
sl@0
    40
const TUint8* PagedBuffer = NULL;
sl@0
    41
const TUint8* UnpagedBuffer = NULL;
sl@0
    42
TInt PageSize;
sl@0
    43
sl@0
    44
TInt FreeRamNoWait()
sl@0
    45
	{
sl@0
    46
	TMemoryInfoV1Buf meminfo;
sl@0
    47
	UserHal::MemoryInfo(meminfo);
sl@0
    48
	return meminfo().iFreeRamInBytes;
sl@0
    49
	}
sl@0
    50
sl@0
    51
void CheckMemoryPresent(const TUint8* aBuffer, TInt aSize, TBool aExpected)
sl@0
    52
	{
sl@0
    53
	if (aExpected)
sl@0
    54
		test.Printf(_L("  Checking memory at %08x is present\n"), aBuffer);
sl@0
    55
	else
sl@0
    56
		test.Printf(_L("  Checking memory at %08x is not present\n"), aBuffer);
sl@0
    57
	for (TInt i = 0 ; i < aSize ; i += PageSize)
sl@0
    58
		test_Equal(aExpected, Ldd.IsMemoryPresent(aBuffer + i));
sl@0
    59
	}
sl@0
    60
sl@0
    61
void FlushPagingCache()
sl@0
    62
	{
sl@0
    63
	test_KErrNone(DPTest::FlushCache());
sl@0
    64
	}
sl@0
    65
sl@0
    66
void TestPinVirtualMemoryUnpaged()
sl@0
    67
	{
sl@0
    68
	test.Printf(_L("Create logical pin object\n"));
sl@0
    69
	test_KErrNone(Ldd.CreateVirtualPinObject());
sl@0
    70
#ifdef __EPOC32__
sl@0
    71
	CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue);
sl@0
    72
	test.Printf(_L("Perform logical pin operation on zero-length buffer\n"));
sl@0
    73
	test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, 0));
sl@0
    74
	CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue);
sl@0
    75
	test.Printf(_L("Perform logical unpin operation\n"));
sl@0
    76
	test_KErrNone(Ldd.UnpinVirtualMemory());
sl@0
    77
	CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue);
sl@0
    78
	test.Printf(_L("Perform logical pin operation on whole buffer\n"));
sl@0
    79
	test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, KMinBufferSize));
sl@0
    80
	CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue);
sl@0
    81
	test.Printf(_L("Perform logical unpin operation\n"));
sl@0
    82
	test_KErrNone(Ldd.UnpinVirtualMemory());
sl@0
    83
	CheckMemoryPresent(UnpagedBuffer, KMinBufferSize, ETrue);
sl@0
    84
#else
sl@0
    85
	// Don't check for memory presence on emulator as paging not supported.
sl@0
    86
	test.Printf(_L("Perform logical pin operation on zero-length buffer\n"));
sl@0
    87
	test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, 0));
sl@0
    88
	test.Printf(_L("Perform logical unpin operation\n"));
sl@0
    89
	test_KErrNone(Ldd.UnpinVirtualMemory());
sl@0
    90
	test.Printf(_L("Perform logical pin operation on whole buffer\n"));
sl@0
    91
	test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)UnpagedBuffer, KMinBufferSize));
sl@0
    92
	test.Printf(_L("Perform logical unpin operation\n"));
sl@0
    93
	test_KErrNone(Ldd.UnpinVirtualMemory());
sl@0
    94
#endif
sl@0
    95
	test.Printf(_L("Perform logical unpin operation (again)\n"));
sl@0
    96
	test_KErrNone(Ldd.UnpinVirtualMemory());	// test double unpin ok
sl@0
    97
	test.Printf(_L("Destroy logical pin object\n"));
sl@0
    98
	test_KErrNone(Ldd.DestroyVirtualPinObject());
sl@0
    99
	test.Printf(_L("Destroy logical pin object (again)\n"));
sl@0
   100
	test_KErrNone(Ldd.DestroyVirtualPinObject());  // test double destroy ok
sl@0
   101
	}
sl@0
   102
sl@0
   103
void TestPinPhysicalMemory()
sl@0
   104
	{
sl@0
   105
	
sl@0
   106
	TInt mm = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0) & EMemModelTypeMask;
sl@0
   107
	if (mm < EMemModelTypeFlexible)
sl@0
   108
		{
sl@0
   109
		test.Printf(_L("Memory model (%d) doesn't support physical pining\n"),mm);
sl@0
   110
		return;
sl@0
   111
		}
sl@0
   112
	TInt i;
sl@0
   113
	TInt8* UCBase;
sl@0
   114
	RChunk chunk;
sl@0
   115
sl@0
   116
	test.Printf(_L("Allocate user chunk\n"));
sl@0
   117
	TChunkCreateInfo createInfo;
sl@0
   118
	createInfo.SetDisconnected(0,KUCPageCount*PageSize,KUCPageCount*PageSize);
sl@0
   119
	createInfo.SetPaging(TChunkCreateInfo::EPaged);
sl@0
   120
	test_KErrNone(chunk.Create(createInfo));
sl@0
   121
	UCBase = (TInt8*)chunk.Base();
sl@0
   122
	
sl@0
   123
	test.Printf(_L("Create physical pin object\n"));
sl@0
   124
	test_KErrNone(Ldd.CreatePhysicalPinObject());
sl@0
   125
sl@0
   126
	test.Printf(_L("Perform physical pin operation on zero-length buffer\n"));
sl@0
   127
	test_KErrNone(Ldd.PinPhysicalMemory((TLinAddr)UCBase, 0));	
sl@0
   128
sl@0
   129
	test.Printf(_L("Perform physical unpin operation\n"));
sl@0
   130
	test_KErrNone(Ldd.UnpinPhysicalMemory());	
sl@0
   131
sl@0
   132
	test.Printf(_L("Perform Physical pin operation on the chunk\n"));
sl@0
   133
	test_KErrNone(Ldd.PinPhysicalMemory((TLinAddr)UCBase, KUCPageCount*PageSize));	
sl@0
   134
sl@0
   135
	test.Printf(_L("Test that pinned physical memory preserves its mapping when recommited\n"));
sl@0
   136
	test_KErrNone(chunk.Decommit(0,KUCPageCount*PageSize));							 //Decommit all
sl@0
   137
	for (i=KUCPageCount-1;i>=0;i--) test_KErrNone(chunk.Commit(i*PageSize,PageSize)); //Commit in reverse order
sl@0
   138
	for (i=0;i<KUCPageCount;i++) // Recommited memory is not paged in. So, write into each page, before driver 
sl@0
   139
		{						// calls Kern::LinearToPhysical or it will get KErrInvalidMemory in return.
sl@0
   140
		volatile TInt8* ptr = (volatile TInt8*)(UCBase+i*PageSize);
sl@0
   141
		*ptr = 10;
sl@0
   142
		}
sl@0
   143
	test_KErrNone(Ldd.CheckPageList(chunk.Base())); 					// Check that the mapping is preserved. 	
sl@0
   144
	
sl@0
   145
	test.Printf(_L("Sync cache & memory of User Chunk\n"));//Test Cache::SyncPhysicalMemoryBeforeDmaWrite
sl@0
   146
	test_KErrNone(Ldd.SyncPinnedPhysicalMemory(0,KUCPageCount*PageSize));
sl@0
   147
sl@0
   148
	test.Printf(_L("Invalidate cache of User Chunk\n"));//Test Cache::SyncPhysicalMemoryBefore/AfterDmaRead
sl@0
   149
	test_KErrNone(Ldd.InvalidatePinnedPhysicalMemory(0,KUCPageCount*PageSize));
sl@0
   150
	
sl@0
   151
	test.Printf(_L("Try to move pinned phys. memory...\n")); //RAM defrag should return error code here.
sl@0
   152
	i = Ldd.MovePinnedPhysicalMemory(0);
sl@0
   153
	test.Printf(_L("...returned %d\n"),i);
sl@0
   154
	test(i!=KErrNone);
sl@0
   155
sl@0
   156
	test.Printf(_L("Close the chunk\n")); // Phys. memory is pinned and shouldn't be ...
sl@0
   157
	chunk.Close();						  // ... mapped to another virtual memory.
sl@0
   158
sl@0
   159
	test.Printf(_L("Allocate & initilise the second chunk\n"));// Kernel sholudn't commit pinned physical memory ...
sl@0
   160
	test_KErrNone(chunk.CreateLocal(KUCPageCount*PageSize,KUCPageCount*PageSize));   // ...that has been just decommited from the first chunk.
sl@0
   161
	UCBase = (TInt8*)chunk.Base();
sl@0
   162
	for (i=0;i<KUCPageCount*PageSize;i++) UCBase[i]=0; //Initialise user buffer
sl@0
   163
sl@0
   164
	test.Printf(_L("Invalidate cache of pinned memory\n"));//This shouldn't affect the second chunk.
sl@0
   165
	test_KErrNone(Ldd.InvalidatePinnedPhysicalMemory(0,KUCPageCount*PageSize));
sl@0
   166
sl@0
   167
	test.Printf(_L("Check data in the second chunk is unaffected\n"));
sl@0
   168
	for (i=0;i<KUCPageCount*PageSize;i++) test(UCBase[i]==0);
sl@0
   169
	
sl@0
   170
	test.Printf(_L("Close the second chunk\n"));
sl@0
   171
	chunk.Close();
sl@0
   172
sl@0
   173
	test.Printf(_L("Perform physical unpin operation\n"));
sl@0
   174
	test_KErrNone(Ldd.UnpinPhysicalMemory());	
sl@0
   175
sl@0
   176
	test.Printf(_L("Perform physical unpin operation (again)\n"));
sl@0
   177
	test_KErrNone(Ldd.UnpinPhysicalMemory());	// test double unpin ok
sl@0
   178
sl@0
   179
	test.Printf(_L("Destroy physical pin object\n"));
sl@0
   180
	test_KErrNone(Ldd.DestroyPhysicalPinObject());
sl@0
   181
sl@0
   182
	test.Printf(_L("Destroy physical pin object (again)\n"));
sl@0
   183
	test_KErrNone(Ldd.DestroyPhysicalPinObject());  // test double destroy ok
sl@0
   184
sl@0
   185
	test.Printf(_L("Test phys. pinning and sync of kernel memory.\n"));
sl@0
   186
	test_KErrNone(Ldd.PinKernelPhysicalMemory());// Simple test of phys. pinning of kernel memory
sl@0
   187
	}
sl@0
   188
sl@0
   189
void TestPhysicalPinOutOfMemory()
sl@0
   190
	{
sl@0
   191
	TInt mm = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0) & EMemModelTypeMask;
sl@0
   192
	if (mm < EMemModelTypeFlexible)
sl@0
   193
		{
sl@0
   194
		test.Printf(_L("Memory model (%d) doesn't support physical pining\n"),mm);
sl@0
   195
		return;
sl@0
   196
		}
sl@0
   197
	
sl@0
   198
	TInt8* UCBase;
sl@0
   199
	RChunk chunk;
sl@0
   200
sl@0
   201
	test.Printf(_L("Allocate user chunk\n"));
sl@0
   202
	test_KErrNone(chunk.CreateDisconnectedLocal(0,KUCPageCount*PageSize,KUCPageCount*PageSize));
sl@0
   203
	UCBase = (TInt8*)chunk.Base();
sl@0
   204
	
sl@0
   205
	const TInt KMaxKernelAllocations = 1024;
sl@0
   206
	TInt r=KErrNoMemory;
sl@0
   207
	TInt i;
sl@0
   208
sl@0
   209
	__KHEAP_MARK;
sl@0
   210
	for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++)
sl@0
   211
		{
sl@0
   212
		__KHEAP_FAILNEXT(i);
sl@0
   213
		test.Printf(_L("Create physical pin object\n"));
sl@0
   214
		r = Ldd.CreatePhysicalPinObject();
sl@0
   215
		__KHEAP_RESET;
sl@0
   216
		}
sl@0
   217
	test.Printf(_L("Create physical pin object took %d tries\n"),i);
sl@0
   218
	test_KErrNone(r);
sl@0
   219
sl@0
   220
	r = KErrNoMemory;
sl@0
   221
sl@0
   222
	for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++)
sl@0
   223
		{
sl@0
   224
		__KHEAP_FAILNEXT(i);
sl@0
   225
		test.Printf(_L("Perform physical pin operation\n"));
sl@0
   226
		r = Ldd.PinPhysicalMemory((TLinAddr)UCBase, KUCPageCount*PageSize);
sl@0
   227
		__KHEAP_RESET;
sl@0
   228
		}
sl@0
   229
	test.Printf(_L("Perform physical pin operation took %d tries\n"),i);
sl@0
   230
	if (r == KErrNone)
sl@0
   231
		{
sl@0
   232
		test.Printf(_L("Perform physical unpin operation\n"));
sl@0
   233
		Ldd.UnpinPhysicalMemory();
sl@0
   234
		}
sl@0
   235
sl@0
   236
	test.Printf(_L("Destroy physical pin object\n"));
sl@0
   237
	Ldd.DestroyPhysicalPinObject();
sl@0
   238
sl@0
   239
	// wait for any async cleanup in the supervisor to finish first...
sl@0
   240
	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);	
sl@0
   241
	__KHEAP_MARKEND;
sl@0
   242
sl@0
   243
	test.Printf(_L("Close the chunk\n"));
sl@0
   244
	chunk.Close();
sl@0
   245
	
sl@0
   246
	test_KErrNone(r);
sl@0
   247
	}
sl@0
   248
sl@0
   249
sl@0
   250
void TestPinVirtualMemoryInvalid()
sl@0
   251
	{
sl@0
   252
	test.Printf(_L("Create logical pin object\n"));
sl@0
   253
	test_KErrNone(Ldd.CreateVirtualPinObject());
sl@0
   254
	test.Printf(_L("Attempt logical pin on bad memory address\n"));
sl@0
   255
	TLinAddr bad = (TLinAddr)0x10000;
sl@0
   256
	TInt r = Ldd.PinVirtualMemory(bad,KMinBufferSize);
sl@0
   257
	test.Printf(_L("%08x r=%d"),bad,r);
sl@0
   258
	if(r==KErrNone)
sl@0
   259
		test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   260
	if ((MemModelAttributes() & EMemModelTypeMask) == EMemModelTypeMultiple)
sl@0
   261
		{
sl@0
   262
		// test unused part of code chunk...
sl@0
   263
		bad = (TLinAddr)0x7f000000;
sl@0
   264
		r = Ldd.PinVirtualMemory(bad,KMinBufferSize);
sl@0
   265
		test.Printf(_L("%08x r=%d"),bad,r);
sl@0
   266
		if(r==KErrNone)
sl@0
   267
			test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   268
		}
sl@0
   269
	test.Printf(_L("Destroy logical pin object\n"));
sl@0
   270
	test_KErrNone(Ldd.DestroyVirtualPinObject());
sl@0
   271
	}
sl@0
   272
sl@0
   273
void TestPinVirtualMemoryPaged()
sl@0
   274
	{
sl@0
   275
	test.Printf(_L("Create logical pin object\n"));
sl@0
   276
	test_KErrNone(Ldd.CreateVirtualPinObject());
sl@0
   277
	FlushPagingCache();
sl@0
   278
	CheckMemoryPresent(PagedBuffer, KMinBufferSize, EFalse);
sl@0
   279
	test.Printf(_L("Perform logical pin operation on zero-length buffer\n"));
sl@0
   280
	test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)PagedBuffer, 0));	
sl@0
   281
	CheckMemoryPresent(PagedBuffer, KMinBufferSize, EFalse);
sl@0
   282
	test.Printf(_L("Perform logical unpin operation\n"));
sl@0
   283
	test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   284
	CheckMemoryPresent(PagedBuffer, KMinBufferSize, EFalse);
sl@0
   285
	test.Printf(_L("Perform logical pin operation on whole buffer\n"));
sl@0
   286
	test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)PagedBuffer, KMinBufferSize));	
sl@0
   287
	CheckMemoryPresent(PagedBuffer, KMinBufferSize, ETrue);
sl@0
   288
	FlushPagingCache();
sl@0
   289
	CheckMemoryPresent(PagedBuffer, KMinBufferSize, ETrue);
sl@0
   290
	test.Printf(_L("Perform logical unpin operation\n"));
sl@0
   291
	test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   292
	CheckMemoryPresent(PagedBuffer, KMinBufferSize, ETrue);
sl@0
   293
	FlushPagingCache();
sl@0
   294
	CheckMemoryPresent(PagedBuffer, KMinBufferSize, EFalse);
sl@0
   295
	test.Printf(_L("Perform logical unpin operation (again)\n"));
sl@0
   296
	test_KErrNone(Ldd.UnpinVirtualMemory());	// test double unpin ok
sl@0
   297
	test.Printf(_L("Destroy logical pin object\n"));
sl@0
   298
	test_KErrNone(Ldd.DestroyVirtualPinObject());
sl@0
   299
	test.Printf(_L("Destroy logical pin object (again)\n"));
sl@0
   300
	test_KErrNone(Ldd.DestroyVirtualPinObject());  // test double destroy ok
sl@0
   301
	}
sl@0
   302
sl@0
   303
sl@0
   304
volatile TBool SoakEnd = false;
sl@0
   305
sl@0
   306
class TRandom
sl@0
   307
	{
sl@0
   308
public:
sl@0
   309
	TRandom(TUint32 aSeed)
sl@0
   310
		: iSeed(aSeed) {};
sl@0
   311
	inline TUint32 Next()
sl@0
   312
		{ iSeed = iSeed*69069+1; return iSeed; }
sl@0
   313
	TUint32 operator()(TUint32 aRange)
sl@0
   314
		{ return (TUint32)((TUint64(Next())*TUint64(aRange))>>32); }
sl@0
   315
private:
sl@0
   316
	TUint iSeed;
sl@0
   317
	};
sl@0
   318
sl@0
   319
#define SOAK_CHECK(r)												\
sl@0
   320
	if(r!=KErrNone)													\
sl@0
   321
		{															\
sl@0
   322
		RDebug::Printf("SOAK_CHECK fail at line %d",__LINE__);		\
sl@0
   323
		return r;													\
sl@0
   324
		}															\
sl@0
   325
sl@0
   326
TInt SoakThread(TAny*)
sl@0
   327
	{
sl@0
   328
	RMemoryTestLdd ldd;
sl@0
   329
	TInt r = ldd.Open();
sl@0
   330
	SOAK_CHECK(r)
sl@0
   331
sl@0
   332
	r = ldd.CreateVirtualPinObject();
sl@0
   333
	SOAK_CHECK(r)
sl@0
   334
sl@0
   335
	TRandom random((TUint32)&ldd);
sl@0
   336
sl@0
   337
	while(!SoakEnd)
sl@0
   338
		{
sl@0
   339
		TUint start = random(KMinBufferSize);
sl@0
   340
		TUint end = random(KMinBufferSize);
sl@0
   341
		if(start>end)
sl@0
   342
			{
sl@0
   343
			TUint temp = start;
sl@0
   344
			start = end;
sl@0
   345
			end = temp;
sl@0
   346
			}
sl@0
   347
		const TUint32 KPageMask = 0xfff;
sl@0
   348
		start &= ~KPageMask;
sl@0
   349
		end = (end+KPageMask)&~KPageMask;
sl@0
   350
sl@0
   351
		r = ldd.PinVirtualMemory((TLinAddr)(PagedBuffer+start),end-start);
sl@0
   352
		SOAK_CHECK(r)
sl@0
   353
sl@0
   354
		r = ldd.UnpinVirtualMemory();
sl@0
   355
		SOAK_CHECK(r)
sl@0
   356
		}
sl@0
   357
sl@0
   358
	r = ldd.DestroyVirtualPinObject();
sl@0
   359
	SOAK_CHECK(r)
sl@0
   360
sl@0
   361
	CLOSE_AND_WAIT(ldd);
sl@0
   362
	return KErrNone;
sl@0
   363
	}
sl@0
   364
sl@0
   365
sl@0
   366
void TestPinVirtualMemoryPagedSoak()
sl@0
   367
	{
sl@0
   368
	test.Start(_L("Create timer"));
sl@0
   369
	RTimer timer;
sl@0
   370
	test_KErrNone(timer.CreateLocal());
sl@0
   371
sl@0
   372
	test.Next(_L("Create threads"));
sl@0
   373
	const TUint KNumThreads = 4;
sl@0
   374
	TRequestStatus status[KNumThreads];
sl@0
   375
	RThread thread[KNumThreads];
sl@0
   376
	TUint i;
sl@0
   377
	for(i=0; i<KNumThreads; i++)
sl@0
   378
		{
sl@0
   379
		test_KErrNone(thread[i].Create(KNullDesC, SoakThread, 0x1000, NULL, 0));
sl@0
   380
		thread[i].Logon(status[i]);
sl@0
   381
		test(status[i].Int()==KRequestPending);
sl@0
   382
		}
sl@0
   383
sl@0
   384
	test.Next(_L("Start threads"));
sl@0
   385
	RThread().SetPriority(EPriorityMore); // make sure we are higher priority than soak threads
sl@0
   386
	for(i=0; i<KNumThreads; i++)
sl@0
   387
		thread[i].Resume();
sl@0
   388
sl@0
   389
	test.Next(_L("Wait..."));
sl@0
   390
	TRequestStatus timeoutStatus;
sl@0
   391
	timer.After(timeoutStatus,10*1000000);
sl@0
   392
	User::WaitForAnyRequest();
sl@0
   393
	test_KErrNone(timeoutStatus.Int()); // we should have timed out if soak threads are still running OK
sl@0
   394
sl@0
   395
	test.Next(_L("Stop threads and check results"));
sl@0
   396
	for(i=0; i<KNumThreads; i++)
sl@0
   397
		test_Equal(KRequestPending,status[i].Int());
sl@0
   398
	SoakEnd = true;
sl@0
   399
	timer.After(timeoutStatus,10*1000000);
sl@0
   400
	for(i=0; i<KNumThreads; i++)
sl@0
   401
		{
sl@0
   402
		User::WaitForAnyRequest();
sl@0
   403
		test_Equal(KRequestPending,timeoutStatus.Int());
sl@0
   404
		}
sl@0
   405
	timer.Cancel();
sl@0
   406
	User::WaitForRequest(timeoutStatus);
sl@0
   407
	RThread().SetPriority(EPriorityNormal); // restore thread priority
sl@0
   408
sl@0
   409
	// cleanup...
sl@0
   410
	CLOSE_AND_WAIT(timer);
sl@0
   411
	for(i=0; i<KNumThreads; i++)
sl@0
   412
		CLOSE_AND_WAIT(thread[i]);
sl@0
   413
sl@0
   414
	test.End();
sl@0
   415
	}
sl@0
   416
sl@0
   417
sl@0
   418
void TestPinVirtualMemoryDecommit()
sl@0
   419
	{
sl@0
   420
	const TInt KChunk = 4*1024*1024; // offset of page table boundary on X86 and ARM
sl@0
   421
	const TInt KPage = PageSize;
sl@0
   422
	const TInt TestData[][2] =
sl@0
   423
		{
sl@0
   424
			{0,				KPage},
sl@0
   425
			{KPage,			KPage},
sl@0
   426
			{KPage,			2*KPage},
sl@0
   427
			{KChunk-KPage,	KPage},
sl@0
   428
			{KChunk-2*KPage,2*KPage},
sl@0
   429
			{KChunk-KPage,	2*KPage},
sl@0
   430
			{0,0} // end marker
sl@0
   431
		};
sl@0
   432
sl@0
   433
	for(TInt i=0; TestData[i][1]; ++i)
sl@0
   434
		{
sl@0
   435
		TInt commitOffset = TestData[i][0];
sl@0
   436
		TInt commitSize = TestData[i][1];
sl@0
   437
		test.Printf(_L("Create chunk 0x%x+0x%x\n"),commitOffset,commitSize);
sl@0
   438
sl@0
   439
		TChunkCreateInfo createInfo;
sl@0
   440
		createInfo.SetDisconnected(commitOffset,commitOffset+commitSize,commitOffset+commitSize);
sl@0
   441
		createInfo.SetPaging(TChunkCreateInfo::EPaged);
sl@0
   442
		RChunk chunk;
sl@0
   443
		test_KErrNone(chunk.Create(createInfo));
sl@0
   444
		TUint8* buffer = chunk.Base()+commitOffset;
sl@0
   445
		TUint bufferSize = commitSize;
sl@0
   446
		FlushPagingCache(); // start with blank slate as far as paged memory is concerned
sl@0
   447
sl@0
   448
		test.Printf(_L("Create virtual pin object\n"));
sl@0
   449
		test_KErrNone(Ldd.CreateVirtualPinObject());
sl@0
   450
		test_KErrNone(Ldd2.CreateVirtualPinObject());
sl@0
   451
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   452
		TInt initialFreeRam = FreeRam();
sl@0
   453
sl@0
   454
		test.Printf(_L("Pin memory\n"));
sl@0
   455
		test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)buffer, bufferSize));	
sl@0
   456
		CheckMemoryPresent(buffer, bufferSize, ETrue);
sl@0
   457
		TInt pinnedFreeRam = FreeRam();
sl@0
   458
		test_Compare(pinnedFreeRam,<,initialFreeRam);
sl@0
   459
		TUint8 c = *buffer;
sl@0
   460
		memset(buffer,~c,bufferSize); // invert memory
sl@0
   461
sl@0
   462
		test.Printf(_L("Decommit pinned memory\n"));
sl@0
   463
		test_KErrNone(chunk.Decommit(commitOffset,commitSize));	
sl@0
   464
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   465
		test_Equal(pinnedFreeRam,FreeRam()); // decommited memory should not be freed as it is pinned
sl@0
   466
sl@0
   467
		test.Printf(_L("Unpin memory\n"));
sl@0
   468
		test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   469
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   470
		test_Equal(initialFreeRam,FreeRam()); // memory should be now freed
sl@0
   471
sl@0
   472
		//
sl@0
   473
		// test recommitting decommitted pinned memory...
sl@0
   474
		//
sl@0
   475
sl@0
   476
		test.Printf(_L("Commit memory\n"));
sl@0
   477
		test_KErrNone(chunk.Commit(commitOffset,commitSize));	
sl@0
   478
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   479
		test_Equal(initialFreeRam,FreeRam());
sl@0
   480
sl@0
   481
		test.Printf(_L("Read memory\n"));
sl@0
   482
		volatile TUint8* p = buffer;
sl@0
   483
		volatile TUint8* pEnd = buffer+bufferSize;
sl@0
   484
		while(p<pEnd)
sl@0
   485
			test_Equal(c,*p++); // memory should have been wiped
sl@0
   486
		test_Equal(initialFreeRam,FreeRam()); // memory now paged in
sl@0
   487
sl@0
   488
		test.Printf(_L("Pin memory which is already paged in\n"));
sl@0
   489
		test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)buffer, bufferSize));	
sl@0
   490
		CheckMemoryPresent(buffer, bufferSize, ETrue);
sl@0
   491
		test_Equal(pinnedFreeRam,FreeRam());
sl@0
   492
		memset(buffer,~c,bufferSize); // invert memory
sl@0
   493
sl@0
   494
		test.Printf(_L("Decommit pinned memory\n"));
sl@0
   495
		test_KErrNone(chunk.Decommit(commitOffset,commitSize));	
sl@0
   496
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   497
		test_Equal(pinnedFreeRam,FreeRam());
sl@0
   498
sl@0
   499
		test.Printf(_L("Commit pinned memory again\n"));
sl@0
   500
		test_KErrNone(chunk.Commit(commitOffset,commitSize));	
sl@0
   501
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   502
		test_Equal(pinnedFreeRam,FreeRam());
sl@0
   503
		p = buffer;
sl@0
   504
		pEnd = buffer+bufferSize;
sl@0
   505
		while(p<pEnd)
sl@0
   506
			test_Equal(c,*p++); // memory should have been wiped
sl@0
   507
sl@0
   508
		test.Printf(_L("Unpin memory\n"));
sl@0
   509
		test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   510
		CheckMemoryPresent(buffer, bufferSize, ETrue);
sl@0
   511
		test_Equal(initialFreeRam,FreeRam());
sl@0
   512
sl@0
   513
		test.Printf(_L("Decommit memory\n"));
sl@0
   514
		test_KErrNone(chunk.Decommit(commitOffset,commitSize));	
sl@0
   515
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   516
		test_Compare(FreeRam(),<=,initialFreeRam);
sl@0
   517
sl@0
   518
		//
sl@0
   519
		// test pin twice...
sl@0
   520
		//
sl@0
   521
sl@0
   522
		test.Printf(_L("Commit memory\n"));
sl@0
   523
		test_KErrNone(chunk.Commit(commitOffset,commitSize));	
sl@0
   524
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   525
		test_Equal(initialFreeRam,FreeRam());
sl@0
   526
sl@0
   527
		test.Printf(_L("Pin memory\n"));
sl@0
   528
		test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)buffer, bufferSize));	
sl@0
   529
		CheckMemoryPresent(buffer, bufferSize, ETrue);
sl@0
   530
		test_Equal(pinnedFreeRam,FreeRam());
sl@0
   531
sl@0
   532
		test.Printf(_L("Pin memory again\n"));
sl@0
   533
		test_KErrNone(Ldd2.PinVirtualMemory((TLinAddr)buffer, bufferSize));	
sl@0
   534
		CheckMemoryPresent(buffer, bufferSize, ETrue);
sl@0
   535
		test_Equal(pinnedFreeRam,FreeRam());
sl@0
   536
sl@0
   537
		test.Printf(_L("Decommit pinned memory\n"));
sl@0
   538
		test_KErrNone(chunk.Decommit(commitOffset,commitSize));	
sl@0
   539
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   540
		test_Equal(pinnedFreeRam,FreeRam()); // decommited memory should not be freed as it is pinned
sl@0
   541
sl@0
   542
		test.Printf(_L("Unpin memory\n"));
sl@0
   543
		test_KErrNone(Ldd2.UnpinVirtualMemory());	
sl@0
   544
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   545
		test_Equal(pinnedFreeRam,FreeRam()); // memory shouldn't be freed as another pin exists
sl@0
   546
sl@0
   547
		test.Printf(_L("Unpin memory again\n"));
sl@0
   548
		test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   549
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   550
		test_Equal(initialFreeRam,FreeRam()); // memory should be now freed
sl@0
   551
sl@0
   552
		//
sl@0
   553
		// test page stealing of decommited memory
sl@0
   554
		//
sl@0
   555
sl@0
   556
		test.Printf(_L("Commit memory\n"));
sl@0
   557
		test_KErrNone(chunk.Commit(commitOffset,commitSize));	
sl@0
   558
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   559
		test_Equal(initialFreeRam,FreeRam());
sl@0
   560
sl@0
   561
		test.Printf(_L("Pin memory\n"));
sl@0
   562
		test_KErrNone(Ldd.PinVirtualMemory((TLinAddr)buffer, bufferSize));	
sl@0
   563
		CheckMemoryPresent(buffer, bufferSize, ETrue);
sl@0
   564
		test_Equal(pinnedFreeRam,FreeRam());
sl@0
   565
sl@0
   566
		test.Printf(_L("Decommit pinned memory\n"));
sl@0
   567
		test_KErrNone(chunk.Decommit(commitOffset,commitSize));	
sl@0
   568
		CheckMemoryPresent(buffer, bufferSize, EFalse);
sl@0
   569
		test_Equal(pinnedFreeRam,FreeRam());
sl@0
   570
sl@0
   571
		test.Printf(_L("Unpin memory a higher priority that supervisor thread\n"));
sl@0
   572
		RThread().SetPriority(EPriorityRealTime);
sl@0
   573
		test_KErrNone(Ldd.UnpinVirtualMemory());	
sl@0
   574
		// on single core system, supervisor thread can't run and free pages yet
sl@0
   575
		// because we're a higher priority...
sl@0
   576
		test.Printf(_L("memory freed = %d\n"),initialFreeRam==FreeRamNoWait());
sl@0
   577
sl@0
   578
		test.Printf(_L("Force decommited unpinned pages out of live list\n"));
sl@0
   579
		FlushPagingCache();
sl@0
   580
		RThread().SetPriority(EPriorityNormal);
sl@0
   581
		test_Equal(initialFreeRam,FreeRam()); // memory should be now freed
sl@0
   582
sl@0
   583
		//
sl@0
   584
		// cleanup...
sl@0
   585
		//
sl@0
   586
sl@0
   587
		test.Printf(_L("Destroy pin object\n"));
sl@0
   588
		test_KErrNone(Ldd.DestroyVirtualPinObject());
sl@0
   589
		test_KErrNone(Ldd2.DestroyVirtualPinObject());
sl@0
   590
		chunk.Close();
sl@0
   591
		}
sl@0
   592
sl@0
   593
	test.Printf(_L("Flush paging cache\n"));
sl@0
   594
	FlushPagingCache(); // this is a test that has shown up bugs in the past
sl@0
   595
	}
sl@0
   596
sl@0
   597
sl@0
   598
void TestPinOutOfMemory()
sl@0
   599
	{
sl@0
   600
	// Ensure that if pinning fails with KErrNoMemory,
sl@0
   601
	// there isn't a memory leak
sl@0
   602
	const TInt KMaxKernelAllocations = 1024;
sl@0
   603
	TInt r=KErrNoMemory;
sl@0
   604
	TInt i;
sl@0
   605
	const TUint8* buffer = NULL;
sl@0
   606
	if (PagedBuffer)
sl@0
   607
		{
sl@0
   608
		buffer = PagedBuffer;
sl@0
   609
		}
sl@0
   610
	else
sl@0
   611
		{
sl@0
   612
		buffer = UnpagedBuffer;
sl@0
   613
		}
sl@0
   614
	test_NotNull(buffer);
sl@0
   615
sl@0
   616
	__KHEAP_MARK;
sl@0
   617
	for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++)
sl@0
   618
		{
sl@0
   619
		__KHEAP_FAILNEXT(i);
sl@0
   620
		test.Printf(_L("Create logical pin object\n"));
sl@0
   621
		r = Ldd.CreateVirtualPinObject();
sl@0
   622
		__KHEAP_RESET;
sl@0
   623
		}
sl@0
   624
	test.Printf(_L("Create logical pin object took %d tries\n"),i);
sl@0
   625
	test_KErrNone(r);
sl@0
   626
sl@0
   627
	r = KErrNoMemory;
sl@0
   628
	for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++)
sl@0
   629
		{
sl@0
   630
		__KHEAP_FAILNEXT(i);
sl@0
   631
		test.Printf(_L("Perform logical pin operation\n"));
sl@0
   632
		r = Ldd.PinVirtualMemory((TLinAddr)buffer, KMinBufferSize);
sl@0
   633
		__KHEAP_RESET;
sl@0
   634
		}
sl@0
   635
	test.Printf(_L("Perform logical pin operation took %d tries\n"),i);
sl@0
   636
	if (r == KErrNone)
sl@0
   637
		{
sl@0
   638
		test.Printf(_L("Perform logical unpin operation\n"));
sl@0
   639
		Ldd.UnpinVirtualMemory();
sl@0
   640
		}
sl@0
   641
	
sl@0
   642
	test.Printf(_L("Destroy logical pin object\n"));
sl@0
   643
	Ldd.DestroyVirtualPinObject();
sl@0
   644
	// wait for any async cleanup in the supervisor to finish first...
sl@0
   645
	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);	
sl@0
   646
	__KHEAP_MARKEND;
sl@0
   647
sl@0
   648
	test_KErrNone(r);
sl@0
   649
	}
sl@0
   650
sl@0
   651
sl@0
   652
TInt KernelModifyData(TAny*)
sl@0
   653
	{
sl@0
   654
	Ldd.KernelMapReadAndModifyMemory();
sl@0
   655
	return KErrNone;
sl@0
   656
	}
sl@0
   657
sl@0
   658
void TestMapAndPinMemory()
sl@0
   659
	{
sl@0
   660
	
sl@0
   661
	TInt mm = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0) & EMemModelTypeMask;
sl@0
   662
	if (mm < EMemModelTypeFlexible)
sl@0
   663
		{
sl@0
   664
		test.Printf(_L("Memory model (%d) doesn't support physical pining\n"),mm);
sl@0
   665
		return;
sl@0
   666
		}
sl@0
   667
	TInt i;
sl@0
   668
	TUint KUCBytes = KUCPageCount * PageSize;
sl@0
   669
	RChunk chunk;
sl@0
   670
sl@0
   671
	test.Printf(_L("Allocate user chunk\n"));
sl@0
   672
	TChunkCreateInfo createInfo;
sl@0
   673
	createInfo.SetDisconnected(0, KUCBytes, KUCBytes);
sl@0
   674
	createInfo.SetPaging(TChunkCreateInfo::EPaged);
sl@0
   675
	test_KErrNone(chunk.Create(createInfo));
sl@0
   676
	TUint8* chunkBase = (TUint8*)chunk.Base();
sl@0
   677
	
sl@0
   678
	test.Printf(_L("Create kernel map object\n"));
sl@0
   679
	test_KErrNone(Ldd.CreateKernelMapObject(0));
sl@0
   680
sl@0
   681
	test.Printf(_L("Perform kernel map operation on zero-length buffer\n"));
sl@0
   682
	test_KErrNone(Ldd.KernelMapMemory((TLinAddr)chunkBase, 0));	
sl@0
   683
sl@0
   684
	test.Printf(_L("Perform kernel unmap operation\n"));
sl@0
   685
	test_KErrNone(Ldd.KernelUnmapMemory());	
sl@0
   686
sl@0
   687
	test.Printf(_L("Perform kernel map operation on the chunk\n"));
sl@0
   688
	test_KErrNone(Ldd.KernelMapMemory((TLinAddr)chunkBase, KUCBytes));
sl@0
   689
sl@0
   690
	test.Printf(_L("Attempt to map the memory again while already mapped\n"));
sl@0
   691
	test_Equal(KErrInUse, Ldd.KernelMapMemory((TLinAddr)chunkBase, KUCBytes));
sl@0
   692
sl@0
   693
	test.Printf(_L("Use the kernel mapping to modify the data and verify it\n"));
sl@0
   694
	TUint8* p = chunkBase;
sl@0
   695
	for (i = 0; i < (TInt)KUCBytes; i++)
sl@0
   696
		*p++ = (TUint8)i;
sl@0
   697
	test_KErrNone(Ldd.KernelMapReadAndModifyMemory());
sl@0
   698
	p = chunkBase;
sl@0
   699
	for (i = 0; i < (TInt)KUCBytes; i++)
sl@0
   700
		test_Equal((TUint8)(i + 1), *p++);	
sl@0
   701
sl@0
   702
	test.Printf(_L("Test that kernel mapped memory preserves its mapping when recommited\n"));
sl@0
   703
	test_KErrNone(chunk.Decommit(0,KUCPageCount*PageSize));							 //Decommit all
sl@0
   704
	for (i=KUCPageCount-1;i>=0;i--) test_KErrNone(chunk.Commit(i*PageSize,PageSize)); //Commit in reverse order
sl@0
   705
	for (i=0;i<KUCPageCount;i++) // Recommited memory is not paged in. So, write into each page, before driver 
sl@0
   706
		{						// calls Kern::LinearToPhysical or it will get KErrInvalidMemory in return.
sl@0
   707
		volatile TInt8* ptr = (volatile TInt8*)(chunkBase+i*PageSize);
sl@0
   708
		*ptr = 10;
sl@0
   709
		}
sl@0
   710
	test_KErrNone(Ldd.KernelMapCheckPageList(chunkBase)); 	// Check that the mapping is preserved. 	
sl@0
   711
	
sl@0
   712
	test.Printf(_L("Sync cache & memory of User Chunk\n"));	//Test Cache::SyncMemoryBeforeDmaWrite
sl@0
   713
	test_KErrNone(Ldd.KernelMapSyncMemory());
sl@0
   714
sl@0
   715
	test.Printf(_L("Invalidate cache of User Chunk\n"));//Test Cache::SyncMemoryBefore/AfterDmaRead
sl@0
   716
	test_KErrNone(Ldd.KernelMapInvalidateMemory());
sl@0
   717
	
sl@0
   718
	test.Printf(_L("Try to move kernel map memory...\n")); //RAM defrag should return error code here.
sl@0
   719
	for (i = 0; i < KUCPageCount; i++)
sl@0
   720
		{
sl@0
   721
		TInt r = Ldd.KernelMapMoveMemory(0);
sl@0
   722
		test.Printf(_L("...[%d] returned %d\n"), i, r);
sl@0
   723
		test(r != KErrNone);
sl@0
   724
		}
sl@0
   725
sl@0
   726
	test.Printf(_L("Unmap the memory and attempt to map with invalid attributes\n"));
sl@0
   727
	test_KErrNone(Ldd.KernelUnmapMemory());
sl@0
   728
	test_Equal(KErrArgument, Ldd.KernelMapMemoryInvalid((TLinAddr)chunkBase, KUCBytes));
sl@0
   729
sl@0
   730
	test.Printf(_L("Map the memory read only and attempt to modify it kernel side\n"));
sl@0
   731
	test_KErrNone(Ldd.KernelMapMemoryRO((TLinAddr)chunkBase, KUCBytes));
sl@0
   732
	// Reset the contents of the memory.
sl@0
   733
	p = chunkBase;
sl@0
   734
	for (i = 0; i < (TInt)KUCBytes; i++)
sl@0
   735
		*p++ = (TUint8)i;
sl@0
   736
sl@0
   737
	RThread modThread;
sl@0
   738
	test_KErrNone(modThread.Create(KNullDesC, KernelModifyData, PageSize, PageSize, PageSize, (TAny*)NULL));
sl@0
   739
	TRequestStatus status;
sl@0
   740
	modThread.Logon(status);
sl@0
   741
	test_Equal(KRequestPending, status.Int());
sl@0
   742
	modThread.Resume();
sl@0
   743
	User::WaitForRequest(status);
sl@0
   744
	test_Equal(EExitPanic, modThread.ExitType());
sl@0
   745
	test(modThread.ExitCategory() == _L("KERN-EXEC"));
sl@0
   746
	test_Equal(ECausedException, modThread.ExitReason());
sl@0
   747
	CLOSE_AND_WAIT(modThread);
sl@0
   748
sl@0
   749
	test.Printf(_L("Close the chunk\n")); // Phys. memory is pinned and shouldn't be ...
sl@0
   750
	chunk.Close();						  // ... mapped to another virtual memory.
sl@0
   751
sl@0
   752
	test.Printf(_L("Allocate & initilise the second chunk\n"));// Kernel shouldn't commit pinned physical memory ...
sl@0
   753
	test_KErrNone(chunk.CreateLocal(KUCBytes, KUCBytes));   // ...that has just been decommited from the first chunk.
sl@0
   754
	chunkBase = (TUint8*)chunk.Base();
sl@0
   755
	for (i = 0; i < KUCPageCount * PageSize; i++) 
sl@0
   756
		chunkBase[i] = 0; //Initialise user buffer
sl@0
   757
sl@0
   758
	test.Printf(_L("Invalidate cache of pinned memory\n"));//This shouldn't affect the second chunk.
sl@0
   759
	test_KErrNone(Ldd.KernelMapInvalidateMemory());
sl@0
   760
sl@0
   761
	test.Printf(_L("Check data in the second chunk is unaffected\n"));
sl@0
   762
	for (i=0; i < KUCPageCount * PageSize; i++) 
sl@0
   763
		test(chunkBase[i]==0);
sl@0
   764
	
sl@0
   765
	test.Printf(_L("Close the second chunk\n"));
sl@0
   766
	chunk.Close();
sl@0
   767
sl@0
   768
	test.Printf(_L("Perform kernel unmap operation\n"));
sl@0
   769
	test_KErrNone(Ldd.KernelUnmapMemory());	
sl@0
   770
sl@0
   771
	test.Printf(_L("Perform physical unpin operation (again)\n"));
sl@0
   772
	test_KErrNone(Ldd.KernelUnmapMemory());	// test double unpin ok
sl@0
   773
sl@0
   774
	test.Printf(_L("Destroy physical pin object\n"));
sl@0
   775
	test_KErrNone(Ldd.DestroyKernelMapObject());
sl@0
   776
sl@0
   777
	test.Printf(_L("Destroy physical pin object (again)\n"));
sl@0
   778
	test_KErrNone(Ldd.DestroyKernelMapObject());  // test double destroy ok
sl@0
   779
sl@0
   780
	//
sl@0
   781
	//	Test a kernel mapping with preserved resources doesn't allocate when mapping and pinning.
sl@0
   782
	//
sl@0
   783
	test.Printf(_L("Create a pre-reserving kernel mapping object\n"));
sl@0
   784
	TUint mappingSize = KUCBytes>>1;
sl@0
   785
	// This test step relies on mapping objet being smaller than the user chunk
sl@0
   786
	// and as mapping object will always be >=2 pages, user chunk must be at least 4.
sl@0
   787
	__ASSERT_COMPILE(KUCPageCount >= 4);
sl@0
   788
	test_KErrNone(Ldd.CreateKernelMapObject(mappingSize));
sl@0
   789
	TChunkCreateInfo chunkInfo;
sl@0
   790
	chunkInfo.SetNormal(KUCBytes, KUCBytes);
sl@0
   791
	chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged);
sl@0
   792
	test_KErrNone(chunk.Create(chunkInfo));
sl@0
   793
sl@0
   794
	test.Printf(_L("Map and pin an unpaged chunk with pre-reserved resources\n"));
sl@0
   795
	__KHEAP_FAILNEXT(1);	// Ensure any attempted kernel heap allocations fail.
sl@0
   796
	test_KErrNone(Ldd.KernelMapMemory((TLinAddr)chunk.Base(), mappingSize));
sl@0
   797
	test_KErrNone(Ldd.KernelUnmapMemory());
sl@0
   798
sl@0
   799
	test.Printf(_L("Map more memory than we have pre-reserved resources for\n"));
sl@0
   800
	test_Equal(KErrArgument, Ldd.KernelMapMemory((TLinAddr)chunk.Base(), mappingSize*2));
sl@0
   801
sl@0
   802
	test.Printf(_L("Destroy the kernel map object with pre-reserved resources\n"));
sl@0
   803
	test_KErrNone(Ldd.DestroyKernelMapObject());	// This will also unpin the memory.
sl@0
   804
	// Clear the kernel heap fail next.
sl@0
   805
	__KHEAP_RESET;
sl@0
   806
	chunk.Close();
sl@0
   807
	}
sl@0
   808
sl@0
   809
TInt E32Main()
sl@0
   810
	{
sl@0
   811
	test.Title();
sl@0
   812
	test.Start(_L("Test kernel pinning APIs"));
sl@0
   813
sl@0
   814
	if (DPTest::Attributes() & DPTest::ERomPaging)
sl@0
   815
		test.Printf(_L("Rom paging supported\n"));
sl@0
   816
	if (DPTest::Attributes() & DPTest::ECodePaging)
sl@0
   817
		test.Printf(_L("Code paging supported\n"));
sl@0
   818
	if (DPTest::Attributes() & DPTest::EDataPaging)
sl@0
   819
		test.Printf(_L("Data paging supported\n"));
sl@0
   820
	
sl@0
   821
	test.Next(_L("Loading test drivers"));
sl@0
   822
	test_KErrNone(Ldd.Open());
sl@0
   823
	test_KErrNone(Ldd2.Open());
sl@0
   824
sl@0
   825
	test.Next(_L("Getting page size"));
sl@0
   826
	test_KErrNone(UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&PageSize,0));
sl@0
   827
	
sl@0
   828
	test.Next(_L("Setting up paged and unpaged buffers"));
sl@0
   829
sl@0
   830
#ifdef __EPOC32__
sl@0
   831
	// Use unpaged rom for our unpaged buffer
sl@0
   832
	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
sl@0
   833
	UnpagedBuffer = (TUint8*)romHeader;
sl@0
   834
	TInt size = romHeader->iPageableRomStart ? romHeader->iPageableRomStart : romHeader->iUncompressedSize;
sl@0
   835
	test(size >= KMinBufferSize);
sl@0
   836
	
sl@0
   837
	if (DPTest::Attributes() & DPTest::ERomPaging)
sl@0
   838
		{
sl@0
   839
		// Use end of paged ROM for our paged buffer
sl@0
   840
		test(romHeader->iPageableRomStart);
sl@0
   841
		TInt offset = romHeader->iPageableRomStart + romHeader->iPageableRomSize - KMinBufferSize;
sl@0
   842
		offset &= ~0xfff;
sl@0
   843
		test(offset>=romHeader->iPageableRomStart);
sl@0
   844
		PagedBuffer = (TUint8*)romHeader + offset;
sl@0
   845
		}
sl@0
   846
	else if (DPTest::Attributes() & DPTest::ECodePaging)
sl@0
   847
		{
sl@0
   848
		// Use code paged DLL for our paged buffer
sl@0
   849
		test_KErrNone(PagedLibrary.Load(KTCodePagingDll4));		
sl@0
   850
		TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)PagedLibrary.Lookup(KGetAddressOfDataFunctionOrdinal);
sl@0
   851
		TInt size;
sl@0
   852
		PagedBuffer = (TUint8*)func(size);
sl@0
   853
		test_NotNull(PagedBuffer);
sl@0
   854
		test(size >= KMinBufferSize);
sl@0
   855
		}
sl@0
   856
#else
sl@0
   857
	UnpagedBuffer = (TUint8*)User::Alloc(KMinBufferSize);
sl@0
   858
	test_NotNull(UnpagedBuffer);
sl@0
   859
#endif
sl@0
   860
sl@0
   861
	RDebug::Printf("UnpagedBuffer=%x\n",UnpagedBuffer);
sl@0
   862
	RDebug::Printf("PagedBuffer=%x\n",PagedBuffer);
sl@0
   863
sl@0
   864
	__KHEAP_MARK;
sl@0
   865
	
sl@0
   866
	test.Next(_L("Logical pin unpaged memory"));
sl@0
   867
	TestPinVirtualMemoryUnpaged();
sl@0
   868
sl@0
   869
	test.Next(_L("Logical pin invalid memory"));
sl@0
   870
	TestPinVirtualMemoryInvalid();
sl@0
   871
sl@0
   872
	test.Next(_L("Physical pinning"));
sl@0
   873
	TestPinPhysicalMemory();
sl@0
   874
	
sl@0
   875
	test.Next(_L("Physical pinning OOM"));
sl@0
   876
	TestPhysicalPinOutOfMemory();
sl@0
   877
sl@0
   878
	test.Next(_L("Kernel pin mapping"));
sl@0
   879
	TestMapAndPinMemory();
sl@0
   880
sl@0
   881
	test.Next(_L("Pin OOM Tests"));
sl@0
   882
	TestPinOutOfMemory();
sl@0
   883
sl@0
   884
	if (PagedBuffer)
sl@0
   885
		{
sl@0
   886
		test.Next(_L("Logical pin paged memory"));
sl@0
   887
		TestPinVirtualMemoryPaged();
sl@0
   888
sl@0
   889
		test.Next(_L("Logical pin paged memory soak test"));
sl@0
   890
		TestPinVirtualMemoryPagedSoak();
sl@0
   891
		}
sl@0
   892
sl@0
   893
	if (DPTest::Attributes() & DPTest::EDataPaging)
sl@0
   894
		{
sl@0
   895
		test.Next(_L("Logical pin then decommit memory"));
sl@0
   896
		TestPinVirtualMemoryDecommit();
sl@0
   897
		}
sl@0
   898
sl@0
   899
	// wait for any async cleanup in the supervisor to finish first...
sl@0
   900
	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, 0, 0);	
sl@0
   901
	__KHEAP_MARKEND;
sl@0
   902
sl@0
   903
#ifndef __EPOC32__
sl@0
   904
	User::Free((TAny*)UnpagedBuffer);
sl@0
   905
#endif
sl@0
   906
sl@0
   907
	PagedLibrary.Close();
sl@0
   908
	Ldd.Close();
sl@0
   909
	Ldd2.Close();
sl@0
   910
	test.End();
sl@0
   911
sl@0
   912
	return KErrNone;
sl@0
   913
	}