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.

957 lines
28 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(memmove)
  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. // Note that v0 is initialize above so it will be zero even if we do not call
  239. // MmGrowKernelStack. This means the predicated stores below are always done.
  240. //
  241. LDPTR (rT0, loc4)
  242. cmp4.ne pt2, pt1 = zero, v0
  243. ;;
  244. nop.m 0
  245. (pt1) st8 [loc3] = rT0, PcBStoreLimit - PcStackLimit
  246. (pt2) br.spnt Kcum10
  247. ;;
  248. mov out0 = rbspInit
  249. (ps1) br.call.spnt.many brp = MmGrowKernelBackingStore
  250. ;;
  251. //
  252. // Get expanded bstore limit from thread object and set the bstore limit
  253. // in PCR if the growth of kernel backing store is successful.
  254. //
  255. LDPTR (rT0, loc5)
  256. cmp4.ne pt2, pt1 = zero, v0
  257. add loc4 = ThCallbackStack - ThStackLimit, loc4
  258. add loc5 = ThCallbackBStore - ThBStoreLimit, loc5
  259. ;;
  260. rPcInStack = rT0
  261. rPcInBStore = rT1
  262. rThCbStack = rT2
  263. rThCbBStore = rT3
  264. rpLabel = rT4
  265. PLDPTRINC (pt1, rThCbStack,loc4, ThTrapFrame - ThCallbackStack)
  266. (pt1) st8 [loc3] = rT0, PcInitialStack - PcBStoreLimit
  267. (pt2) br.spnt Kcum10
  268. ;;
  269. //
  270. // Get the address of the current thread and save the previous trap
  271. // frame and callback stack addresses in the current frame. Also
  272. // save the new callback stack address in the thread object.
  273. //
  274. // Get initial and callback stack & backing store addresses
  275. //
  276. ld8.nt1 rPcInStack = [loc3], PcInitialBStore - PcInitialStack
  277. LDPTRINC (rpTF, loc4, ThCallbackStack - ThTrapFrame)
  278. add rpT1 = @gprel(KeUserCallbackDispatcher), gp
  279. ;;
  280. ld8.nt1 rPcInBStore = [loc3], PcInitialStack-PcInitialBStore
  281. LDPTR (rThCbBStore, loc5)
  282. add rpT2 = CuInStack+STACK_SCRATCH_AREA, sp
  283. ;;
  284. LDPTR (rpLabel, rpT1)
  285. add rpT5 = CuInBStore+STACK_SCRATCH_AREA, sp
  286. add loc6 = PcInitialBStore - PcInitialStack, loc3
  287. ;;
  288. STPTR (loc4, sp) // set callback stack addr
  289. STPTR (loc5, rbsp) // set callback bstore addr
  290. add loc4 = ThInitialStack - ThCallbackStack, loc4
  291. //
  292. // save initial stack and backing store addresses
  293. //
  294. st8.nta [rpT2] = rPcInStack, CuCbStk - CuInStack
  295. st8.nta [rpT5] = rPcInBStore, CuCbBStore - CuInBStore
  296. add loc5 = ThInitialBStore - ThCallbackBStore, loc5
  297. ;;
  298. //
  299. // save callback stack and backing store addresses
  300. //
  301. st8.nta [rpT2] = rThCbStack, CuTrFrame - CuCbStk
  302. st8.nta [rpT5] = rThCbBStore, CuTrStIIP - CuCbBStore
  303. ;;
  304. //
  305. // register aliases
  306. //
  307. rpEntry=rT0
  308. rIPSR=rT1
  309. rIIP=rT2
  310. rsm 1 << PSR_I // disable interrupts
  311. ;;
  312. ld8.nt1 rpEntry = [rpLabel], 8 // get continuation IP
  313. st8.nta [rpT2] = rpTF // save trap frame address
  314. add rpT3 = TrStIIP, rpTF
  315. ;;
  316. ld8.nt1 loc1 = [rpLabel] // get continuation GP
  317. add rpT2 = ThApcState+AsUserApcPending, rpCurTh
  318. ;;
  319. ld8 rIIP = [rpT3], TrStIPSR-TrStIIP // get trap IIP
  320. ld1 rT3 = [rpT2], ThAlerted - ThApcState - AsUserApcPending
  321. ;;
  322. ld8 rIPSR = [rpT3], TrStIIP-TrStIPSR
  323. add rpT1 = -ThreadStateSaveAreaLength-TrapFrameLength+TrStIPSR, sp
  324. cmp4.eq pt0 = zero, rT3
  325. ;;
  326. st8 [rpT3] = rpEntry // set trap IIP
  327. st8.nta [rpT5] = rIIP // save original IIP
  328. ;;
  329. st8 [rpT1] = rIPSR
  330. tbit.nz pUDbg = rIPSR, PSR_DB // if psr.db set, load user DRs
  331. st1 [rpT2] = zero // Clear thread alearted
  332. (pt0) mov gp = loc1 // Set user GP
  333. (pt0) br.sptk Kcum5 // no user apc pending,
  334. ;; // branch to KiUserServiceExit
  335. FAST_ENABLE_INTERRUPTS
  336. mov out1 = APC_LEVEL
  337. ;;
  338. SET_IRQL (out1)
  339. ;;
  340. mov out1 = rpTF
  341. br.call.sptk brp = KiApcInterrupt
  342. ;;
  343. FAST_DISABLE_INTERRUPTS
  344. SET_IRQL (zero)
  345. mov gp = loc1 // Set user GP
  346. ;;
  347. Kcum5:
  348. st8.nta [loc4] = sp // reset initial stack addr
  349. st8.nta [loc3] = sp // reset initial stack addr
  350. cmp4.eq pUser, pKrnl = 0, r0 // preset predicates for
  351. // KiUserServiceExit
  352. // N.B. ps1 -- pUser
  353. // ps2 -- pKrnl
  354. mov t0 = rpTF // set t0 -> trap frame address
  355. // per system call convention
  356. mov s0 = r0 // Clear the kernel save registers
  357. mov s1 = r0 // before calling the user.
  358. mov s2 = r0
  359. mov s3 = r0
  360. st8.nta [loc5] = rbspInit // reset initial bstore addr
  361. st8.nta [loc6] = rbspInit // reset initial bstore addr
  362. br KiUserServiceExit // per system call convention
  363. //
  364. // An attempt to grow the kernel stack or backing store failed.
  365. //
  366. Kcum10:
  367. nop.m 0
  368. add rpT1 = CuBrRp+STACK_SCRATCH_AREA, sp
  369. add rpT2 = CuRsPFS+STACK_SCRATCH_AREA, sp
  370. ;;
  371. ld8.nt1 rT1 = [rpT1], CuPreds-CuBrRp
  372. ;;
  373. ld8.nt1 rT2 = [rpT2]
  374. mov brp = rT1
  375. ;;
  376. ld8.nt1 rT3 = [rpT1]
  377. mov ar.pfs = rT2
  378. ;;
  379. mov pr = rT3, -1
  380. ;;
  381. .restore
  382. add sp = CuFrameLength, sp
  383. nop.i 0
  384. br.ret.sptk.clr brp
  385. NESTED_EXIT(KiCallUserMode)
  386. //++
  387. //
  388. // PVOID
  389. // KeSwitchKernelStack (
  390. // IN PVOID StackBase,
  391. // IN PVOID StackLimit,
  392. // IN PVOID BStoreLimit
  393. // )
  394. //
  395. // Routine Description:
  396. //
  397. // This function switches to the specified large kernel stack.
  398. //
  399. // N.B. This function can ONLY be called when there are no variables
  400. // in the stack that refer to other variables in the stack, i.e.,
  401. // there are no pointers into the stack.
  402. //
  403. // Arguments:
  404. //
  405. // StackBase (a0) - Supplies a pointer to the base of the new kernel
  406. // stack.
  407. //
  408. // StackLimit (a1) - supplies a pointer to the limit of the new kernel
  409. // stack.
  410. //
  411. // BStoreLimit (a2) - supplies a pointer to the limit of the new kernel
  412. // backing store.
  413. //
  414. // Return Value:
  415. //
  416. // The old kernel stack/backing store base is returned as the function value.
  417. //
  418. //--
  419. NESTED_ENTRY(KeSwitchKernelStack)
  420. .regstk 3, 4, 3, 0
  421. .prologue
  422. //
  423. // register aliases
  424. //
  425. rpCurTh = loc0
  426. rThStackBase= loc1
  427. rbsp = loc2
  428. rT0 = t0
  429. rT1 = t1
  430. rT2 = t2
  431. rT3 = t3
  432. rT4 = t4
  433. rT5 = t5
  434. rT6 = t6
  435. rT7 = t7
  436. rpT0 = t10
  437. rpT1 = t11
  438. rpT2 = t12
  439. rpT3 = t13
  440. rpT4 = t14
  441. rpT5 = t15
  442. rpT6 = t16
  443. alloc rT1 = ar.pfs, 3, 3, 3, 0
  444. mov rpT3 = sp
  445. mov rT0 = brp
  446. ;;
  447. mov rbsp = ar.bsp
  448. movl rpT0 = KiPcr+PcCurrentThread
  449. ;;
  450. .fframe 16
  451. flushrs
  452. add sp = -16, sp // allocate space for brp, pfs
  453. ;;
  454. .savepsp brp, 0
  455. LDPTR (rpCurTh, rpT0)
  456. st8 [rpT3] = rT0, 8 // save brp, pfs in old scratch area
  457. ;;
  458. .savepsp ar.pfs, -8
  459. st8 [rpT3] = rT1
  460. add rpT1 = ThStackBase, rpCurTh
  461. add rpT2 = ThTrapFrame, rpCurTh
  462. ;;
  463. PROLOGUE_END
  464. LDPTR (rThStackBase, rpT1)
  465. LDPTR (rT2, rpT2) // get trap frame address
  466. mov out1 = sp
  467. ;;
  468. //
  469. // relocate trap frame.
  470. // copy memory stack and backing store.
  471. //
  472. sub rT1 = rThStackBase, rT2
  473. ;;
  474. sub out2 = rThStackBase, sp // compute the copy size
  475. sub rT2 = a0, rT1
  476. ;;
  477. STPTR (rpT2, rT2) // save new trap frame address
  478. sub out0 = a0, out2
  479. (p0) br.call.sptk.many brp = memmove
  480. ;;
  481. sub out2 = rbsp, rThStackBase
  482. mov out0 = a0
  483. mov out1 = rThStackBase
  484. ;;
  485. mov ar.rsc = r0 // put RSE in lazy mode
  486. mov rbsp = out2
  487. (p0) br.call.sptk.many brp = memmove
  488. ;;
  489. rsm 1 << PSR_I // disable interrupts
  490. mov rpT0 = rpCurTh
  491. sub rT1 = rThStackBase, sp
  492. add rpT1 = ThInitialStack, rpCurTh
  493. add rpT2 = ThStackLimit, rpCurTh
  494. ;;
  495. //
  496. // interrupt disabled, then update kernel stack/bstore base,
  497. // then switch kernel stack and backing store
  498. //
  499. //
  500. // set new initial stack and stack base addresses in the kernel thread object.
  501. // set the return value to the old stack base address.
  502. //
  503. STPTRINC (rpT1, a0, ThInitialBStore - ThInitialStack)
  504. STPTRINC (rpT2, a1, ThBStoreLimit - ThStackLimit)
  505. add rpT5 = 16, sp
  506. ;;
  507. STPTR (rpT1, a0)
  508. STPTR (rpT2, a2)
  509. add rpT6 = 24, sp
  510. ;;
  511. add rpT1 = ThStackBase, rpCurTh
  512. add rpT2 = ThLargeStack, rpCurTh
  513. add rT5 = 1, r0
  514. ;;
  515. STPTR (rpT1, a0) // save new stack/bstore base
  516. st1 [rpT2] = rT5 // large stack indicator
  517. nop.i 0
  518. ld8 rT3 = [rpT5] // restore return pointer
  519. movl rpT3 = KiPcr+PcInitialStack
  520. ;;
  521. ld8 rT4 = [rpT6] // restore pfs
  522. add rpT4 = PcStackLimit - PcInitialStack, rpT3
  523. mov v0 = rThStackBase
  524. ;;
  525. //
  526. // set new initial stack/bstore and their limits in the PCR
  527. //
  528. st8 [rpT3] = a0, PcInitialBStore - PcInitialStack
  529. st8 [rpT4] = a1, PcBStoreLimit - PcStackLimit
  530. sub sp = a0, rT1 // switch to new kernel stack
  531. ;;
  532. st8 [rpT3] = a0
  533. st8 [rpT4] = a2
  534. add rT2 = rbsp, a0
  535. ;;
  536. alloc rT5 = ar.pfs, 0, 0, 0, 0
  537. ;;
  538. mov rT6 = ar.rnat
  539. mov brp = rT3
  540. ;;
  541. loadrs
  542. ;;
  543. mov ar.bspstore = rT2 // switch to new backing store
  544. mov ar.pfs = rT4
  545. ;;
  546. mov ar.rnat = rT6
  547. ssm 1 << PSR_I // enable interrupt
  548. .restore
  549. add sp = 16, sp // deallocate stack frame
  550. ;;
  551. invala
  552. mov ar.rsc = RSC_KERNEL
  553. ;;
  554. br.ret.sptk.clr brp
  555. NESTED_EXIT(KeSwitchKernelStack)
  556. //++
  557. //
  558. // NTSTATUS
  559. // NtCallbackReturn (
  560. // IN PVOID OutputBuffer OPTIONAL,
  561. // IN ULONG OutputLength,
  562. // IN NTSTATUS Status
  563. // )
  564. //
  565. // Routine Description:
  566. //
  567. // This function returns from a user mode callout to the kernel
  568. // mode caller of the user mode callback function.
  569. //
  570. // N.B. This function returns to the function that called out to user
  571. // mode and the KiCallUserMode function calls out to user mode.
  572. // Therefore, the stack layout must be consistent between the
  573. // two routines.
  574. //
  575. // t0 - current trap frame address
  576. //
  577. // Arguments:
  578. //
  579. // OutputBuffer - Supplies an optional pointer to an output buffer.
  580. //
  581. // OutputLength - Supplies the length of the output buffer.
  582. //
  583. // Status - Supplies the status value returned to the caller of the
  584. // callback function.
  585. //
  586. // Return Value:
  587. //
  588. // If the callback return cannot be executed, then an error status is
  589. // returned. Otherwise, the specified callback status is returned to
  590. // the caller of the callback function.
  591. //
  592. // N.B. This function returns to the function that called out to user
  593. // mode is a callout is currently active.
  594. //
  595. //--
  596. LEAF_ENTRY(NtCallbackReturn)
  597. .regstk 3, 1, 0, 0
  598. rT0 = t1
  599. rT1 = t2
  600. rT2 = t3
  601. rT3 = t4
  602. rT4 = t5
  603. rT5 = t6
  604. rT6 = t7
  605. rT7 = t8
  606. rT8 = t9
  607. rT9 = t10
  608. rpT0 = t11
  609. rpT1 = t12
  610. rpT2 = t13
  611. rpT3 = t14
  612. rpT4 = t15
  613. rpT5 = t16
  614. rpT6 = t17
  615. rIPSR = t18
  616. rpCurTh = t19
  617. rThCbStack = t20
  618. rThCbBStore = t21
  619. rRnat = loc0
  620. alloc rT6 = ar.pfs, 3, 1, 0, 0
  621. movl rpT0 = KiPcr+PcCurrentThread
  622. ;;
  623. LDPTR (rpCurTh, rpT0)
  624. add rIPSR = TrStIPSR, t0
  625. ;;
  626. ld8 rIPSR = [rIPSR]
  627. movl rT1 = 1 << PSR_DB | 1 << PSR_TB | 1 << PSR_SS | 1 << PSR_LP
  628. add rpT0 = ThCallbackStack, rpCurTh
  629. add rpT3 = ThCallbackBStore, rpCurTh
  630. ;;
  631. LDPTR (rThCbStack, rpT0) // get callback stack address
  632. LDPTR (rThCbBStore, rpT3) // get callback bstore address
  633. and rIPSR = rIPSR, rT1 // capture db, tb, ss, lp bits
  634. ;;
  635. cmp.eq pt1, pt2 = zero, rThCbStack
  636. add rpT1 = CuIntNats+STACK_SCRATCH_AREA, rThCbStack
  637. add rpT2 = CuApLC+STACK_SCRATCH_AREA, rThCbStack
  638. ;;
  639. (pt2) ld8.nt1 rT0 = [rpT1], CuPreds - CuIntNats
  640. (pt1) movl v0 = STATUS_NO_CALLBACK_ACTIVE
  641. (pt2) ld8.nt1 rT1 = [rpT2], CuBrRp - CuApLC
  642. nop.m 0
  643. (pt1) br.ret.sptk.clr brp
  644. ;;
  645. ld8.nt1 rT2 = [rpT1], CuRsPFS - CuPreds
  646. ld8.nt1 rT3 = [rpT2], CuBrS0 - CuBrRp
  647. mov v0 = a2 // set callback service status
  648. ;;
  649. ld8.nt1 rT4 = [rpT1], CuBrS1 - CuRsPFS
  650. ld8.nt1 rT5 = [rpT2], CuBrS2 - CuBrS0
  651. nop.i 0
  652. ;;
  653. mov ar.unat = rT0
  654. mov ar.lc = rT1
  655. nop.i 0
  656. ld8.nt1 rT6 = [rpT1], CuBrS3 - CuBrS1
  657. ld8.nt1 rT7 = [rpT2], CuBrS4 - CuBrS2
  658. mov pr = rT2, -1
  659. ;;
  660. ld8.nt1 rT8 = [rpT1], CuIntS0 - CuBrS3
  661. ld8.nt1 rT9 = [rpT2], CuIntS1 - CuBrS4
  662. mov brp = rT3
  663. ;;
  664. ld8.fill.nt1 s0 = [rpT1], CuIntS2 - CuIntS0
  665. ld8.fill.nt1 s1 = [rpT2], CuIntS3 - CuIntS1
  666. mov ar.pfs = rT4
  667. ;;
  668. ld8.fill.nt1 s2 = [rpT1], CuApUNAT - CuIntS2
  669. ld8.fill.nt1 s3 = [rpT2], CuRsRNAT - CuIntS3
  670. mov bs0 = rT5
  671. ;;
  672. ld8.nt1 rT0 = [rpT1], CuFltS0 - CuApUNAT
  673. ld8.nt1 rRnat = [rpT2], CuFltS1 - CuRsRNAT
  674. mov bs1 = rT6
  675. ;;
  676. ldf.fill.nt1 fs0 = [rpT1], CuFltS2 - CuFltS0
  677. ldf.fill.nt1 fs1 = [rpT2], CuFltS3 - CuFltS1
  678. mov bs2 = rT7
  679. ;;
  680. ldf.fill.nt1 fs2 = [rpT1], CuFltS4 - CuFltS2
  681. ldf.fill.nt1 fs3 = [rpT2], CuFltS5 - CuFltS3
  682. mov bs3 = rT8
  683. ;;
  684. ldf.fill.nt1 fs4 = [rpT1], CuFltS6 - CuFltS4
  685. ldf.fill.nt1 fs5 = [rpT2], CuFltS7 - CuFltS5
  686. nop.i 0
  687. ;;
  688. ldf.fill.nt1 fs6 = [rpT1], CuFltS8 - CuFltS6
  689. ldf.fill.nt1 fs7 = [rpT2], CuFltS9 - CuFltS7
  690. nop.i 0
  691. ;;
  692. ldf.fill.nt1 fs8 = [rpT1], CuFltS10 - CuFltS8
  693. ldf.fill.nt1 fs9 = [rpT2], CuFltS11 - CuFltS9
  694. nop.i 0
  695. ;;
  696. ldf.fill.nt1 fs10 = [rpT1], CuFltS12 - CuFltS10
  697. ldf.fill.nt1 fs11 = [rpT2], CuFltS13 - CuFltS11
  698. nop.i 0
  699. ;;
  700. ldf.fill.nt1 fs12 = [rpT1], CuFltS14 - CuFltS12
  701. ldf.fill.nt1 fs13 = [rpT2], CuFltS15 - CuFltS13
  702. nop.i 0
  703. ;;
  704. ldf.fill.nt1 fs14 = [rpT1], CuFltS16 - CuFltS14
  705. ldf.fill.nt1 fs15 = [rpT2], CuFltS17 - CuFltS15
  706. nop.i 0
  707. ;;
  708. ldf.fill.nt1 fs16 = [rpT1], CuFltS18 - CuFltS16
  709. ldf.fill.nt1 fs17 = [rpT2], CuFltS19 - CuFltS17
  710. nop.i 0
  711. ;;
  712. ldf.fill.nt1 fs18 = [rpT1], CuA0 - CuFltS18
  713. ldf.fill.nt1 fs19 = [rpT2], CuA1 - CuFltS19
  714. nop.i 0
  715. ;;
  716. ld8.nt1 rpT5 = [rpT1], CuCbStk - CuA0 // load value of A0
  717. mov ar.unat = rT0
  718. mov bs4 = rT9
  719. ;;
  720. ld8.nt1 rT0 = [rpT1], CuTrFrame - CuCbStk // load callback stack
  721. ld8.nt1 rpT6 = [rpT2], CuCbBStore - CuA1 // load value of A1
  722. add rpT3 = ThCallbackStack, rpCurTh
  723. ;;
  724. ld8.nt1 rT1 = [rpT1], CuInStack - CuTrFrame // load trap frame addr
  725. ld8.nt1 rT2 = [rpT2], CuTrStIIP-CuCbBStore // load callback bstore
  726. add rpT4 = ThCallbackBStore, rpCurTh
  727. ;;
  728. ld8.nt1 rT5 = [rpT1] // get previous initial stack
  729. ld8.nt1 rT4 = [rpT2], CuInBStore-CuTrStIIP // load trap frame IIP
  730. add rpT0 = ThTrapFrame, rpCurTh
  731. STPTR (rpT5, a0) // store buffer address in A0
  732. st4 [rpT6] = a1 // store buffer length in A1
  733. add rpT6 = TrStIPSR, rT1
  734. STPTR (rpT3, rT0) // restore callback stack addr
  735. STPTR (rpT4, rT2) // restore callback bstore addr
  736. add rpT3 = ThInitialStack, rpCurTh
  737. ;;
  738. ld8.nt1 rT6 = [rpT2] // get previous initial bstore
  739. ld8 rT0 = [rpT6], TrStIIP-TrStIPSR
  740. add rpT5 = ThInitialBStore, rpCurTh
  741. ;;
  742. st8.nta [rpT6] = rT4, TrStIPSR-TrStIIP // restore trap IIP
  743. rsm 1 << PSR_I // disable interrupts
  744. or rIPSR = rIPSR, rT0
  745. ;;
  746. st8 [rpT6] = rIPSR // propagate ss, db, tb, lp bits
  747. movl rpT4 = KiPcr+PcInitialStack
  748. ;;
  749. alloc rT0 = ar.pfs, 0, 0, 0, 0
  750. mov ar.rsc = r0 // put RSE in lazy mode
  751. mov rT7 = rRnat
  752. ;;
  753. loadrs
  754. STPTR (rpT0, rT1) // restore trap frame address
  755. nop.i 0
  756. ;;
  757. mov ar.bspstore = rThCbBStore // rThCbBStore
  758. st8.nta [rpT4] = rT5, PcInitialBStore - PcInitialStack
  759. nop.i 0
  760. ;;
  761. //
  762. // restore initial stack and bstore.
  763. //
  764. mov ar.rnat = rT7
  765. STPTR (rpT3, rT5)
  766. nop.i 0
  767. ;;
  768. mov ar.rsc = RSC_KERNEL // restore RSC
  769. st8.nta [rpT4] = rT6
  770. add sp = CuFrameLength, rThCbStack
  771. STPTR (rpT5, rT6)
  772. ssm 1 << PSR_I // enable interrupts
  773. invala
  774. br.ret.sptk.clr brp
  775. LEAF_EXIT(NtCallbackReturn)