kernel/eka/memmodel/epoc/flexible/mmu/mmu.cpp
changeset 45 329ab0095843
parent 43 96e5fb8b040d
child 47 46fffbe7b5a7
equal deleted inserted replaced
44:36bfc973b146 45:329ab0095843
   699 	// - The address space of another thread which we are aliasing memory from,
   699 	// - The address space of another thread which we are aliasing memory from,
   700 	//   and we would only do this if we have a reference on this other thread,
   700 	//   and we would only do this if we have a reference on this other thread,
   701 	//   which has a reference on it's process, which should own the address space!
   701 	//   which has a reference on it's process, which should own the address space!
   702 
   702 
   703 #ifdef __BROADCAST_CACHE_MAINTENANCE__
   703 #ifdef __BROADCAST_CACHE_MAINTENANCE__
       
   704 	TInt aliasAsid = -1;
   704 	if (thread->iAliasLinAddr)
   705 	if (thread->iAliasLinAddr)
   705 		{
   706 		{
   706 		// If an alias is in effect, the the thread will be locked to the current CPU,
   707 		// If an alias is in effect, the the thread will be locked to the current CPU,
   707 		// but we need to be able to migrate between CPUs for cache maintainance.  This
   708 		// but we need to be able to migrate between CPUs for cache maintainance.  This
   708 		// must be dealt with by removing the alias and restoring it with a paging trap
   709 		// must be dealt with by removing the alias and restoring it with a paging trap
   711 			{
   712 			{
   712 			// oops, kill system...
   713 			// oops, kill system...
   713 			__KTRACE_OPT2(KPAGING,KPANIC,Kern::Printf("Fault with thread locked to current CPU! addr=0x%08x (%O pc=%x)",aFaultAddress,thread,aPc));
   714 			__KTRACE_OPT2(KPAGING,KPANIC,Kern::Printf("Fault with thread locked to current CPU! addr=0x%08x (%O pc=%x)",aFaultAddress,thread,aPc));
   714 			Exc::Fault(aExceptionInfo);
   715 			Exc::Fault(aExceptionInfo);
   715 			}
   716 			}
       
   717 		// Open a reference on the aliased process's os asid before removing the alias
       
   718 		// so that the address space can't be freed while we try to access its members.
       
   719 		aliasAsid = thread->iAliasProcess->TryOpenOsAsid();
       
   720 		// This should never fail as until we remove the alias there will 
       
   721 		// always be at least one reference on the os asid.
       
   722 		__NK_ASSERT_DEBUG(aliasAsid >= 0);
   716 		thread->RemoveAlias();
   723 		thread->RemoveAlias();
   717 		}
   724 		}
   718 #endif
   725 #endif
   719 
   726 
   720 	// find mapping...
   727 	// find mapping...
   781 		// restore address space (because the trap will bypass any code
   788 		// restore address space (because the trap will bypass any code
   782 		// which would have done this.)...
   789 		// which would have done this.)...
   783 		DMemModelThread::RestoreAddressSpace();
   790 		DMemModelThread::RestoreAddressSpace();
   784 		}
   791 		}
   785 
   792 
       
   793 #ifdef __BROADCAST_CACHE_MAINTENANCE__
       
   794 	// Close any reference on the aliased process's os asid before we leave the
       
   795 	// critical section.
       
   796 	if (aliasAsid >= 0)
       
   797 		{
       
   798 		thread->iAliasProcess->CloseOsAsid();
       
   799 		}
       
   800 #endif
       
   801 
   786 	NKern::ThreadLeaveCS();  // thread will die now if CheckRealtimeThreadFault caused a panic
   802 	NKern::ThreadLeaveCS();  // thread will die now if CheckRealtimeThreadFault caused a panic
   787 
   803 
   788 	// deal with XTRAP_PAGING...
   804 	// deal with XTRAP_PAGING...
   789 	if(trap)
   805 	if(trap)
   790 		{
   806 		{
  1282 		}
  1298 		}
  1283 
  1299 
  1284 	iCount = 0;
  1300 	iCount = 0;
  1285 	}
  1301 	}
  1286 
  1302 
       
  1303 #ifdef __SMP__
       
  1304 /**
       
  1305 Dummy IPI to be invoked when a thread's alias pde members are updated remotely
       
  1306 by another thread.
       
  1307 
       
  1308 @internalComponent
       
  1309 */
       
  1310 class TAliasIPI : public TGenericIPI
       
  1311 	{
       
  1312 public:
       
  1313 	static void RefreshIsr(TGenericIPI*);
       
  1314 	void RefreshAlias();
       
  1315 	};
       
  1316 
       
  1317 
       
  1318 /**
       
  1319 Dummy isr method.
       
  1320 */
       
  1321 void TAliasIPI::RefreshIsr(TGenericIPI*)
       
  1322 	{
       
  1323 	TRACE2(("TAliasIPI"));
       
  1324 	}
       
  1325 
       
  1326 
       
  1327 /**
       
  1328 Queue the dummy IPI on all other processors.  This ensures that DoProcessSwitch will
       
  1329 have completed updating iAliasPdePtr once this method returns.
       
  1330 */
       
  1331 void TAliasIPI::RefreshAlias()
       
  1332 	{
       
  1333 	NKern::Lock();
       
  1334 	QueueAllOther(&RefreshIsr);
       
  1335 	NKern::Unlock();
       
  1336 	WaitCompletion();
       
  1337 	}
       
  1338 
       
  1339 
       
  1340 /** 
       
  1341 Perform a dummy ipi on all the other processors to ensure if any of them are 
       
  1342 executing DoProcessSwitch they will see the new value of iAliasPde before they 
       
  1343 update iAliasPdePtr or will finish updating iAliasPdePtr before we continue.  
       
  1344 This works as DoProcessSwitch() has interrupts disabled while reading iAliasPde 
       
  1345 and updating iAliasPdePtr.
       
  1346 */
       
  1347 void BroadcastAliasRefresh()
       
  1348 	{
       
  1349 	TAliasIPI ipi;
       
  1350 	ipi.RefreshAlias();
       
  1351 	}
       
  1352 #endif //__SMP__
  1287 
  1353 
  1288 /**
  1354 /**
  1289 Remove any thread IPC aliases which use the specified page table.
  1355 Remove any thread IPC aliases which use the specified page table.
  1290 This is used by the page table allocator when a page table is freed.
  1356 This is used by the page table allocator when a page table is freed.
  1291 
  1357 
  1309 			{
  1375 			{
  1310 			// the page table is being aliased by the thread, so remove it...
  1376 			// the page table is being aliased by the thread, so remove it...
  1311 			TRACE2(("Thread %O RemoveAliasesForPageTable", this));
  1377 			TRACE2(("Thread %O RemoveAliasesForPageTable", this));
  1312 			thread->iAliasPde = KPdeUnallocatedEntry;
  1378 			thread->iAliasPde = KPdeUnallocatedEntry;
  1313 #ifdef __SMP__ // we need to also unmap the page table in case thread is running on another core...
  1379 #ifdef __SMP__ // we need to also unmap the page table in case thread is running on another core...
  1314 			// need Data Memory Barrier (DMB) here to make sure iAliasPde change is
  1380 
  1315 			// seen before we set the PDE entry, otherwise 'thread' may read old value
  1381 			// Ensure other processors see the update to iAliasPde.
  1316 			// and put it back
  1382 			BroadcastAliasRefresh();
  1317 			__e32_memory_barrier();
  1383 
  1318 			*thread->iAliasPdePtr = KPdeUnallocatedEntry;
  1384 			*thread->iAliasPdePtr = KPdeUnallocatedEntry;
       
  1385 
  1319 			SinglePdeUpdated(thread->iAliasPdePtr);
  1386 			SinglePdeUpdated(thread->iAliasPdePtr);
  1320 			__NK_ASSERT_DEBUG((thread->iAliasLinAddr&KPageMask)==0);
  1387 			__NK_ASSERT_DEBUG((thread->iAliasLinAddr&KPageMask)==0);
  1321 			// Invalidate the tlb for the page using os asid of the process that created the alias
  1388 			// Invalidate the tlb for the page using os asid of the process that created the alias
  1322 			// this is safe as the os asid will be valid as thread must be running otherwise the alias
  1389 			// this is safe as the os asid will be valid as thread must be running otherwise the alias
  1323 			// would have been removed.
  1390 			// would have been removed.
  1324 			InvalidateTLBForPage(thread->iAliasLinAddr | ((DMemModelProcess*)thread->iOwningProcess)->OsAsid());
  1391 			InvalidateTLBForPage(thread->iAliasLinAddr | ((DMemModelProcess*)thread->iOwningProcess)->OsAsid());
  1325 			// note, race condition with 'thread' updating its iAliasLinAddr is
  1392 			// note, race condition with 'thread' updating its iAliasLinAddr is
  1326 			// not a problem because 'thread' will not the be accessing the aliased
  1393 			// not a problem because 'thread' will not the be accessing the aliased
  1327 			// region and will take care of invalidating the TLB.
  1394 			// region and will take care of invalidating the TLB.
  1328 			// FIXME: There is still a race here. If the thread owning the alias reads the
       
  1329 			// PDE before we clear thread->iAliasPde and writes it after we clear
       
  1330 			// *thread->iAliasPdePtr the alias still ends up restored when it shouldn't be.
       
  1331 #endif
  1395 #endif
  1332 			}
  1396 			}
  1333 		MmuLock::Flash();
  1397 		MmuLock::Flash();
  1334 		}
  1398 		}
  1335 
  1399