- Merge to trunk r37270.
[reactos.git] / reactos / ntoskrnl / ke / i386 / cpu.c
index 948e037..674d12d 100644 (file)
@@ -994,6 +994,20 @@ KeGetRecommendedSharedDataAlignment(VOID)
     return KeLargestCacheLine;
 }
 
+VOID
+NTAPI
+KiFlushTargetEntireTb(IN PKIPI_CONTEXT PacketContext,
+                      IN PVOID Ignored1,
+                      IN PVOID Ignored2,
+                      IN PVOID Ignored3)
+{
+    /* Signal this packet as done */
+    KiIpiSignalPacketDone(PacketContext);
+
+    /* Flush the TB for the Current CPU */
+    KeFlushCurrentTb();
+}
+
 /*
  * @implemented
  */
@@ -1003,19 +1017,50 @@ KeFlushEntireTb(IN BOOLEAN Invalid,
                 IN BOOLEAN AllProcessors)
 {
     KIRQL OldIrql;
+#ifdef CONFIG_SMP
+    KAFFINITY TargetAffinity;
+    PKPRCB Prcb = KeGetCurrentPrcb();
+#endif
 
     /* Raise the IRQL for the TB Flush */
     OldIrql = KeRaiseIrqlToSynchLevel();
 
 #ifdef CONFIG_SMP
-    /* FIXME: Support IPI Flush */
-#error Not yet implemented!
+    /* FIXME: Use KiTbFlushTimeStamp to synchronize TB flush */
+
+    /* Get the current processor affinity, and exclude ourselves */
+    TargetAffinity = KeActiveProcessors;
+    TargetAffinity &= ~Prcb->SetMember;
+
+    /* Make sure this is MP */
+    if (TargetAffinity)
+    {
+        /* Send an IPI TB flush to the other processors */
+        KiIpiSendPacket(TargetAffinity,
+                        KiFlushTargetEntireTb,
+                        NULL,
+                        0,
+                        NULL);
+    }
 #endif
 
-    /* Flush the TB for the Current CPU */
+    /* Flush the TB for the Current CPU, and update the flush stamp */
     KeFlushCurrentTb();
 
-    /* Return to Original IRQL */
+#ifdef CONFIG_SMP
+    /* If this is MP, wait for the other processors to finish */
+    if (TargetAffinity)
+    {
+        /* Sanity check */
+        ASSERT(Prcb == (volatile PKPRCB)KeGetCurrentPrcb());
+
+        /* FIXME: TODO */
+        ASSERTMSG("Not yet implemented\n", FALSE);
+    }
+#endif
+
+    /* Update the flush stamp and return to original IRQL */
+    InterlockedExchangeAdd(&KiTbFlushTimeStamp, 1);
     KeLowerIrql(OldIrql);
 }