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.

629 lines
17 KiB

  1. // TITLE("Interprocessor Interrupt support routines")
  2. //++
  3. //
  4. // Copyright (c) 1993 Microsoft Corporation
  5. // Copyright (c) 1993 Digital Equipment Corporation
  6. //
  7. // Module Name:
  8. //
  9. // mpipi.s
  10. //
  11. // Abstract:
  12. //
  13. // This module implements the Alpha AXP specific functions required to
  14. // support multiprocessor systems.
  15. //
  16. // Author:
  17. //
  18. // David N. Cutler (davec) 22-Apr-1993
  19. // Joe Notarangelo 29-Nov-1993
  20. //
  21. // Environment:
  22. //
  23. // Kernel mode only.
  24. //
  25. // Revision History:
  26. //
  27. //--
  28. #include "ksalpha.h"
  29. SBTTL("Interprocess Interrupt Processing")
  30. //++
  31. //
  32. // VOID
  33. // KeIpiInterrupt (
  34. // IN PKTRAP_FRAME TrapFrame
  35. // );
  36. //
  37. // Routine Description:
  38. //
  39. // This routine is entered as the result of an interprocessor interrupt.
  40. // It's function is to process all interprocess immediate and packet
  41. // requests.
  42. //
  43. // Arguments:
  44. //
  45. // TrapFrame (fp/s6) - Supplies a pointer to a trap frame.
  46. //
  47. // Return Value:
  48. //
  49. // None.
  50. //
  51. //--
  52. NESTED_ENTRY(KeIpiInterrupt, ExceptionFrameLength, zero)
  53. lda sp, -ExceptionFrameLength(sp) // allocate exception frame
  54. stq ra, ExIntRa(sp) // save return address
  55. PROLOGUE_END
  56. //
  57. // Process all interprocessor requests.
  58. //
  59. bsr ra, KiIpiProcessRequests // process requests
  60. and v0, IPI_FREEZE, t0 // check if freeze is requested
  61. beq t0, 10f // if eq, no freeze requested
  62. //
  63. // Save the volatile floating state, the nonvolatile floating state,
  64. // and the nonvolatile integer state.
  65. //
  66. bsr ra, KiSaveVolatileFloatState // save volatile float in trap
  67. bsr ra, KiSaveNonVolatileFloatState // save nv float in exception
  68. stq s0, ExIntS0(sp) // save nonvolatile integer state
  69. stq s1, ExIntS1(sp) //
  70. stq s2, ExIntS2(sp) //
  71. stq s3, ExIntS3(sp) //
  72. stq s4, ExIntS4(sp) //
  73. stq s5, ExIntS5(sp) //
  74. stq fp, ExIntFp(sp) //
  75. //
  76. // Freeze the execution of the current processor.
  77. //
  78. bis fp, zero, a0 // set address of trap frame
  79. bis sp, zero, a1 // set address of exception frame
  80. bsr ra, KiFreezeTargetExecution // freeze current processor
  81. //
  82. // Restore the volatile floating state, the nonvolatile floating state,
  83. // and the nonvolatile integer state.
  84. //
  85. ldq s0, ExIntS0(sp) // restore nonvolatile integer state
  86. ldq s1, ExIntS1(sp) //
  87. ldq s2, ExIntS2(sp) //
  88. ldq s3, ExIntS3(sp) //
  89. ldq s4, ExIntS4(sp) //
  90. ldq s5, ExIntS5(sp) //
  91. ldq fp, ExIntFp(sp) //
  92. bsr ra, KiRestoreVolatileFloatState // restore volatile float
  93. bsr ra, KiRestoreNonVolatileFloatState // restore nv float state
  94. //
  95. // Cleanup and return to the caller.
  96. //
  97. 10: ldq ra, ExIntRa(sp) // restore return address
  98. lda sp, ExceptionFrameLength(sp) // deallocate exception frame
  99. ret zero, (ra) // return
  100. .end KeIpiInterrupt
  101. SBTTL("Processor Request")
  102. //++
  103. //
  104. // ULONG
  105. // KiIpiProcessRequests (
  106. // VOID
  107. // );
  108. //
  109. // Routine Description:
  110. //
  111. // This routine processes interprocessor requests and returns a summary
  112. // of the requests that were processed.
  113. //
  114. // Arguments:
  115. //
  116. // None.
  117. //
  118. // Return Value:
  119. //
  120. // The request summary is returned as the function value.
  121. //
  122. //--
  123. .struct 0
  124. PrS0: .space 8 // saved integer register s0
  125. PrS1: .space 8 // saved integer register s1
  126. .space 8 // fill
  127. PrRa: .space 8 // saved return address
  128. PrFrameLength:
  129. NESTED_ENTRY(KiIpiProcessRequests, PrFrameLength, zero)
  130. lda sp, -PrFrameLength(sp) // allocate stack frame
  131. stq s0, PrS0(sp) // save integer register s0
  132. #if NT_INST
  133. stq s1, PrS1(sp) // save integer register s1
  134. #endif
  135. stq ra, PrRa(sp) // save return address
  136. PROLOGUE_END
  137. //
  138. // Read request summary and write a zero result interlocked.
  139. //
  140. mb // get consistent view of memory
  141. GET_PROCESSOR_CONTROL_BLOCK_BASE // get current prcb address
  142. #if NT_INST
  143. LDP s1, PbIpiCounts(v0) // get interrupt count structure address
  144. #endif
  145. 10: ldq_l s0, PbRequestSummary(v0) // get request summary and entry address
  146. bis zero, zero, t1 // set zero value for store
  147. stq_c t1, PbRequestSummary(v0) // zero request summary, conditionally
  148. beq t1, 15f // if eq, store conditional failed
  149. sra s0, 16, a0 // shift out entry address
  150. //
  151. // Check for Packet ready.
  152. //
  153. // If a packet is ready, then get the address of the requested function
  154. // and call the function passing the address of the packet address as a
  155. // parameter.
  156. //
  157. and s0, IPI_PACKET_READY, t2 // check for packet ready
  158. beq t2, 20f // if eq, no packet ready
  159. bic a0, 1, v0 // clear low order packet address bit
  160. LDP t2, PbWorkerRoutine(v0) // get address of worker function
  161. LDP a1, PbCurrentPacket(v0) // get request parameters
  162. #if defined(_AXP64_)
  163. ldq a2, PbCurrentPacket + 8(v0) //
  164. ldq a3, PbCurrentPacket + 16(v0) //
  165. #else
  166. ldl a2, PbCurrentPacket + 4(v0) //
  167. ldl a3, PbCurrentPacket + 8(v0) //
  168. #endif
  169. jsr ra, (t2) // call worker routine
  170. mb // synchronize memory access
  171. #if NT_INST
  172. ldl t1, IcPacket(s1) // increment number of packet requests
  173. addl t1, 1, t1 //
  174. stl t1, IcPacket(s1) //
  175. #endif
  176. //
  177. // Check for APC interrupt request.
  178. //
  179. // If an APC interrupt is requested, then request a software interrupt at
  180. // APC level on the current processor.
  181. //
  182. 20: and s0, IPI_APC, t1 // check for APC interrupt request
  183. beq t1, 30f // if eq, no APC interrupt requested
  184. ldil a0, APC_LEVEL // set interrupt request level
  185. REQUEST_SOFTWARE_INTERRUPT // request APC interrupt
  186. #if NT_INST
  187. ldl t1, IcAPC(s1) // increment number of APC requests
  188. addl t1, 1, t1 //
  189. stl t1, IcAPC(s1) //
  190. #endif
  191. //
  192. // Check for DPC interrupt request.
  193. //
  194. // If a DPC interrupt is requested, then request a software interrupt at
  195. // DPC level on the current processor.
  196. //
  197. 30: and s0, IPI_DPC, t1 // check for DPC interrupt request
  198. beq t1, 40f // if eq, no DPC interrupt requested
  199. ldil a0, DISPATCH_LEVEL // set interrupt request level
  200. REQUEST_SOFTWARE_INTERRUPT // request DPC interrupt
  201. #if NT_INST
  202. ldl t1, IcDPC(s1) // increment number of DPC requests
  203. addl t1, 1, t1 //
  204. stl t1, IcDPC(s1) //
  205. #endif
  206. //
  207. // Set function return value, restore registers, and return.
  208. //
  209. 40: bis s0, zero, v0 // set function return value
  210. ldq s0, PrS0(sp) // restore integer register s0
  211. #if NT_INST
  212. and v0, IPI_FREEZE, t1 // check if freeze requested
  213. beq t1, 50f // if eq, no freeze requested
  214. ldl t1, IcFreeze(s1) // increment number of freeze requests
  215. addl t1, 1, t1 //
  216. stl t1, IcFreeze(s1) //
  217. 50: ldq s1, PrS1(sp) // restore integer register s1
  218. #endif
  219. ldq ra, PrRa(sp) // restore return address
  220. lda sp, PrFrameLength(sp) // deallocate stack frame
  221. ret zero, (ra) // return
  222. //
  223. // Conditional store failed.
  224. //
  225. 15: br zero, 10b // store conditonal failed, retry
  226. .end KiIpiProcessRequests
  227. SBTTL("Send Interprocess Request")
  228. //++
  229. //
  230. // VOID
  231. // KiIpiSend (
  232. // IN KAFINITY TargetProcessors,
  233. // IN KIPI_REQUEST IpiRequest
  234. // );
  235. //
  236. // Routine Description:
  237. //
  238. // This routine requests the specified operation on the target set of
  239. // processors.
  240. //
  241. // Arguments:
  242. //
  243. // TargetProcessors (a0) - Supplies the set of processors on which the
  244. // specified operation is to be executed.
  245. //
  246. // IpiRequest (a1) - Supplies the request operation mask.
  247. //
  248. // Return Value:
  249. //
  250. // None.
  251. //
  252. //--
  253. LEAF_ENTRY(KiIpiSend)
  254. #if !defined(NT_UP)
  255. bis a0, zero, t0 // copy target processor set
  256. lda t1, KiProcessorBlock // get processor block array address
  257. 10: blbc t0, 30f // if lbc, target processor not set
  258. LDP t2, 0(t1) // get target processor block address
  259. //
  260. // Merge the new request into the target processor request summary.
  261. // The store is conditional to ensure that no updates are lost.
  262. //
  263. 20: ldq_l t3, PbRequestSummary(t2) // get target request summary
  264. bis t3, a1, t4 // merge new request with summary
  265. stq_c t4, PbRequestSummary(t2) // set new request summary
  266. beq t4, 25f // if eq, store conditional failed
  267. 30: srl t0, 1, t0 // shift to next target
  268. #if defined(_AXP64_)
  269. lda t1, 8(t1) // get next processor block element
  270. #else
  271. lda t1, 4(t1) // get next processor block element
  272. #endif
  273. bne t0, 10b // if ne, more targets requested
  274. mb // synchronize memory access
  275. LDP t0, __imp_HalRequestIpi // request IPI interrupt on targets
  276. jmp zero, (t0) //
  277. #else
  278. ret zero, (ra) // simply return for uni-processor
  279. #endif
  280. //
  281. // Conditional store failed.
  282. //
  283. 25: br zero, 20b // store conditional failed, retry
  284. .end KiIpiSend
  285. SBTTL("Send Interprocess Request Packet")
  286. //++
  287. //
  288. // VOID
  289. // KiIpiSendPacket (
  290. // IN KAFFINITY TargetProcessors,
  291. // IN PKIPI_WORKER WorkerFunction,
  292. // IN PVOID Parameter1,
  293. // IN PVOID Parameter2,
  294. // IN PVOID Parameter3
  295. // );
  296. //
  297. // Routine Description:
  298. //
  299. // This routine executes the specified worker function on the specified
  300. // set of processors.
  301. //
  302. // Arguments:
  303. //
  304. // TargetProcessors (a0) - Supplies the set of processors on which the
  305. // specified operation is to be executed.
  306. //
  307. // WorkerFunction (a1) - Supplies the address of the worker function.
  308. //
  309. // Parameter1 - Parameter3 - Supplies arguments for worker.
  310. //
  311. // Return Value:
  312. //
  313. // None.
  314. //
  315. //--
  316. LEAF_ENTRY(KiIpiSendPacket)
  317. #if !defined(NT_UP)
  318. GET_PROCESSOR_CONTROL_BLOCK_BASE // get current prcb address
  319. bis a0, zero, t1 // copy target processor set
  320. lda t2, KiProcessorBlock // get processor block array address
  321. //
  322. // Store function address and parameters in the packet area of the PRCB on
  323. // the current processor.
  324. //
  325. stl a0, PbTargetSet(v0) // set target processor set
  326. STP a1, PbWorkerRoutine(v0) // set worker function address
  327. STP a2, PbCurrentPacket(v0) // store worker function parameters
  328. #if defined(_AXP64_)
  329. stq a3, PbCurrentPacket + 8(v0) //
  330. stq a4, PbCurrentPacket + 16(v0) //
  331. #else
  332. stl a3, PbCurrentPacket + 4(v0) //
  333. stl a4, PbCurrentPacket + 8(v0) //
  334. #endif
  335. subl a0, 1, a1 // compute target set - 1
  336. and a1, a0, a1 // and target set with target set - 1
  337. zapnot a1, 0xf, a1 // clear upper 32 bits
  338. cmpeq a1, zero, a1 // compare if result is zero
  339. bne a1, 5f // if ne, one and only one bit set
  340. stl a0, PbPacketBarrier(v0) // set packet barrier
  341. 5: mb // synchronize memory access
  342. ADDP v0, a1, v0 // set low bit if appropriate
  343. //
  344. // Loop through the target processors and send the packet to the specified
  345. // recipients.
  346. //
  347. 10: blbc t1, 30f // if eq, target not specified
  348. LDP t0, 0(t2) // get target processor block address
  349. sll v0, 16, t3 // shift packet address into position
  350. bis t3, IPI_PACKET_READY, t3 // set packet ready in low 32 bits
  351. 20: ldq_l t4, PbRequestSummary(t0) // get request summary of target
  352. and t4, IPI_PACKET_READY, t6 // check if target packet busy
  353. bne t6, 25f // if ne, target packet busy
  354. bis t4, t3, t4 // set entry address in request summary
  355. stq_c t4, PbRequestSummary(t0) // store request summary and address
  356. beq t4, 20b // if eq, store conditional failed
  357. #if defined(_AXP64_)
  358. 30: lda t2, 8(t2) // advance to next array element
  359. #else
  360. 30: lda t2, 4(t2) // advance to next array element
  361. #endif
  362. srl t1, 1, t1 // shift to next target
  363. bne t1, 10b // if ne, more targets to process
  364. mb // synchronize memory access
  365. LDP t0, __imp_HalRequestIpi // request IPI interrupt on targets
  366. jmp zero, (t0) //
  367. //
  368. // Packet not ready, spin in cache until it looks available.
  369. //
  370. 25: ldq t4, PbRequestSummary(t0) // get request summary of target
  371. and t4, IPI_PACKET_READY, t6 // check if target packet busy
  372. beq t6, 20b // looks available, try again
  373. br zero, 25b // spin again
  374. #else
  375. ret zero, (ra)
  376. #endif //!NT_UP
  377. .end KiIpiSendPacket
  378. SBTTL("Restore Processor Control State")
  379. //++
  380. //
  381. // VOID
  382. // KiRestoreProcessorControlState (
  383. // IN PKPROCESSOR_STATE ProcessorState
  384. // );
  385. //
  386. // Routine Description:
  387. //
  388. // This routine restores the processor control state for the debugger.
  389. //
  390. // Arguments:
  391. //
  392. // ProcessorState (a0) - Pointer to PROCSSOR_STATE
  393. //
  394. // Return Value:
  395. //
  396. // None.
  397. //
  398. //--
  399. LEAF_ENTRY(KiRestoreProcessorControlState)
  400. ret zero, (ra) // return
  401. .end KiRestoreProcessorControlState
  402. SBTTL("Save Processor Control State")
  403. //++
  404. //
  405. // VOID
  406. // KiSaveProcessorControlState (
  407. // IN PKPROCESSOR_STATE ProcessorState
  408. // );
  409. //
  410. // Routine Description:
  411. //
  412. // This routine saves the processor control state for the debugger.
  413. //
  414. // Arguments:
  415. //
  416. // ProcessorState (a0) - Pointer to PROCSSOR_STATE
  417. //
  418. // Return Value:
  419. //
  420. // None.
  421. //
  422. //--
  423. LEAF_ENTRY(KiSaveProcessorControlState)
  424. ret zero, (ra) // return
  425. .end KiSaveProcessorControlState
  426. SBTTL("Signal Packet Done")
  427. //++
  428. //
  429. // VOID
  430. // KiIpiSignalPacketDone (
  431. // IN PKIPI_CONTEXT SignalDone
  432. // );
  433. //
  434. // Routine Description:
  435. //
  436. // This routine signals that a processor has completed a packet by
  437. // clearing the calling processor's set member of the requesting
  438. // processor's packet.
  439. //
  440. // Arguments:
  441. //
  442. // SignalDone (a0) - Supplies a pointer to the processor block of the
  443. // sending processor.
  444. //
  445. // Return Value:
  446. //
  447. // None.
  448. //
  449. //--
  450. #if !defined(NT_UP)
  451. LEAF_ENTRY(KiIpiSignalPacketDone)
  452. GET_PROCESSOR_CONTROL_REGION_BASE // get current pcr address
  453. blbs a0, 30f // if lbs, one and only one bit set
  454. ldl a1, PcSetMember(v0) // get processor set member
  455. mb // synchronize memory access
  456. 10: ldl_l a2, PbTargetSet(a0) // get request target set
  457. bic a2, a1, a2 // clear processor set member
  458. mov a2, v0 // save result target set
  459. stl_c a2, PbTargetSet(a0) // store target set
  460. beq a2, 10b // if eq, store conditional failed
  461. bne v0, 20f // if ne, more targets to go
  462. stl zero, PbPacketBarrier(a0) // clear packet barrier
  463. mb // synchronize memory access
  464. 20: ret zero, (ra) // return
  465. 30: stl zero, PbTargetSet - 1(a0) // clear target set
  466. mb // synchronize memory access
  467. ret zero, (ra) //
  468. .end KiIpiSignalPacketDone
  469. #endif
  470. SBTTL("Read Memory Barrier Time Stamp")
  471. //++
  472. //
  473. // ULONG
  474. // KeReadMbTimeStamp (
  475. // VOID
  476. // );
  477. //
  478. // Routine Description:
  479. //
  480. // This routine reads the current memory bazrrier time stamp value.
  481. //
  482. // Arguments:
  483. //
  484. // None.
  485. //
  486. // Return Value:
  487. //
  488. // The current value of the memory barrier time stamp is returned as the
  489. // function value.
  490. //
  491. //--
  492. #if !defined(NT_UP)
  493. LEAF_ENTRY(KeReadMbTimeStamp)
  494. ldl_l v0,KiMbTimeStamp // read current memory barrier time stamp
  495. ret zero, (ra) // return
  496. .end KeReadMbTimeStamp
  497. #endif