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")); |
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 |