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.

1082 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. #if !defined(NT_UP)
  96. __synci();
  97. KiIpiSignalPacketDone(SignalDone);
  98. #endif
  99. return;
  100. }
  101. VOID
  102. KeSweepIcache (
  103. IN BOOLEAN AllProcessors
  104. )
  105. /*++
  106. Routine Description:
  107. This function flushes the instruction cache on all processors that are
  108. currently running threads which are children of the current process or
  109. flushes the instruction cache on all processors in the host configuration.
  110. N.B. Although PowerPC maintains cache coherency across processors, we
  111. use the flash invalidate function (h/w) for I-Cache sweeps which doesn't
  112. maintain coherency so we still do the MP I-Cache flush in s/w. plj.
  113. Arguments:
  114. AllProcessors - Supplies a boolean value that determines which instruction
  115. caches are flushed.
  116. Return Value:
  117. None.
  118. --*/
  119. {
  120. KIRQL OldIrql;
  121. KAFFINITY TargetProcessors;
  122. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  123. #if !defined(NT_UP)
  124. //
  125. // Acquire cache flush spinlock
  126. // Cache flush is not MP safe yet
  127. //
  128. KeAcquireSpinLock(&KiCacheFlushLock, &OldIrql);
  129. #endif
  130. HalSweepIcache();
  131. #if !defined(NT_UP)
  132. //
  133. // Compute the set of target processors and send the sweep parameters
  134. // to the target processors, if any, for execution.
  135. //
  136. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  137. if (TargetProcessors != 0) {
  138. KiIpiSendPacket(TargetProcessors,
  139. KiSweepIcacheTarget,
  140. NULL,
  141. NULL,
  142. NULL);
  143. }
  144. //
  145. // Wait until all target processors have finished sweeping their
  146. // instruction caches.
  147. //
  148. if (TargetProcessors != 0) {
  149. KiIpiStallOnPacketTargets(TargetProcessors);
  150. }
  151. //
  152. // Lower IRQL to its previous level and return.
  153. //
  154. KeReleaseSpinLock(&KiCacheFlushLock, OldIrql);
  155. #endif
  156. return;
  157. }
  158. VOID
  159. KiSweepIcacheTarget (
  160. IN PULONG SignalDone,
  161. IN PVOID Parameter1,
  162. IN PVOID Parameter2,
  163. IN PVOID Parameter3
  164. )
  165. /*++
  166. Routine Description:
  167. This is the target function for sweeping the instruction cache on
  168. target processors.
  169. Arguments:
  170. SignalDone Supplies a pointer to a variable that is cleared when the
  171. requested operation has been performed.
  172. Parameter1 - Parameter3 - Not used.
  173. Return Value:
  174. None.
  175. --*/
  176. {
  177. //
  178. // Sweep the instruction cache on the current processor and clear
  179. // the sweep instruction cache packet address to signal the source
  180. // to continue.
  181. //
  182. #if !defined(NT_UP)
  183. HalSweepIcache();
  184. KiIpiSignalPacketDone(SignalDone);
  185. #endif
  186. return;
  187. }
  188. VOID
  189. KeSweepDcache (
  190. IN BOOLEAN AllProcessors
  191. )
  192. /*++
  193. Routine Description:
  194. This function flushes the data cache on all processors that are currently
  195. running threads which are children of the current process or flushes the
  196. data cache on all processors in the host configuration.
  197. N.B. PowerPC maintains cache coherency across processors however
  198. in this routine, the range of addresses being flushed is unknown
  199. so we must still broadcast the request to the other processors.
  200. Arguments:
  201. AllProcessors - Supplies a boolean value that determines which data
  202. caches are flushed.
  203. Return Value:
  204. None.
  205. --*/
  206. {
  207. KIRQL OldIrql;
  208. KAFFINITY TargetProcessors;
  209. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  210. #if !defined(NT_UP)
  211. //
  212. // Acquire cache flush spinlock
  213. // Cache flush is not MP safe yet
  214. //
  215. KeAcquireSpinLock(&KiCacheFlushLock, &OldIrql);
  216. #endif
  217. HalSweepDcache();
  218. #if !defined(NT_UP)
  219. //
  220. // Compute the set of target processors and send the sweep parameters
  221. // to the target processors, if any, for execution.
  222. //
  223. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  224. if (TargetProcessors != 0) {
  225. KiIpiSendPacket(TargetProcessors,
  226. KiSweepDcacheTarget,
  227. NULL,
  228. NULL,
  229. NULL);
  230. }
  231. //
  232. // Wait until all target processors have finished sweeping their
  233. // data caches.
  234. //
  235. if (TargetProcessors != 0) {
  236. KiIpiStallOnPacketTargets(TargetProcessors);
  237. }
  238. //
  239. // Lower IRQL to its previous level and return.
  240. //
  241. KeReleaseSpinLock(&KiCacheFlushLock, OldIrql);
  242. #endif
  243. return;
  244. }
  245. VOID
  246. KiSweepDcacheTarget (
  247. IN PULONG SignalDone,
  248. IN PVOID Parameter1,
  249. IN PVOID Parameter2,
  250. IN PVOID Parameter3
  251. )
  252. /*++
  253. Routine Description:
  254. This is the target function for sweeping the data cache on target
  255. processors.
  256. Arguments:
  257. SignalDone Supplies a pointer to a variable that is cleared when the
  258. requested operation has been performed.
  259. Parameter1 - Parameter3 - Not used.
  260. Return Value:
  261. None.
  262. --*/
  263. {
  264. //
  265. // Sweep the data cache on the current processor and clear the sweep
  266. // data cache packet address to signal the source to continue.
  267. //
  268. #if !defined(NT_UP)
  269. HalSweepDcache();
  270. KiIpiSignalPacketDone(SignalDone);
  271. #endif
  272. return;
  273. }
  274. ULONG_PTR
  275. KiSyncMC_DrainTarget(
  276. )
  277. /*++
  278. Routine Description:
  279. This is the target function for issuing PAL_MC_DRAIN to drain
  280. prefetches, demand references and pending fc cache line evictions on the
  281. target CPU it executes.
  282. Argument:
  283. None
  284. Return Value:
  285. Returns the status from the function HalCallPal
  286. --*/
  287. {
  288. ULONG_PTR Status;
  289. //
  290. // Call HalCallPal to drain.
  291. //
  292. Status = HalCallPal(PAL_MC_DRAIN,
  293. 0,
  294. 0,
  295. 0,
  296. 0,
  297. 0,
  298. 0,
  299. 0);
  300. ASSERT(Status == PAL_STATUS_SUCCESS);
  301. return Status;
  302. }
  303. VOID
  304. KeSweepCacheRange (
  305. IN BOOLEAN AllProcessors,
  306. IN PVOID BaseAddress,
  307. IN ULONG Length
  308. )
  309. /*++
  310. Routine Description:
  311. This function is used to flush a range of virtual addresses from both the
  312. instruction and data cache on all processors in the system.
  313. Irrespective of the length of the range, it should not call SweepIcache
  314. or SweepDcache. This is because SweepDcache will only sweep D cache and
  315. not the I cache and Vice versa. Since the caller of KeSweepCacheRange assumes
  316. both the caches are being swept, one cannot call SweepIcache or SweepDcache
  317. in trying to optimize.
  318. Arguments:
  319. AllProcessors - Not used
  320. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  321. Length - Supplies the length of the range that is flushed if the base
  322. address is specified.
  323. Return Value:
  324. None.
  325. --*/
  326. {
  327. KIRQL OldIrql;
  328. KAFFINITY TargetProcessors;
  329. //
  330. // We will not raise IRQL to synchronization level so that we can allow
  331. // a context switch in between Flush Cache. FC need not run in the same processor
  332. // throughout. It can be context switched. So no binding is done to any processor.
  333. //
  334. //
  335. HalSweepCacheRange(BaseAddress,Length);
  336. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  337. //
  338. // Raise IRQL to synchronization level to prevent a context switch.
  339. //
  340. #if !defined(NT_UP)
  341. OldIrql = KeRaiseIrqlToSynchLevel();
  342. //
  343. // Compute the set of target processors and send the sync parameters
  344. // to the target processors, if any, for execution.
  345. //
  346. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  347. if (TargetProcessors != 0) {
  348. KiIpiSendPacket(TargetProcessors,
  349. KiSyncCacheTarget,
  350. NULL,
  351. NULL,
  352. NULL);
  353. }
  354. #endif
  355. //
  356. // Synchronize the Instruction Prefetch pipe in the local processor.
  357. //
  358. __synci();
  359. __isrlz();
  360. //
  361. // Wait until all target processors have finished sweeping the their
  362. // data cache.
  363. //
  364. #if !defined(NT_UP)
  365. if (TargetProcessors != 0) {
  366. KiIpiStallOnPacketTargets(TargetProcessors);
  367. }
  368. //
  369. // Lower IRQL to its previous level and return.
  370. //
  371. KeLowerIrql(OldIrql);
  372. #endif
  373. return;
  374. }
  375. VOID
  376. KeSweepIcacheRange (
  377. IN BOOLEAN AllProcessors,
  378. IN PVOID BaseAddress,
  379. IN SIZE_T Length
  380. )
  381. /*++
  382. Routine Description:
  383. This function is used to flush a range of virtual addresses from the
  384. primary instruction cache on all processors in the host configuration.
  385. If the length of the range is greater than the size of the
  386. instruction cache, then one can call HalSweepIcache which calls
  387. SAL to flush the entire cache. Since SAL does not take care of MP
  388. flushing, HalSweepIcache has to use IPI mechanism to execute SAL
  389. flush from each processor. We need to weight the overhead of all these
  390. versus using HalSweepIcacheRange and avoiding IPI mechanism since
  391. HalSweepIcacheRange uses fc instruction and fc instruction takes care of MP.
  392. Arguments:
  393. AllProcessors - Not used
  394. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  395. Length - Supplies the length of the range that is flushed if the base
  396. address is specified.
  397. Return Value:
  398. None.
  399. Note: For performance reason, we may update KeSweepIcacheRange to do the following:
  400. if the range asked to sweep is very large, we may call KeSweepIcache to flush
  401. the full cache.
  402. --*/
  403. {
  404. KIRQL OldIrql;
  405. KAFFINITY TargetProcessors;
  406. //
  407. // We will not raise IRQL to synchronization level so that we can allow
  408. // a context switch in between Flush Cache. FC need not run in the same processor
  409. // throughout. It can be context switched. So no binding is done to any processor.
  410. //
  411. //
  412. HalSweepIcacheRange(BaseAddress,Length);
  413. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  414. //
  415. // Raise IRQL to synchronization level to prevent a context switch.
  416. //
  417. #if !defined(NT_UP)
  418. OldIrql = KeRaiseIrqlToSynchLevel();
  419. //
  420. // Compute the set of target processors and send the sync parameters
  421. // to the target processors, if any, for execution.
  422. //
  423. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  424. if (TargetProcessors != 0) {
  425. KiIpiSendPacket(TargetProcessors,
  426. KiSyncCacheTarget,
  427. NULL,
  428. NULL,
  429. NULL);
  430. }
  431. #endif
  432. //
  433. // Synchronize the Instruction Prefetch pipe in the local processor.
  434. //
  435. __synci();
  436. __isrlz();
  437. //
  438. // Wait until all target processors have finished sweeping the their
  439. // data cache.
  440. //
  441. #if !defined(NT_UP)
  442. if (TargetProcessors != 0) {
  443. KiIpiStallOnPacketTargets(TargetProcessors);
  444. }
  445. //
  446. // Lower IRQL to its previous level and return.
  447. //
  448. KeLowerIrql(OldIrql);
  449. #endif
  450. return;
  451. }
  452. VOID
  453. KeSweepCurrentIcacheRange (
  454. IN PVOID BaseAddress,
  455. IN SIZE_T Length
  456. )
  457. /*++
  458. Routine Description:
  459. This function is used to flush a range of virtual addresses from the
  460. primary instruction cache on the current processor.
  461. This is used by the kernel debugger for flushing the i-cache after
  462. modifying memory in case the instruction stream is changed.
  463. To avoid calling SAL during phase 0 we use "fc" instead of the SAL cache
  464. flush call.
  465. Arguments:
  466. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  467. Length - Supplies the length of the range that is flushed if the base
  468. address is specified.
  469. Return Value:
  470. None.
  471. --*/
  472. {
  473. KIRQL OldIrql;
  474. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  475. HalSweepIcacheRange(BaseAddress,Length);
  476. //
  477. // Synchronize the Instruction Prefetch pipe in the local processor.
  478. //
  479. __synci();
  480. __isrlz();
  481. KeLowerIrql(OldIrql);
  482. return;
  483. }
  484. VOID
  485. KeSweepDcacheRange (
  486. IN BOOLEAN AllProcessors,
  487. IN PVOID BaseAddress,
  488. IN ULONG Length
  489. )
  490. /*++
  491. Routine Description:
  492. This function is used to flush a range of virtual addresses from the
  493. primary data cache on all processors in the host configuration.
  494. If the length of the range is greater than the size of the
  495. data cache, then one can call HalSweepDcache which calls
  496. SAL to flush the entire cache. Since SAL does not take care of MP
  497. flushing, HalSweepDcache has to use IPI mechanism to execute SAL
  498. flush from each processor. We need to weight the overhead of all these
  499. versus using HalSweepDcacheRange and avoiding IPI mechanism since
  500. HalSweepDcacheRange uses fc instruction and fc instruction takes care of MP.
  501. Arguments:
  502. AllProcessors - Not used
  503. BaseAddress - Supplies a pointer to the base of the range that is flushed.
  504. Length - Supplies the length of the range that is flushed if the base
  505. address is specified.
  506. Return Value:
  507. None.
  508. Note: For performance reason, we may update KeSweepDcacheRange to do the following:
  509. if the range asked to sweep is very large, we may call KeSweepDcache to flush
  510. the full cache.
  511. --*/
  512. {
  513. KIRQL OldIrql;
  514. KAFFINITY TargetProcessors;
  515. //
  516. // We will not raise IRQL to synchronization level so that we can allow
  517. // a context switch in between Flush Cache. FC need not run in the same processor
  518. // throughout. It can be context switched. So no binding is done to any processor.
  519. //
  520. //
  521. HalSweepDcacheRange(BaseAddress,Length);
  522. ASSERT(KeGetCurrentIrql() <= KiSynchIrql);
  523. //
  524. // Raise IRQL to synchronization level to prevent a context switch.
  525. //
  526. #if !defined(NT_UP)
  527. OldIrql = KeRaiseIrqlToSynchLevel();
  528. //
  529. // Compute the set of target processors and send the sync parameters
  530. // to the target processors, if any, for execution.
  531. //
  532. TargetProcessors = KeActiveProcessors & PCR->NotMember;
  533. if (TargetProcessors != 0) {
  534. KiIpiSendPacket(TargetProcessors,
  535. KiSyncCacheTarget,
  536. NULL,
  537. NULL,
  538. NULL);
  539. }
  540. #endif
  541. //
  542. // Synchronize the Instruction Prefetch pipe in the local processor.
  543. //
  544. __synci();
  545. __isrlz();
  546. //
  547. // Wait until all target processors have finished sweeping the their
  548. // data cache.
  549. //
  550. #if !defined(NT_UP)
  551. if (TargetProcessors != 0) {
  552. KiIpiStallOnPacketTargets(TargetProcessors);
  553. }
  554. //
  555. // Lower IRQL to its previous level and return.
  556. //
  557. KeLowerIrql(OldIrql);
  558. #endif
  559. return;
  560. }
  561. ULONG_PTR
  562. KiSyncMC_Drain (
  563. IN BOOLEAN AllProcessors,
  564. IN PVOID BaseAddress,
  565. IN ULONG Length
  566. )
  567. /*++
  568. Routine Description:
  569. KiSyncMC_Drain issues PAL_MC_DRAIN to drain either prefetches, demand references
  570. or pending fc cache line evictions to all the processors in the system.
  571. DrainTypePointer points to the variable, DrainType, which determines the type of
  572. drain to be performed. This is typically used when changing the memory attribute
  573. from WB to UC.
  574. Arguments:
  575. AllProcessors - All processors in the system.
  576. BaseAddress - Supplies a pointer to the base of the range that is to be drained.
  577. Length - Supplies the length of the range that is drained for the base
  578. address specified.
  579. Return Value:
  580. Note: This is used when changing attributes of WB pages to UC pages.
  581. --*/
  582. {
  583. ULONG_PTR Status;
  584. //
  585. // KiIpiGenericCall returns ULONG_PTR as the function value of the specified function
  586. //
  587. Status = (KiIpiGenericCall (
  588. (PKIPI_BROADCAST_WORKER)KiSyncMC_DrainTarget,
  589. (ULONG_PTR)NULL)
  590. );
  591. ASSERT(Status == PAL_STATUS_SUCCESS);
  592. return Status;
  593. }
  594. ULONG_PTR
  595. KiSyncPrefetchVisibleTarget(
  596. )
  597. /*++
  598. Routine Description:
  599. This is the target function for issuing PAL_PREFETCH VISIBILITY
  600. on the target CPU it executes.
  601. Argument:
  602. Not used.
  603. Return Value:
  604. Returns the status from the function HalCallPal
  605. --*/
  606. {
  607. ULONG_PTR Status;
  608. //
  609. // Call HalCallPal to drain.
  610. //
  611. Status = HalCallPal(PAL_PREFETCH_VISIBILITY,
  612. 0,
  613. 0,
  614. 0,
  615. 0,
  616. 0,
  617. 0,
  618. 0);
  619. ASSERT(Status != PAL_STATUS_ERROR);
  620. return Status;
  621. }
  622. ULONG_PTR
  623. KiSyncPrefetchVisible (
  624. IN BOOLEAN AllProcessors,
  625. IN PVOID BaseAddress,
  626. IN ULONG Length
  627. )
  628. /*++
  629. Routine Description:
  630. KiSyncPrefetchVisible issues PAL_PREFETCH_VISIBILITY to cause the processor to make
  631. all pending prefetches visible to subsequent fc instructions; or does nothing, on
  632. processor implementations which does not require PAL support for disabling prefetch
  633. in the architectural sequence. On processors that require PAL support for this
  634. sequence, the actions performed by this procedure may include any or all
  635. of the following (or none, as long as the processor guarantees that
  636. prefetches that were issued prior to this call are not resident in the
  637. processor's caches after the architected sequence is complete.
  638. This is typically used when changing the memory attribute from WB to UC.
  639. Arguments:
  640. AllProcessors - All processors in the system.
  641. BaseAddress - Supplies a pointer to the base of the range that is to be drained.
  642. Length - Supplies the length of the range that is drained for the base
  643. address specified.
  644. Return Value:
  645. Status of the PAL CALL
  646. 0 Success
  647. 1 Call not needed
  648. -3 Error returned
  649. Note: This is used when changing attributes of WB pages to UC pages.
  650. --*/
  651. {
  652. ULONG_PTR Status;
  653. switch (ProbePalVisibilitySupport) {
  654. case 0:
  655. if (NeedPalVisibilitySupport == 0)
  656. Status = PAL_STATUS_SUPPORT_NOT_NEEDED;
  657. else {
  658. Status = (KiIpiGenericCall (
  659. (PKIPI_BROADCAST_WORKER)KiSyncPrefetchVisibleTarget,
  660. (ULONG_PTR)NULL)
  661. );
  662. }
  663. break;
  664. case 1:
  665. Status = KiSyncPrefetchVisibleTarget();
  666. ASSERT(Status != PAL_STATUS_ERROR);
  667. ProbePalVisibilitySupport = 0;
  668. if (Status == PAL_STATUS_SUPPORT_NOT_NEEDED) {
  669. NeedPalVisibilitySupport = 0;
  670. Status = PAL_STATUS_SUPPORT_NOT_NEEDED;
  671. } else {
  672. Status = (KiIpiGenericCall (
  673. (PKIPI_BROADCAST_WORKER)KiSyncPrefetchVisibleTarget,
  674. (ULONG_PTR)NULL)
  675. );
  676. }
  677. break;
  678. default:
  679. Status = PAL_STATUS_ERROR;
  680. break;
  681. }
  682. ASSERT(Status != PAL_STATUS_ERROR);
  683. return Status;
  684. }
  685. VOID
  686. KeSweepCacheRangeWithDrain (
  687. IN BOOLEAN AllProcessors,
  688. IN PVOID BaseAddress,
  689. IN ULONG Length
  690. )
  691. /*++
  692. Routine Description:
  693. This function is used to drain prefetches,demand references followed by flushing
  694. the cache followed by draining pending fc cache line evictions to a specified range
  695. address in all processors in the system.
  696. Arguments:
  697. AllProcessors - All processors in the system.
  698. BaseAddress - Supplies a pointer to the base of the range that is flushed and drained.
  699. Length - Supplies the length of the range that is flushed and drained for the base
  700. address is specified.
  701. Return Value:
  702. None.
  703. Note: This is used when changing attributes of WB pages to UC pages.
  704. --*/
  705. {
  706. ULONG_PTR Status;
  707. Status = KiSyncPrefetchVisible(
  708. AllProcessors,
  709. BaseAddress,
  710. Length
  711. );
  712. ASSERT(Status != PAL_STATUS_ERROR);
  713. KeSweepCacheRange (
  714. AllProcessors,
  715. BaseAddress,
  716. Length
  717. );
  718. Status = KiSyncMC_Drain (
  719. AllProcessors,
  720. BaseAddress,
  721. Length
  722. );
  723. ASSERT(Status == PAL_STATUS_SUCCESS);
  724. return;
  725. }