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.

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