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.

950 lines
27 KiB

  1. //++
  2. //
  3. // Copyright (c) 1994 Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // callout.s
  8. //
  9. // Abstract:
  10. //
  11. // This module implements the code necessary to call out from kernel
  12. // mode to user mode.
  13. //
  14. // Author:
  15. //
  16. // William K. Cheung (wcheung) 30-Oct-1995
  17. //
  18. // Environment:
  19. //
  20. // Kernel mode only.
  21. //
  22. // Revision History:
  23. //
  24. //--
  25. #include "ksia64.h"
  26. PublicFunction(MmGrowKernelStack)
  27. PublicFunction(MmGrowKernelBackingStore)
  28. PublicFunction(KiUserServiceExit)
  29. PublicFunction(KiApcInterrupt)
  30. PublicFunction(RtlMoveMemory)
  31. .global KeUserCallbackDispatcher
  32. //++
  33. //
  34. // NTSTATUS
  35. // KiCallUserMode (
  36. // IN PVOID *OutputBuffer,
  37. // IN PULONG OutputLength
  38. // )
  39. //
  40. // Routine Description:
  41. //
  42. // This function calls a user mode function.
  43. //
  44. // N.B. This function calls out to user mode and the NtCallbackReturn
  45. // function returns back to the caller of this function. Therefore,
  46. // the stack layout must be consistent between the two routines.
  47. //
  48. // Arguments:
  49. //
  50. // OutputBuffer (a0) - Supplies a pointer to the variable that receivies
  51. // the address of the output buffer.
  52. //
  53. // OutputLength (a1) - Supplies a pointer to a variable that receives
  54. // the length of the output buffer.
  55. //
  56. // Return Value:
  57. //
  58. // The final status of the call out function is returned as the status
  59. // of the function.
  60. //
  61. // N.B. This function does not return to its caller. A return to the
  62. // caller is executed when a NtCallbackReturn system service is
  63. // executed.
  64. //
  65. // N.B. This function does return to its caller if a kernel stack
  66. // expansion is required and the attempted expansion fails.
  67. //
  68. // The instruction that restores the sp (i.e. epilogue) must be
  69. // in the last bundle of the function. This is a convention
  70. // by which this functin must abide or the stack unwinder in the
  71. // imagehlp DLL will not work.
  72. //
  73. //--
  74. NESTED_ENTRY(KiCallUserMode)
  75. .regstk 2, 8, 2, 0
  76. .prologue
  77. rT0 = t0
  78. rT1 = t1
  79. rT2 = t2
  80. rT3 = t3
  81. rT4 = t4
  82. rT5 = t5
  83. rT6 = t6
  84. rT7 = t7
  85. rpT0 = t10
  86. rpT1 = t11
  87. rpT2 = t12
  88. rpT3 = t13
  89. rpT4 = t14
  90. rpT5 = t15
  91. rpT6 = t16
  92. rpCurTh = loc0
  93. rbsp = loc1
  94. rbspInit = loc2
  95. rpTF = loc7
  96. //
  97. // following 3 register aliases are copied from trap.s
  98. //
  99. pUser = ps1 // mode on entry was user
  100. pKrnl = ps2 // mode on entry was kernel
  101. pUDbg = ps8 // Kernel debug Active
  102. //
  103. // allocate stack frame to save preserved floating point registers
  104. //
  105. alloc rT1 = ar.pfs, 2, 8, 2, 0
  106. mov rT0 = ar.unat
  107. mov rT2 = brp
  108. //
  109. // save both preserved integer and float registers
  110. //
  111. add rpT1 = -CuFrameLength+CuBrRp+STACK_SCRATCH_AREA, sp
  112. add rpT2 = -CuFrameLength+CuRsPFS+STACK_SCRATCH_AREA, sp
  113. .fframe CuFrameLength
  114. add sp = -CuFrameLength, sp
  115. ;;
  116. .savesp brp, CuBrRp+STACK_SCRATCH_AREA
  117. st8.nta [rpT1] = rT2, CuPreds - CuBrRp // save rp
  118. .savesp ar.pfs, CuRsPFS+STACK_SCRATCH_AREA
  119. st8.nta [rpT2] = rT1, CuApUNAT - CuRsPFS // save pfs
  120. mov rT3 = pr
  121. ;;
  122. .savesp pr, CuPreds+STACK_SCRATCH_AREA
  123. st8.nta [rpT1] = rT3, CuApLC - CuPreds // save predicates
  124. .savesp ar.unat, CuApUNAT+ STACK_SCRATCH_AREA
  125. st8.nta [rpT2] = rT0, CuIntS0 - CuApUNAT // save ar.unat
  126. mov rT4 = ar.lc
  127. ;;
  128. .savesp ar.lc, CuApLC+STACK_SCRATCH_AREA
  129. st8.nta [rpT1] = rT4, CuIntS1 - CuApLC // save ar.lc
  130. st8.spill.nta [rpT2] = s0, CuIntS2 - CuIntS0 // save s0
  131. mov rT0 = bs0
  132. ;;
  133. .mem.offset 0,0
  134. st8.spill.nta [rpT1] = s1, CuIntS3 - CuIntS1 // save s1
  135. .mem.offset 8,0
  136. st8.spill.nta [rpT2] = s2, CuBrS0 - CuIntS2 // save s2
  137. mov rT1 = bs1
  138. ;;
  139. st8.spill.nta [rpT1] = s3, CuBrS1 - CuIntS3 // save s3
  140. st8.nta [rpT2] = rT0, CuBrS2 - CuBrS0 // save bs0
  141. mov rT2 = bs2
  142. ;;
  143. flushrs
  144. mov ar.rsc = r0 // put RSE in lazy mode
  145. mov rT6 = ar.unat
  146. ;;
  147. mov rT5 = ar.rnat
  148. mov rT3 = bs3
  149. ;;
  150. st8.nta [rpT1] = rT1, CuBrS3 - CuBrS1 // save bs1
  151. st8.nta [rpT2] = rT2, CuBrS4 - CuBrS2 // save bs2
  152. mov rT4 = bs4
  153. ;;
  154. st8.nta [rpT1] = rT3, CuRsRNAT - CuBrS3 // save bs3
  155. st8.nta [rpT2] = rT4, CuIntNats - CuBrS4 // save bs4
  156. ;;
  157. st8.nta [rpT1] = rT5, CuFltS0 - CuRsRNAT // save rnat
  158. st8.nta [rpT2] = rT6, CuFltS1 - CuIntNats // save NaTs
  159. ;;
  160. stf.spill.nta [rpT1] = fs0, CuFltS2 - CuFltS0 // save fs0
  161. stf.spill.nta [rpT2] = fs1, CuFltS3 - CuFltS1 // save fs1
  162. mov v0 = zero // set v0 to 0
  163. ;;
  164. stf.spill.nta [rpT1] = fs2, CuFltS4 - CuFltS2 // save fs2
  165. stf.spill.nta [rpT2] = fs3, CuFltS5 - CuFltS3 // save fs3
  166. ;;
  167. stf.spill.nta [rpT1] = fs4, CuFltS6 - CuFltS4 // save fs4
  168. stf.spill.nta [rpT2] = fs5, CuFltS7 - CuFltS5 // save fs5
  169. nop.i 0
  170. ;;
  171. stf.spill.nta [rpT1] = fs6, CuFltS8 - CuFltS6 // save fs6
  172. stf.spill.nta [rpT2] = fs7, CuFltS9 - CuFltS7 // save fs7
  173. nop.i 0
  174. ;;
  175. stf.spill.nta [rpT1] = fs8, CuFltS10 - CuFltS8 // save fs8
  176. stf.spill.nta [rpT2] = fs9, CuFltS11 - CuFltS9 // save fs9
  177. nop.i 0
  178. ;;
  179. stf.spill.nta [rpT1] = fs10, CuFltS12 - CuFltS10 // save fs10
  180. stf.spill.nta [rpT2] = fs11, CuFltS13 - CuFltS11 // save fs11
  181. nop.i 0
  182. ;;
  183. stf.spill.nta [rpT1] = fs12, CuFltS14 - CuFltS12 // save fs12
  184. stf.spill.nta [rpT2] = fs13, CuFltS15 - CuFltS13 // save fs13
  185. nop.i 0
  186. ;;
  187. stf.spill.nta [rpT1] = fs14, CuFltS16 - CuFltS14 // save fs14
  188. stf.spill.nta [rpT2] = fs15, CuFltS17 - CuFltS15 // save fs15
  189. nop.i 0
  190. ;;
  191. stf.spill.nta [rpT1] = fs16, CuFltS18 - CuFltS16 // save fs16
  192. stf.spill.nta [rpT2] = fs17, CuFltS19 - CuFltS17 // save fs17
  193. nop.i 0
  194. ;;
  195. stf.spill.nta [rpT1] = fs18, CuA0 - CuFltS18 // save fs18
  196. stf.spill.nta [rpT2] = fs19, CuA1 - CuFltS19 // save fs19
  197. nop.i 0
  198. ;;
  199. PROLOGUE_END
  200. //
  201. // Check if sufficient rooms are available on both the kernel
  202. // memory stack and backing store for another system call.
  203. // Call the MM functions to grow them if necessary.
  204. //
  205. mov rbsp = ar.bsp
  206. movl loc3 = KiPcr + PcCurrentThread
  207. st8.nta [rpT1] = a0
  208. st8.nta [rpT2] = a1
  209. mov rT2 = 0x1ff
  210. ;;
  211. add rbspInit = 0x200, rbsp
  212. mov rT0 = sp
  213. ;;
  214. andcm rbspInit = rbspInit, rT2
  215. ;;
  216. LDPTRINC (rpCurTh, loc3, PcStackLimit - PcCurrentThread)
  217. add rT0 = -KERNEL_LARGE_STACK_COMMIT, rT0
  218. mov rT1 = rbspInit
  219. ;;
  220. add loc4 = ThStackLimit, rpCurTh
  221. add loc5 = ThBStoreLimit, rpCurTh
  222. add rT1 = KERNEL_LARGE_BSTORE_COMMIT, rT1
  223. ;;
  224. //
  225. // check if it is necessary to grow the kernel stack and backing store
  226. //
  227. LDPTR (rT2, loc4) // Get current stack limit.
  228. LDPTR (rT3, loc5) // Get current bstore limit
  229. mov out0 = sp
  230. ;;
  231. cmp.ge ps0 = rT2, rT0
  232. cmp.ge ps1 = rT1, rT3
  233. (ps0) br.call.spnt.many brp = MmGrowKernelStack
  234. //
  235. // Get expanded stack limit from thread object and set the stack limit
  236. // in PCR if the growth of kernel stack is successful.
  237. //
  238. LDPTR (rT0, loc4)
  239. cmp4.ne pt2, pt1 = zero, v0
  240. ;;
  241. nop.m 0
  242. (pt1) st8 [loc3] = rT0, PcBStoreLimit - PcStackLimit
  243. (pt2) br.spnt Kcum10
  244. ;;
  245. mov out0 = rbspInit
  246. (ps1) br.call.spnt.many brp = MmGrowKernelBackingStore
  247. ;;
  248. //
  249. // Get expanded bstore limit from thread object and set the bstore limit
  250. // in PCR if the growth of kernel backing store is successful.
  251. //
  252. LDPTR (rT0, loc5)
  253. cmp4.ne pt2, pt1 = zero, v0
  254. add loc4 = ThCallbackStack - ThStackLimit, loc4
  255. add loc5 = ThCallbackBStore - ThBStoreLimit, loc5
  256. ;;
  257. rPcInStack = rT0
  258. rPcInBStore = rT1
  259. rThCbStack = rT2
  260. rThCbBStore = rT3
  261. rpLabel = rT4
  262. PLDPTRINC (pt1, rThCbStack,loc4, ThTrapFrame - ThCallbackStack)
  263. (pt1) st8 [loc3] = rT0, PcInitialStack - PcBStoreLimit
  264. (pt2) br.spnt Kcum10
  265. ;;
  266. //
  267. // Get the address of the current thread and save the previous trap
  268. // frame and callback stack addresses in the current frame. Also
  269. // save the new callback stack address in the thread object.
  270. //
  271. // Get initial and callback stack & backing store addresses
  272. //
  273. ld8.nt1 rPcInStack = [loc3], PcInitialBStore - PcInitialStack
  274. LDPTRINC (rpTF, loc4, ThCallbackStack - ThTrapFrame)
  275. add rpT1 = @gprel(KeUserCallbackDispatcher), gp
  276. ;;
  277. ld8.nt1 rPcInBStore = [loc3], PcInitialStack-PcInitialBStore
  278. LDPTR (rThCbBStore, loc5)
  279. add rpT2 = CuInStack+STACK_SCRATCH_AREA, sp
  280. ;;
  281. LDPTR (rpLabel, rpT1)
  282. add rpT5 = CuInBStore+STACK_SCRATCH_AREA, sp
  283. add loc6 = PcInitialBStore - PcInitialStack, loc3
  284. ;;
  285. STPTR (loc4, sp) // set callback stack addr
  286. STPTR (loc5, rbsp) // set callback bstore addr
  287. add loc4 = ThInitialStack - ThCallbackStack, loc4
  288. //
  289. // save initial stack and backing store addresses
  290. //
  291. st8.nta [rpT2] = rPcInStack, CuCbStk - CuInStack
  292. st8.nta [rpT5] = rPcInBStore, CuCbBStore - CuInBStore
  293. add loc5 = ThInitialBStore - ThCallbackBStore, loc5
  294. ;;
  295. //
  296. // save callback stack and backing store addresses
  297. //
  298. st8.nta [rpT2] = rThCbStack, CuTrFrame - CuCbStk
  299. st8.nta [rpT5] = rThCbBStore, CuTrStIIP - CuCbBStore
  300. ;;
  301. //
  302. // register aliases
  303. //
  304. rpEntry=rT0
  305. rIPSR=rT1
  306. rIIP=rT2
  307. rsm 1 << PSR_I // disable interrupts
  308. ;;
  309. ld8.nt1 rpEntry = [rpLabel], 8 // get continuation IP
  310. st8.nta [rpT2] = rpTF // save trap frame address
  311. add rpT3 = TrStIIP, rpTF
  312. ;;
  313. ld8.nt1 loc1 = [rpLabel] // get continuation GP
  314. add rpT2 = ThApcState+AsUserApcPending, rpCurTh
  315. ;;
  316. ld8 rIIP = [rpT3], TrStIPSR-TrStIIP // get trap IIP
  317. ld1 rT3 = [rpT2], ThAlerted-ThApcState-AsUserApcPending
  318. ;;
  319. ld8 rIPSR = [rpT3], TrStIIP-TrStIPSR
  320. add rpT1 = -ThreadStateSaveAreaLength-TrapFrameLength+TrStIPSR, sp
  321. cmp4.eq pt0 = zero, rT3
  322. ;;
  323. st8 [rpT3] = rpEntry // set trap IIP
  324. st8.nta [rpT5] = rIIP // save original IIP
  325. ;;
  326. st8 [rpT1] = rIPSR
  327. tbit.nz pUDbg = rIPSR, PSR_DB // if psr.db set, load user DRs
  328. st1 [rpT2] = zero // Clear thread alearted
  329. (pt0) mov gp = loc1 // Set user GP
  330. (pt0) br.sptk Kcum5 // no user apc pending,
  331. ;; // branch to KiUserServiceExit
  332. FAST_ENABLE_INTERRUPTS
  333. mov out1 = APC_LEVEL
  334. ;;
  335. SET_IRQL (out1)
  336. ;;
  337. mov out1 = rpTF
  338. br.call.sptk brp = KiApcInterrupt
  339. ;;
  340. FAST_DISABLE_INTERRUPTS
  341. SET_IRQL (zero)
  342. mov gp = loc1 // Set user GP
  343. ;;
  344. Kcum5:
  345. st8.nta [loc4] = sp // reset initial stack addr
  346. st8.nta [loc3] = sp // reset initial stack addr
  347. cmp4.eq pUser, pKrnl = 0, r0 // preset predicates for
  348. // KiUserServiceExit
  349. // N.B. ps1 -- pUser
  350. // ps2 -- pKrnl
  351. mov t0 = rpTF // set t0 -> trap frame address
  352. // per system call convention
  353. st8.nta [loc5] = rbspInit // reset initial bstore addr
  354. st8.nta [loc6] = rbspInit // reset initial bstore addr
  355. br KiUserServiceExit // per system call convention
  356. //
  357. // An attempt to grow the kernel stack or backing store failed.
  358. //
  359. Kcum10:
  360. nop.m 0
  361. add rpT1 = CuBrRp+STACK_SCRATCH_AREA, sp
  362. add rpT2 = CuRsPFS+STACK_SCRATCH_AREA, sp
  363. ;;
  364. ld8.nt1 rT1 = [rpT1], CuPreds-CuBrRp
  365. ;;
  366. ld8.nt1 rT2 = [rpT2]
  367. mov brp = rT1
  368. ;;
  369. ld8.nt1 rT3 = [rpT1]
  370. mov ar.pfs = rT2
  371. ;;
  372. mov pr = rT3, -1
  373. ;;
  374. .restore
  375. add sp = CuFrameLength, sp
  376. nop.i 0
  377. br.ret.sptk.clr brp
  378. NESTED_EXIT(KiCallUserMode)
  379. //++
  380. //
  381. // PVOID
  382. // KeSwitchKernelStack (
  383. // IN PVOID StackBase,
  384. // IN PVOID StackLimit,
  385. // IN PVOID BStoreLimit
  386. // )
  387. //
  388. // Routine Description:
  389. //
  390. // This function switches to the specified large kernel stack.
  391. //
  392. // N.B. This function can ONLY be called when there are no variables
  393. // in the stack that refer to other variables in the stack, i.e.,
  394. // there are no pointers into the stack.
  395. //
  396. // Arguments:
  397. //
  398. // StackBase (a0) - Supplies a pointer to the base of the new kernel
  399. // stack.
  400. //
  401. // StackLimit (a1) - supplies a pointer to the limit of the new kernel
  402. // stack.
  403. //
  404. // BStoreLimit (a2) - supplies a pointer to the limit of the new kernel
  405. // backing store.
  406. //
  407. // Return Value:
  408. //
  409. // The old kernel stack/backing store base is returned as the function value.
  410. //
  411. //--
  412. NESTED_ENTRY(KeSwitchKernelStack)
  413. .regstk 3, 4, 3, 0
  414. .prologue
  415. //
  416. // register aliases
  417. //
  418. rpCurTh = loc0
  419. rThStackBase= loc1
  420. rbsp = loc2
  421. rT0 = t0
  422. rT1 = t1
  423. rT2 = t2
  424. rT3 = t3
  425. rT4 = t4
  426. rT5 = t5
  427. rT6 = t6
  428. rT7 = t7
  429. rpT0 = t10
  430. rpT1 = t11
  431. rpT2 = t12
  432. rpT3 = t13
  433. rpT4 = t14
  434. rpT5 = t15
  435. rpT6 = t16
  436. alloc rT1 = ar.pfs, 3, 3, 3, 0
  437. mov rpT3 = sp
  438. mov rT0 = brp
  439. ;;
  440. mov rbsp = ar.bsp
  441. movl rpT0 = KiPcr+PcCurrentThread
  442. ;;
  443. .fframe 16
  444. flushrs
  445. add sp = -16, sp // allocate space for brp, pfs
  446. ;;
  447. .savepsp brp, 0
  448. LDPTR (rpCurTh, rpT0)
  449. st8 [rpT3] = rT0, 8 // save brp, pfs in old scratch area
  450. ;;
  451. .savepsp ar.pfs, -8
  452. st8 [rpT3] = rT1
  453. add rpT1 = ThStackBase, rpCurTh
  454. add rpT2 = ThTrapFrame, rpCurTh
  455. ;;
  456. PROLOGUE_END
  457. LDPTR (rThStackBase, rpT1)
  458. LDPTR (rT2, rpT2) // get trap frame address
  459. mov out1 = sp
  460. ;;
  461. //
  462. // relocate trap frame.
  463. // copy memory stack and backing store.
  464. //
  465. sub rT1 = rThStackBase, rT2
  466. ;;
  467. sub out2 = rThStackBase, sp // compute the copy size
  468. sub rT2 = a0, rT1
  469. ;;
  470. STPTR (rpT2, rT2) // save new trap frame address
  471. sub out0 = a0, out2
  472. (p0) br.call.sptk.many brp = RtlMoveMemory
  473. ;;
  474. sub out2 = rbsp, rThStackBase
  475. mov out0 = a0
  476. mov out1 = rThStackBase
  477. ;;
  478. mov ar.rsc = r0 // put RSE in lazy mode
  479. mov rbsp = out2
  480. (p0) br.call.sptk.many brp = RtlMoveMemory
  481. ;;
  482. rsm 1 << PSR_I // disable interrupts
  483. mov rpT0 = rpCurTh
  484. sub rT1 = rThStackBase, sp
  485. add rpT1 = ThInitialStack, rpCurTh
  486. add rpT2 = ThStackLimit, rpCurTh
  487. ;;
  488. //
  489. // interrupt disabled, then update kernel stack/bstore base,
  490. // then switch kernel stack and backing store
  491. //
  492. //
  493. // set new initial stack and stack base addresses in the kernel thread object.
  494. // set the return value to the old stack base address.
  495. //
  496. STPTRINC (rpT1, a0, ThInitialBStore - ThInitialStack)
  497. STPTRINC (rpT2, a1, ThBStoreLimit - ThStackLimit)
  498. add rpT5 = 16, sp
  499. ;;
  500. STPTR (rpT1, a0)
  501. STPTR (rpT2, a2)
  502. add rpT6 = 24, sp
  503. ;;
  504. add rpT1 = ThStackBase, rpCurTh
  505. add rpT2 = ThLargeStack, rpCurTh
  506. add rT5 = 1, r0
  507. ;;
  508. STPTR (rpT1, a0) // save new stack/bstore base
  509. st1 [rpT2] = rT5 // large stack indicator
  510. nop.i 0
  511. ld8 rT3 = [rpT5] // restore return pointer
  512. movl rpT3 = KiPcr+PcInitialStack
  513. ;;
  514. ld8 rT4 = [rpT6] // restore pfs
  515. add rpT4 = PcStackLimit - PcInitialStack, rpT3
  516. mov v0 = rThStackBase
  517. ;;
  518. //
  519. // set new initial stack/bstore and their limits in the PCR
  520. //
  521. st8 [rpT3] = a0, PcInitialBStore - PcInitialStack
  522. st8 [rpT4] = a1, PcBStoreLimit - PcStackLimit
  523. sub sp = a0, rT1 // switch to new kernel stack
  524. ;;
  525. st8 [rpT3] = a0
  526. st8 [rpT4] = a2
  527. add rT2 = rbsp, a0
  528. ;;
  529. alloc rT5 = ar.pfs, 0, 0, 0, 0
  530. ;;
  531. mov rT6 = ar.rnat
  532. mov brp = rT3
  533. ;;
  534. loadrs
  535. ;;
  536. mov ar.bspstore = rT2 // switch to new backing store
  537. mov ar.pfs = rT4
  538. ;;
  539. mov ar.rnat = rT6
  540. ssm 1 << PSR_I // enable interrupt
  541. .restore
  542. add sp = 16, sp // deallocate stack frame
  543. ;;
  544. invala
  545. mov ar.rsc = RSC_KERNEL
  546. ;;
  547. br.ret.sptk.clr brp
  548. NESTED_EXIT(KeSwitchKernelStack)
  549. //++
  550. //
  551. // NTSTATUS
  552. // NtCallbackReturn (
  553. // IN PVOID OutputBuffer OPTIONAL,
  554. // IN ULONG OutputLength,
  555. // IN NTSTATUS Status
  556. // )
  557. //
  558. // Routine Description:
  559. //
  560. // This function returns from a user mode callout to the kernel
  561. // mode caller of the user mode callback function.
  562. //
  563. // N.B. This function returns to the function that called out to user
  564. // mode and the KiCallUserMode function calls out to user mode.
  565. // Therefore, the stack layout must be consistent between the
  566. // two routines.
  567. //
  568. // t0 - current trap frame address
  569. //
  570. // Arguments:
  571. //
  572. // OutputBuffer - Supplies an optional pointer to an output buffer.
  573. //
  574. // OutputLength - Supplies the length of the output buffer.
  575. //
  576. // Status - Supplies the status value returned to the caller of the
  577. // callback function.
  578. //
  579. // Return Value:
  580. //
  581. // If the callback return cannot be executed, then an error status is
  582. // returned. Otherwise, the specified callback status is returned to
  583. // the caller of the callback function.
  584. //
  585. // N.B. This function returns to the function that called out to user
  586. // mode is a callout is currently active.
  587. //
  588. //--
  589. LEAF_ENTRY(NtCallbackReturn)
  590. .regstk 3, 1, 0, 0
  591. rT0 = t1
  592. rT1 = t2
  593. rT2 = t3
  594. rT3 = t4
  595. rT4 = t5
  596. rT5 = t6
  597. rT6 = t7
  598. rT7 = t8
  599. rT8 = t9
  600. rT9 = t10
  601. rpT0 = t11
  602. rpT1 = t12
  603. rpT2 = t13
  604. rpT3 = t14
  605. rpT4 = t15
  606. rpT5 = t16
  607. rpT6 = t17
  608. rIPSR = t18
  609. rpCurTh = t19
  610. rThCbStack = t20
  611. rThCbBStore = t21
  612. rRnat = loc0
  613. alloc rT6 = ar.pfs, 3, 1, 0, 0
  614. movl rpT0 = KiPcr+PcCurrentThread
  615. ;;
  616. LDPTR (rpCurTh, rpT0)
  617. add rIPSR = TrStIPSR, t0
  618. ;;
  619. ld8 rIPSR = [rIPSR]
  620. movl rT1 = 1 << PSR_DB | 1 << PSR_TB | 1 << PSR_SS | 1 << PSR_LP
  621. add rpT0 = ThCallbackStack, rpCurTh
  622. add rpT3 = ThCallbackBStore, rpCurTh
  623. ;;
  624. LDPTR (rThCbStack, rpT0) // get callback stack address
  625. LDPTR (rThCbBStore, rpT3) // get callback bstore address
  626. and rIPSR = rIPSR, rT1 // capture db, tb, ss, lp bits
  627. ;;
  628. cmp.eq pt1, pt2 = zero, rThCbStack
  629. add rpT1 = CuIntNats+STACK_SCRATCH_AREA, rThCbStack
  630. add rpT2 = CuApLC+STACK_SCRATCH_AREA, rThCbStack
  631. ;;
  632. (pt2) ld8.nt1 rT0 = [rpT1], CuPreds - CuIntNats
  633. (pt1) movl v0 = STATUS_NO_CALLBACK_ACTIVE
  634. (pt2) ld8.nt1 rT1 = [rpT2], CuBrRp - CuApLC
  635. nop.m 0
  636. (pt1) br.ret.sptk.clr brp
  637. ;;
  638. ld8.nt1 rT2 = [rpT1], CuRsPFS - CuPreds
  639. ld8.nt1 rT3 = [rpT2], CuBrS0 - CuBrRp
  640. mov v0 = a2 // set callback service status
  641. ;;
  642. ld8.nt1 rT4 = [rpT1], CuBrS1 - CuRsPFS
  643. ld8.nt1 rT5 = [rpT2], CuBrS2 - CuBrS0
  644. nop.i 0
  645. ;;
  646. mov ar.unat = rT0
  647. mov ar.lc = rT1
  648. nop.i 0
  649. ld8.nt1 rT6 = [rpT1], CuBrS3 - CuBrS1
  650. ld8.nt1 rT7 = [rpT2], CuBrS4 - CuBrS2
  651. mov pr = rT2, -1
  652. ;;
  653. ld8.nt1 rT8 = [rpT1], CuIntS0 - CuBrS3
  654. ld8.nt1 rT9 = [rpT2], CuIntS1 - CuBrS4
  655. mov brp = rT3
  656. ;;
  657. ld8.fill.nt1 s0 = [rpT1], CuIntS2 - CuIntS0
  658. ld8.fill.nt1 s1 = [rpT2], CuIntS3 - CuIntS1
  659. mov ar.pfs = rT4
  660. ;;
  661. ld8.fill.nt1 s2 = [rpT1], CuApUNAT - CuIntS2
  662. ld8.fill.nt1 s3 = [rpT2], CuRsRNAT - CuIntS3
  663. mov bs0 = rT5
  664. ;;
  665. ld8.nt1 rT0 = [rpT1], CuFltS0 - CuApUNAT
  666. ld8.nt1 rRnat = [rpT2], CuFltS1 - CuRsRNAT
  667. mov bs1 = rT6
  668. ;;
  669. ldf.fill.nt1 fs0 = [rpT1], CuFltS2 - CuFltS0
  670. ldf.fill.nt1 fs1 = [rpT2], CuFltS3 - CuFltS1
  671. mov bs2 = rT7
  672. ;;
  673. ldf.fill.nt1 fs2 = [rpT1], CuFltS4 - CuFltS2
  674. ldf.fill.nt1 fs3 = [rpT2], CuFltS5 - CuFltS3
  675. mov bs3 = rT8
  676. ;;
  677. ldf.fill.nt1 fs4 = [rpT1], CuFltS6 - CuFltS4
  678. ldf.fill.nt1 fs5 = [rpT2], CuFltS7 - CuFltS5
  679. nop.i 0
  680. ;;
  681. ldf.fill.nt1 fs6 = [rpT1], CuFltS8 - CuFltS6
  682. ldf.fill.nt1 fs7 = [rpT2], CuFltS9 - CuFltS7
  683. nop.i 0
  684. ;;
  685. ldf.fill.nt1 fs8 = [rpT1], CuFltS10 - CuFltS8
  686. ldf.fill.nt1 fs9 = [rpT2], CuFltS11 - CuFltS9
  687. nop.i 0
  688. ;;
  689. ldf.fill.nt1 fs10 = [rpT1], CuFltS12 - CuFltS10
  690. ldf.fill.nt1 fs11 = [rpT2], CuFltS13 - CuFltS11
  691. nop.i 0
  692. ;;
  693. ldf.fill.nt1 fs12 = [rpT1], CuFltS14 - CuFltS12
  694. ldf.fill.nt1 fs13 = [rpT2], CuFltS15 - CuFltS13
  695. nop.i 0
  696. ;;
  697. ldf.fill.nt1 fs14 = [rpT1], CuFltS16 - CuFltS14
  698. ldf.fill.nt1 fs15 = [rpT2], CuFltS17 - CuFltS15
  699. nop.i 0
  700. ;;
  701. ldf.fill.nt1 fs16 = [rpT1], CuFltS18 - CuFltS16
  702. ldf.fill.nt1 fs17 = [rpT2], CuFltS19 - CuFltS17
  703. nop.i 0
  704. ;;
  705. ldf.fill.nt1 fs18 = [rpT1], CuA0 - CuFltS18
  706. ldf.fill.nt1 fs19 = [rpT2], CuA1 - CuFltS19
  707. nop.i 0
  708. ;;
  709. ld8.nt1 rpT5 = [rpT1], CuCbStk - CuA0 // load value of A0
  710. mov ar.unat = rT0
  711. mov bs4 = rT9
  712. ;;
  713. ld8.nt1 rT0 = [rpT1], CuTrFrame - CuCbStk // load callback stack
  714. ld8.nt1 rpT6 = [rpT2], CuCbBStore - CuA1 // load value of A1
  715. add rpT3 = ThCallbackStack, rpCurTh
  716. ;;
  717. ld8.nt1 rT1 = [rpT1], CuInStack - CuTrFrame // load trap frame addr
  718. ld8.nt1 rT2 = [rpT2], CuTrStIIP-CuCbBStore // load callback bstore
  719. add rpT4 = ThCallbackBStore, rpCurTh
  720. ;;
  721. ld8.nt1 rT5 = [rpT1] // get previous initial stack
  722. ld8.nt1 rT4 = [rpT2], CuInBStore-CuTrStIIP // load trap frame IIP
  723. add rpT0 = ThTrapFrame, rpCurTh
  724. STPTR (rpT5, a0) // store buffer address in A0
  725. st4 [rpT6] = a1 // store buffer length in A1
  726. add rpT6 = TrStIPSR, rT1
  727. STPTR (rpT3, rT0) // restore callback stack addr
  728. STPTR (rpT4, rT2) // restore callback bstore addr
  729. add rpT3 = ThInitialStack, rpCurTh
  730. ;;
  731. ld8.nt1 rT6 = [rpT2] // get previous initial bstore
  732. ld8 rT0 = [rpT6], TrStIIP-TrStIPSR
  733. add rpT5 = ThInitialBStore, rpCurTh
  734. ;;
  735. st8.nta [rpT6] = rT4, TrStIPSR-TrStIIP // restore trap IIP
  736. rsm 1 << PSR_I // disable interrupts
  737. or rIPSR = rIPSR, rT0
  738. ;;
  739. st8 [rpT6] = rIPSR // propagate ss, db, tb, lp bits
  740. movl rpT4 = KiPcr+PcInitialStack
  741. ;;
  742. alloc rT0 = ar.pfs, 0, 0, 0, 0
  743. mov ar.rsc = r0 // put RSE in lazy mode
  744. mov rT7 = rRnat
  745. ;;
  746. loadrs
  747. STPTR (rpT0, rT1) // restore trap frame address
  748. nop.i 0
  749. ;;
  750. mov ar.bspstore = rThCbBStore // rThCbBStore
  751. st8.nta [rpT4] = rT5, PcInitialBStore - PcInitialStack
  752. nop.i 0
  753. ;;
  754. //
  755. // restore initial stack and bstore.
  756. //
  757. mov ar.rnat = rT7
  758. STPTR (rpT3, rT5)
  759. nop.i 0
  760. ;;
  761. mov ar.rsc = RSC_KERNEL // restore RSC
  762. st8.nta [rpT4] = rT6
  763. add sp = CuFrameLength, rThCbStack
  764. STPTR (rpT5, rT6)
  765. ssm 1 << PSR_I // enable interrupts
  766. invala
  767. br.ret.sptk.clr brp
  768. LEAF_EXIT(NtCallbackReturn)