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.

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