106 TUint8* SharedBuffer = NULL; |
107 TUint8* SharedBuffer = NULL; |
107 |
108 |
108 // A descriptor whose header is in paged memory (actually just a pointer to a zero word) |
109 // A descriptor whose header is in paged memory (actually just a pointer to a zero word) |
109 TDesC8* PagedHeaderDes = NULL; |
110 TDesC8* PagedHeaderDes = NULL; |
110 |
111 |
|
112 // An area of paged rom if rom paging is supported, or zero |
|
113 TUint8* RomPagedBuffer = NULL; |
|
114 TInt RomPagedBufferSize = 0; |
|
115 |
|
116 // An area of paged code if code paging is supported, or zero |
|
117 TUint8* CodePagedBuffer = NULL; |
|
118 TInt CodePagedBufferSize = 0; |
|
119 |
111 // A data paged chunk used as a buffer, if data paging is supported |
120 // A data paged chunk used as a buffer, if data paging is supported |
112 _LIT(KChunkName, "t_demandpaging chunk"); |
121 _LIT(KChunkName, "t_demandpaging chunk"); |
113 RChunk DataPagedChunk; |
122 RChunk DataPagedChunk; |
114 TBool DataPagingSupported = EFalse; |
123 TBool DataPagingSupported = EFalse; |
115 TUint8* DataPagedBuffer = NULL; |
124 TUint8* DataPagedBuffer = NULL; |
649 test_Equal(EExitPanic, aThread.ExitType()); |
665 test_Equal(EExitPanic, aThread.ExitType()); |
650 test(aThread.ExitCategory()==_L("KERN-EXEC")); |
666 test(aThread.ExitCategory()==_L("KERN-EXEC")); |
651 test_Equal(EIllegalFunctionForRealtimeThread, aThread.ExitReason()); |
667 test_Equal(EIllegalFunctionForRealtimeThread, aThread.ExitReason()); |
652 break; |
668 break; |
653 |
669 |
|
670 case EAbortPanic: |
|
671 test_Equal(EExitPanic, aThread.ExitType()); |
|
672 // category for paging errors tested elsewhere |
|
673 test_Equal(KErrAbort, aThread.ExitReason()); |
|
674 break; |
|
675 |
654 default: |
676 default: |
655 test(EFalse); |
677 test(EFalse); |
656 } |
678 } |
657 } |
679 } |
658 |
680 |
659 void TestPagedIpc(TIpcDir aIpcDir, |
681 void TestPagedIpc(TIpcDir aIpcDir, |
660 TIpcObjectPaged aClientPaged, |
682 TIpcObjectPaged aClientPaged, |
661 TIpcObjectPaged aServerPaged, |
683 TIpcObjectPaged aServerPaged, |
662 User::TRealtimeState aClientState, |
684 User::TRealtimeState aClientState, |
663 User::TRealtimeState aServerState, |
685 User::TRealtimeState aServerState, |
664 TRealtimeOutcome aClientOutcome, |
686 TThreadOutcome aClientOutcome, |
665 TRealtimeOutcome aServerOutcome) |
687 TThreadOutcome aServerOutcome, |
|
688 TPagingErrorContext aSimulatedError = EPagingErrorContextNone) |
666 { |
689 { |
667 test.Printf(_L("TestPagedIpc %d %d %d %d %d %d %d\n"), aIpcDir, aClientPaged, aServerPaged, |
690 test.Printf(_L("TestPagedIpc %d %d %d %d %d %d %d\n"), aIpcDir, aClientPaged, aServerPaged, |
668 aClientState, aServerState, aClientOutcome, aServerOutcome); |
691 aClientState, aServerState, aClientOutcome, aServerOutcome); |
669 |
692 |
670 RThread serverThread; |
693 RThread serverThread; |
686 TInt clientArg = aIpcDir | (aClientPaged << 8) | (aClientState << 16); |
709 TInt clientArg = aIpcDir | (aClientPaged << 8) | (aClientState << 16); |
687 test_KErrNone(clientThread.Create(KNullDesC, &IpcTestClientFunc, 0x1000, NULL, (TAny*)clientArg)); |
710 test_KErrNone(clientThread.Create(KNullDesC, &IpcTestClientFunc, 0x1000, NULL, (TAny*)clientArg)); |
688 name = clientThread.Name(); |
711 name = clientThread.Name(); |
689 test.Printf(_L(" client: %S\n"), &name); |
712 test.Printf(_L(" client: %S\n"), &name); |
690 clientThread.Logon(clientStatus); |
713 clientThread.Logon(clientStatus); |
|
714 |
|
715 // set up simulated failure if specifed |
|
716 if (aSimulatedError != EPagingErrorContextNone) |
|
717 test_KErrNone(UserSvr::HalFunction(EHalGroupVM, EVMHalDebugSetFail, (TAny*)aSimulatedError, 0)); |
|
718 |
691 clientThread.Resume(); |
719 clientThread.Resume(); |
692 |
720 |
693 User::WaitForRequest(serverStatus); |
721 User::WaitForRequest(serverStatus); |
694 test.Printf(_L(" server exit type is %d %d\n"), serverThread.ExitType(), serverThread.ExitReason()); |
722 test.Printf(_L(" server exit type is %d %d\n"), serverThread.ExitType(), serverThread.ExitReason()); |
695 TestServer.Close(); // because handle is process-relative, it's not closed if the server dies |
723 TestServer.Close(); // because handle is process-relative, it's not closed if the server dies |
696 |
724 |
697 User::WaitForRequest(clientStatus); |
725 User::WaitForRequest(clientStatus); |
698 test.Printf(_L(" client exit type is %d %d\n"), clientThread.ExitType(), clientThread.ExitReason()); |
726 test.Printf(_L(" client exit type is %d %d\n"), clientThread.ExitType(), clientThread.ExitReason()); |
699 |
727 |
700 TestRealtimeOutcome(serverThread, aServerOutcome); |
728 // cancel any simulated failure |
701 TestRealtimeOutcome(clientThread, aClientOutcome); |
729 if (aSimulatedError != EPagingErrorContextNone) |
|
730 test_KErrNone(UserSvr::HalFunction(EHalGroupVM, EVMHalDebugSetFail, (TAny*)EPagingErrorContextNone, 0)); |
|
731 |
|
732 TestThreadOutcome(serverThread, aServerOutcome); |
|
733 TestThreadOutcome(clientThread, aClientOutcome); |
702 |
734 |
703 CLOSE_AND_WAIT(serverThread); |
735 CLOSE_AND_WAIT(serverThread); |
704 CLOSE_AND_WAIT(clientThread); |
736 CLOSE_AND_WAIT(clientThread); |
705 } |
737 } |
706 |
738 |
807 |
839 |
808 test.End(); |
840 test.End(); |
809 |
841 |
810 // retore size of live list |
842 // retore size of live list |
811 test(KErrNone==DPTest::SetCacheSize(0,0)); |
843 test(KErrNone==DPTest::SetCacheSize(0,0)); |
|
844 } |
|
845 |
|
846 enum TPageFaultType |
|
847 { |
|
848 EPageFaultRomRead, |
|
849 EPageFaultCodeRead, |
|
850 EPageFaultDataRead, |
|
851 EPageFaultDataWrite, |
|
852 }; |
|
853 |
|
854 |
|
855 TInt TestPagingErrorThreadFunction(TAny* aArg) |
|
856 { |
|
857 TUint8* ptr = (TUint8*)((TUint)aArg & ~1); |
|
858 TBool write = ((TUint)aArg & 1) != 0; |
|
859 |
|
860 if (write) |
|
861 { |
|
862 WRITE(ptr); |
|
863 return DPTest::FlushCache(); |
|
864 } |
|
865 else |
|
866 { |
|
867 READ(ptr); |
|
868 return KErrNone; |
|
869 } |
|
870 } |
|
871 |
|
872 void TestPagingError(TPageFaultType aPageFaultType, |
|
873 TPagingErrorContext aSimulatedError, |
|
874 TExitType aExpectedExitType, |
|
875 const TDesC& aExpectedExitCategory, |
|
876 TInt aExpectedExitReason) |
|
877 { |
|
878 test.Printf(_L("TestPagingError %d %d %d \"%S\" %d\n"), aPageFaultType, aSimulatedError, |
|
879 aExpectedExitType, &aExpectedExitCategory, aExpectedExitReason); |
|
880 |
|
881 TUint8* ptr; |
|
882 TBool write; |
|
883 |
|
884 switch(aPageFaultType) |
|
885 { |
|
886 case EPageFaultRomRead: ptr = RomPagedBuffer; write = EFalse; break; |
|
887 case EPageFaultCodeRead: ptr = CodePagedBuffer; write = EFalse; break; |
|
888 case EPageFaultDataRead: ptr = DataPagedBuffer; write = EFalse; break; |
|
889 case EPageFaultDataWrite: ptr = DataPagedBuffer; write = ETrue; break; |
|
890 default: test(EFalse); return; |
|
891 } |
|
892 |
|
893 if (ptr == NULL) return; // specified type of paging is not enabled |
|
894 |
|
895 if (write) |
|
896 READ(ptr); // ensure data to be written is paged in |
|
897 else |
|
898 test_KErrNone(DPTest::FlushCache()); // ensure data to be read is paged out |
|
899 |
|
900 // set up simulated failure |
|
901 test_KErrNone(UserSvr::HalFunction(EHalGroupVM, EVMHalDebugSetFail, (TAny*)aSimulatedError, 0)); |
|
902 |
|
903 RThread thread; |
|
904 TAny* arg = (TAny*)((TUint)ptr | (write ? 1 : 0)); |
|
905 test_KErrNone(thread.Create(KNullDesC, &TestPagingErrorThreadFunction, 0x1000, NULL, arg)); |
|
906 TRequestStatus s; |
|
907 thread.Logon(s); |
|
908 test_Equal(KRequestPending, s.Int()); |
|
909 thread.Resume(); |
|
910 User::WaitForRequest(s); |
|
911 |
|
912 // cancel any simulated failure |
|
913 test_KErrNone(UserSvr::HalFunction(EHalGroupVM, EVMHalDebugSetFail, (TAny*)EPagingErrorContextNone, 0)); |
|
914 |
|
915 TExitCategoryName exitCategory = thread.ExitCategory(); |
|
916 test.Printf(_L(" thread exit type is %d \"%S\" %d\n"), |
|
917 thread.ExitType(), &exitCategory, thread.ExitReason()); |
|
918 |
|
919 test_Equal(aExpectedExitType, thread.ExitType()); |
|
920 if (aExpectedExitType == EExitPanic) |
|
921 test_Equal(0, aExpectedExitCategory.Compare(exitCategory)); |
|
922 test_Equal(aExpectedExitReason, thread.ExitReason()); |
|
923 |
|
924 CLOSE_AND_WAIT(thread); |
|
925 } |
|
926 |
|
927 void CreateDataPagedChunk() |
|
928 { |
|
929 TChunkCreateInfo createInfo; |
|
930 createInfo.SetNormal(KMinBufferSize, KMinBufferSize); |
|
931 createInfo.SetPaging(TChunkCreateInfo::EPaged); |
|
932 createInfo.SetOwner(EOwnerProcess); |
|
933 createInfo.SetGlobal(KChunkName); |
|
934 test_KErrNone(DataPagedChunk.Create(createInfo)); |
|
935 test(DataPagedChunk.IsPaged()); // this is only ever called if data paging is supported |
|
936 DataPagedBuffer = (TUint8*)DataPagedChunk.Base(); |
|
937 } |
|
938 |
|
939 void TestPagingErrors() |
|
940 { |
|
941 // test what happens when the paging system encounters errors such as failure when accessing |
|
942 // media or decompressing paged data |
|
943 |
|
944 // page fault type: simulated error: exit type: exit category: exit reason: |
|
945 TestPagingError(EPageFaultRomRead, EPagingErrorContextNone, EExitKill, KNullDesC, KErrNone); |
|
946 TestPagingError(EPageFaultRomRead, EPagingErrorContextRomRead, EExitPanic, _L("PAGED-ROM-READ"), KErrAbort); |
|
947 TestPagingError(EPageFaultRomRead, EPagingErrorContextRomDecompress, EExitPanic, _L("PAGED-ROM-COMP"), KErrAbort); |
|
948 |
|
949 TestPagingError(EPageFaultCodeRead, EPagingErrorContextNone, EExitKill, KNullDesC, KErrNone); |
|
950 TestPagingError(EPageFaultCodeRead, EPagingErrorContextCodeRead, EExitPanic, _L("PAGED-CODE-READ"), KErrAbort); |
|
951 TestPagingError(EPageFaultCodeRead, EPagingErrorContextCodeDecompress, EExitPanic, _L("PAGED-CODE-COMP"), KErrAbort); |
|
952 |
|
953 if (DataPagedBuffer) |
|
954 { |
|
955 // Note WDP write faults are only reported on the next read |
|
956 WRITE(DataPagedBuffer); // ensure page is not blank and will be read from swap |
|
957 |
|
958 // page fault type: simulated error: exit type: exit category: exit reason: |
|
959 TestPagingError(EPageFaultDataRead, EPagingErrorContextNone, EExitKill, KNullDesC, KErrNone); |
|
960 TestPagingError(EPageFaultDataRead, EPagingErrorContextDataRead, EExitPanic, _L("PAGED-DATA-READ"), KErrAbort); |
|
961 TestPagingError(EPageFaultDataWrite, EPagingErrorContextDataWrite, EExitKill, KNullDesC, KErrNone); |
|
962 TestPagingError(EPageFaultDataRead, EPagingErrorContextNone, EExitPanic, _L("PAGED-DATA-WRITE"), KErrAbort); |
|
963 |
|
964 // this will now always panic when we try to access the first page so destroy and re-create it |
|
965 DataPagedChunk.Close(); |
|
966 CreateDataPagedChunk(); |
|
967 } |
|
968 |
|
969 // test attribution of errors during IPC |
|
970 TPagingErrorContext error; |
|
971 if (RomPagedBuffer) |
|
972 error = EPagingErrorContextRomRead; |
|
973 else if (CodePagedBuffer) |
|
974 error = EPagingErrorContextCodeRead; |
|
975 else |
|
976 error = EPagingErrorContextDataRead; |
|
977 // ipc dir: client paged: server paged: client state: server state: client outcome: server outcome: |
|
978 TestPagedIpc(EServerRead, EDesContentPaged, ENothingPaged, User::ERealtimeStateOff, User::ERealtimeStateOff, EAbortPanic, EBadDescriptor, error); |
812 } |
979 } |
813 |
980 |
814 void TestLock() |
981 void TestLock() |
815 { |
982 { |
816 // make sure live list is big enough |
983 // make sure live list is big enough |
1285 test_KErrNone(UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&PageSize,0)); |
1452 test_KErrNone(UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&PageSize,0)); |
1286 |
1453 |
1287 test.Start(_L("Initialisation")); |
1454 test.Start(_L("Initialisation")); |
1288 |
1455 |
1289 if (DPTest::Attributes() & DPTest::ERomPaging) |
1456 if (DPTest::Attributes() & DPTest::ERomPaging) |
|
1457 { |
1290 test.Printf(_L("Rom paging supported\n")); |
1458 test.Printf(_L("Rom paging supported\n")); |
1291 if (DPTest::Attributes() & DPTest::ECodePaging) |
|
1292 test.Printf(_L("Code paging supported\n")); |
|
1293 if (DPTest::Attributes() & DPTest::EDataPaging) |
|
1294 { |
|
1295 test.Printf(_L("Data paging supported\n")); |
|
1296 DataPagingSupported = ETrue; |
|
1297 TChunkCreateInfo createInfo; |
|
1298 createInfo.SetNormal(KMinBufferSize, KMinBufferSize); |
|
1299 createInfo.SetPaging(TChunkCreateInfo::EPaged); |
|
1300 createInfo.SetOwner(EOwnerProcess); |
|
1301 createInfo.SetGlobal(KChunkName); |
|
1302 test_KErrNone(DataPagedChunk.Create(createInfo)); |
|
1303 test(DataPagedChunk.IsPaged()); // this is only ever called if data paging is supported |
|
1304 DataPagedBuffer = (TUint8*)DataPagedChunk.Base(); |
|
1305 } |
|
1306 |
|
1307 if (DPTest::Attributes() & DPTest::ERomPaging) |
|
1308 { |
|
1309 // Use paged part of rom for testing |
|
1310 TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress(); |
1459 TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress(); |
1311 test(romHeader->iPageableRomStart); |
1460 test(romHeader->iPageableRomStart); |
1312 // todo: for some reason the first part of page of paged rom doesn't seem to get paged out |
1461 // todo: for some reason the first part of page of paged rom doesn't seem to get paged out |
1313 // when we flush the paging cache, hence LargeBuffer starts some way into this |
1462 // when we flush the paging cache, hence RomPagedBuffer starts some way into this |
1314 LargeBuffer = (TUint8*)romHeader + romHeader->iPageableRomStart + 64 * PageSize; |
1463 RomPagedBuffer = (TUint8*)romHeader + romHeader->iPageableRomStart + 64 * PageSize; |
1315 LargeBufferSize = romHeader->iPageableRomSize - 64 * PageSize; |
1464 RomPagedBufferSize = romHeader->iPageableRomSize - 64 * PageSize; |
1316 test(LargeBufferSize > 0); |
1465 test(RomPagedBufferSize > 0); |
1317 // Find a zero word in rom to set PagedHeaderDes to |
1466 } |
1318 TUint* ptr = (TUint*)LargeBuffer; |
1467 |
1319 TUint* end = (TUint*)(LargeBuffer + LargeBufferSize); |
1468 if (DPTest::Attributes() & DPTest::ECodePaging) |
1320 while (*ptr && ptr < end) |
1469 { |
1321 ++ptr; |
1470 test.Printf(_L("Code paging supported\n")); |
1322 test(*ptr == 0); |
|
1323 test.Printf(_L("Found zero word at %08x\n"), ptr); |
|
1324 PagedHeaderDes = (TDesC8*)ptr; |
|
1325 } |
|
1326 else if (DPTest::Attributes() & DPTest::ECodePaging) |
|
1327 { |
|
1328 // Use code paged DLL for testing |
|
1329 test_KErrNone(PagedLibrary.Load(KTCodePagingDll4)); |
1471 test_KErrNone(PagedLibrary.Load(KTCodePagingDll4)); |
1330 TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)PagedLibrary.Lookup(KGetAddressOfDataFunctionOrdinal); |
1472 TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)PagedLibrary.Lookup(KGetAddressOfDataFunctionOrdinal); |
1331 LargeBuffer = (TUint8*)func(LargeBufferSize); |
1473 CodePagedBuffer = (TUint8*)func(CodePagedBufferSize); |
1332 test_NotNull(LargeBuffer); |
1474 test_NotNull(CodePagedBuffer); |
1333 PagedHeaderDes = (TDesC8*)LargeBuffer + 4; |
1475 test(CodePagedBufferSize > KMinBufferSize); |
|
1476 } |
|
1477 |
|
1478 if (DPTest::Attributes() & DPTest::EDataPaging) |
|
1479 { |
|
1480 test.Printf(_L("Data paging supported\n")); |
|
1481 DataPagingSupported = ETrue; |
|
1482 CreateDataPagedChunk(); |
|
1483 } |
|
1484 |
|
1485 if (DPTest::Attributes() & DPTest::ERomPaging) |
|
1486 { |
|
1487 // Use paged part of rom for testing |
|
1488 LargeBuffer = RomPagedBuffer; |
|
1489 LargeBufferSize = RomPagedBufferSize; |
|
1490 } |
|
1491 else if (DPTest::Attributes() & DPTest::ECodePaging) |
|
1492 { |
|
1493 // Use code paged DLL for testing |
|
1494 LargeBuffer = CodePagedBuffer; |
|
1495 LargeBufferSize = CodePagedBufferSize; |
1334 } |
1496 } |
1335 else if (DPTest::Attributes() & DPTest::EDataPaging) |
1497 else if (DPTest::Attributes() & DPTest::EDataPaging) |
1336 { |
1498 { |
1337 // Use data paged chunk for testing |
1499 // Use data paged chunk for testing |
1338 LargeBuffer = DataPagedBuffer; |
1500 LargeBuffer = DataPagedBuffer; |
1388 test.Next(_L("Test IPC read from paged memory")); |
1559 test.Next(_L("Test IPC read from paged memory")); |
1389 TestIPC(); |
1560 TestIPC(); |
1390 |
1561 |
1391 test.Next(_L("Test no kernel faults when copying data from unpaged rom with mutex held")); |
1562 test.Next(_L("Test no kernel faults when copying data from unpaged rom with mutex held")); |
1392 TestReadHoldingMutex(); |
1563 TestReadHoldingMutex(); |
|
1564 |
|
1565 #ifdef _DEBUG |
|
1566 // test hook in kernel not present in release mode |
|
1567 if ((MemModelAttributes() & EMemModelTypeMask) == EMemModelTypeFlexible) |
|
1568 { |
|
1569 test.Next(_L("Test unrecoverable errors while paging")); |
|
1570 TestPagingErrors(); |
|
1571 } |
|
1572 #endif |
1393 |
1573 |
1394 test.Next(_L("Close test driver")); |
1574 test.Next(_L("Close test driver")); |
1395 Ldd.DestroyPlatHwChunk(); |
1575 Ldd.DestroyPlatHwChunk(); |
1396 Ldd.Close(); |
1576 Ldd.Close(); |
1397 |
1577 |
1398 test.Next(_L("Test setting publish and subscribe properties from paged area")); |
1578 test.Next(_L("Test setting publish and subscribe properties from paged area")); |
1399 TestPublishAndSubscribe(); |
1579 TestPublishAndSubscribe(); |
1400 |
1580 |
|
1581 #ifndef _DEBUG |
|
1582 // no point benchmarking in debug mode |
1401 if (DPTest::Attributes() & DPTest::ERomPaging) |
1583 if (DPTest::Attributes() & DPTest::ERomPaging) |
1402 { |
1584 { |
1403 test.Next(_L("Rom Paging Benchmark")); |
1585 test.Next(_L("Rom Paging Benchmark")); |
1404 RomPagingBenchmark(); |
1586 RomPagingBenchmark(); |
1405 } |
1587 } |
|
1588 #endif |
1406 |
1589 |
1407 PagedLibrary.Close(); |
1590 PagedLibrary.Close(); |
1408 gobbler.Close(); |
1591 gobbler.Close(); |
1409 test.End(); |
1592 test.End(); |
1410 |
1593 |