Leaked source code of windows server 2003
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.

1017 lines
22 KiB

  1. /*++
  2. Module Name:
  3. flush.c
  4. Abstract:
  5. This module implements IA64 machine dependent kernel functions to flush
  6. the data and instruction caches and to flush I/O buffers.
  7. Author:
  8. 07-Mar-1996
  9. Bernard Lint
  10. M. Jayakumar (Muthurajan.Jayakumar@intel.com)
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. --*/
  15. #include "ki.h"
  16. #include "kxia64.h"
  17. //
  18. // PROBE_VISIBILITY_PAL_SUPPORT flag is one time write (RESET) only and multiple time read
  19. // only flag. It is used to check to see if the processor needs PAL_SUPPORT for VISIBILITY // in prefetches. Once the check is made, this flag optimizes such that further checks are // eliminated.
  20. //
  21. ULONG ProbePalVisibilitySupport=1;
  22. ULONG NeedPalVisibilitySupport=1;
  23. extern KSPIN_LOCK KiCacheFlushLock;
  24. //
  25. // Define forward referenced prototyes.
  26. //
  27. VOID
  28. KiSweepDcacheTarget (
  29. IN PULONG SignalDone,
  30. IN PVOID Parameter1,
  31. IN PVOID Parameter2,
  32. IN PVOID Parameter3
  33. );
  34. VOID
  35. KiSweepIcacheTarget (
  36. IN PULONG SignalDone,
  37. IN PVOID Parameter1,
  38. IN PVOID Parameter2,
  39. IN PVOID Parameter3
  40. );
  41. VOID
  42. KiFlushIoBuffersTarget (
  43. IN PKIPI_CONTEXT SignalDone,
  44. IN PVOID Mdl,
  45. IN PVOID ReadOperation,
  46. IN PVOID DmaOperation
  47. );
  48. VOID
  49. KiSyncCacheTarget(
  50. IN PKIPI_CONTEXT SignalDone,
  51. IN PVOID Parameter1,
  52. IN PVOID Parameter2,
  53. IN PVOID Parameter3
  54. );
  55. ULONG_PTR
  56. KiSyncMC_DrainTarget(
  57. );
  58. ULONG_PTR
  59. KiSyncMC_Drain(
  60. IN BOOLEAN AllProcessors,
  61. IN PVOID BaseAddress,
  62. IN ULONG Length
  63. );
  64. ULONG_PTR
  65. KiSyncPrefetchVisibleTarget(
  66. );
  67. ULONG_PTR
  68. KiSyncPrefetchVisible (
  69. IN BOOLEAN AllProcessors,
  70. IN PVOID BaseAddress,
  71. IN ULONG Length
  72. );
  73. VOID
  74. KiSyncCacheTarget (
  75. IN PKIPI_CONTEXT SignalDone,
  76. IN PVOID Parameter1,
  77. IN PVOID Parameter2,
  78. IN PVOID Parameter3
  79. )
  80. /*++
  81. Routine Description:
  82. This function synchronizes the I-fetch pipeline. Typically this routine will be
  83. executed by every processor in the system in response to an IPI after the cache
  84. is flushed. Each processor executing RFI while leaving the IPI produces the
  85. serialization effect that is required after isync to make sure that further
  86. instruction prefetches wait till the ISYNC completes.
  87. Arguements:
  88. SignalDone Supplies a pointer to a variable that is cleared when the
  89. requested operation has been performed.
  90. Parameter1 - Parameter3 - Not used.
  91. Return Value:
  92. Nothing.
  93. --*/
  94. {
  95. UNREFERENCED_PARAMETER (Parameter1);
  96. UNREFERENCED_PARAMETER (Parameter2);
  97. UNREFERENCED_PARAMETER (Parameter3);
  98. #if !defined(NT_UP)
  99. __synci();
  100. KiIpiSignalPacketDone(SignalDone);
  101. #else
  102. UNREFERENCED_PARAMETER (SignalDone);
  103. #endif
  104. return;
  105. }
  106. VOID
  107. KeSweepIcache (
  108. IN BOOLEAN AllProcessors
  109. )
  110. /*++
  111. Routine Description:
  112. This function flushes the instruction cache on all processors that are
  113. currently running threads which are children of the current process or
  114. flushes the instruction cache on all processors in the host configuration.
  115. N.B. Although PowerPC maintains cache coherency across processors, we
  116. use the flash invalidate function (h/w) for I-Cache sweeps which doesn't
  117. maintain coherency so we still do the MP I-Cache flush in s/w. plj.
  118. Arguments:
  119. AllProcessors - Supplies a boolean value that determines which instruction
  120. caches are flushed.
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. #if !defined(NT_UP)
  126. KIRQL OldIrql;
  127. KAFFINITY TargetProcessors;
  128. #endif
  129. UNREFERENCED_PARAMETER (AllProcessors);
  130. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  131. #if !defined(NT_UP)
  132. //
  133. // Acquire cache flush spinlock
  134. // Cache flush is not MP safe yet
  135. //
  136. KeAcquireSpinLock(&KiCacheFlushLock, &OldIrql);
  137. #endif
  138. HalSweepIcache();
  139. #if !defined(NT_UP)
  140. //
  141. // Compute the set of target processors and send the sweep parameters
  142. // to the target processors, if any, for execution.
  143. //
  144. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  145. if (TargetProcessors != 0) {
  146. KiIpiSendPacket(TargetProcessors,
  147. KiSweepIcacheTarget,
  148. NULL,
  149. NULL,
  150. NULL);
  151. }
  152. //
  153. // Wait until all target processors have finished sweeping their
  154. // instruction caches.
  155. //
  156. if (TargetProcessors != 0) {
  157. KiIpiStallOnPacketTargets(TargetProcessors);
  158. }
  159. //
  160. // Lower IRQL to its previous level and return.
  161. //
  162. KeReleaseSpinLock(&KiCacheFlushLock, OldIrql);
  163. #endif
  164. return;
  165. }
  166. #undef KeSweepCurrentIcache
  167. VOID
  168. KeSweepCurrentIcache(
  169. )
  170. /*++
  171. Routine Description:
  172. This function makes the instruction cache coherent with the data
  173. cache. It is generally called by the debugger.
  174. Arguments:
  175. None.
  176. Return Value:
  177. None.
  178. Note:
  179. This routine only works correct if it is called on the same processor
  180. that made the modification to the instruction memeory
  181. This routine can be called at high IRQL.
  182. --*/
  183. {
  184. HalSweepIcache();
  185. }
  186. VOID
  187. KiSweepIcacheTarget (
  188. IN PULONG SignalDone,
  189. IN PVOID Parameter1,
  190. IN PVOID Parameter2,
  191. IN PVOID Parameter3
  192. )
  193. /*++
  194. Routine Description:
  195. This is the target function for sweeping the instruction cache on
  196. target processors.
  197. Arguments:
  198. SignalDone Supplies a pointer to a variable that is cleared when the
  199. requested operation has been performed.
  200. Parameter1 - Parameter3 - Not used.
  201. Return Value:
  202. None.
  203. --*/
  204. {
  205. UNREFERENCED_PARAMETER (Parameter1);
  206. UNREFERENCED_PARAMETER (Parameter2);
  207. UNREFERENCED_PARAMETER (Parameter3);
  208. //
  209. // Sweep the instruction cache on the current processor and clear
  210. // the sweep instruction cache packet address to signal the source
  211. // to continue.
  212. //
  213. #if !defined(NT_UP)
  214. HalSweepIcache();
  215. KiIpiSignalPacketDone(SignalDone);
  216. #else
  217. UNREFERENCED_PARAMETER (SignalDone);
  218. #endif
  219. return;
  220. }
  221. VOID
  222. KeSweepDcache (
  223. IN BOOLEAN AllProcessors
  224. )
  225. /*++
  226. Routine Description:
  227. This function flushes the data cache on all processors that are currently
  228. running threads which are children of the current process or flushes the
  229. data cache on all processors in the host configuration.
  230. N.B. PowerPC maintains cache coherency across processors however
  231. in this routine, the range of addresses being flushed is unknown
  232. so we must still broadcast the request to the other processors.
  233. Arguments:
  234. AllProcessors - Supplies a boolean value that determines which data
  235. caches are flushed.
  236. Return Value:
  237. None.
  238. --*/
  239. {
  240. #if !defined(NT_UP)
  241. KIRQL OldIrql;
  242. KAFFINITY TargetProcessors;
  243. #endif
  244. UNREFERENCED_PARAMETER (AllProcessors);
  245. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  246. #if !defined(NT_UP)
  247. //
  248. // Acquire cache flush spinlock
  249. // Cache flush is not MP safe yet
  250. //
  251. KeAcquireSpinLock(&KiCacheFlushLock, &OldIrql);
  252. #endif
  253. HalSweepDcache();
  254. #if !defined(NT_UP)
  255. //
  256. // Compute the set of target processors and send the sweep parameters
  257. // to the target processors, if any, for execution.
  258. //
  259. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  260. if (TargetProcessors != 0) {
  261. KiIpiSendPacket(TargetProcessors,
  262. KiSweepDcacheTarget,
  263. NULL,
  264. NULL,
  265. NULL);
  266. }
  267. //
  268. // Wait until all target processors have finished sweeping their
  269. // data caches.
  270. //
  271. if (TargetProcessors != 0) {
  272. KiIpiStallOnPacketTargets(TargetProcessors);
  273. }
  274. //
  275. // Lower IRQL to its previous level and return.
  276. //
  277. KeReleaseSpinLock(&KiCacheFlushLock, OldIrql);
  278. #endif
  279. return;
  280. }
  281. VOID
  282. KiSweepDcacheTarget (
  283. IN PULONG SignalDone,
  284. IN PVOID Parameter1,
  285. IN PVOID Parameter2,
  286. IN PVOID Parameter3
  287. )
  288. /*++
  289. Routine Description:
  290. This is the target function for sweeping the data cache on target
  291. processors.
  292. Arguments:
  293. SignalDone Supplies a pointer to a variable that is cleared when the
  294. requested operation has been performed.
  295. Parameter1 - Parameter3 - Not used.
  296. Return Value:
  297. None.
  298. --*/
  299. {
  300. UNREFERENCED_PARAMETER (Parameter1);
  301. UNREFERENCED_PARAMETER (Parameter2);
  302. UNREFERENCED_PARAMETER (Parameter3);
  303. //
  304. // Sweep the data cache on the current processor and clear the sweep
  305. // data cache packet address to signal the source to continue.
  306. //
  307. #if !defined(NT_UP)
  308. HalSweepDcache();
  309. KiIpiSignalPacketDone(SignalDone);
  310. #else
  311. UNREFERENCED_PARAMETER (SignalDone);
  312. #endif
  313. return;
  314. }
  315. ULONG_PTR
  316. KiSyncMC_DrainTarget(
  317. )
  318. /*++
  319. Routine Description:
  320. This is the target function for issuing PAL_MC_DRAIN to drain
  321. prefetches, demand references and pending fc cache line evictions on the
  322. target CPU it executes.
  323. Argument:
  324. None
  325. Return Value:
  326. Returns the status from the function HalCallPal
  327. --*/
  328. {
  329. ULONG_PTR Status;
  330. //
  331. // Call HalCallPal to drain.
  332. //
  333. Status = HalCallPal(PAL_MC_DRAIN,
  334. 0,
  335. 0,
  336. 0,
  337. 0,
  338. 0,
  339. 0,
  340. 0);
  341. ASSERT(Status == PAL_STATUS_SUCCESS);
  342. return Status;
  343. }
  344. VOID
  345. KeSweepCacheRange (
  346. IN BOOLEAN AllProcessors,
  347. IN PVOID BaseAddress,
  348. IN ULONG Length
  349. )
  350. /*++
  351. Routine Description:
  352. This function is used to flush a range of virtual addresses from both the
  353. instruction and data cache on all processors in the system.
  354. Irrespective of the length of the range, it should not call SweepIcache
  355. or SweepDcache. This is because SweepDcache will only sweep D cache and
  356. not the I cache and Vice versa. Since the caller of KeSweepCacheRange assumes
  357. both the caches are being swept, one cannot call SweepIcache or SweepDcache
  358. in trying to optimize.
  359. Arguments:
  360. AllProcessors - Not used
  361. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  362. Length - Supplies the length of the range that is flushed if the base
  363. address is specified.
  364. Return Value:
  365. None.
  366. --*/
  367. {
  368. UNREFERENCED_PARAMETER (AllProcessors);
  369. //
  370. // We will not raise IRQL to synchronization level so that we can allow
  371. // a context switch in between Flush Cache. FC need not run in the same processor
  372. // throughout. It can be context switched. So no binding is done to any processor.
  373. //
  374. //
  375. HalSweepCacheRange(BaseAddress,Length);
  376. //
  377. // Synchronize the Instruction Prefetch pipe in the local processor.
  378. //
  379. __synci();
  380. __isrlz();
  381. //
  382. // Wait until all target processors have finished sweeping the their
  383. // data cache.
  384. //
  385. return;
  386. }
  387. VOID
  388. KeSweepIcacheRange (
  389. IN BOOLEAN AllProcessors,
  390. IN PVOID BaseAddress,
  391. IN SIZE_T Length
  392. )
  393. /*++
  394. Routine Description:
  395. This function is used to flush a range of virtual addresses from the
  396. primary instruction cache on all processors in the host configuration.
  397. If the length of the range is greater than the size of the
  398. instruction cache, then one can call HalSweepIcache which calls
  399. SAL to flush the entire cache. Since SAL does not take care of MP
  400. flushing, HalSweepIcache has to use IPI mechanism to execute SAL
  401. flush from each processor. We need to weight the overhead of all these
  402. versus using HalSweepIcacheRange and avoiding IPI mechanism since
  403. HalSweepIcacheRange uses fc instruction and fc instruction takes care of MP.
  404. Arguments:
  405. AllProcessors - Not used
  406. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  407. Length - Supplies the length of the range that is flushed if the base
  408. address is specified.
  409. Return Value:
  410. None.
  411. Note: For performance reason, we may update KeSweepIcacheRange to do the following:
  412. if the range asked to sweep is very large, we may call KeSweepIcache to flush
  413. the full cache.
  414. --*/
  415. {
  416. UNREFERENCED_PARAMETER (AllProcessors);
  417. //
  418. // We will not raise IRQL to synchronization level so that we can allow
  419. // a context switch in between Flush Cache. FC need not run in the same processor
  420. // throughout. It can be context switched. So no binding is done to any processor.
  421. //
  422. //
  423. HalSweepIcacheRange(BaseAddress,Length);
  424. //
  425. // Synchronize the Instruction Prefetch pipe in the local processor.
  426. //
  427. __synci();
  428. __isrlz();
  429. return;
  430. }
  431. VOID
  432. KeSweepCurrentIcacheRange (
  433. IN PVOID BaseAddress,
  434. IN SIZE_T Length
  435. )
  436. /*++
  437. Routine Description:
  438. This function is used to flush a range of virtual addresses from the
  439. primary instruction cache on the current processor.
  440. This is used by the kernel debugger for flushing the i-cache after
  441. modifying memory in case the instruction stream is changed.
  442. To avoid calling SAL during phase 0 we use "fc" instead of the SAL cache
  443. flush call.
  444. Arguments:
  445. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  446. Length - Supplies the length of the range that is flushed if the base
  447. address is specified.
  448. Return Value:
  449. None.
  450. --*/
  451. {
  452. KIRQL OldIrql;
  453. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  454. HalSweepIcacheRange(BaseAddress,Length);
  455. //
  456. // Synchronize the Instruction Prefetch pipe in the local processor.
  457. //
  458. __synci();
  459. __isrlz();
  460. KeLowerIrql(OldIrql);
  461. return;
  462. }
  463. VOID
  464. KeSweepDcacheRange (
  465. IN BOOLEAN AllProcessors,
  466. IN PVOID BaseAddress,
  467. IN ULONG Length
  468. )
  469. /*++
  470. Routine Description:
  471. This function is used to flush a range of virtual addresses from the
  472. primary data cache on all processors in the host configuration.
  473. If the length of the range is greater than the size of the
  474. data cache, then one can call HalSweepDcache which calls
  475. SAL to flush the entire cache. Since SAL does not take care of MP
  476. flushing, HalSweepDcache has to use IPI mechanism to execute SAL
  477. flush from each processor. We need to weight the overhead of all these
  478. versus using HalSweepDcacheRange and avoiding IPI mechanism since
  479. HalSweepDcacheRange uses fc instruction and fc instruction takes care of MP.
  480. Arguments:
  481. AllProcessors - Not used
  482. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  483. Length - Supplies the length of the range that is flushed if the base
  484. address is specified.
  485. Return Value:
  486. None.
  487. Note: For performance reason, we may update KeSweepDcacheRange to do the following:
  488. if the range asked to sweep is very large, we may call KeSweepDcache to flush
  489. the full cache.
  490. --*/
  491. {
  492. UNREFERENCED_PARAMETER (AllProcessors);
  493. //
  494. // We will not raise IRQL to synchronization level so that we can allow
  495. // a context switch in between Flush Cache. FC need not run in the same processor
  496. // throughout. It can be context switched. So no binding is done to any processor.
  497. //
  498. //
  499. HalSweepDcacheRange(BaseAddress,Length);
  500. //
  501. // Synchronize the Instruction Prefetch pipe in the local processor.
  502. //
  503. __synci();
  504. __isrlz();
  505. return;
  506. }
  507. ULONG_PTR
  508. KiSyncMC_Drain (
  509. IN BOOLEAN AllProcessors,
  510. IN PVOID BaseAddress,
  511. IN ULONG Length
  512. )
  513. /*++
  514. Routine Description:
  515. KiSyncMC_Drain issues PAL_MC_DRAIN to drain either prefetches, demand references
  516. or pending fc cache line evictions to all the processors in the system.
  517. DrainTypePointer points to the variable, DrainType, which determines the type of
  518. drain to be performed. This is typically used when changing the memory attribute
  519. from WB to UC.
  520. Arguments:
  521. AllProcessors - All processors in the system.
  522. BaseAddress - Supplies a pointer to the base of the range that is to be drained.
  523. Length - Supplies the length of the range that is drained for the base
  524. address specified.
  525. Return Value:
  526. Note: This is used when changing attributes of WB pages to UC pages.
  527. --*/
  528. {
  529. ULONG_PTR Status;
  530. UNREFERENCED_PARAMETER (AllProcessors);
  531. UNREFERENCED_PARAMETER (BaseAddress);
  532. UNREFERENCED_PARAMETER (Length);
  533. //
  534. // KeIpiGenericCall returns ULONG_PTR as the function value of the specified function
  535. //
  536. Status = (KeIpiGenericCall (
  537. (PKIPI_BROADCAST_WORKER)KiSyncMC_DrainTarget,
  538. (ULONG_PTR)NULL)
  539. );
  540. ASSERT(Status == PAL_STATUS_SUCCESS);
  541. return Status;
  542. }
  543. ULONG_PTR
  544. KiSyncPrefetchVisibleTarget(
  545. )
  546. /*++
  547. Routine Description:
  548. This is the target function for issuing PAL_PREFETCH VISIBILITY
  549. on the target CPU it executes.
  550. Argument:
  551. Not used.
  552. Return Value:
  553. Returns the status from the function HalCallPal
  554. --*/
  555. {
  556. ULONG_PTR Status;
  557. //
  558. // Call HalCallPal to drain.
  559. //
  560. Status = HalCallPal(PAL_PREFETCH_VISIBILITY,
  561. 0,
  562. 0,
  563. 0,
  564. 0,
  565. 0,
  566. 0,
  567. 0);
  568. ASSERT(Status != PAL_STATUS_ERROR);
  569. return Status;
  570. }
  571. ULONG_PTR
  572. KiSyncPrefetchVisible (
  573. IN BOOLEAN AllProcessors,
  574. IN PVOID BaseAddress,
  575. IN ULONG Length
  576. )
  577. /*++
  578. Routine Description:
  579. KiSyncPrefetchVisible issues PAL_PREFETCH_VISIBILITY to cause the processor to make
  580. all pending prefetches visible to subsequent fc instructions; or does nothing, on
  581. processor implementations which does not require PAL support for disabling prefetch
  582. in the architectural sequence. On processors that require PAL support for this
  583. sequence, the actions performed by this procedure may include any or all
  584. of the following (or none, as long as the processor guarantees that
  585. prefetches that were issued prior to this call are not resident in the
  586. processor's caches after the architected sequence is complete.
  587. This is typically used when changing the memory attribute from WB to UC.
  588. Arguments:
  589. AllProcessors - All processors in the system.
  590. BaseAddress - Supplies a pointer to the base of the range that is to be drained.
  591. Length - Supplies the length of the range that is drained for the base
  592. address specified.
  593. Return Value:
  594. Status of the PAL CALL
  595. 0 Success
  596. 1 Call not needed
  597. -3 Error returned
  598. Note: This is used when changing attributes of WB pages to UC pages.
  599. --*/
  600. {
  601. ULONG_PTR Status;
  602. UNREFERENCED_PARAMETER (AllProcessors);
  603. UNREFERENCED_PARAMETER (BaseAddress);
  604. UNREFERENCED_PARAMETER (Length);
  605. switch (ProbePalVisibilitySupport) {
  606. case 0:
  607. if (NeedPalVisibilitySupport == 0)
  608. Status = PAL_STATUS_SUPPORT_NOT_NEEDED;
  609. else {
  610. Status = (KeIpiGenericCall (
  611. (PKIPI_BROADCAST_WORKER)KiSyncPrefetchVisibleTarget,
  612. (ULONG_PTR)NULL)
  613. );
  614. }
  615. break;
  616. case 1:
  617. Status = KiSyncPrefetchVisibleTarget();
  618. ASSERT(Status != PAL_STATUS_ERROR);
  619. ProbePalVisibilitySupport = 0;
  620. if (Status == PAL_STATUS_SUPPORT_NOT_NEEDED) {
  621. NeedPalVisibilitySupport = 0;
  622. Status = PAL_STATUS_SUPPORT_NOT_NEEDED;
  623. } else {
  624. Status = (KeIpiGenericCall (
  625. (PKIPI_BROADCAST_WORKER)KiSyncPrefetchVisibleTarget,
  626. (ULONG_PTR)NULL)
  627. );
  628. }
  629. break;
  630. default:
  631. Status = (ULONG_PTR) PAL_STATUS_ERROR;
  632. break;
  633. }
  634. ASSERT(Status != PAL_STATUS_ERROR);
  635. return Status;
  636. }
  637. VOID
  638. KeSweepCacheRangeWithDrain (
  639. IN BOOLEAN AllProcessors,
  640. IN PVOID BaseAddress,
  641. IN ULONG Length
  642. )
  643. /*++
  644. Routine Description:
  645. This function is used to drain prefetches,demand references followed by flushing
  646. the cache followed by draining pending fc cache line evictions to a specified range
  647. address in all processors in the system.
  648. Arguments:
  649. AllProcessors - All processors in the system.
  650. BaseAddress - Supplies a pointer to the base of the range that is flushed and drained.
  651. Length - Supplies the length of the range that is flushed and drained for the base
  652. address is specified.
  653. Return Value:
  654. None.
  655. Note: This is used when changing attributes of WB pages to UC pages.
  656. --*/
  657. {
  658. ULONG_PTR Status;
  659. Status = KiSyncPrefetchVisible(
  660. AllProcessors,
  661. BaseAddress,
  662. Length
  663. );
  664. ASSERT(Status != PAL_STATUS_ERROR);
  665. KeSweepCacheRange (
  666. AllProcessors,
  667. BaseAddress,
  668. Length
  669. );
  670. Status = KiSyncMC_Drain (
  671. AllProcessors,
  672. BaseAddress,
  673. Length
  674. );
  675. ASSERT(Status == PAL_STATUS_SUCCESS);
  676. return;
  677. }