kerneltest/e32test/mmu/t_pin.cpp
changeset 13 46fffbe7b5a7
parent 9 96e5fb8b040d
equal deleted inserted replaced
12:0bf4040442f9 13:46fffbe7b5a7
   113 	TInt8* UCBase;
   113 	TInt8* UCBase;
   114 	RChunk chunk;
   114 	RChunk chunk;
   115 
   115 
   116 	test.Printf(_L("Allocate user chunk\n"));
   116 	test.Printf(_L("Allocate user chunk\n"));
   117 	TChunkCreateInfo createInfo;
   117 	TChunkCreateInfo createInfo;
   118 	createInfo.SetDisconnected(0,UCPageCount*PageSize,UCPageCount*PageSize);
   118 	createInfo.SetDisconnected(0,KUCPageCount*PageSize,KUCPageCount*PageSize);
   119 	createInfo.SetPaging(TChunkCreateInfo::EPaged);
   119 	createInfo.SetPaging(TChunkCreateInfo::EPaged);
   120 	test_KErrNone(chunk.Create(createInfo));
   120 	test_KErrNone(chunk.Create(createInfo));
   121 	UCBase = (TInt8*)chunk.Base();
   121 	UCBase = (TInt8*)chunk.Base();
   122 	
   122 	
   123 	test.Printf(_L("Create physical pin object\n"));
   123 	test.Printf(_L("Create physical pin object\n"));
   128 
   128 
   129 	test.Printf(_L("Perform physical unpin operation\n"));
   129 	test.Printf(_L("Perform physical unpin operation\n"));
   130 	test_KErrNone(Ldd.UnpinPhysicalMemory());	
   130 	test_KErrNone(Ldd.UnpinPhysicalMemory());	
   131 
   131 
   132 	test.Printf(_L("Perform Physical pin operation on the chunk\n"));
   132 	test.Printf(_L("Perform Physical pin operation on the chunk\n"));
   133 	test_KErrNone(Ldd.PinPhysicalMemory((TLinAddr)UCBase, UCPageCount*PageSize));	
   133 	test_KErrNone(Ldd.PinPhysicalMemory((TLinAddr)UCBase, KUCPageCount*PageSize));	
   134 
   134 
   135 	test.Printf(_L("Test that pinned physical memory preserves its mapping when recommited\n"));
   135 	test.Printf(_L("Test that pinned physical memory preserves its mapping when recommited\n"));
   136 	test_KErrNone(chunk.Decommit(0,UCPageCount*PageSize));							 //Decommit all
   136 	test_KErrNone(chunk.Decommit(0,KUCPageCount*PageSize));							 //Decommit all
   137 	for (i=UCPageCount-1;i>=0;i--) test_KErrNone(chunk.Commit(i*PageSize,PageSize)); //Commit in reverse order
   137 	for (i=KUCPageCount-1;i>=0;i--) test_KErrNone(chunk.Commit(i*PageSize,PageSize)); //Commit in reverse order
   138 	for (i=0;i<UCPageCount;i++) // Recommited memory is not paged in. So, write into each page, before driver 
   138 	for (i=0;i<KUCPageCount;i++) // Recommited memory is not paged in. So, write into each page, before driver 
   139 		{						// calls Kern::LinearToPhysical or it will get KErrInvalidMemory in return.
   139 		{						// calls Kern::LinearToPhysical or it will get KErrInvalidMemory in return.
   140 		volatile TInt8* ptr = (volatile TInt8*)(UCBase+i*PageSize);
   140 		volatile TInt8* ptr = (volatile TInt8*)(UCBase+i*PageSize);
   141 		*ptr = 10;
   141 		*ptr = 10;
   142 		}
   142 		}
   143 	test_KErrNone(Ldd.CheckPageList(chunk.Base())); 					// Check that the mapping is preserved. 	
   143 	test_KErrNone(Ldd.CheckPageList(chunk.Base())); 					// Check that the mapping is preserved. 	
   144 	
   144 	
   145 	test.Printf(_L("Sync cache & memory of User Chunk\n"));//Test Cache::SyncPhysicalMemoryBeforeDmaWrite
   145 	test.Printf(_L("Sync cache & memory of User Chunk\n"));//Test Cache::SyncPhysicalMemoryBeforeDmaWrite
   146 	test_KErrNone(Ldd.SyncPinnedPhysicalMemory(0,UCPageCount*PageSize));
   146 	test_KErrNone(Ldd.SyncPinnedPhysicalMemory(0,KUCPageCount*PageSize));
   147 
   147 
   148 	test.Printf(_L("Invalidate cache of User Chunk\n"));//Test Cache::SyncPhysicalMemoryBefore/AfterDmaRead
   148 	test.Printf(_L("Invalidate cache of User Chunk\n"));//Test Cache::SyncPhysicalMemoryBefore/AfterDmaRead
   149 	test_KErrNone(Ldd.InvalidatePinnedPhysicalMemory(0,UCPageCount*PageSize));
   149 	test_KErrNone(Ldd.InvalidatePinnedPhysicalMemory(0,KUCPageCount*PageSize));
   150 	
   150 	
   151 	test.Printf(_L("Try to move pinned phys. memory...\n")); //RAM defrag should return error code here.
   151 	test.Printf(_L("Try to move pinned phys. memory...\n")); //RAM defrag should return error code here.
   152 	i = Ldd.MovePinnedPhysicalMemory(0);
   152 	i = Ldd.MovePinnedPhysicalMemory(0);
   153 	test.Printf(_L("...returned %d\n"),i);
   153 	test.Printf(_L("...returned %d\n"),i);
   154 	test(i!=KErrNone);
   154 	test(i!=KErrNone);
   155 
   155 
   156 	test.Printf(_L("Close the chunk\n")); // Phys. memory is pinned and shouldn't be ...
   156 	test.Printf(_L("Close the chunk\n")); // Phys. memory is pinned and shouldn't be ...
   157 	chunk.Close();						  // ... mapped to another virtual memory.
   157 	chunk.Close();						  // ... mapped to another virtual memory.
   158 
   158 
   159 	test.Printf(_L("Allocate & initilise the second chunk\n"));// Kernel sholudn't commit pinned physical memory ...
   159 	test.Printf(_L("Allocate & initilise the second chunk\n"));// Kernel sholudn't commit pinned physical memory ...
   160 	test_KErrNone(chunk.CreateLocal(2*PageSize,2*PageSize));   // ...that has been just decommited from the first chunk.
   160 	test_KErrNone(chunk.CreateLocal(KUCPageCount*PageSize,KUCPageCount*PageSize));   // ...that has been just decommited from the first chunk.
   161 	UCBase = (TInt8*)chunk.Base();
   161 	UCBase = (TInt8*)chunk.Base();
   162 	for (i=0;i<UCPageCount*PageSize;i++) UCBase[i]=0; //Initialise user buffer
   162 	for (i=0;i<KUCPageCount*PageSize;i++) UCBase[i]=0; //Initialise user buffer
   163 
   163 
   164 	test.Printf(_L("Invalidate cache of pinned memory\n"));//This shouldn't affect the second chunk.
   164 	test.Printf(_L("Invalidate cache of pinned memory\n"));//This shouldn't affect the second chunk.
   165 	test_KErrNone(Ldd.InvalidatePinnedPhysicalMemory(0,UCPageCount*PageSize));
   165 	test_KErrNone(Ldd.InvalidatePinnedPhysicalMemory(0,KUCPageCount*PageSize));
   166 
   166 
   167 	test.Printf(_L("Check data in the second chunk is unaffected\n"));
   167 	test.Printf(_L("Check data in the second chunk is unaffected\n"));
   168 	for (i=0;i<UCPageCount*PageSize;i++) test(UCBase[i]==0);
   168 	for (i=0;i<KUCPageCount*PageSize;i++) test(UCBase[i]==0);
   169 	
   169 	
   170 	test.Printf(_L("Close the second chunk\n"));
   170 	test.Printf(_L("Close the second chunk\n"));
   171 	chunk.Close();
   171 	chunk.Close();
   172 
   172 
   173 	test.Printf(_L("Perform physical unpin operation\n"));
   173 	test.Printf(_L("Perform physical unpin operation\n"));
   197 	
   197 	
   198 	TInt8* UCBase;
   198 	TInt8* UCBase;
   199 	RChunk chunk;
   199 	RChunk chunk;
   200 
   200 
   201 	test.Printf(_L("Allocate user chunk\n"));
   201 	test.Printf(_L("Allocate user chunk\n"));
   202 	test_KErrNone(chunk.CreateDisconnectedLocal(0,UCPageCount*PageSize,UCPageCount*PageSize));
   202 	test_KErrNone(chunk.CreateDisconnectedLocal(0,KUCPageCount*PageSize,KUCPageCount*PageSize));
   203 	UCBase = (TInt8*)chunk.Base();
   203 	UCBase = (TInt8*)chunk.Base();
   204 	
   204 	
   205 	const TInt KMaxKernelAllocations = 1024;
   205 	const TInt KMaxKernelAllocations = 1024;
   206 	TInt r=KErrNoMemory;
   206 	TInt r=KErrNoMemory;
   207 	TInt i;
   207 	TInt i;
   221 
   221 
   222 	for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++)
   222 	for (i = 0; i < KMaxKernelAllocations && r == KErrNoMemory; i++)
   223 		{
   223 		{
   224 		__KHEAP_FAILNEXT(i);
   224 		__KHEAP_FAILNEXT(i);
   225 		test.Printf(_L("Perform physical pin operation\n"));
   225 		test.Printf(_L("Perform physical pin operation\n"));
   226 		r = Ldd.PinPhysicalMemory((TLinAddr)UCBase, UCPageCount*PageSize);
   226 		r = Ldd.PinPhysicalMemory((TLinAddr)UCBase, KUCPageCount*PageSize);
   227 		__KHEAP_RESET;
   227 		__KHEAP_RESET;
   228 		}
   228 		}
   229 	test.Printf(_L("Perform physical pin operation took %d tries\n"),i);
   229 	test.Printf(_L("Perform physical pin operation took %d tries\n"),i);
   230 	if (r == KErrNone)
   230 	if (r == KErrNone)
   231 		{
   231 		{
   647 
   647 
   648 	test_KErrNone(r);
   648 	test_KErrNone(r);
   649 	}
   649 	}
   650 
   650 
   651 
   651 
       
   652 TInt KernelModifyData(TAny*)
       
   653 	{
       
   654 	Ldd.KernelMapReadAndModifyMemory();
       
   655 	return KErrNone;
       
   656 	}
       
   657 
       
   658 void TestMapAndPinMemory()
       
   659 	{
       
   660 	
       
   661 	TInt mm = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, 0, 0) & EMemModelTypeMask;
       
   662 	if (mm < EMemModelTypeFlexible)
       
   663 		{
       
   664 		test.Printf(_L("Memory model (%d) doesn't support physical pining\n"),mm);
       
   665 		return;
       
   666 		}
       
   667 	TInt i;
       
   668 	TUint KUCBytes = KUCPageCount * PageSize;
       
   669 	RChunk chunk;
       
   670 
       
   671 	test.Printf(_L("Allocate user chunk\n"));
       
   672 	TChunkCreateInfo createInfo;
       
   673 	createInfo.SetDisconnected(0, KUCBytes, KUCBytes);
       
   674 	createInfo.SetPaging(TChunkCreateInfo::EPaged);
       
   675 	test_KErrNone(chunk.Create(createInfo));
       
   676 	TUint8* chunkBase = (TUint8*)chunk.Base();
       
   677 	
       
   678 	test.Printf(_L("Create kernel map object\n"));
       
   679 	test_KErrNone(Ldd.CreateKernelMapObject(0));
       
   680 
       
   681 	test.Printf(_L("Perform kernel map operation on zero-length buffer\n"));
       
   682 	test_KErrNone(Ldd.KernelMapMemory((TLinAddr)chunkBase, 0));	
       
   683 
       
   684 	test.Printf(_L("Perform kernel unmap operation\n"));
       
   685 	test_KErrNone(Ldd.KernelUnmapMemory());	
       
   686 
       
   687 	test.Printf(_L("Perform kernel map operation on the chunk\n"));
       
   688 	test_KErrNone(Ldd.KernelMapMemory((TLinAddr)chunkBase, KUCBytes));
       
   689 
       
   690 	test.Printf(_L("Attempt to map the memory again while already mapped\n"));
       
   691 	test_Equal(KErrInUse, Ldd.KernelMapMemory((TLinAddr)chunkBase, KUCBytes));
       
   692 
       
   693 	test.Printf(_L("Use the kernel mapping to modify the data and verify it\n"));
       
   694 	TUint8* p = chunkBase;
       
   695 	for (i = 0; i < (TInt)KUCBytes; i++)
       
   696 		*p++ = (TUint8)i;
       
   697 	test_KErrNone(Ldd.KernelMapReadAndModifyMemory());
       
   698 	p = chunkBase;
       
   699 	for (i = 0; i < (TInt)KUCBytes; i++)
       
   700 		test_Equal((TUint8)(i + 1), *p++);	
       
   701 
       
   702 	test.Printf(_L("Test that kernel mapped memory preserves its mapping when recommited\n"));
       
   703 	test_KErrNone(chunk.Decommit(0,KUCPageCount*PageSize));							 //Decommit all
       
   704 	for (i=KUCPageCount-1;i>=0;i--) test_KErrNone(chunk.Commit(i*PageSize,PageSize)); //Commit in reverse order
       
   705 	for (i=0;i<KUCPageCount;i++) // Recommited memory is not paged in. So, write into each page, before driver 
       
   706 		{						// calls Kern::LinearToPhysical or it will get KErrInvalidMemory in return.
       
   707 		volatile TInt8* ptr = (volatile TInt8*)(chunkBase+i*PageSize);
       
   708 		*ptr = 10;
       
   709 		}
       
   710 	test_KErrNone(Ldd.KernelMapCheckPageList(chunkBase)); 	// Check that the mapping is preserved. 	
       
   711 	
       
   712 	test.Printf(_L("Sync cache & memory of User Chunk\n"));	//Test Cache::SyncMemoryBeforeDmaWrite
       
   713 	test_KErrNone(Ldd.KernelMapSyncMemory());
       
   714 
       
   715 	test.Printf(_L("Invalidate cache of User Chunk\n"));//Test Cache::SyncMemoryBefore/AfterDmaRead
       
   716 	test_KErrNone(Ldd.KernelMapInvalidateMemory());
       
   717 	
       
   718 	test.Printf(_L("Try to move kernel map memory...\n")); //RAM defrag should return error code here.
       
   719 	for (i = 0; i < KUCPageCount; i++)
       
   720 		{
       
   721 		TInt r = Ldd.KernelMapMoveMemory(0);
       
   722 		test.Printf(_L("...[%d] returned %d\n"), i, r);
       
   723 		test(r != KErrNone);
       
   724 		}
       
   725 
       
   726 	test.Printf(_L("Unmap the memory and attempt to map with invalid attributes\n"));
       
   727 	test_KErrNone(Ldd.KernelUnmapMemory());
       
   728 	test_Equal(KErrArgument, Ldd.KernelMapMemoryInvalid((TLinAddr)chunkBase, KUCBytes));
       
   729 
       
   730 	test.Printf(_L("Map the memory read only and attempt to modify it kernel side\n"));
       
   731 	test_KErrNone(Ldd.KernelMapMemoryRO((TLinAddr)chunkBase, KUCBytes));
       
   732 	// Reset the contents of the memory.
       
   733 	p = chunkBase;
       
   734 	for (i = 0; i < (TInt)KUCBytes; i++)
       
   735 		*p++ = (TUint8)i;
       
   736 
       
   737 	RThread modThread;
       
   738 	test_KErrNone(modThread.Create(KNullDesC, KernelModifyData, PageSize, PageSize, PageSize, (TAny*)NULL));
       
   739 	TRequestStatus status;
       
   740 	modThread.Logon(status);
       
   741 	test_Equal(KRequestPending, status.Int());
       
   742 	modThread.Resume();
       
   743 	User::WaitForRequest(status);
       
   744 	test_Equal(EExitPanic, modThread.ExitType());
       
   745 	test(modThread.ExitCategory() == _L("KERN-EXEC"));
       
   746 	test_Equal(ECausedException, modThread.ExitReason());
       
   747 	CLOSE_AND_WAIT(modThread);
       
   748 
       
   749 	test.Printf(_L("Close the chunk\n")); // Phys. memory is pinned and shouldn't be ...
       
   750 	chunk.Close();						  // ... mapped to another virtual memory.
       
   751 
       
   752 	test.Printf(_L("Allocate & initilise the second chunk\n"));// Kernel shouldn't commit pinned physical memory ...
       
   753 	test_KErrNone(chunk.CreateLocal(KUCBytes, KUCBytes));   // ...that has just been decommited from the first chunk.
       
   754 	chunkBase = (TUint8*)chunk.Base();
       
   755 	for (i = 0; i < KUCPageCount * PageSize; i++) 
       
   756 		chunkBase[i] = 0; //Initialise user buffer
       
   757 
       
   758 	test.Printf(_L("Invalidate cache of pinned memory\n"));//This shouldn't affect the second chunk.
       
   759 	test_KErrNone(Ldd.KernelMapInvalidateMemory());
       
   760 
       
   761 	test.Printf(_L("Check data in the second chunk is unaffected\n"));
       
   762 	for (i=0; i < KUCPageCount * PageSize; i++) 
       
   763 		test(chunkBase[i]==0);
       
   764 	
       
   765 	test.Printf(_L("Close the second chunk\n"));
       
   766 	chunk.Close();
       
   767 
       
   768 	test.Printf(_L("Perform kernel unmap operation\n"));
       
   769 	test_KErrNone(Ldd.KernelUnmapMemory());	
       
   770 
       
   771 	test.Printf(_L("Perform physical unpin operation (again)\n"));
       
   772 	test_KErrNone(Ldd.KernelUnmapMemory());	// test double unpin ok
       
   773 
       
   774 	test.Printf(_L("Destroy physical pin object\n"));
       
   775 	test_KErrNone(Ldd.DestroyKernelMapObject());
       
   776 
       
   777 	test.Printf(_L("Destroy physical pin object (again)\n"));
       
   778 	test_KErrNone(Ldd.DestroyKernelMapObject());  // test double destroy ok
       
   779 
       
   780 	//
       
   781 	//	Test a kernel mapping with preserved resources doesn't allocate when mapping and pinning.
       
   782 	//
       
   783 	test.Printf(_L("Create a pre-reserving kernel mapping object\n"));
       
   784 	TUint mappingSize = KUCBytes>>1;
       
   785 	// This test step relies on mapping objet being smaller than the user chunk
       
   786 	// and as mapping object will always be >=2 pages, user chunk must be at least 4.
       
   787 	__ASSERT_COMPILE(KUCPageCount >= 4);
       
   788 	test_KErrNone(Ldd.CreateKernelMapObject(mappingSize));
       
   789 	TChunkCreateInfo chunkInfo;
       
   790 	chunkInfo.SetNormal(KUCBytes, KUCBytes);
       
   791 	chunkInfo.SetPaging(TChunkCreateInfo::EUnpaged);
       
   792 	test_KErrNone(chunk.Create(chunkInfo));
       
   793 
       
   794 	test.Printf(_L("Map and pin an unpaged chunk with pre-reserved resources\n"));
       
   795 	__KHEAP_FAILNEXT(1);	// Ensure any attempted kernel heap allocations fail.
       
   796 	test_KErrNone(Ldd.KernelMapMemory((TLinAddr)chunk.Base(), mappingSize));
       
   797 	test_KErrNone(Ldd.KernelUnmapMemory());
       
   798 
       
   799 	test.Printf(_L("Map more memory than we have pre-reserved resources for\n"));
       
   800 	test_Equal(KErrArgument, Ldd.KernelMapMemory((TLinAddr)chunk.Base(), mappingSize*2));
       
   801 
       
   802 	test.Printf(_L("Destroy the kernel map object with pre-reserved resources\n"));
       
   803 	test_KErrNone(Ldd.DestroyKernelMapObject());	// This will also unpin the memory.
       
   804 	// Clear the kernel heap fail next.
       
   805 	__KHEAP_RESET;
       
   806 	chunk.Close();
       
   807 	}
       
   808 
   652 TInt E32Main()
   809 TInt E32Main()
   653 	{
   810 	{
   654 	test.Title();
   811 	test.Title();
   655 	test.Start(_L("Test kernel pinning APIs"));
   812 	test.Start(_L("Test kernel pinning APIs"));
   656 
   813 
   715 	test.Next(_L("Physical pinning"));
   872 	test.Next(_L("Physical pinning"));
   716 	TestPinPhysicalMemory();
   873 	TestPinPhysicalMemory();
   717 	
   874 	
   718 	test.Next(_L("Physical pinning OOM"));
   875 	test.Next(_L("Physical pinning OOM"));
   719 	TestPhysicalPinOutOfMemory();
   876 	TestPhysicalPinOutOfMemory();
   720 	
   877 
       
   878 	test.Next(_L("Kernel pin mapping"));
       
   879 	TestMapAndPinMemory();
       
   880 
   721 	test.Next(_L("Pin OOM Tests"));
   881 	test.Next(_L("Pin OOM Tests"));
   722 	TestPinOutOfMemory();
   882 	TestPinOutOfMemory();
   723 
   883 
   724 	if (PagedBuffer)
   884 	if (PagedBuffer)
   725 		{
   885 		{