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 |