kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp
changeset 259 57b9594f5772
parent 201 43365a9b78a3
--- a/kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp	Wed Aug 18 11:08:29 2010 +0300
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mpager.cpp	Thu Sep 02 21:54:16 2010 +0300
@@ -2044,9 +2044,8 @@
 	}
 
 
-TInt DPager::CheckRealtimeThreadFault(DThread* aThread, TAny* aExceptionInfo)
+DThread* DPager::ResponsibleThread(DThread* aThread, TAny* aExceptionInfo)
 	{
-	// realtime threads shouldn't take paging faults...
 	DThread* client = aThread->iIpcClient;
 
 	// If iIpcClient is set then we are accessing the address space of a remote thread.  If we are
@@ -2055,29 +2054,81 @@
 	TIpcExcTrap* ipcTrap = (TIpcExcTrap*)aThread->iExcTrap;
 	if (ipcTrap && !ipcTrap->IsTIpcExcTrap())
 		ipcTrap = 0;
-	if (client && (!ipcTrap || ipcTrap->ExcLocation(aThread, aExceptionInfo) == TIpcExcTrap::EExcRemote))
+	if (client &&
+		(!ipcTrap || ipcTrap->ExcLocation(aThread, aExceptionInfo) == TIpcExcTrap::EExcRemote))
+		return client;
+	else
+		return NULL;
+	}
+
+
+TInt DPager::CheckRealtimeThreadFault(DThread* aThread, TAny* aExceptionInfo)
+	{
+	// realtime threads shouldn't take paging faults...
+	DThread* thread = ResponsibleThread(aThread, aExceptionInfo);
+
+	const char* message = thread ?
+		"Access to Paged Memory (by other thread)" : "Access to Paged Memory";
+
+	// kill respsonsible thread...
+	if(K::IllegalFunctionForRealtimeThread(thread, message))
 		{
-		// kill client thread...
-		if(K::IllegalFunctionForRealtimeThread(client,"Access to Paged Memory (by other thread)"))
-			{
-			// treat memory access as bad...
-			return KErrAbort;
-			}
-		// else thread is in 'warning only' state so allow paging...
+		// if we are killing the current thread and we are in a critical section, then the above
+		// kill will be deferred and we will continue executing. We will handle this by returning an
+		// error which means that the thread will take an exception (which hopefully is XTRAPed!)
+
+		// treat memory access as bad...
+		return KErrAbort;
 		}
 	else
 		{
-		// kill current thread...
-		if(K::IllegalFunctionForRealtimeThread(NULL,"Access to Paged Memory"))
-			{
-			// if current thread is in critical section, then the above kill will be deferred
-			// and we will continue executing. We will handle this by returning an error
-			// which means that the thread will take an exception (which hopefully is XTRAPed!)
-			return KErrAbort;
-			}
-		// else thread is in 'warning only' state so allow paging...
+		// thread is in 'warning only' state so allow paging...
+		return KErrNone;
 		}
-	return KErrNone;
+	}
+
+
+void DPager::KillResponsibleThread(TPagingErrorContext aContext, TInt aErrorCode,
+								   TAny* aExceptionInfo)
+	{
+	const char* message = NULL;
+	switch (aContext)
+		{
+		case EPagingErrorContextRomRead:
+			message = "PAGED-ROM-READ";
+			break;
+		case EPagingErrorContextRomDecompress:
+			message = "PAGED-ROM-COMP";
+			break;
+		case EPagingErrorContextCodeRead:
+			message = "PAGED-CODE-READ";
+			break;
+		case EPagingErrorContextCodeDecompress:
+			message = "PAGED-CODE-COMP";
+			break;
+		case EPagingErrorContextDataRead:
+			message = "PAGED-DATA-READ";
+			break;
+		case EPagingErrorContextDataWrite:
+			message = "PAGED-DATA-WRITE";
+			break;
+		default:
+			message = "PAGED-UNKNOWN";
+			break;
+		}
+
+	TPtrC8 category((const unsigned char*)message);
+	DThread* thread = ResponsibleThread(TheCurrentThread, aExceptionInfo);
+	if (thread)
+		{
+		NKern::LockSystem();
+		thread->Die(EExitPanic, aErrorCode,  category);
+		}
+	else
+		{
+		TheCurrentThread->SetExitInfo(EExitPanic, aErrorCode, category);
+		NKern::DeferredExit();
+		}
 	}
 
 
@@ -2103,6 +2154,16 @@
 		r = manager->HandleFault(aMemory, aFaultIndex, aMapping, aMapInstanceCount, aAccessPermissions);
 
 		TheThrashMonitor.NotifyEndPaging();
+
+		// If the paging system encountered an error paging in the memory (as opposed to a thread
+		// accessing non-existent memory), then panic the appropriate thread.  Unfortunately this
+		// situation does occur as media such as eMMC wears out towards the end of its life. 
+		if (r != KErrNone)
+			{
+			TPagingErrorContext context = ExtractErrorContext(r);
+			if (context != EPagingErrorContextNone)
+				KillResponsibleThread(context, ExtractErrorCode(r), aExceptionInfo);
+			}
 		}
 	return r;
 	}
@@ -2644,7 +2705,18 @@
 		if ((K::MemModelAttributes & EMemModelAttrDataPaging) == 0)
 			return KErrNotSupported;
 		return SetDataWriteSize((TUint)a1);
-	
+
+#ifdef _DEBUG
+	case EVMHalDebugSetFail:
+		{
+		TUint context = (TUint)a1;
+		if (context >= EMaxPagingErrorContext)
+			return KErrArgument;
+		__e32_atomic_store_ord32(&(ThePager.iDebugFailContext), context);
+		return KErrNone;
+		}
+#endif
+
 	default:
 		return KErrNotSupported;
 		}