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.

1616 lines
48 KiB

  1. //++
  2. //
  3. // Copyright (c) 1989-2000 Microsoft Corporation
  4. //
  5. // Component Name:
  6. //
  7. // NT / KE
  8. //
  9. // Module Name:
  10. //
  11. // ctxswap.s
  12. //
  13. // Abstract:
  14. //
  15. // This module implements the IA64 Process and Thread Context Swaps.
  16. //
  17. // Author:
  18. //
  19. // David N. Cutler (davec) 5-Mar-1989
  20. //
  21. // Environment:
  22. //
  23. // Kernel mode only
  24. //
  25. // Revision History:
  26. //
  27. // Bernard Lint Jul-12-1995
  28. //
  29. // Initial IA64 version
  30. //
  31. //--
  32. #include "ksia64.h"
  33. .file "ctxswap.s"
  34. .text
  35. //
  36. // Globals imported:
  37. //
  38. .global KeTickCount
  39. .global KiMasterSequence
  40. .global KiMasterRid
  41. .global PPerfGlobalGroupMask
  42. PublicFunction(KeBugCheck)
  43. PublicFunction(KiRetireDpcList)
  44. PublicFunction(KiSaveExceptionFrame)
  45. PublicFunction(KiRestoreExceptionFrame)
  46. PublicFunction(KiActivateWaiterQueue)
  47. PublicFunction(KiReadyThread)
  48. PublicFunction(KiQueueReadyThread)
  49. PublicFunction(KeFlushEntireTb)
  50. PublicFunction(KiQuantumEnd)
  51. PublicFunction(KiSyncNewRegionId)
  52. PublicFunction(KiCheckForSoftwareInterrupt)
  53. PublicFunction(KiSaveHigherFPVolatileAtDispatchLevel)
  54. PublicFunction(KiAcquireSpinLock)
  55. PublicFunction(KeReleaseQueuedSpinLockFromDpcLevel)
  56. PublicFunction(KeAcquireQueuedSpinLockRaiseToSynch)
  57. PublicFunction(KiTimerExpiration)
  58. PublicFunction(WmiTraceContextSwap)
  59. #include "icecap.h"
  60. #if DBG
  61. PublicFunction(KeBugCheckEx)
  62. #endif // DBG
  63. SBTTL("Swap Thread")
  64. //++
  65. //--------------------------------------------------------------------
  66. //
  67. // BOOLEAN
  68. // KiSwapContext (
  69. // IN PKTHREAD OldThread
  70. // IN PKTHREAD NewThread
  71. // )
  72. //
  73. // Routine Description:
  74. //
  75. // This routine saves the non-volatile registers, marshals the
  76. // arguments for SwapContext and calls SwapContext to perform
  77. // the actual thread switch.
  78. //
  79. // Arguments:
  80. //
  81. // OldThread - Supplies the address of the old thread.
  82. // NewThread - Supplies the address of the new thread.
  83. //
  84. // Return Value:
  85. //
  86. // If a kernel APC is pending, then a value of TRUE is returned.
  87. // Otherwise, FALSE is returned.
  88. //
  89. // Notes:
  90. //
  91. // GP valid on entry -- GP is not switched, just use kernel GP
  92. //--------------------------------------------------------------------
  93. //--
  94. NESTED_ENTRY(KiSwapContext)
  95. //
  96. // Register aliases
  97. //
  98. pNoAPC = pt2 // do not dispatch APC
  99. rpT1 = t0 // temp pointer
  100. rpT2 = t1 // temp pointer
  101. rT1 = t10 // temp regs
  102. PROLOGUE_BEGIN
  103. #ifdef _CAPKERN
  104. .regstk 2, 2, 2, 0
  105. alloc t16 = ar.pfs, 2, 2, 2, 0
  106. #else
  107. .regstk 2, 2, 1, 0
  108. alloc t16 = ar.pfs, 2, 2, 1, 0
  109. #endif
  110. .save rp, loc0
  111. mov loc0 = brp
  112. .fframe SwitchFrameLength
  113. add sp = -SwitchFrameLength, sp
  114. ;;
  115. .save ar.unat, loc1
  116. mov loc1 = ar.unat
  117. add t0 = ExFltS19+SwExFrame+STACK_SCRATCH_AREA, sp
  118. add t1 = ExFltS18+SwExFrame+STACK_SCRATCH_AREA, sp
  119. ;;
  120. .save.gf 0x0, 0xC0000
  121. stf.spill [t0] = fs19, ExFltS17-ExFltS19
  122. stf.spill [t1] = fs18, ExFltS16-ExFltS18
  123. ;;
  124. .save.gf 0x0, 0x30000
  125. stf.spill [t0] = fs17, ExFltS15-ExFltS17
  126. stf.spill [t1] = fs16, ExFltS14-ExFltS16
  127. mov t10 = bs4
  128. ;;
  129. .save.gf 0x0, 0xC000
  130. stf.spill [t0] = fs15, ExFltS13-ExFltS15
  131. stf.spill [t1] = fs14, ExFltS12-ExFltS14
  132. mov t11 = bs3
  133. ;;
  134. .save.gf 0x0, 0x3000
  135. stf.spill [t0] = fs13, ExFltS11-ExFltS13
  136. stf.spill [t1] = fs12, ExFltS10-ExFltS12
  137. mov t12 = bs2
  138. ;;
  139. .save.gf 0x0, 0xC00
  140. stf.spill [t0] = fs11, ExFltS9-ExFltS11
  141. stf.spill [t1] = fs10, ExFltS8-ExFltS10
  142. mov t13 = bs1
  143. ;;
  144. .save.gf 0x0, 0x300
  145. stf.spill [t0] = fs9, ExFltS7-ExFltS9
  146. stf.spill [t1] = fs8, ExFltS6-ExFltS8
  147. mov t14 = bs0
  148. ;;
  149. .save.gf 0x0, 0xC0
  150. stf.spill [t0] = fs7, ExFltS5-ExFltS7
  151. stf.spill [t1] = fs6, ExFltS4-ExFltS6
  152. mov t15 = ar.lc
  153. ;;
  154. .save.gf 0x0, 0x30
  155. stf.spill [t0] = fs5, ExFltS3-ExFltS5
  156. stf.spill [t1] = fs4, ExFltS2-ExFltS4
  157. ;;
  158. .save.f 0xC
  159. stf.spill [t0] = fs3, ExFltS1-ExFltS3 // save fs3
  160. stf.spill [t1] = fs2, ExFltS0-ExFltS2 // save fs2
  161. ;;
  162. .save.f 0x3
  163. stf.spill [t0] = fs1, ExBrS4-ExFltS1 // save fs1
  164. stf.spill [t1] = fs0, ExBrS3-ExFltS0 // save fs0
  165. ;;
  166. .save.b 0x18
  167. st8 [t0] = t10, ExBrS2-ExBrS4 // save bs4
  168. st8 [t1] = t11, ExBrS1-ExBrS3 // save bs3
  169. ;;
  170. .save.b 0x6
  171. st8 [t0] = t12, ExBrS0-ExBrS2 // save bs2
  172. st8 [t1] = t13, ExIntS2-ExBrS1 // save bs1
  173. ;;
  174. .save.b 0x1
  175. st8 [t0] = t14, ExIntS3-ExBrS0 // save bs0
  176. ;;
  177. .save.gf 0xC, 0x0
  178. .mem.offset 0,0
  179. st8.spill [t0] = s3, ExIntS1-ExIntS3 // save s3
  180. .mem.offset 8,0
  181. st8.spill [t1] = s2, ExIntS0-ExIntS2 // save s2
  182. ;;
  183. .save.gf 0x3, 0x0
  184. .mem.offset 0,0
  185. st8.spill [t0] = s1, ExApLC-ExIntS1 // save s1
  186. .mem.offset 8,0
  187. st8.spill [t1] = s0, ExApEC-ExIntS0 // save s0
  188. ;;
  189. .savepsp ar.pfs, ExceptionFrameLength-ExApEC-STACK_SCRATCH_AREA
  190. st8 [t1] = t16, ExIntNats-ExApEC
  191. mov t4 = ar.unat // captured Nats of s0-s3
  192. ;;
  193. .savepsp ar.lc, ExceptionFrameLength-ExApLC-STACK_SCRATCH_AREA
  194. st8 [t0] = t15
  195. .savepsp @priunat, ExceptionFrameLength-ExIntNats-STACK_SCRATCH_AREA
  196. st8 [t1] = t4 // save Nats of s0-s3
  197. PROLOGUE_END
  198. //
  199. // For the call to SwapContext-
  200. //
  201. // s0 // Prcb address
  202. // s1 // old thread address
  203. // s2 // new thread address
  204. // pt0 = 1
  205. //
  206. mov s2 = a1 // s2 <- New Thread
  207. movl t0 = KiPcr + PcPrcb
  208. ;;
  209. mov s1 = a0 // OldThread
  210. ld8 s0 = [t0]
  211. ;;
  212. //
  213. // Swap context to the next thread.
  214. //
  215. CAPSTART(KiSwapContext,SwapContext)
  216. br.call.sptk brp = SwapContext // call SwapContext(prcb, OldTh, NewTh)
  217. CAPEND(KiSwapContext)
  218. ;;
  219. //
  220. // Deallocate exception/switch frame.
  221. //
  222. // N.B. SwapContext releases the dispatcher database lock.
  223. //
  224. // N.B. v0 contains the kernel APC pending state on return, ie, 0 if
  225. // no APC pending, 1 if APC pending. v0 will be forced to 0 if
  226. // the new IRQL doesn't allow APCs.
  227. //
  228. // N.B. KiRestoreExceptionFrame doesn't touch v0, t21 or t22.
  229. //
  230. add rpT2 = ThWaitIrql, s2 // -> ThWaitIrql
  231. add rpT1 = ExApEC+SwExFrame+STACK_SCRATCH_AREA, sp
  232. add out0 = STACK_SCRATCH_AREA+SwExFrame, sp
  233. ;;
  234. ld1 t21 = [rpT2] // t21 = original wait IRQL
  235. ld8 t22 = [rpT1] // t22 = PFS
  236. br.call.sptk brp = KiRestoreExceptionFrame
  237. ;;
  238. mov brp = loc0
  239. cmp.ne pNoAPC = zero, t21 // no APC if IRQL != 0
  240. ;;
  241. mov ar.unat = loc1
  242. nop.f 0
  243. mov ar.pfs = t22
  244. .restore
  245. add sp = SwitchFrameLength, sp
  246. (pNoAPC) mov v0 = zero
  247. br.ret.sptk brp
  248. ;;
  249. NESTED_EXIT(KiSwapContext)
  250. SBTTL("Swap Context to Next Thread")
  251. //++
  252. //--------------------------------------------------------------------
  253. // Routine:
  254. //
  255. // SwapContext
  256. //
  257. // Routine Description:
  258. //
  259. // This routine is called to swap context from one thread to the next.
  260. //
  261. // Arguments:
  262. //
  263. // s0 - Address of Processor Control Block (PRCB).
  264. // s1 - Address of previous thread object.
  265. // s2 - Address of next thread object.
  266. //
  267. // Return value:
  268. //
  269. // v0 - Kernel APC pending flag
  270. // s0 - Address of Processor Control Block (PRCB).
  271. // s1 - Address of previous thread object.
  272. // s2 - Address of current thread object.
  273. //
  274. // Note:
  275. // Kernel GP is not saved and restored across context switch
  276. //
  277. // !!WARNING!! - Thierry. 03/01/2000.
  278. // Be aware that this implementation is a result of performance analysis.
  279. // Please consider this when you are making changes...
  280. //
  281. //--------------------------------------------------------------------
  282. //--
  283. NESTED_ENTRY(SwapContext)
  284. //
  285. // Register aliases
  286. //
  287. rT1 = t1 // temp
  288. rT2 = t2 // temp
  289. rT3 = t3 // temp
  290. rNewproc = t4 // next process object
  291. rOldproc = t5 // previous process object
  292. rpThBSL = t6 // pointer to new thread backing store limit
  293. rpT1 = t7 // temp pointer
  294. rpT2 = t8 // temp pointer
  295. rpT3 = t9 // temp pointer
  296. rAr1 = t10
  297. rAr2 = t11
  298. rAr3 = t12
  299. rAr4 = t13
  300. rNewIKS = t14 // new initial kernel stack
  301. rNewKSL = t15 // new kernel stack limit
  302. rNewBSP = t16 // new thread BSP/BSPSTORE
  303. rOldBSP = t16 // old thread BSP
  304. rOldRNAT = t17 // old thread RNAT
  305. rNewRNAT = t17 // new thread RNAT
  306. rOldSbase = t18 // old thread kstack base
  307. pUsTh = pt4 // is user thread?
  308. pLoop = pt4 // Need to loop waiting for context swap.
  309. pKrTh = pt5 // is user thread?
  310. pSave = pt7 // is high fp set dirty?
  311. pDiff = ps4 // if new and old process different
  312. pSame = ps5 // if new and old process same
  313. //
  314. // Set new thread's state to running. Note this must be done
  315. // under the dispatcher lock so that KiSetPriorityThread sees
  316. // the correct state.
  317. //
  318. PROLOGUE_BEGIN
  319. #if !defined(NT_UP)
  320. alloc rT2 = ar.pfs, 0, 0, 4, 0
  321. mov rT1 = brp // move from brp takes 2 cycles
  322. ;;
  323. add rpT2 = SwPFS+STACK_SCRATCH_AREA, sp
  324. add out0 = ThSwapBusy, s2 // Get address of new threads busy field
  325. ;;
  326. .savesp ar.pfs, SwPFS+STACK_SCRATCH_AREA
  327. st8.nta [rpT2] = rT2, SwRp-SwPFS // save pfs
  328. ;;
  329. .savesp brp, SwRp+STACK_SCRATCH_AREA
  330. st8.nta [rpT2] = rT1 // save return link
  331. ;;
  332. //
  333. // Loop while the swap busy flag is set
  334. //
  335. loop1:
  336. ld1.acq out1 = [out0]
  337. ;;
  338. cmp.ne pLoop = zero, out1
  339. ;;
  340. (pLoop) YIELD
  341. (pLoop) br.cond.spnt loop1
  342. ;;
  343. mov out0 = ar.fpsr // move from ar.fpsr takes 12 cycles
  344. movl rpT1 = KiPcr+PcHighFpOwner // setup for prefetching
  345. ;;
  346. { .mmi
  347. lfetch [rpT1]
  348. cmp.ne pUsTh = zero, teb // test for ia32 save required
  349. // must not have a nop.f for next 10 cycles--
  350. // Using temporarely the explicit templating
  351. // for the next cycles.
  352. add out1 = ThStackBase, s1 // move early to start access for rOldSbase
  353. { .mmi
  354. add rpT1 = SwFPSR+STACK_SCRATCH_AREA, sp
  355. add rpT2 = SwPreds+STACK_SCRATCH_AREA, sp
  356. nop.i 0x0
  357. }
  358. ;;
  359. { .mmi
  360. ld8.nta rOldSbase = [out1] // speculative start early for ia32 saves
  361. lfetch.excl [rpT1]
  362. add out2 = ThNumber, s2 // setup for prefetching
  363. }
  364. { .mmi
  365. mov.m ar.rsc = r0 // put RSE in lazy mode
  366. mov rOldBSP = ar.bsp // move from ar.bsp takes 12 cycles
  367. nop.i 0x0
  368. }
  369. ;;
  370. { .mmi
  371. lfetch [out2]
  372. nop.m 0x0
  373. mov rT1 = pr // move from pr takes 2 cycles
  374. }
  375. ;;
  376. { .mmi
  377. flushrs
  378. mov rT3 = psr.um // move from psr.um takes 12 cycles
  379. nop.i 0x0
  380. }
  381. ;;
  382. { .mmi
  383. lfetch.excl [rpT2]
  384. mov.m rOldRNAT = ar.rnat // move from ar.rnat takes 5 cycles
  385. add out2 = @gprel(PPerfGlobalGroupMask), gp
  386. }
  387. ;;
  388. { .mli
  389. lfetch [out2]
  390. movl out3 = KiPcr + PcInterruptionCount // INTERRUPTION_LOGGING on or off, we are prefetching this line.
  391. // If any real performance problem is detected, we will undef these lines.
  392. }
  393. ;;
  394. { .mmi
  395. lfetch [out3]
  396. add rpT3 = SwRnat+STACK_SCRATCH_AREA, sp
  397. }
  398. ;;
  399. #else // NT_UP
  400. alloc rT2 = ar.pfs, 0, 0, 4, 0
  401. cmp.ne pUsTh = zero, teb // test for ia32 save required
  402. ;;
  403. mov.m ar.rsc = r0 // put RSE in lazy mode
  404. add out1 = ThStackBase, s1 // move early to start access for rOldSbase
  405. mov out0 = ar.fpsr // move from ar.fpsr takes 12 cycles
  406. // must not have a nop.f for next 10 cycles--
  407. // Using temporarely the explicit templating
  408. // for the next cycles.
  409. ;;
  410. { .mmi
  411. ld8.nta rOldSbase = [out1] // speculative start early for ia32 saves
  412. mov rOldBSP = ar.bsp // move from ar.bsp takes 12 cycles
  413. add rpT1 = SwRp+STACK_SCRATCH_AREA, sp
  414. }
  415. ;;
  416. flushrs
  417. mov rT3 = psr.um // move from psr.um takes 12 cycles
  418. add rpT2 = SwPFS+STACK_SCRATCH_AREA, sp
  419. ;;
  420. mov.m rOldRNAT = ar.rnat // move from ar.rnat takes 5 cycles
  421. mov rT1 = brp // move from brp takes 2 cycles
  422. add rpT3 = ThState, s2
  423. ;;
  424. { .mmi
  425. mov rAr1 = Running
  426. .savesp brp, SwRp+STACK_SCRATCH_AREA
  427. st8.nta [rpT1] = rT1, SwFPSR-SwRp // save return link
  428. nop.i 0x0
  429. }
  430. ;;
  431. { .mii
  432. st1.nta [rpT3] = rAr1 // set thread state to Running
  433. mov rT1 = pr // move from pr takes 2 cycles
  434. nop.i 0x0
  435. }
  436. ;;
  437. { .mii
  438. .savesp ar.pfs, SwPFS+STACK_SCRATCH_AREA
  439. st8.nta [rpT2] = rT2, SwPreds-SwPFS // save pfs
  440. add rpT3 = SwRnat+STACK_SCRATCH_AREA, sp
  441. nop.i 0x0
  442. }
  443. ;;
  444. #endif // NT_UP
  445. { .mmi
  446. st8.nta [rpT3] = rOldRNAT
  447. nop.m 0x0
  448. nop.i 0x0
  449. }
  450. st8 [rpT1] = out0, SwBsp-SwFPSR // save kernel FPSR
  451. st8 [rpT2] = rT1 // save preserved predicates
  452. ;;
  453. st8.nta [rpT1] = rOldBSP
  454. add rpT3 = ThKernelBStore, s1
  455. tbit.nz pSave = rT3, PSR_MFH // check mfh bit
  456. (pUsTh) br.call.spnt brp = SwapContextIA32Save
  457. ;;
  458. st8.nta [rpT3] = rOldBSP
  459. (pSave) add out0 = -ThreadStateSaveAreaLength+TsHigherFPVolatile, rOldSbase
  460. (pSave) br.call.spnt brp = KiSaveHigherFPVolatileAtDispatchLevel
  461. ;;
  462. PROLOGUE_END
  463. //
  464. // ***** TBD ****** Save performance counters? (user vs. kernel)
  465. //
  466. //
  467. // The following entry point is used to switch from the idle thread to
  468. // another thread.
  469. //
  470. ;;
  471. ALTERNATE_ENTRY(SwapFromIdle)
  472. alloc rT1 = ar.pfs, 2, 0, 2, 0
  473. //
  474. // Check if we are tracing context swaps
  475. //
  476. mov out0 = ATTEMPTED_SWITCH_FROM_DPC
  477. add rpT3 = @gprel(PPerfGlobalGroupMask), gp
  478. ;;
  479. ld8.nta rpT3 = [rpT3] // get value of PperfGlobalGroupMask
  480. mov out1 = s2 // assign out1 to new ethread pointer
  481. add rT1 = PbDpcRoutineActive, s0
  482. ;;
  483. ld4 rT1 = [rT1] // Get the DPC active flag.
  484. add rpT2 = PERF_CONTEXTSWAP_OFFSET, rpT3
  485. cmp.ne pt3 = zero, rpT3 // if it's non-zero, then trace on
  486. ;;
  487. sync.i // Start sync.i well before the srlz.i
  488. (pt3) ld4.nta rpT2 = [rpT2]
  489. cmp.ne pt0 = zero, rT1
  490. ;;
  491. (pt3) and rpT2 = PERF_CONTEXTSWAP_FLAG, rpT2
  492. (pt0) br.call.spnt brp = KeBugCheck // Bugcheck if DPC active.
  493. ;;
  494. (pt3) cmp.ne.unc pt4 = zero, rpT2
  495. mov out0 = s1 // assign out0 to old ethread pointer
  496. (pt4) br.call.spnt brp = WmiTraceContextSwap // optimize for no tracing case
  497. ;;
  498. //
  499. // Get address of old and new process objects.
  500. //
  501. add rpT2 = ThApcState+AsProcess,s2 // -> new thread AsProcess
  502. add rpT1 = ThApcState+AsProcess,s1 // -> old thread AsProcess
  503. ;;
  504. LDPTR (rOldproc, rpT1) // old process
  505. LDPTR (rNewproc, rpT2) // new process
  506. #if !defined(NT_UP)
  507. //
  508. // In MP system,
  509. // should a thread address is recycled and the thread is migrated to a
  510. // processor that holds the stale values in the high fp register set,
  511. // set KiPcr->HighFpOwner to zero (i.e. when pt4 is set to TRUE)
  512. //
  513. add rpT1 = ThNumber, s2
  514. movl rpT2 = KiPcr+PcHighFpOwner
  515. ;;
  516. ld1 rT1 = [rpT1]
  517. ld8 rT2 = [rpT2], PcNumber-PcHighFpOwner
  518. ;;
  519. ld1 rT3 = [rpT2], PcHighFpOwner-PcNumber
  520. cmp.eq pt3 = rT2, s2
  521. ;;
  522. (pt3) cmp.ne.unc pt4 = rT1, rT3
  523. ;;
  524. (pt4) st8 [rpT2] = zero
  525. #endif // !defined(NT_UP)
  526. ;;
  527. flushrs
  528. FAST_DISABLE_INTERRUPTS
  529. ;;
  530. //
  531. // Thierry - 03/29/2000
  532. // It should be noticed that the performance analysis for SwapContext
  533. // was done with INTERRUPTION_LOGGING defined as 1.
  534. //
  535. #if DBG // interruption logging is enabled in checked
  536. #define INTERRUPTION_LOGGING 1
  537. #endif // DBG
  538. #if defined(INTERRUPTION_LOGGING)
  539. // For Conditional Interrupt Logging
  540. #define ContextSwitchBit 63
  541. .global KiVectorLogMask
  542. mov rT3 = gp
  543. ;;
  544. movl gp = _gp
  545. ;;
  546. add rpT1 = @gprel(KiVectorLogMask), gp
  547. ;;
  548. ld8 rT1 = [rpT1]
  549. mov gp = rT3
  550. ;;
  551. tbit.z pt4 = rT1, ContextSwitchBit
  552. (pt4) br.cond.sptk EndOfLogging0
  553. movl rpT1 = KiPcr+PcInterruptionCount
  554. mov rT3 = MAX_NUMBER_OF_IHISTORY_RECORDS - 1
  555. cmp.ne pDiff,pSame=rOldproc,rNewproc
  556. ;;
  557. (pDiff) mov rT1 = 0x91 // process switch
  558. ld4.nt1 rT2 = [rpT1] // get current count
  559. ;;
  560. (pSame) mov rT1 = 0x90 // thread switch
  561. add rpT3 = 1, rT2 // incr count
  562. and rT2 = rT3, rT2 // index of current entry
  563. add rpT2 = 0x1000-PcInterruptionCount, rpT1 // base of history
  564. ;;
  565. st4.nta [rpT1] = rpT3 // save count
  566. shl rT2 = rT2, 5 // offset of current entry
  567. ;;
  568. add rpT2 = rpT2, rT2 // address of current entry
  569. ;;
  570. st8 [rpT2] = rT1, 8 // save switch type
  571. ;;
  572. st8 [rpT2] = s2, 8 // save new thread pointer
  573. ;;
  574. st8 [rpT2] = s1, 8 // save old thread
  575. ;;
  576. st8 [rpT2] = sp // save old sp
  577. ;;
  578. // For Conditional Interrupt Logging
  579. EndOfLogging0:
  580. #endif // INTERRUPTION_LOGGING
  581. mov ar.rsc = r0 // put RSE in lazy mode
  582. add rpT1 = ThInitialStack, s2
  583. add rpT2 = ThKernelStack, s1
  584. ;;
  585. //
  586. // Store the kernel stack pointer in the previous thread object,
  587. // load the new kernel stack pointer from the new thread object,
  588. // switch backing store pointers, select new process id and swap
  589. // to the new process.
  590. //
  591. ld8.nta rNewIKS = [rpT1], ThKernelStack-ThInitialStack
  592. st8.nta [rpT2] = sp // save current sp
  593. ;;
  594. ld8.nta sp = [rpT1], ThStackLimit-ThKernelStack
  595. movl rpT2 = KiPcr + PcInitialStack
  596. ;;
  597. alloc rT1 = 0,0,0,0 // make current frame 0 size
  598. ld8.nta rNewKSL = [rpT1], ThInitialBStore-ThStackLimit
  599. ;;
  600. loadrs // invalidate RSE and ALAT
  601. ld8.nta rT1 = [rpT1], ThBStoreLimit-ThInitialBStore
  602. ;;
  603. ld8.nta rT2 = [rpT1], ThTeb-ThBStoreLimit
  604. st8 [rpT2] = rNewIKS, PcStackLimit-PcInitialStack
  605. add rpT3 = SwBsp+STACK_SCRATCH_AREA, sp
  606. ;;
  607. // get debugger active state
  608. ld8 rNewBSP = [rpT3], SwRnat-SwBsp
  609. st8 [rpT2] = rNewKSL, PcInitialBStore-PcStackLimit
  610. ;;
  611. ld8 rNewRNAT = [rpT3]
  612. st8 [rpT2] = rT1, PcBStoreLimit-PcInitialBStore
  613. ;;
  614. st8 [rpT2] = rT2, PcCurrentThread-PcBStoreLimit
  615. // load new teb
  616. ld8 teb = [rpT1], ThSpecialApcDisable-ThTeb
  617. // set new debugger active state
  618. invala
  619. //
  620. // Setup PCR intial kernel BSP and BSTORE limit
  621. //
  622. mov ar.bspstore = rNewBSP // load new bspstore
  623. cmp.ne pDiff,pSame=rOldproc,rNewproc // if ne, switch process
  624. ;;
  625. ld2 rT2 = [rpT1], ThApcState+AsKernelApcPending-ThSpecialApcDisable // Get APC disable
  626. mov ar.rnat = rNewRNAT // load new RNATs
  627. ;;
  628. mov ar.rsc = RSC_KERNEL // enable RSE
  629. cmp.eq pt0 = zero, rT2 // APC enabled if zero
  630. ;;
  631. //
  632. // If the new process is not the same as the old process, then swap the
  633. // address space to the new process.
  634. //
  635. // N.B. The context swap lock cannot be dropped until all references to the
  636. // old process address space are complete. This includes any possible
  637. // TB Misses that could occur referencing the new address space while
  638. // still executing in the old address space.
  639. //
  640. // N.B. The process address space swap is executed with interrupts disabled.
  641. //
  642. alloc rT1 = 0,4,2,0
  643. add loc1 = PcApcInterrupt-PcCurrentThread, rpT2
  644. mov loc0 = 0 // Initialize ApcPending to zero
  645. ;;
  646. mov kteb = teb // update kernel TEB
  647. st1 [loc1] = r0 // Zero the old apc interrupt.
  648. STPTR (rpT2, s2)
  649. FAST_ENABLE_INTERRUPTS
  650. (pt0) ld1.acq loc0 = [rpT1] // load the ApcPending flag if enabled
  651. ;;
  652. #ifdef _CAPKERN
  653. (pDiff) movl out0 = @fptr(SwapContext)
  654. (pDiff) movl out1 = @fptr(KiSwapProcess)
  655. (pDiff) br.call.sptk.few b0=_CAP_Start_Profiling2;;
  656. #endif
  657. mov out0 = rNewproc // set address of new process
  658. mov out1 = rOldproc // set address of old process
  659. (pDiff) br.call.sptk brp = KxSwapProcess // call swap address space(NewProc, OldProc)
  660. ;;
  661. #if !defined(NT_UP)
  662. add out0 = ThSwapBusy, s1 // Get address of old thread busy flag
  663. cmp.ne pt0 = 0, loc0
  664. ;;
  665. #if DBG
  666. ld1 rT2 = [out0] ;;
  667. cmp.eq pt1 = rT2, r0 ;;
  668. (pt1) break.i BREAKPOINT_STOP
  669. #endif
  670. st1.rel [out0] = zero // clear swap busy flag in old thread
  671. ;;
  672. #else
  673. cmp.ne pt0 = 0, loc0
  674. ;;
  675. #endif // !defined(NT_UP)
  676. #ifdef _CAPKERN
  677. (pDiff) movl out0 = @fptr(SwapContext)
  678. (pDiff) br.call.sptk.few b0=_CAP_End_Profiling2;;
  679. (pDiff) cmp.ne pt0 = 0, loc0 ;;
  680. #endif
  681. //
  682. // In new address space, if changed.
  683. //
  684. (pt0) st1 [loc1] = loc0 // request APC interrupt.
  685. add rpT1 = PbContextSwitches, s0
  686. add rpT2 = ThContextSwitches, s2
  687. ;;
  688. //
  689. // If the new thread has a kernel mode APC pending, then request an APC
  690. // interrupt.
  691. //
  692. ld4 loc1 = [rpT1]
  693. ld4 loc2 = [rpT2]
  694. ;;
  695. //
  696. // Increment context switch counters
  697. //
  698. cmp.ne pUsTh, pKrTh = zero, teb
  699. add loc1 = loc1, zero, 1
  700. add loc2 = loc2, zero, 1
  701. ;;
  702. st4 [rpT1] = loc1 // increment # of context switches
  703. st4 [rpT2] = loc2 // increment # of context switches
  704. add rpT1 = SwFPSR+STACK_SCRATCH_AREA, sp
  705. add rpT2 = SwPFS+STACK_SCRATCH_AREA, sp
  706. ;;
  707. ld8 loc1 = [rpT1], SwRp-SwFPSR // restore brp and pfs
  708. ld8 loc2 = [rpT2], SwPreds-SwPFS
  709. ;;
  710. ld8 rT3 = [rpT1]
  711. ld8 rT2 = [rpT2]
  712. mov v0 = loc0 // set v0 = apc pending
  713. (pUsTh) br.call.spnt brp = SwapContextIA32Restore
  714. ;;
  715. //
  716. // Note: at this point s0 = Prcb, s1 = previous thread, s2 = current thread
  717. //
  718. mov ar.fpsr = loc1
  719. mov ar.pfs = loc2
  720. mov brp = rT3
  721. mov pr = rT2 // Restore preserved preds
  722. ;;
  723. srlz.i
  724. br.ret.sptk brp
  725. NESTED_EXIT(SwapContext)
  726. //++
  727. //--------------------------------------------------------------------
  728. // Routine:
  729. //
  730. // SwapContextIA32Save
  731. //
  732. // Routine Description:
  733. //
  734. // This function saves the IA32 context on the kernel stack.
  735. // Called from SwapContext.
  736. //
  737. // Arguments:
  738. //
  739. // rOldSbase : old thread kstack base.
  740. //
  741. // Return value:
  742. //
  743. // None.
  744. //
  745. // Note:
  746. //
  747. // SwapContext registers context.
  748. //
  749. //--------------------------------------------------------------------
  750. //--
  751. LEAF_ENTRY(SwapContextIA32Save)
  752. mov rAr1 = ar21 // IA32 FP control register FCR
  753. ;;
  754. mov rAr2 = ar24 // IA32 EFLAG register
  755. ;;
  756. mov rAr3 = ar28
  757. ;;
  758. mov rAr4 = ar26
  759. ;;
  760. //
  761. // we may skip saving ar27 because it cannot be modified by user code
  762. //
  763. mov rT1 = ar30
  764. ;;
  765. mov rT3 = ar29
  766. ;;
  767. // these are separated out due to cache miss potential
  768. add rpT1 = -ThreadStateSaveAreaLength+TsAppRegisters+TsAr21, rOldSbase
  769. add rpT2 = -ThreadStateSaveAreaLength+TsAppRegisters+TsAr24, rOldSbase
  770. ;;
  771. st8 [rpT1] = rAr1, TsAr28-TsAr21
  772. st8 [rpT2] = rAr2, TsAr26-TsAr24
  773. ;;
  774. st8 [rpT1] = rAr3, TsAr29-TsAr28
  775. st8 [rpT2] = rAr4, TsAr30-TsAr26
  776. ;;
  777. st8 [rpT2] = rT1
  778. st8 [rpT1] = rT3
  779. br.ret.sptk.few.clr brp
  780. LEAF_EXIT(SwapContextIA32Save)
  781. //++
  782. //--------------------------------------------------------------------
  783. // Routine:
  784. //
  785. // SwapContextIA32Restore
  786. //
  787. // Routine Description:
  788. //
  789. // This function restores the IA32 registers context.
  790. // Called from SwapContext.
  791. //
  792. // Arguments:
  793. //
  794. // s2 - Address of next thread object.
  795. //
  796. // Return value:
  797. //
  798. // None.
  799. //
  800. // Note:
  801. //
  802. // SwapContext registers context.
  803. //
  804. //--------------------------------------------------------------------
  805. //--
  806. LEAF_ENTRY(SwapContextIA32Restore)
  807. add rpT1 = ThStackBase, s2
  808. ;;
  809. ld8.nta rpT1 = [rpT1]
  810. ;;
  811. add rpT2 = -ThreadStateSaveAreaLength+TsAppRegisters+TsAr21, rpT1
  812. add rpT3 = -ThreadStateSaveAreaLength+TsAppRegisters+TsAr24, rpT1
  813. ;;
  814. ld8.nta rAr1 = [rpT2], TsAr27-TsAr21
  815. ld8.nta rAr2 = [rpT3], TsAr26-TsAr24
  816. ;;
  817. ld8.nta rAr4 = [rpT3], TsAr28-TsAr26
  818. ;;
  819. mov ar21 = rAr1
  820. mov ar24 = rAr2
  821. mov ar26 = rAr4
  822. ld8.nta rAr1 = [rpT2], TsAr29-TsAr27
  823. ld8.nta rAr2 = [rpT3], TsAr30-TsAr28
  824. ;;
  825. ld8.nta rAr3 = [rpT2]
  826. ld8.nta rAr4 = [rpT3]
  827. ;;
  828. mov ar27 = rAr1
  829. mov ar28 = rAr2
  830. mov ar29 = rAr3
  831. mov ar30 = rAr4
  832. br.ret.sptk.few.clr brp
  833. LEAF_EXIT(SwapContextIA32Restore)
  834. SBTTL("Swap Process")
  835. //++
  836. //--------------------------------------------------------------------
  837. //
  838. // VOID
  839. // KiSwapProcess (
  840. // IN PKPROCESS NewProcess,
  841. // IN PKPROCESS OldProcess
  842. // )
  843. //
  844. // Routine Description:
  845. //
  846. // This function swaps the address space from one process to another by
  847. // assigning a new region id, if necessary, and loading the fixed entry
  848. // in the TB that maps the process page directory page. This routine follows
  849. // the PowerPC design for handling RID wrap.
  850. //
  851. // On entry/exit:
  852. //
  853. // Interrupt enabled.
  854. //
  855. // Arguments:
  856. //
  857. // NewProcess (a0) - Supplies a pointer to a control object of type process
  858. // which represents the new process that is switched to (32-bit address).
  859. //
  860. // OldProcess (a1) - Supplies a pointer to a control object of type process
  861. // which represents the old process that is switched from (32-bit address).
  862. //
  863. // Return Value:
  864. //
  865. // None.
  866. //
  867. //--------------------------------------------------------------------
  868. //--
  869. NESTED_ENTRY(KiSwapProcess)
  870. NESTED_SETUP(2,3,3,0)
  871. PROLOGUE_END
  872. //
  873. // Register aliases
  874. //
  875. rNewProc = a0
  876. rOldProc = a1
  877. rpCSLock = loc2
  878. rpT1 = t0
  879. rpT2 = t1
  880. rProcSet = t2
  881. rNewActive= t3
  882. rOldActive= t4
  883. rMasterSeq= t5
  884. rNewSeq = t6
  885. rOldPsrL = t7
  886. rVa = t8
  887. rPDE0 = t9 // PDE for page directory page 0
  888. rVa2 = t10
  889. rSessionBase = t11
  890. rSessionInfo = t12
  891. rT1 = t13
  892. rT2 = t14
  893. //
  894. #if !defined(NT_UP)
  895. movl rpT1 = KiPcr+PcPrcb
  896. ;;
  897. ld8 rpT1 = [rpT1]
  898. ;;
  899. br.sptk Ksp_Continue
  900. #endif // !defined(NT_UP)
  901. ;;
  902. ALTERNATE_ENTRY(KxSwapProcess)
  903. NESTED_SETUP(2,3,3,0)
  904. PROLOGUE_END
  905. //
  906. // Clear the processor set member number in the old process and set the
  907. // processor member number in the new process.
  908. //
  909. Ksp_Continue:
  910. #if !defined(NT_UP)
  911. add rpT2 = PrActiveProcessors, rOldProc // -> old active processor set
  912. movl rpT1 = KiPcr + PcSetMember // -> processor set member
  913. ;;
  914. ld8 rProcSet= [rpT1] // rProcSet = processor set member
  915. add rpT1 = PrActiveProcessors, rNewProc // -> new active processor set
  916. ;;
  917. ksp_retry1:
  918. ld8 rT1 = [rpT1] // rT1 = Old processor mask
  919. ;;
  920. mov ar.ccv = rT1 // Load compare register
  921. or rNewActive = rT1,rProcSet // set processor member in new set
  922. ;;
  923. cmpxchg8.rel out0 = [rpT1], rNewActive, ar.ccv // Attempt to set the bit
  924. ;;
  925. cmp.ne pt0, pt1 = out0, rT1 // Did the swap suceed?
  926. (pt0) br.spnt.few ksp_retry1
  927. ksp_retry2:
  928. ld8 rT1 = [rpT2] // rT1 = Old processor mask
  929. ;;
  930. mov ar.ccv = rT1 // Load compare register
  931. xor rOldActive = rT1,rProcSet // clear processor member in old set
  932. ;;
  933. cmpxchg8.rel out0 = [rpT2], rOldActive, ar.ccv // Attempt to clear the bit
  934. ;;
  935. cmp.ne pt0, pt1 = out0, rT1 // Did the swap suceed?
  936. (pt0) br.spnt.few ksp_retry2
  937. #endif // !defined(NT_UP)
  938. //
  939. // If the process sequence number matches the system sequence number, then
  940. // use the process RID. Otherwise, allocate a new process RID.
  941. //
  942. #ifdef _CAPKERN
  943. ;;
  944. CAPSTART(KiSwapProcess,KiSyncNewRegionId)
  945. #endif
  946. add rT2 = PrSessionMapInfo, rNewProc
  947. add out0 = PrProcessRegion, rNewProc
  948. ;;
  949. ld8 out1 = [rT2]
  950. mov out2 = zero // We don't old the swap lock
  951. br.call.sptk brp = KiSyncNewRegionId
  952. CAPEND(KiSwapProcess)
  953. ;;
  954. //
  955. // Switch address space to new process
  956. // v0 = rRid = new process rid
  957. //
  958. fwb // hint to flush write buffers
  959. FAST_DISABLE_INTERRUPTS
  960. add rpT1 = PrDirectoryTableBase, rNewProc
  961. movl rVa = KiPcr+PcPdeUtbase
  962. add rpT2 = PrSessionParentBase, rNewProc
  963. movl rVa2 = KiPcr+PcPdeStbase
  964. ;;
  965. ld8.nta rPDE0 = [rpT1] // rPDE0 = Page directory page 0
  966. ld8.nta rSessionBase = [rpT2]
  967. ld8.nta rVa = [rVa]
  968. ld8.nta rVa2 = [rVa2]
  969. ;;
  970. //
  971. // To access IFA, ITDR registers, PSR.ic bit must be 0. Otherwise,
  972. // it causes an illegal operation fault. While PSR.ic=0, any
  973. // interruption can not be afforded. Make sure there will be no
  974. // TLB miss and no interrupt coming in during this period.
  975. //
  976. rsm 1 << PSR_IC // PSR.ic=0
  977. ;;
  978. srlz.d // must serialize
  979. mov rT1 = PAGE_SHIFT << IDTR_PS // load page size field for IDTR
  980. ;;
  981. mov cr.itir = rT1 // set up IDTR for dirbase
  982. ptr.d rVa, rT1 // remove DTR for user space
  983. ;;
  984. mov cr.ifa = rVa // set up IFA for dirbase vaddr
  985. mov rT2 = DTR_UTBASE_INDEX
  986. ;;
  987. itr.d dtr[rT2] = rPDE0 // insert PDE0 to DTR
  988. ;;
  989. ptr.d rVa2, rT1 // remove DTR for session
  990. ;; // to avoid a overlapping error
  991. mov cr.ifa = rVa2
  992. mov rT2 = DTR_STBASE_INDEX
  993. ;;
  994. itr.d dtr[rT2] = rSessionBase // insert the root for session space
  995. ;;
  996. ssm 1 << PSR_IC // PSR.ic=1
  997. ;;
  998. srlz.i // must I serialize
  999. #if DBG
  1000. mov t0 = PbProcessorState+KpsSpecialRegisters+KsTrD0+(8*DTR_UTBASE_INDEX)
  1001. movl t3 = KiPcr + PcPrcb
  1002. ;;
  1003. ld8 t3 = [t3]
  1004. mov t1 = PbProcessorState+KpsSpecialRegisters+KsTrD0+(8*DTR_STBASE_INDEX)
  1005. ;;
  1006. add t0 = t3, t0
  1007. add t1 = t3, t1
  1008. ;;
  1009. st8 [t0] = rPDE0
  1010. st8 [t1] = rSessionBase
  1011. ;;
  1012. #endif
  1013. FAST_ENABLE_INTERRUPTS
  1014. //
  1015. // Now make sure branch history is enabled for non wow processes
  1016. // and disabled for wow processes
  1017. //
  1018. .global KiHistoryBufferLogMask
  1019. add t1 = @gprel(KiHistoryBufferLogMask), gp
  1020. ;;
  1021. ld8 t1 = [t1]
  1022. ;;
  1023. cmp.eq pt0 = t1, r0
  1024. (pt0) br.cond.sptk SkipBranchHistory
  1025. mov t1 = 3
  1026. ;;
  1027. mov t2 = cpuid[t1]
  1028. add t3 = PrWow64Process, rNewProc
  1029. ;;
  1030. extr.u t2 = t2, 24, 8
  1031. ld4 t4 = [t3];
  1032. ;;
  1033. cmp.ne pt1 = 7, t2
  1034. ;;
  1035. mov t1 = 675
  1036. (pt1) br.dpnt SkipBranchHistory
  1037. ;;
  1038. mov t2 = msr[t1]
  1039. cmp.eq pt1,pt2 = zero, t4 // Wow64 is non-zero
  1040. ;;
  1041. (pt1) mov t3 = 2 // Enable the HB for ia64 procs
  1042. (pt2) mov t3 = 256 // Disable the HB for wow64 procs
  1043. ;;
  1044. dep t2 = t3, t2, 0, 9 // Disable the HB for wow64 procs
  1045. ;;
  1046. mov msr[t1] = t2;
  1047. ;;
  1048. SkipBranchHistory:
  1049. #if !defined(NT_UP)
  1050. movl rpT1 = KiPcr+PcPrcb
  1051. ;;
  1052. ld8 rpT1 = [rpT1]
  1053. ;;
  1054. #endif // !defined(NT_UP)
  1055. NESTED_RETURN
  1056. NESTED_EXIT(KiSwapProcess)
  1057. SBTTL("Dispatch Interrupt")
  1058. //++
  1059. //--------------------------------------------------------------------
  1060. // Routine:
  1061. //
  1062. // KiDispatchInterrupt
  1063. //
  1064. // Routine Description:
  1065. //
  1066. // This routine is entered as the result of a software interrupt generated
  1067. // at DISPATCH_LEVEL. Its function is to process the Deferred Procedure Call
  1068. // (DPC) list, and then perform a context switch if a new thread has been
  1069. // selected for execution on the processor.
  1070. //
  1071. // This routine is entered at IRQL DISPATCH_LEVEL with the dispatcher
  1072. // database unlocked. When a return to the caller finally occurs, the
  1073. // IRQL remains at DISPATCH_LEVEL, and the dispatcher database is still
  1074. // unlocked.
  1075. //
  1076. // N.B. On entry to this routine the volatile states (excluding high
  1077. // floating point register set) have been saved.
  1078. //
  1079. // On entry:
  1080. //
  1081. // sp - points to stack scratch area.
  1082. //
  1083. // Arguments:
  1084. //
  1085. // None
  1086. //
  1087. // Return Value:
  1088. //
  1089. // None.
  1090. //--------------------------------------------------------------------
  1091. //--
  1092. NESTED_ENTRY(KiDispatchInterrupt)
  1093. NESTED_SETUP(0, 4, 2, 0)
  1094. PROLOGUE_END
  1095. //
  1096. // Register aliases
  1097. //
  1098. rPrcb = loc2
  1099. rKerGP = loc3
  1100. rpT1 = t0
  1101. rpT2 = t1
  1102. rT1 = t2
  1103. rT2 = t3
  1104. rpDPLock = t4 // pointer to dispatcher lock
  1105. pNext = pt2 // next thread not null
  1106. pNull = pt3 // no thread available
  1107. pQEnd = pt6 // quantum end request pending
  1108. pNoQEnd = pt7 // no quantum end request pending
  1109. //
  1110. // Increment the dispatch interrupt count
  1111. //
  1112. mov rKerGP = gp // save gp
  1113. movl rPrcb = KiPcr + PcPrcb
  1114. ;;
  1115. LDPTR (rPrcb, rPrcb) // rPrcb -> Prcb
  1116. ;;
  1117. add rpT1 = PbDispatchInterruptCount, rPrcb
  1118. ;;
  1119. ld4 rT1 = [rpT1]
  1120. ;;
  1121. add rT1 = rT1, zero, 1
  1122. ;;
  1123. st4 [rpT1] = rT1
  1124. //
  1125. // Process the deferred procedure call list.
  1126. //
  1127. FAST_ENABLE_INTERRUPTS
  1128. ;;
  1129. srlz.d
  1130. //
  1131. // **** TBD ***** No stack switch as in alpha, mips...
  1132. // Save current initial stack address and set new initial stack address.
  1133. //
  1134. FAST_DISABLE_INTERRUPTS
  1135. CAPSTART(KiDispatchInterrupt,KiRetireDpcList)
  1136. mov out0 = rPrcb
  1137. br.call.sptk brp = KiRetireDpcList
  1138. CAPEND(KiDispatchInterrupt)
  1139. ;;
  1140. //
  1141. // Check to determine if quantum end has occured.
  1142. //
  1143. // N.B. If a new thread is selected as a result of processing a quantum
  1144. // end request, then the new thread is returned with the dispatcher
  1145. // database locked. Otherwise, NULL is returned with the dispatcher
  1146. // database unlocked.
  1147. //
  1148. FAST_ENABLE_INTERRUPTS
  1149. add rpT1 = PbQuantumEnd, rPrcb
  1150. add rpT2 = PbNextThread, rPrcb
  1151. ;;
  1152. ld4 rT1 = [rpT1] // get quantum end indicator
  1153. ;;
  1154. cmp4.ne pQEnd, pNoQEnd = rT1, zero // if zero, no quantum end reqs
  1155. mov gp = rKerGP // restore gp
  1156. ;;
  1157. (pQEnd) st4 [rpT1] = zero // clear quantum end indicator
  1158. (pNoQEnd)ld8 rT1 = [rpT2] // rT1 = address of next thread object
  1159. (pQEnd) br.cond.dpnt Kdi_QuantumEnd
  1160. ;;
  1161. //
  1162. // If no quantum end requests:
  1163. // Check to determine if a new thread has been selected for execution on
  1164. // this processor.
  1165. //
  1166. cmp.eq pNull, pNext = rT1, zero // pNull => no thread selected
  1167. mov ar.pfs = savedpfs // Prepare for return
  1168. mov brp = savedbrp // or tail call
  1169. ;;
  1170. (pNext) br.dpnt.many KxDispatchInterrupt // Jump to KxDispathInterrupt
  1171. (pNull) br.ret.dptk.many.clr brp // Return to the caller
  1172. Kdi_QuantumEnd:
  1173. CAPSTART(KiDispatchInterrupt,KiQuantumEnd)
  1174. br.call.spnt brp = KiQuantumEnd // call KiQuantumEnd (C code)
  1175. CAPEND(KiDispatchInterrupt)
  1176. ;;
  1177. NESTED_RETURN
  1178. NESTED_EXIT(KiDispatchInterrupt)
  1179. NESTED_ENTRY(KxDispatchInterrupt)
  1180. PROLOGUE_BEGIN
  1181. .regstk 0, 4, 2, 0
  1182. alloc t16 = ar.pfs, 0, 4, 2, 0
  1183. .save rp, loc0
  1184. mov loc0 = brp
  1185. .fframe SwitchFrameLength
  1186. add sp = -SwitchFrameLength, sp
  1187. ;;
  1188. .save ar.unat, loc1
  1189. mov loc1 = ar.unat
  1190. add t0 = ExFltS19+SwExFrame+STACK_SCRATCH_AREA, sp
  1191. add t1 = ExFltS18+SwExFrame+STACK_SCRATCH_AREA, sp
  1192. ;;
  1193. .save.gf 0x0, 0xC0000
  1194. stf.spill [t0] = fs19, ExFltS17-ExFltS19
  1195. stf.spill [t1] = fs18, ExFltS16-ExFltS18
  1196. ;;
  1197. .save.gf 0x0, 0x30000
  1198. stf.spill [t0] = fs17, ExFltS15-ExFltS17
  1199. stf.spill [t1] = fs16, ExFltS14-ExFltS16
  1200. mov t10 = bs4
  1201. ;;
  1202. .save.gf 0x0, 0xC000
  1203. stf.spill [t0] = fs15, ExFltS13-ExFltS15
  1204. stf.spill [t1] = fs14, ExFltS12-ExFltS14
  1205. mov t11 = bs3
  1206. ;;
  1207. .save.gf 0x0, 0x3000
  1208. stf.spill [t0] = fs13, ExFltS11-ExFltS13
  1209. stf.spill [t1] = fs12, ExFltS10-ExFltS12
  1210. mov t12 = bs2
  1211. ;;
  1212. .save.gf 0x0, 0xC00
  1213. stf.spill [t0] = fs11, ExFltS9-ExFltS11
  1214. stf.spill [t1] = fs10, ExFltS8-ExFltS10
  1215. mov t13 = bs1
  1216. ;;
  1217. .save.gf 0x0, 0x300
  1218. stf.spill [t0] = fs9, ExFltS7-ExFltS9
  1219. stf.spill [t1] = fs8, ExFltS6-ExFltS8
  1220. mov t14 = bs0
  1221. ;;
  1222. .save.gf 0x0, 0xC0
  1223. stf.spill [t0] = fs7, ExFltS5-ExFltS7
  1224. stf.spill [t1] = fs6, ExFltS4-ExFltS6
  1225. mov t15 = ar.lc
  1226. ;;
  1227. .save.gf 0x0, 0x30
  1228. stf.spill [t0] = fs5, ExFltS3-ExFltS5
  1229. stf.spill [t1] = fs4, ExFltS2-ExFltS4
  1230. movl rPrcb = KiPcr + PcPrcb
  1231. ;;
  1232. .save.f 0xC
  1233. stf.spill [t0] = fs3, ExFltS1-ExFltS3 // save fs3
  1234. stf.spill [t1] = fs2, ExFltS0-ExFltS2 // save fs2
  1235. ;;
  1236. .save.f 0x3
  1237. stf.spill [t0] = fs1, ExBrS4-ExFltS1 // save fs1
  1238. stf.spill [t1] = fs0, ExBrS3-ExFltS0 // save fs0
  1239. ;;
  1240. .save.b 0x18
  1241. st8 [t0] = t10, ExBrS2-ExBrS4 // save bs4
  1242. st8 [t1] = t11, ExBrS1-ExBrS3 // save bs3
  1243. ;;
  1244. .save.b 0x6
  1245. st8 [t0] = t12, ExBrS0-ExBrS2 // save bs2
  1246. st8 [t1] = t13, ExIntS2-ExBrS1 // save bs1
  1247. ;;
  1248. .save.b 0x1
  1249. st8 [t0] = t14, ExIntS3-ExBrS0 // save bs0
  1250. ld8 rPrcb = [rPrcb]
  1251. ;;
  1252. .save.gf 0xC, 0x0
  1253. .mem.offset 0,0
  1254. st8.spill [t0] = s3, ExIntS1-ExIntS3 // save s3
  1255. .mem.offset 8,0
  1256. st8.spill [t1] = s2, ExIntS0-ExIntS2 // save s2
  1257. ;;
  1258. .save.gf 0x3, 0x0
  1259. .mem.offset 0,0
  1260. st8.spill [t0] = s1, ExApLC-ExIntS1 // save s1
  1261. .mem.offset 8,0
  1262. st8.spill [t1] = s0, ExApEC-ExIntS0 // save s0
  1263. ;;
  1264. .savepsp ar.pfs, ExceptionFrameLength-ExApEC-STACK_SCRATCH_AREA
  1265. st8 [t1] = t16, ExIntNats-ExApEC
  1266. mov t4 = ar.unat // captured Nats of s0-s3
  1267. ;;
  1268. .savepsp ar.lc, ExceptionFrameLength-ExApLC-STACK_SCRATCH_AREA
  1269. st8 [t0] = t15
  1270. .savepsp @priunat, ExceptionFrameLength-ExIntNats-STACK_SCRATCH_AREA
  1271. st8 [t1] = t4 // save Nats of s0-s3
  1272. PROLOGUE_END
  1273. mov rT1 = SYNCH_LEVEL
  1274. ;;
  1275. SET_IRQL (rT1)
  1276. movl rpT1 = KiPcr + PcCurrentThread
  1277. mov s0 = rPrcb // setup call
  1278. ;;
  1279. LDPTR (s1, rpT1) // current thread object
  1280. ;;
  1281. add rpT1 = ThSwapBusy, s1
  1282. mov rT1 = 1
  1283. ;;
  1284. #if DBG
  1285. ld1 rT2 = [rpT1] ;;
  1286. cmp.ne pt0 = rT2, r0 ;;
  1287. (pt0) break.i BREAKPOINT_STOP
  1288. #endif
  1289. st1.rel [rpT1] = rT1 // Set swap busy flag
  1290. add out0 = PbPrcbLock, s0 // Get address of prcb lock
  1291. br.call.sptk brp = KiAcquireSpinLock // Acquire PRCB lock
  1292. ;;
  1293. //
  1294. // Reread address of next thread object since it is possible for it to
  1295. // change in a multiprocessor system.
  1296. //
  1297. add rpT2 = PbNextThread, s0 // -> next thread
  1298. add rpT1 = PbCurrentThread, s0
  1299. ;;
  1300. LDPTR (s2, rpT2) // next thread object
  1301. mov rT1 = WrDispatchInt // wait reason is Dispatch Int.
  1302. ;;
  1303. //
  1304. // Reready current thread for execution and swap context to the selected
  1305. // thread.
  1306. //
  1307. // Note: Lock the old thread so no idle processor
  1308. // can switch to this processor before it is removed from the current
  1309. // processor.
  1310. //
  1311. STPTR (rpT2, zero) // clear addr of next thread
  1312. add out0 = ThWaitReason, s1 // set wait reason
  1313. ;;
  1314. st1 [out0] = rT1
  1315. add out1 = ThState, s2
  1316. mov out0 = Running
  1317. ;;
  1318. STPTR (rpT1, s2) // set addr of current thread
  1319. st1 [out1] = out0 // Set thread state to running
  1320. mov out0 = s1
  1321. mov out1 = s0
  1322. br.call.sptk brp = KiQueueReadyThread
  1323. ;;
  1324. Kdi_Swap:
  1325. CAPSTART(KiDispatchInterrupt,SwapContext) // reenabled, works as stub
  1326. br.call.sptk brp = SwapContext // call SwapContext(Prcb, OldTh, NewTh)
  1327. CAPEND(KiDispatchInterrupt)
  1328. ;;
  1329. //
  1330. // Restore saved registers, and return.
  1331. //
  1332. add out0 = STACK_SCRATCH_AREA+SwExFrame, sp
  1333. br.call.sptk brp = KiRestoreExceptionFrame
  1334. ;;
  1335. Kdi_Exit:
  1336. add rpT1 = ExApEC+SwExFrame+STACK_SCRATCH_AREA, sp
  1337. ;;
  1338. ld8 rT1 = [rpT1]
  1339. mov brp = loc0
  1340. ;;
  1341. mov ar.unat = loc1
  1342. mov ar.pfs = rT1
  1343. .restore
  1344. add sp = SwitchFrameLength, sp
  1345. br.ret.sptk brp
  1346. NESTED_EXIT(KxDispatchInterrupt)