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.

562 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. flushtb.c
  5. Abstract:
  6. This module implements machine dependent functions to flush the TB
  7. for an AMD64 system.
  8. N.B. This module contains only MP versions of the TB flush routines.
  9. Author:
  10. David N. Cutler (davec) 22-April-2000
  11. Environment:
  12. Kernel mode only.
  13. --*/
  14. #include "ki.h"
  15. //
  16. // Define prototypes for forward referenced functions.
  17. //
  18. VOID
  19. KiFlushTargetEntireTb (
  20. IN PKIPI_CONTEXT SignalDone,
  21. IN PVOID Invalid,
  22. IN PVOID Parameter2,
  23. IN PVOID Parameter3
  24. );
  25. VOID
  26. KiFlushTargetMultipleTb (
  27. IN PKIPI_CONTEXT SignalDone,
  28. IN PVOID Parameter1,
  29. IN PVOID Parameter2,
  30. IN PVOID Parameter3
  31. );
  32. VOID
  33. KiFlushTargetSingleTb (
  34. IN PKIPI_CONTEXT SignalDone,
  35. IN PVOID Parameter1,
  36. IN PVOID Parameter2,
  37. IN PVOID Parameter3
  38. );
  39. #if !defined(NT_UP)
  40. VOID
  41. KeFlushEntireTb (
  42. IN BOOLEAN Invalid,
  43. IN BOOLEAN AllProcessors
  44. )
  45. /*++
  46. Routine Description:
  47. This function flushes the entire translation buffer (TB) on all
  48. processors that are currently running threads which are children
  49. of the current process or flushes the entire translation buffer
  50. on all processors in the host configuration.
  51. Arguments:
  52. Invalid - Supplies a boolean value that specifies the reason for
  53. flushing the translation buffer.
  54. AllProcessors - Supplies a boolean value that determines which
  55. translation buffers are to be flushed.
  56. Return Value:
  57. None.
  58. --*/
  59. {
  60. KAFFINITY EntireSet;
  61. KIRQL OldIrql;
  62. PKPRCB Prcb;
  63. PKPROCESS Process;
  64. KAFFINITY TargetProcessors;
  65. //
  66. // Compute the target set of processors, disable context switching,
  67. // and send the flush entire parameters to the target processors,
  68. // if any, for execution.
  69. //
  70. if (AllProcessors != FALSE) {
  71. OldIrql = KeRaiseIrqlToSynchLevel();
  72. Prcb = KeGetCurrentPrcb();
  73. TargetProcessors = KeActiveProcessors;
  74. } else {
  75. KiLockContextSwap(&OldIrql);
  76. Prcb = KeGetCurrentPrcb();
  77. Process = Prcb->CurrentThread->ApcState.Process;
  78. TargetProcessors = Process->ActiveProcessors;
  79. }
  80. EntireSet = KeActiveProcessors & Prcb->NotSetMember;
  81. TargetProcessors &= Prcb->NotSetMember;
  82. //
  83. // If the target set of processors is equal to the full set of processors,
  84. // then set the TB flush time stamp busy.
  85. //
  86. if (TargetProcessors == EntireSet) {
  87. KiSetTbFlushTimeStampBusy();
  88. }
  89. //
  90. // Send packet to target processors.
  91. //
  92. if (TargetProcessors != 0) {
  93. KiIpiSendPacket(TargetProcessors,
  94. KiFlushTargetEntireTb,
  95. NULL,
  96. NULL,
  97. NULL);
  98. }
  99. IPI_INSTRUMENT_COUNT(Prcb->Number, FlushEntireTb);
  100. //
  101. // Flush TB on current processor.
  102. //
  103. KeFlushCurrentTb();
  104. //
  105. // Wait until all target processors have finished and complete packet.
  106. //
  107. if (TargetProcessors != 0) {
  108. KiIpiStallOnPacketTargets(TargetProcessors);
  109. }
  110. //
  111. // If the target set of processors is equal to the full set of processors,
  112. // then clear the TB flush time stamp busy.
  113. //
  114. if (TargetProcessors == EntireSet) {
  115. KiClearTbFlushTimeStampBusy();
  116. }
  117. //
  118. // Lower IRQL and unlock as appropriate.
  119. //
  120. if (AllProcessors != FALSE) {
  121. KeLowerIrql(OldIrql);
  122. } else {
  123. KiUnlockContextSwap(OldIrql);
  124. }
  125. return;
  126. }
  127. VOID
  128. KiFlushTargetEntireTb (
  129. IN PKIPI_CONTEXT SignalDone,
  130. IN PVOID Parameter1,
  131. IN PVOID Parameter2,
  132. IN PVOID Parameter3
  133. )
  134. /*++
  135. Routine Description:
  136. This is the target function for flushing the entire TB.
  137. Arguments:
  138. SignalDone - Supplies a pointer to a variable that is cleared when the
  139. requested operation has been performed.
  140. Parameter1 - Parameter3 - Not used.
  141. Return Value:
  142. None.
  143. --*/
  144. {
  145. //
  146. // Flush the entire TB on the current processor.
  147. //
  148. KiIpiSignalPacketDone(SignalDone);
  149. KeFlushCurrentTb();
  150. return;
  151. }
  152. VOID
  153. KeFlushMultipleTb (
  154. IN ULONG Number,
  155. IN PVOID *Virtual,
  156. IN BOOLEAN Invalid,
  157. IN BOOLEAN AllProcessors,
  158. IN PHARDWARE_PTE *PtePointer OPTIONAL,
  159. IN HARDWARE_PTE PteValue
  160. )
  161. /*++
  162. Routine Description:
  163. This function flushes multiple entries from the translation buffer
  164. on all processors that are currently running threads which are
  165. children of the current process or flushes a multiple entries from
  166. the translation buffer on all processors in the host configuration.
  167. Arguments:
  168. Number - Supplies the number of TB entries to flush.
  169. Virtual - Supplies a pointer to an array of virtual addresses that
  170. are within the pages whose translation buffer entries are to be
  171. flushed.
  172. Invalid - Supplies a boolean value that specifies the reason for
  173. flushing the translation buffer.
  174. AllProcessors - Supplies a boolean value that determines which
  175. translation buffers are to be flushed.
  176. PtePointer - Supplies an optional pointer to an array of pointers to
  177. page table entries that receive the specified page table entry
  178. value.
  179. PteValue - Supplies the the new page table entry value.
  180. Return Value:
  181. The previous contents of the specified page table entry is returned
  182. as the function value.
  183. --*/
  184. {
  185. ULONG Index;
  186. KIRQL OldIrql;
  187. PKPRCB Prcb;
  188. PKPROCESS Process;
  189. KAFFINITY TargetProcessors;
  190. //
  191. // Compute target set of processors.
  192. //
  193. if (AllProcessors != FALSE) {
  194. OldIrql = KeRaiseIrqlToSynchLevel();
  195. Prcb = KeGetCurrentPrcb();
  196. TargetProcessors = KeActiveProcessors;
  197. } else {
  198. KiLockContextSwap(&OldIrql);
  199. Prcb = KeGetCurrentPrcb();
  200. Process = Prcb->CurrentThread->ApcState.Process;
  201. TargetProcessors = Process->ActiveProcessors;
  202. }
  203. //
  204. // If a page table entry address array is specified, then set the
  205. // specified page table entries to the specific value.
  206. //
  207. if (ARGUMENT_PRESENT(PtePointer)) {
  208. for (Index = 0; Index < Number; Index += 1) {
  209. *PtePointer[Index] = PteValue;
  210. }
  211. }
  212. //
  213. // If any target processors are specified, then send a flush multiple
  214. // packet to the target set of processors.
  215. //
  216. TargetProcessors &= Prcb->NotSetMember;
  217. if (TargetProcessors != 0) {
  218. KiIpiSendPacket(TargetProcessors,
  219. KiFlushTargetMultipleTb,
  220. (PVOID)Invalid,
  221. (PVOID)((ULONG64)Number),
  222. (PVOID)Virtual);
  223. }
  224. IPI_INSTRUMENT_COUNT (Prcb->Number, FlushMultipleTb);
  225. //
  226. // Flush the specified entries from the TB on the current processor.
  227. //
  228. for (Index = 0; Index < Number; Index += 1) {
  229. KiFlushSingleTb(Invalid, Virtual[Index]);
  230. }
  231. //
  232. // Wait until all target processors have finished and complete packet.
  233. //
  234. if (TargetProcessors != 0) {
  235. KiIpiStallOnPacketTargets(TargetProcessors);
  236. }
  237. //
  238. // Release the context swap lock.
  239. //
  240. if (AllProcessors != FALSE) {
  241. KeLowerIrql(OldIrql);
  242. } else {
  243. KiUnlockContextSwap(OldIrql);
  244. }
  245. return;
  246. }
  247. VOID
  248. KiFlushTargetMultipleTb (
  249. IN PKIPI_CONTEXT SignalDone,
  250. IN PVOID Invalid,
  251. IN PVOID Number,
  252. IN PVOID Virtual
  253. )
  254. /*++
  255. Routine Description:
  256. This is the target function for flushing multiple TB entries.
  257. Arguments:
  258. SignalDone - Supplies a pointer to a variable that is cleared when the
  259. requested operation has been performed.
  260. Invalid - Supplies a boolean value that determines whether the virtual
  261. address is invalid.
  262. Number - Supplies the number of TB entries to flush.
  263. Virtual - Supplies a pointer to an array of virtual addresses that
  264. are within the pages whose translation buffer entries are to be
  265. flushed.
  266. Return Value:
  267. None.
  268. --*/
  269. {
  270. ULONG Index;
  271. PVOID VirtualAddress[FLUSH_MULTIPLE_MAXIMUM];
  272. //
  273. // Capture the virtual addresses that are to be flushed from the TB
  274. // on the current processor and signal pack done.
  275. //
  276. for (Index = 0; Index < (ULONG64)Number; Index += 1) {
  277. VirtualAddress[Index] = ((PVOID *)(Virtual))[Index];
  278. }
  279. KiIpiSignalPacketDone(SignalDone);
  280. //
  281. // Flush the specified virtual address for the TB on the current
  282. // processor.
  283. //
  284. for (Index = 0; Index < (ULONG64)Number; Index += 1) {
  285. KiFlushSingleTb((BOOLEAN)Invalid, VirtualAddress [Index]);
  286. }
  287. }
  288. HARDWARE_PTE
  289. KeFlushSingleTb (
  290. IN PVOID Virtual,
  291. IN BOOLEAN Invalid,
  292. IN BOOLEAN AllProcessors,
  293. IN PHARDWARE_PTE PtePointer,
  294. IN HARDWARE_PTE PteValue
  295. )
  296. /*++
  297. Routine Description:
  298. This function flushes a single entry from translation buffer (TB)
  299. on all processors that are currently running threads which are
  300. children of the current process.
  301. Arguments:
  302. Virtual - Supplies a virtual address that is within the page whose
  303. translation buffer entry is to be flushed.
  304. Invalid - Supplies a boolean value that specifies the reason for
  305. flushing the translation buffer.
  306. AllProcessors - Supplies a boolean value that determines which
  307. translation buffers are to be flushed.
  308. PtePointer - Supplies a pointer to the page table entry which
  309. receives the specified value.
  310. PteValue - Supplies the the new page table entry value.
  311. Return Value:
  312. The previous contents of the specified page table entry is returned
  313. as the function value.
  314. --*/
  315. {
  316. KIRQL OldIrql;
  317. PKPRCB Prcb;
  318. PKPROCESS Process;
  319. HARDWARE_PTE OldPte;
  320. KAFFINITY TargetProcessors;
  321. //
  322. // Compute the target set of processors and send the flush single
  323. // parameters to the target processors, if any, for execution.
  324. //
  325. if (AllProcessors != FALSE) {
  326. OldIrql = KeRaiseIrqlToSynchLevel();
  327. Prcb = KeGetCurrentPrcb();
  328. TargetProcessors = KeActiveProcessors;
  329. } else {
  330. KiLockContextSwap(&OldIrql);
  331. Prcb = KeGetCurrentPrcb();
  332. Process = Prcb->CurrentThread->ApcState.Process;
  333. TargetProcessors = Process->ActiveProcessors;
  334. }
  335. //
  336. // Capture the previous contents of the page table entry and set the
  337. // page table entry to the new value.
  338. //
  339. OldPte = *PtePointer;
  340. *PtePointer = PteValue;
  341. //
  342. // If any target processors are specified, then send a flush single
  343. // packet to the target set of processors.
  344. //
  345. TargetProcessors &= Prcb->NotSetMember;
  346. if (TargetProcessors != 0) {
  347. KiIpiSendPacket(TargetProcessors,
  348. KiFlushTargetSingleTb,
  349. (PVOID)Invalid,
  350. (PVOID)Virtual,
  351. NULL);
  352. }
  353. IPI_INSTRUMENT_COUNT(Prcb->Number, FlushSingleTb);
  354. //
  355. // Flush the specified entry from the TB on the current processor.
  356. //
  357. KiFlushSingleTb(Invalid, Virtual);
  358. //
  359. // Wait until all target processors have finished and complete packet.
  360. //
  361. if (TargetProcessors != 0) {
  362. KiIpiStallOnPacketTargets(TargetProcessors);
  363. }
  364. //
  365. // Release the context swap lock.
  366. //
  367. if (AllProcessors != FALSE) {
  368. KeLowerIrql(OldIrql);
  369. } else {
  370. KiUnlockContextSwap(OldIrql);
  371. }
  372. return OldPte;
  373. }
  374. VOID
  375. KiFlushTargetSingleTb (
  376. IN PKIPI_CONTEXT SignalDone,
  377. IN PVOID Invalid,
  378. IN PVOID VirtualAddress,
  379. IN PVOID Parameter3
  380. )
  381. /*++
  382. Routine Description:
  383. This is the target function for flushing a single TB entry.
  384. Arguments:
  385. SignalDone Supplies a pointer to a variable that is cleared when the
  386. requested operation has been performed.
  387. Invalid - Supplies a boolean value that determines whether the virtual
  388. address is invalid.
  389. Virtual - Supplies a virtual address that is within the page whose
  390. translation buffer entry is to be flushed.
  391. Parameter3 - Not used.
  392. Return Value:
  393. None.
  394. --*/
  395. {
  396. //
  397. // Flush a single entry from the TB on the current processor.
  398. //
  399. KiIpiSignalPacketDone(SignalDone);
  400. KiFlushSingleTb((BOOLEAN)Invalid, (PVOID)VirtualAddress);
  401. }
  402. #endif