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.

547 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. ipi.c
  5. Abstract:
  6. This module implements AMD64 specific interprocessor interrupt
  7. routines.
  8. Author:
  9. David N. Cutler (davec) 24-Aug-2000
  10. Environment:
  11. Kernel mode only.
  12. --*/
  13. #include "ki.h"
  14. VOID
  15. KiRestoreProcessorState (
  16. IN PKTRAP_FRAME TrapFrame,
  17. IN PKEXCEPTION_FRAME ExceptionFrame
  18. )
  19. /*++
  20. Routine Description:
  21. This function restores the processor state to the specified exception
  22. and trap frames, and restores the processor control state.
  23. Arguments:
  24. TrapFrame - Supplies a pointer to a trap frame.
  25. ExceptionFrame - Supplies a pointer to an exception frame.
  26. Return Value:
  27. None.
  28. --*/
  29. {
  30. #if !defined(NT_UP)
  31. PKPRCB Prcb;
  32. KPROCESSOR_MODE PreviousMode;
  33. //
  34. // Get the address of the current processor block, move the specified
  35. // register state from the processor context structure to the specified
  36. // trap and exception frames, and restore the processor control state.
  37. //
  38. if ((TrapFrame->SegCs & MODE_MASK) != 0) {
  39. PreviousMode = UserMode;
  40. } else {
  41. PreviousMode = KernelMode;
  42. }
  43. Prcb = KeGetCurrentPrcb();
  44. KeContextToKframes(TrapFrame,
  45. ExceptionFrame,
  46. &Prcb->ProcessorState.ContextFrame,
  47. CONTEXT_FULL,
  48. PreviousMode);
  49. KiRestoreProcessorControlState(&Prcb->ProcessorState);
  50. #else
  51. UNREFERENCED_PARAMETER(TrapFrame);
  52. UNREFERENCED_PARAMETER(ExceptionFrame);
  53. #endif
  54. return;
  55. }
  56. VOID
  57. KiSaveProcessorState (
  58. IN PKTRAP_FRAME TrapFrame,
  59. IN PKEXCEPTION_FRAME ExceptionFrame
  60. )
  61. /*++
  62. Routine Description:
  63. This function saves the processor state from the specified exception
  64. and trap frames, and saves the processor control state.
  65. Arguments:
  66. TrapFrame - Supplies a pointer to a trap frame.
  67. ExceptionFrame - Supplies a pointer to an exception frame.
  68. Return Value:
  69. None.
  70. --*/
  71. {
  72. #if !defined(NT_UP)
  73. PKPRCB Prcb;
  74. //
  75. // Get the address of the current processor block, move the specified
  76. // register state from specified trap and exception frames to the current
  77. // processor context structure, and save the processor control state.
  78. //
  79. Prcb = KeGetCurrentPrcb();
  80. Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL;
  81. KeContextFromKframes(TrapFrame,
  82. ExceptionFrame,
  83. &Prcb->ProcessorState.ContextFrame);
  84. KiSaveProcessorControlState(&Prcb->ProcessorState);
  85. #else
  86. UNREFERENCED_PARAMETER(TrapFrame);
  87. UNREFERENCED_PARAMETER(ExceptionFrame);
  88. #endif
  89. return;
  90. }
  91. BOOLEAN
  92. KiIpiServiceRoutine (
  93. IN PKTRAP_FRAME TrapFrame,
  94. IN PKEXCEPTION_FRAME ExceptionFrame
  95. )
  96. /*++
  97. Routine Description:
  98. This function is called at IPI_LEVEL to process outstanding interprocess
  99. requests for the current processor.
  100. Arguments:
  101. TrapFrame - Supplies a pointer to a trap frame.
  102. ExceptionFrame - Supplies a pointer to an exception frame
  103. Return Value:
  104. A value of TRUE is returned, if one of more requests were service.
  105. Otherwise, FALSE is returned.
  106. --*/
  107. {
  108. #if !defined(NT_UP)
  109. ULONG RequestMask;
  110. //
  111. // Process any outstanding interprocessor requests.
  112. //
  113. RequestMask = KiIpiProcessRequests();
  114. //
  115. // If freeze is requested, then freeze target execution.
  116. //
  117. if ((RequestMask & IPI_FREEZE) != 0) {
  118. KiFreezeTargetExecution(TrapFrame, ExceptionFrame);
  119. }
  120. //
  121. // Return whether any requests were processed.
  122. //
  123. return (RequestMask & ~IPI_FREEZE) != 0 ? TRUE : FALSE;
  124. #else
  125. UNREFERENCED_PARAMETER(TrapFrame);
  126. UNREFERENCED_PARAMETER(ExceptionFrame);
  127. return TRUE;
  128. #endif
  129. }
  130. ULONG
  131. KiIpiProcessRequests (
  132. VOID
  133. )
  134. /*++
  135. Routine Description:
  136. This routine processes interprocessor requests and returns a summary
  137. of the requests that were processed.
  138. N.B. This routine does not process freeze execution requests. It is the
  139. responsibilty of the caller to determine that a freeze execution
  140. request is outstanding and process it accordingly.
  141. Arguments:
  142. None.
  143. Return Value:
  144. The request summary is returned as the function value.
  145. --*/
  146. {
  147. #if !defined(NT_UP)
  148. PKPRCB CurrentPrcb;
  149. ULONG RequestMask;
  150. PVOID RequestPacket;
  151. LONG64 RequestSummary;
  152. PKPRCB RequestSource;
  153. //
  154. // Get the current request summary value.
  155. //
  156. CurrentPrcb = KeGetCurrentPrcb();
  157. RequestSummary = InterlockedExchange64(&CurrentPrcb->RequestSummary, 0);
  158. RequestMask = (ULONG)(RequestSummary & ((1 << IPI_PACKET_SHIFT) - 1));
  159. RequestPacket = (PVOID)(RequestSummary >> IPI_PACKET_SHIFT);
  160. //
  161. // If a packet request is ready, then process the packet request.
  162. //
  163. if (RequestPacket != NULL) {
  164. RequestSource = (PKPRCB)((ULONG64)RequestPacket & ~1);
  165. (RequestSource->WorkerRoutine)((PKIPI_CONTEXT)RequestPacket,
  166. RequestSource->CurrentPacket[0],
  167. RequestSource->CurrentPacket[1],
  168. RequestSource->CurrentPacket[2]);
  169. }
  170. //
  171. // If an APC interrupt is requested, then request a software interrupt
  172. // at APC level on the current processor.
  173. //
  174. if ((RequestMask & IPI_APC) != 0) {
  175. KiRequestSoftwareInterrupt(APC_LEVEL);
  176. }
  177. //
  178. // If a DPC interrupt is requested, then request a software interrupt
  179. // at DPC level on the current processor.
  180. //
  181. if ((RequestMask & IPI_DPC) != 0) {
  182. KiRequestSoftwareInterrupt(DISPATCH_LEVEL);
  183. }
  184. return RequestMask;
  185. #else
  186. return 0;
  187. #endif
  188. }
  189. VOID
  190. KiIpiSend (
  191. IN KAFFINITY TargetSet,
  192. IN KIPI_REQUEST Request
  193. )
  194. /*++
  195. Routine Description:
  196. This function requests the specified operation on the targt set of
  197. processors.
  198. N.B. This function MUST be called from a non-context switchable state.
  199. Arguments:
  200. TargetSet - Supplies the target set of processors on which the specified
  201. operation is to be executed.
  202. Request - Supplies the request operation flags.
  203. Return Value:
  204. None.
  205. --*/
  206. {
  207. #if !defined(NT_UP)
  208. PKPRCB NextPrcb;
  209. ULONG Processor;
  210. KAFFINITY SummarySet;
  211. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  212. //
  213. // Loop through the target set of processors and merge the request into
  214. // the request summary of the target processors.
  215. //
  216. // N.B. It is guaranteed that there is at least one bit set in the target
  217. // set.
  218. //
  219. ASSERT(TargetSet != 0);
  220. SummarySet = TargetSet;
  221. BitScanForward64(&Processor, SummarySet);
  222. do {
  223. NextPrcb = KiProcessorBlock[Processor];
  224. InterlockedOr64((LONG64 volatile *)&NextPrcb->RequestSummary, Request);
  225. SummarySet ^= AFFINITY_MASK(Processor);
  226. } while (BitScanForward64(&Processor, SummarySet) != FALSE);
  227. //
  228. // Request interprocessor interrupts on the target set of processors.
  229. //
  230. HalRequestIpi(TargetSet);
  231. #else
  232. UNREFERENCED_PARAMETER(TargetSet);
  233. UNREFERENCED_PARAMETER(Request);
  234. #endif
  235. return;
  236. }
  237. VOID
  238. KiIpiSendPacket (
  239. IN KAFFINITY TargetSet,
  240. IN PKIPI_WORKER WorkerFunction,
  241. IN PVOID Parameter1,
  242. IN PVOID Parameter2,
  243. IN PVOID Parameter3
  244. )
  245. /*++
  246. Routine Description:
  247. This routine executes the specified worker function on the specified
  248. set of processors.
  249. N.B. This function MUST be called from a non-context switchable state.
  250. Arguments:
  251. TargetProcessors - Supplies the set of processors on which the specfied
  252. operation is to be executed.
  253. WorkerFunction - Supplies the address of the worker function.
  254. Parameter1 - Parameter3 - Supplies worker function specific paramters.
  255. Return Value:
  256. None.
  257. --*/
  258. {
  259. #if !defined(NT_UP)
  260. PKPRCB CurrentPrcb;
  261. PKPRCB NextPrcb;
  262. ULONG Processor;
  263. LONG64 RequestSummary;
  264. ULONG64 ShiftedPrcb;
  265. KAFFINITY SummarySet;
  266. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  267. //
  268. // Initialize the worker packet information.
  269. //
  270. CurrentPrcb = KeGetCurrentPrcb();
  271. CurrentPrcb->CurrentPacket[0] = Parameter1;
  272. CurrentPrcb->CurrentPacket[1] = Parameter2;
  273. CurrentPrcb->CurrentPacket[2] = Parameter3;
  274. CurrentPrcb->TargetSet = TargetSet;
  275. CurrentPrcb->WorkerRoutine = WorkerFunction;
  276. //
  277. // If the target set contains one and only one processor, then use the
  278. // target set for signal done synchronization. Otherwise, use packet
  279. // barrier for signal done synchronization.
  280. //
  281. if ((TargetSet & (TargetSet - 1)) == 0) {
  282. CurrentPrcb = (PKPRCB)((ULONG64)CurrentPrcb | 1);
  283. } else {
  284. CurrentPrcb->PacketBarrier = 1;
  285. }
  286. //
  287. // Loop through the target set of processors and merge the request into
  288. // the request summary of the target processors.
  289. //
  290. // N.B. It is guaranteed that there is at least one bit set in the target
  291. // set.
  292. //
  293. ShiftedPrcb = (ULONG64)CurrentPrcb << IPI_PACKET_SHIFT;
  294. SummarySet = TargetSet;
  295. BitScanForward64(&Processor, SummarySet);
  296. do {
  297. NextPrcb = KiProcessorBlock[Processor];
  298. do {
  299. do {
  300. RequestSummary = NextPrcb->RequestSummary;
  301. } while ((RequestSummary >> IPI_PACKET_SHIFT) != 0);
  302. } while (InterlockedCompareExchange64(&NextPrcb->RequestSummary,
  303. RequestSummary | ShiftedPrcb,
  304. RequestSummary) != RequestSummary);
  305. SummarySet ^= AFFINITY_MASK(Processor);
  306. } while (BitScanForward64(&Processor, SummarySet) != FALSE);
  307. //
  308. // Request interprocessor interrupts on the target set of processors.
  309. //
  310. HalRequestIpi(TargetSet);
  311. #else
  312. UNREFERENCED_PARAMETER(TargetSet);
  313. UNREFERENCED_PARAMETER(WorkerFunction);
  314. UNREFERENCED_PARAMETER(Parameter1);
  315. UNREFERENCED_PARAMETER(Parameter2);
  316. UNREFERENCED_PARAMETER(Parameter3);
  317. #endif
  318. return;
  319. }
  320. VOID
  321. KiIpiSignalPacketDone (
  322. IN PKIPI_CONTEXT SignalDone
  323. )
  324. /*++
  325. Routine Description:
  326. This routine signals that a processor has completed a packet by clearing
  327. the calling processor's set member of the requesting processor's packet.
  328. Arguments:
  329. SignalDone - Supplies a pointer to the processor block of the sending
  330. processor.
  331. Return Value:
  332. None.
  333. --*/
  334. {
  335. #if !defined(NT_UP)
  336. KAFFINITY SetMember;
  337. PKPRCB TargetPrcb;
  338. KAFFINITY TargetSet;
  339. //
  340. // If the low bit of signal is set, then use target set to notify the
  341. // sender that the operation is complete on the current processor.
  342. // Otherwise, use packet barrier to notify the sender that the operation
  343. // is complete on the current processor.
  344. //
  345. if (((ULONG64)SignalDone & 1) == 0) {
  346. SetMember = KeGetCurrentPrcb()->SetMember;
  347. TargetPrcb = (PKPRCB)SignalDone;
  348. TargetSet = InterlockedXor64((PLONG64)&TargetPrcb->TargetSet,
  349. SetMember);
  350. //
  351. // If no more bits are set in the target set, then clear packet
  352. // barrier.
  353. //
  354. if (SetMember == TargetSet) {
  355. TargetPrcb->PacketBarrier = 0;
  356. }
  357. } else {
  358. TargetPrcb = (PKPRCB)((ULONG64)SignalDone - 1);
  359. TargetPrcb->TargetSet = 0;
  360. }
  361. #else
  362. UNREFERENCED_PARAMETER(SignalDone);
  363. #endif
  364. return;
  365. }