Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

969 lines
20 KiB

  1. /*++
  2. Module Name:
  3. flushtb.c
  4. Abstract:
  5. This module implement machine dependent functions to flush the
  6. translation buffer and synchronize PIDs in an MP system.
  7. Author:
  8. Koichi Yamada 2-Jan-95
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. extern KSPIN_LOCK KiTbBroadcastLock;
  15. #define _x256mb (1024*1024*256)
  16. #define KiFlushSingleTbGlobal(Invalid, Va) __ptcga((__int64)Va, PAGE_SHIFT << 2)
  17. #define KiFlushSingleTbLocal(Invalid, va) __ptcl((__int64)va, PAGE_SHIFT << 2)
  18. #define KiTbSynchronizeGlobal() { __mf(); __isrlz(); }
  19. #define KiTbSynchronizeLocal() { __isrlz(); }
  20. #define KiFlush2gbTbGlobal(Invalid) \
  21. { \
  22. __ptcga((__int64)0, 28 << 2); \
  23. __ptcg((__int64)_x256mb, 28 << 2); \
  24. __ptcg((__int64)_x256mb*2,28 << 2); \
  25. __ptcg((__int64)_x256mb*3, 28 << 2); \
  26. __ptcg((__int64)_x256mb*4, 28 << 2); \
  27. __ptcg((__int64)_x256mb*5, 28 << 2); \
  28. __ptcg((__int64)_x256mb*6, 28 << 2); \
  29. __ptcg((__int64)_x256mb*7, 28 << 2); \
  30. }
  31. #define KiFlush2gbTbLocal(Invalid) \
  32. { \
  33. __ptcl((__int64)0, 28 << 2); \
  34. __ptcl((__int64)_x256mb, 28 << 2); \
  35. __ptcl((__int64)_x256mb*2,28 << 2); \
  36. __ptcl((__int64)_x256mb*3, 28 << 2); \
  37. __ptcl((__int64)_x256mb*4, 28 << 2); \
  38. __ptcl((__int64)_x256mb*5, 28 << 2); \
  39. __ptcl((__int64)_x256mb*6, 28 << 2); \
  40. __ptcl((__int64)_x256mb*7, 28 << 2); \
  41. }
  42. //
  43. // flag to perform the IPI based TLB shootdown
  44. //
  45. BOOLEAN KiIpiTbShootdown = TRUE;
  46. VOID
  47. KiAttachRegion(
  48. IN PKPROCESS Process
  49. );
  50. VOID
  51. KiDetachRegion(
  52. VOID
  53. );
  54. //
  55. // Define forward referenced prototypes.
  56. //
  57. VOID
  58. KiFlushEntireTbTarget (
  59. IN PULONG SignalDone,
  60. IN PVOID Parameter1,
  61. IN PVOID Parameter2,
  62. IN PVOID Parameter3
  63. );
  64. VOID
  65. KiFlushForwardProgressTbBuffer(
  66. KAFFINITY TargetProcessors
  67. );
  68. VOID
  69. KiFlushForwardProgressTbBufferLocal(
  70. VOID
  71. );
  72. KiPurgeTranslationCache (
  73. ULONGLONG Base,
  74. ULONGLONG Stride1,
  75. ULONGLONG Stride2,
  76. ULONGLONG Count1,
  77. ULONGLONG Count2
  78. );
  79. extern IA64_PTCE_INFO KiIA64PtceInfo;
  80. VOID
  81. KeFlushCurrentTb (
  82. VOID
  83. )
  84. {
  85. KiPurgeTranslationCache(
  86. KiIA64PtceInfo.PtceBase,
  87. KiIA64PtceInfo.PtceStrides.Strides1,
  88. KiIA64PtceInfo.PtceStrides.Strides2,
  89. KiIA64PtceInfo.PtceTcCount.Count1,
  90. KiIA64PtceInfo.PtceTcCount.Count2);
  91. }
  92. VOID
  93. KeFlushEntireTb (
  94. IN BOOLEAN Invalid,
  95. IN BOOLEAN AllProcessors
  96. )
  97. /*++
  98. Routine Description:
  99. This function flushes the entire translation buffer (TB) on all
  100. processors that are currently running threads which are children
  101. of the current process or flushes the entire translation buffer
  102. on all processors in the host configuration.
  103. Arguments:
  104. Invalid - Supplies a boolean value that specifies the reason for
  105. flushing the translation buffer.
  106. AllProcessors - Supplies a boolean value that determines which
  107. translation buffers are to be flushed.
  108. Return Value:
  109. None.
  110. --*/
  111. {
  112. KIRQL OldIrql;
  113. KAFFINITY TargetProcessors;
  114. #if defined(NT_UP)
  115. OldIrql = KeRaiseIrqlToSynchLevel();
  116. #else
  117. KiLockContextSwap(&OldIrql);
  118. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  119. KiSetTbFlushTimeStampBusy();
  120. if (TargetProcessors != 0) {
  121. KiIpiSendPacket(TargetProcessors,
  122. KiFlushEntireTbTarget,
  123. NULL,
  124. NULL,
  125. NULL);
  126. }
  127. if (PsGetCurrentProcess()->Wow64Process != NULL) {
  128. KiFlushForwardProgressTbBufferLocal();
  129. }
  130. #endif
  131. KeFlushCurrentTb();
  132. //
  133. // flush ALAT
  134. //
  135. __invalat();
  136. //
  137. // Wait until all target processors have finished.
  138. //
  139. #if defined(NT_UP)
  140. InterlockedIncrement((PLONG)&KiTbFlushTimeStamp);
  141. KeLowerIrql(OldIrql);
  142. #else
  143. if (TargetProcessors != 0) {
  144. KiIpiStallOnPacketTargets(TargetProcessors);
  145. }
  146. KiClearTbFlushTimeStampBusy();
  147. KiUnlockContextSwap(OldIrql);
  148. #endif
  149. return;
  150. }
  151. VOID
  152. KiFlushEntireTbTarget (
  153. IN PULONG SignalDone,
  154. IN PVOID Parameter1,
  155. IN PVOID Parameter2,
  156. IN PVOID Parameter3
  157. )
  158. /*++
  159. Routine Description:
  160. This is the target function for flushing the entire TB.
  161. Arguments:
  162. SignalDone Supplies a pointer to a variable that is cleared when the
  163. requested operation has been performed.
  164. Parameter1 - Parameter3 - Not used.
  165. Return Value:
  166. None.
  167. --*/
  168. {
  169. #if !defined(NT_UP)
  170. //
  171. // Flush the entire TB on the current processor.
  172. //
  173. KiIpiSignalPacketDone(SignalDone);
  174. KiFlushForwardProgressTbBufferLocal();
  175. KeFlushCurrentTb();
  176. //
  177. // flush ALAT
  178. //
  179. __invalat();
  180. #endif
  181. return;
  182. }
  183. #if !defined(NT_UP)
  184. VOID
  185. KiFlushMultipleTbTarget (
  186. IN PKIPI_CONTEXT SignalDone,
  187. IN PVOID Number,
  188. IN PVOID Virtual,
  189. IN PVOID Process
  190. )
  191. /*++
  192. Routine Description:
  193. This is the target function for flushing multiple TB entries.
  194. Arguments:
  195. SignalDone Supplies a pointer to a variable that is cleared when the
  196. requested operation has been performed.
  197. Number - Supplies the number of TB entries to flush.
  198. Virtual - Supplies a pointer to an array of virtual addresses that
  199. are within the pages whose translation buffer entries are to be
  200. flushed.
  201. Process - Supplies a KPROCESS pointer which needs TB be flushed.
  202. Return Value:
  203. None.
  204. --*/
  205. {
  206. ULONG Index;
  207. ULONG Limit;
  208. BOOLEAN SameProcess = FALSE;
  209. Limit = (ULONG)((ULONG_PTR)Number);
  210. //
  211. // Flush the specified virtual address for the TB on the current
  212. // processor.
  213. //
  214. KiFlushForwardProgressTbBufferLocal();
  215. if (Process == (PKPROCESS)PCR->Pcb) {
  216. SameProcess = TRUE;
  217. } else {
  218. KiAttachRegion((PKPROCESS)Process);
  219. }
  220. for (Index = 0; Index < Limit; Index += 1) {
  221. KiFlushSingleTbLocal((BOOLEAN)Invalid, ((PVOID *)(Virtual))[Index]);
  222. }
  223. #ifdef MI_ALTFLG_FLUSH2G
  224. if (((PEPROCESS)Process)->Flags & PS_PROCESS_FLAGS_WOW64_SPLIT_PAGES) {
  225. ASSERT (((PEPROCESS)Process)->Wow64Process != NULL);
  226. KiFlush2gbTbLocal(Invalid);
  227. }
  228. #endif
  229. if (SameProcess != TRUE) {
  230. KiDetachRegion();
  231. }
  232. KiIpiSignalPacketDone(SignalDone);
  233. __invalat();
  234. KiTbSynchronizeLocal();
  235. }
  236. #endif
  237. VOID
  238. KeFlushMultipleTb (
  239. IN ULONG Number,
  240. IN PVOID *Virtual,
  241. IN BOOLEAN Invalid,
  242. IN BOOLEAN AllProcessors,
  243. IN PHARDWARE_PTE *PtePointer OPTIONAL,
  244. IN HARDWARE_PTE PteValue
  245. )
  246. /*++
  247. Routine Description:
  248. This function flushes multiple entries from the translation buffer
  249. on all processors that are currently running threads which are
  250. children of the current process or flushes multiple entries from
  251. the translation buffer on all processors in the host configuration.
  252. N.B. The specified translation entries on all processors in the host
  253. configuration are always flushed since PowerPC TB is tagged by
  254. VSID and translations are held across context switch boundaries.
  255. Arguments:
  256. Number - Supplies the number of TB entries to flush.
  257. Virtual - Supplies a pointer to an array of virtual addresses that
  258. are within the pages whose translation buffer entries are to be
  259. flushed.
  260. Invalid - Supplies a boolean value that specifies the reason for
  261. flushing the translation buffer.
  262. AllProcessors - Supplies a boolean value that determines which
  263. translation buffers are to be flushed.
  264. PtePointer - Supplies an optional pointer to an array of pointers to
  265. page table entries that receive the specified page table entry
  266. value.
  267. PteValue - Supplies the the new page table entry value.
  268. Return Value:
  269. None.
  270. --*/
  271. {
  272. ULONG Index;
  273. PKPRCB Prcb;
  274. KAFFINITY TargetProcessors;
  275. KIRQL OldIrql;
  276. PVOID Wow64Process;
  277. PEPROCESS Process;
  278. BOOLEAN Flush2gb = FALSE;
  279. #if defined(NT_UP)
  280. OldIrql = KeRaiseIrqlToSynchLevel();
  281. #else
  282. KiLockContextSwap(&OldIrql);
  283. #endif
  284. Process = PsGetCurrentProcess();
  285. Wow64Process = Process->Wow64Process;
  286. #ifdef MI_ALTFLG_FLUSH2G
  287. if (Process->Flags & PS_PROCESS_FLAGS_WOW64_SPLIT_PAGES) {
  288. ASSERT (Wow64Process != NULL);
  289. Flush2gb = TRUE;
  290. }
  291. #endif
  292. //
  293. // If a page table entry address array is specified, then set the
  294. // specified page table entries to the specific value.
  295. //
  296. #if !defined(NT_UP)
  297. TargetProcessors = KeActiveProcessors;
  298. TargetProcessors &= PCR->NotMember;
  299. if (TargetProcessors != 0) {
  300. //
  301. // Acquire a global lock. Only one processor at a time can issue
  302. // a PTC.G operation.
  303. //
  304. if (KiIpiTbShootdown == TRUE) {
  305. for (Index = 0; Index < Number; Index += 1) {
  306. if (ARGUMENT_PRESENT(PtePointer)) {
  307. *PtePointer[Index] = PteValue;
  308. }
  309. }
  310. KiIpiSendPacket(TargetProcessors,
  311. KiFlushMultipleTbTarget,
  312. (PVOID)(ULONG_PTR)Number,
  313. (PVOID)Virtual,
  314. (PVOID)PsGetCurrentProcess());
  315. if (Wow64Process != NULL) {
  316. KiFlushForwardProgressTbBufferLocal();
  317. }
  318. //
  319. // Flush the specified entries from the TB on the current processor.
  320. //
  321. for (Index = 0; Index < Number; Index += 1) {
  322. KiFlushSingleTbLocal(Invalid, Virtual[Index]);
  323. }
  324. //
  325. // flush ALAT
  326. //
  327. __invalat();
  328. KiIpiStallOnPacketTargets(TargetProcessors);
  329. KiTbSynchronizeLocal();
  330. } else {
  331. KiAcquireSpinLock(&KiTbBroadcastLock);
  332. for (Index = 0; Index < Number; Index += 1) {
  333. if (ARGUMENT_PRESENT(PtePointer)) {
  334. *PtePointer[Index] = PteValue;
  335. }
  336. //
  337. // Flush the specified TB on each processor. Hardware automatically
  338. // perform broadcasts if MP.
  339. //
  340. KiFlushSingleTbGlobal(Invalid, Virtual[Index]);
  341. }
  342. if (Wow64Process != NULL) {
  343. KiFlushForwardProgressTbBuffer(TargetProcessors);
  344. }
  345. if (Flush2gb == TRUE) {
  346. KiFlush2gbTbGlobal(Invalid);
  347. }
  348. //
  349. // Wait for the broadcast to be complete.
  350. //
  351. KiTbSynchronizeGlobal();
  352. KiReleaseSpinLock(&KiTbBroadcastLock);
  353. }
  354. }
  355. else {
  356. for (Index = 0; Index < Number; Index += 1) {
  357. if (ARGUMENT_PRESENT(PtePointer)) {
  358. *PtePointer[Index] = PteValue;
  359. }
  360. //
  361. // Flush the specified TB on the local processor. No broadcast is
  362. // performed.
  363. //
  364. KiFlushSingleTbLocal(Invalid, Virtual[Index]);
  365. }
  366. if (Wow64Process != NULL) {
  367. KiFlushForwardProgressTbBufferLocal();
  368. }
  369. if (Flush2gb == TRUE) {
  370. KiFlush2gbTbLocal(Invalid);
  371. }
  372. KiTbSynchronizeLocal();
  373. }
  374. KiUnlockContextSwap(OldIrql);
  375. #else
  376. for (Index = 0; Index < Number; Index += 1) {
  377. if (ARGUMENT_PRESENT(PtePointer)) {
  378. *PtePointer[Index] = PteValue;
  379. }
  380. //
  381. // Flush the specified TB on the local processor. No broadcast is
  382. // performed.
  383. //
  384. KiFlushSingleTbLocal(Invalid, Virtual[Index]);
  385. }
  386. if (Wow64Process != NULL) {
  387. KiFlushForwardProgressTbBufferLocal();
  388. }
  389. if (Flush2gb == TRUE) {
  390. KiFlush2gbTbLocal(Invalid);
  391. }
  392. KiTbSynchronizeLocal();
  393. KeLowerIrql(OldIrql);
  394. #endif
  395. return;
  396. }
  397. #if !defined(NT_UP)
  398. VOID
  399. KiFlushSingleTbTarget (
  400. IN PKIPI_CONTEXT SignalDone,
  401. IN PVOID Virtual,
  402. IN PKPROCESS Process,
  403. IN PVOID Parameter3
  404. )
  405. /*++
  406. Routine Description:
  407. This is the target function for flushing a single TB entry.
  408. Arguments:
  409. SignalDone Supplies a pointer to a variable that is cleared when the
  410. requested operation has been performed.
  411. Virtual - Supplies a virtual address that is within the page whose
  412. translation buffer entry is to be flushed.
  413. RequestPacket - Supplies a pointer to a flush single TB packet address.
  414. Process - Supplies a KPROCESS pointer which needs TB be flushed.
  415. Parameter3 - Not used.
  416. Return Value:
  417. None.
  418. --*/
  419. {
  420. BOOLEAN SameProcess = FALSE;
  421. //
  422. // Flush a single entry from the TB on the current processor.
  423. //
  424. KiFlushForwardProgressTbBufferLocal();
  425. if (Process == (PKPROCESS)PCR->Pcb) {
  426. SameProcess = TRUE;
  427. } else {
  428. KiAttachRegion((PKPROCESS)Process);
  429. }
  430. KiFlushSingleTbLocal(TRUE, Virtual);
  431. #ifdef MI_ALTFLG_FLUSH2G
  432. if (((PEPROCESS)Process)->Flags & PS_PROCESS_FLAGS_WOW64_SPLIT_PAGES) {
  433. ASSERT (((PEPROCESS)Process)->Wow64Process != NULL);
  434. KiFlush2gbTbLocal(Invalid);
  435. }
  436. #endif
  437. if (SameProcess != TRUE) {
  438. KiDetachRegion();
  439. }
  440. KiIpiSignalPacketDone(SignalDone);
  441. __invalat();
  442. KiTbSynchronizeLocal();
  443. return;
  444. }
  445. #endif
  446. HARDWARE_PTE
  447. KeFlushSingleTb (
  448. IN PVOID Virtual,
  449. IN BOOLEAN Invalid,
  450. IN BOOLEAN AllProcessors,
  451. IN PHARDWARE_PTE PtePointer,
  452. IN HARDWARE_PTE PteValue
  453. )
  454. /*++
  455. Routine Description:
  456. This function flushes a single entry from the translation buffer
  457. on all processors that are currently running threads which are
  458. children of the current process or flushes a single entry from
  459. the translation buffer on all processors in the host configuration.
  460. N.B. The specified translation entry on all processors in the host
  461. configuration is always flushed since PowerPC TB is tagged by
  462. VSID and translations are held across context switch boundaries.
  463. Arguments:
  464. Virtual - Supplies a virtual address that is within the page whose
  465. translation buffer entry is to be flushed.
  466. Invalid - Supplies a boolean value that specifies the reason for
  467. flushing the translation buffer.
  468. AllProcessors - Supplies a boolean value that determines which
  469. translation buffers are to be flushed.
  470. PtePointer - Supplies a pointer to the page table entry which
  471. receives the specified value.
  472. PteValue - Supplies the the new page table entry value.
  473. Return Value:
  474. The previous contents of the specified page table entry is returned
  475. as the function value.
  476. --*/
  477. {
  478. HARDWARE_PTE OldPte;
  479. PKPRCB Prcb;
  480. KAFFINITY TargetProcessors;
  481. KIRQL OldIrql;
  482. PEPROCESS Process;
  483. PVOID Wow64Process;
  484. BOOLEAN Flush2gb = FALSE;
  485. #if defined(NT_UP)
  486. OldIrql = KeRaiseIrqlToSynchLevel();
  487. #else
  488. KiLockContextSwap(&OldIrql);
  489. #endif
  490. Process = (PEPROCESS)PsGetCurrentProcess();
  491. Wow64Process = Process->Wow64Process;
  492. #ifdef MI_ALTFLG_FLUSH2G
  493. if (Process->Flags & PS_PROCESS_FLAGS_WOW64_SPLIT_PAGES) {
  494. ASSERT (((PEPROCESS)Process)->Wow64Process != NULL);
  495. Flush2gb = TRUE;
  496. }
  497. #endif
  498. //
  499. // Capture the previous contents of the page table entry and set the
  500. // page table entry to the new value.
  501. //
  502. OldPte = *PtePointer;
  503. *PtePointer = PteValue;
  504. #if !defined(NT_UP)
  505. TargetProcessors = KeActiveProcessors;
  506. TargetProcessors &= PCR->NotMember;
  507. if (TargetProcessors != 0) {
  508. if (KiIpiTbShootdown == TRUE) {
  509. KiIpiSendPacket(TargetProcessors,
  510. KiFlushSingleTbTarget,
  511. (PVOID)Virtual,
  512. (PVOID)PsGetCurrentProcess(),
  513. NULL);
  514. if (Wow64Process != NULL) {
  515. KiFlushForwardProgressTbBufferLocal();
  516. }
  517. KiFlushSingleTbLocal(Invalid, Virtual);
  518. //
  519. // flush ALAT
  520. //
  521. __invalat();
  522. KiIpiStallOnPacketTargets(TargetProcessors);
  523. } else {
  524. //
  525. // Flush the specified TB on each processor. Hardware automatically
  526. // perform broadcasts if MP.
  527. //
  528. KiAcquireSpinLock(&KiTbBroadcastLock);
  529. KiFlushSingleTbGlobal(Invalid, Virtual);
  530. if (Wow64Process != NULL) {
  531. KiFlushForwardProgressTbBuffer(TargetProcessors);
  532. }
  533. if (Flush2gb) {
  534. KiFlush2gbTbGlobal(Invalid);
  535. }
  536. KiTbSynchronizeGlobal();
  537. KiReleaseSpinLock(&KiTbBroadcastLock);
  538. }
  539. }
  540. else {
  541. //
  542. // Flush the specified TB on the local processor. No broadcast is
  543. // performed.
  544. //
  545. KiFlushSingleTbLocal(Invalid, Virtual);
  546. if (Wow64Process != NULL) {
  547. KiFlushForwardProgressTbBufferLocal();
  548. }
  549. if (Flush2gb == TRUE) {
  550. KiFlush2gbTbLocal(Invalid);
  551. }
  552. KiTbSynchronizeLocal();
  553. }
  554. KiUnlockContextSwap(OldIrql);
  555. #else
  556. //
  557. // Flush the specified entry from the TB on the local processor.
  558. //
  559. KiFlushSingleTbLocal(Invalid, Virtual);
  560. if (Wow64Process != NULL) {
  561. KiFlushForwardProgressTbBufferLocal();
  562. }
  563. if (Flush2gb == TRUE) {
  564. KiFlush2gbTbLocal(Invalid);
  565. }
  566. KiTbSynchronizeLocal();
  567. KeLowerIrql(OldIrql);
  568. #endif
  569. //
  570. // Return the previous page table entry value.
  571. //
  572. return OldPte;
  573. }
  574. VOID
  575. KiFlushForwardProgressTbBuffer(
  576. KAFFINITY TargetProcessors
  577. )
  578. {
  579. PKPRCB Prcb;
  580. ULONG BitNumber;
  581. PKPROCESS CurrentProcess;
  582. PKPROCESS TargetProcess;
  583. PKPCR Pcr;
  584. ULONG i;
  585. PVOID Va;
  586. volatile ULONGLONG *PointerPte;
  587. CurrentProcess = KeGetCurrentThread()->ApcState.Process;
  588. //
  589. // Flush the ForwardProgressTb buffer on the current processor
  590. //
  591. for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) {
  592. Va = (PVOID)PCR->ForwardProgressBuffer[i*2];
  593. PointerPte = &PCR->ForwardProgressBuffer[(i*2)+1];
  594. if (*PointerPte != 0) {
  595. *PointerPte = 0;
  596. KiFlushSingleTbGlobal(Invalid, Va);
  597. }
  598. }
  599. //
  600. // Flush the ForwardProgressTb buffer on all the processors
  601. //
  602. while (TargetProcessors != 0) {
  603. KeFindFirstSetLeftAffinity(TargetProcessors, &BitNumber);
  604. ClearMember(BitNumber, TargetProcessors);
  605. Prcb = KiProcessorBlock[BitNumber];
  606. Pcr = KSEG_ADDRESS(Prcb->PcrPage);
  607. TargetProcess = (PKPROCESS)Pcr->Pcb;
  608. if (TargetProcess == CurrentProcess) {
  609. for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) {
  610. Va = (PVOID)Pcr->ForwardProgressBuffer[i*2];
  611. PointerPte = &Pcr->ForwardProgressBuffer[(i*2)+1];
  612. if (*PointerPte != 0) {
  613. *PointerPte = 0;
  614. KiFlushSingleTbGlobal(Invalid, Va);
  615. }
  616. }
  617. }
  618. }
  619. }
  620. VOID
  621. KiFlushForwardProgressTbBufferLocal(
  622. VOID
  623. )
  624. {
  625. ULONG i;
  626. PVOID Va;
  627. volatile ULONGLONG *PointerPte;
  628. //
  629. // Flush the ForwardProgressTb buffer on the current processor
  630. //
  631. for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) {
  632. Va = (PVOID)PCR->ForwardProgressBuffer[i*2];
  633. PointerPte = &PCR->ForwardProgressBuffer[(i*2)+1];
  634. if (*PointerPte != 0) {
  635. *PointerPte = 0;
  636. KiFlushSingleTbLocal(Invalid, Va);
  637. }
  638. }
  639. }
  640. VOID
  641. KeSynchronizeMemoryAccess (
  642. VOID
  643. )
  644. /*++
  645. Routine Description:
  646. This function synchronizes memory access across all processors in the
  647. host configuration.
  648. Arguments:
  649. None.
  650. Return Value:
  651. None.
  652. --*/
  653. {
  654. //
  655. // BUGBUG : This needs to be fleshed out with real code.
  656. //
  657. return;
  658. }
  659. LONG KeTempTimeStamp;
  660. ULONG
  661. KeReadMbTimeStamp (
  662. VOID
  663. )
  664. {
  665. //
  666. // BUGBUG : This needs to be fleshed out with real code.
  667. //
  668. return (ULONG) InterlockedIncrement (&KeTempTimeStamp);
  669. }