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.

684 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1993 Digital Equipment Corporation
  4. Module Name:
  5. flush.c
  6. Abstract:
  7. This module implements Alpha AXP machine dependent kernel functions to flush
  8. the data and instruction caches and to flush I/O buffers.
  9. Author:
  10. David N. Cutler (davec) 26-Apr-1990
  11. Joe Notarangelo 29-Nov-1993
  12. Environment:
  13. Kernel mode only.
  14. Revision History:
  15. --*/
  16. #include "ki.h"
  17. //
  18. // Define forward referenced prototypes.
  19. //
  20. VOID
  21. KiSweepDcacheTarget (
  22. IN PKIPI_CONTEXT SignalDone,
  23. IN PVOID Count,
  24. IN PVOID Parameter2,
  25. IN PVOID Parameter3
  26. );
  27. VOID
  28. KiSweepIcacheTarget (
  29. IN PKIPI_CONTEXT SignalDone,
  30. IN PVOID Count,
  31. IN PVOID Parameter2,
  32. IN PVOID Parameter3
  33. );
  34. VOID
  35. KiFlushIoBuffersTarget (
  36. IN PKIPI_CONTEXT SignalDone,
  37. IN PVOID Mdl,
  38. IN PVOID ReadOperation,
  39. IN PVOID DmaOperation
  40. );
  41. VOID
  42. KiSynchronizeMemoryAccessTarget (
  43. IN PKIPI_CONTEXT SignalDone,
  44. IN PVOID Parameter1,
  45. IN PVOID Parameter2,
  46. IN PVOID Parameter3
  47. );
  48. ULONG KiSynchronizeMemoryCallCount = 0;
  49. VOID
  50. KeSweepDcache (
  51. IN BOOLEAN AllProcessors
  52. )
  53. /*++
  54. Routine Description:
  55. This function flushes the data cache on all processors that are currently
  56. running threads which are children of the current process or flushes the
  57. data cache on all processors in the host configuration.
  58. Arguments:
  59. AllProcessors - Supplies a boolean value that determines which data
  60. caches are flushed.
  61. Return Value:
  62. None.
  63. --*/
  64. {
  65. KIRQL OldIrql;
  66. KAFFINITY TargetProcessors;
  67. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  68. //
  69. // Raise IRQL to synchronization level to prevent a context switch.
  70. //
  71. #if !defined(NT_UP)
  72. OldIrql = KeRaiseIrqlToSynchLevel();
  73. //
  74. // Compute the set of target processors and send the sweep parameters
  75. // to the target processors, if any, for execution.
  76. //
  77. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  78. if (TargetProcessors != 0) {
  79. KiIpiSendPacket(TargetProcessors,
  80. KiSweepDcacheTarget,
  81. NULL,
  82. NULL,
  83. NULL);
  84. }
  85. IPI_INSTRUMENT_COUNT(KeGetCurrentPrcb()->Number, SweepDcache);
  86. #endif
  87. //
  88. // Sweep the data cache on the current processor.
  89. //
  90. HalSweepDcache();
  91. //
  92. // Wait until all target processors have finished sweeping the their
  93. // data cache.
  94. //
  95. #if !defined(NT_UP)
  96. if (TargetProcessors != 0) {
  97. KiIpiStallOnPacketTargets(TargetProcessors);
  98. }
  99. //
  100. // Lower IRQL to its previous level and return.
  101. //
  102. KeLowerIrql(OldIrql);
  103. #endif
  104. return;
  105. }
  106. VOID
  107. KiSweepDcacheTarget (
  108. IN PKIPI_CONTEXT SignalDone,
  109. IN PVOID Parameter1,
  110. IN PVOID Parameter2,
  111. IN PVOID Parameter3
  112. )
  113. /*++
  114. Routine Description:
  115. This is the target function for sweeping the data cache on target
  116. processors.
  117. Arguments:
  118. SignalDone - Supplies a pointer to a variable that is cleared when the
  119. requested operation has been performed
  120. Parameter1 - Parameter3 - not used
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. //
  126. // Sweep the data cache on the current processor and clear the sweep
  127. // data cache packet address to signal the source to continue.
  128. //
  129. #if !defined(NT_UP)
  130. HalSweepDcache();
  131. KiIpiSignalPacketDone(SignalDone);
  132. IPI_INSTRUMENT_COUNT(KeGetCurrentPrcb()->Number, SweepDcache);
  133. #endif
  134. return;
  135. }
  136. VOID
  137. KeSweepIcache (
  138. IN BOOLEAN AllProcessors
  139. )
  140. /*++
  141. Routine Description:
  142. This function flushes the instruction cache on all processors that are
  143. currently running threads which are children of the current process or
  144. flushes the instruction cache on all processors in the host configuration.
  145. Arguments:
  146. AllProcessors - Supplies a boolean value that determines which instruction
  147. caches are flushed.
  148. Return Value:
  149. None.
  150. --*/
  151. {
  152. KIRQL OldIrql;
  153. KAFFINITY TargetProcessors;
  154. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  155. //
  156. // Raise IRQL to synchronization level to prevent a context switch.
  157. //
  158. #if !defined(NT_UP)
  159. OldIrql = KeRaiseIrqlToSynchLevel();
  160. //
  161. // Compute the set of target processors and send the sweep parameters
  162. // to the target processors, if any, for execution.
  163. //
  164. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  165. if (TargetProcessors != 0) {
  166. KiIpiSendPacket(TargetProcessors,
  167. KiSweepIcacheTarget,
  168. NULL,
  169. NULL,
  170. NULL);
  171. }
  172. IPI_INSTRUMENT_COUNT(KeGetCurrentPrcb()->Number, SweepIcache);
  173. #endif
  174. //
  175. // Sweep the instruction cache on the current processor.
  176. //
  177. KiImb();
  178. //
  179. // Wait until all target processors have finished sweeping the their
  180. // instruction cache.
  181. //
  182. #if !defined(NT_UP)
  183. if (TargetProcessors != 0) {
  184. KiIpiStallOnPacketTargets(TargetProcessors);
  185. }
  186. //
  187. // Lower IRQL to its previous level and return.
  188. //
  189. KeLowerIrql(OldIrql);
  190. #endif
  191. return;
  192. }
  193. VOID
  194. KiSweepIcacheTarget (
  195. IN PKIPI_CONTEXT SignalDone,
  196. IN PVOID Parameter1,
  197. IN PVOID Parameter2,
  198. IN PVOID Parameter3
  199. )
  200. /*++
  201. Routine Description:
  202. This is the target function for sweeping the instruction cache on
  203. target processors.
  204. Arguments:
  205. SignalDone - Supplies a pointer to a variable that is cleared when the
  206. requested operation has been performed
  207. Parameter1 - Parameter3 - not used
  208. Return Value:
  209. None.
  210. --*/
  211. {
  212. //
  213. // Sweep the instruction cache on the current processor and clear
  214. // the sweep instruction cache packet address to signal the source
  215. // to continue.
  216. //
  217. #if !defined(NT_UP)
  218. KiImb();
  219. KiIpiSignalPacketDone(SignalDone);
  220. IPI_INSTRUMENT_COUNT(KeGetCurrentPrcb()->Number, SweepIcache);
  221. #endif
  222. return;
  223. }
  224. VOID
  225. KeSweepIcacheRange (
  226. IN BOOLEAN AllProcessors,
  227. IN PVOID BaseAddress,
  228. IN ULONG_PTR Length
  229. )
  230. /*++
  231. Routine Description:
  232. This function flushes the an range of virtual addresses from the primary
  233. instruction cache on all processors that are currently running threads
  234. which are children of the current process or flushes the range of virtual
  235. addresses from the primary instruction cache on all processors in the host
  236. configuration.
  237. Arguments:
  238. AllProcessors - Supplies a boolean value that determines which instruction
  239. caches are flushed.
  240. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  241. Length - Supplies the length of the range that is flushed if the base
  242. address is specified.
  243. Return Value:
  244. None.
  245. --*/
  246. {
  247. KeSweepIcache(AllProcessors);
  248. return;
  249. }
  250. VOID
  251. KeFlushIoBuffers (
  252. IN PMDL Mdl,
  253. IN BOOLEAN ReadOperation,
  254. IN BOOLEAN DmaOperation
  255. )
  256. /*++
  257. Routine Description:
  258. This function flushes the I/O buffer specified by the memory descriptor
  259. list from the data cache on all processors.
  260. Alpha requires that caches be coherent with respect to I/O. All that
  261. this routine needs to do is execute a memory barrier on the current
  262. processor. However, in order to maintain i-stream coherency, all
  263. processors must execute the IMB PAL call in the case of page reads.
  264. Thus, all processors are IPI'd to perform the IMB for any flush
  265. that is a DmaOperation, a ReadOperation, and an MDL_IO_PAGE_READ.
  266. Arguments:
  267. Mdl - Supplies a pointer to a memory descriptor list that describes the
  268. I/O buffer location.
  269. ReadOperation - Supplies a boolean value that determines whether the I/O
  270. operation is a read into memory.
  271. DmaOperation - Supplies a boolean value that determines whether the I/O
  272. operation is a DMA operation.
  273. Return Value:
  274. None.
  275. --*/
  276. {
  277. KIRQL OldIrql;
  278. KAFFINITY TargetProcessors;
  279. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  280. KiMb();
  281. //
  282. // If the operation is a DMA operation, then check if the flush
  283. // can be avoided because the host system supports the right set
  284. // of cache coherency attributes. Otherwise, the flush can also
  285. // be avoided if the operation is a programmed I/O and not a page
  286. // read.
  287. //
  288. if (DmaOperation != FALSE) {
  289. if (ReadOperation != FALSE) {
  290. if ((KiDmaIoCoherency & DMA_READ_ICACHE_INVALIDATE) != 0) {
  291. ASSERT((KiDmaIoCoherency & DMA_READ_DCACHE_INVALIDATE) != 0);
  292. return;
  293. } else if (((Mdl->MdlFlags & MDL_IO_PAGE_READ) == 0) &&
  294. ((KiDmaIoCoherency & DMA_READ_DCACHE_INVALIDATE) != 0)) {
  295. return;
  296. }
  297. } else if ((KiDmaIoCoherency & DMA_WRITE_DCACHE_SNOOP) != 0) {
  298. return;
  299. }
  300. } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) == 0) {
  301. return;
  302. }
  303. //
  304. // Either the operation is a DMA operation and the right coherency
  305. // attributes are not supported by the host system, or the operation
  306. // is programmed I/O and a page read.
  307. //
  308. // Raise IRQL to synchronization level to prevent a context switch.
  309. //
  310. OldIrql = KeRaiseIrqlToSynchLevel();
  311. //
  312. // Compute the set of target processors, and send the flush I/O
  313. // parameters to the target processors, if any, for execution.
  314. //
  315. #if !defined(NT_UP)
  316. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  317. if (TargetProcessors != 0) {
  318. KiIpiSendPacket(TargetProcessors,
  319. KiFlushIoBuffersTarget,
  320. (PVOID)Mdl,
  321. ULongToPtr((ULONG)ReadOperation),
  322. ULongToPtr((ULONG)DmaOperation));
  323. }
  324. #endif
  325. //
  326. // Flush I/O buffer on current processor.
  327. //
  328. HalFlushIoBuffers(Mdl, ReadOperation, DmaOperation);
  329. //
  330. // Wait until all target processors have finished flushing the
  331. // specified I/O buffer.
  332. //
  333. #if !defined(NT_UP)
  334. if (TargetProcessors != 0) {
  335. KiIpiStallOnPacketTargets(TargetProcessors);
  336. }
  337. #endif
  338. //
  339. // Lower IRQL to its previous level and return.
  340. //
  341. KeLowerIrql(OldIrql);
  342. return;
  343. }
  344. #if !defined(NT_UP)
  345. VOID
  346. KiFlushIoBuffersTarget (
  347. IN PKIPI_CONTEXT SignalDone,
  348. IN PVOID Mdl,
  349. IN PVOID ReadOperation,
  350. IN PVOID DmaOperation
  351. )
  352. /*++
  353. Routine Description:
  354. This is the target function for flushing an I/O buffer on target
  355. processors.
  356. Arguments:
  357. SignalDone Supplies a pointer to a variable that is cleared when the
  358. requested operation has been performed.
  359. Mdl - Supplies a pointer to a memory descriptor list that describes the
  360. I/O buffer location.
  361. ReadOperation - Supplies a boolean value that determines whether the I/O
  362. operation is a read into memory.
  363. DmaOperation - Supplies a boolean value that determines whether the I/O
  364. operation is a DMA operation.
  365. Return Value:
  366. None.
  367. --*/
  368. {
  369. //
  370. // Flush the specified I/O buffer on the current processor.
  371. //
  372. HalFlushIoBuffers((PMDL)Mdl,
  373. (BOOLEAN)((ULONG_PTR)ReadOperation),
  374. (BOOLEAN)((ULONG_PTR)DmaOperation));
  375. KiIpiSignalPacketDone(SignalDone);
  376. IPI_INSTRUMENT_COUNT(KeGetCurrentPrcb()->Number, FlushIoBuffers);
  377. return;
  378. }
  379. #endif
  380. VOID
  381. KeSynchronizeMemoryAccess (
  382. VOID
  383. )
  384. /*++
  385. Routine Description:
  386. This function synchronizes memory access across all processors in the
  387. host configurarion.
  388. Arguments:
  389. None.
  390. Return Value:
  391. None.
  392. --*/
  393. {
  394. KIRQL OldIrql;
  395. KAFFINITY TargetProcessors;
  396. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  397. KiSynchronizeMemoryCallCount += 1;
  398. //
  399. // Raise IRQL to synchronization level to prevent a context switch.
  400. //
  401. #if !defined(NT_UP)
  402. OldIrql = KeRaiseIrqlToSynchLevel();
  403. //
  404. // Compute the set of target processors and send the synchronize message
  405. // to the target processors, if any, for execution.
  406. //
  407. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  408. if (TargetProcessors != 0) {
  409. KiIpiSendPacket(TargetProcessors,
  410. KiSynchronizeMemoryAccessTarget,
  411. NULL,
  412. NULL,
  413. NULL);
  414. }
  415. //
  416. // On an MP system an implicit memory barrier is executed during the
  417. // end of the IPI message. On a UP system, a memory barrier must be
  418. // executed.
  419. //
  420. #else
  421. __MB();
  422. #endif
  423. //
  424. // Wait until all target processors have finished sweeping the their
  425. // data cache.
  426. //
  427. #if !defined(NT_UP)
  428. if (TargetProcessors != 0) {
  429. KiIpiStallOnPacketTargets(TargetProcessors);
  430. }
  431. //
  432. // Lower IRQL to its previous level and return.
  433. //
  434. KeLowerIrql(OldIrql);
  435. #endif
  436. return;
  437. }
  438. #if !defined(NT_UP)
  439. VOID
  440. KiSynchronizeMemoryAccessTarget (
  441. IN PKIPI_CONTEXT SignalDone,
  442. IN PVOID Parameter1,
  443. IN PVOID Parameter2,
  444. IN PVOID Parameter3
  445. )
  446. /*++
  447. Routine Description:
  448. This function performs no operation, but an implicit memory barrier
  449. is executed when the IPI message is received.
  450. Arguments:
  451. SignalDone - Supplies a pointer to a variable that is cleared when the
  452. requested operation has been performed
  453. Parameter1 - Parameter3 - not used
  454. Return Value:
  455. None.
  456. --*/
  457. {
  458. KiIpiSignalPacketDone(SignalDone);
  459. return;
  460. }
  461. #endif